From 6a4648c7294ac88b148c50cdb846345361323af4 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Fri, 15 Jan 2016 10:28:23 +1300 Subject: [PATCH] new orphan branch for rdf4j contribution to eclipse - scrubbed history tree --- .gitattributes | 27 + .gitignore | 29 + about.html | 105 + bom/pom.xml | 390 + compliance/geosparql/pom.xml | 76 + .../geosparql/MemoryGeoSPARQLQueryTest.java | 57 + compliance/http/pom.xml | 188 + .../rdf4j/http/server/ProtocolTest.java | 664 + .../eclipse/rdf4j/http/server/TestServer.java | 119 + .../http/src/test/resources/log4j.properties | 18 + .../http/src/test/resources/logback-test.xml | 15 + .../resources/testcases/default-graph-1.ttl | 9 + .../resources/testcases/named-graph-1.ttl | 8 + compliance/model/pom.xml | 80 + .../model/LinkedHashModelEqualityTest.java | 22 + .../model/LinkedHashModelNamespacesTest.java | 28 + .../rdf4j/model/LinkedHashModelTest.java | 30 + .../LinkedHashModelWithValueFactoryTest.java | 38 + .../rdf4j/model/SailModelNamespacesTest.java | 54 + .../eclipse/rdf4j/model/SailModelTest.java | 63 + .../rdf4j/model/TreeModelEqualityTest.java | 23 + .../rdf4j/model/TreeModelNamespacesTest.java | 28 + .../eclipse/rdf4j/model/TreeModelTest.java | 30 + .../model/src/test/resources/logback-test.xml | 15 + compliance/pom.xml | 68 + compliance/queryresultio/pom.xml | 102 + .../binary/SPARQLBinaryTupleTest.java | 33 + .../sparqljson/SPARQLJSONBooleanTest.java | 93 + .../sparqljson/SPARQLJSONTupleTest.java | 271 + .../sparqlxml/SPARQLXMLBooleanTest.java | 33 + .../sparqlxml/SPARQLXMLTupleTest.java | 33 + .../resultio/text/SPARQLTextBooleanTest.java | 34 + .../resultio/text/csv/SPARQLCSVTupleTest.java | 243 + .../text/tsv/SPARQLTSVCustomTest.java | 83 + .../resultio/text/tsv/SPARQLTSVTupleTest.java | 130 + .../src/test/resources/logback-test.xml | 15 + .../test/resources/sparqljson/bindings1.srj | 36 + .../test/resources/sparqljson/bindings2.srj | 39 + .../test/resources/sparqljson/boolean1.srj | 3 + .../test/resources/sparqljson/boolean2.srj | 3 + .../test/resources/sparqljson/boolean3.srj | 3 + .../test/resources/sparqljson/boolean4.srj | 3 + .../non-standard-distinct-ordered.srj | 102 + .../sparqljson/non-standard-distinct.srj | 102 + .../sparqljson/non-standard-ordered.srj | 102 + compliance/rio/pom.xml | 170 + .../rdf4j/rio/binary/BinaryHandlingTest.java | 88 + .../rdf4j/rio/binary/BinaryRDFWriterTest.java | 22 + .../DBPediaCelsiusDatatypeHandlerTest.java | 94 + .../RDFLangStringDatatypeHandlerTest.java | 101 + ...tuosoGeometryPointDatatypeHandlerTest.java | 78 + .../XMLSchemaDoubleDatatypeHandlerTest.java | 75 + .../rio/helpers/RDFParserHelperTest.java | 371 + .../rio/jsonld/JSONLDParserHandlerTest.java | 94 + .../rdf4j/rio/jsonld/JSONLDWriterTest.java | 110 + .../eclipse/rdf4j/rio/n3/N3ParserTest.java | 34 + .../rdf4j/rio/nquads/NQuadsEarlReport.java | 27 + .../rdf4j/rio/nquads/NQuadsHandlingTest.java | 87 + .../rdf4j/rio/nquads/NQuadsParserTest.java | 33 + .../rio/nquads/NQuadsParserUnitTest.java | 25 + .../rdf4j/rio/nquads/NQuadsWriterTest.java | 21 + .../rio/ntriples/NTriplesEarlReport.java | 27 + .../rio/ntriples/NTriplesHandlingTest.java | 87 + .../rio/ntriples/NTriplesParserTest.java | 33 + .../rio/ntriples/NTriplesParserUnitTest.java | 25 + .../rio/ntriples/NTriplesWriterTest.java | 23 + .../rio/rdfjson/RDFJSONHandlingTest.java | 88 + .../rio/rdfjson/RDFJSONMimeTypeTest.java | 37 + .../rio/rdfjson/RDFJSONParserCustomTest.java | 30 + .../rdf4j/rio/rdfjson/RDFJSONParserTest.java | 31 + .../rdf4j/rio/rdfjson/RDFJSONWriterTest.java | 23 + .../rdf4j/rio/rdfxml/RDFXMLHandlingTest.java | 87 + .../rio/rdfxml/RDFXMLParserCustomTest.java | 217 + .../rdf4j/rio/rdfxml/RDFXMLParserTest.java | 35 + .../rio/rdfxml/RDFXMLPrettyWriterTest.java | 135 + .../rdf4j/rio/rdfxml/RDFXMLWriterTest.java | 19 + .../rdf4j/rio/trig/TriGEarlReport.java | 27 + .../rdf4j/rio/trig/TriGHandlingTest.java | 87 + .../rdf4j/rio/trig/TriGParserCustomTest.java | 140 + .../rdf4j/rio/trig/TriGParserTest.java | 35 + .../rdf4j/rio/trig/TriGWriterTest.java | 22 + .../rio/turtle/CustomTurtleParserTest.java | 494 + .../rdf4j/rio/turtle/TurtleEarlReport.java | 27 + .../rdf4j/rio/turtle/TurtleHandlingTest.java | 87 + .../rdf4j/rio/turtle/TurtleMimeTypeTest.java | 40 + .../rdf4j/rio/turtle/TurtleParserTest.java | 40 + .../rdf4j/rio/turtle/TurtleWriterTest.java | 22 + .../rio/src/test/resources/logback-test.xml | 15 + compliance/serql/pom.xml | 103 + .../query/parser/serql/SeRQLParserTest.java | 34 + .../query/parser/serql/SeRQLQueryTest.java | 47 + .../serql/src/test/resources/logback-test.xml | 15 + compliance/sparql/pom.xml | 245 + .../sparql/ArbitraryLengthPathTest.java | 106 + .../sparql/MemoryComplexSPARQLQueryTest.java | 27 + .../parser/sparql/MemorySPARQLUpdateTest.java | 30 + .../parser/sparql/SPARQLEmbeddedServer.java | 129 + .../sparql/SPARQLServiceEvaluationTest.java | 792 + .../sparql/manifest/CoreSPARQLSyntaxTest.java | 41 + .../parser/sparql/manifest/EarlReport.java | 186 + .../manifest/MemorySPARQLQueryTest.java | 58 + .../W3CApprovedSPARQL11QueryTest.java | 70 + .../W3CApprovedSPARQL11SyntaxTest.java | 57 + .../W3CApprovedSPARQL11UpdateTest.java | 62 + .../sail/federation/FederationSparqlTest.java | 64 + .../src/test/resources/logback-test.xml | 15 + compliance/store/pom.xml | 200 + .../rdf4j/repository/http/HTTPMemServer.java | 123 + .../repository/http/HTTPRepositoryTest.java | 46 + .../http/HTTPSparqlDatasetTest.java | 44 + .../http/HTTPSparqlSetBindingTest.java | 44 + .../repository/http/HTTPSparqlUpdateTest.java | 112 + .../http/HTTPStoreConnectionTest.java | 120 + ...RDFSchemaHTTPRepositoryConnectionTest.java | 197 + ...erencerMemoryRepositoryConnectionTest.java | 39 + .../MemoryCascadeValueExceptionTest.java | 21 + .../memory/MemoryGraphQueryResultTest.java | 20 + .../memory/MemoryOptimisticIsolationTest.java | 30 + .../sail/memory/MemorySPARQLQueryTest.java | 51 + .../sail/memory/MemorySeRQLQueryTest.java | 47 + .../memory/MemorySparqlAggregatesTest.java | 20 + .../sail/memory/MemorySparqlDatasetTest.java | 20 + .../sail/memory/MemorySparqlOrderByTest.java | 20 + .../sail/memory/MemorySparqlRegexTest.java | 20 + .../memory/MemorySparqlSetBindingTest.java | 21 + .../memory/MemoryStoreConnectionTest.java | 26 + .../memory/MemoryStoreRepositoryTest.java | 21 + .../memory/MemoryTupleQueryResultTest.java | 20 + ...FSchemaMemoryRepositoryConnectionTest.java | 27 + ...erencerNativeRepositoryConnectionTest.java | 56 + .../LimitedSizeNativeStoreConnectionTest.java | 159 + .../NativeCascadeValueExceptionTest.java | 42 + .../NativeComplexSPARQLQueryTest.java | 46 + .../nativerdf/NativeGraphQueryResultTest.java | 42 + .../NativeOptimisticIsolationTest.java | 30 + .../sail/nativerdf/NativeSPARQLQueryTest.java | 74 + .../sail/nativerdf/NativeSeRQLQueryTest.java | 57 + .../nativerdf/NativeSparqlOrderByTest.java | 43 + .../sail/nativerdf/NativeSparqlRegexTest.java | 42 + .../nativerdf/NativeStoreConnectionTest.java | 85 + .../nativerdf/NativeStoreRepositoryTest.java | 43 + .../nativerdf/NativeTupleQueryResultTest.java | 42 + ...FSchemaNativeRepositoryConnectionTest.java | 48 + .../TestNativeStoreMemoryOverflow.java | 163 + .../sail/rdbms/MySqlSPARQL11QueryTest.java | 62 + .../sail/rdbms/MySqlStoreConnectionTest.java | 39 + .../sail/rdbms/PgSqlSPARQL11QueryTest.java | 63 + .../sail/rdbms/PgSqlStoreConnectionTest.java | 39 + .../sparql/SPARQLGraphQueryResultTest.java | 59 + .../SPARQLRepositorySparqlUpdateTest.java | 62 + .../sparql/SPARQLRepositoryTest.java | 72 + .../sparql/SPARQLServiceEvaluationTest.java | 203 + .../sparql/SPARQLStoreConnectionTest.java | 644 + .../federation/FederationConnectionTest.java | 46 + .../rdf4j/sail/federation/FederationTest.java | 44 + .../NotifyingSailConnectionWrapperTest.java | 114 + .../sail/memory/MemCustomInferencingTest.java | 26 + .../rdf4j/sail/memory/MemInferencingTest.java | 22 + .../memory/MemoryStoreConcurrencyTest.java | 31 + .../memory/MemoryStoreIsolationLevelTest.java | 31 + .../rdf4j/sail/memory/MemoryStoreTest.java | 34 + .../memory/PersistentMemoryStoreTest.java | 54 + .../sail/memory/StoreSerializationTest.java | 195 + .../nativerdf/NativeStoreConcurrencyTest.java | 47 + .../nativerdf/NativeStoreConsistencyTest.java | 138 + .../nativerdf/NativeStoreContextTest.java | 48 + .../NativeStoreCustomInferencingTest.java | 41 + .../nativerdf/NativeStoreDirLockTest.java | 53 + .../nativerdf/NativeStoreInferencingTest.java | 36 + .../nativerdf/NativeStoreInterruptTest.java | 49 + .../NativeStoreIsolationLevelTest.java | 47 + .../rdf4j/sail/nativerdf/NativeStoreTest.java | 71 + .../datastore/DataStorePerfTest.java | 118 + .../sail/nativerdf/datastore/measurements.txt | 26 + .../store/src/test/resources/log4j.properties | 18 + .../store/src/test/resources/logback-test.xml | 15 + .../SES-1867/initialState.nq | 59991 ++++++++++++++++ .../SES-1867/newTriples.nt | 20484 ++++++ .../store/src/test/resources/test/ask.rq | 78 + .../src/test/resources/test/delete-insert.ru | 53 + .../src/test/resources/test/insert-data.ru | 78 + core/assembly/pom.xml | 314 + core/assembly/src/main/assembly/sdk.xml | 59 + core/assembly/src/main/dist/bin/console.bat | 60 + core/assembly/src/main/dist/bin/console.sh | 13 + core/config/pom.xml | 36 + .../main/java/org/eclipse/rdf4j/Sesame.java | 22 + .../rdf4j/common/app/AppConfiguration.java | 353 + .../eclipse/rdf4j/common/app/AppVersion.java | 293 + .../common/app/config/Configuration.java | 67 + .../common/app/logging/LogConfiguration.java | 104 + .../base/AbstractLogConfiguration.java | 127 + .../logging/base/LogConfigurationBase.java | 25 + .../app/logging/base/LogConverterHandler.java | 61 + .../app/logging/logback/LogConfigurator.java | 108 + .../logging/logback/LogbackConfiguration.java | 129 + .../rdf4j/common/app/net/ProxySettings.java | 251 + .../common/app/util/ConfigurationUtil.java | 180 + .../rdf4j/common/logging/LogLevel.java | 16 + .../rdf4j/common/logging/LogReader.java | 180 + .../rdf4j/common/logging/LogRecord.java | 23 + .../logging/base/AbstractLogReader.java | 126 + .../common/logging/base/LogReaderBase.java | 17 + .../common/logging/base/LogRecordBase.java | 17 + .../common/logging/base/SimpleLogRecord.java | 90 + .../logging/file/logback/FileLogReader.java | 210 + .../file/logback/MultipleFileLogReader.java | 278 + .../file/logback/StackTracePatternLayout.java | 46 + .../common/platform/AbstractPlatform.java | 90 + .../common/platform/DefaultPlatform.java | 34 + .../rdf4j/common/platform/Platform.java | 84 + .../rdf4j/common/platform/PlatformBase.java | 17 + .../common/platform/PlatformFactory.java | 183 + .../common/platform/ProcessLauncher.java | 317 + .../platform/support/MacOSXPlatform.java | 36 + .../platform/support/PosixGnomePlatform.java | 20 + .../platform/support/PosixKDEPlatform.java | 19 + .../platform/support/PosixPlatform.java | 39 + .../platform/support/WindowsPlatform.java | 189 + .../config/defaults/application.properties | 5 + .../aduna/app/config/defaults/logback.xml | 19 + .../app/config/defaults/logging.properties | 3 + .../app/config/defaults/proxy.properties | 1 + .../rdf4j/common/app/AppVersionTest.java | 38 + core/console/pom.xml | 105 + .../java/org/eclipse/rdf4j/console/Clear.java | 114 + .../java/org/eclipse/rdf4j/console/Close.java | 49 + .../org/eclipse/rdf4j/console/Command.java | 28 + .../org/eclipse/rdf4j/console/Connect.java | 168 + .../org/eclipse/rdf4j/console/Console.java | 386 + .../org/eclipse/rdf4j/console/ConsoleIO.java | 205 + .../rdf4j/console/ConsoleParameters.java | 26 + .../eclipse/rdf4j/console/ConsoleState.java | 39 + .../org/eclipse/rdf4j/console/Create.java | 202 + .../org/eclipse/rdf4j/console/Disconnect.java | 44 + .../java/org/eclipse/rdf4j/console/Drop.java | 102 + .../org/eclipse/rdf4j/console/Federate.java | 169 + .../java/org/eclipse/rdf4j/console/Load.java | 174 + .../eclipse/rdf4j/console/LockRemover.java | 64 + .../java/org/eclipse/rdf4j/console/Open.java | 91 + .../org/eclipse/rdf4j/console/PrintHelp.java | 152 + .../org/eclipse/rdf4j/console/PrintInfo.java | 31 + .../eclipse/rdf4j/console/QueryEvaluator.java | 245 + .../eclipse/rdf4j/console/SetParameters.java | 105 + .../java/org/eclipse/rdf4j/console/Show.java | 172 + .../console/TupleAndGraphQueryEvaluator.java | 209 + .../rdf4j/console/VerificationLIstener.java | 65 + .../org/eclipse/rdf4j/console/Verify.java | 105 + .../org/eclipse/rdf4j/console/package.html | 8 + .../rdf4j/console/AbstractCommandTest.java | 90 + .../eclipse/rdf4j/console/ConsoleIOTest.java | 52 + .../org/eclipse/rdf4j/console/DropTest.java | 112 + .../eclipse/rdf4j/console/FederateTest.java | 298 + .../eclipse/rdf4j/console/package-info.java | 13 + .../test/resources/federate/alien-config.ttl | 17 + .../src/test/resources/federate/alien.ttl | 14 + .../test/resources/federate/http-config.ttl | 11 + .../test/resources/federate/http2-config.ttl | 11 + .../test/resources/federate/scary-config.ttl | 17 + .../src/test/resources/federate/scary.ttl | 21 + .../test/resources/federate/sparql-config.ttl | 11 + .../resources/federate/sparql2-config.ttl | 11 + .../src/test/resources/logback-test.xml | 15 + core/http/client/pom.xml | 83 + .../http/client/BackgroundGraphResult.java | 180 + .../http/client/BackgroundTupleResult.java | 152 + .../http/client/HttpClientDependent.java | 39 + .../rdf4j/http/client/QueueCursor.java | 192 + .../rdf4j/http/client/SesameClient.java | 42 + .../http/client/SesameClientDependent.java | 37 + .../rdf4j/http/client/SesameClientImpl.java | 132 + .../rdf4j/http/client/SesameSession.java | 870 + .../rdf4j/http/client/SparqlSession.java | 1162 + .../http/client/query/AbstractHTTPQuery.java | 79 + .../http/client/query/AbstractHTTPUpdate.java | 89 + .../http/client/util/HttpClientBuilders.java | 68 + .../client/BackgroundGraphResultHangTest.java | 73 + .../http/client/SesameHTTPClientTest.java | 52 + core/http/pom.xml | 25 + core/http/protocol/pom.xml | 44 + .../eclipse/rdf4j/http/protocol/Protocol.java | 544 + .../http/protocol/UnauthorizedException.java | 31 + .../rdf4j/http/protocol/error/ErrorInfo.java | 71 + .../rdf4j/http/protocol/error/ErrorType.java | 78 + .../transaction/TransactionReader.java | 61 + .../transaction/TransactionSAXParser.java | 336 + .../transaction/TransactionWriter.java | 361 + .../transaction/TransactionXMLConstants.java | 116 + .../operations/AddStatementOperation.java | 61 + .../operations/ClearNamespacesOperation.java | 48 + .../operations/ClearOperation.java | 48 + .../operations/ContextOperation.java | 55 + .../operations/RemoveNamespaceOperation.java | 68 + .../operations/RemoveStatementsOperation.java | 58 + .../operations/SPARQLUpdateOperation.java | 158 + .../operations/SetNamespaceOperation.java | 82 + .../operations/StatementOperation.java | 81 + .../operations/TransactionOperation.java | 32 + .../rdf4j/http/protocol/ProtocolTest.java | 111 + .../transaction/TransactionReaderTest.java | 112 + core/http/server-spring/pom.xml | 80 + .../CommonValuesHandlerInterceptor.java | 46 + .../eclipse/rdf4j/common/webapp/Message.java | 47 + .../webapp/MessageHandlerInterceptor.java | 67 + .../common/webapp/filters/PathFilter.java | 78 + .../navigation/AbstractNavigationNode.java | 268 + .../rdf4j/common/webapp/navigation/Group.java | 144 + .../NavigationHandlerInterceptor.java | 66 + .../webapp/navigation/NavigationModel.java | 252 + .../webapp/navigation/NavigationNode.java | 120 + .../webapp/navigation/NavigationNodeBase.java | 21 + .../navigation/NavigationXmlParser.java | 162 + .../rdf4j/common/webapp/navigation/View.java | 43 + .../functions/NavigationFunctions.java | 32 + .../webapp/system/SystemInfoController.java | 159 + .../system/SystemOverviewController.java | 123 + .../logging/LoggingOverviewController.java | 226 + .../system/proxy/ProxySettingsController.java | 104 + .../common/webapp/util/HeaderElement.java | 184 + .../common/webapp/util/HttpServerUtil.java | 416 + .../rdf4j/common/webapp/util/Parameter.java | 55 + .../common/webapp/views/EmptySuccessView.java | 46 + .../views/SimpleCustomResponseView.java | 82 + .../webapp/views/SimpleResponseView.java | 81 + .../http/server/ClientHTTPException.java | 95 + .../rdf4j/http/server/HTTPException.java | 48 + .../server/ProtocolExceptionResolver.java | 61 + .../rdf4j/http/server/ProtocolUtil.java | 203 + .../http/server/ServerHTTPException.java | 102 + .../rdf4j/http/server/ServerInterceptor.java | 92 + .../server/protocol/ProtocolController.java | 45 + .../server/protocol/ProtocolInterceptor.java | 26 + .../repository/BooleanQueryResultView.java | 79 + .../repository/GraphQueryResultView.java | 94 + .../server/repository/QueryResultView.java | 123 + .../repository/RepositoryController.java | 369 + .../repository/RepositoryInterceptor.java | 166 + .../repository/RepositoryListController.java | 135 + .../repository/TupleQueryResultView.java | 120 + .../contexts/ContextsController.java | 89 + .../repository/graph/GraphController.java | 237 + .../namespaces/NamespaceController.java | 150 + .../namespaces/NamespacesController.java | 143 + .../repository/size/SizeController.java | 74 + .../statements/ExportStatementsView.java | 136 + .../statements/StatementsController.java | 497 + .../ActiveTransactionRegistry.java | 233 + .../transaction/TransactionController.java | 766 + .../TransactionStartController.java | 127 + .../webapp/navigation/NavigationTest.java | 63 + .../webapp/util/HttpServerUtilTest.java | 423 + .../src/test/resources/navigation.xml | 29 + core/http/server/.springBeans | 14 + core/http/server/pom.xml | 130 + .../rdf4j/common/webapp/messages.properties | 1 + .../rdf4j/common/webapp/navigation.xml | 20 + .../common/webapp/system/messages.properties | 46 + .../rdf4j/common/webapp/system/navigation.xml | 14 + .../rdf4j/http/server/messages.properties | 5 + .../eclipse/rdf4j/http/server/navigation.xml | 8 + .../main/webapp/WEB-INF/classes/logback.xml | 13 + .../webapp/WEB-INF/common-webapp-servlet.xml | 60 + .../WEB-INF/common-webapp-system-servlet.xml | 66 + .../src/main/webapp/WEB-INF/glassfish-web.xml | 4 + .../components/ContentHeader.html.jspf | 4 + .../includes/components/Footer.html.jspf | 2 + .../includes/components/Header.html.jspf | 5 + .../includes/components/Message.html.jspf | 5 + .../includes/components/Navigation.html.jspf | 84 + .../includes/components/bodyStart.html.jspf | 1 + .../includes/components/bodyStop.html.jspf | 1 + .../includes/components/head.html.jspf | 12 + .../includes/components/htmlStart.html.jspf | 1 + .../includes/components/htmlStop.html.jspf | 1 + .../components/logfilterform.html.jspf | 97 + .../components/logpaginationfooter.html.jspf | 11 + .../components/logpaginationheader.html.jspf | 14 + .../includes/components/page.html.jspf | 4 + .../includes/components/tabs.html.jspf | 21 + .../WEB-INF/includes/stylesheets.html.jspf | 10 + .../main/webapp/WEB-INF/includes/taglibs.jspf | 10 + .../WEB-INF/jboss-deployment-structure.xml | 10 + .../WEB-INF/rdf4j-http-server-servlet.xml | 151 + .../src/main/webapp/WEB-INF/sample-web.xml | 64 + .../webapp/WEB-INF/taglibs/navigation.tld | 17 + .../src/main/webapp/WEB-INF/tags/errors.tag | 15 + .../src/main/webapp/WEB-INF/urlrewrite.xml | 14 + .../webapp/WEB-INF/views/home/overview.jsp | 23 + .../main/webapp/WEB-INF/views/overview.jsp | 2 + .../WEB-INF/views/system/info/debug.jsp | 22 + .../WEB-INF/views/system/info/overview.jsp | 74 + .../WEB-INF/views/system/logging/overview.jsp | 50 + .../webapp/WEB-INF/views/system/overview.jsp | 48 + .../server/src/main/webapp/WEB-INF/web.xml | 125 + core/http/server/src/main/webapp/favicon.ico | Bin 0 -> 894 bytes core/http/server/src/main/webapp/favicon.png | Bin 0 -> 221 bytes .../server/src/main/webapp/images/DEBUG.png | Bin 0 -> 884 bytes .../server/src/main/webapp/images/ERROR.png | Bin 0 -> 1122 bytes .../server/src/main/webapp/images/INFO.png | Bin 0 -> 998 bytes .../server/src/main/webapp/images/WARN.png | Bin 0 -> 814 bytes .../src/main/webapp/images/productgroup.png | Bin 0 -> 6236 bytes .../src/main/webapp/images/transparent.png | Bin 0 -> 153 bytes .../src/main/webapp/styles/basic/all.css | 5 + .../webapp/styles/default/images/bg_body.png | Bin 0 -> 69413 bytes .../styles/default/images/bg_header.png | Bin 0 -> 14711 bytes .../webapp/styles/default/images/bg_html.png | Bin 0 -> 9739 bytes .../webapp/styles/default/images/hr_menu.png | Bin 0 -> 226 bytes .../webapp/styles/default/msie-minheight.css | 3 + .../src/main/webapp/styles/default/print.css | 27 + .../src/main/webapp/styles/default/screen.css | 456 + .../webapp/styles/w3-html40-recommended.css | 81 + .../http/server/WebXmlValidationTest.java | 33 + core/http/workbench/compileTypescript.sh | 14 + core/http/workbench/deployTypeScriptVersion | 12 + core/http/workbench/pom.xml | 160 + .../rdf4j/workbench/RepositoryServlet.java | 23 + .../base/AbstractRepositoryServlet.java | 103 + .../rdf4j/workbench/base/AbstractServlet.java | 346 + .../workbench/base/BaseRepositoryServlet.java | 17 + .../rdf4j/workbench/base/BaseServlet.java | 17 + .../workbench/base/TransformationServlet.java | 129 + .../rdf4j/workbench/base/TupleServlet.java | 67 + .../rdf4j/workbench/commands/AddServlet.java | 162 + .../workbench/commands/ClearServlet.java | 74 + .../workbench/commands/ContextsServlet.java | 33 + .../workbench/commands/CreateServlet.java | 156 + .../workbench/commands/DeleteServlet.java | 87 + .../workbench/commands/ExploreServlet.java | 305 + .../workbench/commands/ExportServlet.java | 85 + .../rdf4j/workbench/commands/InfoServlet.java | 99 + .../commands/InformationServlet.java | 55 + .../workbench/commands/NamespacesServlet.java | 67 + .../workbench/commands/QueryServlet.java | 455 + .../workbench/commands/RemoveServlet.java | 102 + .../commands/RepositoriesServlet.java | 33 + .../commands/SavedQueriesServlet.java | 109 + .../workbench/commands/SummaryServlet.java | 126 + .../workbench/commands/TypesServlet.java | 40 + .../workbench/commands/UpdateServlet.java | 95 + .../exceptions/BadRequestException.java | 22 + .../MissingInitParameterException.java | 19 + .../rdf4j/workbench/proxy/CacheFilter.java | 100 + .../proxy/CookieCacheControlFilter.java | 169 + .../rdf4j/workbench/proxy/CookieHandler.java | 86 + .../proxy/ProxyRepositoryServlet.java | 126 + .../rdf4j/workbench/proxy/RedirectFilter.java | 57 + .../workbench/proxy/ServerValidator.java | 135 + .../workbench/proxy/WorkbenchGateway.java | 311 + .../workbench/proxy/WorkbenchServlet.java | 265 + .../workbench/util/BasicServletConfig.java | 67 + .../rdf4j/workbench/util/CookieHandler.java | 112 + .../workbench/util/DynamicHttpRequest.java | 88 + .../rdf4j/workbench/util/PagedQuery.java | 250 + .../rdf4j/workbench/util/QueryEvaluator.java | 306 + .../rdf4j/workbench/util/QueryFactory.java | 55 + .../rdf4j/workbench/util/QueryStorage.java | 517 + .../workbench/util/QueryStringBuilder.java | 117 + .../workbench/util/TupleResultBuilder.java | 188 + .../rdf4j/workbench/util/ValueDecoder.java | 144 + .../workbench/util/WorkbenchRequest.java | 357 + .../src/main/webapp/WEB-INF/glassfish-web.xml | 4 + .../workbench/src/main/webapp/WEB-INF/web.xml | 197 + .../workbench/src/main/webapp/favicon.ico | Bin 0 -> 894 bytes .../workbench/src/main/webapp/favicon.png | Bin 0 -> 221 bytes .../src/main/webapp/images/affirmative.png | Bin 0 -> 607 bytes .../src/main/webapp/images/bookmark.png | Bin 0 -> 202 bytes .../src/main/webapp/images/cancel.png | Bin 0 -> 686 bytes .../workbench/src/main/webapp/images/edit.png | Bin 0 -> 847 bytes .../src/main/webapp/images/external.png | Bin 0 -> 177 bytes .../src/main/webapp/images/negative.png | Bin 0 -> 792 bytes .../src/main/webapp/images/productgroup.png | Bin 0 -> 6236 bytes .../src/main/webapp/images/server.png | Bin 0 -> 1441 bytes .../src/main/webapp/images/server_network.png | Bin 0 -> 1236 bytes .../workbench/src/main/webapp/images/view.png | Bin 0 -> 733 bytes .../src/main/webapp/locale/messages.xsl | 224 + .../workbench/src/main/webapp/scripts/add.js | 79 + .../src/main/webapp/scripts/add.js.map | 1 + .../src/main/webapp/scripts/cookies.html | 4 + .../main/webapp/scripts/create-federate.js | 56 + .../webapp/scripts/create-federate.js.map | 1 + .../src/main/webapp/scripts/create.js | 72 + .../src/main/webapp/scripts/create.js.map | 1 + .../src/main/webapp/scripts/delete.js | 54 + .../src/main/webapp/scripts/delete.js.map | 1 + .../src/main/webapp/scripts/explore.js | 86 + .../src/main/webapp/scripts/explore.js.map | 1 + .../src/main/webapp/scripts/export.js | 25 + .../src/main/webapp/scripts/export.js.map | 1 + .../src/main/webapp/scripts/namespaces.js | 28 + .../src/main/webapp/scripts/namespaces.js.map | 1 + .../src/main/webapp/scripts/paging.js | 286 + .../src/main/webapp/scripts/paging.js.map | 1 + .../src/main/webapp/scripts/query.js | 323 + .../src/main/webapp/scripts/query.js.map | 1 + .../src/main/webapp/scripts/saved-queries.js | 83 + .../main/webapp/scripts/saved-queries.js.map | 1 + .../src/main/webapp/scripts/template.js | 97 + .../src/main/webapp/scripts/template.js.map | 1 + .../src/main/webapp/scripts/ts/add.ts | 73 + .../main/webapp/scripts/ts/create-federate.ts | 51 + .../src/main/webapp/scripts/ts/create.ts | 72 + .../src/main/webapp/scripts/ts/delete.ts | 47 + .../src/main/webapp/scripts/ts/explore.ts | 86 + .../src/main/webapp/scripts/ts/export.ts | 22 + .../src/main/webapp/scripts/ts/namespaces.ts | 21 + .../src/main/webapp/scripts/ts/paging.ts | 290 + .../src/main/webapp/scripts/ts/query.ts | 341 + .../main/webapp/scripts/ts/saved-queries.ts | 82 + .../src/main/webapp/scripts/ts/template.ts | 97 + .../src/main/webapp/scripts/ts/tuple.ts | 44 + .../src/main/webapp/scripts/ts/update.ts | 76 + .../src/main/webapp/scripts/tuple.js | 45 + .../src/main/webapp/scripts/tuple.js.map | 1 + .../src/main/webapp/scripts/update.js | 74 + .../src/main/webapp/scripts/update.js.map | 1 + .../src/main/webapp/styles/basic/all.css | 5 + .../webapp/styles/default/images/hr_menu.png | Bin 0 -> 226 bytes .../src/main/webapp/styles/default/print.css | 27 + .../src/main/webapp/styles/default/screen.css | 539 + .../webapp/styles/w3-html40-recommended.css | 81 + .../src/main/webapp/styles/yasqe.min.css | 1 + .../src/main/webapp/transformations/add.xsl | 148 + .../main/webapp/transformations/boolean.xsl | 32 + .../src/main/webapp/transformations/clear.xsl | 62 + .../main/webapp/transformations/contexts.xsl | 14 + .../transformations/create-federate.xsl | 112 + .../create-memory-customrule.xsl | 133 + .../transformations/create-memory-rdfs-dt.xsl | 94 + .../transformations/create-memory-rdfs.xsl | 92 + .../webapp/transformations/create-memory.xsl | 93 + .../create-native-customrule.xsl | 120 + .../transformations/create-native-rdfs-dt.xsl | 80 + .../transformations/create-native-rdfs.xsl | 78 + .../webapp/transformations/create-native.xsl | 78 + .../webapp/transformations/create-remote.xsl | 88 + .../webapp/transformations/create-sparql.xsl | 88 + .../main/webapp/transformations/create.xsl | 100 + .../main/webapp/transformations/delete.xsl | 57 + .../main/webapp/transformations/explore.xsl | 215 + .../main/webapp/transformations/export.xsl | 82 + .../src/main/webapp/transformations/graph.xsl | 81 + .../webapp/transformations/information.xsl | 113 + .../src/main/webapp/transformations/list.xsl | 36 + .../webapp/transformations/namespaces.xsl | 77 + .../src/main/webapp/transformations/query.xsl | 150 + .../main/webapp/transformations/remove.xsl | 112 + .../webapp/transformations/repositories.xsl | 57 + .../webapp/transformations/saved-queries.xsl | 126 + .../main/webapp/transformations/server.xsl | 75 + .../main/webapp/transformations/summary.xsl | 83 + .../src/main/webapp/transformations/table.xsl | 234 + .../main/webapp/transformations/template.xsl | 334 + .../src/main/webapp/transformations/tuple.xsl | 117 + .../src/main/webapp/transformations/types.xsl | 13 + .../main/webapp/transformations/update.xsl | 62 + .../webapp/transformations/url-encode.xsl | 71 + .../workbench/commands/TestCreateServlet.java | 43 + .../commands/TestExploreServlet.java | 217 + .../workbench/commands/TestInfoServlet.java | 66 + .../workbench/commands/TestQueryServlet.java | 160 + .../workbench/commands/TestRemoveServlet.java | 55 + .../rdf4j/workbench/util/TestPagedQuery.java | 53 + .../util/TestTupleResultBuilder.java | 80 + .../workbench/util/TestValueDecoder.java | 126 + .../http/workbench/src/test/resources/long.rq | 51 + .../workbench/src/test/resources/ses2307.rq | 8 + core/model/pom.xml | 28 + .../org/eclipse/rdf4j/IsolationLevel.java | 43 + .../org/eclipse/rdf4j/IsolationLevels.java | 136 + .../org/eclipse/rdf4j/OpenRDFException.java | 35 + .../java/org/eclipse/rdf4j/OpenRDFUtil.java | 42 + .../java/org/eclipse/rdf4j/model/BNode.java | 41 + .../java/org/eclipse/rdf4j/model/Graph.java | 96 + .../java/org/eclipse/rdf4j/model/IRI.java | 77 + .../java/org/eclipse/rdf4j/model/Literal.java | 165 + .../java/org/eclipse/rdf4j/model/Model.java | 647 + .../org/eclipse/rdf4j/model/ModelFactory.java | 22 + .../org/eclipse/rdf4j/model/Namespace.java | 33 + .../org/eclipse/rdf4j/model/Resource.java | 16 + .../org/eclipse/rdf4j/model/Statement.java | 67 + .../java/org/eclipse/rdf4j/model/URI.java | 66 + .../java/org/eclipse/rdf4j/model/Value.java | 22 + .../org/eclipse/rdf4j/model/ValueFactory.java | 315 + .../model/datatypes/XMLDatatypeUtil.java | 1987 + .../rdf4j/model/datatypes/XMLDateTime.java | 539 + .../rdf4j/model/impl/AbstractModel.java | 611 + .../model/impl/AbstractValueFactory.java | 279 + .../eclipse/rdf4j/model/impl/BNodeImpl.java | 36 + .../rdf4j/model/impl/BooleanLiteral.java | 68 + .../rdf4j/model/impl/CalendarLiteral.java | 41 + .../rdf4j/model/impl/ContextStatement.java | 73 + .../model/impl/ContextStatementImpl.java | 35 + .../rdf4j/model/impl/DecimalLiteral.java | 91 + .../eclipse/rdf4j/model/impl/EmptyModel.java | 103 + .../rdf4j/model/impl/FilteredModel.java | 259 + .../eclipse/rdf4j/model/impl/GraphImpl.java | 178 + .../rdf4j/model/impl/IntegerLiteral.java | 91 + .../rdf4j/model/impl/LinkedHashModel.java | 541 + .../model/impl/LinkedHashModelFactory.java | 24 + .../eclipse/rdf4j/model/impl/LiteralImpl.java | 48 + .../rdf4j/model/impl/NamespaceImpl.java | 23 + .../rdf4j/model/impl/NumericLiteral.java | 110 + .../eclipse/rdf4j/model/impl/SimpleBNode.java | 98 + .../eclipse/rdf4j/model/impl/SimpleIRI.java | 133 + .../rdf4j/model/impl/SimpleLiteral.java | 245 + .../rdf4j/model/impl/SimpleNamespace.java | 156 + .../rdf4j/model/impl/SimpleStatement.java | 145 + .../rdf4j/model/impl/SimpleValueFactory.java | 39 + .../rdf4j/model/impl/StatementImpl.java | 33 + .../eclipse/rdf4j/model/impl/TreeModel.java | 885 + .../rdf4j/model/impl/TreeModelFactory.java | 24 + .../org/eclipse/rdf4j/model/impl/URIImpl.java | 28 + .../rdf4j/model/impl/UnmodifiableModel.java | 97 + .../rdf4j/model/impl/ValueFactoryBase.java | 20 + .../rdf4j/model/impl/ValueFactoryImpl.java | 36 + .../org/eclipse/rdf4j/model/impl/package.html | 5 + .../java/org/eclipse/rdf4j/model/package.html | 29 + .../eclipse/rdf4j/model/util/GraphUtil.java | 560 + .../rdf4j/model/util/GraphUtilException.java | 38 + .../model/util/LexicalValueComparator.java | 172 + .../eclipse/rdf4j/model/util/LiteralUtil.java | 24 + .../model/util/LiteralUtilException.java | 37 + .../eclipse/rdf4j/model/util/Literals.java | 616 + .../rdf4j/model/util/ModelException.java | 63 + .../eclipse/rdf4j/model/util/ModelUtil.java | 20 + .../org/eclipse/rdf4j/model/util/Models.java | 576 + .../eclipse/rdf4j/model/util/Namespaces.java | 193 + .../rdf4j/model/util/PatternIterator.java | 128 + .../org/eclipse/rdf4j/model/util/URIUtil.java | 265 + .../model/util/language/IanaLanguageTag.java | 141 + .../rdf4j/model/util/language/Iso3166.java | 303 + .../rdf4j/model/util/language/Iso639.java | 580 + .../model/util/language/LanguageTag.java | 333 + .../model/util/language/LanguageTagCodes.java | 83 + .../language/LanguageTagSyntaxException.java | 39 + .../eclipse/rdf4j/model/vocabulary/DC.java | 135 + .../rdf4j/model/vocabulary/DCTERMS.java | 677 + .../eclipse/rdf4j/model/vocabulary/DOAP.java | 90 + .../eclipse/rdf4j/model/vocabulary/EARL.java | 104 + .../eclipse/rdf4j/model/vocabulary/FN.java | 160 + .../eclipse/rdf4j/model/vocabulary/FOAF.java | 196 + .../eclipse/rdf4j/model/vocabulary/GEO.java | 34 + .../eclipse/rdf4j/model/vocabulary/GEOF.java | 114 + .../eclipse/rdf4j/model/vocabulary/OWL.java | 246 + .../eclipse/rdf4j/model/vocabulary/RDF.java | 112 + .../eclipse/rdf4j/model/vocabulary/RDFS.java | 100 + .../eclipse/rdf4j/model/vocabulary/SD.java | 616 + .../rdf4j/model/vocabulary/SESAME.java | 68 + .../rdf4j/model/vocabulary/SESAMEQNAME.java | 48 + .../eclipse/rdf4j/model/vocabulary/SKOS.java | 377 + .../eclipse/rdf4j/model/vocabulary/SP.java | 750 + .../eclipse/rdf4j/model/vocabulary/SPIN.java | 446 + .../rdf4j/model/vocabulary/XMLSchema.java | 279 + .../rdf4j/model/vocabulary/package.html | 6 + .../eclipse/rdf4j/IsolationLevelsTest.java | 99 + .../model/AbstractModelPerformanceTest.java | 474 + .../rdf4j/model/AbstractModelTest.java | 1484 + .../model/LinkedHashModelPerformanceTest.java | 23 + .../rdf4j/model/LinkedHashModelTest.java | 23 + .../rdf4j/model/TreeModelPerformanceTest.java | 23 + .../eclipse/rdf4j/model/TreeModelTest.java | 23 + .../eclipse/rdf4j/model/ValueFactoryTest.java | 176 + .../rdf4j/model/datatypes/DateTimeTest.java | 277 + .../model/datatypes/XMLDatatypeUtilTest.java | 302 + .../model/impl/ContextStatementTest.java | 74 + .../rdf4j/model/impl/SimpleLiteralTest.java | 467 + .../rdf4j/model/util/LiteralsTest.java | 953 + .../eclipse/rdf4j/model/util/ModelsTest.java | 316 + .../rdf4j/model/util/NamespacesTest.java | 475 + .../eclipse/rdf4j/model/util/URIUtilTest.java | 70 + core/pom.xml | 115 + core/query/pom.xml | 35 + .../AbstractTupleQueryResultHandler.java | 51 + .../java/org/eclipse/rdf4j/query/Binding.java | 56 + .../org/eclipse/rdf4j/query/BindingSet.java | 104 + .../org/eclipse/rdf4j/query/BooleanQuery.java | 17 + .../query/BooleanQueryResultHandler.java | 19 + .../BooleanQueryResultHandlerException.java | 54 + .../java/org/eclipse/rdf4j/query/Dataset.java | 59 + .../org/eclipse/rdf4j/query/GraphQuery.java | 20 + .../eclipse/rdf4j/query/GraphQueryResult.java | 35 + .../query/IncompatibleOperationException.java | 38 + .../rdf4j/query/MalformedQueryException.java | 38 + .../org/eclipse/rdf4j/query/Operation.java | 110 + .../java/org/eclipse/rdf4j/query/Query.java | 44 + .../rdf4j/query/QueryEvaluationException.java | 56 + .../query/QueryInterruptedException.java | 36 + .../eclipse/rdf4j/query/QueryLanguage.java | 182 + .../org/eclipse/rdf4j/query/QueryResult.java | 21 + .../rdf4j/query/QueryResultHandler.java | 140 + .../query/QueryResultHandlerException.java | 55 + .../eclipse/rdf4j/query/QueryResultUtil.java | 17 + .../org/eclipse/rdf4j/query/QueryResults.java | 536 + .../org/eclipse/rdf4j/query/TupleQuery.java | 17 + .../eclipse/rdf4j/query/TupleQueryResult.java | 31 + .../rdf4j/query/TupleQueryResultHandler.java | 21 + .../query/TupleQueryResultHandlerBase.java | 17 + .../TupleQueryResultHandlerException.java | 52 + .../UnsupportedQueryLanguageException.java | 50 + .../java/org/eclipse/rdf4j/query/Update.java | 27 + .../rdf4j/query/UpdateExecutionException.java | 60 + .../query/dawg/DAWGTestBooleanParser.java | 88 + .../dawg/DAWGTestResultSetParseException.java | 51 + .../query/dawg/DAWGTestResultSetParser.java | 170 + .../query/dawg/DAWGTestResultSetSchema.java | 52 + .../query/dawg/DAWGTestResultSetUtil.java | 85 + .../query/dawg/DAWGTestResultSetWriter.java | 173 + .../org/eclipse/rdf4j/query/dawg/package.html | 6 + .../rdf4j/query/impl/AbstractOperation.java | 90 + .../rdf4j/query/impl/AbstractQuery.java | 42 + .../rdf4j/query/impl/AbstractUpdate.java | 32 + .../eclipse/rdf4j/query/impl/BindingImpl.java | 25 + .../eclipse/rdf4j/query/impl/DatasetImpl.java | 19 + .../rdf4j/query/impl/EmptyBindingSet.java | 97 + .../rdf4j/query/impl/FallbackDataset.java | 105 + .../query/impl/GraphQueryResultImpl.java | 29 + .../query/impl/IteratingGraphQueryResult.java | 66 + .../query/impl/IteratingTupleQueryResult.java | 84 + .../rdf4j/query/impl/ListBindingSet.java | 212 + .../rdf4j/query/impl/MapBindingSet.java | 171 + .../query/impl/MutableTupleQueryResult.java | 261 + .../rdf4j/query/impl/SimpleBinding.java | 71 + .../rdf4j/query/impl/SimpleDataset.java | 165 + .../query/impl/TupleQueryResultBuilder.java | 54 + .../query/impl/TupleQueryResultImpl.java | 29 + .../java/org/eclipse/rdf4j/query/package.html | 5 + .../rdf4j/common/iteration/AllTests.java | 39 + .../iteration/CloseableIterationTest.java | 54 + .../CloseableIteratorIterationTest.java | 26 + .../iteration/ConvertingIterationTest.java | 42 + .../iteration/DelayedIterationTest.java | 34 + .../DistinctIntersectionIterationTest.java | 32 + .../iteration/DistinctIterationTest.java | 28 + .../iteration/DistinctMinusIterationTest.java | 32 + .../common/iteration/EmptyIterationTest.java | 30 + .../ExceptionConvertingIterationTest.java | 34 + .../common/iteration/FilterIterationTest.java | 37 + .../iteration/IntersectionIterationTest.java | 32 + .../rdf4j/common/iteration/IterationTest.java | 54 + .../iteration/IteratorIterationTest.java | 26 + .../common/iteration/LimitIterationTest.java | 58 + .../iteration/LookAheadIterationTest.java | 44 + .../common/iteration/MinusIterationTest.java | 32 + .../common/iteration/OffsetIterationTest.java | 59 + .../iteration/SingletonIterationTest.java | 26 + .../common/iteration/UnionIterationTest.java | 47 + .../eclipse/rdf4j/query/QueryResultsTest.java | 403 + core/queryalgebra/evaluation/pom.xml | 73 + .../evaluation/EvaluationStrategy.java | 105 + .../algebra/evaluation/QueryBindingSet.java | 205 + .../algebra/evaluation/QueryOptimizer.java | 26 + .../algebra/evaluation/TripleSource.java | 57 + .../ValueExprEvaluationException.java | 39 + .../AbstractFederatedServiceResolver.java | 121 + .../FederatedServiceResolverBase.java | 17 + .../FederatedServiceResolverImpl.java | 79 + .../federation/JoinExecutorBase.java | 154 + .../RepositoryFederatedService.java | 519 + .../federation/SPARQLFederatedService.java | 35 + .../ServiceCrossProductIteration.java | 43 + .../federation/ServiceFallbackIteration.java | 90 + .../ServiceJoinConversionIteration.java | 66 + .../federation/ServiceJoinIterator.java | 73 + .../evaluation/function/BooleanCast.java | 92 + .../evaluation/function/DateTimeCast.java | 123 + .../evaluation/function/DecimalCast.java | 78 + .../evaluation/function/DoubleCast.java | 76 + .../evaluation/function/FloatCast.java | 76 + .../algebra/evaluation/function/Function.java | 23 + .../evaluation/function/FunctionRegistry.java | 42 + .../evaluation/function/IntegerCast.java | 87 + .../evaluation/function/StringCast.java | 82 + .../evaluation/function/datetime/Day.java | 74 + .../evaluation/function/datetime/Hours.java | 74 + .../evaluation/function/datetime/Minutes.java | 74 + .../evaluation/function/datetime/Month.java | 74 + .../evaluation/function/datetime/Now.java | 60 + .../evaluation/function/datetime/Seconds.java | 74 + .../function/datetime/Timezone.java | 95 + .../evaluation/function/datetime/Tz.java | 69 + .../evaluation/function/datetime/Year.java | 72 + .../function/hash/HashFunction.java | 42 + .../algebra/evaluation/function/hash/MD5.java | 64 + .../evaluation/function/hash/SHA1.java | 64 + .../evaluation/function/hash/SHA256.java | 64 + .../evaluation/function/hash/SHA384.java | 63 + .../evaluation/function/hash/SHA512.java | 63 + .../evaluation/function/numeric/Abs.java | 72 + .../evaluation/function/numeric/Ceil.java | 75 + .../evaluation/function/numeric/Floor.java | 74 + .../evaluation/function/numeric/Rand.java | 44 + .../evaluation/function/numeric/Round.java | 74 + .../evaluation/function/rdfterm/STRUUID.java | 44 + .../evaluation/function/rdfterm/StrDt.java | 56 + .../evaluation/function/rdfterm/StrLang.java | 56 + .../evaluation/function/rdfterm/UUID.java | 44 + .../evaluation/function/string/Concat.java | 98 + .../evaluation/function/string/Contains.java | 78 + .../function/string/EncodeForUri.java | 106 + .../evaluation/function/string/LowerCase.java | 71 + .../evaluation/function/string/Replace.java | 125 + .../evaluation/function/string/StrAfter.java | 88 + .../evaluation/function/string/StrBefore.java | 88 + .../evaluation/function/string/StrEnds.java | 61 + .../evaluation/function/string/StrLen.java | 61 + .../evaluation/function/string/StrStarts.java | 65 + .../evaluation/function/string/Substring.java | 124 + .../evaluation/function/string/UpperCase.java | 70 + .../evaluation/impl/BindingAssigner.java | 47 + .../evaluation/impl/CompareOptimizer.java | 86 + .../impl/ConjunctiveConstraintSplitter.java | 103 + .../evaluation/impl/ConstantOptimizer.java | 362 + .../impl/DisjunctiveConstraintOptimizer.java | 90 + .../evaluation/impl/EvaluationStatistics.java | 288 + .../impl/EvaluationStrategyImpl.java | 27 + .../algebra/evaluation/impl/ExternalSet.java | 53 + .../evaluation/impl/FilterOptimizer.java | 207 + .../impl/IterativeEvaluationOptimizer.java | 57 + .../evaluation/impl/OrderLimitOptimizer.java | 87 + .../evaluation/impl/QueryJoinOptimizer.java | 468 + .../evaluation/impl/QueryModelNormalizer.java | 299 + .../evaluation/impl/QueryModelPruner.java | 154 + .../impl/SameTermFilterOptimizer.java | 231 + .../impl/SimpleEvaluationStrategy.java | 1967 + .../BadlyDesignedLeftJoinIterator.java | 91 + .../iterator/BindingSetHashKey.java | 93 + .../iterator/BottomUpJoinIterator.java | 276 + .../iterator/CollectionIteration.java | 49 + .../iterator/CompatibleBindingSetFilter.java | 40 + .../iterator/CrossProductIteration.java | 75 + .../iterator/DescribeIteration.java | 230 + .../iterator/ExtensionIterator.java | 67 + .../evaluation/iterator/FilterIterator.java | 95 + .../evaluation/iterator/GroupIterator.java | 740 + .../iterator/HashJoinIteration.java | 350 + .../evaluation/iterator/JoinIterator.java | 89 + .../evaluation/iterator/LeftJoinIterator.java | 127 + .../iterator/MultiProjectionIterator.java | 104 + .../evaluation/iterator/OrderIterator.java | 237 + .../evaluation/iterator/PathIteration.java | 447 + .../iterator/ProjectionIterator.java | 73 + .../iterator/SPARQLMinusIteration.java | 168 + .../evaluation/iterator/SilentIteration.java | 43 + .../iterator/ZeroLengthPathIteration.java | 181 + .../LimitedSizeEvaluationStrategy.java | 195 + .../LimitedSizeBottomUpJoinIterator.java | 101 + .../LimitedSizeDistinctIteration.java | 48 + .../LimitedSizeHashJoinIteration.java | 86 + .../LimitedSizeIntersectIteration.java | 86 + .../iterator/LimitedSizeIteratorUtil.java | 63 + .../iterator/LimitedSizeOrderIteration.java | 85 + .../iterator/LimitedSizePathIterator.java | 57 + .../LimitedSizeSPARQLMinusIteration.java | 98 + .../LimitedSizeZeroLengthPathIteration.java | 53 + .../evaluation/util/EvaluationStrategies.java | 92 + .../algebra/evaluation/util/MathUtil.java | 219 + .../evaluation/util/OrderComparator.java | 167 + .../evaluation/util/QueryEvaluationUtil.java | 434 + .../evaluation/util/QueryOptimizerList.java | 53 + .../evaluation/util/ValueComparator.java | 195 + ...query.algebra.evaluation.function.Function | 42 + .../evaluation/function/TestDateTimeCast.java | 98 + .../evaluation/function/TestIntegerCast.java | 70 + .../evaluation/function/TestStringCast.java | 125 + .../function/datetime/TimezoneTest.java | 105 + .../evaluation/function/datetime/TzTest.java | 106 + .../function/hash/HashFunctionTest.java | 124 + .../evaluation/function/hash/MD5Test.java | 31 + .../evaluation/function/hash/SHA1Test.java | 30 + .../evaluation/function/hash/SHA256Test.java | 30 + .../evaluation/function/hash/SHA384Test.java | 30 + .../evaluation/function/hash/SHA512Test.java | 30 + .../evaluation/function/numeric/RandTest.java | 73 + .../function/numeric/RoundTest.java | 101 + .../function/string/LowerCaseTest.java | 96 + .../evaluation/function/string/RegexTest.java | 158 + .../function/string/ReplaceTest.java | 170 + .../function/string/StrAfterTest.java | 262 + .../function/string/StrBeforeTest.java | 258 + .../function/string/SubstringTest.java | 114 + .../function/string/UpperCaseTest.java | 96 + .../impl/ConstantOptimizerTest.java | 100 + .../evaluation/impl/EmptyTripleSource.java | 45 + .../impl/QueryJoinOptimizerTest.java | 105 + .../evaluation/iterator/BindingSetSize.java | 56 + .../iterator/HashJoinIterationTest.java | 109 + .../evaluation/iterator/IterationStub.java | 55 + .../evaluation/iterator/JoinIteratorTest.java | 100 + .../iterator/OrderIteratorTest.java | 189 + .../evaluation/iterator/SizeComparator.java | 25 + .../util/LiteralComparatorTest.java | 171 + .../evaluation/util/OrderComparatorTest.java | 209 + .../util/QueryEvaluationUtilTest.java | 258 + .../evaluation/util/ValueComparatorTest.java | 185 + .../src/test/resources/logback-test.xml | 15 + core/queryalgebra/geosparql/pom.xml | 33 + .../function/geosparql/Boundary.java | 31 + .../evaluation/function/geosparql/Buffer.java | 61 + .../function/geosparql/ConvexHull.java | 31 + .../geosparql/DefaultSpatialAlgebra.java | 262 + .../function/geosparql/DefaultWktWriter.java | 112 + .../function/geosparql/Difference.java | 31 + .../function/geosparql/Distance.java | 51 + .../function/geosparql/EhContains.java | 31 + .../function/geosparql/EhCoveredBy.java | 31 + .../function/geosparql/EhCovers.java | 31 + .../function/geosparql/EhDisjoint.java | 31 + .../function/geosparql/EhEquals.java | 31 + .../function/geosparql/EhInside.java | 31 + .../evaluation/function/geosparql/EhMeet.java | 31 + .../function/geosparql/EhOverlap.java | 31 + .../function/geosparql/Envelope.java | 31 + .../function/geosparql/FunctionArguments.java | 140 + .../geosparql/GeometricBinaryFunction.java | 48 + .../geosparql/GeometricRelationFunction.java | 38 + .../geosparql/GeometricUnaryFunction.java | 46 + .../function/geosparql/Intersection.java | 31 + .../evaluation/function/geosparql/RCC8DC.java | 31 + .../evaluation/function/geosparql/RCC8EC.java | 31 + .../evaluation/function/geosparql/RCC8EQ.java | 31 + .../function/geosparql/RCC8NTPP.java | 31 + .../function/geosparql/RCC8NTPPI.java | 31 + .../evaluation/function/geosparql/RCC8PO.java | 31 + .../function/geosparql/RCC8TPP.java | 31 + .../function/geosparql/RCC8TPPI.java | 31 + .../evaluation/function/geosparql/Relate.java | 48 + .../evaluation/function/geosparql/SRID.java | 52 + .../function/geosparql/SfContains.java | 31 + .../function/geosparql/SfCrosses.java | 31 + .../function/geosparql/SfDisjoint.java | 31 + .../function/geosparql/SfEquals.java | 31 + .../function/geosparql/SfIntersects.java | 31 + .../function/geosparql/SfOverlaps.java | 31 + .../function/geosparql/SfTouches.java | 31 + .../function/geosparql/SfWithin.java | 31 + .../function/geosparql/SpatialAlgebra.java | 73 + .../function/geosparql/SpatialSupport.java | 100 + .../geosparql/SymmetricDifference.java | 31 + .../evaluation/function/geosparql/Union.java | 31 + .../function/geosparql/WktWriter.java | 18 + ...query.algebra.evaluation.function.Function | 35 + core/queryalgebra/model/pom.xml | 34 + .../algebra/AbstractAggregateOperator.java | 57 + .../query/algebra/AbstractQueryModelNode.java | 115 + .../org/eclipse/rdf4j/query/algebra/Add.java | 148 + .../query/algebra/AggregateOperator.java | 23 + .../query/algebra/AggregateOperatorBase.java | 23 + .../org/eclipse/rdf4j/query/algebra/And.java | 50 + .../query/algebra/ArbitraryLengthPath.java | 274 + .../org/eclipse/rdf4j/query/algebra/Avg.java | 50 + .../rdf4j/query/algebra/BNodeGenerator.java | 61 + .../query/algebra/BinaryTupleOperator.java | 141 + .../query/algebra/BinaryValueOperator.java | 141 + .../query/algebra/BindingSetAssignment.java | 96 + .../eclipse/rdf4j/query/algebra/Bound.java | 107 + .../eclipse/rdf4j/query/algebra/Clear.java | 136 + .../eclipse/rdf4j/query/algebra/Coalesce.java | 23 + .../eclipse/rdf4j/query/algebra/Compare.java | 113 + .../rdf4j/query/algebra/CompareAll.java | 76 + .../rdf4j/query/algebra/CompareAny.java | 76 + .../algebra/CompareSubQueryValueOperator.java | 83 + .../org/eclipse/rdf4j/query/algebra/Copy.java | 148 + .../eclipse/rdf4j/query/algebra/Count.java | 53 + .../eclipse/rdf4j/query/algebra/Create.java | 115 + .../eclipse/rdf4j/query/algebra/Datatype.java | 54 + .../rdf4j/query/algebra/DeleteData.java | 56 + .../rdf4j/query/algebra/DescribeOperator.java | 26 + .../rdf4j/query/algebra/Difference.java | 70 + .../eclipse/rdf4j/query/algebra/Distinct.java | 47 + .../eclipse/rdf4j/query/algebra/EmptySet.java | 46 + .../eclipse/rdf4j/query/algebra/Exists.java | 50 + .../rdf4j/query/algebra/Extension.java | 139 + .../rdf4j/query/algebra/ExtensionElem.java | 102 + .../eclipse/rdf4j/query/algebra/Filter.java | 96 + .../rdf4j/query/algebra/FunctionCall.java | 143 + .../eclipse/rdf4j/query/algebra/Group.java | 188 + .../rdf4j/query/algebra/GroupConcat.java | 55 + .../rdf4j/query/algebra/GroupElem.java | 103 + .../rdf4j/query/algebra/IRIFunction.java | 70 + .../org/eclipse/rdf4j/query/algebra/If.java | 196 + .../org/eclipse/rdf4j/query/algebra/In.java | 51 + .../rdf4j/query/algebra/InsertData.java | 57 + .../rdf4j/query/algebra/Intersection.java | 77 + .../eclipse/rdf4j/query/algebra/IsBNode.java | 47 + .../rdf4j/query/algebra/IsLiteral.java | 47 + .../rdf4j/query/algebra/IsNumeric.java | 53 + .../rdf4j/query/algebra/IsResource.java | 47 + .../eclipse/rdf4j/query/algebra/IsURI.java | 47 + .../org/eclipse/rdf4j/query/algebra/Join.java | 85 + .../eclipse/rdf4j/query/algebra/Label.java | 52 + .../org/eclipse/rdf4j/query/algebra/Lang.java | 54 + .../rdf4j/query/algebra/LangMatches.java | 51 + .../eclipse/rdf4j/query/algebra/LeftJoin.java | 128 + .../org/eclipse/rdf4j/query/algebra/Like.java | 104 + .../query/algebra/ListMemberOperator.java | 40 + .../org/eclipse/rdf4j/query/algebra/Load.java | 136 + .../rdf4j/query/algebra/LocalName.java | 52 + .../eclipse/rdf4j/query/algebra/MathExpr.java | 96 + .../org/eclipse/rdf4j/query/algebra/Max.java | 43 + .../org/eclipse/rdf4j/query/algebra/Min.java | 43 + .../eclipse/rdf4j/query/algebra/Modify.java | 152 + .../org/eclipse/rdf4j/query/algebra/Move.java | 148 + .../rdf4j/query/algebra/MultiProjection.java | 150 + .../query/algebra/NAryValueOperator.java | 122 + .../rdf4j/query/algebra/Namespace.java | 52 + .../org/eclipse/rdf4j/query/algebra/Not.java | 50 + .../org/eclipse/rdf4j/query/algebra/Or.java | 50 + .../eclipse/rdf4j/query/algebra/Order.java | 127 + .../rdf4j/query/algebra/OrderElem.java | 118 + .../rdf4j/query/algebra/Projection.java | 126 + .../rdf4j/query/algebra/ProjectionElem.java | 133 + .../query/algebra/ProjectionElemList.java | 143 + .../rdf4j/query/algebra/QueryModelNode.java | 99 + .../query/algebra/QueryModelNodeBase.java | 19 + .../query/algebra/QueryModelVisitor.java | 257 + .../rdf4j/query/algebra/QueryRoot.java | 65 + .../eclipse/rdf4j/query/algebra/Reduced.java | 47 + .../eclipse/rdf4j/query/algebra/Regex.java | 103 + .../eclipse/rdf4j/query/algebra/SameTerm.java | 50 + .../eclipse/rdf4j/query/algebra/Sample.java | 45 + .../eclipse/rdf4j/query/algebra/Service.java | 307 + .../rdf4j/query/algebra/SingletonSet.java | 46 + .../eclipse/rdf4j/query/algebra/Slice.java | 128 + .../rdf4j/query/algebra/StatementPattern.java | 307 + .../org/eclipse/rdf4j/query/algebra/Str.java | 55 + .../query/algebra/SubQueryValueOperator.java | 81 + .../org/eclipse/rdf4j/query/algebra/Sum.java | 45 + .../rdf4j/query/algebra/TupleExpr.java | 34 + .../query/algebra/UnaryTupleOperator.java | 115 + .../query/algebra/UnaryValueOperator.java | 112 + .../eclipse/rdf4j/query/algebra/Union.java | 76 + .../rdf4j/query/algebra/UpdateExpr.java | 21 + .../rdf4j/query/algebra/ValueConstant.java | 83 + .../rdf4j/query/algebra/ValueExpr.java | 16 + .../org/eclipse/rdf4j/query/algebra/Var.java | 143 + .../rdf4j/query/algebra/ZeroLengthPath.java | 261 + .../federation/FederatedService.java | 133 + .../federation/FederatedServiceResolver.java | 39 + .../FederatedServiceResolverClient.java | 26 + .../helpers/AbstractQueryModelVisitor.java | 724 + .../helpers/QueryModelNodeReplacer.java | 133 + .../helpers/QueryModelTreePrinter.java | 79 + .../helpers/QueryModelVisitorBase.java | 17 + .../helpers/StatementPatternCollector.java | 49 + .../query/algebra/helpers/TupleExprs.java | 67 + .../algebra/helpers/VarNameCollector.java | 40 + .../eclipse/rdf4j/query/algebra/package.html | 5 + core/queryalgebra/pom.xml | 23 + core/queryparser/api/pom.xml | 38 + .../query/parser/ParsedBooleanQuery.java | 53 + .../rdf4j/query/parser/ParsedGraphQuery.java | 119 + .../rdf4j/query/parser/ParsedOperation.java | 43 + .../rdf4j/query/parser/ParsedQuery.java | 130 + .../rdf4j/query/parser/ParsedTupleQuery.java | 53 + .../rdf4j/query/parser/ParsedUpdate.java | 120 + .../rdf4j/query/parser/QueryParser.java | 25 + .../query/parser/QueryParserFactory.java | 29 + .../query/parser/QueryParserRegistry.java | 45 + .../rdf4j/query/parser/QueryParserUtil.java | 222 + .../rdf4j/query/parser/QueryPrologLexer.java | 235 + .../query/parser/QueryParserUtilTest.java | 33 + .../query/parser/QueryPrologLexerTest.java | 157 + core/queryparser/pom.xml | 23 + core/queryparser/serql/pom.xml | 49 + .../query/parser/serql/ASTVisitorBase.java | 17 + .../parser/serql/AbstractASTVisitor.java | 476 + .../parser/serql/AnonymousVarGenerator.java | 80 + .../parser/serql/ConstructorBuilder.java | 165 + .../query/parser/serql/GraphPattern.java | 195 + .../parser/serql/NamespaceDeclProcessor.java | 143 + .../query/parser/serql/NullProcessor.java | 147 + .../query/parser/serql/OptionalTupleExpr.java | 42 + .../serql/ProjectionAliasProcessor.java | 79 + .../parser/serql/ProjectionProcessor.java | 147 + .../query/parser/serql/QueryModelBuilder.java | 1035 + .../rdf4j/query/parser/serql/SeRQLParser.java | 112 + .../parser/serql/SeRQLParserFactory.java | 36 + .../rdf4j/query/parser/serql/SeRQLUtil.java | 143 + .../parser/serql/StringEscapesProcessor.java | 85 + .../rdf4j/query/parser/serql/ast/ASTAnd.java | 32 + .../query/parser/serql/ast/ASTArgList.java | 32 + .../query/parser/serql/ast/ASTBNode.java | 41 + .../parser/serql/ast/ASTBasicPathExpr.java | 34 + .../serql/ast/ASTBasicPathExprTail.java | 43 + .../parser/serql/ast/ASTBooleanConstant.java | 42 + .../parser/serql/ast/ASTBooleanExpr.java | 19 + .../query/parser/serql/ast/ASTBound.java | 43 + .../parser/serql/ast/ASTCompOperator.java | 38 + .../query/parser/serql/ast/ASTCompare.java | 38 + .../query/parser/serql/ast/ASTCompareAll.java | 38 + .../query/parser/serql/ast/ASTCompareAny.java | 38 + .../query/parser/serql/ast/ASTConstruct.java | 82 + .../parser/serql/ast/ASTConstructQuery.java | 62 + .../query/parser/serql/ast/ASTDatatype.java | 30 + .../rdf4j/query/parser/serql/ast/ASTEdge.java | 35 + .../query/parser/serql/ast/ASTExists.java | 30 + .../rdf4j/query/parser/serql/ast/ASTFrom.java | 45 + .../parser/serql/ast/ASTFunctionCall.java | 35 + .../parser/serql/ast/ASTGraphIntersect.java | 26 + .../query/parser/serql/ast/ASTGraphMinus.java | 26 + .../query/parser/serql/ast/ASTGraphQuery.java | 19 + .../parser/serql/ast/ASTGraphQuerySet.java | 27 + .../query/parser/serql/ast/ASTGraphUnion.java | 48 + .../rdf4j/query/parser/serql/ast/ASTIn.java | 34 + .../query/parser/serql/ast/ASTInList.java | 34 + .../query/parser/serql/ast/ASTIsBNode.java | 30 + .../query/parser/serql/ast/ASTIsLiteral.java | 30 + .../query/parser/serql/ast/ASTIsResource.java | 30 + .../query/parser/serql/ast/ASTIsURI.java | 30 + .../query/parser/serql/ast/ASTLabel.java | 30 + .../rdf4j/query/parser/serql/ast/ASTLang.java | 30 + .../parser/serql/ast/ASTLangMatches.java | 34 + .../rdf4j/query/parser/serql/ast/ASTLike.java | 56 + .../query/parser/serql/ast/ASTLimit.java | 42 + .../query/parser/serql/ast/ASTLiteral.java | 76 + .../query/parser/serql/ast/ASTLocalName.java | 30 + .../query/parser/serql/ast/ASTNamespace.java | 30 + .../parser/serql/ast/ASTNamespaceDecl.java | 46 + .../rdf4j/query/parser/serql/ast/ASTNode.java | 32 + .../query/parser/serql/ast/ASTNodeElem.java | 35 + .../rdf4j/query/parser/serql/ast/ASTNot.java | 43 + .../rdf4j/query/parser/serql/ast/ASTNull.java | 26 + .../query/parser/serql/ast/ASTOffset.java | 41 + .../parser/serql/ast/ASTOptPathExpr.java | 54 + .../parser/serql/ast/ASTOptPathExprTail.java | 70 + .../rdf4j/query/parser/serql/ast/ASTOr.java | 32 + .../query/parser/serql/ast/ASTOrderBy.java | 32 + .../query/parser/serql/ast/ASTOrderExpr.java | 51 + .../query/parser/serql/ast/ASTPathExpr.java | 19 + .../parser/serql/ast/ASTPathExprList.java | 32 + .../parser/serql/ast/ASTPathExprTail.java | 53 + .../parser/serql/ast/ASTPathExprUnion.java | 32 + .../parser/serql/ast/ASTProjectionElem.java | 49 + .../query/parser/serql/ast/ASTQName.java | 47 + .../query/parser/serql/ast/ASTQuery.java | 19 + .../query/parser/serql/ast/ASTQueryBody.java | 58 + .../parser/serql/ast/ASTQueryContainer.java | 40 + .../query/parser/serql/ast/ASTRegex.java | 46 + .../parser/serql/ast/ASTReifiedStat.java | 48 + .../query/parser/serql/ast/ASTSameTerm.java | 34 + .../query/parser/serql/ast/ASTSelect.java | 84 + .../parser/serql/ast/ASTSelectQuery.java | 66 + .../rdf4j/query/parser/serql/ast/ASTStr.java | 30 + .../query/parser/serql/ast/ASTString.java | 42 + .../parser/serql/ast/ASTTupleIntersect.java | 26 + .../query/parser/serql/ast/ASTTupleMinus.java | 26 + .../query/parser/serql/ast/ASTTupleQuery.java | 19 + .../parser/serql/ast/ASTTupleQuerySet.java | 27 + .../query/parser/serql/ast/ASTTupleUnion.java | 48 + .../rdf4j/query/parser/serql/ast/ASTURI.java | 47 + .../query/parser/serql/ast/ASTValue.java | 22 + .../query/parser/serql/ast/ASTValueExpr.java | 20 + .../rdf4j/query/parser/serql/ast/ASTVar.java | 58 + .../query/parser/serql/ast/ASTWhere.java | 30 + .../query/parser/serql/ast/CastingList.java | 36 + .../serql/ast/JJTSyntaxTreeBuilderState.java | 130 + .../rdf4j/query/parser/serql/ast/Node.java | 70 + .../parser/serql/ast/ParseException.java | 194 + .../parser/serql/ast/SimpleCharStream.java | 478 + .../query/parser/serql/ast/SimpleNode.java | 199 + .../parser/serql/ast/SyntaxTreeBuilder.java | 3329 + .../serql/ast/SyntaxTreeBuilderConstants.java | 294 + .../ast/SyntaxTreeBuilderTokenManager.java | 2217 + .../ast/SyntaxTreeBuilderTreeConstants.java | 150 + .../serql/ast/SyntaxTreeBuilderVisitor.java | 80 + .../rdf4j/query/parser/serql/ast/Token.java | 138 + .../query/parser/serql/ast/TokenMgrError.java | 154 + .../parser/serql/ast/VisitorException.java | 30 + .../rdf4j/query/parser/serql/ast/serql.jjt | 916 + .../rdf4j/query/parser/serql/grammar.txt | 142 + .../rdf4j/query/parser/serql/package.html | 5 + ...rg.openrdf.query.parser.QueryParserFactory | 1 + core/queryparser/sparql/pom.xml | 50 + .../query/parser/sparql/ASTVisitorBase.java | 17 + .../parser/sparql/AbstractASTVisitor.java | 1028 + .../parser/sparql/BaseDeclProcessor.java | 136 + .../parser/sparql/BlankNodeVarProcessor.java | 132 + .../parser/sparql/ConstructorBuilder.java | 235 + .../parser/sparql/DatasetDeclProcessor.java | 82 + .../query/parser/sparql/GraphPattern.java | 209 + .../parser/sparql/NegatedPropertySet.java | 120 + .../parser/sparql/PrefixDeclProcessor.java | 193 + .../query/parser/sparql/PropertySetElem.java | 50 + .../query/parser/sparql/SPARQLParser.java | 253 + .../parser/sparql/SPARQLParserFactory.java | 36 + .../rdf4j/query/parser/sparql/SPARQLUtil.java | 110 + .../parser/sparql/StringEscapesProcessor.java | 67 + .../query/parser/sparql/TupleExprBuilder.java | 3146 + .../parser/sparql/UpdateExprBuilder.java | 436 + .../sparql/WildcardProjectionProcessor.java | 190 + .../rdf4j/query/parser/sparql/ast/.gitignore | 2 + .../rdf4j/query/parser/sparql/ast/ASTAbs.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTAdd.java | 39 + .../query/parser/sparql/ast/ASTAggregate.java | 38 + .../rdf4j/query/parser/sparql/ast/ASTAnd.java | 28 + .../query/parser/sparql/ast/ASTAskQuery.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTAvg.java | 28 + .../query/parser/sparql/ast/ASTBNodeFunc.java | 28 + .../query/parser/sparql/ast/ASTBaseDecl.java | 44 + .../sparql/ast/ASTBasicGraphPattern.java | 28 + .../query/parser/sparql/ast/ASTBind.java | 28 + .../parser/sparql/ast/ASTBindingSet.java | 28 + .../parser/sparql/ast/ASTBindingValue.java | 28 + .../parser/sparql/ast/ASTBindingsClause.java | 28 + .../query/parser/sparql/ast/ASTBlankNode.java | 43 + .../sparql/ast/ASTBlankNodePropertyList.java | 44 + .../query/parser/sparql/ast/ASTBound.java | 32 + .../query/parser/sparql/ast/ASTCeil.java | 28 + .../query/parser/sparql/ast/ASTClear.java | 41 + .../query/parser/sparql/ast/ASTCoalesce.java | 28 + .../parser/sparql/ast/ASTCollection.java | 44 + .../query/parser/sparql/ast/ASTCompare.java | 46 + .../query/parser/sparql/ast/ASTConcat.java | 28 + .../parser/sparql/ast/ASTConstraint.java | 28 + .../query/parser/sparql/ast/ASTConstruct.java | 33 + .../parser/sparql/ast/ASTConstructQuery.java | 32 + .../query/parser/sparql/ast/ASTContains.java | 28 + .../query/parser/sparql/ast/ASTCopy.java | 38 + .../query/parser/sparql/ast/ASTCount.java | 43 + .../query/parser/sparql/ast/ASTCreate.java | 38 + .../parser/sparql/ast/ASTDatasetClause.java | 44 + .../query/parser/sparql/ast/ASTDatatype.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTDay.java | 28 + .../parser/sparql/ast/ASTDeleteClause.java | 28 + .../parser/sparql/ast/ASTDeleteData.java | 28 + .../parser/sparql/ast/ASTDeleteWhere.java | 28 + .../query/parser/sparql/ast/ASTDescribe.java | 50 + .../parser/sparql/ast/ASTDescribeQuery.java | 32 + .../query/parser/sparql/ast/ASTDrop.java | 39 + .../parser/sparql/ast/ASTEncodeForURI.java | 28 + .../parser/sparql/ast/ASTExistsFunc.java | 29 + .../query/parser/sparql/ast/ASTFalse.java | 28 + .../query/parser/sparql/ast/ASTFloor.java | 28 + .../parser/sparql/ast/ASTFunctionCall.java | 28 + .../sparql/ast/ASTGraphGraphPattern.java | 28 + .../parser/sparql/ast/ASTGraphOrDefault.java | 28 + .../sparql/ast/ASTGraphPatternGroup.java | 28 + .../parser/sparql/ast/ASTGraphRefAll.java | 59 + .../parser/sparql/ast/ASTGroupClause.java | 47 + .../parser/sparql/ast/ASTGroupConcat.java | 28 + .../parser/sparql/ast/ASTGroupCondition.java | 39 + .../parser/sparql/ast/ASTHavingClause.java | 28 + .../query/parser/sparql/ast/ASTHours.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTIRI.java | 43 + .../query/parser/sparql/ast/ASTIRIFunc.java | 46 + .../rdf4j/query/parser/sparql/ast/ASTIf.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTIn.java | 28 + .../query/parser/sparql/ast/ASTInfix.java | 28 + .../parser/sparql/ast/ASTInlineData.java | 28 + .../parser/sparql/ast/ASTInsertClause.java | 28 + .../parser/sparql/ast/ASTInsertData.java | 28 + .../query/parser/sparql/ast/ASTIsBlank.java | 28 + .../query/parser/sparql/ast/ASTIsIRI.java | 28 + .../query/parser/sparql/ast/ASTIsLiteral.java | 28 + .../query/parser/sparql/ast/ASTIsNumeric.java | 28 + .../query/parser/sparql/ast/ASTLang.java | 28 + .../parser/sparql/ast/ASTLangMatches.java | 28 + .../query/parser/sparql/ast/ASTLimit.java | 44 + .../query/parser/sparql/ast/ASTLoad.java | 38 + .../query/parser/sparql/ast/ASTLowerCase.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTMD5.java | 28 + .../query/parser/sparql/ast/ASTMath.java | 46 + .../rdf4j/query/parser/sparql/ast/ASTMax.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTMin.java | 28 + .../sparql/ast/ASTMinusGraphPattern.java | 28 + .../query/parser/sparql/ast/ASTMinutes.java | 28 + .../query/parser/sparql/ast/ASTModify.java | 50 + .../query/parser/sparql/ast/ASTMonth.java | 28 + .../query/parser/sparql/ast/ASTMove.java | 39 + .../rdf4j/query/parser/sparql/ast/ASTNot.java | 28 + .../parser/sparql/ast/ASTNotExistsFunc.java | 28 + .../query/parser/sparql/ast/ASTNotIn.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTNow.java | 28 + .../parser/sparql/ast/ASTNumericLiteral.java | 56 + .../parser/sparql/ast/ASTObjectList.java | 28 + .../query/parser/sparql/ast/ASTOffset.java | 44 + .../query/parser/sparql/ast/ASTOperation.java | 37 + .../sparql/ast/ASTOperationContainer.java | 47 + .../sparql/ast/ASTOptionalGraphPattern.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTOr.java | 28 + .../parser/sparql/ast/ASTOrderClause.java | 28 + .../parser/sparql/ast/ASTOrderCondition.java | 50 + .../parser/sparql/ast/ASTPathAlternative.java | 28 + .../query/parser/sparql/ast/ASTPathElt.java | 52 + .../query/parser/sparql/ast/ASTPathMod.java | 50 + .../sparql/ast/ASTPathNegatedPropertySet.java | 28 + .../sparql/ast/ASTPathOneInPropertySet.java | 38 + .../parser/sparql/ast/ASTPathSequence.java | 34 + .../parser/sparql/ast/ASTPrefixDecl.java | 48 + .../parser/sparql/ast/ASTProjectionElem.java | 48 + .../parser/sparql/ast/ASTPropertyList.java | 43 + .../sparql/ast/ASTPropertyListPath.java | 43 + .../query/parser/sparql/ast/ASTQName.java | 44 + .../parser/sparql/ast/ASTQuadsNotTriples.java | 28 + .../query/parser/sparql/ast/ASTQuery.java | 57 + .../parser/sparql/ast/ASTQueryContainer.java | 50 + .../parser/sparql/ast/ASTRDFLiteral.java | 60 + .../query/parser/sparql/ast/ASTRDFValue.java | 43 + .../query/parser/sparql/ast/ASTRand.java | 28 + .../parser/sparql/ast/ASTRegexExpression.java | 28 + .../query/parser/sparql/ast/ASTReplace.java | 28 + .../query/parser/sparql/ast/ASTRound.java | 28 + .../query/parser/sparql/ast/ASTSHA1.java | 28 + .../query/parser/sparql/ast/ASTSHA224.java | 28 + .../query/parser/sparql/ast/ASTSHA256.java | 28 + .../query/parser/sparql/ast/ASTSHA384.java | 28 + .../query/parser/sparql/ast/ASTSHA512.java | 28 + .../query/parser/sparql/ast/ASTSTRUUID.java | 28 + .../query/parser/sparql/ast/ASTSameTerm.java | 28 + .../query/parser/sparql/ast/ASTSample.java | 28 + .../query/parser/sparql/ast/ASTSeconds.java | 28 + .../query/parser/sparql/ast/ASTSelect.java | 90 + .../parser/sparql/ast/ASTSelectQuery.java | 36 + .../sparql/ast/ASTServiceGraphPattern.java | 187 + .../rdf4j/query/parser/sparql/ast/ASTStr.java | 28 + .../query/parser/sparql/ast/ASTStrAfter.java | 28 + .../query/parser/sparql/ast/ASTStrBefore.java | 28 + .../query/parser/sparql/ast/ASTStrDt.java | 28 + .../query/parser/sparql/ast/ASTStrEnds.java | 28 + .../query/parser/sparql/ast/ASTStrLang.java | 28 + .../query/parser/sparql/ast/ASTStrLen.java | 28 + .../query/parser/sparql/ast/ASTStrStarts.java | 28 + .../query/parser/sparql/ast/ASTString.java | 44 + .../query/parser/sparql/ast/ASTSubstr.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTSum.java | 28 + .../query/parser/sparql/ast/ASTTimezone.java | 28 + .../sparql/ast/ASTTriplesSameSubject.java | 28 + .../sparql/ast/ASTTriplesSameSubjectPath.java | 28 + .../query/parser/sparql/ast/ASTTrue.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTTz.java | 28 + .../query/parser/sparql/ast/ASTUUID.java | 28 + .../sparql/ast/ASTUnionGraphPattern.java | 28 + .../sparql/ast/ASTUnparsedQuadDataBlock.java | 38 + .../query/parser/sparql/ast/ASTUpdate.java | 26 + .../parser/sparql/ast/ASTUpdateContainer.java | 47 + .../parser/sparql/ast/ASTUpdateSequence.java | 53 + .../query/parser/sparql/ast/ASTUpperCase.java | 28 + .../rdf4j/query/parser/sparql/ast/ASTVar.java | 54 + .../parser/sparql/ast/ASTWhereClause.java | 32 + .../query/parser/sparql/ast/ASTYear.java | 28 + .../sparql/ast/JJTSyntaxTreeBuilderState.java | 130 + .../parser/sparql/ast/JavaCharStream.java | 624 + .../rdf4j/query/parser/sparql/ast/Node.java | 76 + .../parser/sparql/ast/ParseException.java | 194 + .../query/parser/sparql/ast/SimpleNode.java | 202 + .../parser/sparql/ast/SyntaxTreeBuilder.java | 8916 +++ .../ast/SyntaxTreeBuilderConstants.java | 593 + .../ast/SyntaxTreeBuilderTokenManager.java | 3538 + .../ast/SyntaxTreeBuilderTreeConstants.java | 304 + .../sparql/ast/SyntaxTreeBuilderVisitor.java | 157 + .../rdf4j/query/parser/sparql/ast/Token.java | 138 + .../parser/sparql/ast/TokenMgrError.java | 154 + .../parser/sparql/ast/VisitorException.java | 29 + .../rdf4j/query/parser/sparql/ast/sparql.jjt | 1872 + .../rdf4j/query/parser/sparql/package.html | 5 + ...rg.openrdf.query.parser.QueryParserFactory | 1 + .../query/parser/sparql/SPARQLParserTest.java | 223 + .../parser/sparql/TupleExprBuilderTest.java | 220 + core/queryrender/pom.xml | 41 + .../queryrender/BaseTupleExprRenderer.java | 343 + .../rdf4j/queryrender/QueryRenderer.java | 42 + .../rdf4j/queryrender/RenderUtils.java | 164 + .../builder/AbstractQueryBuilder.java | 629 + .../rdf4j/queryrender/builder/BasicGroup.java | 250 + .../queryrender/builder/FilterBuilder.java | 134 + .../rdf4j/queryrender/builder/Group.java | 25 + .../queryrender/builder/GroupBuilder.java | 212 + .../queryrender/builder/QueryBuilder.java | 142 + .../builder/QueryBuilderFactory.java | 126 + .../queryrender/builder/SupportsExpr.java | 24 + .../queryrender/builder/SupportsGroups.java | 38 + .../queryrender/builder/UnionBuilder.java | 142 + .../queryrender/builder/ValueExprFactory.java | 114 + .../rdf4j/queryrender/package-info.java | 14 + .../queryrender/serql/SeRQLQueryRenderer.java | 50 + .../serql/SerqlTupleExprRenderer.java | 349 + .../serql/SerqlValueExprRenderer.java | 497 + .../queryrender/sparql/ContextCollector.java | 169 + .../sparql/SPARQLQueryRenderer.java | 205 + .../sparql/SparqlTupleExprRenderer.java | 315 + .../sparql/SparqlValueExprRenderer.java | 506 + core/queryresultio/api/pom.xml | 39 + .../resultio/AbstractQueryResultParser.java | 92 + .../resultio/AbstractQueryResultWriter.java | 52 + .../AbstractTupleQueryResultParser.java | 60 + .../resultio/BasicQueryWriterSettings.java | 49 + .../resultio/BooleanQueryResultFormat.java | 141 + .../resultio/BooleanQueryResultParser.java | 39 + .../BooleanQueryResultParserFactory.java | 27 + .../BooleanQueryResultParserRegistry.java | 47 + .../resultio/BooleanQueryResultWriter.java | 35 + .../BooleanQueryResultWriterFactory.java | 33 + .../BooleanQueryResultWriterRegistry.java | 47 + .../query/resultio/QueryResultFormat.java | 163 + .../rdf4j/query/resultio/QueryResultIO.java | 516 + .../resultio/QueryResultParseException.java | 130 + .../query/resultio/QueryResultParser.java | 100 + .../query/resultio/QueryResultParserBase.java | 17 + .../query/resultio/QueryResultWriter.java | 126 + .../query/resultio/QueryResultWriterBase.java | 17 + .../resultio/TupleQueryResultFormat.java | 158 + .../resultio/TupleQueryResultParser.java | 51 + .../resultio/TupleQueryResultParserBase.java | 17 + .../TupleQueryResultParserFactory.java | 27 + .../TupleQueryResultParserRegistry.java | 47 + .../resultio/TupleQueryResultWriter.java | 23 + .../TupleQueryResultWriterFactory.java | 33 + .../TupleQueryResultWriterRegistry.java | 47 + ...UnsupportedQueryResultFormatException.java | 48 + .../helpers/QueryResultCollector.java | 187 + core/queryresultio/binary/pom.xml | 46 + .../binary/BinaryQueryResultConstants.java | 133 + .../binary/BinaryQueryResultParser.java | 345 + .../BinaryQueryResultParserFactory.java | 35 + .../binary/BinaryQueryResultWriter.java | 387 + .../BinaryQueryResultWriterFactory.java | 36 + .../query/resultio/binary/QueryErrorType.java | 26 + ...ery.resultio.TupleQueryResultParserFactory | 1 + ...ery.resultio.TupleQueryResultWriterFactory | 1 + core/queryresultio/pom.xml | 25 + core/queryresultio/sparqljson/pom.xml | 43 + .../sparqljson/AbstractSPARQLJSONParser.java | 375 + .../sparqljson/AbstractSPARQLJSONWriter.java | 423 + .../sparqljson/SPARQLBooleanJSONParser.java | 70 + .../SPARQLBooleanJSONParserFactory.java | 36 + .../sparqljson/SPARQLBooleanJSONWriter.java | 63 + .../SPARQLBooleanJSONWriterFactory.java | 37 + .../sparqljson/SPARQLJSONParserBase.java | 17 + .../sparqljson/SPARQLResultsJSONParser.java | 81 + .../SPARQLResultsJSONParserFactory.java | 35 + .../sparqljson/SPARQLResultsJSONWriter.java | 45 + .../SPARQLResultsJSONWriterFactory.java | 37 + .../query/resultio/sparqljson/package.html | 5 + ...y.resultio.BooleanQueryResultParserFactory | 1 + ...y.resultio.BooleanQueryResultWriterFactory | 1 + ...ery.resultio.TupleQueryResultParserFactory | 1 + ...ery.resultio.TupleQueryResultWriterFactory | 1 + core/queryresultio/sparqlxml/pom.xml | 51 + .../sparqlxml/AbstractSPARQLXMLParser.java | 150 + .../sparqlxml/AbstractSPARQLXMLWriter.java | 520 + .../sparqlxml/SPARQLBooleanSAXParser.java | 60 + .../sparqlxml/SPARQLBooleanXMLParser.java | 67 + .../SPARQLBooleanXMLParserFactory.java | 35 + .../sparqlxml/SPARQLBooleanXMLWriter.java | 68 + .../SPARQLBooleanXMLWriterFactory.java | 37 + .../sparqlxml/SPARQLResultsSAXParser.java | 195 + .../sparqlxml/SPARQLResultsXMLConstants.java | 60 + .../sparqlxml/SPARQLResultsXMLParser.java | 86 + .../SPARQLResultsXMLParserFactory.java | 35 + .../sparqlxml/SPARQLResultsXMLWriter.java | 49 + .../SPARQLResultsXMLWriterFactory.java | 37 + .../sparqlxml/SPARQLXMLParserBase.java | 17 + .../query/resultio/sparqlxml/package.html | 5 + ...y.resultio.BooleanQueryResultParserFactory | 1 + ...y.resultio.BooleanQueryResultWriterFactory | 1 + ...ery.resultio.TupleQueryResultParserFactory | 1 + ...ery.resultio.TupleQueryResultWriterFactory | 1 + .../sparqlxml/SPARQLResultsXMLParserTest.java | 73 + .../src/test/resources/localname-result.srx | 28 + .../src/test/resources/logback-test.xml | 15 + .../src/test/resources/namespace-result.srx | 28 + core/queryresultio/text/pom.xml | 52 + .../resultio/text/BooleanTextParser.java | 98 + .../text/BooleanTextParserFactory.java | 35 + .../resultio/text/BooleanTextWriter.java | 155 + .../text/BooleanTextWriterFactory.java | 37 + .../text/csv/SPARQLResultsCSVParser.java | 126 + .../csv/SPARQLResultsCSVParserFactory.java | 35 + .../text/csv/SPARQLResultsCSVWriter.java | 272 + .../csv/SPARQLResultsCSVWriterFactory.java | 37 + .../text/tsv/SPARQLResultsTSVParser.java | 297 + .../tsv/SPARQLResultsTSVParserFactory.java | 35 + .../text/tsv/SPARQLResultsTSVWriter.java | 266 + .../tsv/SPARQLResultsTSVWriterFactory.java | 37 + ...y.resultio.BooleanQueryResultParserFactory | 1 + ...y.resultio.BooleanQueryResultWriterFactory | 1 + ...ery.resultio.TupleQueryResultParserFactory | 2 + ...ery.resultio.TupleQueryResultWriterFactory | 2 + core/repository/api/pom.xml | 50 + .../repository/DelegatingRepository.java | 18 + .../DelegatingRepositoryConnection.java | 16 + .../eclipse/rdf4j/repository/Repository.java | 118 + .../repository/RepositoryConnection.java | 1346 + .../rdf4j/repository/RepositoryException.java | 36 + .../repository/RepositoryLockedException.java | 52 + .../RepositoryReadOnlyException.java | 35 + .../rdf4j/repository/RepositoryResult.java | 147 + .../UnknownTransactionStateException.java | 36 + .../repository/base/AbstractRepository.java | 57 + .../base/AbstractRepositoryConnection.java | 608 + .../rdf4j/repository/base/RepositoryBase.java | 19 + .../base/RepositoryConnectionBase.java | 23 + .../base/RepositoryConnectionWrapper.java | 572 + .../repository/base/RepositoryWrapper.java | 94 + ...bstractDelegatingRepositoryImplConfig.java | 90 + .../config/AbstractRepositoryImplConfig.java | 115 + .../repository/config/ConfigTemplate.java | 136 + .../DelegatingRepositoryImplConfig.java | 17 + .../DelegatingRepositoryImplConfigBase.java | 18 + .../repository/config/RepositoryConfig.java | 175 + .../config/RepositoryConfigException.java | 36 + .../config/RepositoryConfigSchema.java | 52 + .../config/RepositoryConfigUtil.java | 264 + .../repository/config/RepositoryFactory.java | 44 + .../config/RepositoryImplConfig.java | 60 + .../config/RepositoryImplConfigBase.java | 33 + .../repository/config/RepositoryRegistry.java | 44 + .../org/eclipse/rdf4j/repository/package.html | 13 + .../repository/util/AbstractRDFInserter.java | 216 + .../rdf4j/repository/util/RDFInserter.java | 70 + .../rdf4j/repository/util/RDFLoader.java | 325 + .../rdf4j/repository/util/RDFRemover.java | 121 + .../rdf4j/repository/util/Repositories.java | 358 + .../rdf4j/repository/util/RepositoryUtil.java | 280 + .../repository/config/memory-customrule.ttl | 36 + .../repository/config/memory-rdfs-dt.ttl | 28 + .../openrdf/repository/config/memory-rdfs.ttl | 25 + .../org/openrdf/repository/config/memory.ttl | 21 + .../repository/config/native-customrule.ttl | 35 + .../repository/config/native-rdfs-dt.ttl | 27 + .../openrdf/repository/config/native-rdfs.ttl | 24 + .../org/openrdf/repository/config/native.ttl | 20 + .../org/openrdf/repository/config/remote.ttl | 14 + .../org/openrdf/repository/config/sparql.ttl | 15 + .../repository/config/TestConfigTemplate.java | 51 + core/repository/contextaware/pom.xml | 49 + .../contextaware/ContextAwareConnection.java | 924 + .../contextaware/ContextAwareRepository.java | 194 + .../config/ContextAwareConfig.java | 267 + .../config/ContextAwareFactory.java | 73 + .../config/ContextAwareSchema.java | 66 + .../repository/contextaware/package.html | 5 + ...penrdf.repository.config.RepositoryFactory | 1 + .../ContextAwareConnectionTest.java | 272 + core/repository/dataset/pom.xml | 44 + .../dataset/DatasetBooleanQuery.java | 30 + .../repository/dataset/DatasetGraphQuery.java | 39 + .../repository/dataset/DatasetQuery.java | 86 + .../repository/dataset/DatasetRepository.java | 140 + .../dataset/DatasetRepositoryConnection.java | 116 + .../repository/dataset/DatasetTupleQuery.java | 39 + .../config/DatasetRepositoryConfig.java | 20 + .../config/DatasetRepositoryFactory.java | 51 + .../rdf4j/repository/dataset/package.html | 5 + ...penrdf.repository.config.RepositoryFactory | 1 + core/repository/event/pom.xml | 34 + .../event/InterceptingRepository.java | 41 + .../InterceptingRepositoryConnection.java | 30 + .../repository/event/NotifyingRepository.java | 73 + .../event/NotifyingRepositoryConnection.java | 30 + .../RepositoryConnectionInterceptor.java | 125 + .../event/RepositoryConnectionListener.java | 57 + .../event/RepositoryInterceptor.java | 32 + .../repository/event/RepositoryListener.java | 29 + ...terceptingRepositoryConnectionWrapper.java | 368 + .../base/InterceptingRepositoryWrapper.java | 175 + .../NotifyingRepositoryConnectionWrapper.java | 387 + .../base/NotifyingRepositoryWrapper.java | 166 + ...epositoryConnectionInterceptorAdapter.java | 79 + .../RepositoryConnectionListenerAdapter.java | 65 + .../rdf4j/repository/event/package.html | 5 + .../DebugRepositoryConnectionListener.java | 197 + .../repository/event/InterceptorTest.java | 177 + .../rdf4j/repository/event/NotifyingTest.java | 167 + core/repository/http/pom.xml | 70 + .../repository/http/HTTPBooleanQuery.java | 59 + .../rdf4j/repository/http/HTTPGraphQuery.java | 106 + .../http/HTTPQueryEvaluationException.java | 69 + .../rdf4j/repository/http/HTTPRepository.java | 343 + .../http/HTTPRepositoryConnection.java | 936 + .../rdf4j/repository/http/HTTPTupleQuery.java | 81 + .../rdf4j/repository/http/HTTPUpdate.java | 96 + .../http/HTTPUpdateExecutionException.java | 69 + .../http/config/HTTPRepositoryConfig.java | 121 + .../http/config/HTTPRepositoryFactory.java | 57 + .../http/config/HTTPRepositorySchema.java | 41 + .../rdf4j/repository/http/package.html | 12 + ...penrdf.repository.config.RepositoryFactory | 1 + core/repository/manager/pom.xml | 86 + .../manager/LocalRepositoryManager.java | 497 + .../manager/RemoteRepositoryManager.java | 327 + .../repository/manager/RepositoryInfo.java | 77 + .../repository/manager/RepositoryManager.java | 648 + .../manager/RepositoryProvider.java | 257 + .../repository/manager/SystemRepository.java | 101 + .../manager/SystemRepositoryConfig.java | 20 + .../rdf4j/repository/manager/package.html | 5 + .../util/NotifyingLocalRepositoryManager.java | 81 + .../util/RepositoryManagerListener.java | 19 + .../util/TypeFilteringRepositoryManager.java | 314 + .../manager/LocalRepositoryManagerTest.java | 196 + core/repository/pom.xml | 28 + core/repository/sail/pom.xml | 88 + .../repository/sail/ProxyRepository.java | 160 + .../repository/sail/SailBooleanQuery.java | 64 + .../sail/SailCloseableIteration.java | 40 + .../rdf4j/repository/sail/SailGraphQuery.java | 106 + .../rdf4j/repository/sail/SailQuery.java | 90 + .../rdf4j/repository/sail/SailRepository.java | 229 + .../sail/SailRepositoryConnection.java | 508 + .../rdf4j/repository/sail/SailTupleQuery.java | 68 + .../rdf4j/repository/sail/SailUpdate.java | 161 + .../sail/config/ProxyRepositoryConfig.java | 77 + .../sail/config/ProxyRepositoryFactory.java | 49 + .../sail/config/ProxyRepositorySchema.java | 36 + .../sail/config/RepositoryResolver.java | 23 + .../sail/config/RepositoryResolverClient.java | 19 + .../sail/config/SailRepositoryConfig.java | 105 + .../sail/config/SailRepositoryFactory.java | 111 + .../sail/config/SailRepositorySchema.java | 33 + .../sail/helpers/RDFSailInserter.java | 243 + .../sail/helpers/RDFSailRemover.java | 141 + .../helpers/SPARQLUpdateDataBlockParser.java | 130 + .../sail/helpers/SailUpdateExecutor.java | 738 + .../rdf4j/repository/sail/package.html | 5 + ...penrdf.repository.config.RepositoryFactory | 2 + .../repository/sail/TestProxyRepository.java | 119 + .../config/TestProxyRepositoryFactory.java | 76 + .../TestSPARQLUpdateDataBlockParser.java | 41 + .../sail/src/test/resources/proxy.ttl | 12 + core/repository/sparql/pom.xml | 47 + .../repository/sparql/SPARQLConnection.java | 990 + .../repository/sparql/SPARQLRepository.java | 237 + .../sparql/config/SPARQLRepositoryConfig.java | 109 + .../config/SPARQLRepositoryFactory.java | 51 + .../rdf4j/repository/sparql/package.html | 17 + .../sparql/query/InsertBindingSetCursor.java | 48 + .../sparql/query/QueryStringUtil.java | 101 + .../repository/sparql/query/QueueCursor.java | 29 + .../sparql/query/SPARQLBooleanQuery.java | 55 + .../sparql/query/SPARQLGraphQuery.java | 79 + .../sparql/query/SPARQLOperation.java | 169 + .../sparql/query/SPARQLQueryBindingSet.java | 210 + .../sparql/query/SPARQLTupleQuery.java | 80 + .../repository/sparql/query/SPARQLUpdate.java | 69 + ...penrdf.repository.config.RepositoryFactory | 1 + core/rio/api/pom.xml | 33 + .../eclipse/rdf4j/rio/DatatypeHandler.java | 140 + .../rdf4j/rio/DatatypeHandlerRegistry.java | 45 + .../eclipse/rdf4j/rio/LanguageHandler.java | 114 + .../rdf4j/rio/LanguageHandlerRegistry.java | 45 + .../eclipse/rdf4j/rio/ParseErrorListener.java | 70 + .../rdf4j/rio/ParseLocationListener.java | 27 + .../org/eclipse/rdf4j/rio/ParserConfig.java | 226 + .../java/org/eclipse/rdf4j/rio/RDFFormat.java | 501 + .../org/eclipse/rdf4j/rio/RDFHandler.java | 80 + .../rdf4j/rio/RDFHandlerException.java | 50 + .../eclipse/rdf4j/rio/RDFParseException.java | 169 + .../java/org/eclipse/rdf4j/rio/RDFParser.java | 232 + .../eclipse/rdf4j/rio/RDFParserFactory.java | 26 + .../eclipse/rdf4j/rio/RDFParserRegistry.java | 44 + .../java/org/eclipse/rdf4j/rio/RDFWriter.java | 65 + .../eclipse/rdf4j/rio/RDFWriterFactory.java | 45 + .../eclipse/rdf4j/rio/RDFWriterRegistry.java | 44 + .../main/java/org/eclipse/rdf4j/rio/Rio.java | 639 + .../java/org/eclipse/rdf4j/rio/RioConfig.java | 124 + .../org/eclipse/rdf4j/rio/RioSetting.java | 41 + .../rio/UnsupportedRDFormatException.java | 52 + .../org/eclipse/rdf4j/rio/WriterConfig.java | 44 + .../rdf4j/rio/helpers/AbstractRDFHandler.java | 46 + .../rdf4j/rio/helpers/AbstractRDFParser.java | 727 + .../rdf4j/rio/helpers/AbstractRDFWriter.java | 74 + .../rio/helpers/BasicParserSettings.java | 330 + .../rio/helpers/BasicWriterSettings.java | 73 + .../helpers/BufferedGroupingRDFHandler.java | 138 + .../rdf4j/rio/helpers/CodePointIterator.java | 47 + .../rdf4j/rio/helpers/CodePointSequence.java | 36 + .../helpers/ContextStatementCollector.java | 132 + .../eclipse/rdf4j/rio/helpers/JSONLDMode.java | 50 + .../rdf4j/rio/helpers/JSONLDSettings.java | 104 + .../rio/helpers/LargeLiteralHandling.java | 38 + .../rio/helpers/NTriplesParserSettings.java | 37 + .../rio/helpers/NTriplesWriterSettings.java | 36 + .../rio/helpers/ParseErrorCollector.java | 81 + .../rdf4j/rio/helpers/ParseErrorLogger.java | 39 + .../rdf4j/rio/helpers/RDFHandlerBase.java | 17 + .../rdf4j/rio/helpers/RDFHandlerWrapper.java | 96 + .../rio/helpers/RDFJSONParserSettings.java | 96 + .../rdf4j/rio/helpers/RDFParserBase.java | 28 + .../rdf4j/rio/helpers/RDFParserHelper.java | 499 + .../rdf4j/rio/helpers/RDFWriterBase.java | 20 + .../rdf4j/rio/helpers/RDFaParserSettings.java | 65 + .../rdf4j/rio/helpers/RDFaVersion.java | 58 + .../rio/helpers/RioFileTypeDetector.java | 46 + .../rdf4j/rio/helpers/RioSettingImpl.java | 82 + .../rdf4j/rio/helpers/StatementCollector.java | 52 + .../rdf4j/rio/helpers/TriXParserSettings.java | 48 + .../rio/helpers/TurtleParserSettings.java | 30 + .../rdf4j/rio/helpers/XMLParserSettings.java | 153 + .../rdf4j/rio/helpers/XMLWriterSettings.java | 56 + .../eclipse/rdf4j/rio/helpers/package.html | 6 + .../java/org/eclipse/rdf4j/rio/package.html | 6 + .../java.nio.file.spi.FileTypeDetector | 1 + .../rio/helpers/StatementCollectorTest.java | 211 + core/rio/binary/pom.xml | 34 + .../rdf4j/rio/binary/BinaryRDFConstants.java | 52 + .../rdf4j/rio/binary/BinaryRDFParser.java | 282 + .../rio/binary/BinaryRDFParserFactory.java | 34 + .../rdf4j/rio/binary/BinaryRDFWriter.java | 334 + .../rio/binary/BinaryRDFWriterFactory.java | 44 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + core/rio/datatypes/pom.xml | 34 + .../rio/datatypes/DBPediaDatatypeHandler.java | 74 + .../datatypes/GeoSPARQLDatatypeHandler.java | 75 + .../rio/datatypes/RDFDatatypeHandler.java | 84 + .../VirtuosoGeometryDatatypeHandler.java | 116 + .../datatypes/XMLSchemaDatatypeHandler.java | 84 + .../services/org.openrdf.rio.DatatypeHandler | 5 + core/rio/jsonld/pom.xml | 64 + .../rio/jsonld/JSONLDInternalRDFParser.java | 111 + .../jsonld/JSONLDInternalTripleCallback.java | 239 + .../rdf4j/rio/jsonld/JSONLDParser.java | 112 + .../rdf4j/rio/jsonld/JSONLDParserFactory.java | 31 + .../rdf4j/rio/jsonld/JSONLDWriter.java | 168 + .../rdf4j/rio/jsonld/JSONLDWriterFactory.java | 39 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + .../JSONLDInternalTripleCallbackTest.java | 67 + .../src/test/resources/log4j.properties | 5 + core/rio/languages/pom.xml | 34 + .../rio/languages/RFC3066LanguageHandler.java | 89 + .../services/org.openrdf.rio.LanguageHandler | 1 + core/rio/n3/pom.xml | 46 + .../eclipse/rdf4j/rio/n3/N3ParserFactory.java | 35 + .../org/eclipse/rdf4j/rio/n3/N3Writer.java | 94 + .../eclipse/rdf4j/rio/n3/N3WriterFactory.java | 44 + .../org/eclipse/rdf4j/rio/n3/package.html | 8 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + core/rio/nquads/pom.xml | 50 + .../rdf4j/rio/nquads/NQuadsParser.java | 197 + .../rdf4j/rio/nquads/NQuadsParserFactory.java | 35 + .../rdf4j/rio/nquads/NQuadsWriter.java | 77 + .../rdf4j/rio/nquads/NQuadsWriterFactory.java | 45 + .../org/eclipse/rdf4j/rio/nquads/package.html | 7 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + core/rio/ntriples/pom.xml | 45 + .../rdf4j/rio/ntriples/NTriplesParser.java | 757 + .../rio/ntriples/NTriplesParserFactory.java | 34 + .../rdf4j/rio/ntriples/NTriplesUtil.java | 708 + .../rdf4j/rio/ntriples/NTriplesWriter.java | 160 + .../rio/ntriples/NTriplesWriterFactory.java | 44 + .../eclipse/rdf4j/rio/ntriples/package.html | 8 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + core/rio/pom.xml | 33 + core/rio/rdfjson/pom.xml | 54 + .../rdf4j/rio/rdfjson/RDFJSONParser.java | 391 + .../rio/rdfjson/RDFJSONParserFactory.java | 32 + .../rdf4j/rio/rdfjson/RDFJSONUtility.java | 51 + .../rdf4j/rio/rdfjson/RDFJSONWriter.java | 247 + .../rio/rdfjson/RDFJSONWriterFactory.java | 39 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + core/rio/rdfxml/pom.xml | 61 + .../org/eclipse/rdf4j/rio/rdfxml/Att.java | 61 + .../org/eclipse/rdf4j/rio/rdfxml/Atts.java | 180 + .../rdf4j/rio/rdfxml/RDFXMLParser.java | 1438 + .../rdf4j/rio/rdfxml/RDFXMLParserFactory.java | 34 + .../rdf4j/rio/rdfxml/RDFXMLWriter.java | 522 + .../rdf4j/rio/rdfxml/RDFXMLWriterFactory.java | 44 + .../eclipse/rdf4j/rio/rdfxml/SAXFilter.java | 724 + .../org/eclipse/rdf4j/rio/rdfxml/package.html | 8 + .../rio/rdfxml/util/RDFXMLPrettyWriter.java | 583 + .../util/RDFXMLPrettyWriterFactory.java | 44 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + .../rdf4j/rio/rdfxml/RDFXMLParserTest.java | 82 + .../rio/rdfxml/sample-with-rdfxml-data.zip | Bin 0 -> 550 bytes core/rio/trig/pom.xml | 51 + .../eclipse/rdf4j/rio/trig/TriG grammar.txt | 59 + .../eclipse/rdf4j/rio/trig/TriGParser.java | 276 + .../rdf4j/rio/trig/TriGParserFactory.java | 34 + .../eclipse/rdf4j/rio/trig/TriGWriter.java | 171 + .../rdf4j/rio/trig/TriGWriterFactory.java | 44 + .../org/eclipse/rdf4j/rio/trig/package.html | 6 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + core/rio/trix/pom.xml | 50 + .../eclipse/rdf4j/rio/trix/TriXConstants.java | 44 + .../eclipse/rdf4j/rio/trix/TriXParser.java | 291 + .../rdf4j/rio/trix/TriXParserFactory.java | 34 + .../eclipse/rdf4j/rio/trix/TriXWriter.java | 244 + .../rdf4j/rio/trix/TriXWriterFactory.java | 44 + .../org/eclipse/rdf4j/rio/trix/package.html | 7 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + core/rio/turtle/pom.xml | 61 + .../rdf4j/rio/turtle/Turtle grammar.txt | 52 + .../rdf4j/rio/turtle/TurtleParser.java | 1417 + .../rdf4j/rio/turtle/TurtleParserFactory.java | 35 + .../eclipse/rdf4j/rio/turtle/TurtleUtil.java | 615 + .../rdf4j/rio/turtle/TurtleWriter.java | 452 + .../rdf4j/rio/turtle/TurtleWriterFactory.java | 44 + .../org/eclipse/rdf4j/rio/turtle/package.html | 6 + .../services/org.openrdf.rio.RDFParserFactory | 1 + .../services/org.openrdf.rio.RDFWriterFactory | 1 + .../rdf4j/rio/turtle/TestTurtleParser.java | 331 + .../rdf4j/rio/turtle/TurtleUtilTest.java | 273 + .../rio/turtle/sample-with-turtle-data.zip | Bin 0 -> 434 bytes .../src/test/resources/test-newlines.ttl | 11 + core/runtime-osgi/build.xml | 43 + core/runtime-osgi/pom.xml | 98 + .../src/main/resources/LICENSE.txt | 25 + .../src/main/resources/NOTICE.txt | 50 + core/runtime/pom.xml | 260 + .../runtime/RepositoryManagerFederator.java | 205 + .../TestRepositoryManagerFederator.java | 64 + core/sail/api/pom.xml | 44 + .../locks/AbstractReadWriteLockManager.java | 122 + .../locks/ExclusiveLockManager.java | 86 + .../rdf4j/common/concurrent/locks/Lock.java | 25 + .../common/concurrent/locks/LockManager.java | 289 + .../concurrent/locks/LockingIteration.java | 107 + .../common/concurrent/locks/Properties.java | 47 + .../locks/ReadPrefReadWriteLockManager.java | 118 + .../locks/ReadWriteLockManager.java | 53 + .../locks/WritePrefReadWriteLockManager.java | 133 + .../common/concurrent/locks/package.html | 8 + .../org/eclipse/rdf4j/sail/LockManager.java | 54 + .../org/eclipse/rdf4j/sail/NotifyingSail.java | 42 + .../rdf4j/sail/NotifyingSailConnection.java | 40 + .../java/org/eclipse/rdf4j/sail/Sail.java | 124 + .../eclipse/rdf4j/sail/SailChangedEvent.java | 37 + .../rdf4j/sail/SailChangedListener.java | 20 + .../rdf4j/sail/SailConflictException.java | 37 + .../eclipse/rdf4j/sail/SailConnection.java | 539 + .../rdf4j/sail/SailConnectionListener.java | 29 + .../org/eclipse/rdf4j/sail/SailException.java | 35 + .../rdf4j/sail/SailLockedException.java | 72 + .../rdf4j/sail/SailReadOnlyException.java | 23 + .../org/eclipse/rdf4j/sail/StackableSail.java | 25 + .../UnknownSailTransactionStateException.java | 24 + .../org/eclipse/rdf4j/sail/UpdateContext.java | 81 + .../AbstractDelegatingSailImplConfig.java | 96 + .../sail/config/AbstractSailImplConfig.java | 109 + .../sail/config/DelegatingSailImplConfig.java | 17 + .../config/DelegatingSailImplConfigBase.java | 17 + .../sail/config/SailConfigException.java | 36 + .../rdf4j/sail/config/SailConfigSchema.java | 43 + .../rdf4j/sail/config/SailConfigUtil.java | 46 + .../rdf4j/sail/config/SailFactory.java | 45 + .../rdf4j/sail/config/SailImplConfig.java | 39 + .../rdf4j/sail/config/SailImplConfigBase.java | 17 + .../rdf4j/sail/config/SailRegistry.java | 44 + .../sail/helpers/AbstractNotifyingSail.java | 79 + .../rdf4j/sail/helpers/AbstractSail.java | 425 + .../sail/helpers/AbstractSailConnection.java | 1051 + .../sail/helpers/DefaultSailChangedEvent.java | 70 + .../sail/helpers/DirectoryLockManager.java | 283 + .../rdf4j/sail/helpers/NotifyingSailBase.java | 17 + .../helpers/NotifyingSailConnectionBase.java | 82 + .../NotifyingSailConnectionWrapper.java | 62 + .../sail/helpers/NotifyingSailWrapper.java | 74 + .../eclipse/rdf4j/sail/helpers/SailBase.java | 17 + .../rdf4j/sail/helpers/SailBaseIteration.java | 67 + .../sail/helpers/SailConnectionBase.java | 21 + .../sail/helpers/SailConnectionWrapper.java | 266 + .../eclipse/rdf4j/sail/helpers/SailUtil.java | 58 + .../rdf4j/sail/helpers/SailWrapper.java | 143 + .../eclipse/rdf4j/sail/helpers/package.html | 5 + .../java/org/eclipse/rdf4j/sail/package.html | 9 + core/sail/base/pom.xml | 59 + .../rdf4j/sail/base/BackingSailSource.java | 46 + .../eclipse/rdf4j/sail/base/Changeset.java | 359 + .../sail/base/DelegatingSailDataset.java | 71 + .../rdf4j/sail/base/DelegatingSailSource.java | 80 + .../rdf4j/sail/base/ObservingSailDataset.java | 76 + .../eclipse/rdf4j/sail/base/SailClosable.java | 27 + .../rdf4j/sail/base/SailClosingIteration.java | 143 + .../eclipse/rdf4j/sail/base/SailDataset.java | 101 + .../rdf4j/sail/base/SailDatasetImpl.java | 300 + .../sail/base/SailDatasetTripleSource.java | 67 + .../org/eclipse/rdf4j/sail/base/SailSink.java | 160 + .../eclipse/rdf4j/sail/base/SailSource.java | 89 + .../rdf4j/sail/base/SailSourceBranch.java | 548 + .../rdf4j/sail/base/SailSourceConnection.java | 753 + .../eclipse/rdf4j/sail/base/SailStore.java | 46 + .../rdf4j/sail/base/SnapshotSailStore.java | 94 + .../rdf4j/sail/base/UnionSailDataset.java | 112 + .../rdf4j/sail/base/UnionSailSource.java | 88 + core/sail/federation/pom.xml | 65 + .../AbstractEchoWriteConnection.java | 127 + .../AbstractFederationConnection.java | 551 + .../rdf4j/sail/federation/Federation.java | 295 + .../rdf4j/sail/federation/PrefixHashSet.java | 68 + .../sail/federation/ReadOnlyConnection.java | 93 + .../sail/federation/WritableConnection.java | 76 + .../algebra/AbstractNaryOperator.java | 168 + .../algebra/AbstractNaryTupleOperator.java | 74 + .../sail/federation/algebra/NaryJoin.java | 58 + .../federation/algebra/OwnedTupleExpr.java | 98 + .../federation/config/FederationConfig.java | 174 + .../federation/config/FederationFactory.java | 70 + .../evaluation/AlternativeCursor.java | 56 + .../evaluation/FederationStrategy.java | 143 + .../federation/evaluation/FilterCursor.java | 42 + .../evaluation/InsertBindingSetCursor.java | 53 + .../evaluation/ParallelJoinCursor.java | 131 + .../evaluation/ParallelLeftJoinCursor.java | 161 + .../federation/evaluation/QueueCursor.java | 186 + .../evaluation/RepositoryTripleSource.java | 60 + .../optimizers/EmptyPatternOptimizer.java | 72 + .../optimizers/EvaluationStatistics.java | 148 + .../optimizers/FederationJoinOptimizer.java | 759 + .../optimizers/OwnedTupleExprPruner.java | 56 + .../optimizers/PrepareOwnedTupleExpr.java | 473 + .../optimizers/QueryModelPruner.java | 168 + .../optimizers/QueryMultiJoinOptimizer.java | 289 + .../org.openrdf.sail.config.SailFactory | 1 + core/sail/federation/src/site/apt/index.apt | 107 + .../src/site/resources/css/site.css | 331 + .../federation/FederationNamespacesTest.java | 133 + .../sail/federation/FederationQueryTest.java | 199 + .../sail/federation/SPARQLBuilderTest.java | 92 + .../testcases/federation-member-1.ttl | 16 + .../testcases/federation-member-2.ttl | 29 + .../testcases/federation-member-3.ttl | 19 + core/sail/fts/elasticsearch/pom.xml | 57 + .../ElasticsearchBulkUpdater.java | 67 + .../elasticsearch/ElasticsearchDocument.java | 207 + .../ElasticsearchDocumentDistance.java | 68 + .../ElasticsearchDocumentResult.java | 37 + .../ElasticsearchDocumentScore.java | 52 + .../elasticsearch/ElasticsearchIndex.java | 847 + .../elasticsearch/ElasticsearchQuery.java | 73 + .../ElasticsearchSpatialSupport.java | 61 + .../config/ElasticsearchSailConfig.java | 34 + .../config/ElasticsearchSailFactory.java | 62 + .../org.openrdf.sail.config.SailFactory | 1 + .../elasticsearch/ElasticsearchIndexTest.java | 484 + .../ElasticsearchSailGeoSPARQLTest.java | 61 + ...lasticsearchSailIndexedPropertiesTest.java | 35 + .../elasticsearch/ElasticsearchSailTest.java | 38 + .../examples/ElasticsearchSailExample.java | 160 + .../src/test/resources/elasticsearch.yml | 7 + core/sail/fts/lucene-api/pom.xml | 57 + .../sail/lucene/AbstractLuceneIndex.java | 41 + .../sail/lucene/AbstractReaderMonitor.java | 97 + .../sail/lucene/AbstractSearchIndex.java | 892 + .../sail/lucene/BindingSetCollection.java | 105 + .../rdf4j/sail/lucene/BulkUpdater.java | 17 + .../rdf4j/sail/lucene/DistanceQuerySpec.java | 131 + .../sail/lucene/DistanceQuerySpecBuilder.java | 185 + .../rdf4j/sail/lucene/DocumentDistance.java | 13 + .../rdf4j/sail/lucene/DocumentResult.java | 19 + .../rdf4j/sail/lucene/DocumentScore.java | 15 + .../sail/lucene/GeoRelationQuerySpec.java | 122 + .../lucene/GeoRelationQuerySpecBuilder.java | 151 + .../sail/lucene/IndexableStatementFilter.java | 23 + .../eclipse/rdf4j/sail/lucene/LuceneSail.java | 782 + .../rdf4j/sail/lucene/LuceneSailBuffer.java | 229 + .../sail/lucene/LuceneSailConnection.java | 526 + .../rdf4j/sail/lucene/LuceneSailSchema.java | 44 + .../rdf4j/sail/lucene/PropertyCache.java | 65 + .../eclipse/rdf4j/sail/lucene/QuerySpec.java | 233 + .../rdf4j/sail/lucene/QuerySpecBuilder.java | 285 + .../rdf4j/sail/lucene/SearchDocument.java | 36 + .../rdf4j/sail/lucene/SearchFields.java | 189 + .../rdf4j/sail/lucene/SearchIndex.java | 140 + .../rdf4j/sail/lucene/SearchQuery.java | 28 + .../sail/lucene/SearchQueryEvaluator.java | 15 + .../sail/lucene/SearchQueryInterpreter.java | 24 + .../rdf4j/sail/lucene/SimpleBulkUpdater.java | 41 + .../config/AbstractLuceneSailConfig.java | 88 + .../lucene/config/LuceneSailConfigSchema.java | 33 + .../rdf4j/sail/lucene/util/GeoUnits.java | 113 + .../util/IteratorCloseableIteration.java | 26 + .../rdf4j/sail/lucene/util/MapOfListMaps.java | 73 + .../sail/lucene/QuerySpecBuilderTest.java | 224 + core/sail/fts/lucene/pom.xml | 81 + .../rdf4j/sail/lucene/LuceneDocument.java | 157 + .../sail/lucene/LuceneDocumentDistance.java | 65 + .../sail/lucene/LuceneDocumentResult.java | 42 + .../sail/lucene/LuceneDocumentScore.java | 59 + .../rdf4j/sail/lucene/LuceneIndex.java | 1107 + .../rdf4j/sail/lucene/LuceneIndexNIOFS.java | 42 + .../rdf4j/sail/lucene/LuceneQuery.java | 67 + .../rdf4j/sail/lucene/ReaderMonitor.java | 80 + .../sail/lucene/config/LuceneSailConfig.java | 34 + .../sail/lucene/config/LuceneSailFactory.java | 62 + .../org.openrdf.sail.config.SailFactory | 1 + .../rdf4j/sail/lucene/LuceneIndexTest.java | 498 + .../sail/lucene/LuceneSailGeoSPARQLTest.java | 54 + .../LuceneSailIndexedPropertiesTest.java | 20 + .../rdf4j/sail/lucene/LuceneSailTest.java | 124 + .../lucene/examples/LuceneSailExample.java | 165 + core/sail/fts/lucene4/pom.xml | 76 + .../rdf4j/sail/lucene4/LuceneDocument.java | 160 + .../sail/lucene4/LuceneDocumentDistance.java | 65 + .../sail/lucene4/LuceneDocumentResult.java | 42 + .../sail/lucene4/LuceneDocumentScore.java | 59 + .../rdf4j/sail/lucene4/LuceneIndex.java | 1115 + .../rdf4j/sail/lucene4/LuceneIndexNIOFS.java | 39 + .../rdf4j/sail/lucene4/LuceneQuery.java | 67 + .../rdf4j/sail/lucene4/ReaderMonitor.java | 80 + .../sail/lucene4/config/LuceneSailConfig.java | 34 + .../lucene4/config/LuceneSailFactory.java | 62 + .../org.openrdf.sail.config.SailFactory | 1 + .../rdf4j/sail/lucene4/LuceneIndexTest.java | 507 + .../sail/lucene4/LuceneSailGeoSPARQLTest.java | 54 + .../LuceneSailIndexedPropertiesTest.java | 20 + .../rdf4j/sail/lucene4/LuceneSailTest.java | 125 + .../lucene4/examples/LuceneSailExample.java | 163 + core/sail/fts/lucenesail/pom.xml | 70 + .../tier/FixedCartesianPolyFilterBuilder.java | 183 + .../projections/FixedSinusoidalProjector.java | 29 + .../rdf4j/sail/lucene3/LuceneDocument.java | 171 + .../sail/lucene3/LuceneDocumentDistance.java | 48 + .../sail/lucene3/LuceneDocumentResult.java | 42 + .../sail/lucene3/LuceneDocumentScore.java | 59 + .../rdf4j/sail/lucene3/LuceneIndex.java | 1052 + .../rdf4j/sail/lucene3/LuceneIndexNIOFS.java | 39 + .../rdf4j/sail/lucene3/LuceneQuery.java | 67 + .../rdf4j/sail/lucene3/ReaderMonitor.java | 79 + .../rdf4j/sail/lucene3/SpatialStrategy.java | 74 + .../sail/lucene3/config/LuceneSailConfig.java | 34 + .../lucene3/config/LuceneSailFactory.java | 62 + .../org.openrdf.sail.config.SailFactory | 1 + .../rdf4j/sail/lucene3/LuceneIndexTest.java | 483 + .../sail/lucene3/LuceneSailGeoSPARQLTest.java | 28 + .../LuceneSailIndexedPropertiesTest.java | 20 + .../rdf4j/sail/lucene3/LuceneSailTest.java | 124 + .../lucene3/examples/LuceneSailExample.java | 163 + core/sail/fts/pom.xml | 24 + core/sail/fts/solr/pom.xml | 68 + .../solr/solr/cores/embedded/conf/schema.xml | 81 + .../solr/cores/embedded/conf/solrconfig.xml | 12 + .../solr/solr/cores/embedded/core.properties | 1 + core/sail/fts/solr/solr/solr.xml | 3 + .../rdf4j/sail/solr/SolrBulkUpdater.java | 72 + .../rdf4j/sail/solr/SolrClientFactory.java | 15 + .../rdf4j/sail/solr/SolrDocumentDistance.java | 28 + .../rdf4j/sail/solr/SolrDocumentResult.java | 25 + .../rdf4j/sail/solr/SolrDocumentScore.java | 39 + .../eclipse/rdf4j/sail/solr/SolrIndex.java | 699 + .../rdf4j/sail/solr/SolrSearchDocument.java | 140 + .../rdf4j/sail/solr/SolrSearchQuery.java | 88 + .../rdf4j/sail/solr/client/cloud/Factory.java | 20 + .../sail/solr/client/embedded/Factory.java | 27 + .../rdf4j/sail/solr/client/http/Factory.java | 20 + .../sail/solr/config/SolrSailConfig.java | 34 + .../sail/solr/config/SolrSailFactory.java | 62 + .../org.openrdf.sail.config.SailFactory | 1 + .../rdf4j/sail/solr/SolrIndexTest.java | 477 + .../sail/solr/SolrSailGeoSPARQLTest.java | 72 + .../solr/SolrSailIndexedPropertiesTest.java | 36 + .../eclipse/rdf4j/sail/solr/SolrSailTest.java | 36 + .../sail/solr/examples/SolrSailExample.java | 159 + core/sail/inferencer/pom.xml | 70 + .../sail/inferencer/InferencerConnection.java | 95 + .../InferencerConnectionWrapper.java | 162 + .../fc/AbstractForwardChainingInferencer.java | 60 + ...ctForwardChainingInferencerConnection.java | 182 + .../fc/CustomGraphQueryInferencer.java | 343 + .../fc/DirectTypeHierarchyInferencer.java | 303 + .../fc/ForwardChainingRDFSInferencer.java | 71 + ...rwardChainingRDFSInferencerConnection.java | 925 + .../rdf4j/sail/inferencer/fc/RDFSRules.java | 238 + .../CustomGraphQueryInferencerConfig.java | 211 + .../CustomGraphQueryInferencerFactory.java | 65 + .../CustomGraphQueryInferencerSchema.java | 43 + .../DirectTypeHierarchyInferencerConfig.java | 25 + .../DirectTypeHierarchyInferencerFactory.java | 51 + .../ForwardChainingRDFSInferencerConfig.java | 25 + .../ForwardChainingRDFSInferencerFactory.java | 51 + .../rdf4j/sail/inferencer/fc/package.html | 5 + .../org.openrdf.sail.config.SailFactory | 3 + core/sail/memory/pom.xml | 72 + .../org/eclipse/rdf4j/sail/memory/FileIO.java | 408 + .../sail/memory/MemEvaluationStatistics.java | 133 + .../rdf4j/sail/memory/MemNamespaceStore.java | 67 + .../rdf4j/sail/memory/MemorySailStore.java | 763 + .../rdf4j/sail/memory/MemoryStore.java | 472 + .../sail/memory/MemoryStoreConnection.java | 136 + .../sail/memory/config/MemoryStoreConfig.java | 108 + .../memory/config/MemoryStoreFactory.java | 64 + .../sail/memory/config/MemoryStoreSchema.java | 37 + .../org/eclipse/rdf4j/sail/memory/design.txt | 13 + .../sail/memory/model/BooleanMemLiteral.java | 49 + .../sail/memory/model/CalendarMemLiteral.java | 70 + .../sail/memory/model/DecimalMemLiteral.java | 91 + .../sail/memory/model/IntegerMemLiteral.java | 91 + .../rdf4j/sail/memory/model/MemBNode.java | 203 + .../rdf4j/sail/memory/model/MemIRI.java | 343 + .../rdf4j/sail/memory/model/MemLiteral.java | 139 + .../rdf4j/sail/memory/model/MemResource.java | 86 + .../rdf4j/sail/memory/model/MemStatement.java | 153 + .../memory/model/MemStatementIterator.java | 154 + .../sail/memory/model/MemStatementList.java | 149 + .../rdf4j/sail/memory/model/MemValue.java | 86 + .../sail/memory/model/MemValueFactory.java | 419 + .../sail/memory/model/NumericMemLiteral.java | 99 + .../sail/memory/model/WeakObjectRegistry.java | 132 + .../rdf4j/sail/memory/model/package.html | 5 + .../eclipse/rdf4j/sail/memory/package.html | 7 + .../org.openrdf.sail.config.SailFactory | 1 + .../sail/memory/MemTripleSourceTest.java | 1163 + .../rdf4j/sail/memory/model/MemURITest.java | 50 + .../src/test/resources/alp-testdata.ttl | 13 + core/sail/model/pom.xml | 24 + .../eclipse/rdf4j/sail/model/SailModel.java | 314 + core/sail/nativerdf/pom.xml | 70 + .../rdf4j/sail/nativerdf/LRUCache.java | 57 + .../nativerdf/LimitedSizeNativeStore.java | 48 + .../LimitedSizeNativeStoreConnection.java | 46 + .../sail/nativerdf/MemoryOverflowModel.java | 271 + .../rdf4j/sail/nativerdf/NamespaceStore.java | 238 + .../nativerdf/NativeEvaluationStatistics.java | 119 + .../rdf4j/sail/nativerdf/NativeSailStore.java | 654 + .../nativerdf/NativeStatementIterator.java | 101 + .../rdf4j/sail/nativerdf/NativeStore.java | 419 + .../sail/nativerdf/NativeStoreConnection.java | 173 + .../rdf4j/sail/nativerdf/RecordCache.java | 170 + .../rdf4j/sail/nativerdf/SailSourceModel.java | 467 + .../sail/nativerdf/SequentialRecordCache.java | 145 + .../sail/nativerdf/SortedRecordCache.java | 77 + .../rdf4j/sail/nativerdf/TripleStore.java | 1261 + .../rdf4j/sail/nativerdf/TxnStatusFile.java | 130 + .../rdf4j/sail/nativerdf/ValueStore.java | 841 + .../sail/nativerdf/ValueStoreRevision.java | 52 + .../nativerdf/btree/AllocatedNodesList.java | 300 + .../rdf4j/sail/nativerdf/btree/BTree.java | 2599 + .../btree/DefaultRecordComparator.java | 26 + .../nativerdf/btree/RecordComparator.java | 33 + .../sail/nativerdf/btree/RecordIterator.java | 50 + .../nativerdf/config/NativeStoreConfig.java | 208 + .../nativerdf/config/NativeStoreFactory.java | 76 + .../nativerdf/config/NativeStoreSchema.java | 53 + .../sail/nativerdf/datastore/DataFile.java | 229 + .../sail/nativerdf/datastore/DataStore.java | 249 + .../sail/nativerdf/datastore/HashFile.java | 574 + .../sail/nativerdf/datastore/IDFile.java | 204 + .../sail/nativerdf/model/NativeBNode.java | 85 + .../rdf4j/sail/nativerdf/model/NativeIRI.java | 87 + .../sail/nativerdf/model/NativeLiteral.java | 103 + .../sail/nativerdf/model/NativeResource.java | 13 + .../sail/nativerdf/model/NativeValue.java | 39 + .../eclipse/rdf4j/sail/nativerdf/package.html | 5 + .../rdf4j/sail/nativerdf/txn-flags.txt | 22 + .../org.openrdf.sail.config.SailFactory | 1 + .../sail/nativerdf/DefaultIndexTest.java | 59 + .../nativerdf/TestNativeStoreUpgrade.java | 164 + .../nativerdf/TripleStoreRecoveryTest.java | 118 + .../sail/nativerdf/btree/BTreeBenchmark.java | 257 + .../rdf4j/sail/nativerdf/btree/BTreeTest.java | 193 + .../src/test/resources/logback-test.xml | 15 + .../src/test/resources/nativerdf-2.7.15.zip | Bin 0 -> 1347 bytes .../nativerdf-inconsistent-2.7.15.zip | Bin 0 -> 1415 bytes core/sail/pom.xml | 28 + .../openrdf/sail/rdbms/RdbmsConnection.java | 321 + .../org/openrdf/sail/rdbms/RdbmsStore.java | 300 + .../algebra/base/RdbmsQueryModelNodeBase.java | 34 + .../base/RdbmsQueryModelVisitorBase.java | 315 + .../algebra/factories/BNodeExprFactory.java | 105 + .../algebra/factories/BooleanExprFactory.java | 395 + .../factories/DatatypeExprFactory.java | 131 + .../algebra/factories/HashExprFactory.java | 85 + .../algebra/factories/LabelExprFactory.java | 142 + .../factories/LanguageExprFactory.java | 109 + .../algebra/factories/NumericExprFactory.java | 121 + .../algebra/factories/TimeExprFactory.java | 116 + .../algebra/factories/URIExprFactory.java | 144 + .../algebra/factories/ZonedExprFactory.java | 113 + .../sail/rdbms/config/RdbmsStoreConfig.java | 174 + .../rdbms/evaluation/RdbmsEvaluation.java | 169 + .../iteration/base/RdbmIterationBase.java | 101 + .../SameTermFilterRdbmsOptimizer.java | 183 + .../optimizers/ValueIdLookupOptimizer.java | 46 + core/util/pom.xml | 34 + .../rdf4j/common/io/ByteArrayUtil.java | 259 + .../org/eclipse/rdf4j/common/io/FileUtil.java | 390 + .../org/eclipse/rdf4j/common/io/GZipUtil.java | 34 + .../org/eclipse/rdf4j/common/io/IOUtil.java | 568 + .../rdf4j/common/io/IndentingWriter.java | 141 + .../eclipse/rdf4j/common/io/MavenUtil.java | 70 + .../org/eclipse/rdf4j/common/io/NioFile.java | 288 + .../eclipse/rdf4j/common/io/ResourceUtil.java | 288 + .../common/io/UncloseableInputStream.java | 38 + .../org/eclipse/rdf4j/common/io/ZipUtil.java | 114 + .../iteration/AbstractCloseableIteration.java | 66 + .../common/iteration/CloseableIteration.java | 38 + .../iteration/CloseableIterationBase.java | 18 + .../iteration/CloseableIteratorIteration.java | 78 + .../common/iteration/ConvertingIteration.java | 110 + .../common/iteration/DelayedIteration.java | 120 + .../common/iteration/DistinctIteration.java | 87 + .../common/iteration/EmptyIteration.java | 43 + .../ExceptionConvertingIteration.java | 147 + .../common/iteration/FilterIteration.java | 100 + .../rdf4j/common/iteration/InterruptTask.java | 34 + .../common/iteration/IntersectIteration.java | 145 + .../rdf4j/common/iteration/Iteration.java | 64 + .../iteration/IterationSpliterator.java | 91 + .../common/iteration/IterationWrapper.java | 105 + .../rdf4j/common/iteration/Iterations.java | 175 + .../common/iteration/IteratorIteration.java | 36 + .../common/iteration/LimitIteration.java | 78 + .../common/iteration/LookAheadIteration.java | 104 + .../common/iteration/MinusIteration.java | 117 + .../common/iteration/OffsetIteration.java | 68 + .../common/iteration/ReducedIteration.java | 33 + .../common/iteration/SingletonIteration.java | 63 + .../common/iteration/TimeLimitIteration.java | 115 + .../common/iteration/UnionIteration.java | 101 + .../iterator/AbstractCloseableIterator.java | 76 + .../iterator/CloseableIterationIterator.java | 57 + .../iterator/CloseableIteratorBase.java | 17 + .../common/iterator/LookAheadIterator.java | 115 + .../rdf4j/common/iterator/UnionIterator.java | 88 + .../eclipse/rdf4j/common/lang/FileFormat.java | 410 + .../eclipse/rdf4j/common/lang/ObjectUtil.java | 46 + .../service/FileFormatServiceRegistry.java | 53 + .../common/lang/service/ServiceRegistry.java | 139 + .../eclipse/rdf4j/common/net/ParsedURI.java | 583 + .../eclipse/rdf4j/common/text/ASCIIUtil.java | 71 + .../eclipse/rdf4j/common/text/StringUtil.java | 306 + .../rdf4j/common/xml/DocumentUtil.java | 121 + .../rdf4j/common/xml/SimpleSAXAdapter.java | 44 + .../rdf4j/common/xml/SimpleSAXListener.java | 55 + .../rdf4j/common/xml/SimpleSAXParser.java | 339 + .../rdf4j/common/xml/XMLReaderFactory.java | 144 + .../org/eclipse/rdf4j/common/xml/XMLUtil.java | 691 + .../eclipse/rdf4j/common/xml/XMLWriter.java | 495 + .../eclipse/rdf4j/util/NonSerializables.java | 86 + .../util/iterators/ConvertingIterator.java | 79 + .../rdf4j/util/iterators/EmptyIterator.java | 30 + .../rdf4j/util/iterators/FilterIterator.java | 75 + .../rdf4j/util/iterators/Iterators.java | 129 + .../util/iterators/SingletonIterator.java | 44 + .../eclipse/rdf4j/common/io/FileUtilTest.java | 24 + .../rdf4j/common/net/ParsedURITest.java | 292 + license.html | 57 + pom.xml | 705 + testsuites/geosparql/pom.xml | 29 + .../geosparql/GeoSPARQLManifestTest.java | 34 + .../testcases-geosparql/functions/data.ttl | 9 + .../functions/manifest.ttl | 84 + .../functions/q-boundary.rq | 9 + .../functions/q-convexHull.rq | 9 + .../functions/q-difference.rq | 9 + .../functions/q-distance.rq | 9 + .../functions/q-envelope.rq | 8 + .../functions/q-intersection.rq | 9 + .../testcases-geosparql/functions/q-srid.rq | 8 + .../functions/q-symDifference.rq | 9 + .../testcases-geosparql/functions/q-union.rq | 9 + .../functions/result-boundary.srx | 16 + .../functions/result-convexHull.srx | 26 + .../functions/result-difference.srx | 26 + .../functions/result-distance.srx | 21 + .../functions/result-envelope.srx | 21 + .../functions/result-intersection.srx | 26 + .../functions/result-srid.srx | 21 + .../functions/result-symDifference.srx | 21 + .../functions/result-union.srx | 26 + .../testcases-geosparql/manifest.txt | 1 + testsuites/lucene/pom.xml | 38 + .../AbstractLuceneSailGeoSPARQLTest.java | 284 + ...stractLuceneSailIndexedPropertiesTest.java | 216 + .../sail/lucene/AbstractLuceneSailTest.java | 1103 + .../openrdf/sail/lucene/examples/foaf.rdfs | 550 + testsuites/lucene/testdata.kml | 56 + testsuites/model/pom.xml | 34 + .../rdf4j/model/ModelEqualityTest.java | 124 + .../rdf4j/model/ModelNamespacesTest.java | 333 + .../org/eclipse/rdf4j/model/ModelTest.java | 302 + .../model/base/AbstractTestCollection.java | 1323 + .../rdf4j/model/base/AbstractTestObject.java | 319 + .../rdf4j/model/base/AbstractTestSet.java | 185 + .../rdf4j/model/base/ApacheSetTestCase.java | 168 + .../eclipse/rdf4j/model/base/BulkTest.java | 453 + .../equality/sparql-graph-11-shuffled.ttl | 209 + .../model/equality/sparql-graph-11.ttl | 107 + .../testcases/model/equality/test001a.ttl | 6 + .../testcases/model/equality/test001b.ttl | 6 + .../model/equality/toRdf-0061-out.nq | 13 + testsuites/pom.xml | 41 + testsuites/queryresultio/pom.xml | 49 + .../AbstractQueryResultIOBooleanTest.java | 156 + .../resultio/AbstractQueryResultIOTest.java | 754 + .../AbstractQueryResultIOTupleTest.java | 244 + testsuites/rio/pom.xml | 62 + .../rdf4j/rio/AbstractParserHandlingTest.java | 906 + .../org/eclipse/rdf4j/rio/EarlReport.java | 220 + .../org/eclipse/rdf4j/rio/FailureMode.java | 32 + .../eclipse/rdf4j/rio/NegativeParserTest.java | 97 + .../eclipse/rdf4j/rio/ParserConfigTest.java | 312 + .../eclipse/rdf4j/rio/PositiveParserTest.java | 134 + .../org/eclipse/rdf4j/rio/RDFWriterTest.java | 665 + .../AbstractDatatypeHandlerTest.java | 323 + .../rdf4j/rio/n3/N3ParserTestCase.java | 279 + .../rio/nquads/AbstractNQuadsParserTest.java | 169 + .../nquads/AbstractNQuadsParserUnitTest.java | 725 + .../rio/nquads/AbstractNQuadsWriterTest.java | 211 + .../ntriples/AbstractNTriplesParserTest.java | 169 + .../AbstractNTriplesParserUnitTest.java | 426 + .../rio/rdfjson/RDFJSONParserTestCase.java | 318 + .../rio/rdfxml/RDFXMLParserTestCase.java | 349 + .../rio/rdfxml/RDFXMLWriterTestCase.java | 71 + .../rdf4j/rio/trig/TriGParserTestCase.java | 265 + .../rio/turtle/TurtleParserTestCase.java | 347 + .../resources/testcases/rdfjson/manifest.ttl | 400 + .../testcases/rdfjson/rdfjson-eval-file-01.nt | 1 + .../testcases/rdfjson/rdfjson-eval-file-02.nt | 1 + .../testcases/rdfjson/rdfjson-eval-file-03.nt | 1 + .../testcases/rdfjson/rdfjson-eval-file-04.nt | 1 + .../testcases/rdfjson/rdfjson-eval-file-05.nt | 1 + .../testcases/rdfjson/rdfjson-eval-file-06.nt | 1 + .../testcases/rdfjson/rdfjson-eval-file-07.nt | 1 + .../testcases/rdfjson/rdfjson-eval-file-08.nt | 1 + .../testcases/rdfjson/rdfjson-eval-file-09.nt | 1 + .../testcases/rdfjson/rdfjson-eval-file-10.nt | 2 + .../testcases/rdfjson/rdfjson-eval-file-11.nt | 2 + .../testcases/rdfjson/rdfjson-eval-file-12.nt | 2 + .../testcases/rdfjson/rdfjson-eval-file-13.nt | 4 + .../testcases/rdfjson/rdfjson-eval-file-14.nt | 2 + .../testcases/rdfjson/rdfjson-eval-file-15.nt | 4 + .../rdfjson/rdfjson-syntax-bad-01.rj | 1 + .../rdfjson/rdfjson-syntax-bad-02.rj | 3 + .../rdfjson/rdfjson-syntax-bad-03.rj | 3 + .../rdfjson/rdfjson-syntax-bad-04.rj | 3 + .../rdfjson/rdfjson-syntax-bad-05.rj | 3 + .../rdfjson/rdfjson-syntax-bad-06.rj | 3 + .../rdfjson/rdfjson-syntax-bad-07.rj | 3 + .../rdfjson/rdfjson-syntax-bad-08.rj | 3 + .../rdfjson/rdfjson-syntax-bad-09.rj | 3 + .../rdfjson/rdfjson-syntax-bad-10.rj | 3 + .../rdfjson/rdfjson-syntax-bad-11.rj | 3 + .../rdfjson/rdfjson-syntax-bad-12.rj | 3 + .../rdfjson/rdfjson-syntax-bad-13.rj | 3 + .../rdfjson/rdfjson-syntax-bad-14.rj | 3 + .../rdfjson/rdfjson-syntax-bad-15.rj | 3 + .../rdfjson/rdfjson-syntax-bad-16.rj | 3 + .../rdfjson/rdfjson-syntax-bad-17.rj | 3 + .../rdfjson/rdfjson-syntax-bad-18.rj | 3 + .../rdfjson/rdfjson-syntax-bad-19.rj | 3 + .../rdfjson/rdfjson-syntax-bad-20.rj | 3 + .../rdfjson/rdfjson-syntax-bad-21.rj | 3 + .../rdfjson/rdfjson-syntax-file-01.rj | 1 + .../rdfjson/rdfjson-syntax-file-02.rj | 6 + .../rdfjson/rdfjson-syntax-file-03.rj | 7 + .../rdfjson/rdfjson-syntax-file-04.rj | 7 + .../rdfjson/rdfjson-syntax-file-05.rj | 7 + .../rdfjson/rdfjson-syntax-file-06.rj | 6 + .../rdfjson/rdfjson-syntax-file-07.rj | 6 + .../rdfjson/rdfjson-syntax-file-08.rj | 6 + .../rdfjson/rdfjson-syntax-file-09.rj | 6 + .../rdfjson/rdfjson-syntax-file-10.rj | 10 + .../rdfjson/rdfjson-syntax-file-11.rj | 10 + .../rdfjson/rdfjson-syntax-file-12.rj | 8 + .../rdfjson/rdfjson-syntax-file-13.rj | 15 + .../rdfjson/rdfjson-syntax-file-14.rj | 8 + .../rdfjson/rdfjson-syntax-file-15.rj | 14 + .../testcases/rdfxml/openrdf/Manifest.rdf | 116 + .../openrdf/bad-entity-expansion-limit.rdf | 24 + .../rdfms-empty-property-elements/test001a.nt | 2 + .../test001a.rdf | 19 + .../rdfms-empty-property-elements/test001b.nt | 2 + .../test001b.rdf | 18 + .../rdfms-empty-property-elements/test002.nt | 2 + .../test002a.rdf | 19 + .../test002b.rdf | 17 + .../rdfms-empty-property-elements/test003.nt | 1 + .../test003a.rdf | 14 + .../test003b.rdf | 15 + .../rdfxml/openrdf/xmlbase/test001.nt | 1 + .../rdfxml/openrdf/xmlbase/test001.rdf | 10 + .../testcases/turtle/tests-nt/manifest.ttl | 329 + .../turtle/tests-nt/nt-syntax-bad-base-01.nt | 1 + .../turtle/tests-nt/nt-syntax-bad-esc-01.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-esc-02.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-esc-03.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-lang-01.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-num-01.nt | 1 + .../turtle/tests-nt/nt-syntax-bad-num-02.nt | 1 + .../turtle/tests-nt/nt-syntax-bad-num-03.nt | 1 + .../tests-nt/nt-syntax-bad-prefix-01.nt | 1 + .../tests-nt/nt-syntax-bad-string-01.nt | 1 + .../tests-nt/nt-syntax-bad-string-02.nt | 1 + .../tests-nt/nt-syntax-bad-string-03.nt | 1 + .../tests-nt/nt-syntax-bad-string-04.nt | 1 + .../tests-nt/nt-syntax-bad-string-05.nt | 1 + .../tests-nt/nt-syntax-bad-string-06.nt | 1 + .../tests-nt/nt-syntax-bad-string-07.nt | 1 + .../tests-nt/nt-syntax-bad-struct-01.nt | 1 + .../tests-nt/nt-syntax-bad-struct-02.nt | 1 + .../turtle/tests-nt/nt-syntax-bad-uri-01.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-uri-02.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-uri-03.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-uri-04.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-uri-05.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-uri-06.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-uri-07.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-uri-08.nt | 2 + .../turtle/tests-nt/nt-syntax-bad-uri-09.nt | 2 + .../turtle/tests-nt/nt-syntax-bnode-01.nt | 1 + .../turtle/tests-nt/nt-syntax-bnode-02.nt | 2 + .../turtle/tests-nt/nt-syntax-datatypes-01.nt | 1 + .../turtle/tests-nt/nt-syntax-datatypes-02.nt | 1 + .../turtle/tests-nt/nt-syntax-file-01.nt | 0 .../turtle/tests-nt/nt-syntax-file-02.nt | 1 + .../turtle/tests-nt/nt-syntax-file-03.nt | 2 + .../turtle/tests-nt/nt-syntax-str-esc-01.nt | 1 + .../turtle/tests-nt/nt-syntax-str-esc-02.nt | 1 + .../turtle/tests-nt/nt-syntax-str-esc-03.nt | 1 + .../turtle/tests-nt/nt-syntax-string-01.nt | 1 + .../turtle/tests-nt/nt-syntax-string-02.nt | 1 + .../turtle/tests-nt/nt-syntax-string-03.nt | 1 + .../turtle/tests-nt/nt-syntax-subm-01.nt | 79 + .../turtle/tests-nt/nt-syntax-uri-01.nt | 1 + .../turtle/tests-nt/nt-syntax-uri-02.nt | 2 + .../turtle/tests-nt/nt-syntax-uri-03.nt | 2 + .../turtle/tests-nt/nt-syntax-uri-04.nt | 2 + .../turtle/turtle-long-literals-test.nt | 9 + .../turtle/turtle-long-literals-test.ttl | 11 + testsuites/serql/pom.xml | 54 + .../parser/serql/SeRQLParserTestCase.java | 205 + .../parser/serql/SeRQLQueryTestCase.java | 373 + .../testcases/SeRQL/construct/manifest.ttl | 269 + .../testcases/SeRQL/construct/test000-in.nt | 2 + .../testcases/SeRQL/construct/test000-out.nt | 142 + .../SeRQL/construct/test000-query.serql | 4 + .../testcases/SeRQL/construct/test001-in.nt | 4 + .../testcases/SeRQL/construct/test001-out.nt | 5 + .../SeRQL/construct/test001-query.serql | 4 + .../testcases/SeRQL/construct/test002-in.nt | 4 + .../testcases/SeRQL/construct/test002-out.nt | 1 + .../SeRQL/construct/test002-query.serql | 6 + .../testcases/SeRQL/construct/test003-in.nt | 6 + .../testcases/SeRQL/construct/test003-out.nt | 3 + .../SeRQL/construct/test003-query.serql | 6 + .../testcases/SeRQL/construct/test004-in.nt | 5 + .../testcases/SeRQL/construct/test004-out.nt | 1 + .../SeRQL/construct/test004-query.serql | 6 + .../testcases/SeRQL/construct/test005-in.nt | 6 + .../testcases/SeRQL/construct/test005-out.nt | 5 + .../SeRQL/construct/test005-query.serql | 5 + .../testcases/SeRQL/construct/test006-in.nt | 8 + .../testcases/SeRQL/construct/test006-out.nt | 4 + .../SeRQL/construct/test006-query.serql | 6 + .../testcases/SeRQL/construct/test007-in.nt | 9 + .../testcases/SeRQL/construct/test007-out.nt | 3 + .../SeRQL/construct/test007-query.serql | 6 + .../testcases/SeRQL/construct/test008-in.nt | 7 + .../testcases/SeRQL/construct/test008-out.nt | 5 + .../SeRQL/construct/test008-query.serql | 5 + .../testcases/SeRQL/construct/test009-in.nt | 24 + .../testcases/SeRQL/construct/test009-out.nt | 25 + .../SeRQL/construct/test009-query.serql | 6 + .../testcases/SeRQL/construct/test010-in.nt | 5 + .../testcases/SeRQL/construct/test010-out.nt | 6 + .../SeRQL/construct/test010-query.serql | 4 + .../testcases/SeRQL/construct/test011-in.nt | 5 + .../testcases/SeRQL/construct/test011-out.nt | 4 + .../SeRQL/construct/test011-query.serql | 4 + .../testcases/SeRQL/construct/test012-in.nt | 3 + .../testcases/SeRQL/construct/test012-out.nt | 3 + .../SeRQL/construct/test012-query.serql | 4 + .../testcases/SeRQL/construct/test013-in.nt | 9 + .../testcases/SeRQL/construct/test013-out.nt | 3 + .../SeRQL/construct/test013-query.serql | 5 + .../testcases/SeRQL/construct/test014-in.nt | 6 + .../testcases/SeRQL/construct/test014-out.nt | 2 + .../SeRQL/construct/test014-query.serql | 3 + .../testcases/SeRQL/construct/test015-in.nt | 6 + .../testcases/SeRQL/construct/test015-out.nt | 2 + .../SeRQL/construct/test015-query.serql | 3 + .../testcases/SeRQL/construct/test016-in.nt | 6 + .../testcases/SeRQL/construct/test016-out.nt | 1 + .../SeRQL/construct/test016-query.serql | 3 + .../testcases/SeRQL/construct/test017-in.nt | 6 + .../testcases/SeRQL/construct/test017-out.nt | 1 + .../SeRQL/construct/test017-query.serql | 3 + .../testcases/SeRQL/construct/test018-in.nt | 7 + .../testcases/SeRQL/construct/test018-out.nt | 2 + .../SeRQL/construct/test018-query.serql | 2 + .../testcases/SeRQL/construct/test019-in.nt | 3 + .../testcases/SeRQL/construct/test019-out.nt | 1 + .../SeRQL/construct/test019-query.serql | 1 + .../testcases/SeRQL/construct/test020-in.nt | 5 + .../testcases/SeRQL/construct/test020-out.nt | 1 + .../SeRQL/construct/test020-query.serql | 6 + .../testcases/SeRQL/construct/test021-in.nt | 4 + .../testcases/SeRQL/construct/test021-out.nt | 5 + .../SeRQL/construct/test021-query.serql | 7 + .../testcases/SeRQL/construct/test022-in.nt | 7 + .../testcases/SeRQL/construct/test022-out.nt | 4 + .../SeRQL/construct/test022-query.serql | 8 + .../testcases/SeRQL/construct/test023-in.nt | 7 + .../testcases/SeRQL/construct/test023-out.nt | 4 + .../SeRQL/construct/test023-query.serql | 8 + .../SeRQL/construct/test024-graph1.ttl | 8 + .../SeRQL/construct/test024-graph2.ttl | 8 + .../testcases/SeRQL/construct/test024-in.ttl | 9 + .../testcases/SeRQL/construct/test024-out.ttl | 11 + .../SeRQL/construct/test024-query.serql | 12 + .../testcases/SeRQL/construct/test025-in.ttl | 3 + .../testcases/SeRQL/construct/test025-out.ttl | 1 + .../SeRQL/construct/test025-query.serql | 2 + .../testcases/SeRQL/construct/test026-in.trig | 8 + .../testcases/SeRQL/construct/test026-out.ttl | 1 + .../SeRQL/construct/test026-query.serql | 4 + .../testcases/SeRQL/construct/test027-in.trig | 8 + .../testcases/SeRQL/construct/test027-out.ttl | 1 + .../SeRQL/construct/test027-query.serql | 4 + .../testcases/SeRQL/construct/test028-in.ttl | 30 + .../testcases/SeRQL/construct/test028-out.ttl | 12 + .../SeRQL/construct/test028-query.serql | 4 + .../testcases/SeRQL/construct/test029-in.nt | 8 + .../testcases/SeRQL/construct/test029-out.nt | 5 + .../SeRQL/construct/test029-query.serql | 6 + .../testcases/SeRQL/construct/test030-in.nt | 9 + .../testcases/SeRQL/construct/test030-out.nt | 6 + .../SeRQL/construct/test030-query.serql | 6 + .../testcases/SeRQL/construct/test031-in.ttl | 13 + .../testcases/SeRQL/construct/test031-out.ttl | 13 + .../SeRQL/construct/test031-query.serql | 7 + .../testcases/SeRQL/construct/test032-in.ttl | 13 + .../testcases/SeRQL/construct/test032-out.ttl | 10 + .../SeRQL/construct/test032-query.serql | 7 + .../testcases/SeRQL/syntax/manifest.ttl | 329 + .../testcases/SeRQL/syntax/syntax-000.serql | 4 + .../testcases/SeRQL/syntax/syntax-001.serql | 4 + .../testcases/SeRQL/syntax/syntax-002.serql | 4 + .../testcases/SeRQL/syntax/syntax-003.serql | 4 + .../testcases/SeRQL/syntax/syntax-004.serql | 4 + .../testcases/SeRQL/syntax/syntax-005.serql | 4 + .../testcases/SeRQL/syntax/syntax-006.serql | 4 + .../testcases/SeRQL/syntax/syntax-007.serql | 4 + .../testcases/SeRQL/syntax/syntax-008.serql | 4 + .../testcases/SeRQL/syntax/syntax-009.serql | 4 + .../testcases/SeRQL/syntax/syntax-010.serql | 4 + .../testcases/SeRQL/syntax/syntax-011.serql | 4 + .../testcases/SeRQL/syntax/syntax-012.serql | 4 + .../testcases/SeRQL/syntax/syntax-013.serql | 3 + .../testcases/SeRQL/syntax/syntax-014.serql | 4 + .../testcases/SeRQL/syntax/syntax-015.serql | 4 + .../testcases/SeRQL/syntax/syntax-016.serql | 4 + .../testcases/SeRQL/syntax/syntax-017.serql | 4 + .../testcases/SeRQL/syntax/syntax-018.serql | 4 + .../testcases/SeRQL/syntax/syntax-019.serql | 4 + .../testcases/SeRQL/syntax/syntax-020.serql | 4 + .../testcases/SeRQL/syntax/syntax-021.serql | 4 + .../testcases/SeRQL/syntax/syntax-022.serql | 4 + .../testcases/SeRQL/syntax/syntax-023.serql | 4 + .../testcases/SeRQL/syntax/syntax-024.serql | 4 + .../testcases/SeRQL/syntax/syntax-025.serql | 4 + .../testcases/SeRQL/syntax/syntax-026.serql | 4 + .../testcases/SeRQL/syntax/syntax-027.serql | 4 + .../testcases/SeRQL/syntax/syntax-028.serql | 5 + .../testcases/SeRQL/syntax/syntax-029.serql | 5 + .../testcases/SeRQL/syntax/syntax-030.serql | 7 + .../testcases/SeRQL/syntax/syntax-031.serql | 7 + .../testcases/SeRQL/syntax/syntax-032.serql | 8 + .../testcases/SeRQL/syntax/syntax-033.serql | 14 + .../testcases/SeRQL/syntax/syntax-034.serql | 6 + .../testcases/SeRQL/syntax/syntax-035.serql | 6 + .../testcases/SeRQL/syntax/syntax-036.serql | 6 + .../testcases/SeRQL/syntax/syntax-037.serql | 4 + .../testcases/SeRQL/syntax/syntax-038.serql | 5 + .../testcases/SeRQL/syntax/syntax-039.serql | 0 .../testcases/SeRQL/syntax/syntax-040.serql | 1 + .../testcases/SeRQL/syntax/syntax-041.serql | 4 + .../testcases/SeRQL/syntax/syntax-042.serql | 6 + .../testcases/SeRQL/syntax/syntax-043.serql | 6 + .../testcases/SeRQL/syntax/syntax-044.serql | 6 + .../testcases/SeRQL/syntax/syntax-045.serql | 6 + .../testcases/SeRQL/syntax/syntax-046.serql | 6 + .../testcases/SeRQL/syntax/syntax-047.serql | 6 + .../testcases/SeRQL/syntax/syntax-048.serql | 4 + .../testcases/SeRQL/syntax/syntax-049.serql | 4 + .../testcases/SeRQL/syntax/syntax-050.serql | 6 + .../testcases/SeRQL/syntax/syntax-051.serql | 8 + testsuites/sparql/pom.xml | 149 + .../parser/sparql/ComplexSPARQLQueryTest.java | 2141 + .../query/parser/sparql/SPARQLDataSet.java | 50 + .../query/parser/sparql/SPARQLUpdateTest.java | 1828 + .../parser/sparql/manifest/ManifestTest.java | 183 + .../sparql/manifest/SPARQL11ManifestTest.java | 301 + .../sparql/manifest/SPARQL11SyntaxTest.java | 314 + .../sparql/manifest/SPARQLQueryTest.java | 804 + .../sparql/manifest/SPARQLSyntaxTest.java | 266 + .../manifest/SPARQLUpdateConformanceTest.java | 430 + .../main/resources/testcases-service/README | 1 + .../resources/testcases-service/data01.ttl | 5 + .../testcases-service/data01endpoint.ttl | 5 + .../testcases-service/data02endpoint1.ttl | 5 + .../testcases-service/data02endpoint2.ttl | 4 + .../testcases-service/data03endpoint1.ttl | 5 + .../testcases-service/data03endpoint2.ttl | 4 + .../resources/testcases-service/data04.ttl | 9 + .../testcases-service/data04endpoint.ttl | 7 + .../resources/testcases-service/data05.ttl | 10 + .../testcases-service/data05endpoint1.ttl | 7 + .../testcases-service/data05endpoint2.ttl | 5 + .../testcases-service/data06endpoint1.ttl | 5 + .../resources/testcases-service/data07.ttl | 5 + .../resources/testcases-service/data08.ttl | 5 + .../testcases-service/data08endpoint.ttl | 5 + .../testcases-service/data09endpoint.ttl | 5 + .../resources/testcases-service/data10.ttl | 5 + .../testcases-service/data10endpoint.ttl | 4 + .../resources/testcases-service/data11.ttl | 29 + .../testcases-service/data11endpoint.ttl | 17 + .../resources/testcases-service/data12.ttl | 10 + .../resources/testcases-service/data13.ttl | 9 + .../testcases-service/data15endpoint1.ttl | 9 + .../testcases-service/data15endpoint2.ttl | 12 + .../testcases-service/data17endpoint1.ttl | 8 + .../testcases-service/data18endpoint1.rdf | 11 + .../testcases-service/dataendpoint01.ttl | 7 + .../resources/testcases-service/index.html | 42 + .../resources/testcases-service/manifest.ttl | 124 + .../resources/testcases-service/service01.rq | 11 + .../resources/testcases-service/service01.srx | 21 + .../resources/testcases-service/service02.rq | 13 + .../resources/testcases-service/service02.srx | 20 + .../resources/testcases-service/service03.rq | 14 + .../resources/testcases-service/service03.srx | 20 + .../resources/testcases-service/service04.rq | 11 + .../resources/testcases-service/service04.srx | 31 + .../resources/testcases-service/service05.rq | 15 + .../resources/testcases-service/service05.srx | 22 + .../resources/testcases-service/service06.rq | 14 + .../resources/testcases-service/service06.srx | 18 + .../resources/testcases-service/service07.rq | 10 + .../resources/testcases-service/service07.srx | 19 + .../resources/testcases-service/service08.rq | 12 + .../resources/testcases-service/service08.srx | 14 + .../resources/testcases-service/service09.rq | 11 + .../resources/testcases-service/service09.srx | 21 + .../resources/testcases-service/service10.rq | 11 + .../resources/testcases-service/service10.srx | 14 + .../resources/testcases-service/service11.rq | 11 + .../resources/testcases-service/service11.srx | 66 + .../resources/testcases-service/service12.rq | 11 + .../resources/testcases-service/service12.srx | 30 + .../resources/testcases-service/service13.rq | 17 + .../resources/testcases-service/service13.srx | 26 + .../resources/testcases-service/service14.rq | 12 + .../resources/testcases-service/service14.srx | 11 + .../resources/testcases-service/service17.rq | 11 + .../resources/testcases-service/service17.srx | 18 + .../resources/testcases-service/service18.rq | 9 + .../resources/testcases-service/service18.srx | 11 + .../simple-default-graph.ttl | 21 + .../resources/testcases-service/simple.ttl | 20 + .../aggregates/data-01.ttl | 15 + .../aggregates/data-02.ttl | 18 + .../aggregates/data-03.ttl | 22 + .../aggregates/data-04.ttl | 1 + .../aggregates/data-05.ttl | 4 + .../aggregates/data-06.ttl | 6 + .../aggregates/data-07.ttl | 8 + .../aggregates/data-08.ttl | 5 + .../aggregates/manifest.ttl | 147 + .../sparql11-aggregate-expression-01.rq | 6 + .../sparql11-aggregate-expression-01.srx | 25 + .../aggregates/sparql11-aggregate-group-01.rq | 4 + .../sparql11-aggregate-group-01.srx | 49 + .../aggregates/sparql11-aggregate-group-02.rq | 3 + .../sparql11-aggregate-group-02.srx | 33 + .../sparql11-aggregate-subquery-01.rq | 14 + .../sparql11-aggregate-subquery-01.srx | 21 + .../sparql11-aggregate-subquery-02.rq | 14 + .../sparql11-aggregate-subquery-02.srx | 21 + .../aggregates/sparql11-avg-01.rq | 8 + .../aggregates/sparql11-avg-01.srx | 21 + .../aggregates/sparql11-avg-02.rq | 6 + .../aggregates/sparql11-avg-02.srx | 38 + .../aggregates/sparql11-count-01.rq | 3 + .../aggregates/sparql11-count-01.srx | 16 + .../aggregates/sparql11-count-02.rq | 3 + .../aggregates/sparql11-count-02.srx | 36 + .../aggregates/sparql11-count-03.rq | 3 + .../aggregates/sparql11-count-03.srx | 14 + .../aggregates/sparql11-count-04.rq | 6 + .../aggregates/sparql11-count-04.srx | 16 + .../aggregates/sparql11-having-01.rq | 9 + .../aggregates/sparql11-having-01.srx | 16 + .../aggregates/sparql11-max-01.rq | 3 + .../aggregates/sparql11-max-01.srx | 28 + .../aggregates/sparql11-min-01.rq | 3 + .../aggregates/sparql11-min-01.srx | 28 + .../aggregates/sparql11-order-01.rq | 4 + .../aggregates/sparql11-order-01.srx | 33 + .../aggregates/sparql11-order-02.rq | 4 + .../aggregates/sparql11-order-02.srx | 23 + .../aggregates/sparql11-order-03.rq | 4 + .../aggregates/sparql11-order-03.srx | 23 + .../aggregates/sparql11-sum-01.rq | 8 + .../aggregates/sparql11-sum-01.srx | 21 + .../aggregates/sparql11-sum-02.rq | 6 + .../aggregates/sparql11-sum-02.srx | 16 + .../aggregates/sparql11-sum-03.rq | 6 + .../aggregates/sparql11-sum-03.srx | 18 + .../aggregates/sparql11-sum-04.rq | 6 + .../aggregates/sparql11-sum-04.srx | 31 + .../testcases-sparql-1.1/bindings/data-01.ttl | 8 + .../bindings/manifest.ttl | 26 + .../bindings/sparql11-bindings-01.rq | 12 + .../bindings/sparql11-bindings-01.srx | 24 + .../bindings/sparql11-bindings-02.rq | 12 + .../bindings/sparql11-bindings-02.srx | 20 + .../testcases-sparql-1.1/bsbm/bsbm-100.ttl | 44565 ++++++++++++ .../testcases-sparql-1.1/bsbm/bsbm-bi-q5.rq | 40 + .../testcases-sparql-1.1/bsbm/bsbm-bi-q5.srx | 264 + .../testcases-sparql-1.1/bsbm/manifest.ttl | 20 + .../testcases-sparql-1.1/builtin/data-01.ttl | 16 + .../testcases-sparql-1.1/builtin/data-02.ttl | 12 + .../testcases-sparql-1.1/builtin/manifest.ttl | 231 + .../builtin/sparql11-abs-01.rq | 6 + .../builtin/sparql11-abs-01.srx | 20 + .../builtin/sparql11-bnode-01.rq | 6 + .../builtin/sparql11-bnode-01.srx | 20 + .../builtin/sparql11-bnode-02.rq | 6 + .../builtin/sparql11-bnode-02.srx | 20 + .../builtin/sparql11-ceil-01.rq | 6 + .../builtin/sparql11-ceil-01.srx | 20 + .../builtin/sparql11-coalesce-01.rq | 7 + .../builtin/sparql11-coalesce-01.srx | 68 + .../builtin/sparql11-concat-01.rq | 6 + .../builtin/sparql11-concat-01.srx | 20 + .../builtin/sparql11-concat-02.rq | 6 + .../builtin/sparql11-concat-02.srx | 20 + .../builtin/sparql11-concat-03.rq | 6 + .../builtin/sparql11-concat-03.srx | 20 + .../builtin/sparql11-concat-04.rq | 6 + .../builtin/sparql11-concat-04.srx | 20 + .../builtin/sparql11-concat-05.rq | 6 + .../builtin/sparql11-concat-05.srx | 20 + .../builtin/sparql11-encodeforuri-01.rq | 6 + .../builtin/sparql11-encodeforuri-01.srx | 20 + .../builtin/sparql11-floor-01.rq | 6 + .../builtin/sparql11-floor-01.srx | 20 + .../builtin/sparql11-if-01.rq | 6 + .../builtin/sparql11-if-01.srx | 20 + .../builtin/sparql11-if-02.rq | 6 + .../builtin/sparql11-if-02.srx | 20 + .../builtin/sparql11-in-01.rq | 9 + .../builtin/sparql11-in-01.srx | 36 + .../builtin/sparql11-in-02.rq | 9 + .../builtin/sparql11-in-02.srx | 36 + .../builtin/sparql11-in-03.rq | 9 + .../builtin/sparql11-in-03.srx | 12 + .../builtin/sparql11-iri-01.rq | 6 + .../builtin/sparql11-iri-01.srx | 20 + .../builtin/sparql11-isnumeric-01.rq | 7 + .../builtin/sparql11-isnumeric-01.srx | 31 + .../builtin/sparql11-lcase-01.rq | 6 + .../builtin/sparql11-lcase-01.srx | 20 + .../builtin/sparql11-not-in-01.rq | 9 + .../builtin/sparql11-not-in-01.srx | 36 + .../builtin/sparql11-not-in-02.rq | 9 + .../builtin/sparql11-not-in-02.srx | 28 + .../builtin/sparql11-not-in-03.rq | 9 + .../builtin/sparql11-not-in-03.srx | 61 + .../builtin/sparql11-round-01.rq | 6 + .../builtin/sparql11-round-01.srx | 20 + .../builtin/sparql11-round-02.rq | 6 + .../builtin/sparql11-round-02.srx | 20 + .../builtin/sparql11-strdt-01.rq | 6 + .../builtin/sparql11-strdt-01.srx | 20 + .../builtin/sparql11-strends-01.rq | 6 + .../builtin/sparql11-strends-01.srx | 20 + .../builtin/sparql11-strlang-01.rq | 6 + .../builtin/sparql11-strlang-01.srx | 20 + .../builtin/sparql11-strlen-01.rq | 6 + .../builtin/sparql11-strlen-01.srx | 20 + .../builtin/sparql11-strlen-02.rq | 6 + .../builtin/sparql11-strlen-02.srx | 20 + .../builtin/sparql11-strstarts-01.rq | 6 + .../builtin/sparql11-strstarts-01.srx | 20 + .../builtin/sparql11-substr-01.rq | 6 + .../builtin/sparql11-substr-01.srx | 20 + .../builtin/sparql11-substr-02.rq | 6 + .../builtin/sparql11-substr-02.srx | 20 + .../builtin/sparql11-substr-03.rq | 6 + .../builtin/sparql11-substr-03.srx | 20 + .../builtin/sparql11-ucase-01.rq | 6 + .../builtin/sparql11-ucase-01.srx | 20 + .../builtin/sparql11-uri-01.rq | 6 + .../builtin/sparql11-uri-01.srx | 20 + .../expressions/data-01.ttl | 5 + .../expressions/data-02.ttl | 11 + .../expressions/manifest.ttl | 39 + .../expressions/sparql11-alias-01.rq | 7 + .../expressions/sparql11-alias-01.srx | 16 + .../expressions/sparql11-alias-02.rq | 7 + .../expressions/sparql11-alias-02.srx | 20 + .../sparql11-expression-ordered-01.rq | 8 + .../sparql11-expression-ordered-01.srx | 26 + .../expressions/sparql11-numeric-01.rq | 7 + .../expressions/sparql11-numeric-01.srx | 28 + .../manifest-evaluation.ttl | 18 + .../testcases-sparql-1.1/negation/data-01.ttl | 7 + .../testcases-sparql-1.1/negation/data-02.ttl | 11 + .../testcases-sparql-1.1/negation/data-03.ttl | 2 + .../testcases-sparql-1.1/negation/data-04.ttl | 4 + .../negation/manifest.ttl | 84 + .../negation/sparql11-exists-01.rq | 9 + .../negation/sparql11-exists-01.srx | 16 + .../negation/sparql11-exists-02.rq | 9 + .../negation/sparql11-exists-02.srx | 16 + .../negation/sparql11-exists-03.rq | 4 + .../negation/sparql11-exists-03.srx | 12 + .../negation/sparql11-exists-04.rq | 6 + .../negation/sparql11-exists-04.srx | 12 + .../negation/sparql11-exists-05.rq | 7 + .../negation/sparql11-exists-05.srx | 20 + .../negation/sparql11-exists-06.rq | 8 + .../negation/sparql11-exists-06.srx | 20 + .../negation/sparql11-minus-01.rq | 10 + .../negation/sparql11-minus-01.srx | 21 + .../negation/sparql11-minus-02.rq | 4 + .../negation/sparql11-minus-02.srx | 24 + .../negation/sparql11-minus-03.rq | 6 + .../negation/sparql11-minus-03.srx | 24 + .../negation/sparql11-minus-05.rq | 8 + .../negation/sparql11-minus-05.srx | 20 + .../negation/sparql11-minus-06.rq | 9 + .../negation/sparql11-minus-06.srx | 28 + .../negation/sparql11-minus-07.rq | 10 + .../negation/sparql11-minus-07.srx | 28 + .../property-paths/data-01.ttl | 19 + .../property-paths/data-02.ttl | 28 + .../property-paths/data-03.ttl | 20 + .../property-paths/data-04.ttl | 9 + .../property-paths/data-05.ttl | 18 + .../property-paths/data-06.ttl | 4 + .../property-paths/data-07.ttl | 5 + .../property-paths/data-08.ttl | 7 + .../property-paths/data-09.ttl | 9 + .../property-paths/data-10.ttl | 4 + .../property-paths/data-11.ttl | 4 + .../property-paths/manifest.ttl | 228 + .../property-paths/sparql11-alternative-01.rq | 10 + .../sparql11-alternative-01.srx | 36 + .../property-paths/sparql11-alternative-02.rq | 10 + .../sparql11-alternative-02.srx | 44 + .../property-paths/sparql11-collection-01.rq | 9 + .../property-paths/sparql11-collection-01.srx | 34 + .../property-paths/sparql11-collection-02.srx | 34 + .../property-paths/sparql11-inverse-01.rq | 9 + .../property-paths/sparql11-inverse-01.srx | 16 + .../property-paths/sparql11-inverse-02.rq | 8 + .../property-paths/sparql11-inverse-02.srx | 16 + .../property-paths/sparql11-inverse-03.rq | 7 + .../property-paths/sparql11-inverse-03.srx | 16 + .../property-paths/sparql11-negated-01.rq | 3 + .../property-paths/sparql11-negated-01.srx | 26 + .../property-paths/sparql11-negated-02.rq | 8 + .../property-paths/sparql11-negated-02.srx | 26 + .../property-paths/sparql11-negated-03.rq | 7 + .../property-paths/sparql11-negated-03.srx | 26 + .../property-paths/sparql11-negated-04.rq | 7 + .../property-paths/sparql11-negated-04.srx | 26 + .../property-paths/sparql11-nested-01.rq | 7 + .../property-paths/sparql11-nested-01.srx | 16 + .../property-paths/sparql11-nested-02.rq | 7 + .../property-paths/sparql11-nested-02.srx | 27 + .../property-paths/sparql11-nested-03.rq | 7 + .../property-paths/sparql11-nested-03.srx | 22 + .../property-paths/sparql11-nested-04.rq | 7 + .../property-paths/sparql11-nested-04.srx | 34 + .../property-paths/sparql11-nested-05.rq | 6 + .../property-paths/sparql11-nested-05.srx | 50 + .../property-paths/sparql11-nested-06.rq | 6 + .../property-paths/sparql11-nested-06.srx | 34 + .../property-paths/sparql11-sequence-01.rq | 10 + .../property-paths/sparql11-sequence-01.srx | 36 + .../property-paths/sparql11-sequence-02.rq | 9 + .../property-paths/sparql11-sequence-02.srx | 28 + .../property-paths/sparql11-sequence-03.rq | 9 + .../property-paths/sparql11-sequence-03.srx | 36 + .../property-paths/sparql11-sequence-04.rq | 9 + .../property-paths/sparql11-sequence-04.srx | 124 + .../property-paths/sparql11-sequence-05.rq | 9 + .../property-paths/sparql11-sequence-05.srx | 60 + .../property-paths/sparql11-sequence-06.rq | 9 + .../property-paths/sparql11-sequence-06.srx | 124 + .../property-paths/sparql11-sequence-07.rq | 8 + .../property-paths/sparql11-sequence-07.srx | 108 + .../property-paths/sparql11-wildcard-01.rq | 7 + .../property-paths/sparql11-wildcard-01.srx | 132 + .../property-paths/sparql11-wildcard-02.rq | 7 + .../property-paths/sparql11-wildcard-02.srx | 180 + .../property-paths/sparql11-wildcard-03.rq | 7 + .../property-paths/sparql11-wildcard-03.srx | 19 + .../property-paths/sparql11-wildcard-04.rq | 7 + .../property-paths/sparql11-wildcard-04.srx | 19 + .../property-paths/sparql11-wildcard-05.rq | 7 + .../property-paths/sparql11-wildcard-05.srx | 10 + .../property-paths/sparql11-wildcard-06.rq | 7 + .../property-paths/sparql11-wildcard-06.srx | 14 + .../sparql11-wildcard-cycles-01.rq | 3 + .../sparql11-wildcard-cycles-01.srx | 18 + .../sparql11-wildcard-cycles-02.srx | 138 + .../sparql11-wildcard-cycles-03.rq | 6 + .../sparql11-wildcard-cycles-03.srx | 113 + .../sparql11-wildcard-cycles-04.rq | 3 + .../sparql11-wildcard-cycles-04.srx | 23 + .../sparql11-wildcard-reflexive-01.rq | 3 + .../sparql11-wildcard-reflexive-01.srx | 13 + .../testcases-sparql-1.1/subquery/data-01.ttl | 8 + .../testcases-sparql-1.1/subquery/data-02.ttl | 5 + .../testcases-sparql-1.1/subquery/data-03.ttl | 6 + .../testcases-sparql-1.1/subquery/data-04.ttl | 5 + .../subquery/manifest.ttl | 55 + .../subquery/sparql11-count-subquery-01.rq | 4 + .../subquery/sparql11-count-subquery-01.srx | 14 + .../subquery/sparql11-subquery-01.rq | 11 + .../subquery/sparql11-subquery-01.srx | 20 + .../subquery/sparql11-subquery-02.rq | 1 + .../subquery/sparql11-subquery-02.srx | 44 + .../subquery/sparql11-subquery-03.rq | 14 + .../subquery/sparql11-subquery-03.srx | 11 + .../subquery/sparql11-subquery-04.rq | 14 + .../subquery/sparql11-subquery-04.srx | 19 + .../subquery/sparql11-subquery-05.rq | 11 + .../subquery/sparql11-subquery-05.srx | 38 + .../subquery/sparql11-subquery-06.rq | 12 + .../subquery/sparql11-subquery-06.srx | 42 + .../resources/testdata-query/alp-testdata.ttl | 13 + .../testdata-query/dataset-describe.trig | 30 + .../testdata-query/dataset-query.trig | 84 + .../testdata-query/dataset-ses1081.trig | 6 + .../testdata-query/dataset-ses1121.trig | 12 + .../testdata-query/dataset-ses1692.trig | 11 + .../testdata-query/dataset-ses1898.trig | 7 + .../testdata-query/dataset-ses1913.trig | 8 + .../testdata-query/dataset-ses1970.trig | 11 + .../testdata-query/dataset-ses2024.trig | 10 + .../resources/testdata-query/defaultgraph.ttl | 21 + .../main/resources/testdata-query/graph1.ttl | 15 + .../main/resources/testdata-query/graph2.ttl | 11 + .../dataset-update-example9.trig | 17 + .../testdata-update/dataset-update.trig | 28 + testsuites/store/pom.xml | 47 + .../repository/CascadeValueExceptionTest.java | 258 + .../rdf4j/repository/EquivalentTest.java | 313 + .../repository/GraphQueryResultTest.java | 188 + .../repository/OptimisticIsolationTest.java | 98 + .../RDFSchemaRepositoryConnectionTest.java | 198 + .../repository/RepositoryConnectionTest.java | 2259 + .../rdf4j/repository/RepositoryTest.java | 144 + .../repository/SparqlAggregatesTest.java | 182 + .../rdf4j/repository/SparqlDatasetTest.java | 186 + .../rdf4j/repository/SparqlOrderByTest.java | 138 + .../rdf4j/repository/SparqlRegexTest.java | 161 + .../repository/SparqlSetBindingTest.java | 128 + .../repository/TupleQueryResultTest.java | 201 + .../repository/optimistic/DeadLockTest.java | 99 + .../optimistic/DeleteInsertTest.java | 53 + .../repository/optimistic/LinearTest.java | 346 + .../optimistic/ModificationTest.java | 162 + .../repository/optimistic/MonotonicTest.java | 736 + .../optimistic/RemoveIsolationTest.java | 85 + .../optimistic/SailIsolationLevelTest.java | 646 + .../optimistic/SerializableTest.java | 619 + .../repository/optimistic/SnapshotTest.java | 801 + .../sail/CustomGraphQueryInferencerTest.java | 183 + .../eclipse/rdf4j/sail/InferencingTest.java | 296 + .../rdf4j/sail/RDFNotifyingStoreTest.java | 117 + .../org/eclipse/rdf4j/sail/RDFStoreTest.java | 1126 + .../rdf4j/sail/SailConcurrencyTest.java | 201 + .../eclipse/rdf4j/sail/SailInterruptTest.java | 132 + .../rdf4j/sail/SailIsolationLevelTest.java | 680 + .../predicate-serql/delete.ru | 10 + .../predicate-serql/initial.ttl | 4 + .../predicate-serql/match.rq | 6 + .../predicate-serql/rule.rq | 6 + .../predicate/delete.ru | 10 + .../predicate/initial.ttl | 4 + .../predicate/match.rq | 10 + .../predicate/rule.rq | 10 + .../resource/delete.ru | 10 + .../resource/initial.ttl | 4 + .../resource/match.rq | 10 + .../custom-query-inferencing/resource/rule.rq | 12 + .../resources/testcases/default-graph-1.ttl | 9 + .../resources/testcases/default-graph.ttl | 9 + .../resources/testcases/default-graph.ttl.gz | Bin 0 -> 222 bytes .../src/main/resources/testcases/graph1.ttl | 8 + .../src/main/resources/testcases/graph2.ttl | 8 + .../src/main/resources/testcases/graph3.ttl | 13 + .../src/main/resources/testcases/graphs.zip | Bin 0 -> 917 bytes .../testcases/malformed-literals.ttl | 9 + .../rdf-mt-inferencing/domain/error001-in.nt | 7 + .../rdf-mt-inferencing/domain/error001-out.nt | 3 + .../rdf-mt-inferencing/domain/test001-in.nt | 9 + .../rdf-mt-inferencing/domain/test001-out.nt | 4 + .../rdf-mt-inferencing/range/error001-in.nt | 7 + .../rdf-mt-inferencing/range/error001-out.nt | 3 + .../rdf-mt-inferencing/range/test001-in.nt | 9 + .../rdf-mt-inferencing/range/test001-out.nt | 4 + .../subclassof/error001-in.nt | 9 + .../subclassof/error001-out.nt | 4 + .../subclassof/test001-in.nt | 9 + .../subclassof/test001-out.nt | 4 + .../subclassof/test002-in.nt | 7 + .../subclassof/test002-out.nt | 4 + .../subclassof/test003-in.nt | 7 + .../subclassof/test003-out.nt | 4 + .../subpropertyof/error001-in.nt | 7 + .../subpropertyof/error001-out.nt | 3 + .../subpropertyof/test001-in.nt | 7 + .../subpropertyof/test001-out.nt | 3 + .../subpropertyof/test002-in.nt | 6 + .../subpropertyof/test002-out.nt | 3 + .../subpropertyof/test003-in.nt | 8 + .../subpropertyof/test003-out.nt | 3 + .../rdf-mt-inferencing/type/error001-in.nt | 11 + .../rdf-mt-inferencing/type/error001-out.nt | 3 + .../rdf-mt-inferencing/type/error002-in.nt | 10 + .../rdf-mt-inferencing/type/error002-out.nt | 6 + .../rdf-mt-inferencing/type/test001-in.nt | 9 + .../rdf-mt-inferencing/type/test001-out.nt | 7 + .../rdf-mt-inferencing/type/test002-in.nt | 11 + .../rdf-mt-inferencing/type/test002-out.nt | 4 + .../rdf-mt-inferencing/type/test003-in.nt | 8 + .../rdf-mt-inferencing/type/test003-out.nt | 4 + .../rdf-mt-inferencing/type/test004-in.nt | 7 + .../rdf-mt-inferencing/type/test004-out.nt | 4 + .../rdf-mt-inferencing/type/test005-in.nt | 9 + .../rdf-mt-inferencing/type/test005-out.nt | 4 + 3029 files changed, 442981 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 about.html create mode 100644 bom/pom.xml create mode 100644 compliance/geosparql/pom.xml create mode 100644 compliance/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/geosparql/MemoryGeoSPARQLQueryTest.java create mode 100644 compliance/http/pom.xml create mode 100644 compliance/http/src/test/java/org/eclipse/rdf4j/http/server/ProtocolTest.java create mode 100644 compliance/http/src/test/java/org/eclipse/rdf4j/http/server/TestServer.java create mode 100644 compliance/http/src/test/resources/log4j.properties create mode 100644 compliance/http/src/test/resources/logback-test.xml create mode 100644 compliance/http/src/test/resources/testcases/default-graph-1.ttl create mode 100644 compliance/http/src/test/resources/testcases/named-graph-1.ttl create mode 100644 compliance/model/pom.xml create mode 100644 compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelEqualityTest.java create mode 100644 compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelNamespacesTest.java create mode 100644 compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelTest.java create mode 100644 compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelWithValueFactoryTest.java create mode 100644 compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelNamespacesTest.java create mode 100644 compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelTest.java create mode 100644 compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelEqualityTest.java create mode 100644 compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelNamespacesTest.java create mode 100644 compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelTest.java create mode 100644 compliance/model/src/test/resources/logback-test.xml create mode 100644 compliance/pom.xml create mode 100644 compliance/queryresultio/pom.xml create mode 100644 compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/binary/SPARQLBinaryTupleTest.java create mode 100644 compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLJSONBooleanTest.java create mode 100644 compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLJSONTupleTest.java create mode 100644 compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLXMLBooleanTest.java create mode 100644 compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLXMLTupleTest.java create mode 100644 compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/SPARQLTextBooleanTest.java create mode 100644 compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/csv/SPARQLCSVTupleTest.java create mode 100644 compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLTSVCustomTest.java create mode 100644 compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLTSVTupleTest.java create mode 100644 compliance/queryresultio/src/test/resources/logback-test.xml create mode 100644 compliance/queryresultio/src/test/resources/sparqljson/bindings1.srj create mode 100644 compliance/queryresultio/src/test/resources/sparqljson/bindings2.srj create mode 100644 compliance/queryresultio/src/test/resources/sparqljson/boolean1.srj create mode 100644 compliance/queryresultio/src/test/resources/sparqljson/boolean2.srj create mode 100644 compliance/queryresultio/src/test/resources/sparqljson/boolean3.srj create mode 100644 compliance/queryresultio/src/test/resources/sparqljson/boolean4.srj create mode 100644 compliance/queryresultio/src/test/resources/sparqljson/non-standard-distinct-ordered.srj create mode 100644 compliance/queryresultio/src/test/resources/sparqljson/non-standard-distinct.srj create mode 100644 compliance/queryresultio/src/test/resources/sparqljson/non-standard-ordered.srj create mode 100644 compliance/rio/pom.xml create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/binary/BinaryHandlingTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/binary/BinaryRDFWriterTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/DBPediaCelsiusDatatypeHandlerTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/RDFLangStringDatatypeHandlerTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/VirtuosoGeometryPointDatatypeHandlerTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/XMLSchemaDoubleDatatypeHandlerTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelperTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserHandlerTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/n3/N3ParserTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsEarlReport.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsHandlingTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsParserTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsParserUnitTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsWriterTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesEarlReport.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesHandlingTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParserTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParserUnitTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesWriterTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONHandlingTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONMimeTypeTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserCustomTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONWriterTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLHandlingTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserCustomTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLPrettyWriterTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLWriterTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGEarlReport.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGHandlingTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGParserCustomTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGParserTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGWriterTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/CustomTurtleParserTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleEarlReport.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleHandlingTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleMimeTypeTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleParserTest.java create mode 100644 compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleWriterTest.java create mode 100644 compliance/rio/src/test/resources/logback-test.xml create mode 100644 compliance/serql/pom.xml create mode 100644 compliance/serql/src/test/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParserTest.java create mode 100644 compliance/serql/src/test/java/org/eclipse/rdf4j/query/parser/serql/SeRQLQueryTest.java create mode 100644 compliance/serql/src/test/resources/logback-test.xml create mode 100644 compliance/sparql/pom.xml create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/ArbitraryLengthPathTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemoryComplexSPARQLQueryTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemorySPARQLUpdateTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLEmbeddedServer.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLServiceEvaluationTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/CoreSPARQLSyntaxTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/EarlReport.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/MemorySPARQLQueryTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11QueryTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11SyntaxTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11UpdateTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSparqlTest.java create mode 100644 compliance/sparql/src/test/resources/logback-test.xml create mode 100644 compliance/store/pom.xml create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPMemServer.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPRepositoryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlDatasetTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlSetBindingTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlUpdateTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPStoreConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/RDFSchemaHTTPRepositoryConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/CustomGraphQueryInferencerMemoryRepositoryConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryCascadeValueExceptionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryGraphQueryResultTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryOptimisticIsolationTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySPARQLQueryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySeRQLQueryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlAggregatesTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlDatasetTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlOrderByTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlRegexTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlSetBindingTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryStoreConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryStoreRepositoryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryTupleQueryResultTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/RDFSchemaMemoryRepositoryConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/CustomGraphQueryInferencerNativeRepositoryConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/LimitedSizeNativeStoreConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeCascadeValueExceptionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeComplexSPARQLQueryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeGraphQueryResultTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeOptimisticIsolationTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSPARQLQueryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSeRQLQueryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSparqlOrderByTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSparqlRegexTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeStoreConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeStoreRepositoryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeTupleQueryResultTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/RDFSchemaNativeRepositoryConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/TestNativeStoreMemoryOverflow.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/MySqlSPARQL11QueryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/MySqlStoreConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/PgSqlSPARQL11QueryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/PgSqlStoreConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLGraphQueryResultTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLRepositorySparqlUpdateTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLRepositoryTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLServiceEvaluationTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLStoreConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/federation/FederationConnectionTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/federation/FederationTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionWrapperTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemCustomInferencingTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemInferencingTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreConcurrencyTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreIsolationLevelTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/PersistentMemoryStoreTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/StoreSerializationTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConcurrencyTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConsistencyTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreContextTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreCustomInferencingTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreDirLockTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInferencingTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInterruptTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreIsolationLevelTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataStorePerfTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/measurements.txt create mode 100644 compliance/store/src/test/resources/log4j.properties create mode 100644 compliance/store/src/test/resources/logback-test.xml create mode 100755 compliance/store/src/test/resources/nativestore-testdata/SES-1867/initialState.nq create mode 100755 compliance/store/src/test/resources/nativestore-testdata/SES-1867/newTriples.nt create mode 100644 compliance/store/src/test/resources/test/ask.rq create mode 100644 compliance/store/src/test/resources/test/delete-insert.ru create mode 100644 compliance/store/src/test/resources/test/insert-data.ru create mode 100644 core/assembly/pom.xml create mode 100644 core/assembly/src/main/assembly/sdk.xml create mode 100644 core/assembly/src/main/dist/bin/console.bat create mode 100644 core/assembly/src/main/dist/bin/console.sh create mode 100644 core/config/pom.xml create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/Sesame.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/AppConfiguration.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/AppVersion.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/config/Configuration.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/LogConfiguration.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/AbstractLogConfiguration.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/LogConfigurationBase.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/LogConverterHandler.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/logback/LogConfigurator.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/logback/LogbackConfiguration.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/net/ProxySettings.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/app/util/ConfigurationUtil.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogLevel.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogReader.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogRecord.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/AbstractLogReader.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/LogReaderBase.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/LogRecordBase.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/SimpleLogRecord.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/FileLogReader.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/MultipleFileLogReader.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/StackTracePatternLayout.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/AbstractPlatform.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/DefaultPlatform.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/Platform.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/PlatformBase.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/PlatformFactory.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/ProcessLauncher.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/MacOSXPlatform.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixGnomePlatform.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixKDEPlatform.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixPlatform.java create mode 100644 core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/WindowsPlatform.java create mode 100644 core/config/src/main/resources/info/aduna/app/config/defaults/application.properties create mode 100644 core/config/src/main/resources/info/aduna/app/config/defaults/logback.xml create mode 100644 core/config/src/main/resources/info/aduna/app/config/defaults/logging.properties create mode 100644 core/config/src/main/resources/info/aduna/app/config/defaults/proxy.properties create mode 100644 core/config/src/test/java/org/eclipse/rdf4j/common/app/AppVersionTest.java create mode 100644 core/console/pom.xml create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Clear.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Close.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Command.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Connect.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Console.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleIO.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleParameters.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleState.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Create.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Disconnect.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Drop.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Federate.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Load.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/LockRemover.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Open.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/PrintHelp.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/PrintInfo.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/QueryEvaluator.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/SetParameters.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Show.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/TupleAndGraphQueryEvaluator.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/VerificationLIstener.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/Verify.java create mode 100644 core/console/src/main/java/org/eclipse/rdf4j/console/package.html create mode 100644 core/console/src/test/java/org/eclipse/rdf4j/console/AbstractCommandTest.java create mode 100644 core/console/src/test/java/org/eclipse/rdf4j/console/ConsoleIOTest.java create mode 100644 core/console/src/test/java/org/eclipse/rdf4j/console/DropTest.java create mode 100644 core/console/src/test/java/org/eclipse/rdf4j/console/FederateTest.java create mode 100644 core/console/src/test/java/org/eclipse/rdf4j/console/package-info.java create mode 100644 core/console/src/test/resources/federate/alien-config.ttl create mode 100644 core/console/src/test/resources/federate/alien.ttl create mode 100644 core/console/src/test/resources/federate/http-config.ttl create mode 100644 core/console/src/test/resources/federate/http2-config.ttl create mode 100644 core/console/src/test/resources/federate/scary-config.ttl create mode 100644 core/console/src/test/resources/federate/scary.ttl create mode 100644 core/console/src/test/resources/federate/sparql-config.ttl create mode 100644 core/console/src/test/resources/federate/sparql2-config.ttl create mode 100644 core/console/src/test/resources/logback-test.xml create mode 100644 core/http/client/pom.xml create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/BackgroundGraphResult.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/BackgroundTupleResult.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/HttpClientDependent.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/QueueCursor.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClient.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClientDependent.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClientImpl.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameSession.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SparqlSession.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/query/AbstractHTTPQuery.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/query/AbstractHTTPUpdate.java create mode 100644 core/http/client/src/main/java/org/eclipse/rdf4j/http/client/util/HttpClientBuilders.java create mode 100644 core/http/client/src/test/java/org/eclipse/rdf4j/http/client/BackgroundGraphResultHangTest.java create mode 100644 core/http/client/src/test/java/org/eclipse/rdf4j/http/client/SesameHTTPClientTest.java create mode 100644 core/http/pom.xml create mode 100644 core/http/protocol/pom.xml create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/Protocol.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/UnauthorizedException.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/error/ErrorInfo.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/error/ErrorType.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionReader.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionSAXParser.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionWriter.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionXMLConstants.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/AddStatementOperation.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ClearNamespacesOperation.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ClearOperation.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ContextOperation.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/RemoveNamespaceOperation.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/RemoveStatementsOperation.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/SPARQLUpdateOperation.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/SetNamespaceOperation.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/StatementOperation.java create mode 100644 core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/TransactionOperation.java create mode 100644 core/http/protocol/src/test/java/org/eclipse/rdf4j/http/protocol/ProtocolTest.java create mode 100644 core/http/protocol/src/test/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionReaderTest.java create mode 100644 core/http/server-spring/pom.xml create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/CommonValuesHandlerInterceptor.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/Message.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/MessageHandlerInterceptor.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/filters/PathFilter.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/AbstractNavigationNode.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/Group.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationHandlerInterceptor.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationModel.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationNode.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationNodeBase.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationXmlParser.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/View.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/functions/NavigationFunctions.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/SystemInfoController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/SystemOverviewController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/logging/LoggingOverviewController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/proxy/ProxySettingsController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/HeaderElement.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/HttpServerUtil.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/Parameter.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/EmptySuccessView.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/SimpleCustomResponseView.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/SimpleResponseView.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ClientHTTPException.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/HTTPException.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ProtocolExceptionResolver.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ProtocolUtil.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ServerHTTPException.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ServerInterceptor.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/protocol/ProtocolController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/protocol/ProtocolInterceptor.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/BooleanQueryResultView.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/GraphQueryResultView.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/QueryResultView.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryInterceptor.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryListController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/TupleQueryResultView.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/contexts/ContextsController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/graph/GraphController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/namespaces/NamespaceController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/namespaces/NamespacesController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/size/SizeController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/statements/ExportStatementsView.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/statements/StatementsController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/ActiveTransactionRegistry.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionController.java create mode 100644 core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionStartController.java create mode 100644 core/http/server-spring/src/test/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationTest.java create mode 100644 core/http/server-spring/src/test/java/org/eclipse/rdf4j/common/webapp/util/HttpServerUtilTest.java create mode 100644 core/http/server-spring/src/test/resources/navigation.xml create mode 100644 core/http/server/.springBeans create mode 100644 core/http/server/pom.xml create mode 100644 core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/messages.properties create mode 100644 core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/navigation.xml create mode 100644 core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/system/messages.properties create mode 100644 core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/system/navigation.xml create mode 100644 core/http/server/src/main/resources/org/eclipse/rdf4j/http/server/messages.properties create mode 100644 core/http/server/src/main/resources/org/eclipse/rdf4j/http/server/navigation.xml create mode 100644 core/http/server/src/main/webapp/WEB-INF/classes/logback.xml create mode 100644 core/http/server/src/main/webapp/WEB-INF/common-webapp-servlet.xml create mode 100644 core/http/server/src/main/webapp/WEB-INF/common-webapp-system-servlet.xml create mode 100644 core/http/server/src/main/webapp/WEB-INF/glassfish-web.xml create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/ContentHeader.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/Footer.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/Header.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/Message.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/Navigation.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/bodyStart.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/bodyStop.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/head.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/htmlStart.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/htmlStop.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/logfilterform.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/logpaginationfooter.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/logpaginationheader.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/page.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/components/tabs.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/stylesheets.html.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/includes/taglibs.jspf create mode 100644 core/http/server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml create mode 100644 core/http/server/src/main/webapp/WEB-INF/rdf4j-http-server-servlet.xml create mode 100644 core/http/server/src/main/webapp/WEB-INF/sample-web.xml create mode 100644 core/http/server/src/main/webapp/WEB-INF/taglibs/navigation.tld create mode 100644 core/http/server/src/main/webapp/WEB-INF/tags/errors.tag create mode 100644 core/http/server/src/main/webapp/WEB-INF/urlrewrite.xml create mode 100644 core/http/server/src/main/webapp/WEB-INF/views/home/overview.jsp create mode 100644 core/http/server/src/main/webapp/WEB-INF/views/overview.jsp create mode 100644 core/http/server/src/main/webapp/WEB-INF/views/system/info/debug.jsp create mode 100644 core/http/server/src/main/webapp/WEB-INF/views/system/info/overview.jsp create mode 100644 core/http/server/src/main/webapp/WEB-INF/views/system/logging/overview.jsp create mode 100644 core/http/server/src/main/webapp/WEB-INF/views/system/overview.jsp create mode 100644 core/http/server/src/main/webapp/WEB-INF/web.xml create mode 100644 core/http/server/src/main/webapp/favicon.ico create mode 100644 core/http/server/src/main/webapp/favicon.png create mode 100644 core/http/server/src/main/webapp/images/DEBUG.png create mode 100644 core/http/server/src/main/webapp/images/ERROR.png create mode 100644 core/http/server/src/main/webapp/images/INFO.png create mode 100644 core/http/server/src/main/webapp/images/WARN.png create mode 100644 core/http/server/src/main/webapp/images/productgroup.png create mode 100644 core/http/server/src/main/webapp/images/transparent.png create mode 100644 core/http/server/src/main/webapp/styles/basic/all.css create mode 100644 core/http/server/src/main/webapp/styles/default/images/bg_body.png create mode 100644 core/http/server/src/main/webapp/styles/default/images/bg_header.png create mode 100644 core/http/server/src/main/webapp/styles/default/images/bg_html.png create mode 100644 core/http/server/src/main/webapp/styles/default/images/hr_menu.png create mode 100644 core/http/server/src/main/webapp/styles/default/msie-minheight.css create mode 100644 core/http/server/src/main/webapp/styles/default/print.css create mode 100644 core/http/server/src/main/webapp/styles/default/screen.css create mode 100644 core/http/server/src/main/webapp/styles/w3-html40-recommended.css create mode 100644 core/http/server/src/test/java/org/eclipse/rdf4j/http/server/WebXmlValidationTest.java create mode 100755 core/http/workbench/compileTypescript.sh create mode 100755 core/http/workbench/deployTypeScriptVersion create mode 100644 core/http/workbench/pom.xml create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/RepositoryServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/AbstractRepositoryServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/AbstractServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/BaseRepositoryServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/BaseServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/TransformationServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/TupleServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/AddServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ClearServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ContextsServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/CreateServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/DeleteServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ExploreServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ExportServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/InfoServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/InformationServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/NamespacesServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/QueryServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/RemoveServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/RepositoriesServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/SavedQueriesServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/SummaryServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/TypesServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/UpdateServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/exceptions/BadRequestException.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/exceptions/MissingInitParameterException.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CacheFilter.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CookieCacheControlFilter.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CookieHandler.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/ProxyRepositoryServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/RedirectFilter.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/ServerValidator.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/WorkbenchGateway.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/WorkbenchServlet.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/BasicServletConfig.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/CookieHandler.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/DynamicHttpRequest.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/PagedQuery.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryEvaluator.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryFactory.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryStorage.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryStringBuilder.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/TupleResultBuilder.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/ValueDecoder.java create mode 100644 core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/WorkbenchRequest.java create mode 100644 core/http/workbench/src/main/webapp/WEB-INF/glassfish-web.xml create mode 100644 core/http/workbench/src/main/webapp/WEB-INF/web.xml create mode 100644 core/http/workbench/src/main/webapp/favicon.ico create mode 100644 core/http/workbench/src/main/webapp/favicon.png create mode 100644 core/http/workbench/src/main/webapp/images/affirmative.png create mode 100644 core/http/workbench/src/main/webapp/images/bookmark.png create mode 100644 core/http/workbench/src/main/webapp/images/cancel.png create mode 100644 core/http/workbench/src/main/webapp/images/edit.png create mode 100644 core/http/workbench/src/main/webapp/images/external.png create mode 100644 core/http/workbench/src/main/webapp/images/negative.png create mode 100644 core/http/workbench/src/main/webapp/images/productgroup.png create mode 100644 core/http/workbench/src/main/webapp/images/server.png create mode 100644 core/http/workbench/src/main/webapp/images/server_network.png create mode 100644 core/http/workbench/src/main/webapp/images/view.png create mode 100644 core/http/workbench/src/main/webapp/locale/messages.xsl create mode 100644 core/http/workbench/src/main/webapp/scripts/add.js create mode 100644 core/http/workbench/src/main/webapp/scripts/add.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/cookies.html create mode 100644 core/http/workbench/src/main/webapp/scripts/create-federate.js create mode 100644 core/http/workbench/src/main/webapp/scripts/create-federate.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/create.js create mode 100644 core/http/workbench/src/main/webapp/scripts/create.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/delete.js create mode 100644 core/http/workbench/src/main/webapp/scripts/delete.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/explore.js create mode 100644 core/http/workbench/src/main/webapp/scripts/explore.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/export.js create mode 100644 core/http/workbench/src/main/webapp/scripts/export.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/namespaces.js create mode 100644 core/http/workbench/src/main/webapp/scripts/namespaces.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/paging.js create mode 100644 core/http/workbench/src/main/webapp/scripts/paging.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/query.js create mode 100644 core/http/workbench/src/main/webapp/scripts/query.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/saved-queries.js create mode 100644 core/http/workbench/src/main/webapp/scripts/saved-queries.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/template.js create mode 100644 core/http/workbench/src/main/webapp/scripts/template.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/add.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/create-federate.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/create.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/delete.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/explore.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/export.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/namespaces.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/paging.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/query.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/saved-queries.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/template.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/tuple.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/ts/update.ts create mode 100644 core/http/workbench/src/main/webapp/scripts/tuple.js create mode 100644 core/http/workbench/src/main/webapp/scripts/tuple.js.map create mode 100644 core/http/workbench/src/main/webapp/scripts/update.js create mode 100644 core/http/workbench/src/main/webapp/scripts/update.js.map create mode 100644 core/http/workbench/src/main/webapp/styles/basic/all.css create mode 100644 core/http/workbench/src/main/webapp/styles/default/images/hr_menu.png create mode 100644 core/http/workbench/src/main/webapp/styles/default/print.css create mode 100644 core/http/workbench/src/main/webapp/styles/default/screen.css create mode 100644 core/http/workbench/src/main/webapp/styles/w3-html40-recommended.css create mode 100644 core/http/workbench/src/main/webapp/styles/yasqe.min.css create mode 100644 core/http/workbench/src/main/webapp/transformations/add.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/boolean.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/clear.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/contexts.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-federate.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-memory-customrule.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-memory-rdfs-dt.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-memory-rdfs.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-memory.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-native-customrule.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-native-rdfs-dt.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-native-rdfs.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-native.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-remote.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create-sparql.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/create.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/delete.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/explore.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/export.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/graph.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/information.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/list.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/namespaces.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/query.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/remove.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/repositories.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/saved-queries.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/server.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/summary.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/table.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/template.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/tuple.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/types.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/update.xsl create mode 100644 core/http/workbench/src/main/webapp/transformations/url-encode.xsl create mode 100644 core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestCreateServlet.java create mode 100644 core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestExploreServlet.java create mode 100644 core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestInfoServlet.java create mode 100644 core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestQueryServlet.java create mode 100644 core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestRemoveServlet.java create mode 100644 core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestPagedQuery.java create mode 100644 core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestTupleResultBuilder.java create mode 100644 core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestValueDecoder.java create mode 100644 core/http/workbench/src/test/resources/long.rq create mode 100644 core/http/workbench/src/test/resources/ses2307.rq create mode 100644 core/model/pom.xml create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/IsolationLevel.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/IsolationLevels.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/OpenRDFException.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/OpenRDFUtil.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/BNode.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/Graph.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/IRI.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/Literal.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/Model.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/ModelFactory.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/Namespace.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/Resource.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/Statement.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/URI.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/Value.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/ValueFactory.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtil.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDateTime.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/AbstractModel.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/AbstractValueFactory.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/BNodeImpl.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/BooleanLiteral.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/CalendarLiteral.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/ContextStatement.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/ContextStatementImpl.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/DecimalLiteral.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/EmptyModel.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/FilteredModel.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/GraphImpl.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/IntegerLiteral.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/LinkedHashModel.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/LinkedHashModelFactory.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/LiteralImpl.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/NamespaceImpl.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/NumericLiteral.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleBNode.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleIRI.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleLiteral.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleNamespace.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleStatement.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleValueFactory.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/StatementImpl.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/TreeModel.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/TreeModelFactory.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/URIImpl.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/UnmodifiableModel.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValueFactoryBase.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValueFactoryImpl.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/impl/package.html create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/package.html create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphUtil.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphUtilException.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/LexicalValueComparator.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/LiteralUtil.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/LiteralUtilException.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/Literals.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelException.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelUtil.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/Models.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/Namespaces.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/PatternIterator.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/URIUtil.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/language/IanaLanguageTag.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/language/Iso3166.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/language/Iso639.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTag.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTagCodes.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTagSyntaxException.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DC.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DCTERMS.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DOAP.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/EARL.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/FN.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/FOAF.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEO.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEOF.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/OWL.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDF.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDFS.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SD.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SESAME.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SESAMEQNAME.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SKOS.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SP.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SPIN.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/XMLSchema.java create mode 100644 core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/package.html create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/IsolationLevelsTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/AbstractModelPerformanceTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/AbstractModelTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelPerformanceTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/TreeModelPerformanceTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/TreeModelTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/ValueFactoryTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/datatypes/DateTimeTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtilTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/impl/ContextStatementTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/impl/SimpleLiteralTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/util/LiteralsTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/util/ModelsTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/util/NamespacesTest.java create mode 100644 core/model/src/test/java/org/eclipse/rdf4j/model/util/URIUtilTest.java create mode 100644 core/pom.xml create mode 100644 core/query/pom.xml create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/AbstractTupleQueryResultHandler.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/Binding.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/BindingSet.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQuery.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQueryResultHandler.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQueryResultHandlerException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/Dataset.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/GraphQuery.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/GraphQueryResult.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/IncompatibleOperationException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/MalformedQueryException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/Operation.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/Query.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/QueryEvaluationException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/QueryInterruptedException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/QueryLanguage.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/QueryResult.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultHandler.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultHandlerException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultUtil.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/QueryResults.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/TupleQuery.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResult.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandler.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandlerBase.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandlerException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/UnsupportedQueryLanguageException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/Update.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/UpdateExecutionException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestBooleanParser.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetParseException.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetParser.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetSchema.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetUtil.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetWriter.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/dawg/package.html create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractOperation.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractQuery.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractUpdate.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/BindingImpl.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/DatasetImpl.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/EmptyBindingSet.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/FallbackDataset.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/GraphQueryResultImpl.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/IteratingGraphQueryResult.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/IteratingTupleQueryResult.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/ListBindingSet.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/MapBindingSet.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/MutableTupleQueryResult.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/SimpleBinding.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/SimpleDataset.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/TupleQueryResultBuilder.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/impl/TupleQueryResultImpl.java create mode 100644 core/query/src/main/java/org/eclipse/rdf4j/query/package.html create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/AllTests.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/CloseableIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/CloseableIteratorIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/ConvertingIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DelayedIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctIntersectionIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctMinusIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/EmptyIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/ExceptionConvertingIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/FilterIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IntersectionIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IteratorIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/LimitIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/LookAheadIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/MinusIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/OffsetIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/SingletonIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/common/iteration/UnionIterationTest.java create mode 100644 core/query/src/test/java/org/eclipse/rdf4j/query/QueryResultsTest.java create mode 100644 core/queryalgebra/evaluation/pom.xml create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategy.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryBindingSet.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryOptimizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/TripleSource.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ValueExprEvaluationException.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/AbstractFederatedServiceResolver.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverBase.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverImpl.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/JoinExecutorBase.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/RepositoryFederatedService.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/SPARQLFederatedService.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceCrossProductIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceFallbackIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceJoinConversionIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceJoinIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/BooleanCast.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DateTimeCast.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DecimalCast.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DoubleCast.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/FloatCast.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/Function.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/FunctionRegistry.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/IntegerCast.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/StringCast.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Day.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Hours.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Minutes.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Month.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Now.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Seconds.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Timezone.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Tz.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Year.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/HashFunction.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Abs.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Ceil.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Floor.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Rand.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Round.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/STRUUID.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrDt.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrLang.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/UUID.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/EncodeForUri.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCase.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Replace.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfter.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBefore.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrEnds.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrLen.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrStarts.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Substring.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCase.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/BindingAssigner.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/CompareOptimizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConjunctiveConstraintSplitter.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/DisjunctiveConstraintOptimizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EvaluationStatistics.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EvaluationStrategyImpl.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExternalSet.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/FilterOptimizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/IterativeEvaluationOptimizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/OrderLimitOptimizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelPruner.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SameTermFilterOptimizer.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SimpleEvaluationStrategy.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BadlyDesignedLeftJoinIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BindingSetHashKey.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BottomUpJoinIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CollectionIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CompatibleBindingSetFilter.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CrossProductIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/DescribeIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ExtensionIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/FilterIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/MultiProjectionIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/PathIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ProjectionIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SPARQLMinusIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SilentIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/LimitedSizeEvaluationStrategy.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeBottomUpJoinIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeDistinctIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeHashJoinIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeIntersectIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeIteratorUtil.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeOrderIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizePathIterator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeSPARQLMinusIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeZeroLengthPathIteration.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/EvaluationStrategies.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/MathUtil.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtil.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryOptimizerList.java create mode 100644 core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java create mode 100644 core/queryalgebra/evaluation/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestDateTimeCast.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestIntegerCast.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestStringCast.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/TimezoneTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/TzTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/HashFunctionTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5Test.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1Test.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256Test.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384Test.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512Test.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/RandTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/RoundTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCaseTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/RegexTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/ReplaceTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfterTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBeforeTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/SubstringTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCaseTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizerTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EmptyTripleSource.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizerTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BindingSetSize.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIterationTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/IterationStub.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIteratorTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIteratorTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SizeComparator.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/LiteralComparatorTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparatorTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtilTest.java create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparatorTest.java create mode 100644 core/queryalgebra/evaluation/src/test/resources/logback-test.xml create mode 100644 core/queryalgebra/geosparql/pom.xml create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Boundary.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Buffer.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/ConvexHull.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultSpatialAlgebra.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultWktWriter.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Difference.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Distance.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhContains.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhCoveredBy.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhCovers.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhDisjoint.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhEquals.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhInside.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhMeet.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhOverlap.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Envelope.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/FunctionArguments.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricBinaryFunction.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricRelationFunction.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricUnaryFunction.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Intersection.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8DC.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8EC.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8EQ.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8NTPP.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8NTPPI.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8PO.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8TPP.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8TPPI.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Relate.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SRID.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfContains.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfCrosses.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfDisjoint.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfEquals.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfIntersects.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfOverlaps.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfTouches.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfWithin.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SpatialAlgebra.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SpatialSupport.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SymmetricDifference.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Union.java create mode 100644 core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/WktWriter.java create mode 100644 core/queryalgebra/geosparql/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function create mode 100644 core/queryalgebra/model/pom.xml create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AbstractAggregateOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AbstractQueryModelNode.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Add.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AggregateOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AggregateOperatorBase.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/And.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ArbitraryLengthPath.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Avg.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BNodeGenerator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BinaryTupleOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BinaryValueOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BindingSetAssignment.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Bound.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Clear.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Coalesce.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Compare.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareAll.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareAny.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareSubQueryValueOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Copy.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Count.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Create.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Datatype.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/DeleteData.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/DescribeOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Difference.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Distinct.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/EmptySet.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Exists.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Extension.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ExtensionElem.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Filter.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/FunctionCall.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Group.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/GroupConcat.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/GroupElem.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IRIFunction.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/If.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/In.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/InsertData.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Intersection.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsBNode.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsLiteral.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsNumeric.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsResource.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsURI.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Join.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Label.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Lang.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LangMatches.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LeftJoin.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Like.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ListMemberOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Load.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LocalName.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/MathExpr.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Max.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Min.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Modify.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Move.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/MultiProjection.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/NAryValueOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Namespace.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Not.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Or.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Order.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/OrderElem.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Projection.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ProjectionElem.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ProjectionElemList.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelNode.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelNodeBase.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelVisitor.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryRoot.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Reduced.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Regex.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SameTerm.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Sample.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Service.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SingletonSet.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Slice.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/StatementPattern.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Str.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SubQueryValueOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Sum.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/TupleExpr.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UnaryTupleOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UnaryValueOperator.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Union.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UpdateExpr.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ValueConstant.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ValueExpr.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Var.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ZeroLengthPath.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedService.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolver.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverClient.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/AbstractQueryModelVisitor.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelNodeReplacer.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelTreePrinter.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelVisitorBase.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/StatementPatternCollector.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/TupleExprs.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/VarNameCollector.java create mode 100644 core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/package.html create mode 100644 core/queryalgebra/pom.xml create mode 100644 core/queryparser/api/pom.xml create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedBooleanQuery.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedGraphQuery.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedOperation.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedQuery.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedTupleQuery.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedUpdate.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParser.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserFactory.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserRegistry.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserUtil.java create mode 100644 core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryPrologLexer.java create mode 100644 core/queryparser/api/src/test/java/org/eclipse/rdf4j/query/parser/QueryParserUtilTest.java create mode 100644 core/queryparser/api/src/test/java/org/eclipse/rdf4j/query/parser/QueryPrologLexerTest.java create mode 100644 core/queryparser/pom.xml create mode 100644 core/queryparser/serql/pom.xml create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ASTVisitorBase.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/AbstractASTVisitor.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/AnonymousVarGenerator.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ConstructorBuilder.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/GraphPattern.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/NamespaceDeclProcessor.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/NullProcessor.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/OptionalTupleExpr.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ProjectionAliasProcessor.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ProjectionProcessor.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/QueryModelBuilder.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParser.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParserFactory.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLUtil.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/StringEscapesProcessor.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTAnd.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTArgList.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBNode.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBasicPathExpr.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBasicPathExprTail.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBooleanConstant.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBooleanExpr.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBound.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompOperator.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompare.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompareAll.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompareAny.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTConstruct.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTConstructQuery.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTDatatype.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTEdge.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTExists.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTFrom.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTFunctionCall.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphIntersect.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphMinus.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphQuery.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphQuerySet.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphUnion.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIn.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTInList.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsBNode.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsLiteral.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsResource.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsURI.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLabel.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLang.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLangMatches.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLike.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLimit.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLiteral.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLocalName.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNamespace.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNamespaceDecl.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNode.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNodeElem.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNot.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNull.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOffset.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOptPathExpr.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOptPathExprTail.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOr.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOrderBy.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOrderExpr.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExpr.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprList.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprTail.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprUnion.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTProjectionElem.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQName.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQuery.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQueryBody.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQueryContainer.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTRegex.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTReifiedStat.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSameTerm.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSelect.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSelectQuery.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTStr.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTString.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleIntersect.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleMinus.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleQuery.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleQuerySet.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleUnion.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTURI.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTValue.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTValueExpr.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTVar.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTWhere.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/CastingList.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/JJTSyntaxTreeBuilderState.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/Node.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ParseException.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SimpleCharStream.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SimpleNode.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilder.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderConstants.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderTokenManager.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderTreeConstants.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderVisitor.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/Token.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/TokenMgrError.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/VisitorException.java create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/serql.jjt create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/grammar.txt create mode 100644 core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/package.html create mode 100644 core/queryparser/serql/src/main/resources/META-INF/services/org.openrdf.query.parser.QueryParserFactory create mode 100644 core/queryparser/sparql/pom.xml create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ASTVisitorBase.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/AbstractASTVisitor.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/BaseDeclProcessor.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/BlankNodeVarProcessor.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ConstructorBuilder.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/DatasetDeclProcessor.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/GraphPattern.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/NegatedPropertySet.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/PrefixDeclProcessor.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/PropertySetElem.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLParser.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLParserFactory.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLUtil.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/StringEscapesProcessor.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilder.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/UpdateExprBuilder.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/WildcardProjectionProcessor.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/.gitignore create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTAbs.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTAdd.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTAggregate.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTAnd.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTAskQuery.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTAvg.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBNodeFunc.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBaseDecl.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBasicGraphPattern.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBind.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBindingSet.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBindingValue.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBindingsClause.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBlankNode.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBlankNodePropertyList.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTBound.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTCeil.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTClear.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTCoalesce.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTCollection.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTCompare.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTConcat.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTConstraint.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTConstruct.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTConstructQuery.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTContains.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTCopy.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTCount.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTCreate.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTDatasetClause.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTDatatype.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTDay.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTDeleteClause.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTDeleteData.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTDeleteWhere.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTDescribe.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTDescribeQuery.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTDrop.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTEncodeForURI.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTExistsFunc.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTFalse.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTFloor.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTFunctionCall.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTGraphGraphPattern.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTGraphOrDefault.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTGraphPatternGroup.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTGraphRefAll.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTGroupClause.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTGroupConcat.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTGroupCondition.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTHavingClause.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTHours.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTIRI.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTIRIFunc.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTIf.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTIn.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTInfix.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTInlineData.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTInsertClause.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTInsertData.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTIsBlank.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTIsIRI.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTIsLiteral.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTIsNumeric.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTLang.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTLangMatches.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTLimit.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTLoad.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTLowerCase.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTMD5.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTMath.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTMax.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTMin.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTMinusGraphPattern.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTMinutes.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTModify.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTMonth.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTMove.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTNot.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTNotExistsFunc.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTNotIn.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTNow.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTNumericLiteral.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTObjectList.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTOffset.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTOperation.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTOperationContainer.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTOptionalGraphPattern.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTOr.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTOrderClause.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTOrderCondition.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTPathAlternative.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTPathElt.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTPathMod.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTPathNegatedPropertySet.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTPathOneInPropertySet.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTPathSequence.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTPrefixDecl.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTProjectionElem.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTPropertyList.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTPropertyListPath.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTQName.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTQuadsNotTriples.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTQuery.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTQueryContainer.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTRDFLiteral.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTRDFValue.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTRand.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTRegexExpression.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTReplace.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTRound.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSHA1.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSHA224.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSHA256.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSHA384.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSHA512.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSTRUUID.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSameTerm.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSample.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSeconds.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSelect.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSelectQuery.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTServiceGraphPattern.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTStr.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTStrAfter.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTStrBefore.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTStrDt.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTStrEnds.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTStrLang.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTStrLen.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTStrStarts.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTString.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSubstr.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTSum.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTTimezone.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTTriplesSameSubject.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTTriplesSameSubjectPath.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTTrue.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTTz.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTUUID.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTUnionGraphPattern.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTUnparsedQuadDataBlock.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTUpdate.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTUpdateContainer.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTUpdateSequence.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTUpperCase.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTVar.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTWhereClause.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ASTYear.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/JJTSyntaxTreeBuilderState.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/JavaCharStream.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/Node.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/ParseException.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/SimpleNode.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/SyntaxTreeBuilder.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/SyntaxTreeBuilderConstants.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/SyntaxTreeBuilderTokenManager.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/SyntaxTreeBuilderTreeConstants.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/SyntaxTreeBuilderVisitor.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/Token.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/TokenMgrError.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/VisitorException.java create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ast/sparql.jjt create mode 100644 core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/package.html create mode 100644 core/queryparser/sparql/src/main/resources/META-INF/services/org.openrdf.query.parser.QueryParserFactory create mode 100644 core/queryparser/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLParserTest.java create mode 100644 core/queryparser/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilderTest.java create mode 100644 core/queryrender/pom.xml create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/BaseTupleExprRenderer.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/QueryRenderer.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/RenderUtils.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/AbstractQueryBuilder.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/BasicGroup.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/FilterBuilder.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/Group.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/GroupBuilder.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/QueryBuilder.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/QueryBuilderFactory.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/SupportsExpr.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/SupportsGroups.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/UnionBuilder.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/builder/ValueExprFactory.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/package-info.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/serql/SeRQLQueryRenderer.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/serql/SerqlTupleExprRenderer.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/serql/SerqlValueExprRenderer.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/sparql/ContextCollector.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/sparql/SPARQLQueryRenderer.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/sparql/SparqlTupleExprRenderer.java create mode 100644 core/queryrender/src/main/java/org/eclipse/rdf4j/queryrender/sparql/SparqlValueExprRenderer.java create mode 100644 core/queryresultio/api/pom.xml create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/AbstractQueryResultParser.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/AbstractQueryResultWriter.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/AbstractTupleQueryResultParser.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/BasicQueryWriterSettings.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/BooleanQueryResultFormat.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/BooleanQueryResultParser.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/BooleanQueryResultParserFactory.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/BooleanQueryResultParserRegistry.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/BooleanQueryResultWriter.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/BooleanQueryResultWriterFactory.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/BooleanQueryResultWriterRegistry.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/QueryResultFormat.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/QueryResultIO.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/QueryResultParseException.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/QueryResultParser.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/QueryResultParserBase.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/QueryResultWriter.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/QueryResultWriterBase.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/TupleQueryResultFormat.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/TupleQueryResultParser.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/TupleQueryResultParserBase.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/TupleQueryResultParserFactory.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/TupleQueryResultParserRegistry.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/TupleQueryResultWriter.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/TupleQueryResultWriterFactory.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/TupleQueryResultWriterRegistry.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/UnsupportedQueryResultFormatException.java create mode 100644 core/queryresultio/api/src/main/java/org/eclipse/rdf4j/query/resultio/helpers/QueryResultCollector.java create mode 100644 core/queryresultio/binary/pom.xml create mode 100644 core/queryresultio/binary/src/main/java/org/eclipse/rdf4j/query/resultio/binary/BinaryQueryResultConstants.java create mode 100644 core/queryresultio/binary/src/main/java/org/eclipse/rdf4j/query/resultio/binary/BinaryQueryResultParser.java create mode 100644 core/queryresultio/binary/src/main/java/org/eclipse/rdf4j/query/resultio/binary/BinaryQueryResultParserFactory.java create mode 100644 core/queryresultio/binary/src/main/java/org/eclipse/rdf4j/query/resultio/binary/BinaryQueryResultWriter.java create mode 100644 core/queryresultio/binary/src/main/java/org/eclipse/rdf4j/query/resultio/binary/BinaryQueryResultWriterFactory.java create mode 100644 core/queryresultio/binary/src/main/java/org/eclipse/rdf4j/query/resultio/binary/QueryErrorType.java create mode 100644 core/queryresultio/binary/src/main/resources/META-INF/services/org.openrdf.query.resultio.TupleQueryResultParserFactory create mode 100644 core/queryresultio/binary/src/main/resources/META-INF/services/org.openrdf.query.resultio.TupleQueryResultWriterFactory create mode 100644 core/queryresultio/pom.xml create mode 100644 core/queryresultio/sparqljson/pom.xml create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/AbstractSPARQLJSONParser.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/AbstractSPARQLJSONWriter.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLBooleanJSONParser.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLBooleanJSONParserFactory.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLBooleanJSONWriter.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLBooleanJSONWriterFactory.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLJSONParserBase.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLResultsJSONParser.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLResultsJSONParserFactory.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLResultsJSONWriter.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLResultsJSONWriterFactory.java create mode 100644 core/queryresultio/sparqljson/src/main/java/org/eclipse/rdf4j/query/resultio/sparqljson/package.html create mode 100644 core/queryresultio/sparqljson/src/main/resources/META-INF/services/org.openrdf.query.resultio.BooleanQueryResultParserFactory create mode 100644 core/queryresultio/sparqljson/src/main/resources/META-INF/services/org.openrdf.query.resultio.BooleanQueryResultWriterFactory create mode 100644 core/queryresultio/sparqljson/src/main/resources/META-INF/services/org.openrdf.query.resultio.TupleQueryResultParserFactory create mode 100644 core/queryresultio/sparqljson/src/main/resources/META-INF/services/org.openrdf.query.resultio.TupleQueryResultWriterFactory create mode 100644 core/queryresultio/sparqlxml/pom.xml create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/AbstractSPARQLXMLParser.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/AbstractSPARQLXMLWriter.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLBooleanSAXParser.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLBooleanXMLParser.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLBooleanXMLParserFactory.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLBooleanXMLWriter.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLBooleanXMLWriterFactory.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLResultsSAXParser.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLResultsXMLConstants.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLResultsXMLParser.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLResultsXMLParserFactory.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLResultsXMLWriter.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLResultsXMLWriterFactory.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLXMLParserBase.java create mode 100644 core/queryresultio/sparqlxml/src/main/java/org/eclipse/rdf4j/query/resultio/sparqlxml/package.html create mode 100644 core/queryresultio/sparqlxml/src/main/resources/META-INF/services/org.openrdf.query.resultio.BooleanQueryResultParserFactory create mode 100644 core/queryresultio/sparqlxml/src/main/resources/META-INF/services/org.openrdf.query.resultio.BooleanQueryResultWriterFactory create mode 100644 core/queryresultio/sparqlxml/src/main/resources/META-INF/services/org.openrdf.query.resultio.TupleQueryResultParserFactory create mode 100644 core/queryresultio/sparqlxml/src/main/resources/META-INF/services/org.openrdf.query.resultio.TupleQueryResultWriterFactory create mode 100644 core/queryresultio/sparqlxml/src/test/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLResultsXMLParserTest.java create mode 100644 core/queryresultio/sparqlxml/src/test/resources/localname-result.srx create mode 100644 core/queryresultio/sparqlxml/src/test/resources/logback-test.xml create mode 100644 core/queryresultio/sparqlxml/src/test/resources/namespace-result.srx create mode 100644 core/queryresultio/text/pom.xml create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/BooleanTextParser.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/BooleanTextParserFactory.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/BooleanTextWriter.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/BooleanTextWriterFactory.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/csv/SPARQLResultsCSVParser.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/csv/SPARQLResultsCSVParserFactory.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/csv/SPARQLResultsCSVWriter.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/csv/SPARQLResultsCSVWriterFactory.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLResultsTSVParser.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLResultsTSVParserFactory.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLResultsTSVWriter.java create mode 100644 core/queryresultio/text/src/main/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLResultsTSVWriterFactory.java create mode 100644 core/queryresultio/text/src/main/resources/META-INF/services/org.openrdf.query.resultio.BooleanQueryResultParserFactory create mode 100644 core/queryresultio/text/src/main/resources/META-INF/services/org.openrdf.query.resultio.BooleanQueryResultWriterFactory create mode 100644 core/queryresultio/text/src/main/resources/META-INF/services/org.openrdf.query.resultio.TupleQueryResultParserFactory create mode 100644 core/queryresultio/text/src/main/resources/META-INF/services/org.openrdf.query.resultio.TupleQueryResultWriterFactory create mode 100644 core/repository/api/pom.xml create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/DelegatingRepository.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/DelegatingRepositoryConnection.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/Repository.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/RepositoryConnection.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/RepositoryException.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/RepositoryLockedException.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/RepositoryReadOnlyException.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/RepositoryResult.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/UnknownTransactionStateException.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/base/AbstractRepository.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/base/AbstractRepositoryConnection.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/base/RepositoryBase.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/base/RepositoryConnectionBase.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/base/RepositoryConnectionWrapper.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/base/RepositoryWrapper.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/AbstractDelegatingRepositoryImplConfig.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/AbstractRepositoryImplConfig.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/ConfigTemplate.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/DelegatingRepositoryImplConfig.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/DelegatingRepositoryImplConfigBase.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/RepositoryConfig.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/RepositoryConfigException.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/RepositoryConfigSchema.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/RepositoryConfigUtil.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/RepositoryFactory.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/RepositoryImplConfig.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/RepositoryImplConfigBase.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/config/RepositoryRegistry.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/package.html create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/util/AbstractRDFInserter.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/util/RDFInserter.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/util/RDFLoader.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/util/RDFRemover.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/util/Repositories.java create mode 100644 core/repository/api/src/main/java/org/eclipse/rdf4j/repository/util/RepositoryUtil.java create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/memory-customrule.ttl create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/memory-rdfs-dt.ttl create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/memory-rdfs.ttl create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/memory.ttl create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/native-customrule.ttl create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/native-rdfs-dt.ttl create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/native-rdfs.ttl create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/native.ttl create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/remote.ttl create mode 100644 core/repository/api/src/main/resources/org/openrdf/repository/config/sparql.ttl create mode 100644 core/repository/api/src/test/java/org/eclipse/rdf4j/repository/config/TestConfigTemplate.java create mode 100644 core/repository/contextaware/pom.xml create mode 100644 core/repository/contextaware/src/main/java/org/eclipse/rdf4j/repository/contextaware/ContextAwareConnection.java create mode 100644 core/repository/contextaware/src/main/java/org/eclipse/rdf4j/repository/contextaware/ContextAwareRepository.java create mode 100644 core/repository/contextaware/src/main/java/org/eclipse/rdf4j/repository/contextaware/config/ContextAwareConfig.java create mode 100644 core/repository/contextaware/src/main/java/org/eclipse/rdf4j/repository/contextaware/config/ContextAwareFactory.java create mode 100644 core/repository/contextaware/src/main/java/org/eclipse/rdf4j/repository/contextaware/config/ContextAwareSchema.java create mode 100644 core/repository/contextaware/src/main/java/org/eclipse/rdf4j/repository/contextaware/package.html create mode 100644 core/repository/contextaware/src/main/resources/META-INF/services/org.openrdf.repository.config.RepositoryFactory create mode 100644 core/repository/contextaware/src/test/java/org/eclipse/rdf4j/repository/contextaware/ContextAwareConnectionTest.java create mode 100644 core/repository/dataset/pom.xml create mode 100644 core/repository/dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetBooleanQuery.java create mode 100644 core/repository/dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetGraphQuery.java create mode 100644 core/repository/dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetQuery.java create mode 100644 core/repository/dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetRepository.java create mode 100644 core/repository/dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetRepositoryConnection.java create mode 100644 core/repository/dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetTupleQuery.java create mode 100644 core/repository/dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/config/DatasetRepositoryConfig.java create mode 100644 core/repository/dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/config/DatasetRepositoryFactory.java create mode 100644 core/repository/dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/package.html create mode 100644 core/repository/dataset/src/main/resources/META-INF/services/org.openrdf.repository.config.RepositoryFactory create mode 100644 core/repository/event/pom.xml create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/InterceptingRepository.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/InterceptingRepositoryConnection.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/NotifyingRepository.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/NotifyingRepositoryConnection.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/RepositoryConnectionInterceptor.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/RepositoryConnectionListener.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/RepositoryInterceptor.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/RepositoryListener.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/base/InterceptingRepositoryConnectionWrapper.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/base/InterceptingRepositoryWrapper.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/base/NotifyingRepositoryConnectionWrapper.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/base/NotifyingRepositoryWrapper.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/base/RepositoryConnectionInterceptorAdapter.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/base/RepositoryConnectionListenerAdapter.java create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/package.html create mode 100644 core/repository/event/src/main/java/org/eclipse/rdf4j/repository/event/util/DebugRepositoryConnectionListener.java create mode 100644 core/repository/event/src/test/java/org/eclipse/rdf4j/repository/event/InterceptorTest.java create mode 100644 core/repository/event/src/test/java/org/eclipse/rdf4j/repository/event/NotifyingTest.java create mode 100644 core/repository/http/pom.xml create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/HTTPBooleanQuery.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/HTTPGraphQuery.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/HTTPQueryEvaluationException.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/HTTPRepository.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/HTTPRepositoryConnection.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/HTTPTupleQuery.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/HTTPUpdate.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/HTTPUpdateExecutionException.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/config/HTTPRepositoryConfig.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/config/HTTPRepositoryFactory.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/config/HTTPRepositorySchema.java create mode 100644 core/repository/http/src/main/java/org/eclipse/rdf4j/repository/http/package.html create mode 100644 core/repository/http/src/main/resources/META-INF/services/org.openrdf.repository.config.RepositoryFactory create mode 100644 core/repository/manager/pom.xml create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/LocalRepositoryManager.java create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/RemoteRepositoryManager.java create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/RepositoryInfo.java create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/RepositoryManager.java create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/RepositoryProvider.java create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/SystemRepository.java create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/SystemRepositoryConfig.java create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/package.html create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/util/NotifyingLocalRepositoryManager.java create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/util/RepositoryManagerListener.java create mode 100644 core/repository/manager/src/main/java/org/eclipse/rdf4j/repository/manager/util/TypeFilteringRepositoryManager.java create mode 100644 core/repository/manager/src/test/java/org/eclipse/rdf4j/repository/manager/LocalRepositoryManagerTest.java create mode 100644 core/repository/pom.xml create mode 100644 core/repository/sail/pom.xml create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/ProxyRepository.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailBooleanQuery.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailCloseableIteration.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailGraphQuery.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailQuery.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepository.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepositoryConnection.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailTupleQuery.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailUpdate.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/config/ProxyRepositoryConfig.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/config/ProxyRepositoryFactory.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/config/ProxyRepositorySchema.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/config/RepositoryResolver.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/config/RepositoryResolverClient.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/config/SailRepositoryConfig.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/config/SailRepositoryFactory.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/config/SailRepositorySchema.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/helpers/RDFSailInserter.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/helpers/RDFSailRemover.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/helpers/SPARQLUpdateDataBlockParser.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/helpers/SailUpdateExecutor.java create mode 100644 core/repository/sail/src/main/java/org/eclipse/rdf4j/repository/sail/package.html create mode 100644 core/repository/sail/src/main/resources/META-INF/services/org.openrdf.repository.config.RepositoryFactory create mode 100644 core/repository/sail/src/test/java/org/eclipse/rdf4j/repository/sail/TestProxyRepository.java create mode 100644 core/repository/sail/src/test/java/org/eclipse/rdf4j/repository/sail/config/TestProxyRepositoryFactory.java create mode 100644 core/repository/sail/src/test/java/org/eclipse/rdf4j/repository/sail/helpers/TestSPARQLUpdateDataBlockParser.java create mode 100644 core/repository/sail/src/test/resources/proxy.ttl create mode 100644 core/repository/sparql/pom.xml create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/SPARQLConnection.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/SPARQLRepository.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/config/SPARQLRepositoryConfig.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/config/SPARQLRepositoryFactory.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/package.html create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/query/InsertBindingSetCursor.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/query/QueryStringUtil.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/query/QueueCursor.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/query/SPARQLBooleanQuery.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/query/SPARQLGraphQuery.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/query/SPARQLOperation.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/query/SPARQLQueryBindingSet.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/query/SPARQLTupleQuery.java create mode 100644 core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/query/SPARQLUpdate.java create mode 100644 core/repository/sparql/src/main/resources/META-INF/services/org.openrdf.repository.config.RepositoryFactory create mode 100644 core/rio/api/pom.xml create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/DatatypeHandler.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/DatatypeHandlerRegistry.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/LanguageHandler.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/LanguageHandlerRegistry.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/ParseErrorListener.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/ParseLocationListener.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/ParserConfig.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFFormat.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFHandler.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFHandlerException.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFParseException.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFParser.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFParserFactory.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFParserRegistry.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFWriter.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFWriterFactory.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RDFWriterRegistry.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/Rio.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RioConfig.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RioSetting.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/UnsupportedRDFormatException.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/WriterConfig.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/AbstractRDFHandler.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/AbstractRDFParser.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/AbstractRDFWriter.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/BasicParserSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/BasicWriterSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/BufferedGroupingRDFHandler.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/CodePointIterator.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/CodePointSequence.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/ContextStatementCollector.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/JSONLDMode.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/JSONLDSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/LargeLiteralHandling.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/NTriplesParserSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/NTriplesWriterSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/ParseErrorCollector.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/ParseErrorLogger.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFHandlerBase.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFHandlerWrapper.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFJSONParserSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserBase.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelper.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFWriterBase.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFaParserSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFaVersion.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RioFileTypeDetector.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RioSettingImpl.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/StatementCollector.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/TriXParserSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/TurtleParserSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/XMLParserSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/XMLWriterSettings.java create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/package.html create mode 100644 core/rio/api/src/main/java/org/eclipse/rdf4j/rio/package.html create mode 100644 core/rio/api/src/main/resources/META-INF/services/java.nio.file.spi.FileTypeDetector create mode 100644 core/rio/api/src/test/java/org/eclipse/rdf4j/rio/helpers/StatementCollectorTest.java create mode 100644 core/rio/binary/pom.xml create mode 100644 core/rio/binary/src/main/java/org/eclipse/rdf4j/rio/binary/BinaryRDFConstants.java create mode 100644 core/rio/binary/src/main/java/org/eclipse/rdf4j/rio/binary/BinaryRDFParser.java create mode 100644 core/rio/binary/src/main/java/org/eclipse/rdf4j/rio/binary/BinaryRDFParserFactory.java create mode 100644 core/rio/binary/src/main/java/org/eclipse/rdf4j/rio/binary/BinaryRDFWriter.java create mode 100644 core/rio/binary/src/main/java/org/eclipse/rdf4j/rio/binary/BinaryRDFWriterFactory.java create mode 100644 core/rio/binary/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/binary/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/datatypes/pom.xml create mode 100644 core/rio/datatypes/src/main/java/org/eclipse/rdf4j/rio/datatypes/DBPediaDatatypeHandler.java create mode 100644 core/rio/datatypes/src/main/java/org/eclipse/rdf4j/rio/datatypes/GeoSPARQLDatatypeHandler.java create mode 100644 core/rio/datatypes/src/main/java/org/eclipse/rdf4j/rio/datatypes/RDFDatatypeHandler.java create mode 100644 core/rio/datatypes/src/main/java/org/eclipse/rdf4j/rio/datatypes/VirtuosoGeometryDatatypeHandler.java create mode 100644 core/rio/datatypes/src/main/java/org/eclipse/rdf4j/rio/datatypes/XMLSchemaDatatypeHandler.java create mode 100644 core/rio/datatypes/src/main/resources/META-INF/services/org.openrdf.rio.DatatypeHandler create mode 100644 core/rio/jsonld/pom.xml create mode 100644 core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDInternalRDFParser.java create mode 100644 core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDInternalTripleCallback.java create mode 100644 core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParser.java create mode 100644 core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserFactory.java create mode 100644 core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriter.java create mode 100644 core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterFactory.java create mode 100644 core/rio/jsonld/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/jsonld/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDInternalTripleCallbackTest.java create mode 100644 core/rio/jsonld/src/test/resources/log4j.properties create mode 100644 core/rio/languages/pom.xml create mode 100644 core/rio/languages/src/main/java/org/eclipse/rdf4j/rio/languages/RFC3066LanguageHandler.java create mode 100644 core/rio/languages/src/main/resources/META-INF/services/org.openrdf.rio.LanguageHandler create mode 100644 core/rio/n3/pom.xml create mode 100644 core/rio/n3/src/main/java/org/eclipse/rdf4j/rio/n3/N3ParserFactory.java create mode 100644 core/rio/n3/src/main/java/org/eclipse/rdf4j/rio/n3/N3Writer.java create mode 100644 core/rio/n3/src/main/java/org/eclipse/rdf4j/rio/n3/N3WriterFactory.java create mode 100644 core/rio/n3/src/main/java/org/eclipse/rdf4j/rio/n3/package.html create mode 100644 core/rio/n3/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/n3/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/nquads/pom.xml create mode 100644 core/rio/nquads/src/main/java/org/eclipse/rdf4j/rio/nquads/NQuadsParser.java create mode 100644 core/rio/nquads/src/main/java/org/eclipse/rdf4j/rio/nquads/NQuadsParserFactory.java create mode 100644 core/rio/nquads/src/main/java/org/eclipse/rdf4j/rio/nquads/NQuadsWriter.java create mode 100644 core/rio/nquads/src/main/java/org/eclipse/rdf4j/rio/nquads/NQuadsWriterFactory.java create mode 100644 core/rio/nquads/src/main/java/org/eclipse/rdf4j/rio/nquads/package.html create mode 100644 core/rio/nquads/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/nquads/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/ntriples/pom.xml create mode 100644 core/rio/ntriples/src/main/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParser.java create mode 100644 core/rio/ntriples/src/main/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParserFactory.java create mode 100644 core/rio/ntriples/src/main/java/org/eclipse/rdf4j/rio/ntriples/NTriplesUtil.java create mode 100644 core/rio/ntriples/src/main/java/org/eclipse/rdf4j/rio/ntriples/NTriplesWriter.java create mode 100644 core/rio/ntriples/src/main/java/org/eclipse/rdf4j/rio/ntriples/NTriplesWriterFactory.java create mode 100644 core/rio/ntriples/src/main/java/org/eclipse/rdf4j/rio/ntriples/package.html create mode 100644 core/rio/ntriples/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/ntriples/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/pom.xml create mode 100644 core/rio/rdfjson/pom.xml create mode 100644 core/rio/rdfjson/src/main/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParser.java create mode 100644 core/rio/rdfjson/src/main/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserFactory.java create mode 100644 core/rio/rdfjson/src/main/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONUtility.java create mode 100644 core/rio/rdfjson/src/main/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONWriter.java create mode 100644 core/rio/rdfjson/src/main/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONWriterFactory.java create mode 100644 core/rio/rdfjson/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/rdfjson/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/rdfxml/pom.xml create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/Att.java create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/Atts.java create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParser.java create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserFactory.java create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLWriter.java create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLWriterFactory.java create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/SAXFilter.java create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/package.html create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/util/RDFXMLPrettyWriter.java create mode 100644 core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/util/RDFXMLPrettyWriterFactory.java create mode 100644 core/rio/rdfxml/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/rdfxml/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/rdfxml/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTest.java create mode 100644 core/rio/rdfxml/src/test/resources/org/openrdf/rio/rdfxml/sample-with-rdfxml-data.zip create mode 100644 core/rio/trig/pom.xml create mode 100644 core/rio/trig/src/main/java/org/eclipse/rdf4j/rio/trig/TriG grammar.txt create mode 100644 core/rio/trig/src/main/java/org/eclipse/rdf4j/rio/trig/TriGParser.java create mode 100644 core/rio/trig/src/main/java/org/eclipse/rdf4j/rio/trig/TriGParserFactory.java create mode 100644 core/rio/trig/src/main/java/org/eclipse/rdf4j/rio/trig/TriGWriter.java create mode 100644 core/rio/trig/src/main/java/org/eclipse/rdf4j/rio/trig/TriGWriterFactory.java create mode 100644 core/rio/trig/src/main/java/org/eclipse/rdf4j/rio/trig/package.html create mode 100644 core/rio/trig/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/trig/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/trix/pom.xml create mode 100644 core/rio/trix/src/main/java/org/eclipse/rdf4j/rio/trix/TriXConstants.java create mode 100644 core/rio/trix/src/main/java/org/eclipse/rdf4j/rio/trix/TriXParser.java create mode 100644 core/rio/trix/src/main/java/org/eclipse/rdf4j/rio/trix/TriXParserFactory.java create mode 100644 core/rio/trix/src/main/java/org/eclipse/rdf4j/rio/trix/TriXWriter.java create mode 100644 core/rio/trix/src/main/java/org/eclipse/rdf4j/rio/trix/TriXWriterFactory.java create mode 100644 core/rio/trix/src/main/java/org/eclipse/rdf4j/rio/trix/package.html create mode 100644 core/rio/trix/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/trix/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/turtle/pom.xml create mode 100644 core/rio/turtle/src/main/java/org/eclipse/rdf4j/rio/turtle/Turtle grammar.txt create mode 100644 core/rio/turtle/src/main/java/org/eclipse/rdf4j/rio/turtle/TurtleParser.java create mode 100644 core/rio/turtle/src/main/java/org/eclipse/rdf4j/rio/turtle/TurtleParserFactory.java create mode 100644 core/rio/turtle/src/main/java/org/eclipse/rdf4j/rio/turtle/TurtleUtil.java create mode 100644 core/rio/turtle/src/main/java/org/eclipse/rdf4j/rio/turtle/TurtleWriter.java create mode 100644 core/rio/turtle/src/main/java/org/eclipse/rdf4j/rio/turtle/TurtleWriterFactory.java create mode 100644 core/rio/turtle/src/main/java/org/eclipse/rdf4j/rio/turtle/package.html create mode 100644 core/rio/turtle/src/main/resources/META-INF/services/org.openrdf.rio.RDFParserFactory create mode 100644 core/rio/turtle/src/main/resources/META-INF/services/org.openrdf.rio.RDFWriterFactory create mode 100644 core/rio/turtle/src/test/java/org/eclipse/rdf4j/rio/turtle/TestTurtleParser.java create mode 100644 core/rio/turtle/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleUtilTest.java create mode 100644 core/rio/turtle/src/test/resources/org/openrdf/rio/turtle/sample-with-turtle-data.zip create mode 100644 core/rio/turtle/src/test/resources/test-newlines.ttl create mode 100644 core/runtime-osgi/build.xml create mode 100644 core/runtime-osgi/pom.xml create mode 100644 core/runtime-osgi/src/main/resources/LICENSE.txt create mode 100644 core/runtime-osgi/src/main/resources/NOTICE.txt create mode 100644 core/runtime/pom.xml create mode 100644 core/runtime/src/main/java/org/eclipse/rdf4j/runtime/RepositoryManagerFederator.java create mode 100644 core/runtime/src/test/java/org/eclipse/rdf4j/runtime/TestRepositoryManagerFederator.java create mode 100644 core/sail/api/pom.xml create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/AbstractReadWriteLockManager.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/ExclusiveLockManager.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/Lock.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/LockManager.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/LockingIteration.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/Properties.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/ReadPrefReadWriteLockManager.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/ReadWriteLockManager.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/WritePrefReadWriteLockManager.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/package.html create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/LockManager.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/NotifyingSail.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/NotifyingSailConnection.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/Sail.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/SailChangedEvent.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/SailChangedListener.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/SailConflictException.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/SailConnection.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/SailConnectionListener.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/SailException.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/SailLockedException.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/SailReadOnlyException.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/StackableSail.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/UnknownSailTransactionStateException.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/UpdateContext.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/AbstractDelegatingSailImplConfig.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/AbstractSailImplConfig.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/DelegatingSailImplConfig.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/DelegatingSailImplConfigBase.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/SailConfigException.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/SailConfigSchema.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/SailConfigUtil.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/SailFactory.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/SailImplConfig.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/SailImplConfigBase.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/config/SailRegistry.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractNotifyingSail.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSail.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSailConnection.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/DefaultSailChangedEvent.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/DirectoryLockManager.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailBase.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionBase.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionWrapper.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailWrapper.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/SailBase.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/SailBaseIteration.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/SailConnectionBase.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/SailConnectionWrapper.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/SailUtil.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/SailWrapper.java create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/helpers/package.html create mode 100644 core/sail/api/src/main/java/org/eclipse/rdf4j/sail/package.html create mode 100644 core/sail/base/pom.xml create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/BackingSailSource.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/Changeset.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/DelegatingSailDataset.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/DelegatingSailSource.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/ObservingSailDataset.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailClosable.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailClosingIteration.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailDataset.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailDatasetImpl.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailDatasetTripleSource.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailSink.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailSource.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceBranch.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceConnection.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SailStore.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SnapshotSailStore.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/UnionSailDataset.java create mode 100644 core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/UnionSailSource.java create mode 100644 core/sail/federation/pom.xml create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/AbstractEchoWriteConnection.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/AbstractFederationConnection.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/PrefixHashSet.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/ReadOnlyConnection.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/WritableConnection.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryOperator.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryTupleOperator.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/NaryJoin.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/OwnedTupleExpr.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/config/FederationConfig.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/config/FederationFactory.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/AlternativeCursor.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/FederationStrategy.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/FilterCursor.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/InsertBindingSetCursor.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelJoinCursor.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelLeftJoinCursor.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/QueueCursor.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/RepositoryTripleSource.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/EmptyPatternOptimizer.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/EvaluationStatistics.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/FederationJoinOptimizer.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/OwnedTupleExprPruner.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/PrepareOwnedTupleExpr.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/QueryModelPruner.java create mode 100644 core/sail/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/QueryMultiJoinOptimizer.java create mode 100644 core/sail/federation/src/main/resources/META-INF/services/org.openrdf.sail.config.SailFactory create mode 100644 core/sail/federation/src/site/apt/index.apt create mode 100644 core/sail/federation/src/site/resources/css/site.css create mode 100644 core/sail/federation/src/test/java/org/eclipse/rdf4j/sail/federation/FederationNamespacesTest.java create mode 100644 core/sail/federation/src/test/java/org/eclipse/rdf4j/sail/federation/FederationQueryTest.java create mode 100644 core/sail/federation/src/test/java/org/eclipse/rdf4j/sail/federation/SPARQLBuilderTest.java create mode 100644 core/sail/federation/src/test/resources/testcases/federation-member-1.ttl create mode 100644 core/sail/federation/src/test/resources/testcases/federation-member-2.ttl create mode 100644 core/sail/federation/src/test/resources/testcases/federation-member-3.ttl create mode 100644 core/sail/fts/elasticsearch/pom.xml create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchBulkUpdater.java create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchDocument.java create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchDocumentDistance.java create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchDocumentResult.java create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchDocumentScore.java create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndex.java create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchQuery.java create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSpatialSupport.java create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/config/ElasticsearchSailConfig.java create mode 100644 core/sail/fts/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/config/ElasticsearchSailFactory.java create mode 100644 core/sail/fts/elasticsearch/src/main/resources/META-INF/services/org.openrdf.sail.config.SailFactory create mode 100644 core/sail/fts/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java create mode 100644 core/sail/fts/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailGeoSPARQLTest.java create mode 100644 core/sail/fts/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailIndexedPropertiesTest.java create mode 100644 core/sail/fts/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailTest.java create mode 100644 core/sail/fts/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/examples/ElasticsearchSailExample.java create mode 100644 core/sail/fts/elasticsearch/src/test/resources/elasticsearch.yml create mode 100644 core/sail/fts/lucene-api/pom.xml create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractLuceneIndex.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractReaderMonitor.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractSearchIndex.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/BindingSetCollection.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/BulkUpdater.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/DistanceQuerySpec.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/DistanceQuerySpecBuilder.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/DocumentDistance.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/DocumentResult.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/DocumentScore.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/GeoRelationQuerySpec.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/GeoRelationQuerySpecBuilder.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/IndexableStatementFilter.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSail.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailBuffer.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailConnection.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailSchema.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/PropertyCache.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpec.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilder.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/SearchDocument.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/SearchFields.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/SearchIndex.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/SearchQuery.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/SearchQueryEvaluator.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/SearchQueryInterpreter.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/SimpleBulkUpdater.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/config/AbstractLuceneSailConfig.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/config/LuceneSailConfigSchema.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/util/GeoUnits.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/util/IteratorCloseableIteration.java create mode 100644 core/sail/fts/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/util/MapOfListMaps.java create mode 100644 core/sail/fts/lucene-api/src/test/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilderTest.java create mode 100644 core/sail/fts/lucene/pom.xml create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneDocument.java create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneDocumentDistance.java create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneDocumentResult.java create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneDocumentScore.java create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneIndex.java create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneIndexNIOFS.java create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneQuery.java create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/ReaderMonitor.java create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/config/LuceneSailConfig.java create mode 100644 core/sail/fts/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/config/LuceneSailFactory.java create mode 100644 core/sail/fts/lucene/src/main/resources/META-INF/services/org.openrdf.sail.config.SailFactory create mode 100644 core/sail/fts/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/LuceneIndexTest.java create mode 100644 core/sail/fts/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/LuceneSailGeoSPARQLTest.java create mode 100644 core/sail/fts/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/LuceneSailIndexedPropertiesTest.java create mode 100644 core/sail/fts/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/LuceneSailTest.java create mode 100644 core/sail/fts/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/examples/LuceneSailExample.java create mode 100644 core/sail/fts/lucene4/pom.xml create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/LuceneDocument.java create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/LuceneDocumentDistance.java create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/LuceneDocumentResult.java create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/LuceneDocumentScore.java create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/LuceneIndex.java create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/LuceneIndexNIOFS.java create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/LuceneQuery.java create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/ReaderMonitor.java create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/config/LuceneSailConfig.java create mode 100644 core/sail/fts/lucene4/src/main/java/org/eclipse/rdf4j/sail/lucene4/config/LuceneSailFactory.java create mode 100644 core/sail/fts/lucene4/src/main/resources/META-INF/services/org.openrdf.sail.config.SailFactory create mode 100644 core/sail/fts/lucene4/src/test/java/org/eclipse/rdf4j/sail/lucene4/LuceneIndexTest.java create mode 100644 core/sail/fts/lucene4/src/test/java/org/eclipse/rdf4j/sail/lucene4/LuceneSailGeoSPARQLTest.java create mode 100644 core/sail/fts/lucene4/src/test/java/org/eclipse/rdf4j/sail/lucene4/LuceneSailIndexedPropertiesTest.java create mode 100644 core/sail/fts/lucene4/src/test/java/org/eclipse/rdf4j/sail/lucene4/LuceneSailTest.java create mode 100644 core/sail/fts/lucene4/src/test/java/org/eclipse/rdf4j/sail/lucene4/examples/LuceneSailExample.java create mode 100644 core/sail/fts/lucenesail/pom.xml create mode 100644 core/sail/fts/lucenesail/src/main/java/org/apache/lucene/spatial/tier/FixedCartesianPolyFilterBuilder.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/apache/lucene/spatial/tier/projections/FixedSinusoidalProjector.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/LuceneDocument.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/LuceneDocumentDistance.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/LuceneDocumentResult.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/LuceneDocumentScore.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/LuceneIndex.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/LuceneIndexNIOFS.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/LuceneQuery.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/ReaderMonitor.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/SpatialStrategy.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/config/LuceneSailConfig.java create mode 100644 core/sail/fts/lucenesail/src/main/java/org/eclipse/rdf4j/sail/lucene3/config/LuceneSailFactory.java create mode 100644 core/sail/fts/lucenesail/src/main/resources/META-INF/services/org.openrdf.sail.config.SailFactory create mode 100644 core/sail/fts/lucenesail/src/test/java/org/eclipse/rdf4j/sail/lucene3/LuceneIndexTest.java create mode 100644 core/sail/fts/lucenesail/src/test/java/org/eclipse/rdf4j/sail/lucene3/LuceneSailGeoSPARQLTest.java create mode 100644 core/sail/fts/lucenesail/src/test/java/org/eclipse/rdf4j/sail/lucene3/LuceneSailIndexedPropertiesTest.java create mode 100644 core/sail/fts/lucenesail/src/test/java/org/eclipse/rdf4j/sail/lucene3/LuceneSailTest.java create mode 100644 core/sail/fts/lucenesail/src/test/java/org/eclipse/rdf4j/sail/lucene3/examples/LuceneSailExample.java create mode 100644 core/sail/fts/pom.xml create mode 100644 core/sail/fts/solr/pom.xml create mode 100644 core/sail/fts/solr/solr/cores/embedded/conf/schema.xml create mode 100644 core/sail/fts/solr/solr/cores/embedded/conf/solrconfig.xml create mode 100644 core/sail/fts/solr/solr/cores/embedded/core.properties create mode 100644 core/sail/fts/solr/solr/solr.xml create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrBulkUpdater.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrClientFactory.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrDocumentDistance.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrDocumentResult.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrDocumentScore.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrIndex.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrSearchDocument.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrSearchQuery.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/client/cloud/Factory.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/client/embedded/Factory.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/client/http/Factory.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/config/SolrSailConfig.java create mode 100644 core/sail/fts/solr/src/main/java/org/eclipse/rdf4j/sail/solr/config/SolrSailFactory.java create mode 100644 core/sail/fts/solr/src/main/resources/META-INF/services/org.openrdf.sail.config.SailFactory create mode 100644 core/sail/fts/solr/src/test/java/org/eclipse/rdf4j/sail/solr/SolrIndexTest.java create mode 100644 core/sail/fts/solr/src/test/java/org/eclipse/rdf4j/sail/solr/SolrSailGeoSPARQLTest.java create mode 100644 core/sail/fts/solr/src/test/java/org/eclipse/rdf4j/sail/solr/SolrSailIndexedPropertiesTest.java create mode 100644 core/sail/fts/solr/src/test/java/org/eclipse/rdf4j/sail/solr/SolrSailTest.java create mode 100644 core/sail/fts/solr/src/test/java/org/eclipse/rdf4j/sail/solr/examples/SolrSailExample.java create mode 100644 core/sail/inferencer/pom.xml create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/InferencerConnection.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/InferencerConnectionWrapper.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/AbstractForwardChainingInferencer.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/AbstractForwardChainingInferencerConnection.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/CustomGraphQueryInferencer.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/DirectTypeHierarchyInferencer.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencer.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencerConnection.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/RDFSRules.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/CustomGraphQueryInferencerConfig.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/CustomGraphQueryInferencerFactory.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/CustomGraphQueryInferencerSchema.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/DirectTypeHierarchyInferencerConfig.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/DirectTypeHierarchyInferencerFactory.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerConfig.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerFactory.java create mode 100644 core/sail/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/package.html create mode 100644 core/sail/inferencer/src/main/resources/META-INF/services/org.openrdf.sail.config.SailFactory create mode 100644 core/sail/memory/pom.xml create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/FileIO.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemEvaluationStatistics.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemNamespaceStore.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemorySailStore.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStore.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStoreConnection.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/config/MemoryStoreConfig.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/config/MemoryStoreFactory.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/config/MemoryStoreSchema.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/design.txt create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/BooleanMemLiteral.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/CalendarMemLiteral.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/DecimalMemLiteral.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/IntegerMemLiteral.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemBNode.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemIRI.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemLiteral.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemResource.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemStatement.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemStatementIterator.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemStatementList.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValue.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/NumericMemLiteral.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/WeakObjectRegistry.java create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/package.html create mode 100644 core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/package.html create mode 100644 core/sail/memory/src/main/resources/META-INF/services/org.openrdf.sail.config.SailFactory create mode 100644 core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/MemTripleSourceTest.java create mode 100644 core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/model/MemURITest.java create mode 100644 core/sail/memory/src/test/resources/alp-testdata.ttl create mode 100644 core/sail/model/pom.xml create mode 100644 core/sail/model/src/main/java/org/eclipse/rdf4j/sail/model/SailModel.java create mode 100644 core/sail/nativerdf/pom.xml create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/LRUCache.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/LimitedSizeNativeStore.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/LimitedSizeNativeStoreConnection.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/MemoryOverflowModel.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NamespaceStore.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeEvaluationStatistics.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeSailStore.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStatementIterator.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStore.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConnection.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/RecordCache.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/SailSourceModel.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/SequentialRecordCache.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/SortedRecordCache.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/TripleStore.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/TxnStatusFile.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ValueStore.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ValueStoreRevision.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/AllocatedNodesList.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/BTree.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/DefaultRecordComparator.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/RecordComparator.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/RecordIterator.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/config/NativeStoreConfig.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/config/NativeStoreFactory.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/config/NativeStoreSchema.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataFile.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataStore.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/datastore/HashFile.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/datastore/IDFile.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/model/NativeBNode.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/model/NativeIRI.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/model/NativeLiteral.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/model/NativeResource.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/model/NativeValue.java create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/package.html create mode 100644 core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/txn-flags.txt create mode 100644 core/sail/nativerdf/src/main/resources/META-INF/services/org.openrdf.sail.config.SailFactory create mode 100644 core/sail/nativerdf/src/test/java/org/eclipse/rdf4j/sail/nativerdf/DefaultIndexTest.java create mode 100644 core/sail/nativerdf/src/test/java/org/eclipse/rdf4j/sail/nativerdf/TestNativeStoreUpgrade.java create mode 100644 core/sail/nativerdf/src/test/java/org/eclipse/rdf4j/sail/nativerdf/TripleStoreRecoveryTest.java create mode 100644 core/sail/nativerdf/src/test/java/org/eclipse/rdf4j/sail/nativerdf/btree/BTreeBenchmark.java create mode 100644 core/sail/nativerdf/src/test/java/org/eclipse/rdf4j/sail/nativerdf/btree/BTreeTest.java create mode 100644 core/sail/nativerdf/src/test/resources/logback-test.xml create mode 100644 core/sail/nativerdf/src/test/resources/nativerdf-2.7.15.zip create mode 100644 core/sail/nativerdf/src/test/resources/nativerdf-inconsistent-2.7.15.zip create mode 100644 core/sail/pom.xml create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/RdbmsConnection.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/RdbmsStore.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/base/RdbmsQueryModelNodeBase.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/base/RdbmsQueryModelVisitorBase.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/BNodeExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/BooleanExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/DatatypeExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/HashExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/LabelExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/LanguageExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/NumericExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/TimeExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/URIExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/algebra/factories/ZonedExprFactory.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/config/RdbmsStoreConfig.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/evaluation/RdbmsEvaluation.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/iteration/base/RdbmIterationBase.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/optimizers/SameTermFilterRdbmsOptimizer.java create mode 100644 core/sail/rdbms/src/main/java/org/openrdf/sail/rdbms/optimizers/ValueIdLookupOptimizer.java create mode 100644 core/util/pom.xml create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/ByteArrayUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/FileUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/GZipUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/IOUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/IndentingWriter.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/MavenUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/NioFile.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/ResourceUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/UncloseableInputStream.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/io/ZipUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/AbstractCloseableIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/CloseableIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/CloseableIterationBase.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/CloseableIteratorIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/ConvertingIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/DelayedIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/DistinctIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/EmptyIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/ExceptionConvertingIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/FilterIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/InterruptTask.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/IntersectIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/Iteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/IterationSpliterator.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/IterationWrapper.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/Iterations.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/IteratorIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/LimitIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/LookAheadIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/MinusIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/OffsetIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/ReducedIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/SingletonIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/TimeLimitIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iteration/UnionIteration.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iterator/AbstractCloseableIterator.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iterator/CloseableIterationIterator.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iterator/CloseableIteratorBase.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iterator/LookAheadIterator.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/iterator/UnionIterator.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/lang/FileFormat.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/lang/ObjectUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/lang/service/FileFormatServiceRegistry.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/lang/service/ServiceRegistry.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/net/ParsedURI.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/text/ASCIIUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/text/StringUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/xml/DocumentUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/xml/SimpleSAXAdapter.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/xml/SimpleSAXListener.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/xml/SimpleSAXParser.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/xml/XMLReaderFactory.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/xml/XMLUtil.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/common/xml/XMLWriter.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/util/NonSerializables.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/util/iterators/ConvertingIterator.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/util/iterators/EmptyIterator.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/util/iterators/FilterIterator.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/util/iterators/Iterators.java create mode 100644 core/util/src/main/java/org/eclipse/rdf4j/util/iterators/SingletonIterator.java create mode 100644 core/util/src/test/java/org/eclipse/rdf4j/common/io/FileUtilTest.java create mode 100644 core/util/src/test/java/org/eclipse/rdf4j/common/net/ParsedURITest.java create mode 100644 license.html create mode 100644 pom.xml create mode 100644 testsuites/geosparql/pom.xml create mode 100644 testsuites/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/geosparql/GeoSPARQLManifestTest.java create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/data.ttl create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/manifest.ttl create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/q-boundary.rq create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/q-convexHull.rq create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/q-difference.rq create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/q-distance.rq create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/q-envelope.rq create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/q-intersection.rq create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/q-srid.rq create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/q-symDifference.rq create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/q-union.rq create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/result-boundary.srx create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/result-convexHull.srx create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/result-difference.srx create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/result-distance.srx create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/result-envelope.srx create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/result-intersection.srx create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/result-srid.srx create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/result-symDifference.srx create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/functions/result-union.srx create mode 100644 testsuites/geosparql/src/main/resources/testcases-geosparql/manifest.txt create mode 100644 testsuites/lucene/pom.xml create mode 100644 testsuites/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractLuceneSailGeoSPARQLTest.java create mode 100644 testsuites/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractLuceneSailIndexedPropertiesTest.java create mode 100644 testsuites/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractLuceneSailTest.java create mode 100644 testsuites/lucene/src/main/resources/org/openrdf/sail/lucene/examples/foaf.rdfs create mode 100644 testsuites/lucene/testdata.kml create mode 100644 testsuites/model/pom.xml create mode 100644 testsuites/model/src/main/java/org/eclipse/rdf4j/model/ModelEqualityTest.java create mode 100644 testsuites/model/src/main/java/org/eclipse/rdf4j/model/ModelNamespacesTest.java create mode 100644 testsuites/model/src/main/java/org/eclipse/rdf4j/model/ModelTest.java create mode 100644 testsuites/model/src/main/java/org/eclipse/rdf4j/model/base/AbstractTestCollection.java create mode 100644 testsuites/model/src/main/java/org/eclipse/rdf4j/model/base/AbstractTestObject.java create mode 100644 testsuites/model/src/main/java/org/eclipse/rdf4j/model/base/AbstractTestSet.java create mode 100644 testsuites/model/src/main/java/org/eclipse/rdf4j/model/base/ApacheSetTestCase.java create mode 100644 testsuites/model/src/main/java/org/eclipse/rdf4j/model/base/BulkTest.java create mode 100644 testsuites/model/src/main/resources/testcases/model/equality/sparql-graph-11-shuffled.ttl create mode 100644 testsuites/model/src/main/resources/testcases/model/equality/sparql-graph-11.ttl create mode 100644 testsuites/model/src/main/resources/testcases/model/equality/test001a.ttl create mode 100644 testsuites/model/src/main/resources/testcases/model/equality/test001b.ttl create mode 100644 testsuites/model/src/main/resources/testcases/model/equality/toRdf-0061-out.nq create mode 100644 testsuites/pom.xml create mode 100644 testsuites/queryresultio/pom.xml create mode 100644 testsuites/queryresultio/src/main/java/org/eclipse/rdf4j/query/resultio/AbstractQueryResultIOBooleanTest.java create mode 100644 testsuites/queryresultio/src/main/java/org/eclipse/rdf4j/query/resultio/AbstractQueryResultIOTest.java create mode 100644 testsuites/queryresultio/src/main/java/org/eclipse/rdf4j/query/resultio/AbstractQueryResultIOTupleTest.java create mode 100644 testsuites/rio/pom.xml create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/AbstractParserHandlingTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/EarlReport.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/FailureMode.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/NegativeParserTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/ParserConfigTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/PositiveParserTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/RDFWriterTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/datatypes/AbstractDatatypeHandlerTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/n3/N3ParserTestCase.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/nquads/AbstractNQuadsParserTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/nquads/AbstractNQuadsParserUnitTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/nquads/AbstractNQuadsWriterTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/ntriples/AbstractNTriplesParserTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/ntriples/AbstractNTriplesParserUnitTest.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserTestCase.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTestCase.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLWriterTestCase.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/trig/TriGParserTestCase.java create mode 100644 testsuites/rio/src/main/java/org/eclipse/rdf4j/rio/turtle/TurtleParserTestCase.java create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/manifest.ttl create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-03.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-04.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-05.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-06.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-07.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-08.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-09.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-10.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-11.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-12.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-13.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-14.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-eval-file-15.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-01.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-02.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-03.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-04.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-05.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-06.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-07.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-08.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-09.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-10.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-11.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-12.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-13.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-14.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-15.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-16.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-17.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-18.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-19.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-20.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-bad-21.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-01.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-02.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-03.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-04.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-05.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-06.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-07.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-08.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-09.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-10.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-11.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-12.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-13.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-14.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfjson/rdfjson-syntax-file-15.rj create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/Manifest.rdf create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/bad-entity-expansion-limit.rdf create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test001a.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test001a.rdf create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test001b.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test001b.rdf create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test002.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test002a.rdf create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test002b.rdf create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test003.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test003a.rdf create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/rdfms-empty-property-elements/test003b.rdf create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/xmlbase/test001.nt create mode 100644 testsuites/rio/src/main/resources/testcases/rdfxml/openrdf/xmlbase/test001.rdf create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/manifest.ttl create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-base-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-esc-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-esc-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-esc-03.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-lang-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-num-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-num-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-num-03.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-prefix-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-string-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-string-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-string-03.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-string-04.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-string-05.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-string-06.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-string-07.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-struct-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-struct-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-uri-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-uri-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-uri-03.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-uri-04.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-uri-05.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-uri-06.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-uri-07.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-uri-08.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bad-uri-09.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bnode-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-bnode-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-datatypes-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-datatypes-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-file-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-file-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-file-03.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-str-esc-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-str-esc-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-str-esc-03.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-string-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-string-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-string-03.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-subm-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-uri-01.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-uri-02.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-uri-03.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/tests-nt/nt-syntax-uri-04.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/turtle-long-literals-test.nt create mode 100644 testsuites/rio/src/main/resources/testcases/turtle/turtle-long-literals-test.ttl create mode 100644 testsuites/serql/pom.xml create mode 100644 testsuites/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParserTestCase.java create mode 100644 testsuites/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLQueryTestCase.java create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/manifest.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test000-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test000-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test000-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test001-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test001-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test001-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test002-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test002-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test002-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test003-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test003-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test003-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test004-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test004-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test004-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test005-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test005-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test005-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test006-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test006-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test006-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test007-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test007-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test007-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test008-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test008-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test008-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test009-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test009-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test009-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test010-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test010-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test010-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test011-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test011-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test011-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test012-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test012-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test012-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test013-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test013-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test013-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test014-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test014-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test014-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test015-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test015-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test015-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test016-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test016-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test016-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test017-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test017-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test017-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test018-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test018-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test018-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test019-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test019-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test019-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test020-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test020-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test020-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test021-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test021-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test021-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test022-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test022-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test022-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test023-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test023-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test023-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test024-graph1.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test024-graph2.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test024-in.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test024-out.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test024-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test025-in.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test025-out.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test025-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test026-in.trig create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test026-out.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test026-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test027-in.trig create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test027-out.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test027-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test028-in.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test028-out.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test028-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test029-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test029-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test029-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test030-in.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test030-out.nt create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test030-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test031-in.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test031-out.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test031-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test032-in.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test032-out.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/construct/test032-query.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/manifest.ttl create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-000.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-001.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-002.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-003.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-004.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-005.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-006.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-007.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-008.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-009.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-010.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-011.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-012.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-013.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-014.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-015.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-016.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-017.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-018.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-019.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-020.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-021.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-022.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-023.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-024.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-025.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-026.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-027.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-028.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-029.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-030.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-031.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-032.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-033.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-034.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-035.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-036.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-037.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-038.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-039.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-040.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-041.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-042.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-043.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-044.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-045.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-046.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-047.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-048.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-049.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-050.serql create mode 100644 testsuites/serql/src/main/resources/testcases/SeRQL/syntax/syntax-051.serql create mode 100644 testsuites/sparql/pom.xml create mode 100644 testsuites/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/ComplexSPARQLQueryTest.java create mode 100644 testsuites/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLDataSet.java create mode 100644 testsuites/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLUpdateTest.java create mode 100644 testsuites/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/manifest/ManifestTest.java create mode 100644 testsuites/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/manifest/SPARQL11ManifestTest.java create mode 100644 testsuites/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/manifest/SPARQL11SyntaxTest.java create mode 100644 testsuites/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/manifest/SPARQLQueryTest.java create mode 100644 testsuites/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/manifest/SPARQLSyntaxTest.java create mode 100644 testsuites/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/manifest/SPARQLUpdateConformanceTest.java create mode 100644 testsuites/sparql/src/main/resources/testcases-service/README create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data01.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data01endpoint.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data02endpoint1.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data02endpoint2.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data03endpoint1.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data03endpoint2.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data04.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data04endpoint.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data05.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data05endpoint1.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data05endpoint2.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data06endpoint1.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data07.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data08.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data08endpoint.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data09endpoint.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data10.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data10endpoint.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data11.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data11endpoint.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data12.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data13.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data15endpoint1.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data15endpoint2.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data17endpoint1.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/data18endpoint1.rdf create mode 100644 testsuites/sparql/src/main/resources/testcases-service/dataendpoint01.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/index.html create mode 100644 testsuites/sparql/src/main/resources/testcases-service/manifest.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service05.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service05.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service06.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service06.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service07.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service07.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service08.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service08.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service09.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service09.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service10.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service10.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service11.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service11.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service12.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service12.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service13.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service13.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service14.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service14.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service17.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service17.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service18.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-service/service18.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-service/simple-default-graph.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-service/simple.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/data-01.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/data-02.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/data-03.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/data-04.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/data-05.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/data-06.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/data-07.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/data-08.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/manifest.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-expression-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-expression-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-group-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-group-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-group-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-group-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-subquery-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-subquery-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-subquery-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-aggregate-subquery-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-avg-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-avg-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-avg-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-avg-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-count-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-count-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-count-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-count-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-count-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-count-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-count-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-count-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-having-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-having-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-max-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-max-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-min-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-min-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-order-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-order-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-order-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-order-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-order-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-order-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-sum-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-sum-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-sum-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-sum-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-sum-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-sum-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-sum-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/aggregates/sparql11-sum-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bindings/data-01.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bindings/manifest.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bindings/sparql11-bindings-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bindings/sparql11-bindings-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bindings/sparql11-bindings-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bindings/sparql11-bindings-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bsbm/bsbm-100.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bsbm/bsbm-bi-q5.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bsbm/bsbm-bi-q5.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/bsbm/manifest.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/data-01.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/data-02.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/manifest.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-abs-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-abs-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-bnode-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-bnode-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-bnode-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-bnode-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-ceil-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-ceil-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-coalesce-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-coalesce-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-05.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-concat-05.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-encodeforuri-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-encodeforuri-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-floor-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-floor-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-if-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-if-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-if-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-if-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-in-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-in-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-in-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-in-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-in-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-in-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-iri-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-iri-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-isnumeric-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-isnumeric-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-lcase-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-lcase-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-not-in-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-not-in-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-not-in-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-not-in-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-not-in-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-not-in-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-round-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-round-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-round-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-round-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strdt-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strdt-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strends-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strends-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strlang-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strlang-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strlen-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strlen-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strlen-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strlen-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strstarts-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-strstarts-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-substr-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-substr-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-substr-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-substr-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-substr-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-substr-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-ucase-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-ucase-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-uri-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/builtin/sparql11-uri-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/data-01.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/data-02.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/manifest.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/sparql11-alias-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/sparql11-alias-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/sparql11-alias-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/sparql11-alias-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/sparql11-expression-ordered-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/sparql11-expression-ordered-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/sparql11-numeric-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/expressions/sparql11-numeric-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/manifest-evaluation.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/data-01.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/data-02.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/data-03.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/data-04.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/manifest.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-05.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-05.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-06.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-exists-06.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-05.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-05.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-06.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-06.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-07.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/negation/sparql11-minus-07.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-01.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-02.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-03.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-04.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-05.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-06.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-07.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-08.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-09.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-10.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/data-11.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/manifest.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-alternative-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-alternative-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-alternative-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-alternative-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-collection-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-collection-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-collection-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-inverse-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-inverse-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-inverse-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-inverse-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-inverse-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-inverse-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-negated-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-negated-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-negated-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-negated-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-negated-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-negated-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-negated-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-negated-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-05.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-05.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-06.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-nested-06.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-05.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-05.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-06.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-06.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-07.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-sequence-07.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-05.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-05.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-06.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-06.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-cycles-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-cycles-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-cycles-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-cycles-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-cycles-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-cycles-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-cycles-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-reflexive-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/property-paths/sparql11-wildcard-reflexive-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/data-01.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/data-02.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/data-03.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/data-04.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/manifest.ttl create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-count-subquery-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-count-subquery-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-01.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-01.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-02.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-02.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-03.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-03.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-04.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-04.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-05.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-05.srx create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-06.rq create mode 100644 testsuites/sparql/src/main/resources/testcases-sparql-1.1/subquery/sparql11-subquery-06.srx create mode 100644 testsuites/sparql/src/main/resources/testdata-query/alp-testdata.ttl create mode 100644 testsuites/sparql/src/main/resources/testdata-query/dataset-describe.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-query/dataset-query.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-query/dataset-ses1081.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-query/dataset-ses1121.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-query/dataset-ses1692.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-query/dataset-ses1898.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-query/dataset-ses1913.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-query/dataset-ses1970.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-query/dataset-ses2024.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-query/defaultgraph.ttl create mode 100644 testsuites/sparql/src/main/resources/testdata-query/graph1.ttl create mode 100644 testsuites/sparql/src/main/resources/testdata-query/graph2.ttl create mode 100644 testsuites/sparql/src/main/resources/testdata-update/dataset-update-example9.trig create mode 100644 testsuites/sparql/src/main/resources/testdata-update/dataset-update.trig create mode 100644 testsuites/store/pom.xml create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/CascadeValueExceptionTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/EquivalentTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/GraphQueryResultTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/OptimisticIsolationTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/RDFSchemaRepositoryConnectionTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/RepositoryConnectionTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/RepositoryTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/SparqlAggregatesTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/SparqlDatasetTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/SparqlOrderByTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/SparqlRegexTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/SparqlSetBindingTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/TupleQueryResultTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/optimistic/DeadLockTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/optimistic/DeleteInsertTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/optimistic/LinearTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/optimistic/ModificationTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/optimistic/MonotonicTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/optimistic/RemoveIsolationTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/optimistic/SailIsolationLevelTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/optimistic/SerializableTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/repository/optimistic/SnapshotTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/sail/CustomGraphQueryInferencerTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/sail/InferencingTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/sail/RDFNotifyingStoreTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/sail/RDFStoreTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/sail/SailConcurrencyTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/sail/SailInterruptTest.java create mode 100644 testsuites/store/src/main/java/org/eclipse/rdf4j/sail/SailIsolationLevelTest.java create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/predicate-serql/delete.ru create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/predicate-serql/initial.ttl create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/predicate-serql/match.rq create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/predicate-serql/rule.rq create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/predicate/delete.ru create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/predicate/initial.ttl create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/predicate/match.rq create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/predicate/rule.rq create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/resource/delete.ru create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/resource/initial.ttl create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/resource/match.rq create mode 100644 testsuites/store/src/main/resources/testcases/custom-query-inferencing/resource/rule.rq create mode 100644 testsuites/store/src/main/resources/testcases/default-graph-1.ttl create mode 100644 testsuites/store/src/main/resources/testcases/default-graph.ttl create mode 100644 testsuites/store/src/main/resources/testcases/default-graph.ttl.gz create mode 100644 testsuites/store/src/main/resources/testcases/graph1.ttl create mode 100644 testsuites/store/src/main/resources/testcases/graph2.ttl create mode 100644 testsuites/store/src/main/resources/testcases/graph3.ttl create mode 100644 testsuites/store/src/main/resources/testcases/graphs.zip create mode 100644 testsuites/store/src/main/resources/testcases/malformed-literals.ttl create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/domain/error001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/domain/error001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/domain/test001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/domain/test001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/range/error001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/range/error001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/range/test001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/range/test001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subclassof/error001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subclassof/error001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subclassof/test001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subclassof/test001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subclassof/test002-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subclassof/test002-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subclassof/test003-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subclassof/test003-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subpropertyof/error001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subpropertyof/error001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subpropertyof/test001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subpropertyof/test001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subpropertyof/test002-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subpropertyof/test002-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subpropertyof/test003-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/subpropertyof/test003-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/error001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/error001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/error002-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/error002-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test001-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test001-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test002-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test002-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test003-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test003-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test004-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test004-out.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test005-in.nt create mode 100644 testsuites/store/src/main/resources/testcases/rdf-mt-inferencing/type/test005-out.nt diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..c00cc0a08cf --- /dev/null +++ b/.gitattributes @@ -0,0 +1,27 @@ +# default behaviour for when user does not have core.autocrlf set when set to +# 'auto', all line endings are normalized to LF (unix line endings) on checkin +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.java text +*.jsp text +*.jspf text +*.txt text +*.html text +*.xml text +*.css text +*.tld text +*.ts text +*.js text +*.tag text +*.sh text + +# dos batch files should retain windows line endings +*.bat text eol=crlf + +# binaries that should never be modified +*.png binary +*.jpg binary +*.gif binary + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..3e6881d57d1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# Eclipse settings +.project +**/.project +.classpath +**/.classpath +.settings +**/.settings +bin +**/bin + +# Eclipse Plug-In Settings +.pmd + +# Maven generated stuff +target/ +*/target/ +pom.xml.versionsBackup + +# GEdit generated stuff +*.*~ + +# IntelliJ files +.idea/ +*.iml +*.ipr +*.iws + +# Mac nonsense +.DS_Store diff --git a/about.html b/about.html new file mode 100644 index 00000000000..5cc42dcf2de --- /dev/null +++ b/about.html @@ -0,0 +1,105 @@ + + + + + +About this Content + + + +

About this Content

+

October 7, 2015

+ +

License

+ +

The Eclipse Foundation makes available all content in this + project ("Content"). Unless otherwise indicated below, the Content is + provided to you under the terms and conditions of the Eclipse + Distribution License Version 1.0 ("EDL"). See the file 'license.html' + accompanying this Content for details. A copy of the EDL is available + at https://www.eclipse.org/org/documents/edl-v10.php. For purposes of + the EPL, "Software" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse + Foundation, the Content is being redistributed by another party + ("Redistributor") and different terms and conditions may apply to your + use of any object code in the Content. Check the Redistributor's + license that was provided with the Content. If no such license exists, + contact the Redistributor. Unless otherwise indicated below, the terms + and conditions of the EDL still apply to any source code in the + Content and such source code may be obtained at + http://www.eclipse.org.

+ + +

Third Party Content

+ +

The Content includes items that have been sourced from third + parties as set out below. If you did not receive this Content directly + from the Eclipse Foundation, the following is provided for + informational purposes only, and you should look to the + Redistributor's license for terms and conditions of use.

+ +

Aduna

+ +

+ This project includes software developed by Aduna as part of the OpenRDF Sesame project. It is + licensed under the terms of the Aduna BSD-license. See the file + 'license.html' accompanying this project for details. +

+ +

Apache Software Foundation

+

+ This product includes various software packages developed by The Apache Software Foundation. Your + use of these software packages is governed by the terms and conditions + of the Apache Software License, v2.0. A copy of this license is + available at http://www.apache.org/licenses/LICENSE-2.0.html. +

+ +

JUnit

+ This product includes software developed by the JUnit project + (http://www.junit.org/). License: + http://junit.sourceforge.net/cpl-v10.html +

+

Yasqe

+

Parts of this product use software developed by Laurens Rietveld + (http://yasqe.yasgui.org/). License: + https://github.com/YASGUI/YASQE/blob/gh-pages/license.txt

+ +

Codemirror

+

Parts of this product use software developed by Marijn Haverbeke + et al. (http://codemirror.net/) License: http://codemirror.net/LICENSE +

+ +

jQuery

+

Parts of this product use software developed by the jQuery + Foundation et al. (https://jquery.com/) License: + https://github.com/jquery/jquery/blob/master/LICENSE.txt

+ +

JSON.org

+

Parts of this product use software developed by JSON.org + (http://www.json.org/). License: http://www.json.org/license.html

+ +

Mockito

+

Parts of this product use software developed by the Mockito + project (https://code.google.com/p/mockito/). License: + https://github.com/mockito/mockito/blob/master/LICENSE

+ +

FasterXML

+

Parts of this product use software developed by FasterXML, LLC + (https://fasterxml.com). License: + http://www.apache.org/licenses/LICENSE-2.0

+ +

Google Guava

+

Parts of this product use software developed by the Google Guava + project (https://github.com/google/guava/). License: + https://github.com/google/guava/blob/master/COPYING

+ +

Spatial4J

+

Parts of this product use software developed by the Spatial4j + project (https://github.com/spatial4j/spatial4j/). License: + https://github.com/spatial4j/spatial4j/blob/master/LICENSE.txt

+ + diff --git a/bom/pom.xml b/bom/pom.xml new file mode 100644 index 00000000000..0c120f174ec --- /dev/null +++ b/bom/pom.xml @@ -0,0 +1,390 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j + 4.1.0-SNAPSHOT + + + rdf4j-bom + pom + + RDF4J BOM + RDF4J Bill of Materials (BOM) + + + + + + + + org.eclipse.rdf4j + rdf4j-config + ${project.version} + + + org.eclipse.rdf4j + rdf4j-console + ${project.version} + + + org.eclipse.rdf4j + rdf4j-http-client + ${project.version} + + + org.eclipse.rdf4j + rdf4j-http-protocol + ${project.version} + + + org.eclipse.rdf4j + rdf4j-http-server + ${project.version} + + + org.eclipse.rdf4j + rdf4j-http-server-spring + ${project.version} + + + org.eclipse.rdf4j + rdf4j-http-workbench + ${project.version} + + + org.eclipse.rdf4j + rdf4j-model + ${project.version} + + + org.eclipse.rdf4j + rdf4j-query + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryalgebra-evaluation + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryalgebra-model + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryalgebra-geosparql + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryparser-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryparser-serql + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryparser-sparql + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryrender + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-binary + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-sparqljson + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-sparqlxml + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-text + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-contextaware + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-dataset + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-event + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-http + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-manager + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-sail + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-sparql + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-binary + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-datatypes + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-languages + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-n3 + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-nquads + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-ntriples + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-rdfjson + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-rdfxml + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-trig + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-trix + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-turtle + ${project.version} + + + org.eclipse.rdf4j + rdf4j-runtime + ${project.version} + + + org.eclipse.rdf4j + rdf4j-runtime-osgi + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-federation + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-inferencer + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-elasticsearch + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-lucene + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-lucene-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-lucene-test + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-lucene4 + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-lucenesail + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-solr + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-memory + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-nativerdf + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-rdbms + ${project.version} + + + org.eclipse.rdf4j + rdf4j-util + ${project.version} + + + + + + org.eclipse.rdf4j + rdf4j-http-compliance + ${project.version} + + + org.eclipse.rdf4j + rdf4j-model-compliance + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-compliance + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-compliance + ${project.version} + + + org.eclipse.rdf4j + rdf4j-serql-compliance + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sparql-compliance + ${project.version} + + + org.eclipse.rdf4j + rdf4j-geosparql-compliance + ${project.version} + + + org.eclipse.rdf4j + rdf4j-store-compliance + ${project.version} + + + + + + org.eclipse.rdf4j + rdf4j-model-testsuite + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-testsuite + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-testsuite + ${project.version} + + + org.eclipse.rdf4j + rdf4j-serql-testsuite + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sparql-testsuite + ${project.version} + + + org.eclipse.rdf4j + rdf4j-geosparql-testsuite + ${project.version} + + + org.eclipse.rdf4j + rdf4j-store-testsuite + ${project.version} + + + + diff --git a/compliance/geosparql/pom.xml b/compliance/geosparql/pom.xml new file mode 100644 index 00000000000..476b6ae8f4a --- /dev/null +++ b/compliance/geosparql/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-compliance + 4.1.0-SNAPSHOT + + + rdf4j-geosparql-compliance + + RDF4J GeoSPARQL compliance tests + Tests for the GeoSPARQL query language implementation + + + + ${project.groupId} + rdf4j-geosparql-testsuite + ${project.version} + + + ${project.groupId} + rdf4j-queryalgebra-geosparql + ${project.version} + + + + + + + org.apache.maven.plugins + maven-war-plugin + + ${project.build.directory}/openrdf-sesame + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + 1 + false + -Xmx512M -XX:MaxPermSize=256M + + **/*Test.java + + + + + integration-tests + integration-test + + integration-test + + + + verify + verify + + verify + + + + + + + diff --git a/compliance/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/geosparql/MemoryGeoSPARQLQueryTest.java b/compliance/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/geosparql/MemoryGeoSPARQLQueryTest.java new file mode 100644 index 00000000000..d66fa675e75 --- /dev/null +++ b/compliance/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/geosparql/MemoryGeoSPARQLQueryTest.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.geosparql; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.geosparql.GeoSPARQLManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemoryGeoSPARQLQueryTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return GeoSPARQLManifestTest.suite(new Factory() { + + @Override + public SPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, + false); + } + + @Override + public SPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + return new MemoryGeoSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder); + } + + }); + } + + protected MemoryGeoSPARQLQueryTest(String testURI, String name, String queryFileURL, String resultFileURL, + Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder); + } + + @Override + protected Repository newRepository() + throws Exception + { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/http/pom.xml b/compliance/http/pom.xml new file mode 100644 index 00000000000..0393fa39da6 --- /dev/null +++ b/compliance/http/pom.xml @@ -0,0 +1,188 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-compliance + 4.1.0-SNAPSHOT + + + rdf4j-http-compliance + war + + RDF4J HTTP server compliance tests + Tests for the HTTP server. + + + + ${project.groupId} + rdf4j-queryparser-api + ${project.version} + + + + ${project.groupId} + rdf4j-queryresultio-api + ${project.version} + + + + ${project.groupId} + rdf4j-queryresultio-binary + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-queryresultio-sparqljson + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-queryresultio-sparqlxml + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-rio-api + ${project.version} + + + + ${project.groupId} + rdf4j-rio-rdfxml + ${project.version} + runtime + + + + junit + junit + compile + + + + ${project.groupId} + rdf4j-http-server + ${project.version} + war + + + + ${project.groupId} + rdf4j-http-protocol + ${project.version} + + + + ${project.groupId} + rdf4j-repository-http + ${project.version} + + + + ${project.groupId} + rdf4j-repository-manager + ${project.version} + + + + ${project.groupId} + rdf4j-config + ${project.version} + + + + org.eclipse.jetty + jetty-server + 7.0.2.v20100331 + + + + org.eclipse.jetty + jetty-webapp + 7.0.2.v20100331 + + + + org.mortbay.jetty + jetty-jsp-2.1 + 7.0.2.v20100331 + runtime + + + + ch.qos.logback + logback-classic + test + + + org.slf4j + jcl-over-slf4j + test + + + org.slf4j + log4j-over-slf4j + test + + + + + + + + org.apache.maven.plugins + maven-war-plugin + + ${project.build.directory}/openrdf-sesame + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + 1 + false + -Xmx512M -XX:MaxPermSize=256M + + **/*Test.java + + + **/TestServer.java + + + + + integration-tests + integration-test + + integration-test + + + + verify + verify + + verify + + + + + + + + diff --git a/compliance/http/src/test/java/org/eclipse/rdf4j/http/server/ProtocolTest.java b/compliance/http/src/test/java/org/eclipse/rdf4j/http/server/ProtocolTest.java new file mode 100644 index 00000000000..6f7b8be47ea --- /dev/null +++ b/compliance/http/src/test/java/org/eclipse/rdf4j/http/server/ProtocolTest.java @@ -0,0 +1,664 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleIRI; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.resultio.QueryResultIO; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ProtocolTest { + + private static TestServer server; + + private static ValueFactory vf = SimpleValueFactory.getInstance(); + + @BeforeClass + public static void startServer() + throws Exception + { + server = new TestServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + } + + /** + * Tests the server's methods for updating all data in a repository. + */ + @Test + public void testRepository_PUT() + throws Exception + { + putFile(Protocol.getStatementsLocation(TestServer.REPOSITORY_URL), "/testcases/default-graph-1.ttl"); + } + + /** + * Tests the server's methods for deleting all data in a repository. + */ + @Test + public void testRepository_DELETE() + throws Exception + { + delete(Protocol.getStatementsLocation(TestServer.REPOSITORY_URL)); + } + + /** + * Tests the server's methods for updating the data in the default context of + * a repository. + */ + @Test + public void testNullContext_PUT() + throws Exception + { + String location = Protocol.getStatementsLocation(TestServer.REPOSITORY_URL); + location += "?" + Protocol.CONTEXT_PARAM_NAME + "=" + Protocol.NULL_PARAM_VALUE; + putFile(location, "/testcases/default-graph-1.ttl"); + } + + /** + * Tests the server's methods for deleting the data from the default context + * of a repository. + */ + @Test + public void testNullContext_DELETE() + throws Exception + { + String location = Protocol.getStatementsLocation(TestServer.REPOSITORY_URL); + location += "?" + Protocol.CONTEXT_PARAM_NAME + "=" + Protocol.NULL_PARAM_VALUE; + delete(location); + } + + /** + * Tests the server's methods for updating the data in a named context of a + * repository. + */ + @Test + public void testNamedContext_PUT() + throws Exception + { + String location = Protocol.getStatementsLocation(TestServer.REPOSITORY_URL); + String encContext = Protocol.encodeValue(vf.createIRI("urn:x-local:graph1")); + location += "?" + Protocol.CONTEXT_PARAM_NAME + "=" + encContext; + putFile(location, "/testcases/named-graph-1.ttl"); + } + + /** + * Tests the server's methods for deleting the data from a named context of a + * repository. + */ + @Test + public void testNamedContext_DELETE() + throws Exception + { + String location = Protocol.getStatementsLocation(TestServer.REPOSITORY_URL); + String encContext = Protocol.encodeValue(vf.createIRI("urn:x-local:graph1")); + location += "?" + Protocol.CONTEXT_PARAM_NAME + "=" + encContext; + delete(location); + } + + /** + * Tests the server's methods for quering a repository using GET requests to + * send SeRQL-select queries. + */ + @Test + public void testSeRQLselect() + throws Exception + { + TupleQueryResult queryResult = evaluateTupleQuery(TestServer.REPOSITORY_URL, "select * from {X} P {Y}", + QueryLanguage.SERQL); + QueryResultIO.writeTuple(queryResult, TupleQueryResultFormat.SPARQL, System.out); + } + + /** + * Checks that the server accepts a direct POST with a content type of + * "application/sparql-query". + */ + @Test + public void testQueryDirect_POST() + throws Exception + { + String query = "DESCRIBE "; + String location = TestServer.REPOSITORY_URL; + + CloseableHttpClient httpclient = HttpClients.createDefault(); + HttpPost post = new HttpPost(location); + HttpEntity entity = new StringEntity(query, ContentType.create(Protocol.SPARQL_QUERY_MIME_TYPE)); + post.setEntity(entity); + + CloseableHttpResponse response = httpclient.execute(post); + + System.out.println("Query Direct POST Status: " + response.getStatusLine()); + int statusCode = response.getStatusLine().getStatusCode(); + assertEquals(true, statusCode >= 200 && statusCode < 400); + } + + /** + * Checks that the server accepts a direct POST with a content type of + * "application/sparql-update". + */ + @Test + public void testUpdateDirect_POST() + throws Exception + { + String query = "delete where { ?p ?o }"; + String location = Protocol.getStatementsLocation(TestServer.REPOSITORY_URL); + + CloseableHttpClient httpclient = HttpClients.createDefault(); + HttpPost post = new HttpPost(location); + HttpEntity entity = new StringEntity(query, ContentType.create(Protocol.SPARQL_UPDATE_MIME_TYPE)); + post.setEntity(entity); + + CloseableHttpResponse response = httpclient.execute(post); + + System.out.println("Update Direct Post Status: " + response.getStatusLine()); + int statusCode = response.getStatusLine().getStatusCode(); + assertEquals(true, statusCode >= 200 && statusCode < 400); + } + + /** + * Checks that the requested content type is returned when accept header + * explicitly set. + */ + @Test + public void testContentTypeForGraphQuery1_GET() + throws Exception + { + String query = "DESCRIBE "; + String location = TestServer.REPOSITORY_URL; + location += "?query=" + URLEncoder.encode(query, "UTF-8"); + + URL url = new URL(location); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + + // Request RDF/XML formatted results: + conn.setRequestProperty("Accept", RDFFormat.RDFXML.getDefaultMIMEType()); + + conn.connect(); + + try { + int responseCode = conn.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + String contentType = conn.getHeaderField("Content-Type"); + assertNotNull(contentType); + + // snip off optional charset declaration + int charPos = contentType.indexOf(";"); + if (charPos > -1) { + contentType = contentType.substring(0, charPos); + } + + assertEquals(RDFFormat.RDFXML.getDefaultMIMEType(), contentType); + } + else { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + throw new RuntimeException(response); + } + } + finally { + conn.disconnect(); + } + } + + /** + * Checks that a proper error (HTTP 406) is returned when accept header is + * set incorrectly on graph query. + */ + @Test + public void testContentTypeForGraphQuery2_GET() + throws Exception + { + String query = "DESCRIBE "; + String location = TestServer.REPOSITORY_URL; + location += "?query=" + URLEncoder.encode(query, "UTF-8"); + + URL url = new URL(location); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + + // incorrect mime-type for graph query results + conn.setRequestProperty("Accept", TupleQueryResultFormat.SPARQL.getDefaultMIMEType()); + + conn.connect(); + + try { + int responseCode = conn.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_NOT_ACCEPTABLE) { + // do nothing, expected + } + else { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + } + } + finally { + conn.disconnect(); + } + } + + /** + * Checks that a suitable RDF content type is returned when accept header not + * explicitly set. + */ + @Test + public void testContentTypeForGraphQuery3_GET() + throws Exception + { + String query = "DESCRIBE "; + String location = TestServer.REPOSITORY_URL; + location += "?query=" + URLEncoder.encode(query, "UTF-8"); + + URL url = new URL(location); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + + conn.connect(); + + try { + int responseCode = conn.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + String contentType = conn.getHeaderField("Content-Type"); + assertNotNull(contentType); + + // snip off optional charset declaration + int charPos = contentType.indexOf(";"); + if (charPos > -1) { + contentType = contentType.substring(0, charPos); + } + + RDFFormat format = Rio.getParserFormatForMIMEType(contentType).orElseThrow( + Rio.unsupportedFormat(contentType)); + assertNotNull(format); + } + else { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + throw new RuntimeException(response); + } + } + finally { + conn.disconnect(); + } + } + + @Test + public void testQueryResponse_HEAD() + throws Exception + { + String query = "DESCRIBE "; + String location = TestServer.REPOSITORY_URL; + location += "?query=" + URLEncoder.encode(query, "UTF-8"); + + URL url = new URL(location); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod("HEAD"); + + // Request RDF/XML formatted results: + conn.setRequestProperty("Accept", RDFFormat.RDFXML.getDefaultMIMEType()); + + conn.connect(); + + try { + int responseCode = conn.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + String contentType = conn.getHeaderField("Content-Type"); + assertNotNull(contentType); + + // snip off optional charset declaration + int charPos = contentType.indexOf(";"); + if (charPos > -1) { + contentType = contentType.substring(0, charPos); + } + + assertEquals(RDFFormat.RDFXML.getDefaultMIMEType(), contentType); + assertEquals(0, conn.getContentLength()); + } + else { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + throw new RuntimeException(response); + } + } + finally { + conn.disconnect(); + } + } + + @Test + public void testUpdateResponse_HEAD() + throws Exception + { + String query = "INSERT DATA { \"foo\". } "; + String location = Protocol.getStatementsLocation(TestServer.REPOSITORY_URL); + location += "?update=" + URLEncoder.encode(query, "UTF-8"); + + URL url = new URL(location); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod("HEAD"); + + conn.connect(); + + try { + int responseCode = conn.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + String contentType = conn.getHeaderField("Content-Type"); + assertNotNull(contentType); + + // snip off optional charset declaration + int charPos = contentType.indexOf(";"); + if (charPos > -1) { + contentType = contentType.substring(0, charPos); + } + + assertEquals(0, conn.getContentLength()); + } + else { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + throw new RuntimeException(response); + } + } + finally { + conn.disconnect(); + } + } + + /** + * Test for SES-1861 + * + * @throws Exception + */ + @Test + public void testSequentialNamespaceUpdates() + throws Exception + { + int limitCount = 1000; + int limitPrefix = 50; + + Random prng = new Random(); + // String repositoryLocation = + // Protocol.getRepositoryLocation("http://localhost:8080/openrdf-sesame", + // "Test-NativeStore"); + String repositoryLocation = TestServer.REPOSITORY_URL; + + for (int count = 0; count < limitCount; count++) { + int i = prng.nextInt(limitPrefix); + String prefix = "prefix" + i; + String ns = "http://example.org/namespace" + i; + + String location = Protocol.getNamespacePrefixLocation(repositoryLocation, prefix); + + if (count % 2 == 0) { + putNamespace(location, ns); + } + else { + deleteNamespace(location); + } + } + } + + /** + * Test for SES-1861 + * + * @throws Exception + */ + @Test + public void testConcurrentNamespaceUpdates() + throws Exception + { + int limitCount = 1000; + int limitPrefix = 50; + + Random prng = new Random(); + + // String repositoryLocation = + // Protocol.getRepositoryLocation("http://localhost:8080/openrdf-sesame", + // "Test-NativeStore"); + String repositoryLocation = TestServer.REPOSITORY_URL; + + ExecutorService threadPool = Executors.newFixedThreadPool(20); + + for (int count = 0; count < limitCount; count++) { + final int number = count; + final int i = prng.nextInt(limitPrefix); + final String prefix = "prefix" + i; + final String ns = "http://example.org/namespace" + i; + + final String location = Protocol.getNamespacePrefixLocation(repositoryLocation, prefix); + + Runnable runner = new Runnable() { + + public void run() { + try { + if (number % 2 == 0) { + putNamespace(location, ns); + } + else { + deleteNamespace(location); + } + } + catch (Exception e) { + e.printStackTrace(); + fail("Failed in test: " + number); + } + } + }; + threadPool.execute(runner); + } + threadPool.shutdown(); + threadPool.awaitTermination(30000, TimeUnit.MILLISECONDS); + threadPool.shutdownNow(); + } + + private void putNamespace(String location, String namespace) + throws Exception + { + // System.out.println("Put namespace to " + location); + + URL url = new URL(location); + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod("PUT"); + conn.setDoOutput(true); + + InputStream dataStream = new ByteArrayInputStream(namespace.getBytes("UTF-8")); + try { + OutputStream connOut = conn.getOutputStream(); + + try { + IOUtil.transfer(dataStream, connOut); + } + finally { + connOut.close(); + } + } + finally { + dataStream.close(); + } + + conn.connect(); + + int responseCode = conn.getResponseCode(); + + if (responseCode != HttpURLConnection.HTTP_OK && // 200 OK + responseCode != HttpURLConnection.HTTP_NO_CONTENT) // 204 NO CONTENT + { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + } + } + + private void deleteNamespace(String location) + throws Exception + { + // System.out.println("Delete namespace at " + location); + + URL url = new URL(location); + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod("DELETE"); + conn.setDoOutput(true); + + conn.connect(); + + int responseCode = conn.getResponseCode(); + + if (responseCode != HttpURLConnection.HTTP_OK && // 200 OK + responseCode != HttpURLConnection.HTTP_NO_CONTENT) // 204 NO CONTENT + { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + } + } + + private void putFile(String location, String file) + throws Exception + { + System.out.println("Put file to " + location); + + URL url = new URL(location); + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod("PUT"); + conn.setDoOutput(true); + + RDFFormat dataFormat = Rio.getParserFormatForFileName(file).orElse(RDFFormat.RDFXML); + conn.setRequestProperty("Content-Type", dataFormat.getDefaultMIMEType()); + + InputStream dataStream = ProtocolTest.class.getResourceAsStream(file); + try { + OutputStream connOut = conn.getOutputStream(); + + try { + IOUtil.transfer(dataStream, connOut); + } + finally { + connOut.close(); + } + } + finally { + dataStream.close(); + } + + conn.connect(); + + int responseCode = conn.getResponseCode(); + + if (responseCode != HttpURLConnection.HTTP_OK && // 200 OK + responseCode != HttpURLConnection.HTTP_NO_CONTENT) // 204 NO CONTENT + { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + } + } + + private void delete(String location) + throws Exception + { + URL url = new URL(location); + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod("DELETE"); + + conn.connect(); + + int responseCode = conn.getResponseCode(); + + if (responseCode != HttpURLConnection.HTTP_OK && // 200 OK + responseCode != HttpURLConnection.HTTP_NO_CONTENT) // 204 NO CONTENT + { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + } + } + + private TupleQueryResult evaluateTupleQuery(String location, String query, QueryLanguage queryLn) + throws Exception + { + location += "?query=" + URLEncoder.encode(query, "UTF-8") + "&queryLn=" + queryLn.getName(); + + URL url = new URL(location); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + + // Request SPARQL-XML formatted results: + conn.setRequestProperty("Accept", TupleQueryResultFormat.SPARQL.getDefaultMIMEType()); + + conn.connect(); + + try { + int responseCode = conn.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + // Process query results + return QueryResultIO.parseTuple(conn.getInputStream(), TupleQueryResultFormat.SPARQL); + } + else { + String response = "location " + location + " responded: " + conn.getResponseMessage() + " (" + + responseCode + ")"; + fail(response); + throw new RuntimeException(response); + } + } + finally { + conn.disconnect(); + } + } + +} diff --git a/compliance/http/src/test/java/org/eclipse/rdf4j/http/server/TestServer.java b/compliance/http/src/test/java/org/eclipse/rdf4j/http/server/TestServer.java new file mode 100644 index 00000000000..003e4cbe7c0 --- /dev/null +++ b/compliance/http/src/test/java/org/eclipse/rdf4j/http/server/TestServer.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +import java.io.File; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.nio.BlockingChannelConnector; +import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigUtil; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.repository.manager.SystemRepository; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.sail.inferencer.fc.config.ForwardChainingRDFSInferencerConfig; +import org.eclipse.rdf4j.sail.memory.config.MemoryStoreConfig; + +/** + * @author Herko ter Horst + */ +public class TestServer { + + private static final String HOST = "localhost"; + + private static final int PORT = 18080; + + private static final String TEST_REPO_ID = "Test"; + + private static final String TEST_INFERENCE_REPO_ID = "Test-RDFS"; + + private static final String OPENRDF_CONTEXT = "/openrdf"; + + private static final String SERVER_URL = "http://" + HOST + ":" + PORT + OPENRDF_CONTEXT; + + public static String REPOSITORY_URL = Protocol.getRepositoryLocation(SERVER_URL, TEST_REPO_ID); + + private final Server jetty; + + public TestServer() { + System.clearProperty("DEBUG"); + + jetty = new Server(); + + Connector conn = new BlockingChannelConnector(); + conn.setHost(HOST); + conn.setPort(PORT); + jetty.addConnector(conn); + + WebAppContext webapp = new WebAppContext(); + webapp.addSystemClass("org.slf4j."); + webapp.addSystemClass("ch.qos.logback."); + webapp.setContextPath(OPENRDF_CONTEXT); + // warPath configured in pom.xml maven-war-plugin configuration + webapp.setWar("./target/openrdf-sesame"); + jetty.setHandler(webapp); + } + + public void start() + throws Exception + { + File dataDir = new File(System.getProperty("user.dir") + "/target/datadir"); + dataDir.mkdirs(); + System.setProperty("info.aduna.platform.appdata.basedir", dataDir.getAbsolutePath()); + + jetty.start(); + + createTestRepositories(); + } + + public void stop() + throws Exception + { + Repository systemRepo = new HTTPRepository(Protocol.getRepositoryLocation(SERVER_URL, + SystemRepository.ID)); + RepositoryConnection con = systemRepo.getConnection(); + try { + con.clear(); + } + finally { + con.close(); + } + + jetty.stop(); + System.clearProperty("org.mortbay.log.class"); + } + + private void createTestRepositories() + throws RepositoryException, RepositoryConfigException + { + Repository systemRep = new HTTPRepository(Protocol.getRepositoryLocation(SERVER_URL, + SystemRepository.ID)); + + // create a (non-inferencing) memory store + MemoryStoreConfig memStoreConfig = new MemoryStoreConfig(); + SailRepositoryConfig sailRepConfig = new SailRepositoryConfig(memStoreConfig); + RepositoryConfig repConfig = new RepositoryConfig(TEST_REPO_ID, sailRepConfig); + + RepositoryConfigUtil.updateRepositoryConfigs(systemRep, repConfig); + + // create an inferencing memory store + ForwardChainingRDFSInferencerConfig inferMemStoreConfig = new ForwardChainingRDFSInferencerConfig( + new MemoryStoreConfig()); + sailRepConfig = new SailRepositoryConfig(inferMemStoreConfig); + repConfig = new RepositoryConfig(TEST_INFERENCE_REPO_ID, sailRepConfig); + + RepositoryConfigUtil.updateRepositoryConfigs(systemRep, repConfig); + } +} diff --git a/compliance/http/src/test/resources/log4j.properties b/compliance/http/src/test/resources/log4j.properties new file mode 100644 index 00000000000..885932a0ea6 --- /dev/null +++ b/compliance/http/src/test/resources/log4j.properties @@ -0,0 +1,18 @@ +# root logger +log4j.rootLogger=WARN, MainLog + +# MainLog configuration +log4j.appender.MainLog=org.apache.log4j.DailyRollingFileAppender +log4j.appender.MainLog.DatePattern='.'yyyy-MM-dd +# Real filename is set in AppConfiguration, relative to dataDir +log4j.appender.MainLog.File=target/combined-client-server.log + +# MainLog uses a custom PatternLayout that also outputs stack traces +log4j.appender.MainLog.layout=info.aduna.logging.file.log4j.StackTracePatternLayout + +# OpenRDF logging +log4j.logger.org.openrdf=DEBUG + +# Aduna logging +log4j.logger.info.aduna.iteration=DEBUG +log4j.logger.info.aduna.collections=DEBUG diff --git a/compliance/http/src/test/resources/logback-test.xml b/compliance/http/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..4a6f17fbfa4 --- /dev/null +++ b/compliance/http/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + diff --git a/compliance/http/src/test/resources/testcases/default-graph-1.ttl b/compliance/http/src/test/resources/testcases/default-graph-1.ttl new file mode 100644 index 00000000000..a6a4ee05846 --- /dev/null +++ b/compliance/http/src/test/resources/testcases/default-graph-1.ttl @@ -0,0 +1,9 @@ +# Default graph +@prefix dc: . +@prefix xsd: . + + dc:publisher "Bob" . + dc:date "2004-12-06T00:00:00Z"^^xsd:dateTime . + + dc:publisher "Bob" . + dc:date "2005-01-10T00:00:00Z"^^xsd:dateTime . \ No newline at end of file diff --git a/compliance/http/src/test/resources/testcases/named-graph-1.ttl b/compliance/http/src/test/resources/testcases/named-graph-1.ttl new file mode 100644 index 00000000000..0f13fbddb02 --- /dev/null +++ b/compliance/http/src/test/resources/testcases/named-graph-1.ttl @@ -0,0 +1,8 @@ +# named graph: urn:x-local:graph1 +@prefix foaf: . + +_:a foaf:name "Alice" . +_:a foaf:mbox . + +_:b foaf:name "Bob" . +_:b foaf:mbox . \ No newline at end of file diff --git a/compliance/model/pom.xml b/compliance/model/pom.xml new file mode 100644 index 00000000000..da36f04a226 --- /dev/null +++ b/compliance/model/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-compliance + 4.1.0-SNAPSHOT + + + rdf4j-model-compliance + + RDF4J Model compliance test + Tests for RDF4J Model + + + + ${project.groupId} + rdf4j-runtime + ${project.version} + + + + ${project.groupId} + rdf4j-model-testsuite + ${project.version} + + + + + ${project.groupId} + rdf4j-sail-memory + ${project.version} + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + 1 + false + -Xmx512M -XX:MaxPermSize=256M + + **/*Test.java + + + **/TestServer.java + + + + + integration-tests + integration-test + + integration-test + + + + verify + verify + + verify + + + + + + + + diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelEqualityTest.java b/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelEqualityTest.java new file mode 100644 index 00000000000..ff98680da56 --- /dev/null +++ b/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelEqualityTest.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.ModelEqualityTest; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; + +/** + * @author Arjohn Kampman + */ +public class LinkedHashModelEqualityTest extends ModelEqualityTest { + protected Model createEmptyModel() + { + return new LinkedHashModel(); + } +} diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelNamespacesTest.java b/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelNamespacesTest.java new file mode 100644 index 00000000000..9d872a6fe32 --- /dev/null +++ b/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelNamespacesTest.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.ModelNamespacesTest; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; + +/** + * Tests for {@link Namespace} support in {@link LinkedHashModel} using the + * abstract tests defined in {@link ModelNamespacesTest}. + * + * @author Peter Ansell p_ansell@yahoo.com + */ +public class LinkedHashModelNamespacesTest extends ModelNamespacesTest { + + @Override + protected Model getModelImplementation() { + return new LinkedHashModel(); + } + +} diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelTest.java b/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelTest.java new file mode 100644 index 00000000000..7dcc2109fb4 --- /dev/null +++ b/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelTest.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.LinkedHashModelTest; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.ModelTest; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; + +import junit.framework.Test; + +public class LinkedHashModelTest extends ModelTest { + + public static Test suite() throws Exception { + return ModelTest.suite(LinkedHashModelTest.class); + } + + public LinkedHashModelTest(String name) { + super(name); + } + + public Model makeEmptyModel() { + return new LinkedHashModel(); + } +} diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelWithValueFactoryTest.java b/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelWithValueFactoryTest.java new file mode 100644 index 00000000000..29363aba705 --- /dev/null +++ b/compliance/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelWithValueFactoryTest.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.ModelTest; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; + +import junit.framework.Test; + +/** + * ValueFactory is not serializable. This test ensures that the + * LinkedHashModel's getValueFactory() does not try to serialize a ValueFactory + * with it. + * + * @author James Leigh + */ +public class LinkedHashModelWithValueFactoryTest extends ModelTest { + + public static Test suite() throws Exception { + return ModelTest.suite(LinkedHashModelWithValueFactoryTest.class); + } + + public LinkedHashModelWithValueFactoryTest(String name) { + super(name); + } + + public Model makeEmptyModel() { + LinkedHashModel model = new LinkedHashModel(); + model.getValueFactory(); + return model; + } +} diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelNamespacesTest.java b/compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelNamespacesTest.java new file mode 100644 index 00000000000..c73dc9b98b2 --- /dev/null +++ b/compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelNamespacesTest.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.ModelNamespacesTest; +import org.eclipse.rdf4j.model.util.ModelException; +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.SailConnection; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.eclipse.rdf4j.sail.model.SailModel; + + +/** + * + * @author Mark + */ +public class SailModelNamespacesTest extends ModelNamespacesTest { + private Sail sail; + private SailConnection conn; + + @Override + protected Model getModelImplementation() { + sail = new MemoryStore(); + try { + sail.initialize(); + conn = sail.getConnection(); + conn.begin(); + return new SailModel(conn, false); + } catch (SailException e) { + throw new ModelException(e); + } + } + + @Override + public void tearDown() throws Exception { + if(conn != null) { + conn.commit(); + conn.close(); + conn = null; + } + if(sail != null) { + sail.shutDown(); + sail = null; + } + super.tearDown(); + } +} diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelTest.java b/compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelTest.java new file mode 100644 index 00000000000..a5773aea378 --- /dev/null +++ b/compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelTest.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import junit.framework.Test; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.ModelTest; +import org.eclipse.rdf4j.model.util.ModelException; +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.SailConnection; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.eclipse.rdf4j.sail.model.SailModel; + +/** + * + * @author Mark + */ +public class SailModelTest extends ModelTest { + private Sail sail; + private SailConnection conn; + + public static Test suite() throws Exception { + return ModelTest.suite(SailModelTest.class); + } + + public SailModelTest(String name) { + super(name); + } + + @Override + public Model makeEmptyModel() { + sail = new MemoryStore(); + try { + sail.initialize(); + conn = sail.getConnection(); + conn.begin(); + return new SailModel(conn, false); + } catch (SailException e) { + throw new ModelException(e); + } + } + + @Override + protected void tearDown() throws Exception { + if(conn != null) { + conn.commit(); + conn.close(); + conn = null; + } + if(sail != null) { + sail.shutDown(); + sail = null; + } + super.tearDown(); + } +} diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelEqualityTest.java b/compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelEqualityTest.java new file mode 100644 index 00000000000..a917bc75ce2 --- /dev/null +++ b/compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelEqualityTest.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.ModelEqualityTest; +import org.eclipse.rdf4j.model.impl.TreeModel; + +/** + * @author Arjohn Kampman + */ +public class TreeModelEqualityTest extends ModelEqualityTest { + @Override + protected Model createEmptyModel() + { + return new TreeModel(); + } +} diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelNamespacesTest.java b/compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelNamespacesTest.java new file mode 100644 index 00000000000..507620be1ef --- /dev/null +++ b/compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelNamespacesTest.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.ModelNamespacesTest; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.impl.TreeModel; + +/** + * Tests for {@link Namespace} support in {@link TreeModel} using the abstract + * tests defined in {@link ModelNamespacesTest}. + * + * @author Peter Ansell p_ansell@yahoo.com + */ +public class TreeModelNamespacesTest extends ModelNamespacesTest { + + @Override + protected Model getModelImplementation() { + return new TreeModel(); + } + +} diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelTest.java b/compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelTest.java new file mode 100644 index 00000000000..2ec93e0a2c7 --- /dev/null +++ b/compliance/model/src/test/java/org/eclipse/rdf4j/model/TreeModelTest.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.ModelTest; +import org.eclipse.rdf4j.model.TreeModelTest; +import org.eclipse.rdf4j.model.impl.TreeModel; + +import junit.framework.Test; + +public class TreeModelTest extends ModelTest { + + public static Test suite() throws Exception { + return ModelTest.suite(TreeModelTest.class); + } + + public TreeModelTest(String name) { + super(name); + } + + public Model makeEmptyModel() { + return new TreeModel(); + } +} diff --git a/compliance/model/src/test/resources/logback-test.xml b/compliance/model/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..8abddfeaaa1 --- /dev/null +++ b/compliance/model/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + diff --git a/compliance/pom.xml b/compliance/pom.xml new file mode 100644 index 00000000000..f368bc07c3d --- /dev/null +++ b/compliance/pom.xml @@ -0,0 +1,68 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j + 4.1.0-SNAPSHOT + + + rdf4j-compliance + pom + + + model + queryresultio + rio + http + store + serql + sparql + geosparql + + + RDF4J compliance tests + RDF4J compliance tests + + + + + ${project.groupId} + rdf4j-http-compliance + ${project.version} + + + + ${project.groupId} + rdf4j-rio-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-store-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-serql-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-sparql-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-queryparser-sparql-compliance + ${project.version} + + + + + diff --git a/compliance/queryresultio/pom.xml b/compliance/queryresultio/pom.xml new file mode 100644 index 00000000000..8ffb4660304 --- /dev/null +++ b/compliance/queryresultio/pom.xml @@ -0,0 +1,102 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-compliance + 4.1.0-SNAPSHOT + + + rdf4j-queryresultio-compliance + + RDF4J Query Result IO compliance tests + Tests for parsers and writers of various Query Results file formats. + + + + ${project.groupId} + rdf4j-runtime + ${project.version} + + + + ${project.groupId} + rdf4j-repository-sail + ${project.version} + + + + ${project.groupId} + rdf4j-sail-memory + ${project.version} + + + + ${project.groupId} + rdf4j-queryresultio-testsuite + ${project.version} + + + + junit + junit + test + + + + ch.qos.logback + logback-classic + test + + + org.slf4j + jcl-over-slf4j + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + 1 + false + -Xmx512M -XX:MaxPermSize=256M + + **/*Test.java + + + **/N3ParserTest.java + + + + + integration-tests + integration-test + + integration-test + + + + verify + verify + + verify + + + + + + + + diff --git a/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/binary/SPARQLBinaryTupleTest.java b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/binary/SPARQLBinaryTupleTest.java new file mode 100644 index 00000000000..ff5edae3fb5 --- /dev/null +++ b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/binary/SPARQLBinaryTupleTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.resultio.binary; + +import org.eclipse.rdf4j.query.resultio.AbstractQueryResultIOTupleTest; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; + +/** + * @author Peter Ansell + */ +public class SPARQLBinaryTupleTest extends AbstractQueryResultIOTupleTest { + + @Override + protected String getFileName() { + return "test.brt"; + } + + @Override + protected TupleQueryResultFormat getTupleFormat() { + return TupleQueryResultFormat.BINARY; + } + + @Override + protected BooleanQueryResultFormat getMatchingBooleanFormatOrNull() { + return null; + } +} diff --git a/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLJSONBooleanTest.java b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLJSONBooleanTest.java new file mode 100644 index 00000000000..2dd369e89d7 --- /dev/null +++ b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLJSONBooleanTest.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.resultio.sparqljson; + +import static org.junit.Assert.*; + +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.resultio.AbstractQueryResultIOBooleanTest; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.helpers.QueryResultCollector; +import org.eclipse.rdf4j.query.resultio.sparqljson.SPARQLBooleanJSONParser; +import org.junit.Test; + +/** + * @author Peter Ansell + * @author Sebastian Schaffert + */ +public class SPARQLJSONBooleanTest extends AbstractQueryResultIOBooleanTest { + + @Override + protected String getFileName() { + return "test.srj"; + } + + @Override + protected BooleanQueryResultFormat getBooleanFormat() { + return BooleanQueryResultFormat.JSON; + } + + @Override + protected TupleQueryResultFormat getMatchingTupleFormatOrNull() { + return TupleQueryResultFormat.JSON; + } + + @Test + public void testBoolean1() + throws Exception + { + SPARQLBooleanJSONParser parser = new SPARQLBooleanJSONParser(SimpleValueFactory.getInstance()); + QueryResultCollector handler = new QueryResultCollector(); + parser.setQueryResultHandler(handler); + + parser.parseQueryResult(this.getClass().getResourceAsStream("/sparqljson/boolean1.srj")); + + assertTrue(handler.getBoolean()); + } + + @Test + public void testBoolean2() + throws Exception + { + SPARQLBooleanJSONParser parser = new SPARQLBooleanJSONParser(SimpleValueFactory.getInstance()); + QueryResultCollector handler = new QueryResultCollector(); + parser.setQueryResultHandler(handler); + + parser.parseQueryResult(this.getClass().getResourceAsStream("/sparqljson/boolean2.srj")); + + assertTrue(handler.getBoolean()); + } + + @Test + public void testBoolean3() + throws Exception + { + SPARQLBooleanJSONParser parser = new SPARQLBooleanJSONParser(SimpleValueFactory.getInstance()); + QueryResultCollector handler = new QueryResultCollector(); + parser.setQueryResultHandler(handler); + + parser.parseQueryResult(this.getClass().getResourceAsStream("/sparqljson/boolean3.srj")); + + assertFalse(handler.getBoolean()); + } + + @Test + public void testBoolean4() + throws Exception + { + SPARQLBooleanJSONParser parser = new SPARQLBooleanJSONParser(SimpleValueFactory.getInstance()); + QueryResultCollector handler = new QueryResultCollector(); + parser.setQueryResultHandler(handler); + + parser.parseQueryResult(this.getClass().getResourceAsStream("/sparqljson/boolean4.srj")); + + assertFalse(handler.getBoolean()); + } + +} diff --git a/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLJSONTupleTest.java b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLJSONTupleTest.java new file mode 100644 index 00000000000..25afc7ab206 --- /dev/null +++ b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqljson/SPARQLJSONTupleTest.java @@ -0,0 +1,271 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.resultio.sparqljson; + +import static org.junit.Assert.*; + +import java.io.InputStream; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.resultio.AbstractQueryResultIOTupleTest; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.helpers.QueryResultCollector; +import org.eclipse.rdf4j.query.resultio.sparqljson.SPARQLResultsJSONParser; +import org.junit.Test; + +/** + * @author Peter Ansell + * @author Sebastian Schaffert + */ +public class SPARQLJSONTupleTest extends AbstractQueryResultIOTupleTest { + + @Override + protected String getFileName() { + return "test.srj"; + } + + @Override + protected TupleQueryResultFormat getTupleFormat() { + return TupleQueryResultFormat.JSON; + } + + @Override + protected BooleanQueryResultFormat getMatchingBooleanFormatOrNull() { + return BooleanQueryResultFormat.JSON; + } + + @Test + public void testBindings1() + throws Exception + { + SPARQLResultsJSONParser parser = new SPARQLResultsJSONParser(SimpleValueFactory.getInstance()); + QueryResultCollector handler = new QueryResultCollector(); + parser.setQueryResultHandler(handler); + + InputStream stream = this.getClass().getResourceAsStream("/sparqljson/bindings1.srj"); + assertNotNull("Could not find test resource", stream); + parser.parseQueryResult(stream); + + // there must be two variables + assertEquals(2, handler.getBindingNames().size()); + + // first must be called "book", the second "title" + assertEquals("book", handler.getBindingNames().get(0)); + assertEquals("title", handler.getBindingNames().get(1)); + + // should be 7 solutions alltogether + assertEquals(7, handler.getBindingSets().size()); + + // Results are ordered, so first should be book6 + assertEquals("http://example.org/book/book6", + handler.getBindingSets().get(0).getValue("book").stringValue()); + + for (BindingSet b : handler.getBindingSets()) { + assertNotNull(b.getValue("book")); + assertNotNull(b.getValue("title")); + assertTrue(b.getValue("book") instanceof IRI); + assertTrue(b.getValue("title") instanceof Literal); + + IRI book = (IRI)b.getValue("book"); + if (book.stringValue().equals("http://example.org/book/book6")) { + assertEquals("Harry Potter and the Half-Blood Prince", b.getValue("title").stringValue()); + } + else if (book.stringValue().equals("http://example.org/book/book7")) { + assertEquals("Harry Potter and the Deathly Hallows", b.getValue("title").stringValue()); + } + else if (book.stringValue().equals("http://example.org/book/book5")) { + assertEquals("Harry Potter and the Order of the Phoenix", b.getValue("title").stringValue()); + } + else if (book.stringValue().equals("http://example.org/book/book4")) { + assertEquals("Harry Potter and the Goblet of Fire", b.getValue("title").stringValue()); + } + else if (book.stringValue().equals("http://example.org/book/book2")) { + assertEquals("Harry Potter and the Chamber of Secrets", b.getValue("title").stringValue()); + } + else if (book.stringValue().equals("http://example.org/book/book3")) { + assertEquals("Harry Potter and the Prisoner Of Azkaban", b.getValue("title").stringValue()); + } + else if (book.stringValue().equals("http://example.org/book/book1")) { + assertEquals("Harry Potter and the Philosopher's Stone", b.getValue("title").stringValue()); + } + else { + fail("Found unexpected binding set in result: " + b.toString()); + } + } + + } + + @Test + public void testBindings2() + throws Exception + { + SPARQLResultsJSONParser parser = new SPARQLResultsJSONParser(SimpleValueFactory.getInstance()); + QueryResultCollector handler = new QueryResultCollector(); + parser.setQueryResultHandler(handler); + + InputStream stream = this.getClass().getResourceAsStream("/sparqljson/bindings2.srj"); + assertNotNull("Could not find test resource", stream); + parser.parseQueryResult(stream); + + // there must be 7 variables + assertEquals(7, handler.getBindingNames().size()); + + // first must be called "x", etc., + assertEquals("x", handler.getBindingNames().get(0)); + assertEquals("hpage", handler.getBindingNames().get(1)); + assertEquals("name", handler.getBindingNames().get(2)); + assertEquals("mbox", handler.getBindingNames().get(3)); + assertEquals("age", handler.getBindingNames().get(4)); + assertEquals("blurb", handler.getBindingNames().get(5)); + assertEquals("friend", handler.getBindingNames().get(6)); + + // 2 results + assertEquals(2, handler.getBindingSets().size()); + + // Results are ordered, so first should be alice + assertEquals("http://work.example.org/alice/", + handler.getBindingSets().get(0).getValue("hpage").stringValue()); + + for (BindingSet b : handler.getBindingSets()) { + + assertNotNull(b.getValue("x")); + assertNotNull(b.getValue("hpage")); + assertNotNull(b.getValue("name")); + assertNotNull(b.getValue("mbox")); + assertNotNull(b.getValue("friend")); + + assertTrue(b.getValue("x") instanceof BNode); + assertTrue(b.getValue("hpage") instanceof IRI); + assertTrue(b.getValue("name") instanceof Literal); + assertTrue(b.getValue("friend") instanceof BNode); + + BNode value = (BNode)b.getValue("x"); + + if (value.getID().equals("r1")) { + assertNotNull(b.getValue("blurb")); + + assertTrue(b.getValue("mbox") instanceof Literal); + assertTrue(b.getValue("blurb") instanceof Literal); + + assertEquals("http://work.example.org/alice/", b.getValue("hpage").stringValue()); + + Literal name = (Literal)b.getValue("name"); + assertEquals("Alice", name.stringValue()); + assertFalse(name.getLanguage().isPresent()); + assertEquals(XMLSchema.STRING, name.getDatatype()); + + Literal mbox = (Literal)b.getValue("mbox"); + assertEquals("", mbox.stringValue()); + assertFalse(mbox.getLanguage().isPresent()); + assertEquals(XMLSchema.STRING, mbox.getDatatype()); + + Literal blurb = (Literal)b.getValue("blurb"); + assertEquals("

My name is alice

", + blurb.stringValue()); + assertFalse(blurb.getLanguage().isPresent()); + assertEquals(RDF.XMLLITERAL, blurb.getDatatype()); + } + else if (value.getID().equals("r2")) { + assertNull(b.getValue("blurb")); + + assertTrue(b.getValue("mbox") instanceof IRI); + + assertEquals("http://work.example.org/bob/", b.getValue("hpage").stringValue()); + + Literal name = (Literal)b.getValue("name"); + assertEquals("Bob", name.stringValue()); + assertEquals("en", name.getLanguage().orElse(null)); + assertEquals(RDF.LANGSTRING, name.getDatatype()); + + assertEquals("mailto:bob@work.example.org", b.getValue("mbox").stringValue()); + } + else { + fail("Found unexpected binding set in result: " + b.toString()); + } + } + + assertEquals(1, handler.getLinks().size()); + assertEquals("http://www.w3.org/TR/2013/REC-sparql11-results-json-20130321/#example", + handler.getLinks().get(0)); + + } + + @Test + public void testNonStandardDistinct() + throws Exception + { + SPARQLResultsJSONParser parser = new SPARQLResultsJSONParser(SimpleValueFactory.getInstance()); + QueryResultCollector handler = new QueryResultCollector(); + parser.setQueryResultHandler(handler); + + InputStream stream = this.getClass().getResourceAsStream("/sparqljson/non-standard-distinct.srj"); + assertNotNull("Could not find test resource", stream); + parser.parseQueryResult(stream); + + // there must be 1 variable + assertEquals(1, handler.getBindingNames().size()); + + // first must be called "Concept", etc., + assertEquals("Concept", handler.getBindingNames().get(0)); + + // -1 results + assertEquals(100, handler.getBindingSets().size()); + } + + @Test + public void testNonStandardOrdered() + throws Exception + { + SPARQLResultsJSONParser parser = new SPARQLResultsJSONParser(SimpleValueFactory.getInstance()); + QueryResultCollector handler = new QueryResultCollector(); + parser.setQueryResultHandler(handler); + + InputStream stream = this.getClass().getResourceAsStream("/sparqljson/non-standard-ordered.srj"); + assertNotNull("Could not find test resource", stream); + parser.parseQueryResult(stream); + + // there must be 1 variable + assertEquals(1, handler.getBindingNames().size()); + + // first must be called "Concept", etc., + assertEquals("Concept", handler.getBindingNames().get(0)); + + // -1 results + assertEquals(100, handler.getBindingSets().size()); + } + + @Test + public void testNonStandardDistinctOrdered() + throws Exception + { + SPARQLResultsJSONParser parser = new SPARQLResultsJSONParser(SimpleValueFactory.getInstance()); + QueryResultCollector handler = new QueryResultCollector(); + parser.setQueryResultHandler(handler); + + InputStream stream = this.getClass().getResourceAsStream( + "/sparqljson/non-standard-distinct-ordered.srj"); + assertNotNull("Could not find test resource", stream); + parser.parseQueryResult(stream); + + // there must be 1 variable + assertEquals(1, handler.getBindingNames().size()); + + // first must be called "Concept", etc., + assertEquals("Concept", handler.getBindingNames().get(0)); + + // -1 results + assertEquals(100, handler.getBindingSets().size()); + } +} diff --git a/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLXMLBooleanTest.java b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLXMLBooleanTest.java new file mode 100644 index 00000000000..f119a73b5fa --- /dev/null +++ b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLXMLBooleanTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.resultio.sparqlxml; + +import org.eclipse.rdf4j.query.resultio.AbstractQueryResultIOBooleanTest; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; + +/** + * @author Peter Ansell + */ +public class SPARQLXMLBooleanTest extends AbstractQueryResultIOBooleanTest { + + @Override + protected String getFileName() { + return "test.srx"; + } + + @Override + protected BooleanQueryResultFormat getBooleanFormat() { + return BooleanQueryResultFormat.SPARQL; + } + + @Override + protected TupleQueryResultFormat getMatchingTupleFormatOrNull() { + return TupleQueryResultFormat.SPARQL; + } +} diff --git a/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLXMLTupleTest.java b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLXMLTupleTest.java new file mode 100644 index 00000000000..4762df16ef3 --- /dev/null +++ b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/sparqlxml/SPARQLXMLTupleTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.resultio.sparqlxml; + +import org.eclipse.rdf4j.query.resultio.AbstractQueryResultIOTupleTest; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; + +/** + * @author Peter Ansell + */ +public class SPARQLXMLTupleTest extends AbstractQueryResultIOTupleTest { + + @Override + protected String getFileName() { + return "test.srx"; + } + + @Override + protected TupleQueryResultFormat getTupleFormat() { + return TupleQueryResultFormat.SPARQL; + } + + @Override + protected BooleanQueryResultFormat getMatchingBooleanFormatOrNull() { + return BooleanQueryResultFormat.SPARQL; + } +} diff --git a/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/SPARQLTextBooleanTest.java b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/SPARQLTextBooleanTest.java new file mode 100644 index 00000000000..7f4f2ae2b1b --- /dev/null +++ b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/SPARQLTextBooleanTest.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.resultio.text; + +import org.eclipse.rdf4j.query.resultio.AbstractQueryResultIOBooleanTest; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; + +/** + * @author Peter Ansell + */ +public class SPARQLTextBooleanTest extends AbstractQueryResultIOBooleanTest { + + @Override + protected String getFileName() { + return "test.txt"; + } + + @Override + protected BooleanQueryResultFormat getBooleanFormat() { + return BooleanQueryResultFormat.TEXT; + } + + @Override + protected TupleQueryResultFormat getMatchingTupleFormatOrNull() { + return null; + } + +} diff --git a/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/csv/SPARQLCSVTupleTest.java b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/csv/SPARQLCSVTupleTest.java new file mode 100644 index 00000000000..ea0e09d7e2a --- /dev/null +++ b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/csv/SPARQLCSVTupleTest.java @@ -0,0 +1,243 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.resultio.text.csv; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.algebra.Compare; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; +import org.eclipse.rdf4j.query.resultio.AbstractQueryResultIOTupleTest; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.QueryResultIO; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriter; +import org.junit.Test; + +/** + * @author Peter Ansell + * @author James Leigh + */ +public class SPARQLCSVTupleTest extends AbstractQueryResultIOTupleTest { + + @Override + protected String getFileName() { + return "test.csv"; + } + + @Override + protected TupleQueryResultFormat getTupleFormat() { + return TupleQueryResultFormat.CSV; + } + + @Override + protected BooleanQueryResultFormat getMatchingBooleanFormatOrNull() { + return null; + } + + @Test + public void testEndOfLine() throws Exception { + TupleQueryResultFormat format = getTupleFormat(); + ByteArrayOutputStream out = new ByteArrayOutputStream(4096); + TupleQueryResultWriter writer = QueryResultIO.createTupleWriter(format, out); + writer.startDocument(); + writer.startHeader(); + writer.handleLinks(Arrays. asList()); + QueryResults.report(createTupleNoBindingSets(), writer); + + assertEquals("\r\n", out.toString("UTF-8").replaceAll("\\S+", "")); + } + + @Test + public void testEmptyResults() throws Exception { + TupleQueryResultFormat format = getTupleFormat(); + ByteArrayOutputStream out = new ByteArrayOutputStream(4096); + TupleQueryResultWriter writer = QueryResultIO.createTupleWriter(format, out); + writer.startDocument(); + writer.startHeader(); + writer.handleLinks(Arrays. asList()); + QueryResults.report(createTupleNoBindingSets(), writer); + + assertRegex("a,b,c(\r\n)?", out.toString("UTF-8")); + } + + @Test + public void testSingleVarResults() + throws Exception + { + TupleQueryResultFormat format = getTupleFormat(); + ByteArrayOutputStream out = new ByteArrayOutputStream(4096); + TupleQueryResultWriter writer = QueryResultIO.createTupleWriter(format, out); + writer.startDocument(); + writer.startHeader(); + writer.handleLinks(Arrays. asList()); + QueryResults.report(createTupleSingleVarMultipleBindingSets(), writer); + + System.out.println(out.toString("UTF-8")); + assertRegex("a\r\n" + "foo:bar\r\n" + "2.0(E0)?\r\n" + + "_:bnode3\r\n" + "''single-quoted string\r\n" + + "\"\"\"\"\"double-quoted string\"\r\n" + + "space at the end \r\n" + + "space at the end \r\n" + + "\"\"\"\"\"double-quoted string with no datatype\"\r\n" + + "\"newline at the end \n\"(\r\n)?", + out.toString("UTF-8")); + } + + @Test + public void testmultipleVarResults() + throws Exception + { + TupleQueryResultFormat format = getTupleFormat(); + ByteArrayOutputStream out = new ByteArrayOutputStream(4096); + TupleQueryResultWriter writer = QueryResultIO.createTupleWriter(format, out); + writer.startDocument(); + writer.startHeader(); + writer.handleLinks(Arrays. asList()); + QueryResults.report(createTupleMultipleBindingSets(), writer); + + assertRegex( + "a,b,c\r\n" + + "foo:bar,_:bnode,baz\r\n" + + "1,,Hello World!\r\n" + + "http://example.org/test/ns/bindingA,http://example.com/other/ns/bindingB,\"http://example.com/other/ns/binding,C\"\r\n" + + "\"string with newline at the end \n\",string with space at the end , \r\n" + + "''single-quoted string,\"\"\"\"\"double-quoted string\",\t\tunencoded tab characters followed by encoded \t\t(\r\n)?", + out.toString("UTF-8")); + } + + private void assertRegex(String pattern, String actual) { + if (!Pattern.compile(pattern, Pattern.DOTALL).matcher(actual).matches()) { + assertEquals(pattern, actual); + } + } + + protected void assertQueryResultsEqual(TupleQueryResult tqr1, TupleQueryResult tqr2) + throws QueryEvaluationException + { + List list1 = Iterations.asList(tqr1); + List list2 = Iterations.asList(tqr2); + + // Compare the number of statements in both sets + if (list1.size() != list2.size()) { + fail(); + } + + assertTrue(matchBindingSets(list1, list2, new HashMap(), 0)); + } + + private boolean matchBindingSets(List queryResult1, + Iterable queryResult2, Map bNodeMapping, int idx) + { + boolean result = false; + + if (idx < queryResult1.size()) { + BindingSet bs1 = queryResult1.get(idx); + + List matchingBindingSets = findMatchingBindingSets(bs1, queryResult2, bNodeMapping); + + for (BindingSet bs2 : matchingBindingSets) { + // Map bNodes in bs1 to bNodes in bs2 + Map newBNodeMapping = new HashMap(bNodeMapping); + + for (Binding binding : bs1) { + if (binding.getValue() instanceof BNode) { + newBNodeMapping.put((BNode)binding.getValue(), (BNode)bs2.getValue(binding.getName())); + } + } + + // FIXME: this recursive implementation has a high risk of + // triggering a stack overflow + + // Enter recursion + result = matchBindingSets(queryResult1, queryResult2, newBNodeMapping, idx + 1); + + if (result == true) { + // models match, look no further + break; + } + } + } + else { + // All statements have been mapped successfully + result = true; + } + + return result; + } + + private static List findMatchingBindingSets(BindingSet st, + Iterable model, Map bNodeMapping) + { + List result = new ArrayList(); + + for (BindingSet modelSt : model) { + if (bindingSetsMatch(st, modelSt, bNodeMapping)) { + // All components possibly match + result.add(modelSt); + } + } + + return result; + } + + private static boolean bindingSetsMatch(BindingSet bs1, BindingSet bs2, Map bNodeMapping) { + + if (bs1.size() != bs2.size()) { + return false; + } + + for (Binding binding1 : bs1) { + Value value1 = binding1.getValue(); + Value value2 = bs2.getValue(binding1.getName()); + + if (value1 == null && value2 != null) { + return false; + } + else if (value1 != null && value2 == null) { + return false; + } + else if (value1 != null && value2 != null) { + if (!equals(value1, value2) && !value1.stringValue().equals(value2.stringValue())) { + return false; + } + } + } + + return true; + } + + protected static boolean equals(Value value1, Value value2) + { + try { + return QueryEvaluationUtil.compare(value1, value2, Compare.CompareOp.EQ); + } + catch (ValueExprEvaluationException e) { + return false; + } + } + +} diff --git a/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLTSVCustomTest.java b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLTSVCustomTest.java new file mode 100644 index 00000000000..14a461488f2 --- /dev/null +++ b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLTSVCustomTest.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.resultio.text.tsv; + +import static org.junit.Assert.*; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; +import org.eclipse.rdf4j.query.impl.IteratingTupleQueryResult; +import org.eclipse.rdf4j.query.impl.ListBindingSet; +import org.eclipse.rdf4j.query.resultio.QueryResultIO; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Custom tests for the SPARQL TSV writer. + * + * @author Peter Ansell + */ +public class SPARQLTSVCustomTest { + + /** + * Only Literals with the XML Schema numeric types should be simplified. + *

+ * NOTE: This will fail when using RDF-1.1, as the datatype + * {@link XMLSchema#STRING} is implied and hence is not generally + * represented. + * + * @throws Exception + */ + @Ignore("This test does not work with RDF-1.1") + @Test + public void testSES2126QuotedLiteralIntegerAsStringExplicitType() + throws Exception + { + List bindingNames = Arrays.asList("test"); + TupleQueryResult tqr = new IteratingTupleQueryResult(bindingNames, Arrays.asList(new ListBindingSet( + bindingNames, SimpleValueFactory.getInstance().createLiteral("1", XMLSchema.STRING)))); + String result = writeTupleResult(tqr); + assertEquals("?test\n\"1\"^^\n", result); + } + + /** + * Only Literals with the XML Schema numeric types should be simplified. + * + * @throws Exception + */ + @Test + public void testSES2126QuotedLiteralIntegerAsStringImplicitType() + throws Exception + { + List bindingNames = Arrays.asList("test"); + TupleQueryResult tqr = new IteratingTupleQueryResult(bindingNames, Arrays.asList(new ListBindingSet( + bindingNames, SimpleValueFactory.getInstance().createLiteral("1")))); + String result = writeTupleResult(tqr); + assertEquals("?test\n\"1\"\n", result); + } + + private String writeTupleResult(TupleQueryResult tqr) + throws IOException, TupleQueryResultHandlerException, QueryEvaluationException + { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + QueryResultIO.writeTuple(tqr, TupleQueryResultFormat.TSV, output); + String result = new String(output.toByteArray(), Charset.forName("UTF-8")); + return result; + } + +} diff --git a/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLTSVTupleTest.java b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLTSVTupleTest.java new file mode 100644 index 00000000000..1248a84905c --- /dev/null +++ b/compliance/queryresultio/src/test/java/org/eclipse/rdf4j/query/resultio/text/tsv/SPARQLTSVTupleTest.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.resultio.text.tsv; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.regex.Pattern; + +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; +import org.eclipse.rdf4j.query.impl.MutableTupleQueryResult; +import org.eclipse.rdf4j.query.resultio.AbstractQueryResultIOTupleTest; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.QueryResultIO; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriter; +import org.junit.Test; + +/** + * @author Peter Ansell + * @author James Leigh + */ +public class SPARQLTSVTupleTest extends AbstractQueryResultIOTupleTest { + + @Override + protected String getFileName() { + return "test.tsv"; + } + + @Override + protected TupleQueryResultFormat getTupleFormat() { + return TupleQueryResultFormat.TSV; + } + + @Override + protected BooleanQueryResultFormat getMatchingBooleanFormatOrNull() { + return null; + } + + @Test + public void testEndOfLine() + throws Exception + { + assertEquals("\n", toString(createTupleNoBindingSets()).replaceAll("\\S+|\t", "")); + } + + @Test + public void testEmptyResults() + throws Exception + { + assertRegex("\\?a\t\\?b\t\\?c\n?", toString(createTupleNoBindingSets())); + } + + @Test + public void testSingleVarResults() + throws Exception + { + assertRegex("\\?a\n" + "\n" + "(2.0(E0)?|\"2.0\"\\^\\^)\n" + + "_:bnode3\n" + "\"''single-quoted string\"(\\^\\^)?\n" + + "\"\\\\\"\\\\\"double-quoted string\"(\\^\\^)?\n" + + "\"space at the end \"(\\^\\^)?\n" + + "\"space at the end \"(\\^\\^)?\n" + + "\"\\\\\"\\\\\"double-quoted string with no datatype\"(\\^\\^)?\n" + + "\"newline at the end \\\\n\"(\\^\\^)?\n?", + toString(createTupleSingleVarMultipleBindingSets())); + } + + @Test + public void testmultipleVarResults() + throws Exception + { + assertRegex( + "\\?a\t\\?b\t\\?c\n" + + "\t_:bnode\t\"baz\"(\\^\\^)?\n" + + "(1|\"1\"\\^\\^)\t\t\"Hello World!\"@en\n" + + "\t\"http://example.com/other/ns/bindingB\"(\\^\\^)?\t\n" + + "\"string with newline at the end \\\\n\"(\\^\\^)?\t\"string with space at the end \"(\\^\\^)?\t\" \"(\\^\\^)?\n" + + "\"''single-quoted string\"(\\^\\^)?\t\"\\\\\"\\\\\"double-quoted string\"(\\^\\^)?\t\"\\\\t\\\\tunencoded tab characters followed by encoded \\\\t\\\\t\"(\\^\\^)?\n?", + toString(createTupleMultipleBindingSets())); + } + + private String toString(TupleQueryResult results) + throws QueryResultHandlerException, TupleQueryResultHandlerException, QueryEvaluationException, + UnsupportedEncodingException + { + TupleQueryResultFormat format = getTupleFormat(); + ByteArrayOutputStream out = new ByteArrayOutputStream(4096); + TupleQueryResultWriter writer = QueryResultIO.createTupleWriter(format, out); + writer.startDocument(); + writer.startHeader(); + writer.handleLinks(Arrays. asList()); + QueryResults.report(results, writer); + + return out.toString("UTF-8"); + } + + private void assertRegex(String pattern, String actual) { + if (!Pattern.compile(pattern, Pattern.DOTALL).matcher(actual).matches()) { + assertEquals(pattern, actual); + } + } + + protected void assertQueryResultsEqual(TupleQueryResult expected, TupleQueryResult output) + throws QueryEvaluationException, TupleQueryResultHandlerException, QueryResultHandlerException, + UnsupportedEncodingException + { + MutableTupleQueryResult r1 = new MutableTupleQueryResult(expected); + MutableTupleQueryResult r2 = new MutableTupleQueryResult(output); + if (!QueryResults.equals(r1, r2)) { + r1.beforeFirst(); + r2.beforeFirst(); + assertEquals(toString(r1), toString(r2)); + r2.beforeFirst(); + fail(toString(r2)); + } + } + +} diff --git a/compliance/queryresultio/src/test/resources/logback-test.xml b/compliance/queryresultio/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..86b31ec4b71 --- /dev/null +++ b/compliance/queryresultio/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + diff --git a/compliance/queryresultio/src/test/resources/sparqljson/bindings1.srj b/compliance/queryresultio/src/test/resources/sparqljson/bindings1.srj new file mode 100644 index 00000000000..a7045c76481 --- /dev/null +++ b/compliance/queryresultio/src/test/resources/sparqljson/bindings1.srj @@ -0,0 +1,36 @@ +{ + "head": { "vars": [ "book" , "title" ] + } , + "results": { + "bindings": [ + { + "book": { "type": "uri" , "value": "http://example.org/book/book6" } , + "title": { "type": "literal" , "value": "Harry Potter and the Half-Blood Prince" } + } , + { + "book": { "type": "uri" , "value": "http://example.org/book/book7" } , + "title": { "type": "literal" , "value": "Harry Potter and the Deathly Hallows" } + } , + { + "book": { "type": "uri" , "value": "http://example.org/book/book5" } , + "title": { "type": "literal" , "value": "Harry Potter and the Order of the Phoenix" } + } , + { + "book": { "type": "uri" , "value": "http://example.org/book/book4" } , + "title": { "type": "literal" , "value": "Harry Potter and the Goblet of Fire" } + } , + { + "book": { "type": "uri" , "value": "http://example.org/book/book2" } , + "title": { "type": "literal" , "value": "Harry Potter and the Chamber of Secrets" } + } , + { + "book": { "type": "uri" , "value": "http://example.org/book/book3" } , + "title": { "type": "literal" , "value": "Harry Potter and the Prisoner Of Azkaban" } + } , + { + "book": { "type": "uri" , "value": "http://example.org/book/book1" } , + "title": { "type": "literal" , "value": "Harry Potter and the Philosopher's Stone" } + } + ] + } +} diff --git a/compliance/queryresultio/src/test/resources/sparqljson/bindings2.srj b/compliance/queryresultio/src/test/resources/sparqljson/bindings2.srj new file mode 100644 index 00000000000..29de29569d3 --- /dev/null +++ b/compliance/queryresultio/src/test/resources/sparqljson/bindings2.srj @@ -0,0 +1,39 @@ +{ + "head": { + "link": [ + "http://www.w3.org/TR/2013/REC-sparql11-results-json-20130321/#example" + ], + "vars": [ + "x", + "hpage", + "name", + "mbox", + "age", + "blurb", + "friend" + ] + }, + "results": { + "bindings": [ + { + "x" : { "type": "bnode", "value": "r1" }, + "hpage" : { "type": "uri", "value": "http://work.example.org/alice/" }, + "name" : { "type": "literal", "value": "Alice" } , + "mbox" : { "type": "literal", "value": "" } , + "blurb" : { + "datatype": "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral", + "type": "literal", + "value": "

My name is alice

" + }, + "friend" : { "type": "bnode", "value": "r2" } + }, + { + "x" : { "type": "bnode", "value": "r2" }, + "hpage" : { "type": "uri", "value": "http://work.example.org/bob/" }, + "name" : { "type": "literal", "value": "Bob", "xml:lang": "en" }, + "mbox" : { "type": "uri", "value": "mailto:bob@work.example.org" }, + "friend" : { "type": "bnode", "value": "r1" } + } + ] + } +} diff --git a/compliance/queryresultio/src/test/resources/sparqljson/boolean1.srj b/compliance/queryresultio/src/test/resources/sparqljson/boolean1.srj new file mode 100644 index 00000000000..4a70b7489b7 --- /dev/null +++ b/compliance/queryresultio/src/test/resources/sparqljson/boolean1.srj @@ -0,0 +1,3 @@ +{ + "boolean": true +} diff --git a/compliance/queryresultio/src/test/resources/sparqljson/boolean2.srj b/compliance/queryresultio/src/test/resources/sparqljson/boolean2.srj new file mode 100644 index 00000000000..91b69eabc24 --- /dev/null +++ b/compliance/queryresultio/src/test/resources/sparqljson/boolean2.srj @@ -0,0 +1,3 @@ +{ + "boolean": "true" +} diff --git a/compliance/queryresultio/src/test/resources/sparqljson/boolean3.srj b/compliance/queryresultio/src/test/resources/sparqljson/boolean3.srj new file mode 100644 index 00000000000..f4d94926ea6 --- /dev/null +++ b/compliance/queryresultio/src/test/resources/sparqljson/boolean3.srj @@ -0,0 +1,3 @@ +{ + "boolean": false +} diff --git a/compliance/queryresultio/src/test/resources/sparqljson/boolean4.srj b/compliance/queryresultio/src/test/resources/sparqljson/boolean4.srj new file mode 100644 index 00000000000..06a2bc2be02 --- /dev/null +++ b/compliance/queryresultio/src/test/resources/sparqljson/boolean4.srj @@ -0,0 +1,3 @@ +{ + "boolean": "false" +} diff --git a/compliance/queryresultio/src/test/resources/sparqljson/non-standard-distinct-ordered.srj b/compliance/queryresultio/src/test/resources/sparqljson/non-standard-distinct-ordered.srj new file mode 100644 index 00000000000..64f4c9182f8 --- /dev/null +++ b/compliance/queryresultio/src/test/resources/sparqljson/non-standard-distinct-ordered.srj @@ -0,0 +1,102 @@ +{ "head": { "link": [], "vars": ["Concept"] }, + "results": { "distinct": false, "ordered": true, "bindings": [ + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Thing" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Class" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#ObjectProperty" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Ontology" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#FunctionalProperty" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#DatatypeProperty" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Company" }}, + { "Concept": { "type": "uri", "value": "http://xmlns.com/foaf/0.1/Person" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Activity" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Person" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Language" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Software" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/School" }}, + { "Concept": { "type": "uri", "value": "http://purl.org/ontology/bibo/Book" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Name" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Actor" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Place" }}, + { "Concept": { "type": "uri", "value": "http://www.opengis.net/gml/_Feature" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/OfficeHolder" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TennisPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Organisation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/MilitaryPerson" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BaseballPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ProgrammingLanguage" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BodyOfWater" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ChemicalCompound" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ArchitecturalStructure" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Infrastructure" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/CelestialBody" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/AutomobileEngine" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/AcademicJournal" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Broadcaster" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TelevisionStation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RailwayTunnel" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/GovernmentAgency" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Biomolecule" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RailwayLine" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/MartialArtist" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RecordLabel" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/AmericanFootballTeam" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/PublicTransitSystem" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BaseballLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/HistoricPlace" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RugbyLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/HistoricBuilding" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/OlympicResult" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/FootballMatch" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Language" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/MusicGroup" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/RiverBodyOfWater" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/SportsTeam" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/LakeBodyOfWater" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/MusicAlbum" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Mountain" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/StadiumOrArena" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Canal" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Hospital" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/LandmarksOrHistoricalBuildings" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/SportsEvent" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Festival" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/CanadianFootballLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RugbyPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TelevisionEpisode" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/GaelicGamesPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SnookerPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TennisLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RoadJunction" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SnookerChamp" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Book" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Work" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Philosopher" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Agent" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Award" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Film" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Song" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SpaceMission" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Event" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/City" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Band" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/FictionalCharacter" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Plant" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Saint" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Sport" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Fish" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Game" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Town" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/River" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/NaturalPlace" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Non-ProfitOrganisation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ChemicalSubstance" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BritishRoyalty" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Drug" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SportsTeamMember" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SportsLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/MeanOfTransportation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Lake" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BroadcastNetwork" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Play" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Album" }} ] } } \ No newline at end of file diff --git a/compliance/queryresultio/src/test/resources/sparqljson/non-standard-distinct.srj b/compliance/queryresultio/src/test/resources/sparqljson/non-standard-distinct.srj new file mode 100644 index 00000000000..f7d27d01be2 --- /dev/null +++ b/compliance/queryresultio/src/test/resources/sparqljson/non-standard-distinct.srj @@ -0,0 +1,102 @@ +{ "head": { "link": [], "vars": ["Concept"] }, + "results": { "distinct": false, "bindings": [ + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Thing" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Class" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#ObjectProperty" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Ontology" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#FunctionalProperty" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#DatatypeProperty" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Company" }}, + { "Concept": { "type": "uri", "value": "http://xmlns.com/foaf/0.1/Person" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Activity" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Person" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Language" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Software" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/School" }}, + { "Concept": { "type": "uri", "value": "http://purl.org/ontology/bibo/Book" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Name" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Actor" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Place" }}, + { "Concept": { "type": "uri", "value": "http://www.opengis.net/gml/_Feature" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/OfficeHolder" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TennisPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Organisation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/MilitaryPerson" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BaseballPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ProgrammingLanguage" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BodyOfWater" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ChemicalCompound" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ArchitecturalStructure" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Infrastructure" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/CelestialBody" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/AutomobileEngine" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/AcademicJournal" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Broadcaster" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TelevisionStation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RailwayTunnel" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/GovernmentAgency" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Biomolecule" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RailwayLine" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/MartialArtist" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RecordLabel" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/AmericanFootballTeam" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/PublicTransitSystem" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BaseballLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/HistoricPlace" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RugbyLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/HistoricBuilding" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/OlympicResult" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/FootballMatch" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Language" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/MusicGroup" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/RiverBodyOfWater" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/SportsTeam" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/LakeBodyOfWater" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/MusicAlbum" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Mountain" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/StadiumOrArena" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Canal" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Hospital" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/LandmarksOrHistoricalBuildings" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/SportsEvent" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Festival" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/CanadianFootballLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RugbyPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TelevisionEpisode" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/GaelicGamesPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SnookerPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TennisLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RoadJunction" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SnookerChamp" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Book" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Work" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Philosopher" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Agent" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Award" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Film" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Song" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SpaceMission" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Event" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/City" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Band" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/FictionalCharacter" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Plant" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Saint" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Sport" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Fish" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Game" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Town" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/River" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/NaturalPlace" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Non-ProfitOrganisation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ChemicalSubstance" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BritishRoyalty" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Drug" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SportsTeamMember" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SportsLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/MeanOfTransportation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Lake" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BroadcastNetwork" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Play" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Album" }} ] } } \ No newline at end of file diff --git a/compliance/queryresultio/src/test/resources/sparqljson/non-standard-ordered.srj b/compliance/queryresultio/src/test/resources/sparqljson/non-standard-ordered.srj new file mode 100644 index 00000000000..4a6a0a3276b --- /dev/null +++ b/compliance/queryresultio/src/test/resources/sparqljson/non-standard-ordered.srj @@ -0,0 +1,102 @@ +{ "head": { "link": [], "vars": ["Concept"] }, + "results": { "ordered": true, "bindings": [ + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Thing" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Class" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#ObjectProperty" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Ontology" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#FunctionalProperty" }}, + { "Concept": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#DatatypeProperty" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Company" }}, + { "Concept": { "type": "uri", "value": "http://xmlns.com/foaf/0.1/Person" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Activity" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Person" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Language" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Software" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/School" }}, + { "Concept": { "type": "uri", "value": "http://purl.org/ontology/bibo/Book" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Name" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Actor" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Place" }}, + { "Concept": { "type": "uri", "value": "http://www.opengis.net/gml/_Feature" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/OfficeHolder" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TennisPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Organisation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/MilitaryPerson" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BaseballPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ProgrammingLanguage" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BodyOfWater" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ChemicalCompound" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ArchitecturalStructure" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Infrastructure" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/CelestialBody" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/AutomobileEngine" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/AcademicJournal" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Broadcaster" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TelevisionStation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RailwayTunnel" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/GovernmentAgency" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Biomolecule" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RailwayLine" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/MartialArtist" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RecordLabel" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/AmericanFootballTeam" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/PublicTransitSystem" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BaseballLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/HistoricPlace" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RugbyLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/HistoricBuilding" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/OlympicResult" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/FootballMatch" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Language" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/MusicGroup" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/RiverBodyOfWater" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/SportsTeam" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/LakeBodyOfWater" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/MusicAlbum" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Mountain" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/StadiumOrArena" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Canal" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Hospital" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/LandmarksOrHistoricalBuildings" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/SportsEvent" }}, + { "Concept": { "type": "uri", "value": "http://schema.org/Festival" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/CanadianFootballLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RugbyPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TelevisionEpisode" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/GaelicGamesPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SnookerPlayer" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/TennisLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/RoadJunction" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SnookerChamp" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Book" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Work" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Philosopher" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Agent" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Award" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Film" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Song" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SpaceMission" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Event" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/City" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Band" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/FictionalCharacter" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Plant" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Saint" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Sport" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Fish" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Game" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Town" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/River" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/NaturalPlace" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Non-ProfitOrganisation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/ChemicalSubstance" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BritishRoyalty" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Drug" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SportsTeamMember" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/SportsLeague" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/MeanOfTransportation" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Lake" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/BroadcastNetwork" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Play" }}, + { "Concept": { "type": "uri", "value": "http://dbpedia.org/ontology/Album" }} ] } } \ No newline at end of file diff --git a/compliance/rio/pom.xml b/compliance/rio/pom.xml new file mode 100644 index 00000000000..9d800fee5db --- /dev/null +++ b/compliance/rio/pom.xml @@ -0,0 +1,170 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-compliance + 4.1.0-SNAPSHOT + + + rdf4j-rio-compliance + + RDF4J Rio compliance tests + Tests for parsers and writers of various RDF file formats. + + + + ${project.groupId} + rdf4j-runtime + ${project.version} + + + + ${project.groupId} + rdf4j-repository-sail + ${project.version} + + + + ${project.groupId} + rdf4j-sail-memory + ${project.version} + + + + ${project.groupId} + rdf4j-rio-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-rio-datatypes + ${project.version} + + + + ${project.groupId} + rdf4j-rio-languages + ${project.version} + + + + ${project.groupId} + rdf4j-rio-rdfxml + ${project.version} + + + + ${project.groupId} + rdf4j-rio-ntriples + ${project.version} + + + + ${project.groupId} + rdf4j-rio-nquads + ${project.version} + + + + ${project.groupId} + rdf4j-rio-turtle + ${project.version} + + + + ${project.groupId} + rdf4j-rio-trig + ${project.version} + + + + ${project.groupId} + rdf4j-rio-binary + ${project.version} + + + + ${project.groupId} + rdf4j-rio-rdfjson + ${project.version} + + + + xml-security + xmlsec + 1.3.0 + + + + + xalan + xalan + 2.6.0 + + + + junit + junit + test + + + + ch.qos.logback + logback-classic + test + + + org.slf4j + jcl-over-slf4j + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + 1 + false + -Xmx512M -XX:MaxPermSize=256M + + **/*Test.java + + + **/N3ParserTest.java + **/TestServer.java + + + + + integration-tests + integration-test + + integration-test + + + + verify + verify + + verify + + + + + + + + diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/binary/BinaryHandlingTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/binary/BinaryHandlingTest.java new file mode 100644 index 00000000000..a079d839a48 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/binary/BinaryHandlingTest.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.binary; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.charset.Charset; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.rio.AbstractParserHandlingTest; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.binary.BinaryRDFParser; +import org.eclipse.rdf4j.rio.binary.BinaryRDFWriter; + +/** + * Test for error handling by Binary Parser. + * + * @author Peter Ansell + */ +public class BinaryHandlingTest extends AbstractParserHandlingTest { + + @Override + protected InputStream getUnknownDatatypeStream(Model unknownDatatypeStatements) + throws Exception + { + return writeBinary(unknownDatatypeStatements); + } + + @Override + protected InputStream getKnownDatatypeStream(Model knownDatatypeStatements) + throws Exception + { + return writeBinary(knownDatatypeStatements); + } + + @Override + protected InputStream getUnknownLanguageStream(Model unknownLanguageStatements) + throws Exception + { + return writeBinary(unknownLanguageStatements); + } + + @Override + protected InputStream getKnownLanguageStream(Model knownLanguageStatements) + throws Exception + { + return writeBinary(knownLanguageStatements); + } + + @Override + protected RDFParser getParser() { + return new BinaryRDFParser(); + } + + /** + * Helper method to write the given model to N-Triples and return an + * InputStream containing the results. + * + * @param statements + * @return An {@link InputStream} containing the results. + * @throws RDFHandlerException + */ + private InputStream writeBinary(Model statements) + throws RDFHandlerException + { + ByteArrayOutputStream output = new ByteArrayOutputStream(8096); + + RDFWriter binaryWriter = new BinaryRDFWriter(output); + binaryWriter.startRDF(); + for (Statement nextStatement : statements) { + binaryWriter.handleStatement(nextStatement); + } + binaryWriter.endRDF(); + + return new ByteArrayInputStream(output.toByteArray()); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/binary/BinaryRDFWriterTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/binary/BinaryRDFWriterTest.java new file mode 100644 index 00000000000..1ece3be42f3 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/binary/BinaryRDFWriterTest.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.binary; + +import org.eclipse.rdf4j.rio.RDFWriterTest; +import org.eclipse.rdf4j.rio.binary.BinaryRDFParserFactory; +import org.eclipse.rdf4j.rio.binary.BinaryRDFWriterFactory; + +/** + * @author Arjohn Kampman + */ +public class BinaryRDFWriterTest extends RDFWriterTest { + + public BinaryRDFWriterTest() { + super(new BinaryRDFWriterFactory(), new BinaryRDFParserFactory()); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/DBPediaCelsiusDatatypeHandlerTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/DBPediaCelsiusDatatypeHandlerTest.java new file mode 100644 index 00000000000..fd52035a3ed --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/DBPediaCelsiusDatatypeHandlerTest.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.datatypes; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.rio.DatatypeHandler; +import org.eclipse.rdf4j.rio.datatypes.AbstractDatatypeHandlerTest; +import org.eclipse.rdf4j.rio.datatypes.DBPediaDatatypeHandler; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Test for {@link DBPediaDatatypeHandler} with + * http://dbpedia.org/datatype/degreeCelsius . + * + * @author Peter Ansell + */ +public class DBPediaCelsiusDatatypeHandlerTest extends AbstractDatatypeHandlerTest { + + @Ignore("DBPedia datatypes are not currently verified") + @Test + @Override + public void testVerifyDatatypeInvalidValue() + throws Exception + { + } + + @Ignore("DBPedia datatypes are not currently normalised") + @Test + @Override + public void testNormalizeDatatypeInvalidValue() + throws Exception + { + } + + // ------------------------------------- + // RDF LangString specific methods + // ------------------------------------- + + @Override + protected IRI getRecognisedDatatypeUri() { + return SimpleValueFactory.getInstance().createIRI("http://dbpedia.org/datatype/", "degreeCelsius"); + } + + @Override + protected String getValueMatchingRecognisedDatatypeUri() { + return "1.0"; + } + + @Override + protected String getValueNotMatchingRecognisedDatatypeUri() { + return "Not a degrees celsius value."; + } + + @Override + protected Literal getNormalisedLiteralForRecognisedDatatypeAndValue() { + return SimpleValueFactory.getInstance().createLiteral("1.0", + SimpleValueFactory.getInstance().createIRI("http://dbpedia.org/datatype/", "degreeCelsius")); + } + + // ------------------------------------- + // Common methods + // ------------------------------------- + + @Override + protected DatatypeHandler getNewDatatypeHandler() { + return new DBPediaDatatypeHandler(); + } + + @Override + protected ValueFactory getValueFactory() { + return SimpleValueFactory.getInstance(); + } + + @Override + protected IRI getUnrecognisedDatatypeUri() { + return XMLSchema.DOUBLE; + } + + @Override + protected String getExpectedKey() { + return DatatypeHandler.DBPEDIA; + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/RDFLangStringDatatypeHandlerTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/RDFLangStringDatatypeHandlerTest.java new file mode 100644 index 00000000000..0baf659d821 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/RDFLangStringDatatypeHandlerTest.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.datatypes; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.rio.DatatypeHandler; +import org.eclipse.rdf4j.rio.datatypes.AbstractDatatypeHandlerTest; +import org.eclipse.rdf4j.rio.datatypes.RDFDatatypeHandler; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Test for {@link RDFDatatypeHandler} with {@link RDF#LANGSTRING}. + * + * @author Peter Ansell + */ +public class RDFLangStringDatatypeHandlerTest extends AbstractDatatypeHandlerTest { + + @Ignore("There are no invalid values for RDF LangString other than null, which is tested seperately") + @Test + @Override + public void testVerifyDatatypeInvalidValue() + throws Exception + { + } + + @Ignore("There are no invalid values for RDF LangString other than null, which is tested seperately") + @Test + @Override + public void testNormalizeDatatypeInvalidValue() + throws Exception + { + } + + @Ignore("This test relies on a null language, which is not allowed for RDF.LANGSTRING") + @Test + @Override + public void testNormalizeDatatypeValidValue() + throws Exception + { + } + + // ------------------------------------- + // RDF LangString specific methods + // ------------------------------------- + + @Override + protected IRI getRecognisedDatatypeUri() { + return RDF.LANGSTRING; + } + + @Override + protected String getValueMatchingRecognisedDatatypeUri() { + return "This is a string"; + } + + @Override + protected String getValueNotMatchingRecognisedDatatypeUri() { + return "Everything is a lang string."; + } + + @Override + protected Literal getNormalisedLiteralForRecognisedDatatypeAndValue() { + return SimpleValueFactory.getInstance().createLiteral("This is a string", RDF.LANGSTRING); + } + + // ------------------------------------- + // Common methods + // ------------------------------------- + + @Override + protected DatatypeHandler getNewDatatypeHandler() { + return new RDFDatatypeHandler(); + } + + @Override + protected ValueFactory getValueFactory() { + return SimpleValueFactory.getInstance(); + } + + @Override + protected IRI getUnrecognisedDatatypeUri() { + return XMLSchema.DOUBLE; + } + + @Override + protected String getExpectedKey() { + return DatatypeHandler.RDFDATATYPES; + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/VirtuosoGeometryPointDatatypeHandlerTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/VirtuosoGeometryPointDatatypeHandlerTest.java new file mode 100644 index 00000000000..dfe3c220a52 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/VirtuosoGeometryPointDatatypeHandlerTest.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.datatypes; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.rio.DatatypeHandler; +import org.eclipse.rdf4j.rio.datatypes.AbstractDatatypeHandlerTest; +import org.eclipse.rdf4j.rio.datatypes.VirtuosoGeometryDatatypeHandler; + +/** + * Test for {@link VirtuosoDatatypeHandler} with + * http://www.openlinksw.com/schemas/virtrdf#Geometry . + * + * @author Peter Ansell + */ +public class VirtuosoGeometryPointDatatypeHandlerTest extends AbstractDatatypeHandlerTest { + + // ------------------------------------- + // XMLSchema Double specific methods + // ------------------------------------- + + @Override + protected IRI getRecognisedDatatypeUri() { + return SimpleValueFactory.getInstance().createIRI("http://www.openlinksw.com/schemas/virtrdf#", + "Geometry"); + } + + @Override + protected String getValueMatchingRecognisedDatatypeUri() { + return "POINT(123.0000 143.000)"; + } + + @Override + protected String getValueNotMatchingRecognisedDatatypeUri() { + return "POINT(This is not a point)"; + } + + @Override + protected Literal getNormalisedLiteralForRecognisedDatatypeAndValue() { + return SimpleValueFactory.getInstance().createLiteral( + "POINT(123.0000 143.000)", + SimpleValueFactory.getInstance().createIRI("http://www.openlinksw.com/schemas/virtrdf#", "Geometry")); + } + + // ------------------------------------- + // Common methods + // ------------------------------------- + + @Override + protected DatatypeHandler getNewDatatypeHandler() { + return new VirtuosoGeometryDatatypeHandler(); + } + + @Override + protected ValueFactory getValueFactory() { + return SimpleValueFactory.getInstance(); + } + + @Override + protected IRI getUnrecognisedDatatypeUri() { + return RDF.LANGSTRING; + } + + @Override + protected String getExpectedKey() { + return DatatypeHandler.VIRTUOSOGEOMETRY; + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/XMLSchemaDoubleDatatypeHandlerTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/XMLSchemaDoubleDatatypeHandlerTest.java new file mode 100644 index 00000000000..ad199ef3250 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/datatypes/XMLSchemaDoubleDatatypeHandlerTest.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.datatypes; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.rio.DatatypeHandler; +import org.eclipse.rdf4j.rio.datatypes.AbstractDatatypeHandlerTest; +import org.eclipse.rdf4j.rio.datatypes.XMLSchemaDatatypeHandler; + +/** + * Test for {@link XMLSchemaDatatypeHandler} with {@link XMLSchema#DOUBLE}. + * + * @author Peter Ansell + */ +public class XMLSchemaDoubleDatatypeHandlerTest extends AbstractDatatypeHandlerTest { + + // ------------------------------------- + // XMLSchema Double specific methods + // ------------------------------------- + + @Override + protected IRI getRecognisedDatatypeUri() { + return XMLSchema.DOUBLE; + } + + @Override + protected String getValueMatchingRecognisedDatatypeUri() { + return "123.0000"; + } + + @Override + protected String getValueNotMatchingRecognisedDatatypeUri() { + return "This is not a double"; + } + + @Override + protected Literal getNormalisedLiteralForRecognisedDatatypeAndValue() { + return SimpleValueFactory.getInstance().createLiteral("1.23E2", XMLSchema.DOUBLE); + } + + // ------------------------------------- + // Common methods + // ------------------------------------- + + @Override + protected DatatypeHandler getNewDatatypeHandler() { + return new XMLSchemaDatatypeHandler(); + } + + @Override + protected ValueFactory getValueFactory() { + return SimpleValueFactory.getInstance(); + } + + @Override + protected IRI getUnrecognisedDatatypeUri() { + return RDF.LANGSTRING; + } + + @Override + protected String getExpectedKey() { + return DatatypeHandler.XMLSCHEMA; + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelperTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelperTest.java new file mode 100644 index 00000000000..aef4771e061 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelperTest.java @@ -0,0 +1,371 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.helpers; + +import static org.junit.Assert.*; + +import java.util.Collections; +import java.util.HashSet; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.rio.DatatypeHandler; +import org.eclipse.rdf4j.rio.LanguageHandler; +import org.eclipse.rdf4j.rio.ParseErrorListener; +import org.eclipse.rdf4j.rio.ParserConfig; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RioSetting; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.eclipse.rdf4j.rio.helpers.ParseErrorCollector; +import org.eclipse.rdf4j.rio.helpers.RDFParserHelper; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * Tests for {@link RDFParserHelper} methods. + * + * @author Peter Ansell + */ +public class RDFParserHelperTest { + + private static final String TEST_MESSAGE_FOR_FAILURE = "Test message for failure."; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private static final String LABEL_TESTA = "test-a"; + + private static final String LANG_EN = "en"; + + private ParserConfig parserConfig; + + private ParseErrorCollector errListener; + + private ValueFactory valueFactory; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + parserConfig = new ParserConfig(); + // By default we wipe out the SPI loaded datatype and language handlers + parserConfig.set(BasicParserSettings.DATATYPE_HANDLERS, Collections. emptyList()); + parserConfig.set(BasicParserSettings.LANGUAGE_HANDLERS, Collections. emptyList()); + // Ensure that the set of non-fatal errors is empty by default + parserConfig.setNonFatalErrors(new HashSet>()); + errListener = new ParseErrorCollector(); + valueFactory = SimpleValueFactory.getInstance(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#createLiteral(java.lang.String, java.lang.String, org.eclipse.rdf4j.model.URI, org.eclipse.rdf4j.rio.ParserConfig, org.eclipse.rdf4j.rio.ParseErrorListener, org.eclipse.rdf4j.model.ValueFactory)} + * . + */ + @Test + public final void testCreateLiteralLabelNull() + throws Exception + { + thrown.expect(NullPointerException.class); + thrown.expectMessage("Cannot create a literal using a null label"); + RDFParserHelper.createLiteral(null, null, null, parserConfig, errListener, valueFactory); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#createLiteral(java.lang.String, java.lang.String, org.eclipse.rdf4j.model.URI, org.eclipse.rdf4j.rio.ParserConfig, org.eclipse.rdf4j.rio.ParseErrorListener, org.eclipse.rdf4j.model.ValueFactory)} + * . + */ + @Test + public final void testCreateLiteralLabelOnly() + throws Exception + { + Literal literal = RDFParserHelper.createLiteral(LABEL_TESTA, null, null, parserConfig, errListener, + valueFactory); + + assertEquals(LABEL_TESTA, literal.getLabel()); + assertFalse(literal.getLanguage().isPresent()); + assertEquals(XMLSchema.STRING, literal.getDatatype()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#createLiteral(java.lang.String, java.lang.String, org.eclipse.rdf4j.model.URI, org.eclipse.rdf4j.rio.ParserConfig, org.eclipse.rdf4j.rio.ParseErrorListener, org.eclipse.rdf4j.model.ValueFactory)} + * . + */ + @Test + public final void testCreateLiteralLabelAndLanguage() + throws Exception + { + Literal literal = RDFParserHelper.createLiteral(LABEL_TESTA, LANG_EN, null, parserConfig, errListener, + valueFactory); + + assertEquals(LABEL_TESTA, literal.getLabel()); + assertEquals(LANG_EN, literal.getLanguage().orElse(null)); + assertEquals(RDF.LANGSTRING, literal.getDatatype()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#createLiteral(java.lang.String, java.lang.String, org.eclipse.rdf4j.model.URI, org.eclipse.rdf4j.rio.ParserConfig, org.eclipse.rdf4j.rio.ParseErrorListener, org.eclipse.rdf4j.model.ValueFactory)} + * . + */ + @Test + public final void testCreateLiteralLabelAndDatatype() + throws Exception + { + Literal literal = RDFParserHelper.createLiteral(LABEL_TESTA, null, XMLSchema.STRING, parserConfig, + errListener, valueFactory); + + assertEquals(LABEL_TESTA, literal.getLabel()); + assertFalse(literal.getLanguage().isPresent()); + assertEquals(XMLSchema.STRING, literal.getDatatype()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#createLiteral(java.lang.String, java.lang.String, org.eclipse.rdf4j.model.URI, org.eclipse.rdf4j.rio.ParserConfig, org.eclipse.rdf4j.rio.ParseErrorListener, org.eclipse.rdf4j.model.ValueFactory)} + * . + *

+ * SES-1803 : Temporary decision to ensure RDF-1.0 backwards compatibility + * for Literals created by this method in cases where {@link RDF#LANGSTRING} + * is given and there is a language. + */ + @Test + public final void testCreateLiteralLabelAndLanguageWithRDFLangString() + throws Exception + { + Literal literal = RDFParserHelper.createLiteral(LABEL_TESTA, LANG_EN, RDF.LANGSTRING, parserConfig, + errListener, valueFactory); + + assertEquals(LABEL_TESTA, literal.getLabel()); + assertEquals(LANG_EN, literal.getLanguage().orElse(null)); + assertEquals(RDF.LANGSTRING, literal.getDatatype()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#createLiteral(java.lang.String, java.lang.String, org.eclipse.rdf4j.model.URI, org.eclipse.rdf4j.rio.ParserConfig, org.eclipse.rdf4j.rio.ParseErrorListener, org.eclipse.rdf4j.model.ValueFactory)} + * . + *

+ * SES-1803 : Temporary decision to ensure RDF-1.0 backwards compatibility + * for Literals created by this method in cases where {@link RDF#LANGSTRING} + * is given and there is NO given language. + *

+ * SES-2203 : This was inconsistent, so has been changed to verify failure. + */ + @Test + public final void testCreateLiteralLabelNoLanguageWithRDFLangString() + throws Exception + { + thrown.expect(RDFParseException.class); + RDFParserHelper.createLiteral(LABEL_TESTA, null, RDF.LANGSTRING, parserConfig, + errListener, valueFactory); + } + + @Test + public final void testReportErrorStringFatalActive() + throws Exception + { + parserConfig.set(BasicParserSettings.VERIFY_DATATYPE_VALUES, true); + assertTrue(parserConfig.get(BasicParserSettings.VERIFY_DATATYPE_VALUES)); + thrown.expect(RDFParseException.class); + thrown.expectMessage(TEST_MESSAGE_FOR_FAILURE); + try { + RDFParserHelper.reportError(TEST_MESSAGE_FOR_FAILURE, BasicParserSettings.VERIFY_DATATYPE_VALUES, + parserConfig, errListener); + } + finally { + assertErrorListener(0, 1, 0); + } + } + + @Test + public final void testReportErrorStringNonFatalActive() + throws Exception + { + parserConfig.set(BasicParserSettings.VERIFY_DATATYPE_VALUES, true); + assertTrue(parserConfig.get(BasicParserSettings.VERIFY_DATATYPE_VALUES)); + parserConfig.addNonFatalError(BasicParserSettings.VERIFY_DATATYPE_VALUES); + RDFParserHelper.reportError(TEST_MESSAGE_FOR_FAILURE, BasicParserSettings.VERIFY_DATATYPE_VALUES, + parserConfig, errListener); + assertErrorListener(0, 1, 0); + } + + @Test + public final void testReportErrorStringFatalInactive() + throws Exception + { + assertFalse(parserConfig.get(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES)); + RDFParserHelper.reportError(TEST_MESSAGE_FOR_FAILURE, BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES, + parserConfig, errListener); + assertErrorListener(0, 0, 0); + } + + @Test + public final void testReportErrorStringNonFatalInactive() + throws Exception + { + assertFalse(parserConfig.get(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES)); + parserConfig.addNonFatalError(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES); + RDFParserHelper.reportError(TEST_MESSAGE_FOR_FAILURE, BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES, + parserConfig, errListener); + assertErrorListener(0, 0, 0); + } + + @Test + public final void testReportErrorStringIntIntFatalActive() + throws Exception + { + parserConfig.set(BasicParserSettings.VERIFY_DATATYPE_VALUES, true); + assertTrue(parserConfig.get(BasicParserSettings.VERIFY_DATATYPE_VALUES)); + thrown.expect(RDFParseException.class); + thrown.expectMessage(TEST_MESSAGE_FOR_FAILURE); + try { + RDFParserHelper.reportError(TEST_MESSAGE_FOR_FAILURE, 1, 1, + BasicParserSettings.VERIFY_DATATYPE_VALUES, parserConfig, errListener); + } + finally { + assertErrorListener(0, 1, 0); + } + } + + @Test + public final void testReportErrorStringIntIntNonFatalActive() + throws Exception + { + parserConfig.set(BasicParserSettings.VERIFY_DATATYPE_VALUES, true); + assertTrue(parserConfig.get(BasicParserSettings.VERIFY_DATATYPE_VALUES)); + parserConfig.addNonFatalError(BasicParserSettings.VERIFY_DATATYPE_VALUES); + RDFParserHelper.reportError(TEST_MESSAGE_FOR_FAILURE, 1, 1, BasicParserSettings.VERIFY_DATATYPE_VALUES, + parserConfig, errListener); + assertErrorListener(0, 1, 0); + } + + @Test + public final void testReportErrorStringIntIntFatalInactive() + throws Exception + { + assertFalse(parserConfig.get(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES)); + RDFParserHelper.reportError(TEST_MESSAGE_FOR_FAILURE, 1, 1, + BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES, parserConfig, errListener); + assertErrorListener(0, 0, 0); + } + + @Test + public final void testReportErrorStringIntIntNonFatalInactive() + throws Exception + { + assertFalse(parserConfig.get(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES)); + parserConfig.addNonFatalError(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES); + RDFParserHelper.reportError(TEST_MESSAGE_FOR_FAILURE, 1, 1, + BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES, parserConfig, errListener); + assertErrorListener(0, 0, 0); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#reportError(java.lang.Exception, int, int, org.eclipse.rdf4j.rio.RioSetting, org.eclipse.rdf4j.rio.ParserConfig, org.eclipse.rdf4j.rio.ParseErrorListener)} + * . + */ + @Ignore + @Test + public final void testReportErrorExceptionIntInt() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#reportFatalError(java.lang.String, org.eclipse.rdf4j.rio.ParseErrorListener)} + * . + */ + @Ignore + @Test + public final void testReportFatalErrorString() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#reportFatalError(java.lang.String, int, int, org.eclipse.rdf4j.rio.ParseErrorListener)} + * . + */ + @Ignore + @Test + public final void testReportFatalErrorStringIntInt() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#reportFatalError(java.lang.Exception, org.eclipse.rdf4j.rio.ParseErrorListener)} + * . + */ + @Ignore + @Test + public final void testReportFatalErrorException() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.rio.helpers.RDFParserHelper#reportFatalError(java.lang.Exception, int, int, org.eclipse.rdf4j.rio.ParseErrorListener)} + * . + */ + @Ignore + @Test + public final void testReportFatalErrorExceptionIntInt() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Private method for verifying the number of errors that were logged to the + * {@link ParseErrorListener}. + * + * @param fatalErrors + * Expected number of fatal errors logged by error listener. + * @param errors + * Expected number of errors logged by error listener. + * @param warnings + * Expected number of warnings logged by error listener. + */ + private void assertErrorListener(int fatalErrors, int errors, int warnings) { + assertEquals(fatalErrors, errListener.getFatalErrors().size()); + assertEquals(errors, errListener.getErrors().size()); + assertEquals(warnings, errListener.getWarnings().size()); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserHandlerTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserHandlerTest.java new file mode 100644 index 00000000000..f027f871676 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserHandlerTest.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.jsonld; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.charset.Charset; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.rio.AbstractParserHandlingTest; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.jsonld.JSONLDParser; +import org.eclipse.rdf4j.rio.jsonld.JSONLDWriter; + +/** + * Unit tests for {@link JSONLDParser} related to handling of datatypes and + * languages. + * + * @author Peter Ansell + */ +public class JSONLDParserHandlerTest extends AbstractParserHandlingTest { + + @Override + protected InputStream getUnknownDatatypeStream(Model unknownDatatypeStatements) + throws Exception + { + return writeJSONLD(unknownDatatypeStatements); + } + + @Override + protected InputStream getKnownDatatypeStream(Model knownDatatypeStatements) + throws Exception + { + return writeJSONLD(knownDatatypeStatements); + } + + @Override + protected InputStream getUnknownLanguageStream(Model unknownLanguageStatements) + throws Exception + { + return writeJSONLD(unknownLanguageStatements); + } + + @Override + protected InputStream getKnownLanguageStream(Model knownLanguageStatements) + throws Exception + { + return writeJSONLD(knownLanguageStatements); + } + + @Override + protected RDFParser getParser() { + return new JSONLDParser(); + } + + /** + * Helper method to write the given model to JSON-LD and return an + * InputStream containing the results. + * + * @param statements + * @return An {@link InputStream} containing the results. + * @throws RDFHandlerException + */ + private InputStream writeJSONLD(Model statements) + throws RDFHandlerException + { + final StringWriter writer = new StringWriter(); + + final RDFWriter jsonldWriter = new JSONLDWriter(writer); + jsonldWriter.startRDF(); + for (final Namespace prefix : statements.getNamespaces()) { + jsonldWriter.handleNamespace(prefix.getPrefix(), prefix.getName()); + } + for (final Statement nextStatement : statements) { + jsonldWriter.handleStatement(nextStatement); + } + jsonldWriter.endRDF(); + + // System.out.println(writer.toString()); + + return new ByteArrayInputStream(writer.toString().getBytes(Charset.forName("UTF-8"))); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterTest.java new file mode 100644 index 00000000000..13b5ad8ea73 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterTest.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.jsonld; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.rio.ParserConfig; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.RDFWriterTest; +import org.eclipse.rdf4j.rio.WriterConfig; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.eclipse.rdf4j.rio.helpers.JSONLDMode; +import org.eclipse.rdf4j.rio.helpers.JSONLDSettings; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; +import org.eclipse.rdf4j.rio.jsonld.JSONLDParserFactory; +import org.eclipse.rdf4j.rio.jsonld.JSONLDWriterFactory; +import org.junit.Ignore; +import org.junit.Test; + +/** + * @author Peter Ansell + */ +public class JSONLDWriterTest extends RDFWriterTest { + + public JSONLDWriterTest() { + super(new JSONLDWriterFactory(), new JSONLDParserFactory()); + } + + @Override + protected void setupWriterConfig(WriterConfig config) { + super.setupWriterConfig(config); + config.set(JSONLDSettings.JSONLD_MODE, JSONLDMode.COMPACT); + } + + @Override + protected void setupParserConfig(ParserConfig config) { + super.setupParserConfig(config); + config.set(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES, true); + config.set(BasicParserSettings.FAIL_ON_UNKNOWN_LANGUAGES, true); + } + + @Test + @Override + @Ignore("TODO: Determine why this test is breaking") + public void testIllegalPrefix() + throws RDFHandlerException, RDFParseException, IOException + { + } + + @Test + public void testRoundTripNamespaces() + throws Exception + { + String exNs = "http://example.org/"; + IRI uri1 = vf.createIRI(exNs, "uri1"); + IRI uri2 = vf.createIRI(exNs, "uri2"); + Literal plainLit = vf.createLiteral("plain", XMLSchema.STRING); + + Statement st1 = vf.createStatement(uri1, uri2, plainLit); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + RDFWriter rdfWriter = rdfWriterFactory.getWriter(out); + rdfWriter.getWriterConfig().set(JSONLDSettings.JSONLD_MODE, JSONLDMode.COMPACT); + rdfWriter.handleNamespace("ex", exNs); + rdfWriter.startRDF(); + rdfWriter.handleStatement(st1); + rdfWriter.endRDF(); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + RDFParser rdfParser = rdfParserFactory.getParser(); + ParserConfig config = new ParserConfig(); + config.set(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES, true); + config.set(BasicParserSettings.FAIL_ON_UNKNOWN_LANGUAGES, true); + rdfParser.setParserConfig(config); + rdfParser.setValueFactory(vf); + Model model = new LinkedHashModel(); + rdfParser.setRDFHandler(new StatementCollector(model)); + + rdfParser.parse(in, "foo:bar"); + + assertEquals("Unexpected number of statements, found " + model.size(), 1, model.size()); + + assertTrue("missing namespaced statement", model.contains(st1)); + + if (rdfParser.getRDFFormat().supportsNamespaces()) { + assertTrue("Expected at least one namespace, found " + model.getNamespaces().size(), + model.getNamespaces().size() >= 1); + assertEquals(exNs, model.getNamespace("ex").get().getName()); + } + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/n3/N3ParserTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/n3/N3ParserTest.java new file mode 100644 index 00000000000..dd06ef277bb --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/n3/N3ParserTest.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.n3; + +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.n3.N3ParserTestCase; +import org.eclipse.rdf4j.rio.turtle.TurtleParser; +import org.junit.Ignore; + +import junit.framework.Test; + +/** + * JUnit test for the N3 parser that uses the tests that are available online. + */ +@Ignore("FIXME: This test is badly broken") +public class N3ParserTest extends N3ParserTestCase { + + public static Test suite() + throws Exception + { + return new N3ParserTest().createTestSuite(); + } + + @Override + protected RDFParser createRDFParser() { + return new TurtleParser(); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsEarlReport.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsEarlReport.java new file mode 100644 index 00000000000..bc5c3bc382f --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsEarlReport.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.nquads; + +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.rio.EarlReport; + +/** + * Class for generating EARL reports for N-Quads parser. + * + * @author Peter Ansell + */ +public class NQuadsEarlReport { + + public static void main(String[] args) + throws Exception + { + new EarlReport().generateReport(new NQuadsParserTest().createTestSuite(), EarlReport.ANSELL, + SimpleValueFactory.getInstance().createIRI("http://www.w3.org/TR/n-quads/")); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsHandlingTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsHandlingTest.java new file mode 100644 index 00000000000..02a3f1c5ea2 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsHandlingTest.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.nquads; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.charset.Charset; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.rio.AbstractParserHandlingTest; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.nquads.NQuadsParser; +import org.eclipse.rdf4j.rio.nquads.NQuadsWriter; + +/** + * Test for error handling by N-Quads Parser. + * + * @author Peter Ansell + */ +public class NQuadsHandlingTest extends AbstractParserHandlingTest { + + @Override + protected InputStream getUnknownDatatypeStream(Model unknownDatatypeStatements) + throws Exception + { + return writeNQuads(unknownDatatypeStatements); + } + + @Override + protected InputStream getKnownDatatypeStream(Model knownDatatypeStatements) + throws Exception + { + return writeNQuads(knownDatatypeStatements); + } + + @Override + protected InputStream getUnknownLanguageStream(Model unknownLanguageStatements) + throws Exception + { + return writeNQuads(unknownLanguageStatements); + } + + @Override + protected InputStream getKnownLanguageStream(Model knownLanguageStatements) + throws Exception + { + return writeNQuads(knownLanguageStatements); + } + + @Override + protected RDFParser getParser() { + return new NQuadsParser(); + } + + /** + * Helper method to write the given model to N-Triples and return an + * InputStream containing the results. + * + * @param statements + * @return An {@link InputStream} containing the results. + * @throws RDFHandlerException + */ + private InputStream writeNQuads(Model statements) + throws RDFHandlerException + { + StringWriter writer = new StringWriter(); + + RDFWriter nQuadsWriter = new NQuadsWriter(writer); + nQuadsWriter.startRDF(); + for (Statement nextStatement : statements) { + nQuadsWriter.handleStatement(nextStatement); + } + nQuadsWriter.endRDF(); + + return new ByteArrayInputStream(writer.toString().getBytes(Charset.forName("UTF-8"))); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsParserTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsParserTest.java new file mode 100644 index 00000000000..9bed6413cbb --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsParserTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.nquads; + +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.nquads.AbstractNQuadsParserTest; +import org.eclipse.rdf4j.rio.nquads.NQuadsParser; + +import junit.framework.Test; + +/** + * JUnit test for the N-Quads parser. + * + * @author Arjohn Kampman + */ +public class NQuadsParserTest extends AbstractNQuadsParserTest { + + public static Test suite() + throws Exception + { + return new NQuadsParserTest().createTestSuite(); + } + + @Override + protected RDFParser createRDFParser() { + return new NQuadsParser(); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsParserUnitTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsParserUnitTest.java new file mode 100644 index 00000000000..4a7752fd0d9 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsParserUnitTest.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.nquads; + +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.nquads.AbstractNQuadsParserUnitTest; +import org.eclipse.rdf4j.rio.nquads.NQuadsParser; + +/** + * JUnit test for the N-Quads parser. + * + * @author Peter Ansell + */ +public class NQuadsParserUnitTest extends AbstractNQuadsParserUnitTest { + + @Override + protected RDFParser createRDFParser() { + return new NQuadsParser(); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsWriterTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsWriterTest.java new file mode 100644 index 00000000000..1fa4e97f1b6 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/nquads/NQuadsWriterTest.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.nquads; + +import org.eclipse.rdf4j.rio.nquads.AbstractNQuadsWriterTest; +import org.eclipse.rdf4j.rio.nquads.NQuadsParserFactory; +import org.eclipse.rdf4j.rio.nquads.NQuadsWriterFactory; + +public class NQuadsWriterTest extends AbstractNQuadsWriterTest { + + public NQuadsWriterTest() { + super(new NQuadsWriterFactory(), new NQuadsParserFactory()); + } + + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesEarlReport.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesEarlReport.java new file mode 100644 index 00000000000..b100a007c0e --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesEarlReport.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.ntriples; + +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.rio.EarlReport; + +/** + * Class for generating EARL reports for N-Quads parser. + * + * @author Peter Ansell + */ +public class NTriplesEarlReport { + + public static void main(String[] args) + throws Exception + { + new EarlReport().generateReport(new NTriplesParserTest().createTestSuite(), EarlReport.ANSELL, + SimpleValueFactory.getInstance().createIRI("http://www.w3.org/TR/n-triples/")); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesHandlingTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesHandlingTest.java new file mode 100644 index 00000000000..63d50e7f1be --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesHandlingTest.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.ntriples; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.charset.Charset; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.rio.AbstractParserHandlingTest; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.ntriples.NTriplesParser; +import org.eclipse.rdf4j.rio.ntriples.NTriplesWriter; + +/** + * Test for error handling by N-Triples Parser. + * + * @author Peter Ansell + */ +public class NTriplesHandlingTest extends AbstractParserHandlingTest { + + @Override + protected InputStream getUnknownDatatypeStream(Model unknownDatatypeStatements) + throws Exception + { + return writeNTriples(unknownDatatypeStatements); + } + + @Override + protected InputStream getKnownDatatypeStream(Model knownDatatypeStatements) + throws Exception + { + return writeNTriples(knownDatatypeStatements); + } + + @Override + protected InputStream getUnknownLanguageStream(Model unknownLanguageStatements) + throws Exception + { + return writeNTriples(unknownLanguageStatements); + } + + @Override + protected InputStream getKnownLanguageStream(Model knownLanguageStatements) + throws Exception + { + return writeNTriples(knownLanguageStatements); + } + + @Override + protected RDFParser getParser() { + return new NTriplesParser(); + } + + /** + * Helper method to write the given model to N-Triples and return an + * InputStream containing the results. + * + * @param statements + * @return An {@link InputStream} containing the results. + * @throws RDFHandlerException + */ + private InputStream writeNTriples(Model statements) + throws RDFHandlerException + { + StringWriter writer = new StringWriter(); + + RDFWriter nTriplesWriter = new NTriplesWriter(writer); + nTriplesWriter.startRDF(); + for (Statement nextStatement : statements) { + nTriplesWriter.handleStatement(nextStatement); + } + nTriplesWriter.endRDF(); + + return new ByteArrayInputStream(writer.toString().getBytes(Charset.forName("UTF-8"))); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParserTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParserTest.java new file mode 100644 index 00000000000..8c19786488b --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParserTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.ntriples; + +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.ntriples.AbstractNTriplesParserTest; +import org.eclipse.rdf4j.rio.ntriples.NTriplesParser; + +import junit.framework.Test; + +/** + * JUnit test for the N-Triples parser. + * + * @author Arjohn Kampman + */ +public class NTriplesParserTest extends AbstractNTriplesParserTest { + + public static Test suite() + throws Exception + { + return new NTriplesParserTest().createTestSuite(); + } + + @Override + protected RDFParser createRDFParser() { + return new NTriplesParser(); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParserUnitTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParserUnitTest.java new file mode 100644 index 00000000000..8b37c4addf6 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesParserUnitTest.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.ntriples; + +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.ntriples.AbstractNTriplesParserUnitTest; +import org.eclipse.rdf4j.rio.ntriples.NTriplesParser; + +/** + * JUnit test for the N-Triples parser. + * + * @author Arjohn Kampman + */ +public class NTriplesParserUnitTest extends AbstractNTriplesParserUnitTest { + + @Override + protected RDFParser createRDFParser() { + return new NTriplesParser(); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesWriterTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesWriterTest.java new file mode 100644 index 00000000000..3d1cb488963 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/ntriples/NTriplesWriterTest.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.ntriples; + +import org.eclipse.rdf4j.rio.RDFWriterTest; +import org.eclipse.rdf4j.rio.ntriples.NTriplesParserFactory; +import org.eclipse.rdf4j.rio.ntriples.NTriplesWriterFactory; + +/** + * JUnit test for the RDF/JSON parser. + * @author Peter Ansell + */ +public class NTriplesWriterTest extends RDFWriterTest { + + public NTriplesWriterTest() { + super(new NTriplesWriterFactory(), new NTriplesParserFactory()); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONHandlingTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONHandlingTest.java new file mode 100644 index 00000000000..8d73230b031 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONHandlingTest.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.rdfjson; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.charset.Charset; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.rio.AbstractParserHandlingTest; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.rdfjson.RDFJSONParser; +import org.eclipse.rdf4j.rio.rdfjson.RDFJSONWriter; + +/** + * Test for error handling by RDFJSON Parser. + * + * @author Peter Ansell + */ +public class RDFJSONHandlingTest extends AbstractParserHandlingTest { + + @Override + protected InputStream getUnknownDatatypeStream(Model unknownDatatypeStatements) + throws Exception + { + return writeRDFJSON(unknownDatatypeStatements); + } + + @Override + protected InputStream getKnownDatatypeStream(Model knownDatatypeStatements) + throws Exception + { + return writeRDFJSON(knownDatatypeStatements); + } + + @Override + protected InputStream getUnknownLanguageStream(Model unknownLanguageStatements) + throws Exception + { + return writeRDFJSON(unknownLanguageStatements); + } + + @Override + protected InputStream getKnownLanguageStream(Model knownLanguageStatements) + throws Exception + { + return writeRDFJSON(knownLanguageStatements); + } + + @Override + protected RDFParser getParser() { + return new RDFJSONParser(); + } + + /** + * Helper method to write the given model to RDFJSON and return an + * InputStream containing the results. + * + * @param statements + * @return An {@link InputStream} containing the results. + * @throws RDFHandlerException + */ + private InputStream writeRDFJSON(Model statements) + throws RDFHandlerException + { + StringWriter writer = new StringWriter(); + + RDFWriter rdfjsonWriter = new RDFJSONWriter(writer, RDFFormat.RDFJSON); + rdfjsonWriter.startRDF(); + for (Statement nextStatement : statements) { + rdfjsonWriter.handleStatement(nextStatement); + } + rdfjsonWriter.endRDF(); + + return new ByteArrayInputStream(writer.toString().getBytes(Charset.forName("UTF-8"))); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONMimeTypeTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONMimeTypeTest.java new file mode 100644 index 00000000000..935a28110a7 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONMimeTypeTest.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.rdfjson; + +import static org.junit.Assert.*; + +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; +import org.junit.Test; + +/** + * @author Peter Ansell + */ +public class RDFJSONMimeTypeTest { + + @Test + public void testApplicationRDFJSON() { + assertEquals( + RDFFormat.RDFJSON, + Rio.getParserFormatForMIMEType("application/rdf+json").orElseThrow( + Rio.unsupportedFormat(RDFFormat.RDFJSON))); + } + + @Test + public void testApplicationRDFJSONUtf8() { + assertEquals( + RDFFormat.RDFJSON, + Rio.getParserFormatForMIMEType("application/rdf+json;charset=UTF-8").orElseThrow( + Rio.unsupportedFormat(RDFFormat.RDFJSON))); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserCustomTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserCustomTest.java new file mode 100644 index 00000000000..7fd5f96a07c --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserCustomTest.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.rdfjson; + +import static org.junit.Assert.*; + +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; +import org.junit.Test; + +/** + * Custom (non-manifest) tests for RDF/JSON parser. + * + * @author Peter Ansell + */ +public class RDFJSONParserCustomTest { + + @Test + public void testSupportedSettings() + throws Exception + { + assertEquals(17, Rio.createParser(RDFFormat.RDFJSON).getSupportedSettings().size()); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserTest.java new file mode 100644 index 00000000000..85742efea9e --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParserTest.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.rdfjson; + +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.rdfjson.RDFJSONParser; +import org.eclipse.rdf4j.rio.rdfjson.RDFJSONParserTestCase; + +/** + * JUnit test for the RDF/JSON parser. + * + * @author Peter Ansell + */ +public class RDFJSONParserTest extends RDFJSONParserTestCase { + + public static junit.framework.Test suite() + throws Exception + { + return new RDFJSONParserTest().createTestSuite(); + } + + @Override + protected RDFParser createRDFParser() { + return new RDFJSONParser(); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONWriterTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONWriterTest.java new file mode 100644 index 00000000000..f9c033aa2f7 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONWriterTest.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.rdfjson; + +import org.eclipse.rdf4j.rio.RDFWriterTest; +import org.eclipse.rdf4j.rio.rdfjson.RDFJSONParserFactory; +import org.eclipse.rdf4j.rio.rdfjson.RDFJSONWriterFactory; + +/** + * JUnit test for the RDF/JSON parser. + * @author Peter Ansell + */ +public class RDFJSONWriterTest extends RDFWriterTest { + + public RDFJSONWriterTest() { + super(new RDFJSONWriterFactory(), new RDFJSONParserFactory()); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLHandlingTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLHandlingTest.java new file mode 100644 index 00000000000..f20f7227f7f --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLHandlingTest.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.rdfxml; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.charset.Charset; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.rio.AbstractParserHandlingTest; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.rdfxml.RDFXMLParser; +import org.eclipse.rdf4j.rio.rdfxml.RDFXMLWriter; + +/** + * Test for error handling by RDFXML Parser. + * + * @author Peter Ansell + */ +public class RDFXMLHandlingTest extends AbstractParserHandlingTest { + + @Override + protected InputStream getUnknownDatatypeStream(Model unknownDatatypeStatements) + throws Exception + { + return writeRDFXML(unknownDatatypeStatements); + } + + @Override + protected InputStream getKnownDatatypeStream(Model knownDatatypeStatements) + throws Exception + { + return writeRDFXML(knownDatatypeStatements); + } + + @Override + protected InputStream getUnknownLanguageStream(Model unknownLanguageStatements) + throws Exception + { + return writeRDFXML(unknownLanguageStatements); + } + + @Override + protected InputStream getKnownLanguageStream(Model knownLanguageStatements) + throws Exception + { + return writeRDFXML(knownLanguageStatements); + } + + @Override + protected RDFParser getParser() { + return new RDFXMLParser(); + } + + /** + * Helper method to write the given model to RDFXML and return an InputStream + * containing the results. + * + * @param statements + * @return An {@link InputStream} containing the results. + * @throws RDFHandlerException + */ + private InputStream writeRDFXML(Model statements) + throws RDFHandlerException + { + StringWriter writer = new StringWriter(); + + RDFWriter rdfxmlWriter = new RDFXMLWriter(writer); + rdfxmlWriter.startRDF(); + for (Statement nextStatement : statements) { + rdfxmlWriter.handleStatement(nextStatement); + } + rdfxmlWriter.endRDF(); + + return new ByteArrayInputStream(writer.toString().getBytes(Charset.forName("UTF-8"))); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserCustomTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserCustomTest.java new file mode 100644 index 00000000000..09955b9c6ae --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserCustomTest.java @@ -0,0 +1,217 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.rdfxml; + +import static org.junit.Assert.*; + +import java.io.StringReader; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.rio.ParserConfig; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.RDFParser.DatatypeHandling; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; +import org.eclipse.rdf4j.rio.helpers.XMLParserSettings; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Custom tests for RDFXML Parser. + * + * @author Michael Grove + */ +public class RDFXMLParserCustomTest { + + /** + * Test with the default ParserConfig settings. Ie, setParserConfig is not + * called. + * + * @throws Exception + */ + @Test + public void testEntityExpansionDefaultSettings() + throws Exception + { + final Model aGraph = new LinkedHashModel(); + RDFParser aParser = Rio.createParser(RDFFormat.RDFXML); + aParser.setRDFHandler(new StatementCollector(aGraph)); + + try { + // this should trigger a SAX parse exception that will blow up at the + // 64k + // entity limit rather than OOMing + aParser.parse( + this.getClass().getResourceAsStream("/testcases/rdfxml/openrdf/bad-entity-expansion-limit.rdf"), + "http://example.org"); + fail("Parser did not throw an exception"); + } + catch (RDFParseException e) { + // assertTrue(e.getMessage().contains( + // "The parser has encountered more than \"64,000\" entity expansions in this document; this is the limit imposed by the ")); + } + } + + /** + * Test with unrelated ParserConfig settings + * + * @throws Exception + */ + @Test + public void testEntityExpansionUnrelatedSettings() + throws Exception + { + final Model aGraph = new LinkedHashModel(); + RDFParser aParser = Rio.createParser(RDFFormat.RDFXML); + aParser.setRDFHandler(new StatementCollector(aGraph)); + + ParserConfig config = new ParserConfig(); + aParser.setParserConfig(config); + + try { + // this should trigger a SAX parse exception that will blow up at the + // 64k entity limit rather than OOMing + aParser.parse( + this.getClass().getResourceAsStream("/testcases/rdfxml/openrdf/bad-entity-expansion-limit.rdf"), + "http://example.org"); + fail("Parser did not throw an exception"); + } + catch (RDFParseException e) { + // assertTrue(e.getMessage().contains( + // "The parser has encountered more than \"64,000\" entity expansions in this document; this is the limit imposed by the ")); + } + } + + /** + * Test with Secure processing setting on. + * + * @throws Exception + */ + @Test + public void testEntityExpansionSecureProcessing() + throws Exception + { + final Model aGraph = new LinkedHashModel(); + RDFParser aParser = Rio.createParser(RDFFormat.RDFXML); + aParser.setRDFHandler(new StatementCollector(aGraph)); + + ParserConfig config = new ParserConfig(); + config.set(XMLParserSettings.SECURE_PROCESSING, true); + aParser.setParserConfig(config); + + try { + // this should trigger a SAX parse exception that will blow up at the + // 64k entity limit rather than OOMing + aParser.parse( + this.getClass().getResourceAsStream("/testcases/rdfxml/openrdf/bad-entity-expansion-limit.rdf"), + "http://example.org"); + fail("Parser did not throw an exception"); + } + catch (RDFParseException e) { + // assertTrue(e.getMessage().contains( + // "The parser has encountered more than \"64,000\" entity expansions in this document; this is the limit imposed by the ")); + } + } + + /** + * Test with Secure processing setting off. + *

+ * IMPORTANT: Only turn this on to verify it is still working, as there is no + * way to safely perform this test. + *

+ * WARNING: This test will cause an OutOfMemoryException when it eventually + * fails, as it will eventually fail. + * + * @throws Exception + */ + @Ignore + @Test(timeout = 10000) + public void testEntityExpansionNoSecureProcessing() + throws Exception + { + final Model aGraph = new LinkedHashModel(); + RDFParser aParser = Rio.createParser(RDFFormat.RDFXML); + aParser.setRDFHandler(new StatementCollector(aGraph)); + + ParserConfig config = new ParserConfig(); + config.set(XMLParserSettings.SECURE_PROCESSING, false); + aParser.setParserConfig(config); + + try { + // IMPORTANT: This will not use the entity limit + aParser.parse( + this.getClass().getResourceAsStream("/testcases/rdfxml/openrdf/bad-entity-expansion-limit.rdf"), + "http://example.org"); + fail("Parser did not throw an exception"); + } + catch (RDFParseException e) { + // assertTrue(e.getMessage().contains( + // "The parser has encountered more than \"64,000\" entity expansions in this document; this is the limit imposed by the")); + } + } + + @Test + public void testParseCollection() + throws Exception + { + // Example from: + // http://www.w3.org/TR/rdf-syntax-grammar/#section-Syntax-parsetype-Collection + StringBuilder string = new StringBuilder(); + string.append("\n"); + string.append(" \n"); + string.append(" \n"); + string.append(" \n"); + string.append(" \n"); + string.append(" \n"); + string.append(" \n"); + string.append(" \n"); + string.append(" \n"); + string.append(""); + + Model parse = Rio.parse(new StringReader(string.toString()), "", RDFFormat.RDFXML); + Rio.write(parse, System.out, RDFFormat.NTRIPLES); + assertEquals(7, parse.size()); + assertEquals(3, parse.filter(null, RDF.FIRST, null).size()); + assertEquals(3, parse.filter(null, RDF.REST, null).size()); + assertEquals(1, parse.filter(null, null, RDF.NIL).size()); + } + + @Test + public void testParseCommentAtStart() + throws Exception + { + // Example from: + // http://www.w3.org/TR/rdf-syntax-grammar/#section-Syntax-parsetype-Collection + StringBuilder string = new StringBuilder(); + string.append("\n"); + string.append(" \n"); + string.append(" \n"); + string.append(" \n"); + string.append(" Mango\n"); + string.append(" \n"); + string.append(" \n"); + string.append(""); + + Model parse = Rio.parse(new StringReader(string.toString()), "", RDFFormat.RDFXML); + Rio.write(parse, System.out, RDFFormat.NTRIPLES); + assertEquals(1, parse.size()); + } + + @Test + public void testSupportedSettings() + throws Exception + { + assertEquals(21, Rio.createParser(RDFFormat.RDFXML).getSupportedSettings().size()); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTest.java new file mode 100644 index 00000000000..3038311d11a --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTest.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.rdfxml; + +import org.eclipse.rdf4j.rio.rdfxml.RDFXMLParser; +import org.eclipse.rdf4j.rio.rdfxml.RDFXMLParserTest; +import org.eclipse.rdf4j.rio.rdfxml.RDFXMLParserTestCase; + +import junit.framework.Test; + +/** + * JUnit test for the RDF/XML parser that uses the test manifest that is + * available online. + */ +public class RDFXMLParserTest extends RDFXMLParserTestCase { + + public static Test suite() + throws Exception + { + return new RDFXMLParserTest().createTestSuite(); + } + + @Override + protected RDFXMLParser createRDFParser() { + RDFXMLParser rdfxmlParser = new RDFXMLParser(); + rdfxmlParser.setParseStandAloneDocuments(true); + return rdfxmlParser; + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLPrettyWriterTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLPrettyWriterTest.java new file mode 100644 index 00000000000..8d687a56852 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLPrettyWriterTest.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.rdfxml; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +import org.apache.commons.io.IOUtils; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.rdfxml.RDFXMLParserFactory; +import org.eclipse.rdf4j.rio.rdfxml.RDFXMLWriterTestCase; +import org.eclipse.rdf4j.rio.rdfxml.util.RDFXMLPrettyWriterFactory; +import org.junit.Test; + +public class RDFXMLPrettyWriterTest extends RDFXMLWriterTestCase { + + private static ValueFactory vf = SimpleValueFactory.getInstance(); + + public RDFXMLPrettyWriterTest() { + super(new RDFXMLPrettyWriterFactory(), new RDFXMLParserFactory()); + } + + /** + * Extract lines that start an rdf element so basic assertions can be made. + */ + private static List rdfOpenTags(String s) + throws IOException + { + String withoutSpaces = Pattern.compile("^\\s+", Pattern.MULTILINE).matcher(s).replaceAll(""); + + List rdfLines = new ArrayList(); + + for (String l : IOUtils.readLines(new StringReader(withoutSpaces))) { + if (l.startsWith(" rdfLines = rdfOpenTags(writer.toString()); + + assertEquals(Arrays.asList(" rdfLines = rdfOpenTags(writer.toString()); + + assertEquals(Arrays.asList(" rdfLines = rdfOpenTags(writer.toString()); + + assertEquals(Arrays.asList(" { [] \"Foo\" }"), "", + RDFFormat.TRIG); + } + + @Test + public void testTrailingSemicolon() + throws Exception + { + Rio.parse(new StringReader("{ ;}"), "", + RDFFormat.TRIG); + } + + @Test + public void testAnonymousGraph1() + throws Exception + { + Rio.parse(new StringReader("PREFIX : \n GRAPH [] { :s :p :o }"), "", RDFFormat.TRIG); + } + + @Test + public void testAnonymousGraph2() + throws Exception + { + Rio.parse(new StringReader("PREFIX : \n [] { :s :p :o }"), "", RDFFormat.TRIG); + } + + @Test + public void testTurtle() + throws Exception + { + Rio.parse(new StringReader(" "), "", RDFFormat.TRIG); + } + + @Test + public void testMinimalWhitespace() + throws Exception + { + Rio.parse( + this.getClass().getResourceAsStream("/testcases/trig/trig-syntax-minimal-whitespace-01.trig"), + "", RDFFormat.TRIG); + } + + @Test + public void testMinimalWhitespaceLine12() + throws Exception + { + Rio.parse(new StringReader("@prefix : . {_:s:p :o ._:s:p\"Alice\". _:s:p _:o .}"), + "", RDFFormat.TRIG); + } + + @Test + public void testBadPname02() + throws Exception + { + try { + Rio.parse(new StringReader("@prefix : . {:a%2 :p :o .}"), "", RDFFormat.TRIG); + fail("Did not receive expected exception"); + } + catch (RDFParseException e) { + + } + } + + @Test + public void testSupportedSettings() + throws Exception + { + assertEquals(12, Rio.createParser(RDFFormat.TRIG).getSupportedSettings().size()); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGParserTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGParserTest.java new file mode 100644 index 00000000000..6caebde2f21 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGParserTest.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.trig; + +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.nquads.NQuadsParser; +import org.eclipse.rdf4j.rio.trig.TriGParser; +import org.eclipse.rdf4j.rio.trig.TriGParserTestCase; + +/** + * JUnit test for the TriG parser. + */ +public class TriGParserTest extends TriGParserTestCase { + + public static junit.framework.Test suite() + throws Exception + { + return new TriGParserTest().createTestSuite(); + } + + @Override + protected RDFParser createTriGParser() { + return new TriGParser(); + } + + @Override + protected RDFParser createNQuadsParser() { + return new NQuadsParser(); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGWriterTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGWriterTest.java new file mode 100644 index 00000000000..633fdefbd56 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/trig/TriGWriterTest.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.trig; + +import org.eclipse.rdf4j.rio.RDFWriterTest; +import org.eclipse.rdf4j.rio.trig.TriGParserFactory; +import org.eclipse.rdf4j.rio.trig.TriGWriterFactory; + +/** + * @author Arjohn Kampman + */ +public class TriGWriterTest extends RDFWriterTest { + + public TriGWriterTest() { + super(new TriGWriterFactory(), new TriGParserFactory()); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/CustomTurtleParserTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/CustomTurtleParserTest.java new file mode 100644 index 00000000000..6c7e0e67cc4 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/CustomTurtleParserTest.java @@ -0,0 +1,494 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.turtle; + +import static org.junit.Assert.*; + +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Collections; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.impl.NamespaceImpl; +import org.eclipse.rdf4j.model.impl.ValueFactoryImpl; +import org.eclipse.rdf4j.model.util.Models; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.SKOS; +import org.eclipse.rdf4j.rio.ParserConfig; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.eclipse.rdf4j.rio.helpers.ParseErrorCollector; +import org.eclipse.rdf4j.rio.helpers.ParseErrorLogger; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Timeout; + +/** + * Custom tests for Turtle Parser + * + * @author Peter Ansell + */ +public class CustomTurtleParserTest { + + @Rule + public Timeout timeout = new Timeout(1000000); + + private ValueFactory vf; + + private ParserConfig settingsNoVerifyLangTag; + + private ParseErrorCollector errors; + + private RDFParser parser; + + private StatementCollector statementCollector; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + vf = ValueFactoryImpl.getInstance(); + settingsNoVerifyLangTag = new ParserConfig(); + settingsNoVerifyLangTag.set(BasicParserSettings.VERIFY_LANGUAGE_TAGS, false); + errors = new ParseErrorCollector(); + parser = Rio.createParser(RDFFormat.TURTLE); + statementCollector = new StatementCollector(new LinkedHashModel()); + parser.setRDFHandler(statementCollector); + } + + @Test + public void testSES1887NoLangTagFailure() + throws Exception + { + try { + Rio.parse(new StringReader(" \"Foo\"@."), "", RDFFormat.TURTLE); + fail("Did not receive an exception"); + } + catch (RDFParseException e) { + assertTrue(e.getMessage().contains("Expected a letter, found '.'")); + } + } + + @Test + public void testSES1887NoLangTagFailure2() + throws Exception + { + try { + // NOTE: Bad things may happen when VERIFY_LANGUAGE_TAGS is turned off + // on a file of this structure + Rio.parse(new StringReader(" \"Foo\"@."), "", RDFFormat.TURTLE, + settingsNoVerifyLangTag, vf, errors); + fail("Did not receive an exception"); + } + catch (RDFParseException e) { + assertTrue(e.getMessage().contains("Unexpected end of file")); + } + } + + @Test + public void testSES1887Whitespace() + throws Exception + { + Model model = Rio.parse(new StringReader(" \"Foo\"@fr-FR ."), "", + RDFFormat.TURTLE); + + assertEquals(1, model.size()); + assertTrue(model.contains(null, null, vf.createLiteral("Foo", "fr-FR"))); + } + + @Test + public void testSES1887Period() + throws Exception + { + Model model = Rio.parse(new StringReader(" \"Foo\"@fr-FR."), "", + RDFFormat.TURTLE); + + assertEquals(1, model.size()); + assertTrue(model.contains(null, null, vf.createLiteral("Foo", "fr-FR"))); + } + + @Test + public void testSES1887Semicolon() + throws Exception + { + Model model = Rio.parse(new StringReader( + " \"Foo\"@fr-FR;\"Blah\"@en-AU."), + "", RDFFormat.TURTLE); + + assertEquals(2, model.size()); + assertTrue(model.contains(null, null, vf.createLiteral("Foo", "fr-FR"))); + assertTrue(model.contains(null, null, vf.createLiteral("Blah", "en-AU"))); + } + + @Test + public void testSES1887Comma() + throws Exception + { + Model model = Rio.parse(new StringReader( + " \"Foo\"@fr-FR,\"Blah\"@en-AU."), "", RDFFormat.TURTLE); + + assertEquals(2, model.size()); + assertTrue(model.contains(null, null, vf.createLiteral("Foo", "fr-FR"))); + assertTrue(model.contains(null, null, vf.createLiteral("Blah", "en-AU"))); + } + + @Test + public void testSES1887CloseParentheses() + throws Exception + { + Model model = Rio.parse(new StringReader(" (\"Foo\"@fr-FR)."), "", + RDFFormat.TURTLE); + + assertEquals(3, model.size()); + assertTrue(model.contains(null, null, vf.createLiteral("Foo", "fr-FR"))); + } + + @Test + public void testSES1887CloseSquareBracket() + throws Exception + { + Model model = Rio.parse(new StringReader("[ \"Foo\"@fr-FR]."), "", + RDFFormat.TURTLE); + + assertEquals(1, model.size()); + assertTrue(model.contains(null, null, vf.createLiteral("Foo", "fr-FR"))); + } + + @Test + public void testLiteralWithNewlines() + throws Exception + { + String namespace = "http://www.foo.com/bar#"; + String okLiteralString = "Literal \n without \n new line at the beginning. \n "; + String errLiteralString = "\n Literal \n with \n new line at the beginning. \n "; + + URI mySubject = vf.createURI(namespace, "Subject"); + URI myPredicate = vf.createURI(namespace, "Predicate"); + Literal myOkObject = vf.createLiteral(okLiteralString); + Literal myErrObject = vf.createLiteral(errLiteralString); + + StringWriter out = new StringWriter(); + Model model = new LinkedHashModel(); + model.add(mySubject, myPredicate, myOkObject); + model.add(mySubject, myPredicate, myErrObject); + Rio.write(model, out, RDFFormat.TURTLE); + + String str = out.toString(); + + System.err.println(str); + + assertTrue("okLiteralString not found", str.contains(okLiteralString)); + assertTrue("errLiteralString not found", str.contains(errLiteralString)); + } + + @Test + public void testSupportedSettings() + throws Exception + { + assertEquals(12, parser.getSupportedSettings().size()); + } + + @Test + public void testSES1988BlankNodePeriodEOF() + throws Exception + { + Model model = Rio.parse(new StringReader(" _:blank."), "", RDFFormat.TURTLE); + + assertEquals(1, model.size()); + } + + @Test + public void testSES1988BlankNodePeriodSpace() + throws Exception + { + Model model = Rio.parse(new StringReader(" _:blank. "), "", RDFFormat.TURTLE); + + assertEquals(1, model.size()); + } + + @Test + public void testSES1988BlankNodePeriodTab() + throws Exception + { + Model model = Rio.parse(new StringReader(" _:blank.\t"), "", RDFFormat.TURTLE); + + assertEquals(1, model.size()); + } + + @Test + public void testSES1988BlankNodePeriodNewLine() + throws Exception + { + Model model = Rio.parse(new StringReader(" _:blank.\n"), "", RDFFormat.TURTLE); + + assertEquals(1, model.size()); + } + + @Test + public void testSES1988BlankNodePeriodCarriageReturn() + throws Exception + { + Model model = Rio.parse(new StringReader(" _:blank.\r"), "", RDFFormat.TURTLE); + + assertEquals(1, model.size()); + } + + @Test + public void testSES1988BlankNodePeriodURI() + throws Exception + { + Model model = Rio.parse(new StringReader(" _:blank. ."), "", + RDFFormat.TURTLE); + + assertEquals(2, model.size()); + } + + @Test + public void testSES1988BlankNodePeriodBNode() + throws Exception + { + Model model = Rio.parse(new StringReader(" _:blank._:blank ."), "", + RDFFormat.TURTLE); + + assertEquals(2, model.size()); + } + + @Test + public void testSES2013BlankNodeSemiColonBNodeSpaceA() + throws Exception + { + Model model = Rio.parse(new StringReader(" a _:c2; a ."), "", RDFFormat.TURTLE); + + assertEquals(2, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), RDF.TYPE, vf.createURI("urn:b"))); + } + + @Test + public void testSES2013BlankNodeSemiColonBNodeA() + throws Exception + { + Model model = Rio.parse(new StringReader(" a _:c2;a ."), "", RDFFormat.TURTLE); + + assertEquals(2, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), RDF.TYPE, vf.createURI("urn:b"))); + } + + @Test + public void testSES2013BlankNodeSemiColonBNodeSpaceURI() + throws Exception + { + Model model = Rio.parse(new StringReader(" a _:c2; ."), "", RDFFormat.TURTLE); + + assertEquals(2, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), vf.createURI("urn:b"), vf.createURI("urn:c"))); + } + + @Test + public void testSES2013BlankNodeSemiColonBNodeURI() + throws Exception + { + Model model = Rio.parse(new StringReader(" a _:c2; ."), "", RDFFormat.TURTLE); + + assertEquals(2, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), vf.createURI("urn:b"), vf.createURI("urn:c"))); + } + + @Test + public void testSES2019ParseLongLiterals() + throws Exception + { + parser.parse(this.getClass().getResourceAsStream("/testcases/turtle/turtle-long-literals-test.ttl"), ""); + + assertTrue(errors.getWarnings().isEmpty()); + assertTrue(errors.getErrors().isEmpty()); + assertTrue(errors.getFatalErrors().isEmpty()); + + assertFalse(statementCollector.getStatements().isEmpty()); + assertEquals(5, statementCollector.getStatements().size()); + + Models.isomorphic(statementCollector.getStatements(), Rio.parse( + this.getClass().getResourceAsStream("/testcases/turtle/turtle-long-literals-test.nt"), "", + RDFFormat.NTRIPLES)); + } + + @Test + public void testSES2086PeriodEndingLocalNamesFailure1() + throws Exception + { + try { + Rio.parse(new StringReader( + "@prefix : .\n :test. ."), "", + RDFFormat.TURTLE); + fail("Did not receive an exception"); + } + catch (RDFParseException e) { + System.out.println(e.getMessage()); + assertTrue(e.getMessage().contains("Object for statement missing")); + } + } + + @Test + public void testSES2086PeriodEndingLocalNamesFailure2() + throws Exception + { + try { + Rio.parse( + new StringReader( + "@prefix ns: . ns:uriWithDot. a ns:Product ; ns:title \"An example subject ending with a dot.\" . "), + "", RDFFormat.TURTLE); + fail("Did not receive an exception"); + } + catch (RDFParseException e) { + System.out.println(e.getMessage()); + assertTrue(e.getMessage().contains( + "Illegal predicate value: \"\"^^")); + } + } + + @Test + public void testSES2086PeriodEndingLocalNamesFailure3() + throws Exception + { + try { + Rio.parse( + new StringReader( + "@prefix ns: . ns:1 a ns:Product ; ns:affects ns:4 , ns:16 , ns:uriWithDot. ; ns:title \"An example entity with uriWithDot as an object\" . "), + "", RDFFormat.TURTLE); + fail("Did not receive an exception"); + } + catch (RDFParseException e) { + System.out.println(e.getMessage()); + assertTrue(e.getMessage().contains("Expected an RDF value here, found ';'")); + } + } + + @Test + public void testSES2086PeriodEndingLocalNamesFailure4() + throws Exception + { + try { + Rio.parse( + new StringReader( + "@prefix ns: . ns:1 a ns:uriWithDot. ; ns:title \"An example entity with uriWithDot as an object\" . "), + "", RDFFormat.TURTLE); + fail("Did not receive an exception"); + } + catch (RDFParseException e) { + System.out.println(e.getMessage()); + assertTrue(e.getMessage().contains("Expected an RDF value here, found ';'")); + } + } + + @Test + public void testSES2165LiteralSpaceDatatypeNewline() + throws Exception + { + Model model = Rio.parse(new StringReader(" \"testliteral\"^^\n ."), "", + RDFFormat.TURTLE); + + assertEquals(1, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), vf.createURI("urn:b"), + vf.createLiteral("testliteral", vf.createURI("urn:datatype")))); + } + + @Test + public void testSES2165LiteralSpaceDatatypeTab() + throws Exception + { + Model model = Rio.parse(new StringReader(" \"testliteral\"^^\t ."), "", + RDFFormat.TURTLE); + + assertEquals(1, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), vf.createURI("urn:b"), + vf.createLiteral("testliteral", vf.createURI("urn:datatype")))); + } + + @Test + public void testSES2165LiteralSpaceDatatypeCarriageReturn() + throws Exception + { + Model model = Rio.parse(new StringReader(" \"testliteral\"^^\r ."), "", + RDFFormat.TURTLE); + + assertEquals(1, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), vf.createURI("urn:b"), + vf.createLiteral("testliteral", vf.createURI("urn:datatype")))); + } + + @Test + public void testSES2165LiteralSpaceDatatypeSpace() + throws Exception + { + Model model = Rio.parse(new StringReader(" \"testliteral\"^^ ."), "", + RDFFormat.TURTLE); + + assertEquals(1, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), vf.createURI("urn:b"), + vf.createLiteral("testliteral", vf.createURI("urn:datatype")))); + } + + @Test + public void testSES2165LiteralSpaceDatatypeComment() + throws Exception + { + Model model = Rio.parse(new StringReader(" \"testliteral\"^^#comment\n ."), "", + RDFFormat.TURTLE); + + assertEquals(1, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), vf.createURI("urn:b"), + vf.createLiteral("testliteral", vf.createURI("urn:datatype")))); + } + + @Test + public void testParsingDefaultNamespaces() throws Exception { + Model model = Rio.parse(new StringReader(" skos:broader ."), "", + RDFFormat.TURTLE); + + assertEquals(1, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), SKOS.BROADER, vf.createURI("urn:b"))); + } + + @Test + public void testParsingNamespacesWithOption() throws Exception { + ParserConfig aConfig = new ParserConfig(); + + aConfig.set(BasicParserSettings.NAMESPACES, Collections.singleton(new NamespaceImpl("foo", SKOS.NAMESPACE))); + + Model model = Rio.parse(new StringReader(" foo:broader ."), "", RDFFormat.TURTLE, aConfig, vf, new ParseErrorLogger()); + + assertEquals(1, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), SKOS.BROADER, vf.createURI("urn:b"))); + } + + @Test + public void testParsingNamespacesWithOverride() throws Exception { + ParserConfig aConfig = new ParserConfig(); + + aConfig.set(BasicParserSettings.NAMESPACES, Collections.singleton(new NamespaceImpl("foo", SKOS.NAMESPACE))); + + Model model = Rio.parse(new StringReader("@prefix skos : ." + + " skos:broader ."), "", + RDFFormat.TURTLE, aConfig, vf, new ParseErrorLogger()); + + assertEquals(1, model.size()); + assertTrue(model.contains(vf.createURI("urn:a"), vf.createURI("urn:not_skos:broader"), vf.createURI("urn:b"))); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleEarlReport.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleEarlReport.java new file mode 100644 index 00000000000..e42c8edbd35 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleEarlReport.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.turtle; + +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.rio.EarlReport; + +/** + * Class for generating EARL reports for Turtle parser. + * + * @author Peter Ansell + */ +public class TurtleEarlReport { + + public static void main(String[] args) + throws Exception + { + new EarlReport().generateReport(new TurtleParserTest().createTestSuite(), EarlReport.ANSELL, + SimpleValueFactory.getInstance().createIRI("http://www.w3.org/TR/turtle/")); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleHandlingTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleHandlingTest.java new file mode 100644 index 00000000000..658fdf8a62e --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleHandlingTest.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.turtle; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.charset.Charset; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.rio.AbstractParserHandlingTest; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.turtle.TurtleParser; +import org.eclipse.rdf4j.rio.turtle.TurtleWriter; + +/** + * Test for error handling by Turtle Parser. + * + * @author Peter Ansell + */ +public class TurtleHandlingTest extends AbstractParserHandlingTest { + + @Override + protected InputStream getUnknownDatatypeStream(Model unknownDatatypeStatements) + throws Exception + { + return writeTurtle(unknownDatatypeStatements); + } + + @Override + protected InputStream getKnownDatatypeStream(Model knownDatatypeStatements) + throws Exception + { + return writeTurtle(knownDatatypeStatements); + } + + @Override + protected InputStream getUnknownLanguageStream(Model unknownLanguageStatements) + throws Exception + { + return writeTurtle(unknownLanguageStatements); + } + + @Override + protected InputStream getKnownLanguageStream(Model knownLanguageStatements) + throws Exception + { + return writeTurtle(knownLanguageStatements); + } + + @Override + protected RDFParser getParser() { + return new TurtleParser(); + } + + /** + * Helper method to write the given model to Turtle and return an InputStream + * containing the results. + * + * @param statements + * @return An {@link InputStream} containing the results. + * @throws RDFHandlerException + */ + private InputStream writeTurtle(Model statements) + throws RDFHandlerException + { + StringWriter writer = new StringWriter(); + + RDFWriter turtleWriter = new TurtleWriter(writer); + turtleWriter.startRDF(); + for (Statement nextStatement : statements) { + turtleWriter.handleStatement(nextStatement); + } + turtleWriter.endRDF(); + + return new ByteArrayInputStream(writer.toString().getBytes(Charset.forName("UTF-8"))); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleMimeTypeTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleMimeTypeTest.java new file mode 100644 index 00000000000..6ab78b0d9e0 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleMimeTypeTest.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.turtle; + +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; + +import junit.framework.TestCase; + +/** + * @author James Leigh + */ +public class TurtleMimeTypeTest extends TestCase { + + public void testTextTurtle() { + assertEquals( + RDFFormat.TURTLE, + Rio.getParserFormatForMIMEType("text/turtle").orElseThrow(Rio.unsupportedFormat(RDFFormat.TURTLE))); + } + + public void testTextTurtleUtf8() { + assertEquals( + RDFFormat.TURTLE, + Rio.getParserFormatForMIMEType("text/turtle;charset=UTF-8").orElseThrow( + Rio.unsupportedFormat(RDFFormat.TURTLE))); + } + + public void testApplicationXTurtle() { + assertEquals( + RDFFormat.TURTLE, + Rio.getParserFormatForMIMEType("application/x-turtle").orElseThrow( + Rio.unsupportedFormat(RDFFormat.TURTLE))); + } + +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleParserTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleParserTest.java new file mode 100644 index 00000000000..2772287154e --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleParserTest.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.turtle; + +import junit.framework.Test; + +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.helpers.TurtleParserSettings; +import org.eclipse.rdf4j.rio.ntriples.NTriplesParser; +import org.eclipse.rdf4j.rio.turtle.TurtleParser; +import org.eclipse.rdf4j.rio.turtle.TurtleParserTestCase; + +/** + * JUnit test for the Turtle parser that uses the tests that are available online. + */ +public class TurtleParserTest extends TurtleParserTestCase { + + public static Test suite() + throws Exception + { + return new TurtleParserTest().createTestSuite(); + } + + @Override + protected RDFParser createTurtleParser() { + RDFParser result = new TurtleParser(); + return result; + } + + @Override + protected RDFParser createNTriplesParser() { + return new NTriplesParser(); + } +} diff --git a/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleWriterTest.java b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleWriterTest.java new file mode 100644 index 00000000000..c74036cf892 --- /dev/null +++ b/compliance/rio/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleWriterTest.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.rio.turtle; + +import org.eclipse.rdf4j.rio.RDFWriterTest; +import org.eclipse.rdf4j.rio.turtle.TurtleParserFactory; +import org.eclipse.rdf4j.rio.turtle.TurtleWriterFactory; + +/** + * @author Arjohn Kampman + */ +public class TurtleWriterTest extends RDFWriterTest { + + public TurtleWriterTest() { + super(new TurtleWriterFactory(), new TurtleParserFactory()); + } +} diff --git a/compliance/rio/src/test/resources/logback-test.xml b/compliance/rio/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..ab29c59504b --- /dev/null +++ b/compliance/rio/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + diff --git a/compliance/serql/pom.xml b/compliance/serql/pom.xml new file mode 100644 index 00000000000..678463eddfa --- /dev/null +++ b/compliance/serql/pom.xml @@ -0,0 +1,103 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-compliance + 4.1.0-SNAPSHOT + + + rdf4j-serql-compliance + + RDF4J SeRQL query parser compliance tests + Tests for the SeRQL query language implementation + + + + ${project.groupId} + rdf4j-runtime + ${project.version} + + + + ${project.groupId} + rdf4j-serql-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-queryparser-serql + ${project.version} + + + + ${project.groupId} + rdf4j-repository-sail + ${project.version} + + + + ${project.groupId} + rdf4j-sail-memory + ${project.version} + + + + ch.qos.logback + logback-classic + test + + + + junit + junit + compile + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + 1 + false + -Xmx512M -XX:MaxPermSize=256M + + **/*Test.java + + + **/TestServer.java + + + + + integration-tests + integration-test + + integration-test + + + + verify + verify + + verify + + + + + + + + diff --git a/compliance/serql/src/test/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParserTest.java b/compliance/serql/src/test/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParserTest.java new file mode 100644 index 00000000000..e56bea38b64 --- /dev/null +++ b/compliance/serql/src/test/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParserTest.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import junit.framework.Test; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.parser.QueryParser; +import org.eclipse.rdf4j.query.parser.serql.SeRQLParser; +import org.eclipse.rdf4j.query.parser.serql.SeRQLParserTestCase; + +public class SeRQLParserTest extends SeRQLParserTestCase { + public static Test suite() throws Exception { + return SeRQLParserTestCase.suite(new Factory() { + public Test createTest(String name, String queryFile, Value result) { + return new SeRQLParserTest(name, queryFile, result); + } + }); + } + + public SeRQLParserTest(String name, String queryFile, Value result) { + super(name, queryFile, result); + } + + @Override + protected QueryParser createParser() { + return new SeRQLParser(); + } +} diff --git a/compliance/serql/src/test/java/org/eclipse/rdf4j/query/parser/serql/SeRQLQueryTest.java b/compliance/serql/src/test/java/org/eclipse/rdf4j/query/parser/serql/SeRQLQueryTest.java new file mode 100644 index 00000000000..aeff0871078 --- /dev/null +++ b/compliance/serql/src/test/java/org/eclipse/rdf4j/query/parser/serql/SeRQLQueryTest.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import java.util.List; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.parser.serql.SeRQLQueryTestCase; +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class SeRQLQueryTest extends SeRQLQueryTestCase { + + public static Test suite() throws Exception { + return SeRQLQueryTestCase.suite(new Factory() { + public Test createTest(String name, String dataFile, + List graphNames, String queryFile, + String resultFile, String entailment) { + return new SeRQLQueryTest(name, dataFile, graphNames, + queryFile, resultFile, entailment); + } + }); + } + + public SeRQLQueryTest(String name, String dataFile, + List graphNames, String queryFile, String resultFile, + String entailment) { + super(name, dataFile, graphNames, queryFile, resultFile, entailment); + } + + @Override + protected QueryLanguage getQueryLanguage() { + return QueryLanguage.SERQL; + } + + @Override + protected NotifyingSail newSail() { + return new MemoryStore(); + } +} diff --git a/compliance/serql/src/test/resources/logback-test.xml b/compliance/serql/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..4a6f17fbfa4 --- /dev/null +++ b/compliance/serql/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + diff --git a/compliance/sparql/pom.xml b/compliance/sparql/pom.xml new file mode 100644 index 00000000000..91b299dbe92 --- /dev/null +++ b/compliance/sparql/pom.xml @@ -0,0 +1,245 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-compliance + 4.1.0-SNAPSHOT + + + rdf4j-sparql-compliance + war + + RDF4J SPARQL query parser compliance tests + Tests for the SPARQL query language implementation + + + + ${project.groupId} + rdf4j-model + ${project.version} + + + + ${project.groupId} + rdf4j-sparql-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-rio-api + ${project.version} + + + + ${project.groupId} + rdf4j-rio-turtle + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-rio-rdfxml + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-query + ${project.version} + + + + ${project.groupId} + rdf4j-queryresultio-api + ${project.version} + + + + ${project.groupId} + rdf4j-queryresultio-sparqlxml + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-queryparser-api + ${project.version} + + + + ${project.groupId} + rdf4j-queryparser-sparql + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-repository-api + ${project.version} + + + + ${project.groupId} + rdf4j-repository-dataset + ${project.version} + + + + ${project.groupId} + rdf4j-repository-contextaware + ${project.version} + + + + ${project.groupId} + rdf4j-repository-sail + ${project.version} + + + + ${project.groupId} + rdf4j-sail-api + ${project.version} + + + + ${project.groupId} + rdf4j-http-server + ${project.version} + war + + + + ${project.groupId} + rdf4j-sail-memory + ${project.version} + + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + ${project.groupId} + rdf4j-sail-federation + ${project.version} + + + + org.slf4j + slf4j-api + + + + ch.qos.logback + logback-classic + test + + + + junit + junit + compile + + + + ${project.groupId} + rdf4j-http-protocol + ${project.version} + + + + ${project.groupId} + rdf4j-repository-manager + ${project.version} + + + + + org.eclipse.jetty + jetty-server + 7.0.2.v20100331 + + + + org.eclipse.jetty + jetty-webapp + 7.0.2.v20100331 + + + + org.mortbay.jetty + jetty-jsp-2.1 + 7.0.2.v20100331 + runtime + + + + org.slf4j + jcl-over-slf4j + test + + + org.slf4j + log4j-over-slf4j + test + + + + + + + org.apache.maven.plugins + maven-war-plugin + + ${project.build.directory}/openrdf-sesame + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + 1 + false + -Xmx512M -XX:MaxPermSize=256M + + **/*Test.java + + + + + integration-tests + integration-test + + integration-test + + + + verify + verify + + verify + + + + + + + diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/ArbitraryLengthPathTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/ArbitraryLengthPathTest.java new file mode 100644 index 00000000000..a30ccfe1751 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/ArbitraryLengthPathTest.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import junit.framework.TestCase; + +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author james + */ +public class ArbitraryLengthPathTest extends TestCase { + + private Repository repo; + + private RepositoryConnection con; + + @Before + public void setUp() + throws Exception + { + repo = new SailRepository(new MemoryStore()); + repo.initialize(); + con = repo.getConnection(); + } + + @After + public void tearDown() + throws Exception + { + con.close(); + repo.shutDown(); + } + + @Test + public void test10() + throws Exception + { + populate(10); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void test100() + throws Exception + { + populate(100); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void test1000() + throws Exception + { + populate(1000); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void test10000() + throws Exception + { + populate(10000); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void test100000() + throws Exception + { + populate(100000); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + private void populate(int n) + throws RepositoryException + { + ValueFactory vf = con.getValueFactory(); + for (int i = 0; i < n; i++) { + con.add(vf.createIRI("urn:test:root"), vf.createIRI("urn:test:hasChild"), + vf.createIRI("urn:test:node" + i)); + } + con.add(vf.createIRI("urn:test:root"), vf.createIRI("urn:test:hasChild"), + vf.createIRI("urn:test:node-end")); + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemoryComplexSPARQLQueryTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemoryComplexSPARQLQueryTest.java new file mode 100644 index 00000000000..1c08edf4528 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemoryComplexSPARQLQueryTest.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import org.eclipse.rdf4j.query.parser.sparql.ComplexSPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +/** + * @author jeen + */ +public class MemoryComplexSPARQLQueryTest extends ComplexSPARQLQueryTest { + + @Override + protected Repository newRepository() + throws Exception + { + return new SailRepository(new MemoryStore()); + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemorySPARQLUpdateTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemorySPARQLUpdateTest.java new file mode 100644 index 00000000000..8a05a5e4e7c --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemorySPARQLUpdateTest.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import org.eclipse.rdf4j.query.parser.sparql.SPARQLUpdateTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + + +/** + * Test SPARQL 1.1 Update functionality on an in-memory store. + * + * @author Jeen Broekstra + */ +public class MemorySPARQLUpdateTest extends SPARQLUpdateTest { + + @Override + protected Repository newRepository() + throws Exception + { + return new SailRepository(new MemoryStore()); + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLEmbeddedServer.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLEmbeddedServer.java new file mode 100644 index 00000000000..35fd60fd84e --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLEmbeddedServer.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import java.io.File; +import java.util.List; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.nio.BlockingChannelConnector; +import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigUtil; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.repository.manager.SystemRepository; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.sail.memory.config.MemoryStoreConfig; + +/** + * An embedded http server for SPARQL query testing. Initializes a memory store + * repository for each specified reposiotoryId. + * + * @author Andreas Schwarte + */ +public class SPARQLEmbeddedServer { + + private static final String HOST = "localhost"; + + private static final int PORT = 18080; + + private static final String OPENRDF_CONTEXT = "/openrdf"; + + private final List repositoryIds; + + private final Server jetty; + + /** + * @param repositoryIds + */ + public SPARQLEmbeddedServer(List repositoryIds) { + this.repositoryIds = repositoryIds; + System.clearProperty("DEBUG"); + + jetty = new Server(); + + Connector conn = new BlockingChannelConnector(); + conn.setHost(HOST); + conn.setPort(PORT); + jetty.addConnector(conn); + + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath(OPENRDF_CONTEXT); + // warPath configured in pom.xml maven-war-plugin configuration + webapp.setWar("./target/openrdf-sesame"); + jetty.setHandler(webapp); + } + + /** + * @return the url to the repository with given id + */ + public String getRepositoryUrl(String repoId) { + return Protocol.getRepositoryLocation(getServerUrl(), repoId); + } + + /** + * @return the server url + */ + public String getServerUrl() { + return "http://" + HOST + ":" + PORT + OPENRDF_CONTEXT; + } + + public void start() + throws Exception + { + File dataDir = new File(System.getProperty("user.dir") + "/target/datadir"); + dataDir.mkdirs(); + System.setProperty("info.aduna.platform.appdata.basedir", dataDir.getAbsolutePath()); + + jetty.start(); + + createTestRepositories(); + } + + public void stop() + throws Exception + { + Repository systemRepo = new HTTPRepository(Protocol.getRepositoryLocation(getServerUrl(), + SystemRepository.ID)); + RepositoryConnection con = systemRepo.getConnection(); + try { + con.clear(); + } + finally { + con.close(); + systemRepo.shutDown(); + } + + jetty.stop(); + System.clearProperty("org.mortbay.log.class"); + } + + private void createTestRepositories() + throws RepositoryException, RepositoryConfigException + { + Repository systemRep = new HTTPRepository(Protocol.getRepositoryLocation(getServerUrl(), + SystemRepository.ID)); + + // create a memory store for each provided repository id + for (String repId : repositoryIds) { + MemoryStoreConfig memStoreConfig = new MemoryStoreConfig(); + memStoreConfig.setPersist(false); + SailRepositoryConfig sailRepConfig = new SailRepositoryConfig(memStoreConfig); + RepositoryConfig repConfig = new RepositoryConfig(repId, sailRepConfig); + + RepositoryConfigUtil.updateRepositoryConfigs(systemRep, repConfig); + } + + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLServiceEvaluationTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLServiceEvaluationTest.java new file mode 100644 index 00000000000..aadb5301c13 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLServiceEvaluationTest.java @@ -0,0 +1,792 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import junit.framework.TestCase; + +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.common.text.StringUtil; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.util.Models; +import org.eclipse.rdf4j.model.vocabulary.FOAF; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.BooleanQuery; +import org.eclipse.rdf4j.query.GraphQuery; +import org.eclipse.rdf4j.query.GraphQueryResult; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.Query; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.dawg.DAWGTestResultSetUtil; +import org.eclipse.rdf4j.query.impl.MutableTupleQueryResult; +import org.eclipse.rdf4j.query.impl.TupleQueryResultBuilder; +import org.eclipse.rdf4j.query.resultio.QueryResultFormat; +import org.eclipse.rdf4j.query.resultio.QueryResultIO; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultParser; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.RDFParser.DatatypeHandling; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Test suite for evaluation of SPARQL queries involving SERVICE clauses. The + * test suite starts up an embedded Jetty server running Sesame, which functions + * as the SPARQL endpoint to test against. The test is configured to execute the + * W3C service tests located in + * sesame-sparql-testsuite/src/main/resources/testcases-service + * + * @author Jeen Broekstra + * @author Andreas Schwarte + */ +public class SPARQLServiceEvaluationTest extends TestCase { + + static final Logger logger = LoggerFactory.getLogger(SPARQLServiceEvaluationTest.class); + + /** + * The maximal number of endpoints occurring in a (single) test case + */ + protected static final int MAX_ENDPOINTS = 3; + + private SPARQLEmbeddedServer server; + + private SailRepository localRepository; + + private List remoteRepositories; + + public SPARQLServiceEvaluationTest() { + + } + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + // set up the server: the maximal number of endpoints must be known + List repositoryIds = new ArrayList(MAX_ENDPOINTS); + for (int i = 1; i <= MAX_ENDPOINTS; i++) + repositoryIds.add("endpoint" + i); + server = new SPARQLEmbeddedServer(repositoryIds); + + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + + remoteRepositories = new ArrayList(MAX_ENDPOINTS); + for (int i = 1; i <= MAX_ENDPOINTS; i++) { + HTTPRepository r = new HTTPRepository(getRepositoryUrl(i)); + r.initialize(); + remoteRepositories.add(r); + } + + localRepository = new SailRepository(new MemoryStore()); + localRepository.initialize(); + } + + /** + * Get the repository url, initialized repositories are called endpoint1 + * endpoint2 .. endpoint%MAX_ENDPOINTS% + * + * @param i + * the index of the repository, starting with 1 + * @return + */ + protected String getRepositoryUrl(int i) { + return server.getRepositoryUrl("endpoint" + i); + } + + /** + * Get the repository, initialized repositories are called endpoint1 + * endpoint2 .. endpoint%MAX_ENDPOINTS% + * + * @param i + * the index of the repository, starting with 1 + * @return + */ + public HTTPRepository getRepository(int i) { + return remoteRepositories.get(i - 1); + } + + /** + * Prepare a particular test, and load the specified data. Note: the + * repositories are cleared before loading data + * + * @param localData + * a local data file that is added to local repository, use null if + * there is no local data + * @param endpointData + * a list of endpoint data files, dataFile at index is loaded to + * endpoint%i%, use empty list for no remote data + * @throws Exception + */ + protected void prepareTest(String localData, List endpointData) + throws Exception + { + + if (endpointData.size() > MAX_ENDPOINTS) + throw new RuntimeException("MAX_ENDPOINTs to low, " + endpointData.size() + + " repositories needed. Adjust configuration"); + + if (localData != null) { + loadDataSet(localRepository, localData); + } + + int i = 1; // endpoint id, start with 1 + for (String s : endpointData) { + loadDataSet(getRepository(i++), s); + } + + } + + /** + * Load a dataset. Note: the repositories are cleared before loading data + * + * @param rep + * @param datasetFile + * @throws RDFParseException + * @throws RepositoryException + * @throws IOException + */ + protected void loadDataSet(Repository rep, String datasetFile) + throws RDFParseException, RepositoryException, IOException + { + logger.debug("loading dataset..."); + InputStream dataset = SPARQLServiceEvaluationTest.class.getResourceAsStream(datasetFile); + + if (dataset == null) + throw new IllegalArgumentException("Datasetfile " + datasetFile + " not found."); + + RepositoryConnection con = rep.getConnection(); + try { + con.clear(); + con.add(dataset, "", + Rio.getParserFormatForFileName(datasetFile).orElseThrow(Rio.unsupportedFormat(datasetFile))); + } + finally { + dataset.close(); + con.close(); + } + logger.debug("dataset loaded."); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + try { + localRepository.shutDown(); + } + finally { + server.stop(); + } + } + + @Test + public void testSimpleServiceQuery() + throws RepositoryException + { + // test setup + String EX_NS = "http://example.org/"; + ValueFactory f = localRepository.getValueFactory(); + IRI bob = f.createIRI(EX_NS, "bob"); + IRI alice = f.createIRI(EX_NS, "alice"); + IRI william = f.createIRI(EX_NS, "william"); + + // clears the repository and adds new data + try { + prepareTest("/testcases-service/simple-default-graph.ttl", + Arrays.asList("/testcases-service/simple.ttl")); + } + catch (Exception e1) { + fail(e1.getMessage()); + } + + StringBuilder qb = new StringBuilder(); + qb.append(" SELECT * \n"); + qb.append(" WHERE { \n"); + qb.append(" SERVICE <" + getRepositoryUrl(1) + "> { \n"); + qb.append(" ?X <" + FOAF.NAME + "> ?Y \n "); + qb.append(" } \n "); + qb.append(" ?X a <" + FOAF.PERSON + "> . \n"); + qb.append(" } \n"); + + RepositoryConnection conn = localRepository.getConnection(); + try { + TupleQuery tq = conn.prepareTupleQuery(QueryLanguage.SPARQL, qb.toString()); + + TupleQueryResult tqr = tq.evaluate(); + + assertNotNull(tqr); + assertTrue(tqr.hasNext()); + + int count = 0; + while (tqr.hasNext()) { + BindingSet bs = tqr.next(); + count++; + + Value x = bs.getValue("X"); + Value y = bs.getValue("Y"); + + assertFalse(william.equals(x)); + + assertTrue(bob.equals(x) || alice.equals(x)); + if (bob.equals(x)) { + f.createLiteral("Bob").equals(y); + } + else if (alice.equals(x)) { + f.createLiteral("Alice").equals(y); + } + } + + assertEquals(2, count); + + } + catch (MalformedQueryException e) { + fail(e.getMessage()); + } + catch (QueryEvaluationException e) { + fail(e.getMessage()); + } + finally { + conn.close(); + } + } + + @Test + public void test1() + throws Exception + { + prepareTest("/testcases-service/data01.ttl", Arrays.asList("/testcases-service/data01endpoint.ttl")); + execute("/testcases-service/service01.rq", "/testcases-service/service01.srx", false); + } + + @Test + public void test2() + throws Exception + { + prepareTest(null, + Arrays.asList("/testcases-service/data02endpoint1.ttl", "/testcases-service/data02endpoint2.ttl")); + execute("/testcases-service/service02.rq", "/testcases-service/service02.srx", false); + } + + @Test + public void test3() + throws Exception + { + prepareTest(null, + Arrays.asList("/testcases-service/data03endpoint1.ttl", "/testcases-service/data03endpoint2.ttl")); + execute("/testcases-service/service03.rq", "/testcases-service/service03.srx", false); + } + + @Test + public void test4() + throws Exception + { + prepareTest("/testcases-service/data04.ttl", Arrays.asList("/testcases-service/data04endpoint.ttl")); + execute("/testcases-service/service04.rq", "/testcases-service/service04.srx", false); + } + + @Test + public void test5() + throws Exception + { + prepareTest("/testcases-service/data05.ttl", + Arrays.asList("/testcases-service/data05endpoint1.ttl", "/testcases-service/data05endpoint2.ttl")); + execute("/testcases-service/service05.rq", "/testcases-service/service05.srx", false); + } + + @Test + public void test6() + throws Exception + { + prepareTest(null, Arrays.asList("/testcases-service/data06endpoint1.ttl")); + execute("/testcases-service/service06.rq", "/testcases-service/service06.srx", false); + } + + @Test + public void test7() + throws Exception + { + // clears the repository and adds new data + execute + prepareTest("/testcases-service/data07.ttl", Collections. emptyList()); + execute("/testcases-service/service07.rq", "/testcases-service/service07.srx", false); + } + + @Test + public void test8() + throws Exception + { + /* test where the SERVICE expression is to be evaluated as ASK request */ + prepareTest("/testcases-service/data08.ttl", Arrays.asList("/testcases-service/data08endpoint.ttl")); + execute("/testcases-service/service08.rq", "/testcases-service/service08.srx", false); + } + + @Test + public void test9() + throws Exception + { + /* test where the service endpoint is bound at runtime through BIND */ + prepareTest(null, Arrays.asList("/testcases-service/data09endpoint.ttl")); + execute("/testcases-service/service09.rq", "/testcases-service/service09.srx", false); + } + + @Test + public void test10() + throws Exception + { + /* test how we deal with blank node */ + prepareTest("/testcases-service/data10.ttl", Arrays.asList("/testcases-service/data10endpoint.ttl")); + execute("/testcases-service/service10.rq", "/testcases-service/service10.srx", false); + } + + @Test + public void test11() + throws Exception + { + /* test vectored join with more intermediate results */ + // clears the repository and adds new data + execute + prepareTest("/testcases-service/data11.ttl", Arrays.asList("/testcases-service/data11endpoint.ttl")); + execute("/testcases-service/service11.rq", "/testcases-service/service11.srx", false); + } + + // test on remote DBpedia endpoint disabled. Only enable for manual testing, + // should not be enabled for + // Surefire or Hudson. + // /** + // * This is a manual test to see the Fallback in action. Query asks + // * DBpedia, which does not support BINDINGS + // * + // * @throws Exception + // */ + // public void testFallbackWithDBpedia() throws Exception { + // /* test vectored join with more intermediate results */ + // // clears the repository and adds new data + execute + // prepareTest("/testcases-service/data12.ttl", + // Collections.emptyList()); + // execute("/testcases-service/service12.rq", + // "/testcases-service/service12.srx", false); + // } + + @Test + public void test13() + throws Exception + { + /* test for bug SES-899: cross product is required */ + prepareTest(null, Arrays.asList("/testcases-service/data13.ttl")); + execute("/testcases-service/service13.rq", "/testcases-service/service13.srx", false); + } + + @Test + public void testEmptyServiceBlock() + throws Exception + { + /* test for bug SES-900: nullpointer for empty service block */ + prepareTest(null, Arrays.asList("/testcases-service/data13.ttl")); + execute("/testcases-service/service14.rq", "/testcases-service/service14.srx", false); + } + + @Test + public void testNotProjectedCount() + throws Exception + { + /* test projection of subqueries - SES-1000 */ + prepareTest(null, Arrays.asList("/testcases-service/data17endpoint1.ttl")); + execute("/testcases-service/service17.rq", "/testcases-service/service17.srx", false); + } + + @Test + public void testNonAsciiCharHandling() + throws Exception + { + /* SES-1056 */ + prepareTest(null, Arrays.asList("/testcases-service/data18endpoint1.rdf")); + execute("/testcases-service/service18.rq", "/testcases-service/service18.srx", false); + } + + /** + * Execute a testcase, both queryFile and expectedResultFile must be files + * located on the class path. + * + * @param queryFile + * @param expectedResultFile + * @param checkOrder + * @throws Exception + */ + private void execute(String queryFile, String expectedResultFile, boolean checkOrder) + throws Exception + { + RepositoryConnection conn = localRepository.getConnection(); + String queryString = readQueryString(queryFile); + + try { + Query query = conn.prepareQuery(QueryLanguage.SPARQL, queryString); + + if (query instanceof TupleQuery) { + TupleQueryResult queryResult = ((TupleQuery)query).evaluate(); + + TupleQueryResult expectedResult = readExpectedTupleQueryResult(expectedResultFile); + + compareTupleQueryResults(queryResult, expectedResult, checkOrder); + + } + else if (query instanceof GraphQuery) { + GraphQueryResult gqr = ((GraphQuery)query).evaluate(); + Set queryResult = Iterations.asSet(gqr); + + Set expectedResult = readExpectedGraphQueryResult(expectedResultFile); + + compareGraphs(queryResult, expectedResult); + + } + else if (query instanceof BooleanQuery) { + // TODO implement if needed + throw new RuntimeException("Not yet supported " + query.getClass()); + } + else { + throw new RuntimeException("Unexpected query type: " + query.getClass()); + } + } + finally { + conn.close(); + } + } + + /** + * Read the query string from the specified resource + * + * @param queryResource + * @return + * @throws RepositoryException + * @throws IOException + */ + private String readQueryString(String queryResource) + throws RepositoryException, IOException + { + InputStream stream = SPARQLServiceEvaluationTest.class.getResourceAsStream(queryResource); + try { + return IOUtil.readString(new InputStreamReader(stream, "UTF-8")); + } + finally { + stream.close(); + } + } + + /** + * Read the expected tuple query result from the specified resource + * + * @param queryResource + * @return + * @throws RepositoryException + * @throws IOException + */ + private TupleQueryResult readExpectedTupleQueryResult(String resultFile) + throws Exception + { + Optional tqrFormat = QueryResultIO.getParserFormatForFileName(resultFile); + + if (tqrFormat.isPresent()) { + InputStream in = SPARQLServiceEvaluationTest.class.getResourceAsStream(resultFile); + try { + TupleQueryResultParser parser = QueryResultIO.createTupleParser(tqrFormat.get()); + parser.setValueFactory(SimpleValueFactory.getInstance()); + + TupleQueryResultBuilder qrBuilder = new TupleQueryResultBuilder(); + parser.setQueryResultHandler(qrBuilder); + + parser.parseQueryResult(in); + return qrBuilder.getQueryResult(); + } + finally { + in.close(); + } + } + else { + Set resultGraph = readExpectedGraphQueryResult(resultFile); + return DAWGTestResultSetUtil.toTupleQueryResult(resultGraph); + } + } + + /** + * Read the expected graph query result from the specified resource + * + * @param resultFile + * @return + * @throws Exception + */ + private Set readExpectedGraphQueryResult(String resultFile) + throws Exception + { + RDFFormat rdfFormat = Rio.getParserFormatForFileName(resultFile).orElseThrow( + Rio.unsupportedFormat(resultFile)); + + RDFParser parser = Rio.createParser(rdfFormat); + parser.setDatatypeHandling(DatatypeHandling.IGNORE); + parser.setPreserveBNodeIDs(true); + parser.setValueFactory(SimpleValueFactory.getInstance()); + + Set result = new LinkedHashSet(); + parser.setRDFHandler(new StatementCollector(result)); + + InputStream in = SPARQLServiceEvaluationTest.class.getResourceAsStream(resultFile); + try { + parser.parse(in, null); // TODO check + } + finally { + in.close(); + } + + return result; + } + + /** + * Compare two tuple query results + * + * @param queryResult + * @param expectedResult + * @param checkOrder + * @throws Exception + */ + private void compareTupleQueryResults(TupleQueryResult queryResult, TupleQueryResult expectedResult, + boolean checkOrder) + throws Exception + { + // Create MutableTupleQueryResult to be able to re-iterate over the + // results + MutableTupleQueryResult queryResultTable = new MutableTupleQueryResult(queryResult); + MutableTupleQueryResult expectedResultTable = new MutableTupleQueryResult(expectedResult); + + boolean resultsEqual; + + resultsEqual = QueryResults.equals(queryResultTable, expectedResultTable); + + if (checkOrder) { + // also check the order in which solutions occur. + queryResultTable.beforeFirst(); + expectedResultTable.beforeFirst(); + + while (queryResultTable.hasNext()) { + BindingSet bs = queryResultTable.next(); + BindingSet expectedBs = expectedResultTable.next(); + + if (!bs.equals(expectedBs)) { + resultsEqual = false; + break; + } + } + } + + if (!resultsEqual) { + queryResultTable.beforeFirst(); + expectedResultTable.beforeFirst(); + + /* + * StringBuilder message = new StringBuilder(128); + * message.append("\n============ "); message.append(getName()); + * message.append(" =======================\n"); + * message.append("Expected result: \n"); while + * (expectedResultTable.hasNext()) { + * message.append(expectedResultTable.next()); message.append("\n"); } + * message.append("============="); StringUtil.appendN('=', + * getName().length(), message); + * message.append("========================\n"); message.append("Query + * result: \n"); while (queryResultTable.hasNext()) { + * message.append(queryResultTable.next()); message.append("\n"); } + * message.append("============="); StringUtil.appendN('=', + * getName().length(), message); + * message.append("========================\n"); + */ + + List queryBindings = Iterations.asList(queryResultTable); + + List expectedBindings = Iterations.asList(expectedResultTable); + + List missingBindings = new ArrayList(expectedBindings); + missingBindings.removeAll(queryBindings); + + List unexpectedBindings = new ArrayList(queryBindings); + unexpectedBindings.removeAll(expectedBindings); + + StringBuilder message = new StringBuilder(128); + message.append("\n============ "); + message.append(getName()); + message.append(" =======================\n"); + + if (!missingBindings.isEmpty()) { + + message.append("Missing bindings: \n"); + for (BindingSet bs : missingBindings) { + message.append(bs); + message.append("\n"); + } + + message.append("============="); + StringUtil.appendN('=', getName().length(), message); + message.append("========================\n"); + } + + if (!unexpectedBindings.isEmpty()) { + message.append("Unexpected bindings: \n"); + for (BindingSet bs : unexpectedBindings) { + message.append(bs); + message.append("\n"); + } + + message.append("============="); + StringUtil.appendN('=', getName().length(), message); + message.append("========================\n"); + } + + if (checkOrder && missingBindings.isEmpty() && unexpectedBindings.isEmpty()) { + message.append("Results are not in expected order.\n"); + message.append(" =======================\n"); + message.append("query result: \n"); + for (BindingSet bs : queryBindings) { + message.append(bs); + message.append("\n"); + } + message.append(" =======================\n"); + message.append("expected result: \n"); + for (BindingSet bs : expectedBindings) { + message.append(bs); + message.append("\n"); + } + message.append(" =======================\n"); + + System.out.print(message.toString()); + } + + logger.error(message.toString()); + fail(message.toString()); + } + /* debugging only: print out result when test succeeds + else { + queryResultTable.beforeFirst(); + + List queryBindings = Iterations.asList(queryResultTable); + StringBuilder message = new StringBuilder(128); + + message.append("\n============ "); + message.append(getName()); + message.append(" =======================\n"); + + message.append(" =======================\n"); + message.append("query result: \n"); + for (BindingSet bs: queryBindings) { + message.append(bs); + message.append("\n"); + } + + System.out.print(message.toString()); + } + */ + } + + /** + * Compare two graphs + * + * @param queryResult + * @param expectedResult + * @throws Exception + */ + private void compareGraphs(Set queryResult, Set expectedResult) + throws Exception + { + if (!Models.isomorphic(expectedResult, queryResult)) { + // Don't use RepositoryUtil.difference, it reports incorrect diffs + /* + * Collection unexpectedStatements = + * RepositoryUtil.difference(queryResult, expectedResult); Collection missingStatements = + * RepositoryUtil.difference(expectedResult, queryResult); + * StringBuilder message = new StringBuilder(128); + * message.append("\n=======Diff: "); message.append(getName()); + * message.append("========================\n"); if + * (!unexpectedStatements.isEmpty()) { message.append("Unexpected + * statements in result: \n"); for (Statement st : + * unexpectedStatements) { message.append(st.toString()); + * message.append("\n"); } message.append("============="); for (int i = + * 0; i < getName().length(); i++) { message.append("="); } + * message.append("========================\n"); } if + * (!missingStatements.isEmpty()) { message.append("Statements missing + * in result: \n"); for (Statement st : missingStatements) { + * message.append(st.toString()); message.append("\n"); } + * message.append("============="); for (int i = 0; i < + * getName().length(); i++) { message.append("="); } + * message.append("========================\n"); } + */ + StringBuilder message = new StringBuilder(128); + message.append("\n============ "); + message.append(getName()); + message.append(" =======================\n"); + message.append("Expected result: \n"); + for (Statement st : expectedResult) { + message.append(st.toString()); + message.append("\n"); + } + message.append("============="); + StringUtil.appendN('=', getName().length(), message); + message.append("========================\n"); + + message.append("Query result: \n"); + for (Statement st : queryResult) { + message.append(st.toString()); + message.append("\n"); + } + message.append("============="); + StringUtil.appendN('=', getName().length(), message); + message.append("========================\n"); + + logger.error(message.toString()); + fail(message.toString()); + } + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/CoreSPARQLSyntaxTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/CoreSPARQLSyntaxTest.java new file mode 100644 index 00000000000..30a8c76a94a --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/CoreSPARQLSyntaxTest.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLSyntaxTest; + +public class CoreSPARQLSyntaxTest extends SPARQLSyntaxTest { + + public static Test suite() + throws Exception + { + return SPARQLSyntaxTest.suite(new Factory() { + + public SPARQLSyntaxTest createSPARQLSyntaxTest(String testURI, String testName, String testAction, + boolean positiveTest) + { + return new CoreSPARQLSyntaxTest(testURI, testName, testAction, positiveTest); + } + }); + } + + public CoreSPARQLSyntaxTest(String testURI, String name, String queryFileURL, boolean positiveTest) { + super(testURI, name, queryFileURL, positiveTest); + } + + protected void parseQuery(String query, String queryFileURL) + throws MalformedQueryException + { + QueryParserUtil.parseQuery(QueryLanguage.SPARQL, query, queryFileURL); + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/EarlReport.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/EarlReport.java new file mode 100644 index 00000000000..6802a6ea9db --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/EarlReport.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import java.io.File; +import java.io.FileOutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestListener; +import junit.framework.TestResult; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.DC; +import org.eclipse.rdf4j.model.vocabulary.DCTERMS; +import org.eclipse.rdf4j.model.vocabulary.DOAP; +import org.eclipse.rdf4j.model.vocabulary.EARL; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11SyntaxTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLUpdateConformanceTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFWriterFactory; +import org.eclipse.rdf4j.rio.RDFWriterRegistry; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Arjohn Kampman + */ +public class EarlReport { + + protected static Repository earlRepository; + + protected static ValueFactory vf; + + protected static RepositoryConnection con; + + protected static Resource projectNode; + + protected static Resource asserterNode; + + private static Logger logger = LoggerFactory.getLogger(EarlReport.class); + + public static void main(String[] args) + throws Exception + { + earlRepository = new SailRepository(new MemoryStore()); + earlRepository.initialize(); + vf = earlRepository.getValueFactory(); + con = earlRepository.getConnection(); + con.begin(); + + con.setNamespace("rdf", RDF.NAMESPACE); + con.setNamespace("xsd", XMLSchema.NAMESPACE); + con.setNamespace("doap", DOAP.NAMESPACE); + con.setNamespace("earl", EARL.NAMESPACE); + con.setNamespace("dcterms", DCTERMS.NAMESPACE); + + projectNode = vf.createBNode(); + BNode releaseNode = vf.createBNode(); + con.add(projectNode, RDF.TYPE, DOAP.PROJECT); + con.add(projectNode, DOAP.NAME, vf.createLiteral("OpenRDF Sesame")); + con.add(projectNode, DOAP.RELEASE, releaseNode); + con.add(projectNode, DOAP.HOMEPAGE, vf.createIRI("http://www.openrdf.org/")); + con.add(releaseNode, RDF.TYPE, DOAP.VERSION); + con.add(releaseNode, DOAP.NAME, vf.createLiteral("Sesame 2.7.0")); + SimpleDateFormat xsdDataFormat = new SimpleDateFormat("yyyy-MM-dd"); + String currentDate = xsdDataFormat.format(new Date()); + con.add(releaseNode, DOAP.CREATED, vf.createLiteral(currentDate, XMLSchema.DATE)); + + asserterNode = vf.createBNode(); + con.add(asserterNode, RDF.TYPE, EARL.SOFTWARE); + con.add(asserterNode, DC.TITLE, vf.createLiteral("OpenRDF SPARQL 1.1 compliance tests")); + + TestResult testResult = new TestResult(); + EarlTestListener listener = new EarlTestListener(); + testResult.addListener(listener); + + logger.info("running query evaluation tests.."); + W3CApprovedSPARQL11QueryTest.suite().run(testResult); + + logger.info("running syntax tests..."); + W3CApprovedSPARQL11SyntaxTest.suite().run(testResult); + + logger.info("running update tests..."); + W3CApprovedSPARQL11UpdateTest.suite().run(testResult); + logger.info("tests complete, generating EARL report..."); + + con.commit(); + + RDFWriterFactory factory = RDFWriterRegistry.getInstance().get(RDFFormat.TURTLE).orElseThrow( + Rio.unsupportedFormat(RDFFormat.TURTLE)); + File outFile = File.createTempFile("sesame-sparql-compliance", + "." + RDFFormat.TURTLE.getDefaultFileExtension()); + FileOutputStream out = new FileOutputStream(outFile); + try { + con.export(factory.getWriter(out)); + } + finally { + out.close(); + } + + con.close(); + earlRepository.shutDown(); + + logger.info("EARL output written to " + outFile); + } + + protected static class EarlTestListener implements TestListener { + + private int errorCount; + + private int failureCount; + + public void startTest(Test test) { + errorCount = failureCount = 0; + } + + public void endTest(Test test) { + String testURI = null; + ; + if (test instanceof SPARQLQueryTest) { + testURI = ((SPARQLQueryTest)test).testURI; + } + else if (test instanceof SPARQL11SyntaxTest) { + testURI = ((SPARQL11SyntaxTest)test).testURI; + } + else if (test instanceof SPARQLUpdateConformanceTest) { + testURI = ((SPARQLUpdateConformanceTest)test).testURI; + } + else { + throw new RuntimeException("Unexpected test type: " + test.getClass()); + } + + try { + BNode testNode = vf.createBNode(); + BNode resultNode = vf.createBNode(); + con.add(testNode, RDF.TYPE, EARL.ASSERTION); + con.add(testNode, EARL.ASSERTEDBY, asserterNode); + con.add(testNode, EARL.MODE, EARL.AUTOMATIC); + con.add(testNode, EARL.SUBJECT, projectNode); + con.add(testNode, EARL.TEST, vf.createIRI(testURI)); + con.add(testNode, EARL.RESULT, resultNode); + con.add(resultNode, RDF.TYPE, EARL.TESTRESULT); + + if (errorCount > 0) { + con.add(resultNode, EARL.OUTCOME, EARL.FAIL); + } + else if (failureCount > 0) { + con.add(resultNode, EARL.OUTCOME, EARL.FAIL); + } + else { + con.add(resultNode, EARL.OUTCOME, EARL.PASS); + } + } + catch (RepositoryException e) { + throw new RuntimeException(e); + } + } + + public void addError(Test test, Throwable t) { + errorCount++; + } + + public void addFailure(Test test, AssertionFailedError error) { + failureCount++; + } + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/MemorySPARQLQueryTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/MemorySPARQLQueryTest.java new file mode 100644 index 00000000000..0e4e29569e0 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/MemorySPARQLQueryTest.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.parser.sparql.manifest.ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemorySPARQLQueryTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return ManifestTest.suite(new Factory() { + + public MemorySPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, false); + } + + public MemorySPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + return new MemorySPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder); + } + }); + } + + protected MemorySPARQLQueryTest(String testURI, String name, String queryFileURL, String resultFileURL, + Dataset dataSet, boolean laxCardinality) + { + this(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false); + } + + protected MemorySPARQLQueryTest(String testURI, String name, String queryFileURL, String resultFileURL, + Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder); + } + + protected Repository newRepository() { + return new DatasetRepository(new SailRepository(new MemoryStore())); + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11QueryTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11QueryTest.java new file mode 100644 index 00000000000..0d35b23368c --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11QueryTest.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class W3CApprovedSPARQL11QueryTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return SPARQL11ManifestTest.suite(new Factory() { + + public W3CApprovedSPARQL11QueryTest createSPARQLQueryTest(String testURI, String name, + String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, + false); + } + + public W3CApprovedSPARQL11QueryTest createSPARQLQueryTest(String testURI, String name, + String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality, + boolean checkOrder) + { + String[] ignoredTests = { + // test case incompatible with RDF 1.1 - see + // http://lists.w3.org/Archives/Public/public-sparql-dev/2013AprJun/0006.html + "STRDT TypeErrors", + // test case incompatible with RDF 1.1 - see + // http://lists.w3.org/Archives/Public/public-sparql-dev/2013AprJun/0006.html + "STRLANG TypeErrors", + // known issue: SES-937 + "sq03 - Subquery within graph pattern, graph variable is not bound" }; + + return new W3CApprovedSPARQL11QueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder, ignoredTests); + } + }, true, true, false, "service"); + } + + protected W3CApprovedSPARQL11QueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, String... ignoredTests) + { + this(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false, ignoredTests); + } + + protected W3CApprovedSPARQL11QueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder, + String... ignoredTests) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder, ignoredTests); + } + + protected Repository newRepository() { + return new DatasetRepository(new SailRepository(new MemoryStore())); + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11SyntaxTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11SyntaxTest.java new file mode 100644 index 00000000000..1620f923c72 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11SyntaxTest.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.parser.ParsedOperation; +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11SyntaxTest; + +public class W3CApprovedSPARQL11SyntaxTest extends SPARQL11SyntaxTest { + + public static Test suite() + throws Exception + { + return SPARQL11SyntaxTest.suite(new Factory() { + + public SPARQL11SyntaxTest createSPARQLSyntaxTest(String testURI, String testName, String testAction, + boolean positiveTest) + { + return new W3CApprovedSPARQL11SyntaxTest(testURI, testName, testAction, positiveTest); + } + }, false); + } + + public W3CApprovedSPARQL11SyntaxTest(String testURI, String name, String queryFileURL, boolean positiveTest) { + super(testURI, name, queryFileURL, positiveTest); + } + + protected ParsedOperation parseOperation(String operation, String fileURL) + throws MalformedQueryException + { + return QueryParserUtil.parseOperation(QueryLanguage.SPARQL, operation, fileURL); + } + + @Override + protected void runTest() + throws Exception + { + if (this.getName().contains("syntax-update-54")) { + // we skip this negative syntax test because it is an unnecessarily restrictive test that is almost + // impossible to implement correctly, and which in practice Sesame handles correctly simply by + // assigning different blank node ids. + } + else { + super.runTest(); + } + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11UpdateTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11UpdateTest.java new file mode 100644 index 00000000000..a3a8c5de9d5 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11UpdateTest.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import java.util.Map; + +import junit.framework.Test; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLUpdateConformanceTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.contextaware.ContextAwareRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + + +/** + * @author Jeen Broekstra + */ +public class W3CApprovedSPARQL11UpdateTest extends SPARQLUpdateConformanceTest { + + public W3CApprovedSPARQL11UpdateTest(String testURI, String name, String requestFile, + IRI defaultGraphURI, Map inputNamedGraphs, IRI resultDefaultGraphURI, + Map resultNamedGraphs) + { + super(testURI, name, requestFile, defaultGraphURI, inputNamedGraphs, resultDefaultGraphURI, + resultNamedGraphs); + } + + public static Test suite() + throws Exception + { + return SPARQL11ManifestTest.suite(new Factory() { + + public W3CApprovedSPARQL11UpdateTest createSPARQLUpdateConformanceTest(String testURI, + String name, String requestFile, IRI defaultGraphURI, Map inputNamedGraphs, + IRI resultDefaultGraphURI, Map resultNamedGraphs) + { + return new W3CApprovedSPARQL11UpdateTest(testURI, name, requestFile, defaultGraphURI, + inputNamedGraphs, resultDefaultGraphURI, resultNamedGraphs); + } + + }, true, true, false); + } + + @Override + protected ContextAwareRepository newRepository() + throws Exception + { + SailRepository repo = new SailRepository(new MemoryStore()); + + return new ContextAwareRepository(repo); + } + +} + diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSparqlTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSparqlTest.java new file mode 100644 index 00000000000..631103dab76 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSparqlTest.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.federation; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.parser.sparql.manifest.ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.federation.Federation; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class FederationSparqlTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return ManifestTest.suite(new Factory() { + + public SPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return new FederationSparqlTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality); + } + + public SPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + return new FederationSparqlTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder); + } + }); + } + + public FederationSparqlTest(String testURI, String name, String queryFileURL, String resultFileURL, + Dataset dataSet, boolean laxCardinality) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality); + } + + public FederationSparqlTest(String testURI, String name, String queryFileURL, String resultFileURL, + Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder); + } + + @Override + protected Repository newRepository() { + Federation sail = new Federation(); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + return new DatasetRepository(new SailRepository(sail)); + } +} diff --git a/compliance/sparql/src/test/resources/logback-test.xml b/compliance/sparql/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..86b31ec4b71 --- /dev/null +++ b/compliance/sparql/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + diff --git a/compliance/store/pom.xml b/compliance/store/pom.xml new file mode 100644 index 00000000000..1dfafb51770 --- /dev/null +++ b/compliance/store/pom.xml @@ -0,0 +1,200 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-compliance + 4.1.0-SNAPSHOT + + + rdf4j-store-compliance + war + + RDF4J SAIL and Repository compliance test + Tests for the core SAILs and Repositories + + + + ${project.groupId} + rdf4j-store-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-serql-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-sparql-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-repository-http + ${project.version} + + + + ${project.groupId} + rdf4j-repository-sail + ${project.version} + + + + ${project.groupId} + rdf4j-repository-sparql + ${project.version} + + + + ${project.groupId} + rdf4j-sail-memory + ${project.version} + + + + ${project.groupId} + rdf4j-sail-nativerdf + ${project.version} + + + + ${project.groupId} + rdf4j-sail-federation + ${project.version} + + + + ${project.groupId} + rdf4j-http-server + ${project.version} + war + + + + junit + junit + compile + + + + ch.qos.logback + logback-classic + test + + + + postgresql + postgresql + + + + mysql + mysql-connector-java + + + + ${project.groupId} + rdf4j-http-protocol + ${project.version} + + + + ${project.groupId} + rdf4j-repository-manager + ${project.version} + + + + + + org.eclipse.jetty + jetty-server + 7.0.2.v20100331 + + + + org.eclipse.jetty + jetty-webapp + 7.0.2.v20100331 + + + + org.mortbay.jetty + jetty-jsp-2.1 + 7.0.2.v20100331 + runtime + + + + org.slf4j + jcl-over-slf4j + test + + + org.slf4j + log4j-over-slf4j + test + + + + + + + org.apache.maven.plugins + maven-war-plugin + + ${project.build.directory}/openrdf-sesame + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + 1 + false + -Xmx1024M -XX:MaxPermSize=256M + + **/*Test.java + + + **/DataStorePerfTest.java + **/TestServer.java + + + + + integration-tests + integration-test + + integration-test + + + + verify + verify + + verify + + + + + + + + diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPMemServer.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPMemServer.java new file mode 100644 index 00000000000..b736eaac609 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPMemServer.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.http; + +import java.io.File; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.nio.BlockingChannelConnector; +import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigUtil; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.repository.manager.SystemRepository; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.sail.inferencer.fc.config.ForwardChainingRDFSInferencerConfig; +import org.eclipse.rdf4j.sail.memory.config.MemoryStoreConfig; + +/** + * @author Herko ter Horst + */ +public class HTTPMemServer { + + private static final String HOST = "localhost"; + + private static final int PORT = 18080; + + private static final String TEST_REPO_ID = "Test"; + + private static final String TEST_INFERENCE_REPO_ID = "Test-RDFS"; + + private static final String OPENRDF_CONTEXT = "/openrdf"; + + private static final String SERVER_URL = "http://" + HOST + ":" + PORT + OPENRDF_CONTEXT; + + public static final String REPOSITORY_URL = Protocol.getRepositoryLocation(SERVER_URL, TEST_REPO_ID); + + public static String INFERENCE_REPOSITORY_URL = Protocol.getRepositoryLocation(SERVER_URL, + TEST_INFERENCE_REPO_ID); + + private final Server jetty; + + public HTTPMemServer() { + System.clearProperty("DEBUG"); + + jetty = new Server(); + + Connector conn = new BlockingChannelConnector(); + conn.setHost(HOST); + conn.setPort(PORT); + jetty.addConnector(conn); + + WebAppContext webapp = new WebAppContext(); + // TODO temporarily disabled so the integration test server shows server-side logging. +// webapp.addSystemClass("org.slf4j."); +// webapp.addSystemClass("ch.qos.logback."); + webapp.setContextPath(OPENRDF_CONTEXT); + // warPath configured in pom.xml maven-war-plugin configuration + webapp.setWar("./target/openrdf-sesame"); + jetty.setHandler(webapp); + } + + public void start() + throws Exception + { + File dataDir = new File(System.getProperty("user.dir") + "/target/datadir"); + dataDir.mkdirs(); + System.setProperty("info.aduna.platform.appdata.basedir", dataDir.getAbsolutePath()); + + jetty.start(); + + createTestRepositories(); + } + + public void stop() + throws Exception + { + Repository systemRepo = new HTTPRepository(Protocol.getRepositoryLocation(SERVER_URL, + SystemRepository.ID)); + RepositoryConnection con = systemRepo.getConnection(); + try { + con.clear(); + } + finally { + con.close(); + } + + jetty.stop(); + System.clearProperty("org.mortbay.log.class"); + } + + private void createTestRepositories() + throws RepositoryException, RepositoryConfigException + { + Repository systemRep = new HTTPRepository(Protocol.getRepositoryLocation(SERVER_URL, + SystemRepository.ID)); + + // create a (non-inferencing) memory store + MemoryStoreConfig memStoreConfig = new MemoryStoreConfig(); + SailRepositoryConfig sailRepConfig = new SailRepositoryConfig(memStoreConfig); + RepositoryConfig repConfig = new RepositoryConfig(TEST_REPO_ID, sailRepConfig); + + RepositoryConfigUtil.updateRepositoryConfigs(systemRep, repConfig); + + // create an inferencing memory store + ForwardChainingRDFSInferencerConfig inferMemStoreConfig = new ForwardChainingRDFSInferencerConfig( + new MemoryStoreConfig()); + sailRepConfig = new SailRepositoryConfig(inferMemStoreConfig); + repConfig = new RepositoryConfig(TEST_INFERENCE_REPO_ID, sailRepConfig); + + RepositoryConfigUtil.updateRepositoryConfigs(systemRep, repConfig); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPRepositoryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPRepositoryTest.java new file mode 100644 index 00000000000..8c3928d9cd2 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPRepositoryTest.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.http; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryTest; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +public class HTTPRepositoryTest extends RepositoryTest { + + private static HTTPMemServer server; + + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + } + + @Override + protected Repository createRepository() { + return new HTTPRepository(HTTPMemServer.REPOSITORY_URL); + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlDatasetTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlDatasetTest.java new file mode 100644 index 00000000000..67de32929e6 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlDatasetTest.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.http; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.SparqlDatasetTest; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +public class HTTPSparqlDatasetTest extends SparqlDatasetTest { + + private static HTTPMemServer server; + + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + } + + protected Repository newRepository() { + return new HTTPRepository(HTTPMemServer.REPOSITORY_URL); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlSetBindingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlSetBindingTest.java new file mode 100644 index 00000000000..6567464a556 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlSetBindingTest.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.http; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.SparqlSetBindingTest; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +public class HTTPSparqlSetBindingTest extends SparqlSetBindingTest { + + private static HTTPMemServer server; + + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + } + + protected Repository newRepository() { + return new HTTPRepository(HTTPMemServer.REPOSITORY_URL); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlUpdateTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlUpdateTest.java new file mode 100644 index 00000000000..9d6d40ee0b9 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPSparqlUpdateTest.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.http; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.eclipse.rdf4j.model.vocabulary.FOAF; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.Update; +import org.eclipse.rdf4j.query.parser.sparql.SPARQLUpdateTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +/** + * @author jeen + */ +public class HTTPSparqlUpdateTest extends SPARQLUpdateTest { + + private static HTTPMemServer server; + + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + } + + @Override + protected Repository newRepository() + throws Exception + { + return new HTTPRepository(HTTPMemServer.REPOSITORY_URL); + } + + @Ignore + @Test + @Override + public void testAutoCommitHandling() { + // transaction isolation is not supported for HTTP connections. disabling + // test. + System.err.println("temporarily disabled testAutoCommitHandling() for HTTPRepository. See SES-1652"); + } + + @Test + public void testBindingsInUpdateTransaction() + throws Exception + { + // See issue SES-1889 + logger.debug("executing test testBindingsInUpdateTransaction"); + + StringBuilder update1 = new StringBuilder(); + update1.append(getNamespaceDeclarations()); + update1.append("DELETE { ?x foaf:name ?y } WHERE {?x foaf:name ?y }"); + + try { + assertTrue(con.hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); + assertTrue(con.hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); + + con.begin(); + Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update1.toString()); + operation.setBinding("x", bob); + + + operation.execute(); + + con.commit(); + + // only bob's name should have been deleted (due to the binding) + assertFalse(con.hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); + assertTrue(con.hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); + + } + catch (Exception e) { + if(con.isActive()) { + con.rollback(); + } + } + } + + @Ignore + @Test + @Override + public void testConsecutiveUpdatesInSameTransaction() { + // transaction isolation is not supported for HTTP connections. disabling + // test. + System.err.println("temporarily disabled testConsecutiveUpdatesInSameTransaction() for HTTPRepository. See SES-1652"); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPStoreConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPStoreConnectionTest.java new file mode 100644 index 00000000000..42d66df4b15 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/HTTPStoreConnectionTest.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.http; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.Update; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +public class HTTPStoreConnectionTest extends RepositoryConnectionTest { + + private static HTTPMemServer server; + + public HTTPStoreConnectionTest(IsolationLevel level) { + super(level); + } + + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + } + + @Override + protected Repository createRepository() { + return new HTTPRepository(HTTPMemServer.REPOSITORY_URL); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testOrderByQueriesAreInterruptable() { + System.err.println("temporarily disabled testOrderByQueriesAreInterruptable() for HTTPRepository"); + } + + @Test + public void testUpdateExecution() + throws Exception + { + + IRI foobar = vf.createIRI("foo:bar"); + + String sparql = "INSERT DATA { . } "; + + Update update = testCon.prepareUpdate(QueryLanguage.SPARQL, sparql); + + update.execute(); + + assertTrue(testCon.hasStatement(foobar, foobar, foobar, true)); + + testCon.clear(); + + assertFalse(testCon.hasStatement(foobar, foobar, foobar, true)); + + testCon.begin(); + update.execute(); + testCon.commit(); + + assertTrue(testCon.hasStatement(foobar, foobar, foobar, true)); + + } + + @Test + @Override + public void testAddMalformedLiteralsDefaultConfig() + throws Exception + { + try { + testCon.add( + RepositoryConnectionTest.class.getResourceAsStream(TEST_DIR_PREFIX + "malformed-literals.ttl"), + "", RDFFormat.TURTLE); + } + catch (OpenRDFException e) { + fail("upload of malformed literals should not fail with error in default configuration for HTTPRepository"); + } + } + + @Test + @Override + @Ignore("See SES-1833") + public void testAddMalformedLiteralsStrictConfig() + throws Exception + { + System.err.println("SES-1833: temporarily disabled testAddMalformedLiteralsStrictConfig() for HTTPRepository"); + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/RDFSchemaHTTPRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/RDFSchemaHTTPRepositoryConnectionTest.java new file mode 100644 index 00000000000..d18c28af3c1 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/http/RDFSchemaHTTPRepositoryConnectionTest.java @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.http; + +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.repository.RDFSchemaRepositoryConnectionTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +public class RDFSchemaHTTPRepositoryConnectionTest extends RDFSchemaRepositoryConnectionTest { + + private static HTTPMemServer server; + + public RDFSchemaHTTPRepositoryConnectionTest(IsolationLevel level) { + super(level); + } + + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + } + + @Override + protected Repository createRepository() { + return new HTTPRepository(HTTPMemServer.INFERENCE_REPOSITORY_URL); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testTransactionIsolationForRead() + throws Exception + { + System.err.println("temporarily disabled testTransactionIsolationForRead() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testTransactionIsolationForReadWithDeleteOperation() + throws Exception + { + System.err.println("temporarily disabled testTransactionIsolationForReadWithDeleteOperation() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testTransactionIsolation() + throws Exception + { + System.err.println("temporarily disabled testTransactionIsolation() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testAutoCommit() + throws Exception + { + System.err.println("temporarily disabled testAutoCommit() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testRollback() + throws Exception + { + System.err.println("temporarily disabled testRollback() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testEmptyCommit() + throws Exception + { + System.err.println("temporarily disabled testEmptyCommit() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testEmptyRollback() + throws Exception + { + System.err.println("temporarily disabled testEmptyRollback() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testSizeCommit() + throws Exception + { + System.err.println("temporarily disabled testSizeCommit() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testSizeRollback() + throws Exception + { + System.err.println("temporarily disabled testSizeRollback() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testGetContextIDs() + throws Exception + { + System.err.println("temporarily disabled testGetContextIDs() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testInferencerQueryDuringTransaction() + throws Exception + { + System.err.println("temporarily disabled testInferencerDuringTransaction() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testInferencerTransactionIsolation() + throws Exception + { + System.err.println("temporarily disabled testInferencerTransactionIsolation() for HTTPRepository"); + } + + @Ignore("temporarily disabled for HTTPRepository") + @Test + @Override + public void testOrderByQueriesAreInterruptable() { + System.err.println("temporarily disabled testOrderByQueriesAreInterruptable() for HTTPRepository"); + } + + @Test + @Override + public void testAddMalformedLiteralsDefaultConfig() + throws Exception + { + try { + testCon.add( + RepositoryConnectionTest.class.getResourceAsStream(TEST_DIR_PREFIX + "malformed-literals.ttl"), + "", RDFFormat.TURTLE); + } + catch (OpenRDFException e) { + fail("upload of malformed literals should not fail with error in default configuration for HTTPRepository"); + } + } + + @Test + @Override + @Ignore("See SES-1833") + public void testAddMalformedLiteralsStrictConfig() + throws Exception + { + System.err.println("SES-1833: temporarily disabled testAddMalformedLiteralsStrictConfig() for HTTPRepository"); + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/CustomGraphQueryInferencerMemoryRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/CustomGraphQueryInferencerMemoryRepositoryConnectionTest.java new file mode 100644 index 00000000000..a887ca90629 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/CustomGraphQueryInferencerMemoryRepositoryConnectionTest.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import java.io.IOException; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.common.io.ResourceUtil; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.inferencer.fc.CustomGraphQueryInferencer; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class CustomGraphQueryInferencerMemoryRepositoryConnectionTest extends RepositoryConnectionTest { + + public CustomGraphQueryInferencerMemoryRepositoryConnectionTest(IsolationLevel level) { + super(level); + } + + @Override + protected Repository createRepository() + throws MalformedQueryException, UnsupportedQueryLanguageException, SailException, IOException + { + return new SailRepository(new CustomGraphQueryInferencer(new MemoryStore(), + QueryLanguage.SPARQL, + ResourceUtil.getString("/testcases/custom-query-inferencing/predicate/rule.rq"), + ResourceUtil.getString("/testcases/custom-query-inferencing/predicate/match.rq"))); + } +} \ No newline at end of file diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryCascadeValueExceptionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryCascadeValueExceptionTest.java new file mode 100644 index 00000000000..53125fdb7af --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryCascadeValueExceptionTest.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.CascadeValueExceptionTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemoryCascadeValueExceptionTest extends CascadeValueExceptionTest { + + protected Repository newRepository() { + return new SailRepository(new MemoryStore()); + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryGraphQueryResultTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryGraphQueryResultTest.java new file mode 100644 index 00000000000..631a38ef558 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryGraphQueryResultTest.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.GraphQueryResultTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemoryGraphQueryResultTest extends GraphQueryResultTest { + + protected Repository newRepository() { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryOptimisticIsolationTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryOptimisticIsolationTest.java new file mode 100644 index 00000000000..25d0627e900 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryOptimisticIsolationTest.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.OptimisticIsolationTest; +import org.eclipse.rdf4j.sail.memory.config.MemoryStoreFactory; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +public class MemoryOptimisticIsolationTest extends OptimisticIsolationTest { + + @BeforeClass + public static void setUpClass() + throws Exception + { + setSailFactory(new MemoryStoreFactory()); + } + + @AfterClass + public static void tearDown() + throws Exception + { + setSailFactory(null); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySPARQLQueryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySPARQLQueryTest.java new file mode 100644 index 00000000000..023ef380c4e --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySPARQLQueryTest.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.parser.sparql.manifest.ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemorySPARQLQueryTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return ManifestTest.suite(new Factory() { + + public MemorySPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false); + } + + public MemorySPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + return new MemorySPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder); + } + }); + } + + protected MemorySPARQLQueryTest(String testURI, String name, String queryFileURL, String resultFileURL, + Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder); + } + + protected Repository newRepository() { + return new DatasetRepository(new SailRepository(new MemoryStore())); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySeRQLQueryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySeRQLQueryTest.java new file mode 100644 index 00000000000..bdfb7952fb2 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySeRQLQueryTest.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import java.util.List; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.parser.serql.SeRQLQueryTestCase; +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemorySeRQLQueryTest extends SeRQLQueryTestCase { + + public static Test suite() throws Exception { + return SeRQLQueryTestCase.suite(new Factory() { + public Test createTest(String name, String dataFile, + List graphNames, String queryFile, + String resultFile, String entailment) { + return new MemorySeRQLQueryTest(name, dataFile, graphNames, + queryFile, resultFile, entailment); + } + }); + } + + public MemorySeRQLQueryTest(String name, String dataFile, + List graphNames, String queryFile, String resultFile, + String entailment) { + super(name, dataFile, graphNames, queryFile, resultFile, entailment); + } + + @Override + protected QueryLanguage getQueryLanguage() { + return QueryLanguage.SERQL; + } + + @Override + protected NotifyingSail newSail() { + return new MemoryStore(); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlAggregatesTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlAggregatesTest.java new file mode 100644 index 00000000000..221076e041d --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlAggregatesTest.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.SparqlAggregatesTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemorySparqlAggregatesTest extends SparqlAggregatesTest { + + protected Repository newRepository() { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlDatasetTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlDatasetTest.java new file mode 100644 index 00000000000..7a1ff4c2852 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlDatasetTest.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.SparqlDatasetTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemorySparqlDatasetTest extends SparqlDatasetTest { + + protected Repository newRepository() { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlOrderByTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlOrderByTest.java new file mode 100644 index 00000000000..250c8bfa3a7 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlOrderByTest.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.SparqlOrderByTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemorySparqlOrderByTest extends SparqlOrderByTest { + + protected Repository newRepository() { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlRegexTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlRegexTest.java new file mode 100644 index 00000000000..3e86f8444c4 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlRegexTest.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.SparqlRegexTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemorySparqlRegexTest extends SparqlRegexTest { + + protected Repository newRepository() { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlSetBindingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlSetBindingTest.java new file mode 100644 index 00000000000..bdcfe95ba93 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemorySparqlSetBindingTest.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.SparqlRegexTest; +import org.eclipse.rdf4j.repository.SparqlSetBindingTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemorySparqlSetBindingTest extends SparqlSetBindingTest { + + protected Repository newRepository() { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryStoreConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryStoreConnectionTest.java new file mode 100644 index 00000000000..a686df0fbf2 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryStoreConnectionTest.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemoryStoreConnectionTest extends RepositoryConnectionTest { + + public MemoryStoreConnectionTest(IsolationLevel level) { + super(level); + } + + @Override + protected Repository createRepository() { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryStoreRepositoryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryStoreRepositoryTest.java new file mode 100644 index 00000000000..4e4eb30b525 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryStoreRepositoryTest.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemoryStoreRepositoryTest extends RepositoryTest { + + @Override + protected Repository createRepository() { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryTupleQueryResultTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryTupleQueryResultTest.java new file mode 100644 index 00000000000..ac8804e6ec4 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryTupleQueryResultTest.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.TupleQueryResultTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemoryTupleQueryResultTest extends TupleQueryResultTest { + + protected Repository newRepository() { + return new SailRepository(new MemoryStore()); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/RDFSchemaMemoryRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/RDFSchemaMemoryRepositoryConnectionTest.java new file mode 100644 index 00000000000..d8ff0313ddc --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/RDFSchemaMemoryRepositoryConnectionTest.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.repository.RDFSchemaRepositoryConnectionTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.inferencer.fc.ForwardChainingRDFSInferencer; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class RDFSchemaMemoryRepositoryConnectionTest extends RDFSchemaRepositoryConnectionTest { + + public RDFSchemaMemoryRepositoryConnectionTest(IsolationLevel level) { + super(level); + } + + @Override + protected Repository createRepository() { + return new SailRepository(new ForwardChainingRDFSInferencer(new MemoryStore())); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/CustomGraphQueryInferencerNativeRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/CustomGraphQueryInferencerNativeRepositoryConnectionTest.java new file mode 100644 index 00000000000..2d4dc1f9d64 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/CustomGraphQueryInferencerNativeRepositoryConnectionTest.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.common.io.ResourceUtil; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.inferencer.fc.CustomGraphQueryInferencer; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +public class CustomGraphQueryInferencerNativeRepositoryConnectionTest extends RepositoryConnectionTest { + + private File dataDir; + + public CustomGraphQueryInferencerNativeRepositoryConnectionTest(IsolationLevel level) { + super(level); + } + + @Override + protected Repository createRepository() + throws IOException, MalformedQueryException, UnsupportedQueryLanguageException, SailException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new CustomGraphQueryInferencer(new NativeStore(dataDir, "spoc"), + QueryLanguage.SPARQL, + ResourceUtil.getString("/testcases/custom-query-inferencing/predicate/rule.rq"), + ResourceUtil.getString("/testcases/custom-query-inferencing/predicate/match.rq"))); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/LimitedSizeNativeStoreConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/LimitedSizeNativeStoreConnectionTest.java new file mode 100644 index 00000000000..44257a03de9 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/LimitedSizeNativeStoreConnectionTest.java @@ -0,0 +1,159 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.sail.nativerdf.LimitedSizeNativeStore; +import org.eclipse.rdf4j.sail.nativerdf.LimitedSizeNativeStoreConnection; +import org.junit.Test; + +public class LimitedSizeNativeStoreConnectionTest extends RepositoryConnectionTest { + + private File dataDir; + + public LimitedSizeNativeStoreConnectionTest(IsolationLevel level) { + super(level); + } + + @Override + protected Repository createRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new LimitedSizeNativeStore(dataDir, "spoc")); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } + + @Test + public void testSES715() + throws Exception + { + // load 1000 triples in two different contexts + testCon.begin(); + ValueFactory vf = testCon.getValueFactory(); + IRI context1 = vf.createIRI("http://my.context.1"); + IRI context2 = vf.createIRI("http://my.context.2"); + IRI predicate = vf.createIRI("http://my.predicate"); + IRI object = vf.createIRI("http://my.object"); + + for (int j = 0; j < 1000; j++) { + testCon.add(vf.createIRI("http://my.subject" + j), predicate, object, context1); + testCon.add(vf.createIRI("http://my.subject" + j), predicate, object, context2); + } + assertEquals(1000, Iterations.asList(testCon.getStatements(null, null, null, false, context1)).size()); + assertEquals(1000, Iterations.asList(testCon.getStatements(null, null, null, false, context2)).size()); + + // remove all triples from context 1 + testCon.clear(context1); + assertEquals(0, Iterations.asList(testCon.getStatements(null, null, null, false, context1)).size()); + assertEquals(1000, Iterations.asList(testCon.getStatements(null, null, null, false, context2)).size()); + testCon.commit(); + + // check context content using fresh connection + assertEquals(0, Iterations.asList(testCon2.getStatements(null, null, null, false, context1)).size()); + assertEquals(1000, Iterations.asList(testCon2.getStatements(null, null, null, false, context2)).size()); + + testCon2.close(); + } + + @Test + public void testLimit() + throws Exception + { + ((LimitedSizeNativeStoreConnection)((SailRepositoryConnection)testCon).getSailConnection()).setMaxCollectionsSize(2); + testCon.begin(); + ValueFactory vf = testCon.getValueFactory(); + IRI context1 = vf.createIRI("http://my.context.1"); + IRI predicate = vf.createIRI("http://my.predicate"); + IRI object = vf.createIRI("http://my.object"); + + for (int j = 0; j < 100; j++) { + testCon.add(vf.createIRI("http://my.subject" + j), predicate, object, context1); + } + testCon.commit(); + String queryString = "SELECT DISTINCT ?s WHERE {?s ?p ?o}"; + TupleQuery q = testCon.prepareTupleQuery(QueryLanguage.SPARQL, queryString); + QueryEvaluationException shouldThrow = runQuery(q); + assertNotNull(shouldThrow); + + // There is just one object therefore we should not throw a new exception + queryString = "SELECT DISTINCT ?o WHERE {?s ?p ?o}"; + q = testCon.prepareTupleQuery(QueryLanguage.SPARQL, queryString); + shouldThrow = runQuery(q); + assertNull(shouldThrow); + } + + @Test + public void testOrderAndLimit() + throws Exception + { + ((LimitedSizeNativeStoreConnection)((SailRepositoryConnection)testCon).getSailConnection()).setMaxCollectionsSize(2); + testCon.begin(); + ValueFactory vf = testCon.getValueFactory(); + IRI context1 = vf.createIRI("http://my.context.1"); + IRI predicate = vf.createIRI("http://my.predicate"); + IRI object = vf.createIRI("http://my.object"); + + for (int j = 0; j < 100; j++) { + testCon.add(vf.createIRI("http://my.subject" + j), predicate, object, context1); + } + testCon.commit(); + String queryString = "SELECT DISTINCT ?s WHERE {?s ?p ?o} ORDER BY ?s"; + TupleQuery q = testCon.prepareTupleQuery(QueryLanguage.SPARQL, queryString); + QueryEvaluationException shouldThrow = runQuery(q); + assertNotNull(shouldThrow); + + queryString = "SELECT DISTINCT ?s WHERE {?s ?p ?o} ORDER BY ?s LIMIT 2"; + q = testCon.prepareTupleQuery(QueryLanguage.SPARQL, queryString); + shouldThrow = runQuery(q); + assertNull(shouldThrow); + } + + protected QueryEvaluationException runQuery(TupleQuery q) { + QueryEvaluationException shouldThrow = null; + try { + TupleQueryResult r = q.evaluate(); + assertTrue(r.hasNext()); + while (r.hasNext()) { + assertNotNull(r.next()); + } + } + catch (QueryEvaluationException e) { + shouldThrow = e; + } + return shouldThrow; + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeCascadeValueExceptionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeCascadeValueExceptionTest.java new file mode 100644 index 00000000000..071fb2d0b5f --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeCascadeValueExceptionTest.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.repository.CascadeValueExceptionTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +public class NativeCascadeValueExceptionTest extends CascadeValueExceptionTest { + + private File dataDir; + + @Override + protected Repository newRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new NativeStore(dataDir, "spoc")); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeComplexSPARQLQueryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeComplexSPARQLQueryTest.java new file mode 100644 index 00000000000..00a197f4c71 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeComplexSPARQLQueryTest.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.query.parser.sparql.ComplexSPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +/** + * @author jeen + */ +public class NativeComplexSPARQLQueryTest extends ComplexSPARQLQueryTest { + + File dataDir = null; + + @Override + protected Repository newRepository() + throws Exception + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new NativeStore(dataDir, "spoc")); + + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeGraphQueryResultTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeGraphQueryResultTest.java new file mode 100644 index 00000000000..532eaefcdd1 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeGraphQueryResultTest.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.repository.GraphQueryResultTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +public class NativeGraphQueryResultTest extends GraphQueryResultTest { + + private File dataDir; + + @Override + protected Repository newRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new NativeStore(dataDir, "spoc")); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeOptimisticIsolationTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeOptimisticIsolationTest.java new file mode 100644 index 00000000000..0c81ce7c4f7 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeOptimisticIsolationTest.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import org.eclipse.rdf4j.repository.OptimisticIsolationTest; +import org.eclipse.rdf4j.sail.nativerdf.config.NativeStoreFactory; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +public class NativeOptimisticIsolationTest extends OptimisticIsolationTest { + + @BeforeClass + public static void setUpClass() + throws Exception + { + setSailFactory(new NativeStoreFactory()); + } + + @AfterClass + public static void tearDown() + throws Exception + { + setSailFactory(null); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSPARQLQueryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSPARQLQueryTest.java new file mode 100644 index 00000000000..44896f6a097 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSPARQLQueryTest.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.parser.sparql.manifest.ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +import junit.framework.Test; + +public class NativeSPARQLQueryTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return ManifestTest.suite(new Factory() { + + public NativeSPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, false); + } + + public NativeSPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + return new NativeSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder); + } + }); + } + + private File dataDir; + + protected NativeSPARQLQueryTest(String testURI, String name, String queryFileURL, String resultFileURL, + Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder); + } + + @Override + protected Repository newRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new DatasetRepository(new SailRepository(new NativeStore(dataDir, "spoc"))); + } + + @Override + protected void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSeRQLQueryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSeRQLQueryTest.java new file mode 100644 index 00000000000..340ac6cea64 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSeRQLQueryTest.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.parser.serql.SeRQLQueryTestCase; +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +import junit.framework.Test; + +public class NativeSeRQLQueryTest extends SeRQLQueryTestCase { + + public static Test suite() + throws Exception + { + return SeRQLQueryTestCase.suite(new Factory() { + + public Test createTest(String name, String dataFile, List graphNames, String queryFile, + String resultFile, String entailment) + { + return new NativeSeRQLQueryTest(name, dataFile, graphNames, queryFile, resultFile, entailment); + } + }); + } + + private File dataDir; + + public NativeSeRQLQueryTest(String name, String dataFile, List graphNames, String queryFile, + String resultFile, String entailment) + { + super(name, dataFile, graphNames, queryFile, resultFile, entailment); + } + + @Override + protected QueryLanguage getQueryLanguage() { + return QueryLanguage.SERQL; + } + + @Override + protected NotifyingSail newSail() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new NativeStore(dataDir, "spoc"); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSparqlOrderByTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSparqlOrderByTest.java new file mode 100644 index 00000000000..6d0cc365e29 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSparqlOrderByTest.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.SparqlOrderByTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +public class NativeSparqlOrderByTest extends SparqlOrderByTest { + + private File dataDir; + + @Override + protected Repository newRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new NativeStore(dataDir, "spoc")); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSparqlRegexTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSparqlRegexTest.java new file mode 100644 index 00000000000..7b8d5b3f633 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeSparqlRegexTest.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.SparqlRegexTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +public class NativeSparqlRegexTest extends SparqlRegexTest { + + private File dataDir; + + @Override + protected Repository newRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new NativeStore(dataDir, "spoc")); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeStoreConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeStoreConnectionTest.java new file mode 100644 index 00000000000..7c525ac3f47 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeStoreConnectionTest.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Test; + +public class NativeStoreConnectionTest extends RepositoryConnectionTest { + + private File dataDir; + + public NativeStoreConnectionTest(IsolationLevel level) { + super(level); + } + + @Override + protected Repository createRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new NativeStore(dataDir, "spoc")); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } + + @Test + public void testSES715() + throws Exception + { + // load 1000 triples in two different contexts + testCon.begin(); + ValueFactory vf = testCon.getValueFactory(); + IRI context1 = vf.createIRI("http://my.context.1"); + IRI context2 = vf.createIRI("http://my.context.2"); + IRI predicate = vf.createIRI("http://my.predicate"); + IRI object = vf.createIRI("http://my.object"); + + for (int j = 0; j < 1000; j++) { + testCon.add(vf.createIRI("http://my.subject" + j), predicate, object, context1); + testCon.add(vf.createIRI("http://my.subject" + j), predicate, object, context2); + } + assertEquals(1000, Iterations.asList(testCon.getStatements(null, null, null, false, context1)).size()); + assertEquals(1000, Iterations.asList(testCon.getStatements(null, null, null, false, context2)).size()); + + // remove all triples from context 1 + testCon.clear(context1); + assertEquals(0, Iterations.asList(testCon.getStatements(null, null, null, false, context1)).size()); + assertEquals(1000, Iterations.asList(testCon.getStatements(null, null, null, false, context2)).size()); + testCon.commit(); + + // check context content using fresh connection + assertEquals(0, Iterations.asList(testCon2.getStatements(null, null, null, false, context1)).size()); + assertEquals(1000, Iterations.asList(testCon2.getStatements(null, null, null, false, context2)).size()); + + testCon2.close(); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeStoreRepositoryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeStoreRepositoryTest.java new file mode 100644 index 00000000000..cf33ceda2de --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeStoreRepositoryTest.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +public class NativeStoreRepositoryTest extends RepositoryTest { + + private File dataDir; + + @Override + protected Repository createRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new NativeStore(dataDir, "spoc")); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeTupleQueryResultTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeTupleQueryResultTest.java new file mode 100644 index 00000000000..a04c618410a --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeTupleQueryResultTest.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.TupleQueryResultTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +public class NativeTupleQueryResultTest extends TupleQueryResultTest { + + private File dataDir; + + @Override + protected Repository newRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new NativeStore(dataDir, "spoc")); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/RDFSchemaNativeRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/RDFSchemaNativeRepositoryConnectionTest.java new file mode 100644 index 00000000000..108b30b22a9 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/RDFSchemaNativeRepositoryConnectionTest.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.repository.RDFSchemaRepositoryConnectionTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.inferencer.fc.ForwardChainingRDFSInferencer; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; + +public class RDFSchemaNativeRepositoryConnectionTest extends RDFSchemaRepositoryConnectionTest { + + private File dataDir; + + public RDFSchemaNativeRepositoryConnectionTest(IsolationLevel level) { + super(level); + } + + @Override + protected Repository createRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new ForwardChainingRDFSInferencer(new NativeStore(dataDir, "spoc"))); + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/TestNativeStoreMemoryOverflow.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/TestNativeStoreMemoryOverflow.java new file mode 100644 index 00000000000..64ac7d2b0bb --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/TestNativeStoreMemoryOverflow.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.IsolationLevels; +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * + * @author James Leigh + */ +@RunWith(Parameterized.class) +public class TestNativeStoreMemoryOverflow { + + @Parameters(name="{0}") + public static final IsolationLevel[] parameters() { + return IsolationLevels.values(); + } + + private File dataDir; + + private Repository testRepository; + + private RepositoryConnection testCon; + + private RepositoryConnection testCon2; + + private IsolationLevel level; + + public TestNativeStoreMemoryOverflow(IsolationLevel level) { + this.level = level; + } + + @Before + public void setUp() + throws Exception + { + testRepository = createRepository(); + testRepository.initialize(); + + testCon = testRepository.getConnection(); + testCon.setIsolationLevel(level); + testCon.clear(); + testCon.clearNamespaces(); + + testCon2 = testRepository.getConnection(); + testCon2.setIsolationLevel(level); + } + + private Repository createRepository() + throws IOException + { + dataDir = FileUtil.createTempDir("nativestore"); + return new SailRepository(new NativeStore(dataDir, "spoc")); + } + + @After + public void tearDown() + throws Exception + { + try { + testCon2.close(); + testCon.close(); + testRepository.shutDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } + + @Test + public void test() + throws Exception + { + int size = 10000; // this should really be bigger + // load a lot of triples in two different contexts + testCon.begin(); + final ValueFactory vf = testCon.getValueFactory(); + URI context1 = vf.createURI("http://my.context.1"); + URI context2 = vf.createURI("http://my.context.2"); + final URI predicate = vf.createURI("http://my.predicate"); + final URI object = vf.createURI("http://my.object"); + + testCon.add(new DynamicIteration(size, predicate, object, vf), context1); + testCon.add(new DynamicIteration(size, predicate, object, vf), context2); + + assertEquals(size, Iterations.asList(testCon.getStatements(null, null, null, false, context1)).size()); + assertEquals(size, Iterations.asList(testCon.getStatements(null, null, null, false, context2)).size()); + testCon.commit(); + + assertEquals(size, Iterations.asList(testCon.getStatements(null, null, null, false, context1)).size()); + assertEquals(size, Iterations.asList(testCon.getStatements(null, null, null, false, context2)).size()); + + testCon.close(); + } + + private static final class DynamicIteration implements Iteration { + + private final int size; + + private final URI predicate; + + private final URI object; + + private final ValueFactory vf; + + private int i; + + private DynamicIteration(int size, URI predicate, URI object, ValueFactory vf) { + this.size = size; + this.predicate = predicate; + this.object = object; + this.vf = vf; + } + + @Override + public boolean hasNext() + throws RuntimeException + { + return i < size; + } + + @Override + public Statement next() + throws RuntimeException + { + return vf.createStatement(vf.createURI("http://my.subject" + i++), predicate, object); + } + + @Override + public void remove() + throws RuntimeException + { + throw new UnsupportedOperationException(); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/MySqlSPARQL11QueryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/MySqlSPARQL11QueryTest.java new file mode 100644 index 00000000000..c3260b0f27c --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/MySqlSPARQL11QueryTest.java @@ -0,0 +1,62 @@ +package org.eclipse.rdf4j.repository.sail.rdbms; +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +// SES-1071 disabling rdbms-based tests +//package org.eclipse.rdf4j.repository.sail.rdbms; +// +//import junit.framework.Test; +// +//import org.eclipse.rdf4j.query.Dataset; +//import org.eclipse.rdf4j.query.parser.sparql.SPARQL11ManifestTest; +//import org.eclipse.rdf4j.query.parser.sparql.SPARQLQueryTest; +//import org.eclipse.rdf4j.repository.Repository; +//import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +//import org.eclipse.rdf4j.repository.sail.SailRepository; +//import org.eclipse.rdf4j.sail.rdbms.mysql.MySqlStore; +// +//public class MySqlSPARQL11QueryTest extends SPARQLQueryTest { +// +// public static Test suite() +// throws Exception +// { +// return SPARQL11ManifestTest.suite(new Factory() { +// +// public MySqlSPARQL11QueryTest createSPARQLQueryTest(String testURI, String name, +// String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality) +// { +// return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false); +// } +// +// public MySqlSPARQL11QueryTest createSPARQLQueryTest(String testURI, String name, +// String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder) +// { +// return new MySqlSPARQL11QueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, +// laxCardinality, checkOrder); +// } +// }); +// } +// +// protected MySqlSPARQL11QueryTest(String testURI, String name, String queryFileURL, String resultFileURL, +// Dataset dataSet, boolean laxCardinality) +// { +// this(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false); +// } +// +// protected MySqlSPARQL11QueryTest(String testURI, String name, String queryFileURL, String resultFileURL, +// Dataset dataSet, boolean laxCardinality, boolean checkOrder) +// { +// super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder); +// } +// +// protected Repository newRepository() { +// MySqlStore sail = new MySqlStore("sesame_test"); +// sail.setUser("sesame"); +// sail.setPassword("opensesame"); +// return new DatasetRepository(new SailRepository(sail)); +// } +//} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/MySqlStoreConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/MySqlStoreConnectionTest.java new file mode 100644 index 00000000000..ea25221e2f9 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/MySqlStoreConnectionTest.java @@ -0,0 +1,39 @@ +package org.eclipse.rdf4j.repository.sail.rdbms; +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +// SES-1071 disabling rdbms-based tests +//package org.eclipse.rdf4j.repository.sail.rdbms; +// +//import java.io.IOException; +// +//import org.eclipse.rdf4j.repository.Repository; +//import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +//import org.eclipse.rdf4j.repository.sail.SailRepository; +//import org.eclipse.rdf4j.sail.rdbms.mysql.MySqlStore; +// +//public class MySqlStoreConnectionTest extends RepositoryConnectionTest { +// +// public MySqlStoreConnectionTest(String name) { +// super(name); +// } +// +// @Override +// protected Repository createRepository() +// throws IOException +// { +// MySqlStore sail = new MySqlStore("sesame_test"); +// sail.setUser("sesame"); +// sail.setPassword("opensesame"); +// return new SailRepository(sail); +// } +// +// @Override +// public void testOrderByQueriesAreInterruptable() { +// System.err.println("temporarily disabled testOrderByQueriesAreInterruptable() for RDBMS store"); +// } +//} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/PgSqlSPARQL11QueryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/PgSqlSPARQL11QueryTest.java new file mode 100644 index 00000000000..e284d3822f6 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/PgSqlSPARQL11QueryTest.java @@ -0,0 +1,63 @@ +package org.eclipse.rdf4j.repository.sail.rdbms; +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +// SES-1071 disabling rdbms-based tests +//package org.eclipse.rdf4j.repository.sail.rdbms; +// +//import junit.framework.Test; +// +//import org.eclipse.rdf4j.query.Dataset; +//import org.eclipse.rdf4j.query.parser.sparql.SPARQL11ManifestTest; +//import org.eclipse.rdf4j.query.parser.sparql.SPARQLQueryTest; +//import org.eclipse.rdf4j.repository.Repository; +//import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +//import org.eclipse.rdf4j.repository.sail.SailRepository; +//import org.eclipse.rdf4j.sail.memory.MemoryStore; +//import org.eclipse.rdf4j.sail.rdbms.postgresql.PgSqlStore; +// +//public class PgSqlSPARQL11QueryTest extends SPARQLQueryTest { +// +// public static Test suite() +// throws Exception +// { +// return SPARQL11ManifestTest.suite(new Factory() { +// +// public PgSqlSPARQL11QueryTest createSPARQLQueryTest(String testURI, String name, +// String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality) +// { +// return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false); +// } +// +// public PgSqlSPARQL11QueryTest createSPARQLQueryTest(String testURI, String name, +// String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder) +// { +// return new PgSqlSPARQL11QueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, +// laxCardinality, checkOrder); +// } +// }); +// } +// +// protected PgSqlSPARQL11QueryTest(String testURI, String name, String queryFileURL, String resultFileURL, +// Dataset dataSet, boolean laxCardinality) +// { +// this(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false); +// } +// +// protected PgSqlSPARQL11QueryTest(String testURI, String name, String queryFileURL, String resultFileURL, +// Dataset dataSet, boolean laxCardinality, boolean checkOrder) +// { +// super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder); +// } +// +// protected Repository newRepository() { +// PgSqlStore sail = new PgSqlStore("sesame_test"); +// sail.setUser("sesame"); +// sail.setPassword("opensesame"); +// return new DatasetRepository(new SailRepository(sail)); +// } +//} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/PgSqlStoreConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/PgSqlStoreConnectionTest.java new file mode 100644 index 00000000000..f4f95a74e37 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/rdbms/PgSqlStoreConnectionTest.java @@ -0,0 +1,39 @@ +package org.eclipse.rdf4j.repository.sail.rdbms; +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +// SES-1071 disabling rdbms-based tests +//package org.eclipse.rdf4j.repository.sail.rdbms; +// +//import java.io.IOException; +// +//import org.eclipse.rdf4j.repository.Repository; +//import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +//import org.eclipse.rdf4j.repository.sail.SailRepository; +//import org.eclipse.rdf4j.sail.rdbms.postgresql.PgSqlStore; +// +//public class PgSqlStoreConnectionTest extends RepositoryConnectionTest { +// +// public PgSqlStoreConnectionTest(String name) { +// super(name); +// } +// +// @Override +// protected Repository createRepository() +// throws IOException +// { +// PgSqlStore sail = new PgSqlStore("sesame_test"); +// sail.setUser("sesame"); +// sail.setPassword("opensesame"); +// return new SailRepository(sail); +// } +// +// @Override +// public void testOrderByQueriesAreInterruptable() { +// System.err.println("temporarily disabled testOrderByQueriesAreInterruptable() for RDBMS store"); +// } +//} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLGraphQueryResultTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLGraphQueryResultTest.java new file mode 100644 index 00000000000..1c295d70dfe --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLGraphQueryResultTest.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sparql; + +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.repository.GraphQueryResultTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.http.HTTPMemServer; +import org.eclipse.rdf4j.repository.sparql.SPARQLRepository; +import org.junit.AfterClass; +import org.junit.BeforeClass; + + +/** + * + * @author Jeen Broekstra + */ +public class SPARQLGraphQueryResultTest extends GraphQueryResultTest { + + + private static HTTPMemServer server; + + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + server = null; + } + + @Override + protected Repository newRepository() + throws Exception + { + return new SPARQLRepository(HTTPMemServer.REPOSITORY_URL, + Protocol.getStatementsLocation(HTTPMemServer.REPOSITORY_URL)); + + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLRepositorySparqlUpdateTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLRepositorySparqlUpdateTest.java new file mode 100644 index 00000000000..5d8f10c9b19 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLRepositorySparqlUpdateTest.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sparql; + +import org.eclipse.rdf4j.query.parser.sparql.SPARQLUpdateTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.http.HTTPMemServer; +import org.junit.Ignore; +import org.junit.Test; + +/** + * @author Jeen Broekstra + */ +//public class SPARQLRepositorySparqlUpdateTest extends SPARQLUpdateTest { +// +// private HTTPMemServer server; +// +// @Override +// public void setUp() +// throws Exception +// { +// server = new HTTPMemServer(); +// +// try { +// server.start(); +// super.setUp(); +// } +// catch (Exception e) { +// server.stop(); +// throw e; +// } +// } +// +// @Override +// public void tearDown() +// throws Exception +// { +// super.tearDown(); +// server.stop(); +// } +// +// @Override +// protected Repository newRepository() +// throws Exception +// { +// return new SPARQLRepository(HTTPMemServer.REPOSITORY_URL, HTTPMemServer.REPOSITORY_URL + "/statements"); +// } +// +// @Ignore +// @Test +// @Override +// public void testAutoCommitHandling() +// { +// // transaction isolation is not supported for HTTP connections. disabling test. +// System.err.println("temporarily disabled testAutoCommitHandling() for HTTPRepository"); +// } +//} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLRepositoryTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLRepositoryTest.java new file mode 100644 index 00000000000..7b4862d5f3a --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLRepositoryTest.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sparql; + +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryTest; +import org.eclipse.rdf4j.repository.http.HTTPMemServer; +import org.eclipse.rdf4j.repository.sparql.SPARQLRepository; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * @author Jeen Broekstra + */ +public class SPARQLRepositoryTest extends RepositoryTest { + + private static HTTPMemServer server; + + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + + } + + @Before + @Override + public void setUp() + throws Exception + { + super.setUp(); + // overwrite bnode test values as SPARQL endpoints do not generally work + // well with bnodes + bob = testRepository.getValueFactory().createIRI("urn:x-local:bob"); + alice = testRepository.getValueFactory().createIRI("urn:x-local:alice"); + alexander = testRepository.getValueFactory().createIRI("urn:x-local:alexander"); + + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + server = null; + } + + @Override + protected Repository createRepository() + throws Exception + { + return new SPARQLRepository(HTTPMemServer.REPOSITORY_URL, + Protocol.getStatementsLocation(HTTPMemServer.REPOSITORY_URL)); + + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLServiceEvaluationTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLServiceEvaluationTest.java new file mode 100644 index 00000000000..674473db267 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLServiceEvaluationTest.java @@ -0,0 +1,203 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sparql; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FOAF; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.http.HTTPMemServer; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Test suite for evaluation of SPARQL queries involving SERVICE clauses. The + * test suite starts up an embedded Jetty server running Sesame, which functions + * as the SPARQL endpoint to test against. + * + * @author Jeen Broekstra + */ +public class SPARQLServiceEvaluationTest { + + static final Logger logger = LoggerFactory.getLogger(SPARQLServiceEvaluationTest.class); + + private static HTTPMemServer server; + + private HTTPRepository remoteRepository; + + private SailRepository localRepository; + + private ValueFactory f; + + private IRI bob; + + private IRI alice; + + private IRI william; + + protected static final String EX_NS = "http://example.org/"; + + /** + * @throws java.lang.Exception + */ + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + } + + @Before + public void setUp() + throws Exception + { + remoteRepository = new HTTPRepository(HTTPMemServer.REPOSITORY_URL); + remoteRepository.initialize(); + loadDataSet(remoteRepository, "/testdata-query/graph1.ttl"); + loadDataSet(remoteRepository, "/testdata-query/graph2.ttl"); + + localRepository = new SailRepository(new MemoryStore()); + localRepository.initialize(); + + loadDataSet(localRepository, "/testdata-query/defaultgraph.ttl"); + + f = localRepository.getValueFactory(); + + bob = f.createIRI(EX_NS, "bob"); + alice = f.createIRI(EX_NS, "alice"); + william = f.createIRI(EX_NS, "william"); + } + + protected void loadDataSet(Repository rep, String datasetFile) + throws RDFParseException, RepositoryException, IOException + { + logger.debug("loading dataset..."); + InputStream dataset = SPARQLServiceEvaluationTest.class.getResourceAsStream(datasetFile); + + RepositoryConnection con = rep.getConnection(); + try { + con.add(dataset, "", + Rio.getParserFormatForFileName(datasetFile).orElseThrow(Rio.unsupportedFormat(datasetFile))); + } + finally { + dataset.close(); + con.close(); + } + logger.debug("dataset loaded."); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + localRepository.shutDown(); + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + server = null; + } + + @Test + public void testSimpleServiceQuery() + throws RepositoryException + { + StringBuilder qb = new StringBuilder(); + qb.append(" SELECT * \n"); + qb.append(" WHERE { \n"); + qb.append(" SERVICE <" + HTTPMemServer.REPOSITORY_URL + "> { \n"); + qb.append(" ?X <" + FOAF.NAME + "> ?Y \n "); + qb.append(" } \n "); + qb.append(" ?X a <" + FOAF.PERSON + "> . \n"); + qb.append(" } \n"); + + RepositoryConnection conn = localRepository.getConnection(); + try { + TupleQuery tq = conn.prepareTupleQuery(QueryLanguage.SPARQL, qb.toString()); + + TupleQueryResult tqr = tq.evaluate(); + + assertNotNull(tqr); + assertTrue(tqr.hasNext()); + + int count = 0; + while (tqr.hasNext()) { + BindingSet bs = tqr.next(); + count++; + + Value x = bs.getValue("X"); + Value y = bs.getValue("Y"); + + assertFalse(william.equals(x)); + + assertTrue(bob.equals(x) || alice.equals(x)); + if (bob.equals(x)) { + f.createLiteral("Bob").equals(y); + } + else if (alice.equals(x)) { + f.createLiteral("Alice").equals(y); + } + } + + assertEquals(2, count); + + } + catch (MalformedQueryException e) { + fail(e.getMessage()); + } + catch (QueryEvaluationException e) { + fail(e.getMessage()); + } + finally { + conn.close(); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLStoreConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLStoreConnectionTest.java new file mode 100644 index 00000000000..3b59209917d --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sparql/SPARQLStoreConnectionTest.java @@ -0,0 +1,644 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sparql; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.List; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.GraphQuery; +import org.eclipse.rdf4j.query.GraphQueryResult; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.Update; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +import org.eclipse.rdf4j.repository.http.HTTPMemServer; +import org.eclipse.rdf4j.repository.sparql.SPARQLConnection; +import org.eclipse.rdf4j.repository.sparql.SPARQLRepository; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +public class SPARQLStoreConnectionTest extends RepositoryConnectionTest { + + private static HTTPMemServer server; + + public SPARQLStoreConnectionTest(IsolationLevel level) { + super(level); + } + + @BeforeClass + public static void startServer() + throws Exception + { + server = new HTTPMemServer(); + try { + server.start(); + } + catch (Exception e) { + server.stop(); + server = null; + throw e; + } + + } + + @AfterClass + public static void stopServer() + throws Exception + { + server.stop(); + server = null; + } + + @Before + @Override + public void setUp() + throws Exception + { + super.setUp(); + // overwrite bnode test values as SPARQL endpoints do not generally work + // well with bnodes + bob = testRepository.getValueFactory().createIRI("urn:x-local:bob"); + alice = testRepository.getValueFactory().createIRI("urn:x-local:alice"); + alexander = testRepository.getValueFactory().createIRI("urn:x-local:alexander"); + } + + @Override + protected Repository createRepository() { + return new SPARQLRepository(HTTPMemServer.REPOSITORY_URL, + Protocol.getStatementsLocation(HTTPMemServer.REPOSITORY_URL)); + } + + @Override + @Ignore + public void testDuplicateFilter() throws Exception { + System.err.println("temporarily disabled testDuplicateFilter() for SPARQLRepository"); + } + + @Override + @Ignore + public void testAddDelete() + throws OpenRDFException + { + System.err.println("temporarily disabled testAddDelete() for SPARQLRepository"); + } + + @Override + @Ignore + public void testAddRemoveInsert() + throws OpenRDFException + { + System.err.println("temporarily disabled testAddRemoveInsert() for SPARQLRepository"); + } + + @Override + @Ignore + public void testSizeRollback() + throws Exception + { + System.err.println("temporarily disabled testSizeRollback() for SPARQLRepository"); + } + + @Test + @Ignore + @Override + public void testURISerialization() + throws Exception + { + System.err.println("temporarily disabled testURISerialization() for SPARQLRepository"); + } + + @Test + @Ignore + @Override + public void testStatementSerialization() + throws Exception + { + System.err.println("temporarily disabled testStatementSerialization() for SPARQLRepository"); + } + + @Override + @Ignore + public void testAutoCommit() + throws Exception + { + System.err.println("temporarily disabled testAutoCommit() for SPARQLRepository"); + } + + @Override + @Ignore + public void testRollback() + throws Exception + { + System.err.println("temporarily disabled testRollback() for SPARQLRepository"); + } + + @Override + @Ignore + public void testEmptyRollback() + throws Exception + { + System.err.println("temporarily disabled testEmptyRollback() for SPARQLRepository"); + } + + @Override + @Ignore + public void testEmptyCommit() + throws Exception + { + System.err.println("temporarily disabled testEmptyCommit() for SPARQLRepository"); + } + + @Override + @Ignore + public void testPrepareSeRQLQuery() + throws Exception + { + System.err.println("disabled testPrepareSeRQLQuery() for SPARQLRepository"); + } + + @Override + @Ignore + public void testLiteralSerialization() + throws Exception + { + System.err.println("temporarily disabled testLiteralSerialization() for SPARQLRepository"); + } + + @Override + @Ignore + public void testSizeCommit() + throws Exception + { + System.err.println("temporarily disabled testSizeCommit() for SPARQLRepository"); + } + + @Override + @Ignore + public void testGetStatementsInMultipleContexts() + throws Exception + { + System.err.println("temporarily disabled testGetStatementsInMultipleContexts() for SPARQLRepository: implementation of statement context using SPARQL not yet complete"); + // TODO see SES-1776 + } + + @Test + public void testGetStatementsContextHandling() + throws Exception + { + // enable quad mode + enableQuadModeOnConnection((SPARQLConnection)testCon); + + testCon.clear(); + + testCon.begin(); + testCon.add(alice, name, nameAlice, context1); + testCon.add(bob, name, nameBob); + testCon.commit(); + + List res; + + // test 1: alice statement should have context 1 + res = Iterations.asList(testCon.getStatements(alice, null, null, false)); + Assert.assertEquals(1, res.size()); + Assert.assertEquals(context1, res.iterator().next().getContext()); + + // test 2: bob statement should have default named graph + res = Iterations.asList(testCon.getStatements(bob, null, null, false)); + Assert.assertEquals(1, res.size()); + Assert.assertEquals(null, res.iterator().next().getContext()); + + // test 3: bound statement should fetch context + res = Iterations.asList(testCon.getStatements(alice, name, nameAlice, false)); + Assert.assertEquals(1, res.size()); + Assert.assertEquals(context1, res.iterator().next().getContext()); + + } + + /** + * Enable the quadMode on the given connection. This is done + * via reflection here as the test setup already creates the + * repository and connection and we do not have a chance to + * set the mode easily inside the test (as quadMode is an + * immutable field of the connection). + * + * Note: this is only done such that we can reuse the test + * infrastructure of the base class. + */ + private void enableQuadModeOnConnection(SPARQLConnection con) + throws Exception + { + Field quadModeField = SPARQLConnection.class.getDeclaredField("quadMode"); + quadModeField.setAccessible(true); + + // remove final modifier from field + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(quadModeField, quadModeField.getModifiers() & ~Modifier.FINAL); + + quadModeField.set(con, true); + } + + @Override + @Ignore + public void testGetStatementsInSingleContext() + throws Exception + { + System.err.println("temporarily disabled testGetStatementsInSingleContext() for SPARQLRepository: implementation of statement context using SPARQL not yet complete"); + // TODO see SES-1776 + } + + @Ignore + @Override + public void testOrderByQueriesAreInterruptable() + throws Exception + { + System.err.println("temporarily disabled testOrderByQueriesAreInterruptable() for SPARQLRepository"); + } + + @Test + @Override + @Ignore("can not execute test because required data add results in illegal SPARQL syntax") + public void testGetStatementsMalformedLanguageLiteral() + throws Exception + { + System.err.println("temporarily disabled testGetStatementsMalformedLanguageLiteral() for SPARQLRepository"); + } + + @Override + public void testPreparedTupleQuery() + throws Exception + { + testCon.add(alice, name, nameAlice, context2); + testCon.add(alice, mbox, mboxAlice, context2); + testCon.add(context2, publisher, nameAlice); + + testCon.add(bob, name, nameBob, context1); + testCon.add(bob, mbox, mboxBob, context1); + testCon.add(context1, publisher, nameBob); + + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append(" PREFIX foaf: <" + FOAF_NS + "> "); + queryBuilder.append(" SELECT ?name ?mbox"); + queryBuilder.append(" WHERE { [] foaf:name ?name;"); + queryBuilder.append(" foaf:mbox ?mbox. }"); + + TupleQuery query = testCon.prepareTupleQuery(QueryLanguage.SPARQL, queryBuilder.toString()); + query.setBinding("name", nameBob); + + TupleQueryResult result = query.evaluate(); + + try { + assertTrue(result != null); + assertTrue(result.hasNext()); + + while (result.hasNext()) { + BindingSet solution = result.next(); + assertTrue(solution.hasBinding("name")); + assertTrue(solution.hasBinding("mbox")); + + Value nameResult = solution.getValue("name"); + Value mboxResult = solution.getValue("mbox"); + + assertEquals("unexpected value for name: " + nameResult, nameBob, nameResult); + assertEquals("unexpected value for mbox: " + mboxResult, mboxBob, mboxResult); + } + } + finally { + result.close(); + } + } + + @Override + @Ignore + public void testGetNamespaces() + throws Exception + { + System.err.println("disabled testGetNamespaces() as namespace retrieval is not supported by SPARQL"); + } + + @Override + @Ignore + public void testGetNamespace() + throws Exception + { + System.err.println("disabled testGetNamespace() as namespace retrieval is not supported by SPARQL"); + } + + @Ignore("temporarily disabled for SPARQLRepository") + @Test + @Override + public void testTransactionIsolationForRead() + throws Exception + { + System.err.println("temporarily disabled testTransactionIsolationForRead() for SPARQLRepository"); + } + + @Ignore("temporarily disabled for SPARQLRepository") + @Test + @Override + public void testTransactionIsolationForReadWithDeleteOperation() + throws Exception + { + System.err.println("temporarily disabled testTransactionIsolationForReadWithDeleteOperation() for SPARQLRepository"); + } + + @Override + @Ignore + public void testTransactionIsolation() + throws Exception + { + System.err.println("temporarily disabled testTransactionIsolation() for SPARQLRepository"); + } + + @Override + public void testPreparedTupleQuery2() + throws Exception + { + testCon.add(alice, name, nameAlice, context2); + testCon.add(alice, mbox, mboxAlice, context2); + testCon.add(context2, publisher, nameAlice); + + testCon.add(bob, name, nameBob, context1); + testCon.add(bob, mbox, mboxBob, context1); + testCon.add(context1, publisher, nameBob); + + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append(" PREFIX foaf: <" + FOAF_NS + ">"); + queryBuilder.append(" SELECT ?name ?mbox"); + queryBuilder.append(" WHERE {?p foaf:name ?name ;"); + queryBuilder.append(" foaf:mbox ?mbox ."); + queryBuilder.append(" FILTER (?p = ?VAR) } "); + + TupleQuery query = testCon.prepareTupleQuery(QueryLanguage.SPARQL, queryBuilder.toString()); + query.setBinding("VAR", bob); + + TupleQueryResult result = query.evaluate(); + + try { + assertTrue(result != null); + assertTrue(result.hasNext()); + + while (result.hasNext()) { + BindingSet solution = result.next(); + assertTrue(solution.hasBinding("name")); + assertTrue(solution.hasBinding("mbox")); + + Value nameResult = solution.getValue("name"); + Value mboxResult = solution.getValue("mbox"); + + assertEquals("unexpected value for name: " + nameResult, nameBob, nameResult); + assertEquals("unexpected value for mbox: " + mboxResult, mboxBob, mboxResult); + } + } + finally { + result.close(); + } + } + + @Override + public void testPreparedTupleQueryUnicode() + throws Exception + { + testCon.add(alexander, name, Александър); + + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append(" PREFIX foaf: <" + FOAF_NS + "> "); + queryBuilder.append(" SELECT ?person"); + queryBuilder.append(" WHERE {?person foaf:name ?name . }"); + + TupleQuery query = testCon.prepareTupleQuery(QueryLanguage.SPARQL, queryBuilder.toString()); + query.setBinding("name", Александър); + + TupleQueryResult result = query.evaluate(); + + try { + assertNotNull(result); + assertTrue(result.hasNext()); + + while (result.hasNext()) { + BindingSet solution = result.next(); + assertTrue(solution.hasBinding("person")); + assertEquals(alexander, solution.getValue("person")); + } + } + finally { + result.close(); + } + } + + @Override + public void testSimpleGraphQuery() + throws Exception + { + testCon.add(alice, name, nameAlice, context2); + testCon.add(alice, mbox, mboxAlice, context2); + testCon.add(context2, publisher, nameAlice); + + testCon.add(bob, name, nameBob, context1); + testCon.add(bob, mbox, mboxBob, context1); + testCon.add(context1, publisher, nameBob); + + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append(" PREFIX foaf: <" + FOAF_NS + ">"); + queryBuilder.append(" CONSTRUCT "); + queryBuilder.append(" WHERE { [] foaf:name ?name; "); + queryBuilder.append(" foaf:mbox ?mbox. }"); + + GraphQueryResult result = testCon.prepareGraphQuery(QueryLanguage.SPARQL, queryBuilder.toString()).evaluate(); + + try { + assertTrue(result != null); + assertTrue(result.hasNext()); + + while (result.hasNext()) { + Statement st = result.next(); + if (name.equals(st.getPredicate())) { + assertTrue(nameAlice.equals(st.getObject()) || nameBob.equals(st.getObject())); + } + else { + assertTrue(mbox.equals(st.getPredicate())); + assertTrue(mboxAlice.equals(st.getObject()) || mboxBob.equals(st.getObject())); + } + } + } + finally { + result.close(); + } + } + + @Override + public void testPreparedGraphQuery() + throws Exception + { + testCon.add(alice, name, nameAlice, context2); + testCon.add(alice, mbox, mboxAlice, context2); + testCon.add(context2, publisher, nameAlice); + + testCon.add(bob, name, nameBob, context1); + testCon.add(bob, mbox, mboxBob, context1); + testCon.add(context1, publisher, nameBob); + + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append(" PREFIX foaf: <" + FOAF_NS + "> "); + queryBuilder.append(" CONSTRUCT "); + queryBuilder.append(" WHERE { [] foaf:name ?name ;"); + queryBuilder.append(" foaf:mbox ?mbox . "); + queryBuilder.append(" } "); + + GraphQuery query = testCon.prepareGraphQuery(QueryLanguage.SPARQL, queryBuilder.toString()); + query.setBinding("name", nameBob); + + GraphQueryResult result = query.evaluate(); + + try { + assertTrue(result != null); + assertTrue(result.hasNext()); + + while (result.hasNext()) { + Statement st = result.next(); + assertTrue(name.equals(st.getPredicate()) || mbox.equals(st.getPredicate())); + if (name.equals(st.getPredicate())) { + assertTrue("unexpected value for name: " + st.getObject(), nameBob.equals(st.getObject())); + } + else { + assertTrue(mbox.equals(st.getPredicate())); + assertTrue("unexpected value for mbox: " + st.getObject(), mboxBob.equals(st.getObject())); + } + + } + } + finally { + result.close(); + } + } + + @Override + public void testSimpleTupleQuery() + throws Exception + { + testCon.add(alice, name, nameAlice, context2); + testCon.add(alice, mbox, mboxAlice, context2); + testCon.add(context2, publisher, nameAlice); + + testCon.add(bob, name, nameBob, context1); + testCon.add(bob, mbox, mboxBob, context1); + testCon.add(context1, publisher, nameBob); + + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append(" PREFIX foaf: <" + FOAF_NS + "> "); + queryBuilder.append(" SELECT ?name ?mbox"); + queryBuilder.append(" WHERE { [] foaf:name ?name ;"); + queryBuilder.append(" foaf:mbox ?mbox . "); + queryBuilder.append(" } "); + TupleQueryResult result = testCon.prepareTupleQuery(QueryLanguage.SPARQL, queryBuilder.toString()).evaluate(); + + try { + assertTrue(result != null); + assertTrue(result.hasNext()); + + while (result.hasNext()) { + BindingSet solution = result.next(); + assertTrue(solution.hasBinding("name")); + assertTrue(solution.hasBinding("mbox")); + + Value nameResult = solution.getValue("name"); + Value mboxResult = solution.getValue("mbox"); + + assertTrue((nameAlice.equals(nameResult) || nameBob.equals(nameResult))); + assertTrue((mboxAlice.equals(mboxResult) || mboxBob.equals(mboxResult))); + } + } + finally { + result.close(); + } + } + + @Override + public void testSimpleTupleQueryUnicode() + throws Exception + { + testCon.add(alexander, name, Александър); + + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append(" PREFIX foaf: <" + FOAF_NS + ">"); + queryBuilder.append(" SELECT ?person"); + queryBuilder.append(" WHERE { ?person foaf:name \"").append(Александър.getLabel()).append("\" . } "); + + TupleQueryResult result = testCon.prepareTupleQuery(QueryLanguage.SPARQL, queryBuilder.toString()).evaluate(); + + try { + assertNotNull(result); + assertTrue(result.hasNext()); + + while (result.hasNext()) { + BindingSet solution = result.next(); + assertTrue(solution.hasBinding("person")); + assertEquals(alexander, solution.getValue("person")); + } + } + finally { + result.close(); + } + } + + @Override + @Ignore + public void testBNodeSerialization() + throws Exception + { + System.err.println("temporarily disabled testBNodeSerialization() for SPARQLRepository"); + } + + @Test + public void testUpdateExecution() + throws Exception + { + + IRI foobar = vf.createIRI("foo:bar"); + + String sparql = "INSERT DATA { . } "; + + Update update = testCon.prepareUpdate(QueryLanguage.SPARQL, sparql); + + update.execute(); + + assertTrue(testCon.hasStatement(foobar, foobar, foobar, true)); + + testCon.clear(); + + assertFalse(testCon.hasStatement(foobar, foobar, foobar, true)); + + testCon.begin(); + update.execute(); + testCon.commit(); + + assertTrue(testCon.hasStatement(foobar, foobar, foobar, true)); + + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/federation/FederationConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/federation/FederationConnectionTest.java new file mode 100644 index 00000000000..a7ddd3cafd5 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/federation/FederationConnectionTest.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.federation; + +import java.io.IOException; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.IsolationLevels; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnectionTest; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.federation.Federation; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class FederationConnectionTest extends RepositoryConnectionTest { + + @Parameters(name="{0}") + public static final IsolationLevel[] parametersNONE() { + // isolation is not supported + return new IsolationLevel[] { IsolationLevels.NONE }; + } + + public FederationConnectionTest(IsolationLevel level) { + super(level); + } + + @Override + protected Repository createRepository() + throws IOException + { + Federation sail = new Federation(); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + return new SailRepository(sail); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/federation/FederationTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/federation/FederationTest.java new file mode 100644 index 00000000000..09fdbbc2fdf --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/federation/FederationTest.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.federation; + +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.RDFStoreTest; +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.federation.Federation; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +/** + * An extension of RDFStoreTest for testing the class {@link MulgaraStore}. + */ +public class FederationTest extends RDFStoreTest { + + /*--------------* + * Constructors * + *--------------*/ + public FederationTest() { + super(); + } + + /*---------* + * Methods * + *---------*/ + + @Override + protected Sail createSail() + throws SailException + { + Federation sail = new Federation(); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + sail.initialize(); + return sail; + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionWrapperTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionWrapperTest.java new file mode 100644 index 00000000000..0dbfdb5677f --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionWrapperTest.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.helpers; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; + +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.sail.SailConnectionListener; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.helpers.NotifyingSailConnectionWrapper; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Some general tests for {@link NogifyingSailConnectionWrapper} expected + * behaviour. + * + * @author Dale Visser + */ +public class NotifyingSailConnectionWrapperTest { + + /** + * @author Dale Visser + */ + private final class TestListener implements SailConnectionListener { + + int testCounter = 0; + + @Override + public void statementAdded(Statement st) { + testCounter++; + } + + @Override + public void statementRemoved(Statement st) { + testCounter--; + } + + public int getCount() { + return testCounter; + } + } + + NotifyingSailConnectionWrapper wrapper; + + ValueFactory factory; + + TestListener listener = new TestListener(); + + MemoryStore memoryStore = new MemoryStore(); + + @Before + public void before() + throws SailException + { + memoryStore.initialize(); + wrapper = new NotifyingSailConnectionWrapper(memoryStore.getConnection()); + factory = memoryStore.getValueFactory(); + } + + @After + public void after() + throws SailException + { + wrapper.close(); + memoryStore.shutDown(); + } + + /** + * Regression test for SES-1934. + * + * @throws SailException + */ + @Test + public void testAddThenRemoveListener() + throws SailException + { + wrapper.addConnectionListener(listener); + addStatement("a"); + assertThat(listener.getCount(), is(equalTo(1))); + removeStatement("a"); + assertThat(listener.getCount(), is(equalTo(0))); + wrapper.removeConnectionListener(listener); + addStatement("b"); + assertThat(listener.getCount(), is(equalTo(0))); + } + + private void removeStatement(String objectValue) + throws SailException + { + wrapper.begin(); + wrapper.removeStatements(null, factory.createIRI("urn:pred"), factory.createLiteral(objectValue)); + wrapper.commit(); + } + + private void addStatement(String objectValue) + throws SailException + { + wrapper.begin(); + wrapper.addStatement(factory.createBNode(), factory.createIRI("urn:pred"), + factory.createLiteral(objectValue)); + wrapper.commit(); + } +} \ No newline at end of file diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemCustomInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemCustomInferencingTest.java new file mode 100644 index 00000000000..583e11afc3c --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemCustomInferencingTest.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.memory; + +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.sail.CustomGraphQueryInferencerTest; +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemCustomInferencingTest extends CustomGraphQueryInferencerTest { + + public MemCustomInferencingTest(String resourceFolder, Expectation testData, QueryLanguage language) { + super(resourceFolder, testData, language); + } + + @Override + protected NotifyingSail newSail() { + NotifyingSail store = new MemoryStore(); + return store; + } +} \ No newline at end of file diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemInferencingTest.java new file mode 100644 index 00000000000..c18daba3823 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemInferencingTest.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.memory; + +import org.eclipse.rdf4j.sail.InferencingTest; +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.inferencer.fc.ForwardChainingRDFSInferencer; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class MemInferencingTest extends InferencingTest { + + @Override + protected Sail createSail() { + Sail sailStack = new ForwardChainingRDFSInferencer(new MemoryStore()); + return sailStack; + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreConcurrencyTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreConcurrencyTest.java new file mode 100644 index 00000000000..3f332e94b02 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreConcurrencyTest.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.memory; + +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.SailConcurrencyTest; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +/** + * An extension of {@link SailConcurrencyTest} for testing the class + * {@link MemoryStore}. + */ +public class MemoryStoreConcurrencyTest extends SailConcurrencyTest { + + /*---------* + * Methods * + *---------*/ + + @Override + protected Sail createSail() + throws SailException + { + return new MemoryStore(); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreIsolationLevelTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreIsolationLevelTest.java new file mode 100644 index 00000000000..d9cd8c9a15d --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreIsolationLevelTest.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.memory; + +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.SailIsolationLevelTest; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +/** + * An extension of {@link SailIsolationLevelTest} for testing the class + * {@link MemoryStore}. + */ +public class MemoryStoreIsolationLevelTest extends SailIsolationLevelTest { + + /*---------* + * Methods * + *---------*/ + + @Override + protected Sail createSail() + throws SailException + { + return new MemoryStore(); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreTest.java new file mode 100644 index 00000000000..e55350d9214 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreTest.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.memory; + +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.RDFNotifyingStoreTest; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + + +/** + * An extension of RDFStoreTest for testing the class + * org.eclipse.rdf4j.sesame.sail.memory.MemoryStore. + */ +public class MemoryStoreTest extends RDFNotifyingStoreTest { + + /*---------* + * Methods * + *---------*/ + + @Override + protected NotifyingSail createSail() + throws SailException + { + NotifyingSail sail = new MemoryStore(); + sail.initialize(); + return sail; + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/PersistentMemoryStoreTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/PersistentMemoryStoreTest.java new file mode 100644 index 00000000000..f99fcbca48e --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/PersistentMemoryStoreTest.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.sail.memory; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.RDFNotifyingStoreTest; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +/** + * An extension of RDFStoreTest for testing the class + * org.eclipse.rdf4j.sesame.sail.memory.MemoryStore. + */ +public class PersistentMemoryStoreTest extends RDFNotifyingStoreTest { + + private volatile File dataDir; + + @Override + protected NotifyingSail createSail() + throws SailException + { + try { + dataDir = FileUtil.createTempDir(PersistentMemoryStoreTest.class.getSimpleName()); + NotifyingSail sail = new MemoryStore(dataDir); + sail.initialize(); + return sail; + } + catch (IOException e) { + throw new SailException(e); + } + } + + @Override + public void tearDown() + throws Exception + { + try { + super.tearDown(); + } + finally { + FileUtil.deleteDir(dataDir); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/StoreSerializationTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/StoreSerializationTest.java new file mode 100644 index 00000000000..e63c10af784 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/StoreSerializationTest.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.memory; + +import java.io.File; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.eclipse.rdf4j.query.parser.ParsedTupleQuery; +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.eclipse.rdf4j.sail.SailConnection; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +import junit.framework.TestCase; + +public class StoreSerializationTest extends TestCase { + + /*-----------* + * Variables * + *-----------*/ + + private File dataDir; + + /*---------* + * Methods * + *---------*/ + + @Override + protected void setUp() + throws Exception + { + super.setUp(); + dataDir = FileUtil.createTempDir("memorystore"); + } + + @Override + protected void tearDown() + throws Exception + { + super.tearDown(); + FileUtil.deleteDir(dataDir); + } + + public void testShortLiterals() + throws Exception + { + MemoryStore store = new MemoryStore(dataDir); + store.initialize(); + + ValueFactory factory = store.getValueFactory(); + IRI foo = factory.createIRI("http://www.foo.example/foo"); + + StringBuilder sb = new StringBuilder(4); + for (int i = 0; i < 4; i++) { + sb.append('a'); + } + + Literal longLiteral = factory.createLiteral(sb.toString()); + + SailConnection con = store.getConnection(); + con.begin(); + con.addStatement(foo, RDF.VALUE, longLiteral); + con.commit(); + + con.close(); + store.shutDown(); + + store = new MemoryStore(dataDir); + store.initialize(); + + con = store.getConnection(); + + CloseableIteration iter = con.getStatements(foo, RDF.VALUE, null, + false); + assertTrue(iter.hasNext()); + iter.next(); + iter.close(); + + con.close(); + store.shutDown(); + } + + public void testSerialization() + throws Exception + { + MemoryStore store = new MemoryStore(dataDir); + store.initialize(); + + ValueFactory factory = store.getValueFactory(); + IRI foo = factory.createIRI("http://www.foo.example/foo"); + IRI bar = factory.createIRI("http://www.foo.example/bar"); + + SailConnection con = store.getConnection(); + con.begin(); + con.addStatement(foo, RDF.TYPE, bar); + con.commit(); + + ParsedTupleQuery query = QueryParserUtil.parseTupleQuery(QueryLanguage.SERQL, + "SELECT X, P, Y FROM {X} P {Y}", null); + TupleExpr tupleExpr = query.getTupleExpr(); + + CloseableIteration iter = con.evaluate(tupleExpr, null, + EmptyBindingSet.getInstance(), false); + + BindingSet bindingSet = iter.next(); + + assertEquals(bindingSet.getValue("X"), foo); + assertEquals(bindingSet.getValue("P"), RDF.TYPE); + assertEquals(bindingSet.getValue("Y"), bar); + iter.close(); + con.close(); + + store.shutDown(); + + store = new MemoryStore(dataDir); + store.initialize(); + + factory = store.getValueFactory(); + foo = factory.createIRI("http://www.foo.example/foo"); + bar = factory.createIRI("http://www.foo.example/bar"); + + con = store.getConnection(); + + iter = con.evaluate(tupleExpr, null, EmptyBindingSet.getInstance(), false); + + bindingSet = iter.next(); + + assertEquals(bindingSet.getValue("X"), foo); + assertEquals(bindingSet.getValue("P"), RDF.TYPE); + assertEquals(bindingSet.getValue("Y"), bar); + + iter.close(); + con.begin(); + con.addStatement(bar, RDF.TYPE, foo); + con.commit(); + con.close(); + + store.shutDown(); + } + + public void testLongLiterals() + throws Exception + { + MemoryStore store = new MemoryStore(dataDir); + store.initialize(); + + ValueFactory factory = store.getValueFactory(); + IRI foo = factory.createIRI("http://www.foo.example/foo"); + + StringBuilder sb = new StringBuilder(66000); + for (int i = 0; i < 66000; i++) { + sb.append('a'); + } + + Literal longLiteral = factory.createLiteral(sb.toString()); + + SailConnection con = store.getConnection(); + con.begin(); + con.addStatement(foo, RDF.VALUE, longLiteral); + con.commit(); + + con.close(); + store.shutDown(); + + store = new MemoryStore(dataDir); + store.initialize(); + + con = store.getConnection(); + + CloseableIteration iter = con.getStatements(foo, RDF.VALUE, null, + false); + assertTrue(iter.hasNext()); + iter.next(); + iter.close(); + + con.close(); + store.shutDown(); + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConcurrencyTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConcurrencyTest.java new file mode 100644 index 00000000000..b6db4449936 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConcurrencyTest.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf; + +import java.io.IOException; + +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.SailConcurrencyTest; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; + +/** + * An extension of {@link SailConcurrencyTest} for testing the class + * {@link NativeStore}. + */ +public class NativeStoreConcurrencyTest extends SailConcurrencyTest { + + /*-----------* + * Variables * + *-----------*/ + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + /*---------* + * Methods * + *---------*/ + + @Override + protected NotifyingSail createSail() + throws SailException + { + try { + return new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); + } + catch (IOException e) { + throw new AssertionError(e); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConsistencyTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConsistencyTest.java new file mode 100644 index 00000000000..1f043fe6e35 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConsistencyTest.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.util.Collection; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.repository.util.RepositoryUtil; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * Integration tests for checking Native Store index consistency. + * + * @author Jeen Broekstra + */ +public class NativeStoreConsistencyTest { + + /*-----------* + * Variables * + *-----------*/ + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + /*---------* + * Methods * + *---------*/ + + @Test + public void testSES1867IndexCorruption() throws Exception { + ValueFactory vf = SimpleValueFactory.getInstance(); + IRI oldContext = vf.createIRI("http://example.org/oldContext"); + IRI newContext = vf.createIRI("http://example.org/newContext"); + + File dataDir = tempDir.newFolder("nativestore-consistency"); + + Repository repo = new SailRepository(new NativeStore(dataDir, "spoc,psoc")); + repo.initialize(); + + RepositoryConnection conn = repo.getConnection(); + + // Step1: setup the initial database state + System.out.println("Preserving initial state ..."); + conn.add(getClass().getResourceAsStream("/nativestore-testdata/SES-1867/initialState.nq"), "", + RDFFormat.NQUADS); + System.out.println("Number of statements: " + conn.size()); + + // Step 2: in a single transaction remove "oldContext", then add + // statements to "newContext" + conn.begin(); + + System.out.println("Removing old context"); + conn.remove((Resource)null, (IRI)null, (Value)null, oldContext); + + System.out.println("Adding updated context"); + conn.add(getClass().getResourceAsStream("/nativestore-testdata/SES-1867/newTriples.nt"), "", + RDFFormat.NTRIPLES, newContext); + conn.commit(); + + // Step 3: check whether oldContext is actually empty + List stmts = Iterations.asList(conn.getStatements(null, null, null, false, oldContext)); + System.out.println("Not deleted statements: " + stmts.size()); + + conn.close(); + repo.shutDown(); + + // Step 4: check the repository size with SPOC only + new File(dataDir, "triples.prop").delete(); // delete triples.prop to + // update index usage + repo = new SailRepository(new NativeStore(dataDir, "spoc")); + repo.initialize(); + conn = repo.getConnection(); + System.out.println("Repository size with SPOC index only: " + conn.size()); + Model spocStatements = Iterations.addAll(conn.getStatements(null, null, null, false), + new LinkedHashModel()); + conn.close(); + repo.shutDown(); + + // Step 5: check the repository size with PSOC only + new File(dataDir, "triples.prop").delete(); // delete triples.prop to + // update index usage + repo = new SailRepository(new NativeStore(dataDir, "psoc")); + repo.initialize(); + conn = repo.getConnection(); + System.out.println("Repository size with PSOC index only: " + conn.size()); + Model psocStatements = Iterations.addAll(conn.getStatements(null, null, null, false), + new LinkedHashModel()); + conn.close(); + repo.shutDown(); + + // Step 6: computing the differences of the contents of the indices + System.out.println("Computing differences of sets..."); + + Collection differenceA = RepositoryUtil.difference(spocStatements, psocStatements); + Collection differenceB = RepositoryUtil.difference(psocStatements, spocStatements); + + System.out.println("Difference SPOC MINUS PSOC: " + differenceA.size()); + System.out.println("Difference PSOC MINUS SPOC: " + differenceB.size()); + + System.out.println("Different statements in SPOC MINUS PSOC (Mind the contexts):"); + for (Statement st : differenceA) { + System.out.println(" * " + st); + } + + System.out.println("Different statements in PSOC MINUS SPOC (Mind the contexts):"); + for (Statement st : differenceB) { + System.out.println(" * " + st); + } + + assertEquals(0, differenceA.size()); + assertEquals(0, differenceB.size()); + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreContextTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreContextTest.java new file mode 100644 index 00000000000..8fe84d8ed7e --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreContextTest.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf; + +import java.io.IOException; + +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.RDFNotifyingStoreTest; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; + +/** + * An extension of RDFStoreTest for testing the class {@link NativeStore}. + */ +public class NativeStoreContextTest extends RDFNotifyingStoreTest { + + /*-----------* + * Variables * + *-----------*/ + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + /*---------* + * Methods * + *---------*/ + + @Override + protected NotifyingSail createSail() + throws SailException + { + try { + NotifyingSail sail = new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); + sail.initialize(); + return sail; + } + catch (IOException e) { + throw new AssertionError(e); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreCustomInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreCustomInferencingTest.java new file mode 100644 index 00000000000..92ffec07534 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreCustomInferencingTest.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf; + +import static org.junit.Assert.fail; + +import java.io.IOException; + +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.sail.CustomGraphQueryInferencerTest; +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; + +public class NativeStoreCustomInferencingTest extends CustomGraphQueryInferencerTest { + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + public NativeStoreCustomInferencingTest(String resourceFolder, Expectation testData, QueryLanguage language) + { + super(resourceFolder, testData, language); + } + + @Override + protected NotifyingSail newSail() { + try { + return new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); + } + catch (IOException e) { + fail(e.getMessage()); + throw new AssertionError(e); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreDirLockTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreDirLockTest.java new file mode 100644 index 00000000000..c216ebb27eb --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreDirLockTest.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.io.File; + +import org.eclipse.rdf4j.sail.SailLockedException; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +public class NativeStoreDirLockTest { + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + @Test + public void testLocking() + throws Exception + { + File dataDir = tempDir.newFolder("nativestore"); + NativeStore sail = new NativeStore(dataDir, "spoc,posc"); + sail.initialize(); + + try { + NativeStore sail2 = new NativeStore(dataDir, "spoc,posc"); + sail2.initialize(); + try { + fail("initialized a second native store with same dataDir"); + } + finally { + sail2.shutDown(); + } + } + catch (SailLockedException e) { + // Expected: should not be able to open two native stores with the + // same dataDir + assertNotNull(e); + } + finally { + sail.shutDown(); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInferencingTest.java new file mode 100644 index 00000000000..2b107fc471a --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInferencingTest.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf; + +import java.io.IOException; + +import org.eclipse.rdf4j.sail.InferencingTest; +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.inferencer.fc.ForwardChainingRDFSInferencer; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; + +public class NativeStoreInferencingTest extends InferencingTest { + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + @Override + protected Sail createSail() { + try { + NotifyingSail sailStack = new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); + sailStack = new ForwardChainingRDFSInferencer(sailStack); + return sailStack; + } + catch (IOException e) { + throw new AssertionError(e); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInterruptTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInterruptTest.java new file mode 100644 index 00000000000..380ed1e66e2 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInterruptTest.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf; + +import java.io.IOException; + +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.SailConcurrencyTest; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.SailInterruptTest; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; + +/** + * An extension of {@link SailConcurrencyTest} for testing the class + * {@link NativeStore}. + */ +public class NativeStoreInterruptTest extends SailInterruptTest { + + /*-----------* + * Variables * + *-----------*/ + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + /*---------* + * Methods * + *---------*/ + + @Override + protected NotifyingSail createSail() + throws SailException + { + try { + return new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); + } + catch (IOException e) { + throw new AssertionError(e); + } + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreIsolationLevelTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreIsolationLevelTest.java new file mode 100644 index 00000000000..2bdebe3c939 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreIsolationLevelTest.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf; + +import java.io.IOException; + +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.SailIsolationLevelTest; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; + +/** + * An extension of {@link SailIsolationLevelTest} for testing the class + * {@link NativeStore}. + */ +public class NativeStoreIsolationLevelTest extends SailIsolationLevelTest { + + /*-----------* + * Variables * + *-----------*/ + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + /*---------* + * Methods * + *---------*/ + + @Override + protected NotifyingSail createSail() + throws SailException + { + try { + return new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); + } + catch (IOException e) { + throw new AssertionError(e); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreTest.java new file mode 100644 index 00000000000..380f9842f64 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreTest.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.sail.NotifyingSail; +import org.eclipse.rdf4j.sail.RDFNotifyingStoreTest; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * An extension of RDFStoreTest for testing the class {@link NativeStore}. + */ +public class NativeStoreTest extends RDFNotifyingStoreTest { + + /*-----------* + * Variables * + *-----------*/ + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + /*---------* + * Methods * + *---------*/ + + @Override + protected NotifyingSail createSail() + throws SailException + { + try { + NotifyingSail sail = new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); + sail.initialize(); + return sail; + } + catch (IOException e) { + throw new AssertionError(e); + } + } + + // Test for SES-542 + @Test() + public void testGetNamespacePersistence() + throws Exception + { + con.begin(); + con.setNamespace("rdf", RDF.NAMESPACE); + con.commit(); + assertEquals(RDF.NAMESPACE, con.getNamespace("rdf")); + + con.close(); + sail.shutDown(); + sail.initialize(); + con = sail.getConnection(); + + assertEquals(RDF.NAMESPACE, con.getNamespace("rdf")); + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataStorePerfTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataStorePerfTest.java new file mode 100644 index 00000000000..a69a68ef2e9 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataStorePerfTest.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.nativerdf.datastore; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.sail.nativerdf.datastore.DataStore; + +/** + * + */ +public class DataStorePerfTest { + + public static void main(String[] args) + throws Exception + { + System.out.println("DataStore performance test"); + System.out.println("=========================="); + + System.out.println("Warming up..."); + for (int i = 0; i < 3; i++) { + runPerformanceTest(10000); + System.gc(); + Thread.sleep(2000); + } + + System.out.println("Starting test..."); + + List timeDataList = new ArrayList(); + + for (int stringCount = 1000000; stringCount <= 3000000; stringCount += 1000000) { + timeDataList.add( runPerformanceTest(stringCount)); + System.gc(); + Thread.sleep(1000); + } + + System.out.println("Performance test results, average times in micro seconds"); + System.out.println("#str\tstore\tgetID\tgetData"); + for (long[] timeData : timeDataList) { + System.out.printf("%d\t%d\t%d\t%d", + timeData[0], timeData[1]/1000, timeData[2]/1000, timeData[3]/1000); + System.out.println(); + } + } + + private static long[] runPerformanceTest(int stringCount) + throws Exception + { + System.out.println("Running performance test with " + stringCount + " strings..."); + + long[] timeData = new long[4]; + timeData[0] = stringCount; + + File dataDir = FileUtil.createTempDir("datastoretest"); + + try { + System.out.println("Initializing data store in directory " + dataDir); + DataStore dataStore = new DataStore(dataDir, "strings"); + + System.out.println("Storing strings..."); + long startTime = System.nanoTime(); + + for (int i = 1; i <= stringCount; i++) { + dataStore.storeData(String.valueOf(i).getBytes()); + } + + dataStore.sync(); + long endTime = System.nanoTime(); + timeData[1] = (endTime - startTime) / stringCount; + System.out.println("Strings stored in " + (endTime-startTime)/1E6 + " ms"); + + System.out.println("Fetching IDs for all strings..."); + startTime = System.nanoTime(); + + for (int i = 1; i <= stringCount; i++) { + int sID = dataStore.getID(String.valueOf(i).getBytes()); + if (sID == -1) { + throw new RuntimeException("Failed to get ID for string \"" + i + "\""); + } + } + + endTime = System.nanoTime(); + timeData[2] = (endTime - startTime) / stringCount; + System.out.println("All IDs fetched in " + (endTime-startTime)/1E6 + " ms"); + + System.out.println("Fetching data for all IDs..."); + startTime = System.nanoTime(); + + for (int id = 1; id <= stringCount; id++) { + String s = new String(dataStore.getData(id)); + if (s == null) { + throw new RuntimeException("Failed to get data for ID " + id); + } + } + + endTime = System.nanoTime(); + timeData[3] = (endTime - startTime) / stringCount; + System.out.println("All data fetched in " + (endTime-startTime)/1E6 + " ms"); + + System.out.println("Closing DataStore..."); + dataStore.close(); + System.out.println("Done."); + + return timeData; + } + finally { + FileUtil.deleteDir(dataDir); + } + } +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/measurements.txt b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/measurements.txt new file mode 100644 index 00000000000..05fa38e7253 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/measurements.txt @@ -0,0 +1,26 @@ +Performance test results of DataStorePerfTest. Average times in micro seconds. +Results gathered on Dell Latitude D610 w/ 1.73GHz Pentium M, 1 GB mem @800MHz, +Toshiba MK6026GAX 60GB hard drive @5400rpm. + +===Baseline times=== +#str store getID getData +1000000 93 17 14 +2000000 268 17 14 + +===2005-12-21: hash file stores IDs instead of offsets; removed ID from data file=== +#str store getID getData +1000000 87 21 13 +2000000 136 21 13 +3000000 166 21 14 + +===2005-12-22: replaced hash file with btree w/ 2048 byte nodes=== +#str store getID getData +1000000 91 31 14 +2000000 116 36 14 +3000000 247 43 14 + +===2006-01-05: hash file, bug fixed IDIterator loops=== +#str store getID getData +1000000 85 21 14 +2000000 106 21 14 +3000000 250 22 14 \ No newline at end of file diff --git a/compliance/store/src/test/resources/log4j.properties b/compliance/store/src/test/resources/log4j.properties new file mode 100644 index 00000000000..885932a0ea6 --- /dev/null +++ b/compliance/store/src/test/resources/log4j.properties @@ -0,0 +1,18 @@ +# root logger +log4j.rootLogger=WARN, MainLog + +# MainLog configuration +log4j.appender.MainLog=org.apache.log4j.DailyRollingFileAppender +log4j.appender.MainLog.DatePattern='.'yyyy-MM-dd +# Real filename is set in AppConfiguration, relative to dataDir +log4j.appender.MainLog.File=target/combined-client-server.log + +# MainLog uses a custom PatternLayout that also outputs stack traces +log4j.appender.MainLog.layout=info.aduna.logging.file.log4j.StackTracePatternLayout + +# OpenRDF logging +log4j.logger.org.openrdf=DEBUG + +# Aduna logging +log4j.logger.info.aduna.iteration=DEBUG +log4j.logger.info.aduna.collections=DEBUG diff --git a/compliance/store/src/test/resources/logback-test.xml b/compliance/store/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..4a6f17fbfa4 --- /dev/null +++ b/compliance/store/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + diff --git a/compliance/store/src/test/resources/nativestore-testdata/SES-1867/initialState.nq b/compliance/store/src/test/resources/nativestore-testdata/SES-1867/initialState.nq new file mode 100755 index 00000000000..57b7facb872 --- /dev/null +++ b/compliance/store/src/test/resources/nativestore-testdata/SES-1867/initialState.nq @@ -0,0 +1,59991 @@ + . + . + "1ac494e5da5f59dffa0bc7b9c26331d2c9262baf4cbff0eb0d95bada13befcbf" . + . + "90631bc85d77d4e499ccefaef93719cafe3b6e05fe4c783c474ff64b4b2361a4" . + "5233559d21a86abffab5a50811a3fef635c6665b47c6bf175e670a09178597ca" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + . + . + "364075b6fa26518d49f5ac8f4b4cf066f69b26ebb70f31b7106b1adc3ca1c599" . + "64af40e9a0ad777cc50e88f5c83e004697378bed0bad1348f00132ce4545d08e" . + "cc661425d96fb8569a2fa170dbf799e20374ba12e6406fd2428585c2d65b2bec" . + "74297d1544703954e5241af3b2bc73cca998294fc52eb1dbd7ca9a249f24a74b" . + "090f8c082d07ee72264f9dbdd057638b5678e7bcd2912fa8a9746e136825605d" . + "1f8f2e8ca92ba60aa1a5e2f90dcbbaf4d84cffb2ff3c2e4217e6aa947bfd360c" . + "e24fc71932b15053a5af5528d238b32915c0c848ca353e349e4bdb5e97dfb3a8" . + . + . + "09935c39844e26159f81c9d3362673a5c47b2c9cec6663a9d550a8290146622d" . + "ff4e5307375723653ec95db30b1365232a7a1eca49ac4f1b6e6267472d874378" . + . + . + . + . + . + . + "82b5f96f9efac3afeb6b362260d2a7d9a7a26b0c8fcd11212aac5ea0dfe001a1" . + . + . + . + . + . + . + "a179299be872e7a082e6990005bcc163d839726cd8c30a4d04ca4d8dad4d45bb" . + . + . + . + . + . + "67e4e051271b99f237d6ffc3ac3714029ed83561403b3379b36633723ef8af68" . + . + . + . + . + . + . + . + . + "2e11f7f6e11df49ae8edf97db7606b01ced26939b92649a1e4ec5aba38b68c46" . + . + . + . + . + . + . + . + . + . + "58f8680f81adadc63f10021afe904b221d96009e78b8cee7450665ae858000c5" . + "58f8680f81adadc63f10021afe904b221d96009e78b8cee7450665ae858000c5" . + . + . + . + . + . + "1ff4393bcd872405377779cd81a787a54906f836cdd1d316ed2c5710d98d925b" . + . + . + . + . + . + . + "ce290bcc812b46e8d660aafe07a601afc9bd84eeddbe6d33278bf4798e6a6659" . + . + . + . + . + "5ff2e7d1ff56c704eb7ccd999ab24c9ad4d85e7b871bb0786e7f51858d2159ee" . + . + . + . + "9075cb9ccf11688e0ed065b021290d19d67612ed49eee1c61ae32e041dbd0ebb" . + . + . + . + . + "4511ff51bc465aa3e971448f226b75527d6921eda42386c908ef19084ad35fb6" . + . + . + . + "12fd80b5a13086a51203fe84d5accec21938529a586ed164cc156501d2be4639" . + . + . + . + "471cacee86a419f75111098ba664eeb1e7db51b9436a9821c23851df5ed52c15" . + . + . + . + . + "6c6b7df3070f112f2b6d5f2b57cb7bc885e62f52497e4121bb79431d188c7982" . + "c10f769bda83e9e09e21513f3e6ebe8defcd3efad65ddef59b6ef2e5dc8e4a13" . + "c8b61ec034d17530b93c32e49e0d98eb7b27225cba9fbea927212a9d6ab0a5ce" . + . + . + . + . + "86a3d4125c91d4621cfc34f7d2ac1f2fb7df908cae63aef232d0b9e0713171db" . + . + . + . + . + . + . + "6ed673a65da2dd2ace92e60f1c6827d1d835789a71f4c1ebbf92ed90435f2bf9" . + "6ed673a65da2dd2ace92e60f1c6827d1d835789a71f4c1ebbf92ed90435f2bf9" . + . + . + . + . + . + "9b0c48284ba496e90ed4b7e23389f04be235c1c3c3342097cfd0ade8fc3f6168" . + . + . + . + . + . + "2f988527ec2fcdb950f432d9635be8d0713a57b8a07672932d8cd59306c95bb2" . + "5662554a1894ec3d3f90ae8a92645d703c3b3a1402687a126df1404e861bfd5d" . + . + . + . + "fc5955c8599edf7d5badc9a7243a3930592b567d700cd6b9c27d750b386f5046" . + . + . + . + . + "71c3a64ba3e703caded311175da2349a8e62726150300ea76342411ccb11c7ca" . + . + . + . + "8da62800a3716c3726ef9fa9bef52bc08dce5a7489fc277ae0038f6bffef212d" . + . + . + . + . + . + "e95b10c45d30735c648afc79479ac77ca241935d9b0eaad247e2676954205c87" . + . + . + . + . + . + . + "e26943ae7ea1b011752dbf9fcf46b233559c026a1e50f029af5979ad86063a60" . + . + . + . + "a12f05b9dff3f47583166f08a778299c8aed3113ecfc1f4bdb5b61761fb85b0d" . + . + . + . + "4241d7207fc79ecb2534f5475b76bcbd4f79b83eb61ded086a376d8c24a09792" . + . + . + . + "27a3a501b7f9ac1da6779f2bbeda50ddae3f75c1166e9726c69af88d5c770325" . + . + . + . + . + "f23db0fdcb15be116a154a106c3e9b2defb6c4f7db4ad97a95a3763877b1fae5" . + . + . + . + "bfdde6f5651ac5e4e6711f3c2836d5f8c5c4b381a50eb87c51d990b7eb36501b" . + . + . + . + . + . + "ab4b7fa1526b74938f21b947959127921c4a74f6c3ee8888b152148b5a9fa611" . + . + . + . + . + . + "6efec98683cc8a510eed3cef394bc29ac75d238b37525f77035541e142b7ee45" . + . + . + . + . + . + "6ffe58b85cad95f1e86f1afebc4ffba738ef6c5520811cb5f393f6c0234ffcb0" . + . + . + . + . + . + . + "94e59eb54958669303b899780ed91850ced34375a8f1ac7e79dbba832338a930" . + . + . + . + . + . + . + "dd714b64f0130e6255a492a7c9856a3362088af955de6672a25c35e6a5c1d05e" . + . + . + . + . + . + "76de2519bbe030df1b8414ce1dad1b2cfeef3119c1907c9bc8977fe35416dc8e" . + . + . + . + . + . + "44ad8791f7fb835af624170bf247491ef3fde63444ccc1ae443daaf45d0ebf64" . + . + . + . + . + . + "8b02242de25a8aea09f2b33587375365a942f3047925ead6a22f254cf7140fb1" . + . + . + . + "1fa627e35abda105b23ef20e3450a4e51eba1873a8a826c5fe941742df38a519" . + . + . + . + "82f8fc8ed1eed68fc3a7106fa179dcfe2c7c3499cff04a22d6b025eb8c5d9c7a" . + . + . + . + . + "309f141d2d80e395b3fae78a2f70f5ed68d4b91ba63592c3722e630c6e173097" . + . + . + . + "cfc31bcc34ed7f4cc7895026ae8a54f0494f73757e9f914d0f6ed90f9bc34f51" . + . + . + . + "97eb808e59de5804140e8ca50e1c043cec058ee1bf52eb36345975741bacedf4" . + "9e916443592bffdb0b4e1cdbe29078a7a73c0f7f3f34ad41d8e746ad976d3779" . + . + . + . + . + . + "67aaa8bc04fcc0d82759e4d4622264aeb05173e3bc74dccb5082c5d48a5f89b4" . + "67aaa8bc04fcc0d82759e4d4622264aeb05173e3bc74dccb5082c5d48a5f89b4" . + . + . + . + . + "e6d7a8fea55c7471cf94d571da08d1317a79293fe34812a443b44da911a6a26e" . + "e6d7a8fea55c7471cf94d571da08d1317a79293fe34812a443b44da911a6a26e" . + . + . + . + . + "5a1e90933d69ea0111cecd4e4162c7ddc0d0e9a9b6df606b1d8396553d33e4ba" . + "5a1e90933d69ea0111cecd4e4162c7ddc0d0e9a9b6df606b1d8396553d33e4ba" . + . + . + . + . + "ba362eb65c4c9584e762040a59a488214e36c712c6e7967c4df91dc1fe00fdae" . + . + . + . + . + "87dfbbd263f118137d036701c9df923f7214ce109ccf397139825fcf4b4e7a5c" . + . + . + . + "a8aefc374937a4d288f3337ad85ab61a6fbf2ed5a4264d73f72922a37cd9bd8e" . + . + . + . + . + "acff5028d5add61179078fde71c9067ae5edf15865de7cc816b4b0ed94f0bd60" . + . + . + . + "270ceeee6d7edf34fcc731f43d63e65760380a96ff2acc633036a5525af5d9b3" . + "13fd15f5e59e83006192b5f46b4e702391fc99a2b3f5ea18c69872dd5fa5e7ab" . + . + . + . + . + "2992f9abc1d6e757b4b15fafa0b37e9d753f9d0d34e72b9b643e4fae8cf4a098" . + . + "51cff04ae240482b1412373bcae234e44c65f04a88417126802469baac41d6e2" . + . + . + "0964d23e8cc184a2e8e8c23be8dffc6af832131ba608488f5366804e26404a54" . + . + . + . + . + . + . + . + . + . + . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3b72ed2b5bd89eb23e5b5528a16d9f3d0cb73bb7476f6ae2852b71702ebc6da4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "e31fc311a4e657e93fefa9b6434a9f5f08a94553cd50188c51f37b2a8c932b80" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9e010727d63730fd63f5a8c2bf25adc100101ac4ab461ae6a7e876737f6ec994" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ffa333edb9a00aca3ac584c68b5a28ef9178ea217da9d187bd0e253b12eb551f" . + "bda40e9a8ffd28216e2c8827988bfb5e3c9bd8bd771b8cc6c1cc68cb1a523db4" . + "4d231049a895fe6ccb92cac773d7c76dfe7934209ca8de35548ec7a7f523fb2c" . + "2f46103238e598c1ada8589fe1d528ca916366413e097a49e46aa57401fd0c51" . + "d6d3c6318a4582617a85821b502962b17d7f38a93c7e408a0ecf22516f560f71" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "cbc554f70533b2817c57562d8157472a794c91ce707833f99b00ccb8f5bde13f" . + "5a0abf6e1f7a4d9e5da3824cfab98a45643f82f13cae8c899e0e65119a172cde" . + "266aa5886067fbbc1a3a39fe432fc5bbf561abc90e4b8a322215ac17df6ce012" . + . + "17eed2c0e7c9788d0b46fafdf328b3e955aa0a22132c16cde72aa4f32dcd5282" . + . + "e23f8f39182c82127c1bef3cbfd9b54e30e1df4916da81dcfc2a801c23f3bf01" . + . + "a04908f573e7a1c9b9f62563bb9a5188334fd250d76875e845de3f24c895eb4b" . + . + "c8d8f2e29fb181ffb8e4d234ede6633fb9529c69b8ef280605002e44764be39c" . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "6b889fc1b5d505a02b1e449e415a5ff65644115877a7802a7c8fc5b077006c50" . + . + "f9cacf3cb91a12e03bc4546834f95a50a4c5fe02276ac260148ea9296c442d39" . + . + "2bf175f9655e7bb7357b9f0a7c6051465a5ae701104ffe741b98e852c0e4d460" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "c116c838040f676d887fc856d8fbf4e143f70ce5c91f78e66de880fb35be356d" . + . + "bb628f904b3ffb3905e77454632dfecf87f47b4fe61fe695d7613c209196e48c" . + . + "6bdea40ac8424f8b4d04558a8e59cc746185e0c159c091e47a1b3330abda4f73" . + . + "f326bd84707ed76597becb832280595d1a5aaceb0905dc40e3553ebb861bde80" . + . + "6bdea40ac8424f8b4d04558a8e59cc746185e0c159c091e47a1b3330abda4f73" . + . + "a5009944cc0deb7463d9f0040b6ca1f1685dee27016ab51c86adfd07492c3494" . + . + "ade1a1c2a61af0f279a4978dfddcdb6acd33f5a8b61e62c5fd881e8a88a387bc" . + . + "c7e05c3805ca65af412b1d8ad0d096d94f09b176766c132dfc102b20f30f794b" . + . + "c7e05c3805ca65af412b1d8ad0d096d94f09b176766c132dfc102b20f30f794b" . + . + "e23f8f39182c82127c1bef3cbfd9b54e30e1df4916da81dcfc2a801c23f3bf01" . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "ade1a1c2a61af0f279a4978dfddcdb6acd33f5a8b61e62c5fd881e8a88a387bc" . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c5c3e94ebb9fe3bc376488e94493a1c1a35be92e883f124008c65989c5c45972" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "88e6c2e1c344b2fca45c0f6fb1760ad618631465ea00f121e80eb2ec8a030e23" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "77d33a20155cd267181bdcf474e9b2e70ae00830e62f5d66f2fff249f39720ff" . + "331cf860e7f519f796eaad08d6990c797bad7bb4e247f757c84bafaa2a4e474d" . + "80283ec1985dee973d7f590face6aefe38b13154545514594a3f44c5b3118358" . + "895b57228a87762d4c6ceea67d017d54e7289d9e1d85d1b89ffba10c1a775670" . + "a5009944cc0deb7463d9f0040b6ca1f1685dee27016ab51c86adfd07492c3494" . + "340fcdaaf07c1fb0bc10061580d57fc8bd7a681f65211d09040296c0a56c5097" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "a4aab3f1f08004e907d2357fafe74cab56359bcb32e23f52e7eb1d3a9c0a2ad3" . + . + "227e4918add1d7964e1745439f5cf44f3e3aba15de6f570942d418510b022b9d" . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "e4bb04eec661be0b6c4cde1d3e6dca3fff3c9bdbb8c1244061f85bab274505e9" . + . + "e23f8f39182c82127c1bef3cbfd9b54e30e1df4916da81dcfc2a801c23f3bf01" . + . + "a4aab3f1f08004e907d2357fafe74cab56359bcb32e23f52e7eb1d3a9c0a2ad3" . + . + "a4aab3f1f08004e907d2357fafe74cab56359bcb32e23f52e7eb1d3a9c0a2ad3" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "a5009944cc0deb7463d9f0040b6ca1f1685dee27016ab51c86adfd07492c3494" . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "4ed39c44a26d6cc42e8f0af019fd6148aa1a1523662fe39fa4b8c40e5efb567b" . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + . + "ade516f85ff9f88e2ed3ff0977e2ed8081386b6ed660552f8f4d54736babad99" . + . + "8334c554c7276f59674810b92fff5197cd46bf6ccbe872742f9b04ca31dfe3d1" . + . + "a4aab3f1f08004e907d2357fafe74cab56359bcb32e23f52e7eb1d3a9c0a2ad3" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + . + . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "07f7c82a6d65dc204a8cdbf71ed5ae422053021abe64e06aeef7b3c0240319dd" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8424969bdb3f23c69b5b676ca451b94f6dbacada86ea036c31e8762c6712ccd2" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "65ff8c33729bc5cbf9a4a4732bf3e4cd1bf342eecd8fddac0dee5b850f2150f5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "81bf1e7870efb2b5ca9374ea06c74c89448c72fe2a143de6d560322274ad5cd4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + . + . + . + "1e9013137f7ab4ed0338598577a074c77ff99a1d24099522f4f78b4223e3d342" . + "34a9d7423465f177e3ad6cc3912a5f9cdc297a77dc7faae238ef0a8cf9695b5e" . + "c8b61ec034d17530b93c32e49e0d98eb7b27225cba9fbea927212a9d6ab0a5ce" . + . + . + . + . + . + "aa7e6ee1e235416d3a78563dacb10d0a1e28726e11174523a1b1c487e0387b5c" . + "d3cd4a9fc7c3e9ff0d3ad69f6a495a344645e95c73b6bb4cb0c1b28669f0b771" . + "fc5955c8599edf7d5badc9a7243a3930592b567d700cd6b9c27d750b386f5046" . + . + . + "2f988527ec2fcdb950f432d9635be8d0713a57b8a07672932d8cd59306c95bb2" . + . + "1cba67b84a1e23aebf7d515178ab74cbfba3fe4e7795d90f1dac36d1425c7f12" . + . + . + "05f6f85efd8925dcc30afb56722bf6517013d0ea1a2033bf06fe0bc9455644cb" . + "08b6ff91d0e998f403044845060ababbe3314c5cf54ada0cf9390d3e85be1928" . + . + "fc5955c8599edf7d5badc9a7243a3930592b567d700cd6b9c27d750b386f5046" . + . + . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "86a026267195d06983e285ac47e5298a457e3aff9b5641e0a435a5ff7b24f48b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3002ee5a19531d1def2c37ba3e9b72868d2807a3a640e04641f3dedfec349e4f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9ca092f8dd29b1c3d3d3d7e8531ee6af88783997193e6f6650f5f494f4d0f975" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a29a7d9473617ccd8acde8a585bd32d71f3008216cfb31a26ff282b4785fddbf" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7daa958979bb5b312cbf6ee5fdfcb3ed12b978e9a4a8f2d9b1ad89b2614c5deb" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3143c664091dff5b7f82c5e99bee94f5804ab2aec91ced857e00871ddd811263" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a8fccec4eb2f9aae328d12f3af53d7d3f4fdf25d975ffba9c5bd43fc9ed89f36" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1ac0a5d32b2ceb1026e194a36e9898b5b5fab2c78d7b898d40f601344197dc85" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5a00acefab55ed678649751c4874c256de0cd495b527adf9d5902c95604da739" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5c5f0e90bb95ffe4a400c3916b310f6dada12489117af30e433c76d360580988" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "81f9e095a97c4a050e8c66d67b27576b1b48947fe04a0d5d4ef8131d509c14ae" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "eefcec3832bccae557d449c8f3c0fbb386a00b3bb93b414b4fddb59f2edbbe06" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "53df991b18d3477746f61a03593a3f36aecdf880aacd81de72611064da6dc1ea" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "db29bbd7727a06779f35adc9c30215e10b1c8f5d2c1fc799fb26b9771fa4915b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b79b840d72ea8fcbbbab4d2d87e0fb8497408e195d22fbd78454cd54adbef19a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bb0c7d3a515e5e5b2dc66bb6f6f407c47c4f77ddf2af234fe2f1df1ef2ccc99f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e6334377bca81cae5b4a46a56616e9b781a0893b46378aac4254815b003d69c6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5f3f4e2a74fd6cde98f3e0ce1c267d000601f114c3914acb943f73ef82d7ce6b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "239b6f74a125784d2b50fa7aa77d9b9cfeb618aa27f2bf03f6256023c9ac7b01" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a4d6ad844714d76b073ce06ed1fc612a4b136d978e095f2ea4937bc82d1bc651" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "db5ec15bc7dfd2a4682e5168923953057244fae7cfa43a42ac30d7beff7f7643" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "098f1313134ea3ccf779b370a418fa6420cc65fc0bfff38beefa98564b74993d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9457aae7101bf412ff69fa82b717c26003e53c49f951dd105d1df1eee210632c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7554e78369c8c600065678310c95d3bdaf920ff73c756bb8ab2fa054b15c6376" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d79ccd1cd0eb4cb4ebae52ff0e5e2bed02b24f8226b1bfcf7631fa3d1fe61dec" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "37313c0317d4e7a79ac8a2f1993c25f60afce14e78651b5068819f8933a339f4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c839b7a9ae3a4a95791e095da45fdd3d951fc362d7f250f7fa653d13bdc8c35e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2669e1982c43c6cfe8044525761b18765e91953b6424cc14cbe5ca44338b151e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "be87ee9856dc03d434770b6f651063bc80856db4fd0a895266c08dcbcab4379a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "77e7b4b629d6313011b148c4bf2a7c47c8edc664dc66073a35e5db7f666ebc39" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2801dd6a25e0169a20ee32d29dda8eaaf164a657531fa6bf4345c945184689dd" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "51d9842f3baf95680c5aba6ccaa72194f56684a3d086ee7ed58e2c0edd67ee9d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2dc8d600f7be04a57b4895a0c1762fd7ed08ba69b327875835d1f515fb2b792d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e6950bb2bd6b773fe05275961847ca1e3cc228a94ebb0eff8bce637195e4e850" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "107d4237249b2684f43a4734b046dc4a398580a9ad107de533b60cce897ab1e8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + . + "88e6c2e1c344b2fca45c0f6fb1760ad618631465ea00f121e80eb2ec8a030e23" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "12734ff515825232a7b7c22f6db19d12603d556ede92074dc33644545ce8921b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "b5a1e42a9acdb8dbf83b8d477673174538c11da459cdd2d66e9ce2f48c86bb09" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + . + . + . + . + . + . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "97a4b10718f7ade1ebc52acb7c99f06ec14175fa511ef2297b8112269ee88953" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e62676828bf8ed7e199c84f5980a89609ee8c1cb24c4369125852a82b7bb1b82" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b9d4b7b34ca255fb959178560a07c6711307026f8792113ea5e34e850d721bfc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "66c8f2c0e14588bd3670392e4b6fdc1d504868b1e243d3db9ced084e8b3d4522" . + . + . + . + . + . + "4bbe1d1440cac31d3e924825fe340e8cac363bc4338d49e2cb487f82efde0f50" . + "65df1881c5ead0b840b51219910bbcd686ffbdbf23725155927936a30641f899" . + "737f9584ea2ef7b0b29dbd91b1bc99578ede96596754da6fef812002af6451e0" . + "a9f6a5c9d070450542c8f542714920ad6e81911144586f2d730dbfc2be80e75b" . + "2afdf73e7eb0a941880659c7abd909c19e3139833c3a7c02eb9052132068ac8e" . + "737f9584ea2ef7b0b29dbd91b1bc99578ede96596754da6fef812002af6451e0" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "3e306ebfef811581800d51f6b420ccd0cfbf79625c6a7f6306701e54b588dcad" . + "f76baf7d0aebd050f7d65f93d238d487f26d53e78367f19ed7fdbde326b80509" . + "49104d58ad30cde29ad5d1c676c50b6c595349c5b6546b69eba07049c067f0b8" . + "9287ab8765726d0ad116a9876a2f90187dbf68856e72ed73ba3469cea83a3404" . + . + "a669b764da0b3c8aeea79781da9f4b9236653cd983ff7498d1760440eefc48fe" . + "598f70bee3e88491cb818ba23e012a92defe1bf341c39d737d9848913fa70edd" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "02a8f83a9927d9ecdb056203c68592db24441255f8871e40c5a4f1d1d539389a" . + "5974d963295843600ba48a8e294e8ea5a1267abb92d039021aae74b0f8ccffd5" . + "47d39b43bee0eccef2ecbac7e0d4e4a0fe4071811a7b6e4dada43167eaec581d" . + "17f91bb269c8fd02249949314e37a01defea436896e56604c10966cee0b6c878" . + "a692ab7c9ca12ac3cc69f9f4eaae7bf55d5e7740fade7bcb295abf14a3912fed" . + "265949cbe9929b8336a7155d5815aafc39b6705bee5840b446d75c868959aad2" . + "9af796cd9fe2ab60f266867e63dcbc925251afb2efef013183ef828a803c228a" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "56b236288f2e2fbf188a86fe7d61d51f3cf03e655e68374852d8652e659dae4e" . + "dd5c5ae2a005152222ac9404c120124fc6d4b57eeee3d44646d4c32ed26967d4" . + "7d514e4421a51dc332b3402844e18afceafe6fe1b9f3cd7e908f83abf4e891fd" . + . + "3eece10bb1ad196b40521b2fd09690a056d26afd882b5a83634c03d6c34871a4" . + "cc11310c456c3690d5a74c23aa31cc25b4e74cdae146c71e54ad9dbc1d109fde" . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + "c88c054d065aae174e8f459a6fec82ef763aa538749d238309c1324921e15169" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0df03414c299bbf569a75806fc1ffb14e03123179f8d0605b8215a6c683ce05f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + . + "af500860ef81866022d72a7adb5b80076ce09f245384d1932f7248d5524d9efd" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9dab936679f17db297104593256c4a4cd65dc40a471990589dc823050a27cddd" . + "6dab0410f3a48e7136471fc143d1e403c8048be393a8075f9f6b0e7e5fdb56f4" . + "995fedf823c45aaf3ea487c2f73d6488bd46bd12e4059e4411daf83a3e34acc0" . + "f8e7ae0772f356bed595c943c83488248ce3a53591731b8408064a7677d7bac3" . + "2f8b1b1a4c7cb2f35d55ecf31bac40ef86869a4adf91489dec831030d857214b" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "a33c07f11f405376282562fce8769740a72aba7bdbc2309bf9b048452e55edf8" . + "3e306ebfef811581800d51f6b420ccd0cfbf79625c6a7f6306701e54b588dcad" . + "607b1b1717c13e13b015d098be68a88962674e9503786c9d32ef375c3a2f1640" . + "d2c1bec81ddaa839243d4174c9109edd9203e347642936b04d2ddd41e04f1ff2" . + "c03fcccaba2fa1ce953f2147b8267cfe6c5260c4577ab3a58ec20667307af135" . + "e5e8b62ffee5845c41bc3c0c250636f14f522c19d94701675e7d641d1eec87a0" . + "4ee63f7232037cac4a1d72de7969397cd6319e6901c043eaea23de15f60f8808" . + "1a3c137fe20664e9aab6f7704e0de46e442b378a90c66f1901818fec9fafc080" . + "35e9a58f815cb16f5231c1f876144095f6e93cb9b9469beb0c6fbc3c96b10fb8" . + "1d7355e9232088228d82aa347623a9918ae8f06bb4956c56af9e6b8cee030b36" . + "0e529f1257d451fbf07fade631a5912792dbf1d6c9883c004b2f3295cf8d1440" . + "0efe023fc6e689609c250e081f32d39cbc48489ce1809de3d0a911f7c0a31f75" . + "12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126" . + "12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126" . + "20836b6091a986c6ae3b1fa137a29f156c5a4b2a0daf817d3bbf27497a1532af" . + "5706fa33e73befc0ca3d9695456813ab2bf893797fd38d4dd347a029f5a04018" . + . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "affe0caf5b1696d5e8f6fda250b5414c5860782f7197b42920743f51b9839439" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b7106b733f47ee719813e0cdbe290ce40371730801459c1d9896efa8a2d5d889" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "4fb8c87949ae8d3f5643c437053bdeff40ded42683674f89608a435d1b021832" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8307e11187bcac31096309844debf51453bfde6743c57b00be555103fd0e9e58" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "0a39525bc6521dd01ff41cdcfe9e0ae966b34a646cc2794deb1a850e190ddb4c" . + . + . + . + "0a39525bc6521dd01ff41cdcfe9e0ae966b34a646cc2794deb1a850e190ddb4c" . + "5443a9a67851846505615021a75e791095c6a860facc373abc3c6540a3578fbc" . + . + "c88c054d065aae174e8f459a6fec82ef763aa538749d238309c1324921e15169" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "3c2ae3668c87b1ed29de8d0b5356e96b02c34bf093bec5b239a89259dd672933" . + "04fb016ebeed0e7b8ed781c3a44e825246da6932ff3769e6e613dad97c06b3f5" . + "a79311e50b23e885116ca71be0452c7ad490f5a372cec3728dde7fd523cb2f69" . + "02084080d885cd6279537fa18b4a9e577af6b112d1d5798b3cc40a06b84ce419" . + . + "aa3573f67398866f7e37b60875313423300e096d43e6d5b954e5eb06d36b0de5" . + "05fa715dbdbb6fd5c828a9f01789d77ebbd9c6e2d0153f10222f567d2166e643" . + "71d9bf479b9655de8173b2a212d23ab7206cb2a3a8ec284b4303fd8af66ffc22" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9b1d7e7b075903f770c766c1923d18ed2b40be5683318dcd9dea679abd696a41" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ef5990b51020e2a5818d21759dfca49efd7b908091a2735bf6074b22edb0c8c1" . + . + "6e56a46f5e5f6c33c7d3469fa7d39de58ed4b99ab31554905e79596938ccbd5c" . + . + . + . + . + . + . + . + . + . + . + "37122c0f1ecdaf82819af4bcb5484d0a90208b34b9dde7c9b24449f95947543c" . + "105959cf49ccee7068b0549131a0979c8387ab66d6d5a8c43ea56cbba50e6846" . + "a45e07ccd2c61f5f74432be1143968907ca80c23c7f5e87c6644465b1be5faee" . + "9ffe424c660893de4b44986581e80dad5db83a3abccfa333b6e06ff21ec203a2" . + "57fbf6a6a9fa4f06137f4aa2020cc2ec3afa0bf85fd2959c9d66424c120e3df3" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9f3726bdbfbd1f7488d49ab5d4ddc93127fd7412838c476c60134695cddbaede" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f0dd1354f86c86cba968d145333d83e1bfe95e44586187ec934994200ea18150" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "92dea35eb2320cbde3219f2e57871c0933fcabedb249228b67df98d1e41ec339" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ef5990b51020e2a5818d21759dfca49efd7b908091a2735bf6074b22edb0c8c1" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "33a257a4ca75b99f3aefd16ae18f72bc6f2e443f02fd645eb103be1ec9e9bd1f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "886531ae3f7fb5bd89b0f0d8344924a4372e193a3d9d39e791c50db2b362e3c3" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ef5990b51020e2a5818d21759dfca49efd7b908091a2735bf6074b22edb0c8c1" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1a43a7d4a73cad2fdf82ca848537773102380cc9ad5e10115f532e7f8010effb" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8c62bb022c785b98efe14af1180734fa83fc717ba7a494d0efba306ee14739b6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f4c3fd67fc2ef2fba8de08460927d6e93820e40db7a52bc1d35baa53cbaa0e65" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e37282083ae93ff8ba41d49e06241012c5095f3ce6d973e6bd991a7704218f1b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6098d698403d78fb17025d551d022146e47577aeba9c49d0ac2d1014cda4c683" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ca5258698936f928c9454c3e584077e2cb49da957a7e3db95eeedfc89740bd19" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + "6acf70f8afa827349684de681de1b6ebf50a2b9bb6caef7f8147652cd0d8e13f" . + . + . + "fe150b25f6be0d8e455055926f9c5821b46d102b771f1a72fb7c4278df295a7f" . + "3248c0facf4dd594e7a6c021a5ab7eb92bc02ab36876af7c1694e64f7b502d69" . + "3248c0facf4dd594e7a6c021a5ab7eb92bc02ab36876af7c1694e64f7b502d69" . + "dbd2fcc59c0f6bb2b62b0d3c0070afefb778cd90dfd027cac8ecae0b2c725b16" . + "dbd2fcc59c0f6bb2b62b0d3c0070afefb778cd90dfd027cac8ecae0b2c725b16" . + "4a673e34f4b60e20305dd081358a3b85b106e465201a44c2bd82a5dcbbdf1434" . + "da7c60928ed0f5ae3751e05a98bfc9f2373630953ab24755715707e2df7b2dbb" . + "173a57de87be676f0aa989b3c64baa43c495999d575c42f037726ede4d73bb7a" . + "f6eac97c000903b0b70b0891eb514bcd0880bb24f138d1a26d5a53b8001ee1c7" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c92ea9979d58539b773335af35f2378dc541b02ee3683cdbf3926abe69f3b82b" . + "c92ea9979d58539b773335af35f2378dc541b02ee3683cdbf3926abe69f3b82b" . + "69a2d8976ed8ab7f4aecacb2f40a4763c074fc296a0b3a46c6b1dba833a40bac" . + "69a2d8976ed8ab7f4aecacb2f40a4763c074fc296a0b3a46c6b1dba833a40bac" . + "e417f7b315659f7220f6a33b6a86a331f1d6ea6a11c0e3cb27185bc1c2364af8" . + "e417f7b315659f7220f6a33b6a86a331f1d6ea6a11c0e3cb27185bc1c2364af8" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "186525b67155ba0f0244d1a10322aebefc02760d43269925dbe1d4dbf905db8b" . + "186525b67155ba0f0244d1a10322aebefc02760d43269925dbe1d4dbf905db8b" . + "9caaa7d78a180843850240e87769c3701b47cc29dd2651a9fb92f226ab18dc74" . + "2261d308d02c28396ff643612831a23eea0c990c0ba068b2a28c4a4f6bd89bbc" . + "278659b6bba5ad7c9d3c7ceb213768f89eeac09ac44565329593f7bc37d857a3" . + "9d433cbeef056c19bde7a5cb1cc7c645abbcb795592ce1e4a5e3aa345c808ad0" . + "69109f7fe11a28d14d156edcd48f34760f50c290e84a2fe39b26e4868c7ae7e3" . + "69109f7fe11a28d14d156edcd48f34760f50c290e84a2fe39b26e4868c7ae7e3" . + "a538e2c7e421f2613e928c254c944078a797878b21be86d6348a04da6e691173" . + "a538e2c7e421f2613e928c254c944078a797878b21be86d6348a04da6e691173" . + "6897b0386628dbbadf75a3df444aed11ae290554c527267282c0e67db0a81741" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9f2231e829edc9778d459861c5321f460bb287994b7f5d8de60c4c6c67e7f9d0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + "ef1ae6b5437defdc38fd67718c47228a59043172335a0a0459df2087002c439e" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c72ebbb8dea44ae663f2f5b5eb9879fce8ec41d9bd4d6dd36dff21667f385962" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + "4045fbbe7e9bb95a1a5f1223544e20a2b9816ac7e8f704a070f30193dfaaa739" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7bbd24926e7d2cedb1470f3588f84f994ee79dccf775a30192701e8f315f223f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "892932d3e9c41cd2571ec8d4116af3588b4a75f026329f359c35af87ef320a7f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c4abc36e7a58dbe81550bcbe4613dafc033fe1acc7a85ce2f66999745e87cad4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + "47ba9a149821da75298d2d5b440db432bc5ed0ae5b25ea097e77799c6ec12ae8" . + . + . + "a04b432dff5be98da4e858561947b08c58f720d509e8de83dbd39a4375bddcdf" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f008c0498bbbc30202f045c2f4a75dc2f88e93e56cc520643e3a772a9e6363f8" . + "bd6a3edff7c49076321241a74a5c4de2f6d2eb7f57b6de30284dcaeea8ca38df" . + "c6a060b64a6078eae41e886dddf1ad15fc86afea1a7774066088e7df3140921c" . + "edd36e391c4da727ee2bbdf037f174596205f28431a5f9a2ce67b65e1900f27d" . + "891686511d53716b5db7caf140443bfb9e1908edd6cedf554b78f0edd44467ff" . + "82ba380f285937d00fa80b9547e092b671f6013b95ab0d2dc9eeb9fa3c12744b" . + "d85da57614bc0bc0abf9fc9a4ee42e1e1f12c170b2ca082144d57c369cdde761" . + "af88bbfade6f53f83aa75f3082feaeea6c7084a706ba36db96bce49014f62bfa" . + "f041b32a257b641570ac3d189435ef38eed50a292d2f4ece79441c3458116317" . + "e4bc98dc7464a564db9fbce1ab4ae58af628fd3d6ecea013538ff4ad2e499868" . + "e8db058060a3a4b6e0c419f4fd67c2b05c88e7e0f632aed942ee05cc6bc9ed39" . + "9c3b9d8d758fdc0576a0617de3fd3883149755c57b56798fc93a882c496f6b50" . + "8ccf69a412cf71b816e78f44115772d954141c401bbe52574687ff894c3b2bf1" . + "d9702253869e2dd6b3c504f78dea77d7086001a51e5f16b4de082dad6065271d" . + "f13a22e1e0436ac53522cd3ca5006a2dae33f9f23ddc52e8e9bfe52f40e9b71d" . + "5f15aa1ac3cd998b3e83f37736c60927246c578fba469c0d6bcf77d7759e5e61" . + "ea89656212e0f90a4206f9def518a21f8f16eebc9d3c23c1b064a312f3ae7b34" . + "a30bf54d5e6fe4dfbf070db7b43eb39c99aa8b261d4cd05c2f798c8abf512dd3" . + "29a1b5fff5b6c756f73d9958f305b71b451b30658574bee38046b2608afc0d47" . + "d1f614a49e1c51c5f490e939887c30f64be7bfa4911c61430b79b03b576abf74" . + "6cdca31aa6cddb00ffecb516f24b5c54e696208a51110baa60abba3c01a7291a" . + "bf07f73e874fc423695607e34e2bccbc0ac4ee240f7eda622d70fd5f069e3c9a" . + "5f389d8597885d20f2b24c2bb95d40215468a0d16f1cb0b6423d8f89920ce9b8" . + "bf96546881f372d8557923746eac3c5e006467b68b6a1933ab350ffdc7f85348" . + "0e2d9883e64355069dc987453ac77c5df826112e98cba06c42951c964cd02ca7" . + "959321a1c57cbaaf956ea226f69d89c6d7fc7603565428662353ef081b30d79e" . + "53479264f060b477774e1a55898588518c37ebfe96dd87efedc0d1ac66c75e7a" . + "81e28639da73c32b230a380a3d5f850a461f7adc190f8433c2372c4906cdd52b" . + "9fc2def47f6653c800d3c63fc0b0800eaaa0c54a32726cb3898747ded9969b6f" . + "ae49c81bb55c29b82ced498831392af06e806225df61d383bedc71443c573028" . + "0e529f1257d451fbf07fade631a5912792dbf1d6c9883c004b2f3295cf8d1440" . + "106e00ad8216e30761d8cf6b62904ce2627241e76c4dfb667610faa73f3c0962" . + "cd8e2f5082fe9a646fb8351a55f3efc9c2e7b362b15e398cb4e72d8ed398b2fc" . + "0ef171023429321855a276c5df69d538fca4802484f25ad4ebc3d2e3e875834b" . + "4a69f705fc64dc9ce39dea3f1c7c53700a8224a945e1813e693208c0dcaa4b97" . + "6e0c92b294bda15851abb6f16512c5851d924ceabf48b529d75a4223f8bf0eb8" . + "5465fb1470f00f3ffc5765e753907f8d792be4b5d4be53eea7fa93761447fd6f" . + "32db2404f9a55497d325c0a60ed06062f90fe5ad4276b2240464391ccfc21090" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "99d23b0e0ba7ab42b16f4582b4547f25c5f4478f010b2ace24fa6361e4805ff7" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1cf8f25c0b6372540727e346399176cc0286ce74a3f9ccda0f9b9978cbf9fe03" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + "69681f376aa748899aa93373f92f107aef13774eb942df89d27f1fc7a22bbe5e" . + "83e24ce7a5bf67324eebe27d12095e7f2a3760aefcd1bf1c71a73c14a969f41c" . + "6ed3d0d6be45ecf5bff5d39c5008ef036668b1dbfbf6dd0f08f65b117f4ef736" . + "62779caab990707e9f78e505c5523622698e688df83380d9077e1ea1e2b546bf" . + "1c1621b25cc6cabe51bdc8a93202d93afd564d0f434b05e2062718fdc4ebbfe8" . + "623b6d935fa77921b277b19c3c5c0dc3a9ef9d72b282e88f53fc6ba3b353078f" . + "5f0bf99238bef7709e47a216824cc05352fb7ad08d5fe7362ec0736d13be9cef" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "71bc198b2cc01d8c95df7986f19139afac2609b462b7c654eb1e3031272e678f" . + "8fd42027430cb4037f977f48a13def22bdc0faf3c6a00c8a2c39ef2f66b9f93b" . + "8fd9507e17c92ae2cbcd82e9980029a7e64918c1d772b5a06e902e355be55f9f" . + "733fcf8416c27cee487474d436d6b331422e92bdf9e751cbf0f9ae0c90770338" . + "3e201a56042905d6b063ccc0174704704be800b2f82e665e4ffbf33e766dd29c" . + "3868a7366a78d3278f32b7af4124c6f0c6ba9c05b82e24afe3f216a87daf1a1d" . + . + "26909708717b39870b3fe663e3b53148774355a26d3e5887aa0d71a55694579a" . + . + . + . + . + . + . + "1221c210089608c92e9001f6ee8b9ff0570341b6d12ebdbe2907431ad8f536cb" . + . + "ac1b85133272ebb7bc179c52f23089b7e7206d689066c69934946000dd403dcb" . + . + "cb6b6bb32e5a719211ef7fd0cccc030b22d3d5feb859257d06964f0a5c61ae3a" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "256056baa7d466b308ec858255a32497c26ac9f072f3a3928f9f663c3542c400" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "8ff7b728a5ef34aee3367a6f90e4e8d1df30137d2617e54336dd57229a82d87e" . + . + "abd1770d317697519401bf52638a0573ec0ef4c3bccdc5a941a102cf2ae5a425" . + . + "ac9539a9515b7800540164519e02b9fb81d08b1cfb2753e7b732dede2ff8c652" . + "095617895cac9e6c2b479a58e607995a9ab84cc78067133ab5de2942d5cc4f6e" . + . + "365d6c019c36c417503f46011b12891b581a108868e016bb2b8159a843d8c2e2" . + . + "8704730ad125ad6e20da50c688230bf0c99f21d4d22c1af114b0737496ecfff3" . + . + "f17e7c4e2e1568fede2864f3afad7f166727e9cc18c855fdd2e51f3c306b7d69" . + . + "d066455760ad4fafdfee035f0f8604bdd84f9c44d9e4f430d3b82fe3c0acbea2" . + . + "7d33218ce6eced3b3baec539c7f06f64189f76fe153d02db0c56eb37dff0e92e" . + . + "cabb290a6a35d60fcba0cb7009ed68688ee1f43fdc1cbb886357789f86a8075c" . + . + "4bf827b58f7067c9bb68f8c42737d73ed366ce9bdaaf9beea6c9a5508766b6ed" . + . + "bf8143cb7c43209753f393c363037f53d15ca1462c5951ef56f15c4e70f8b247" . + . + "8b90db69cbac4b36af9df0a9e6b8cc370850a8b82477a9f2dc2946be246eb7f0" . + . + "e953b13568035c09310a68657d0051e24e838aae3fcf195cc258cfda94928d07" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9cc95b302267b656c61e836b65ac2bcd3edbce24b3ef10e6269c1f22a739efda" . + "d5401b4f9904c08dd9fada150eaff43ba6cfcdb934b2040c8d57443cf0e3dd3f" . + "4c3cda3c645ba8583329e5829a71742741e344a8a96b686013d2e3597845db24" . + "dccc1cd0a04d8f84e714213fddf1a0159e5184e4f9b08e325a23438fb0f2efdd" . + "f708963c55ec74f5fbe691c40df07504dae6f3b696a1f190e31aa3f3c4d2b5ab" . + "78881eae4636b40b3da7b78715b66c9c31eadfc93d79cda4033dd4196faadd19" . + "b7cd5a0b5f47f5a11bda8187bd0572a59549ccfee0f3e1547225df561b0bd665" . + "d65c415a257447f4948b3c31cc3c26ea883f1ceb61b115b2981ca8dc15a59c0b" . + "d6a07f2240b9d4f42560cea6ad2960bd8bb613cd6a59d7fd4f3bc22a3cd79c27" . + "3541fd19e8e0f5a3232b7ab5037c51cbad53d3e53139b65278c69701b75da22e" . + "61bf64ccba3329eca4752808ccb9a3146e42c74d483f646354b9e10ad001987b" . + "e5c966334a2d19538cb17729b753ad4200dd15401c1fc565b81590f64edec4c5" . + "0d209555f92feff192e434704229bab451b5e8791a4c7bbc910f609117dcb99d" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "c6b2610fdc03b4a461de6de5b7523a958dbf96d005c2b117e8b0945cf1a5b252" . + "f71127181bf1e7089375ff481683de20c8582782bdcc4c18e3c88c82824effef" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "9c7f5d3858f8b5efbd6b354eac828c76aa36abb372c21c098596a69fdc8d260f" . + "a68f454b67dfd8429e41dca15c43c3171a94510b1daeca2c38d0b44561937e5d" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "8a766f0d8dd2cfd6e894a5ac7e64103877192dcdabeb06d9cf4e9cfd83aa0e88" . + "00e0ba7376058d18946fa98fe4bd4e09c4f0ec27ff6cf7ba0ff4414a58fa685b" . + "d998755bac03fbb8de73214d2141cc1c16b265ebce1b0a84ac737a49596fbf11" . + "54b3b96d9677cf9ec701ae2e465155527c3c1567f47859f9ab7ee5e39f9b1d26" . + "76c7094db145bbbdec3e563b5e02b2b95c08c1c20e5645c1461c90372ccf4dfc" . + "e9da6c6f9092ec49233413e302a7cb57f01b3d11b26cdb887b490f3d971671c3" . + "da32f173a4f8aac0e23da5c4713e2d5acc544243cf14c6e7389c56ebb56d2262" . + . + . + . + "6b6373d7a4995e3cb8a14cb7358bdff30b7e9255ffe72b89fc00feb0082f1824" . + . + . + . + . + . + . + . + . + . + . + . + "134e3ecd29e830e60140f5ba28d598dda57eac4ce92bca3844c941681dec1c92" . + "a157bd971411d68fae5a5ab548522918f8cb7b1ab3fc0cd8f500e327f505177f" . + "8233c372d94730a8d65c394a6afefba856b789a6427052c6715fbff2066049fd" . + "318a523faaabfc3b599d43f86f1cf36a56b234403633e034aa9d472d96d75027" . + "8b2866b49819a19a99dbf236468e45c73d409bd300079353e32dada50888da71" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "c6b2610fdc03b4a461de6de5b7523a958dbf96d005c2b117e8b0945cf1a5b252" . + "f71127181bf1e7089375ff481683de20c8582782bdcc4c18e3c88c82824effef" . + "665db136ce7af19ac06095048d5e7b5627fbcc6453094273cb2b1403b46cc986" . + "fd69e60b1fc1719546c9d7ac189d4d5d9a22db5f2e900778937ab77548a1c6f1" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "49fe14e9c5f09b5be2df861089093df269754f42025b668f969d6d89bedf6b16" . + "565070f9fb2bcf71eb2ada0b60d3869cb46b79beabab6378231d382f83c8bb1b" . + "1873c1e970eb106fea75efedb20d91e8bee1658d967d328de842fba04cfb3e3a" . + "b2df2639530ff673fca07084624122e3e4a80f28e6b44fc600bc4d30c4ecc5b2" . + "8a9f8f1da04846f4fd4d576e4ac88a51165702e334bde5d908ba4af5c0a4db6f" . + . + "8603033169ab160c6801bdd6feb01cb1aa0c9fe4b1b547614ca42778e1df52c0" . + . + "870db13b36b12b7e84d5b9c2d8960425bac189baba451b715dca3ca8ba855bd0" . + . + . + "06c82631eca64b52f2340f89be5b1ba1fec13a10732dd3e2597a9abd8b264319" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "6c8b70a3f93ac0068a195f4ca72c3bfb44d37067b5591da0508119117278328a" . + "23797eb79048d78dd5feaff5cdf682a08dee8cc15350024f1638e5cdd4ade251" . + "74aa3dccaee033730ac01d6330d425bee37b24fa5c88f8a679485b7fd544d51d" . + "dde88dd448b631b6799fea0cb8fde027687ae4d9f3694ddb6f314168d728acf5" . + "55c5e35127f6af815bde18cb691c1ca2528d6880b0d13f378d4315e41c58a18e" . + "7a79a311145f163dfb2ee399bea158dc51c8544642f64ec5695182e97306931f" . + "8599fb91e3631c995c9a9e1c6cb3ef1b93b1a424f6d62ff56f0395ff78de6b58" . + "b024b9d052302418920e045d83ce2eac6680a66dbf79b2aee707fb04855eb06c" . + "75cc7571d5d1586af04089ef77af6b46d3fa6e3a2744a168c274c26280ba9192" . + "4acec0b1e144f441dcc76898b75777b83aa3d78b8794b41b347d01864c15ae38" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "513c7946352757aed6be631df9583d14a1bf761dd7fec09450de55896b36b988" . + "b8cb43274e6f607a819d18361488fd69f283a06f878f2a1ee59f80feae17bd32" . + "b1b4cdcd83fbeedda562ebc0ef43517d8279e34c9bbef01d8f964ce5c1b0a5b8" . + "513730fff727b815ba69b68504520414714ce975269b55a77a1eb257d54a3027" . + "e1d0d57a1e919608fc1d71b38a805274069de49e216c94ae3500f2447d57f2bb" . + "9caae8e001bf2b5696b600ac10e5ade0cdfca3c902fd767cccf4813287554c97" . + "af14062693e6c417d31d5ae996786d0525daa37f8f43582c586e1e5db1e190d1" . + "3cda0f550e1f7fcd899359d03149a2d37e1a39f357abda311d96c9262d9e9f3c" . + "4e9f28d0c0951fd8670baaf5ceb8f6cbcc02d98059edd5dc9eaaab89b8cec76c" . + "c9e1e112148780241654317edc531310e7782361fba5af2de0fd6ddb3f987390" . + "4b52e34ceb3c24a9255d6bb60b38e05db538df06c132842fcc1a9435ed767b0d" . + "30abd3d29253778c8a96d5a3d29997dbd3e2cf2c583e499f98e52b3461f74071" . + "9acf0442068f2724042dd1ddcedaecb2be0aab7f71523f049d805c117368987b" . + "4a69f705fc64dc9ce39dea3f1c7c53700a8224a945e1813e693208c0dcaa4b97" . + "e54907611d0268f9628ee5b8c826100769150076abc70845111cf9748f80c223" . + "57283a9c38f0b256bfcfb716369479f5d2a280078314833752e0b1b624c6d972" . + "7d041e3399658264b03114e6037d2f8933d6030a5bf32562e914526f24348e32" . + . + . + "cc11310c456c3690d5a74c23aa31cc25b4e74cdae146c71e54ad9dbc1d109fde" . + "cc11310c456c3690d5a74c23aa31cc25b4e74cdae146c71e54ad9dbc1d109fde" . + "78c58c4fc69146e7cfde53004857e7fcff135068252c9789a9fd456f1db6849d" . + . + . + . + . + . + . + . + . + . + . + . + . + . + "01f676e391406c74fb7504505e55e148faf13f4c54de08549de37f43a096f01e" . + "b80819a4a3070acef544865046dd5cae053086c653a1fc2679c9eabea1af7559" . + "0d4fe2d381e0c0b502f82179e27f9f5de58e19677f4a3b9cda18c6061030556c" . + "21dab151a568f03cf98aa0c0ae281003c713061b3f2d639635d35b1c069acc56" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8c7bc025a970ce0263ef5d66f19ab4afde57316ab6244a8f22f21b44d9fd39a7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "eb62920f3d6e4153cbd3c29d0a3792c6d0294bdbf806de1cd0509402b8695d50" . + . + "4377f055450decf24b3ee701aa7c24ff21ef1c1cd1dcedefec85cfb32dc4fb39" . + "3208f46619552e8ff8f7f51ad42173c1ce6a9f30d16935996368339d4541bd86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d6ca069e428d9f8e534dc67402ed83ef31e03fb449fb7a42d2c6fc5dd170049f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e893ec74d23e0aad39d0d6e3d9df4a1c03a6c0f9e99a857950364c5d76c660e7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ef5990b51020e2a5818d21759dfca49efd7b908091a2735bf6074b22edb0c8c1" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "73ae68c00a76ca25c831e08bdabad1a2a0aea591dd6f18d8112bcbe85fe82e72" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3b75a08d6c35646fd4c1006db6199e716251c2eee6fbdf0449bee792547844ef" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cb9e3302f3a37be0189c7ac4c1df386ecd42fc665cd604ea0d492bf37e02dc2c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c641d08d0b17316311906526096c07aa041e09a298cb73fc0ef973b6fcb6d560" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e57d9199ccc04e9a7bedbc79bf4c9794d9d0b0d41a0557cf48035d69f7a9a18b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9244c5be851048ff4d1dd3f14e8ea9ac5b151b2c9c49e4fd422496344b8a9173" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "433c018b38504b1296f40376c928e9a668a7d2fea2028281cedc69cf64d98bfd" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "c20d0a36d63724c49bab2cab4d0e942f22dddb7df3b86279d29902b4b15f428a" . + "d8c9c9ee36e0397dc7ef18a37d0449a5d100ff44f7d37ea965b3f822d45e459a" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b0ccd9d879e71b351bb0bbba455041b8ac465ca28be7cbd19f39867e511a6451" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "8e3596e2fea4da27554e2f0c4c88b9e51bac6bb2ac0d7240e3c017238a3e730f" . + "2fdf96b10781ddb265ce152a3c09e42e299bfab5945b4a16579d2c6a93265f98" . + "13f8f15646164f8d9d33f3aff790a7d85826c40653147b56e514a3937c6c58d9" . + "f4507449379c2b3db440f9e36e02989a778d976df87a65ad2a16533a936c1691" . + "a1962427f350c23b17f998705e01c5d45efa094896d75e1fa38d3ac2fbd945f1" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d2f828f94648b7c09b5789b61828d3ae096aae612dc15d4fdcbb37defb04412e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "51d4921dc7e613d184e9ad7bfd45acf49107025ba3381d703dfe8cc47c0ef3d2" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "01385e13083f3379f46550be6e4a9c3df44460d63934863f3ac61c96f9ddf0c1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "c19586baa4ffb8db5f113d07d2cc5e19b36d8b02a85b5e76513a2474e77b1505" . + "7b5951232b5f93a760d16efe84f1c7c542700071509ae96d5e796aec66eff248" . + . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d21d4776f597db6e5ba2d60eb3b81f059f163a40f1c6bee554cac443edc08194" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6898f2d058cabb0a8d39a498ed4a4303903f91e0b3f6e49084c624dbb28f6134" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "232c45cfea5ccfe7f15aec95716e1c5f9b5e21757125cea2de5a89bf11e913ff" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f802dc854f8a8f03d16ffea04ef2747da75f1e430cfed910418f8e5c19906145" . + "7e11e35831db03c03954253ab254250aa5d06f8b4cb1e1b8c86613460946cc2b" . + "bac90cf655953da6c510122c5b29c26800cba65b2c68c3cb26fdc7c288c7cf1c" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "fa8bcbbb2cbac7d75c67b5946843939120123de8b3654fc069aaece05c485cb9" . + "b74213e3a638d910155cd46aa280a2460b30401b05ec33fbf9d83d130dbd5141" . + "6edec87496165d04fc7d79cd7cdab701bdc63a2b20303e7a160e280170d29db3" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6b278c177d9fa4b142308b6af4ea1b70b4e008902a6fd354a09037032c53c242" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "bd19cc9e2c7b1933de6a97faf4ce92238a9f324d8e5fe99a2f3e954798ede962" . + . + . + . + . + "38e131e8f43395c6bd600b8a6753d8dc50c0afe6a77a6d8d407ff662a397c616" . + "d12f0e614489339020f3a25cd0cf076dc842cd0edbc0cf99cd5c3544381e42af" . + "79bfdfe272f62e0c9512dc6efc9be229c9d876512c54805d33dbe60b157d740e" . + "f7ea49df53cb9e87ea0a5b8ae33c0b70c8e52d951f4b22b07a61a1bc85957b5e" . + "6720a470dc7d220c6dc8a2abe2e642232bf29e01fdaa5b94cd40185ddf9b6735" . + "40db5e5cbf437802cae7981388e939827a5d37a0ec922b74fc75506325065551" . + "9af796cd9fe2ab60f266867e63dcbc925251afb2efef013183ef828a803c228a" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "24cebd54b78c0c439c43e11e7638e90b093523140cd914d308af9ca920c94e51" . + . + "2043bb9c0cb6f39a57daf16c352c5962828f2ae540aba2c6eb5c904f61572c8f" . + "dca1b8fde1b329dd4d6d5f3ac65c79360beb356b748ecdeb11a8cb44516584a6" . + "24977909fdc97b330890f57e51115f01141e8f804df5bacd883672022c6603e6" . + "c5de12e05900a2a09b6c70e774d92d20340695e66433d3283a2d8032651782be" . + "24cebd54b78c0c439c43e11e7638e90b093523140cd914d308af9ca920c94e51" . + "a59b1201dc817854c88355d7d0a1840040a93d3a43be0ebba47c073913380642" . + "0387123277148e749e82bf05a2fd26888fbb25199d1ab63fd10883036caeccad" . + "4e9f28d0c0951fd8670baaf5ceb8f6cbcc02d98059edd5dc9eaaab89b8cec76c" . + "dffabf9ce50150538a3bfc879dc9e20b6859c2a8cc8c1a7fcf4061e534e96b3f" . + . + "e976ba623ad48f1e0c9b3e327e49bb882e45236f007dfcfb0d50e6ebf9638d6d" . + . + "13af10643e520beb685808facd57a367ea38847872ea2c0b087aa2e95b5b85dd" . + . + "8d19931a3ad6c48cd28ca9437f01818f106aae785ca003f8c918cf83174afe60" . + "2ee9026694870c8590b79ee61be6d962a59716cd56112724a1b4b2eac6c9db9c" . + . + "869349ab4ca6a8e89eece8a6f4814ebf01511eeb3b464938dda8481624b41436" . + "5ec517d8128466fbeda44aa4650d20990418372364e07dd54b83aba7582a4715" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c892c4be874bba10c346b2196d0128ba2499a36166066bd99e6efbc475842c52" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "278c957d047a11a929aeb186779a2dd8e3682b36d152be32b64842c0caee0bdc" . + "f9785e8a913cb01daa876d631b4591bdcf41bd620a22242b663ce65708c79cec" . + . + . + "0a9f539bf98b4325c8fca60c8ff93a214b8026acc33ef68211e1dac322a49a20" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "151ae11fa594f971e99cb03031fcd1babf386fb6b0da512cc8ebc54aaec62a12" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "213eec1a4d4801006d6957736fe91c36099ada998b27a969826016fdd07c3f8e" . + . + . + . + . + . + "961d7d7435644bd0e859d4f3c18379b4d4aa32e8b93e3594406a0bbfa48b5fd6" . + . + . + . + "8b4ce0ca8167ef495be894c066f9a00319f21d82116bb75cc881b91f3a8675fd" . + . + . + . + . + . + . + "eeee824263f5d010eff6e1df066d28fee96271e256569d09806020ed0e88c3d0" . + . + . + . + "e1ac3ccdcfae684075de7bbfc2569ca58d5f80f5891b2ef6731cdc5b4a107111" . + . + . + . + "0d7638088f5ed599b5b069ca9b02f1188ee686c454ceaf44ad5724b552f639d9" . + . + . + . + "0e13196f3b092e4a0d7d2be9464e43b3938aeb190ceaace244a9993173de697c" . + . + . + . + "dbfaade806c0f7db59d5b8d846e0ba643c3d6b9671aec29b236bc0deb175b757" . + . + . + . + "70a207ee50ae1a806eb8f06f642b754462fbfaef01cf02ca27a767c46bf9e2df" . + . + . + . + . + "1d802cf539b8f78ff9cc484fe6c6441b1cd50972ed6bbbc66ba6307451931ce3" . + . + . + . + "d8ee78802c97f8343a703a8ff796aa0a5a4a586c92c80bd8c9df3d15dd6ae2a2" . + . + . + . + "109872a6584d076fdd3e3a554d0c48125492fef8cd69e1a9a01d0f9ad6a97762" . + . + . + . + "51986a795eea7729c38425373e178e3a49a8a788ced7a0550f4007a5148c462c" . + . + . + . + "505bb7ae9e6671a0cc19bee7c33a146a8df2e4f3252cf3dfb5b4e8463d327d77" . + . + . + . + . + . + . + "30adbe197c56445a557d7f590f6c2a2b55ea3fa4098746cb0eb28afeba1feffe" . + . + . + . + . + . + "6de8cecb8263bdc98ceaeb99700cd173165712f9676bc5eb92dd4b6eaad2fa4b" . + . + . + "0e48120326dee18dea7d3166f5441c99d48c1ce225648002d17854762bce52b5" . + . + . + . + "2d7b057e6e29a236e284927128d0b0ab9cd5aa3f08055111cb746f6674d2ffd5" . + . + . + . + "f8ee2801e910c81b6872bf386cdf0ba66072ef5d2f95dcb950af738c4aaadaf6" . + . + . + "ccc8e5ca946513cfd8896bfba06ce1d0f22e521e809c0b8c175202c2774ce86d" . + . + . + . + "3ec35f9fc0d7ccd10435d13c31d8336ff1c906f7828a884bb49b6a6c8789d5d0" . + . + . + . + . + "7479e1b9d5b9eed5eb326ab44482cd4330dfc00569126d08e22ed242c2e1e248" . + . + . + . + . + . + . + . + "16ce6b4f8941b26fbee149b965168e3c82a2d73ab0c4c4d397a524f094b14e35" . + "586092073fcf22ec030eed49ecf3d08d750fae995b751cc16421e1552918ee36" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ed7449ea06cbe1b8cb4d4ff7b9b7ede8453fd39908ee6dd20bcc6595db1c4753" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "c43a1b39f08178313ce69fd66c9b9879c7473af18f80ea2efa2830a7b4b38da6" . + "4e4decc26b96ec66b48a65674e918d618dba58177d9f020e4e0bd093be2f50eb" . + . + "bbe9849608c33b7e72dc5e62d5b0cd5bd7049c738d07aee260bafa9fa96a118e" . + "c0de58fb6623677d2ec8058634d16ffb11844c387b884ea33c4823349edc5e9c" . + . + "ece697d67d4606971fbdc6982ce3b495eb34dc2a2fa44e807c666be13ef41368" . + "6b44ca7e6156949d3c93bb04c8fa151fc70648ed4fe705e0ada26858d5554bee" . + . + "e576ba63cbe4089d474c8370ec0ec8ebc3ab386c85da56f321d5d09c764b57f5" . + "7e8c24fdbba32da3cd5e0f7c0b3e37787550caf26d3d6837e5ebaae4857ec721" . + . + "435e2d4896db7e7fd8257085feb54938d68d277ccd5c8884a64cc1ebe11db29c" . + "53873981740ef71a4ed1422c78883787d79e6fecd2b5e20b37a3617520af70cb" . + . + . + "5ff67c6354ad43f192d401bbbe58939431ea254dca5df40fb4ceaf84fec7b397" . + . + . + . + "4a97119b5d317b89ccf4131dce6d4bea1fb2143f25a693a5d1b5736b88efeb20" . + . + . + "e7392da9dd19f0aa197831b2b24b6de90ab3ed2c440282c4cb918ceee374deb5" . + . + . + . + . + . + . + . + "e9242d7a652879635dd97f53a3173cc5b2c663334aa9cdfaa4910864cb41f355" . + "62513f77233f45606bef61ad51a660386f30ee4f1c227b735768ace8395e8176" . + "b20826038849e7930ec4234f3d91a2c04f37fa6eeca9e245b5eaf8821afac689" . + "ba9197f2f781edb022db457aab24458993b9be050d4927f86736321e3aa39d9b" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4e8475744806eba0483071e06957d6a7aff0ba6eeae94825c5e8622e1e29d069" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b30c1d47b36c08527895d3274363e92293e335c777b1b38393f8130bfe20061b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4d48f6f58b0a64bc2794bd590ecd6cb452fed8c50add7a29a21f4d121a85032c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "23f194bb92df13a3208e8fcb0fb9edd1f48fb82bf30f4444a8695549fb5c86e8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "d736107f0f0e2ce291a37395aacfc327e986bb48d47c4c462d3ddec83243f8c8" . + . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d84c0edfdb8b2e93bfbd3cd1a5e925d1f81a0aae6ff39b8329c5924a726c70c9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "0a31618027b242f7d9bacfb08543c0fd359c7847eb7ab02db95b0c4619b9a9a8" . + "f4192d2aa5f9be0ba94dda2c9267db4c60af9d28a12043b71fb1091d12aa80b4" . + . + . + "5579188b920e15d93e58517abdd1dd09e2661059447cd78278d14b3280106430" . + "7bfc302b703654ded7d6533718cd4ea665f1846bdd5f1c8497465a5367606708" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "38eba6ad2c5749b8bc430c05796e025aa8eff82c82cb2ef9698033308e0c03e7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "fff6994d43af2bf99f34f3727adf8ae074a6a79b1f0c83a89ca1c75380094778" . + "601c3ff4cba3899858307bab8d094c30e805cafeccff2121f890d19d552ede88" . + . + "774b96c053c9efe51e02ad0dd67a89d460b62aafa20edd0f626fb98b75206028" . + "065f24f0c302b3b2d693e52c678fc458ddb82a5f26b1624ee79ad6290b94e11d" . + . + "85a28ea334e4d83da3bb6818d816b16f6e7537a8ca7bceab80e2df13b95093ea" . + "8dcd97e13dd37682d6c2e6c63210982aa359a58a049776ec448a6062b8078331" . + . + "aa9dec1aecc233348fc87f2bf229c7939792d13ea46077510a473897d5ba4242" . + "18b43fbdb79d713a1fb49963fb3af81012701712a2c0e6360d28f16a743d9a5d" . + . + "ca5d8edb4c90db29eb18ec03bba4dd358d9d065ababbae9519b4d0796e61877f" . + . + "2d86dda24e3990d2b2da2982f63be7cc4812a4933004d08c85f52404b8e5a8bd" . + . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7361d655d26beed55da29858f69748236a677e469072d573d1946abebaeda93e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "47a687c304c4f142ac990d47aa8e6b8447cce1aea6f573593b8c59cc8571b526" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "76d8ca4c7d475d7976bd9416de036fb37b3c0cd7a98b1e80a9135a1be7b30903" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ffa333edb9a00aca3ac584c68b5a28ef9178ea217da9d187bd0e253b12eb551f" . + "32536fa1c4881ef81824cc0916fb463ebd189a39f1aff46d4e810485e5b09ca6" . + "4e30a85f846f92c08f8820777aca51632da25a336dc1a9fa05f8476dbd8a32c5" . + "4e0b90a83d5c9be4b4cd8de8fd2996a4cd66de55ace76ebce942ae73e4a0746a" . + "c0bd3216391a061156865ab0c5e45d5b6a328d0a273bad31e95cd3c13c782376" . + "1bf2c9a9ac509db4b66b33236df0fe223b2a1484e6389ba0d096a9d389d6420d" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "78f046d5cfcf2574d7dac84a03ddb1c4a1720bfac9d771ba9d5fb8ed945e3299" . + "b74213e3a638d910155cd46aa280a2460b30401b05ec33fbf9d83d130dbd5141" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + . + . + . + . + "89118146f8fdbd8ef7836fecb06cae41c9559c4b3dda53f996ad1c2207bf0eae" . + "e54345cd2779367ee7953a01ca5902e5fcdf0d5a4028ad3729699aaf2c574ad2" . + "f7b8e3a13e1e873649b5d5ba085f91969b7a9080dcbf924071591f0d44815b17" . + "ce17c6fa38659deaf5c5c18c7a63c14c84df2f0857e7383ca6ab59ef524eef43" . + "36887ba2641f7260ae4d57a75ff3f1a89314260387536ff83bfc6781cafd79e4" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "b183aedbcc02f511ee05cb05382740d132263ed69bad4bc08eabb46c0ed9ffbd" . + "3f9649e5b6f637e1247a7e440cc2876e0a3654abb662605d3f9961b67a7d21c2" . + "07e497a48038c59cd44048a0b1380facd83e65357f6f54b251f231cc7069786d" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "949daed8712ab770760d47a5085620bb73db35794ab183fecbaf385a7fcb1c48" . + "949daed8712ab770760d47a5085620bb73db35794ab183fecbaf385a7fcb1c48" . + "08613d789c983c083110cd21ae1b9aec53375e65defbdba127ae939b7d02172d" . + "f0db34bf8cb6e3776f644f9c04f339f0473fd7ace1f63aed8f05ad600d69b0cb" . + "2d500c6f5c3d9da750dd2f30714450e36ac4a3b04844211acc0e27d649c7f937" . + "7b2863243a142ccf30dcc463691d992558ca18fa47b611734133b5574087d84b" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "6856c5ea8793d97ffdf956cd62b5ea3c55c549ca173eaf5cab81cd88053e0f20" . + "88516f3a0044db8db308e85b7503abb74db625d1a2a09d4cfa5d625f7757bb13" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + . + "6856c5ea8793d97ffdf956cd62b5ea3c55c549ca173eaf5cab81cd88053e0f20" . + "e096cf6767565495e0fcacdf0e4cc97b0385c740765b441b9b2d2b1458d37c62" . + "b6142b3d2075fc7b6f94bee1184ca4f7b6999315948007dc94648e7d6f09067f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "73bb9ef36a646c3ff58e23c8170aa9123c7b7f7fac33fb1c9e120aa7c17414f1" . + "ca077ecaaeec0a1c4094892ebc8fdf9cb52f66f3af9238c858ee41a76a78f76e" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "c1f59675d338dff80c3b36963ce20df9760bccd8dde0f950c5537563c14f9feb" . + "86aacc707f6993785e436dd5065da41d18de4e040919397f7fd80bfa4e3127e6" . + . + "ca6135b888e548c9f2b9a710c6d4c5610d9b5db3d273cf6014f3077775421c75" . + "8fc62a7fc8818948a61a732e91c4a0e16c4851c3659db5a7230da1cd68780b56" . + "0fda986d3bed30fd261042de50f403187131164cd9fb2e59e305ffac2f357796" . + "80b2d9761b18566ec37be10ed19ca844734c4ae77d268845397d06e45e38f200" . + "163d6a36c321fb4189bb1528e3943b3903ac5bc16e20cc5b39f2fef8b8c76999" . + "750810459bd4eafd2b9bfe4161d77df60c77321e71ce9f468fd24561d4aa3c82" . + "68d574d431c180f871caccf59a539fa2cad0413bb126c288ef7691e10c23ae26" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7284c06dab71cbec33d8939464ba7be8d5e6a0967d8358bebd193f7d4c267d4b" . + "ce09da08bee518abc84567e4e6004c345210025a6fa067f98c0561cc6c865564" . + "b83e3ef1f0184f478a4f240744ccc5956b19e353651b931a2be84545db7644bd" . + "97b4380618b51d69dd1599e9d8689e27fbaa0429d12c5a153cc2390897854969" . + "37e31c7e5c8b76a5d25aacaef6d03e8070f6de0d65f99c144dc2e58abc79e51b" . + "a1e6a8c524d43efb36a223d4ebe9279346d365887865db446a64e0a041344b3a" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "457daf636e21370abaafa4b305bf3573b62e40f50af034e5e941e182c43a2db8" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5232369315c375f25c3d8c0c452d1f093235d9788192513de2deb94c15c3aad8" . + "962e3da391b17c12d6554f5eadcb1e307157634b8577adba9df596bb523efa72" . + "8d4077e7a697866d311c0c1c6766720cb6b6e91d1a53a53d818fb23f7dcff194" . + "34067e360291a319c38f862688f9556d1914ce999788228b7f3728d280c5ee9c" . + "381a24d03d66d11dd30bcdc450c346fb188560a0e966b9a87aaa89d73ddd60d2" . + "d2044b06b29c10e3f0875547c845d43448ddb8b2c2223021588dafc6538d5e5e" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d3a26612167208d21cdbf5d971e14a3ece1ce2bfec7b28e5891a6ac6f47fbd76" . + "de7beccf52185c75a25eef5256f1a680458a12f717055cfc3cb57b5c09f26ad3" . + "2340d91fc3e683204f72b41c080b6e42f0cc309bceb8d43c1825838e165a1f9e" . + "b1eca2289d2d1d5f37f8656d9bd7ad901d86449d1e52f50c16da18e173eea3a5" . + "9c9bb1fefbe2784bea81c7512ce90162826dc66b493fd837ef83c372c1ac93b4" . + "922f74eafc8062cbbde3a7fd98a7c393b37655d00c55236fb86f21aa4c1d8473" . + "f1da126aa5e95cfaab8cd9982e14523ce096c63f6a9138910d1e0412d12bd115" . + "30acdf1a5c61ba259fa69d2ff38c449924512ad6cacddedb77fef002753086fb" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "702f2a22deb8bb61931cadc6a08c8884eff13e84eaeddfab5eb797234cf19cad" . + "b9dba451749176c340ecd33c9b9bd3f8f66f24f8bdad9ced5c8690ee5ccfe4da" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "e48f4360ac68c6666da4cfcd0a94c645abd5e4ec015e91dde5e9f9358481c4fe" . + "33d5902dbfed842b6d94f85e7f1e2982a1031773f200005d0aee117e16fe6f09" . + "bc90cd3a568d440fd0706f77b1399ebd848016dd5852fdcf41203eaa587de582" . + "438dadc9115c050b9c2123f650be840f50802fd85abaacde62e6713d5dd4c02e" . + "a600c5d7e96dea41105c6db871c4d731703ade3eb6c6078a602a2ef76fe38743" . + "315a990af93b5e0d5cd8c3160165232b1e123f975f2c1824f3a970732b716064" . + "1145e4ca84279ffe775800c45cbec661520b4bc7b17896e523eaf9dc5dfbf412" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "12e6f9dc2d3b2cfa1c7b032e9595ea1b5c244a11cdc1ef864963d38d5e03f74a" . + "ed66eaf93e1a31f22950d630a07430d3bda612a203d87bbce4938b9247656c18" . + "e8a1334949f31d9bba90a97f9a1aaa7ee241d9e8d9354592fee8baf900aa2024" . + "9cbccad0770d537ffbbc0eaceedda3e014b9c7b2aab9fe5edc9168a6ecd1bc0b" . + "508b86406abb3673070f69c08b2845b045c8d763ef1db2e8b72ba4bf50bff561" . + . + "9b1957f0e01a32cffa9b1b6bfc09d2b302d403b8673cf83d5f9e9471f36afc8c" . + "fdf0cfb5edc1381a1433476dc15c7f6bc2d0ee2363a3d1ce1ee37547ec6ce6e1" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + "f0ddc3ac78451dc215f63ad894b8635459782a0516e1032983f65f8f54a69893" . + "c37801f86b00020090423adef04740e9c4bb70aa7313116cd21dd957a5e21f79" . + "b6c8675a96825ef980495549354d42683db72a5ccfd62b14aab12f0c5f8c3c53" . + "0a38c0db3f85f77367e8a5094ef7272ea081cebf9f9df9788d0b2771cf9643ae" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d2265a23dd0994b9ef44a7ce50158a78fcb8b32641e63394fa6a93d09a5f9033" . + "3248e44897429d9f12585a7ec8e69956cd41548fd72da07ba22206e96c1e49d9" . + "3674c344dc53468c2666f54df77065372c2896d818bfe314d86146bb55abd9b2" . + "05dad95919f12790218f083e6fb8a2acb73fc8445e62427e88abc5c0223b8f69" . + "3e3c8c3fbe18183f5258d15175d6315e9239e3ac093965ea898e0e5f8680cdf5" . + . + "60d63967de5f8e5532c39a81ea951316f6576b2555d3dfc8d79342e11e0ac40a" . + "c3a3a805b4da33aba959d452733a64c0d1970252d9eddd32acdab4bf014dfe0c" . + "174ba1079549feb4e13e0033c2f328080b5bfaa7f401946fdf0e2f97c3ddd823" . + "58803709bd4287711223e4a3e432f9f897abc0d7c4546ba78dec8d7131b58ed1" . + "34e199a0ff79d3c54c5897d0bc8aaef53b8b527ef1d4dec6b4884b3f028f9dd4" . + "cfab25f54ed57c9c6cb816576a55515b0ae206b6d5421fae2721851854a5312f" . + "eede98ab9bc0de49595dfadff1af59452db30da520d2176e5c5d19daa3fe3666" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b679168f33a2ba7f89093a433e52eda741f0592edf5fbe37f5bf8403fa177ce4" . + "e1edb8063b962d9309bb20b7b57297077008a269945ee22f5c04c02ed7c1ff6c" . + "c36affd4b410d778d2e78b3f1801f7bd486fd33b29030c4aefb8f8ec25fd1f6d" . + "44f5664d407b1c08734f83eafe8a58a0166d5330d8b76c1d0ee45020ccd7f6e6" . + "2f62a5db07f3575c3b6dfd369ad2f597f5d96e84a03325078aef013c5e9cf32f" . + "92aa8319d4ade229e8ecdb9ac12c649edcfd4a5aa7b95444210f6522e95b89de" . + "e264b38c25b06637d59bb6a977a6e0e4aee50cdfe218f34a4398721fc4e1f08c" . + "c06df952017432cd42bdf88844e1540a51254c6aef537b0788a50376652dbde6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "6dafa9d1ec9d50491b01c3a45ed6530008d2fdbd83362c93faaf2b228bc6fe08" . + "a259b009d3c662cb93e09d8beac71c9fde16db77c77a5d2e58c3fc258367fce7" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "3f71ae9eefb8b3a193ad18d012d2a1d04c9d1336a8af4cc175b003c3e839d9d2" . + "9ca9688dfc5224e76d4aff0fa613762852d0889ebd2a0f6d8f8de68bc6bbc51c" . + "9ed90523c896c0d8a7693d968e7ee166d29c0b20bb7c03fd62569e1bb52f90f9" . + "42ad7f7f7f03bc9e895796576de8d65b0ddc6388dcb001af6c35c5068e2c326d" . + "ab19c98a2db9f9224a86ddfe556c693910a640cc87ec275f0ac22a6c00f9a002" . + "4be4e66c4ad4b81b2932ac7bf71fb544d7661debcd377aeae2e009138ea0f0c1" . + "ee04204f7c9b8011d2088c0cb5394c3ec7e11410e370b9d826ce97641097f58f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ec5a6216f6899631d2ff57e7a623c4e3f0795566fca4c3c0e1beed6ea7219a62" . + "a8f323dec0ff0201a6e9d2ffb610cac0e65bc5555d7d6d16d587a587172acae4" . + "f44d54ddedeebcae430a68440a853fce7010652acc0a7474abb79b04d3e78af8" . + "819a5cd3c79abb7f9338a3b0e9059506fee9a79627f13e253305c66d68ab8600" . + "f5424826f0fa4d32e4e493d454b3a6984e83d058846d8b932da8147c1c5bc4e5" . + . + "ded9d48500b5f02e5019a1514eb8f238b095abb5f97592fd3b1c8b8e5aad23e3" . + "98031a111a95636d2437f0099ffe1537aa430bb85c4ca744e4dd18ad31f60517" . + "58dda1a90f1969937f69bcf6a06391fb2d7253744f35efceb609a1b16c54696e" . + "77e99097d3b8466571fd0a5e060de3a08520442f3b5222de7620fee31ec40235" . + "eac375ffa8699fb7d541c8b61699e93860cda0108fa3f6d03a6b4e223dc5ff49" . + "ed658e752737f08d5391fc71ee6b79b710d054b1842392177db64c19fe093d30" . + "d4262ec006fc6fa5b14ab212d2a0383b39114c5953cbc930fbff238c297ba395" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0471ba8d7f03a8d8b463a93170090809dae2df4f1fba71ea7e5f87778f560e93" . + "69436ca0bebfad89ae5256231a98e1d954baf712286c3623dda124ffb35e0061" . + "342699f79c2f9679397cec3b998199797fe1895f953dfd9638ab412baafab7d1" . + "98a5e734da545bf0e52c4c9b4a8858cfafc53b8b969595edf9d1cc0770a20c8a" . + "eb8dce6e245ba5e73b1395c765d96f6c493af1c212c46ac22c9f96417994fa07" . + . + "fa8e4ac14e3b965f68db8cba9ead2c45065ab48e2577f894debeee40acb5e615" . + "93edf1484e096ad69fc40ffd871b3f07740b458d688ccde52a5fbb30c1ab25de" . + "84df77b3dbdff684b5488be2aecb6900c81ac3ee2b4065fefce389a47645ea13" . + "73da84c44f67a2c453eb148579d4f2483af8a0a755e98a6365c8237637c3de8b" . + "fa8e4ac14e3b965f68db8cba9ead2c45065ab48e2577f894debeee40acb5e615" . + "d159dbcbeac47f1830b98842599c758e80f223a9d14fbf4116d92b4adc394c29" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a161fac4c1e84d99ad6893e1dc3316d32370f06cab9e0b1fed3450171e0767fe" . + "553c22fd3c7ad4d1856dc3c461e8769066b03a1f138613c36a3e85b1dface63b" . + "25e7e1c316b52d31fd02ca6e9c5d2da651623892e58a43ca6646a6c3b492c0f0" . + "b7c8b48224fa2db1fdce797ed772c50e7677f8baf6a468d2e9c704cd57a20e81" . + "d1642072b71609484474edb7f4ab5b6d12684dcd4cc80b67c1125de2ec6176e3" . + "e554b66b66d982bd4d506a2a5a46aa0998dbdf12da73b1108560548a1cf0af9a" . + "b5c1f19c7be3a927b507fd2a79c509e57a9313eb2ab2f794bd1635a14dbfa0c6" . + "3055bf5374833bce6f4a21405d2f536f50b993d1448099388a48184dfd3485e0" . + "a3a95abe9ed2e118ab801aa7c1a9ef2e7fbd372a44e227b607cbd3e6a5019bb3" . + "60655539f2737f12d507658f3bb2f23132a202aed18a478c3ecd1b3fae17c814" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "6a51cc88b650d0694cf94d63971bd530521e17f79c4f215882ecdc5ee6a0dae9" . + "64f43aae6b79987b78a745e7d7ea95c44d540d3ca2baf825470958170b88b125" . + "9530f8441a321cd2f86911fa9fc7682df9d47302ed82e983f4e1e261fee55ad3" . + "7a631000dc6f9896c15c02eec1c2f4635c1369ccfa9d96222132e3cf8abb9bb8" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "749102c5c6d64848e4d8c534c8957255078264fb44e826cb51e04656966a3b45" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + . + "e2d583645e9c9c38e9a7b8f7b89d1867bcc5417da453671eb96fbab760ade0cb" . + "f82e0ad5ffaa3d0190fddb8dc2a1103ad548eec28227ecc585779bc23bdd2d7c" . + "be7f6dc27352cee8bf0460de0c86183f236e116b7000b67559bff8e5ccb2da9c" . + "5aed0a628f7cb5292473fadc94d2c32a94d4f0f3d9ffda233086adc0ed7345c9" . + "e2d583645e9c9c38e9a7b8f7b89d1867bcc5417da453671eb96fbab760ade0cb" . + "7e8520a9dcab415ff10ffb423f773e23b1bccd30b824098e8b71a41046b1776f" . + "0278db0c196b6084d67cf602f94998ce641b6a8b70bd979bcf4dcac764a62b16" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "96b046f391e0957d5ac186fdd8845d1d854a459c87d7a7961cb07c0e0d6872fc" . + "ea12ab6c94bb223eada6c6591ee4c43fe71888f33b063ecf5a50b80841af47ba" . + "5bdb97988c02678ba653ed3ceac9ec557cc76cce0538812ce240d04ca8964684" . + "eba00d1f26a467979bb0b95e26986f68ad64d4baa71e72f1b3842ef6fcf7f133" . + "07bf28f3fd65e7341b617920f166a7fe0c6f940ae386f126914ac1698ed7ded8" . + "4dc7a3a8497d2ebbb024cbd3ffa0625ee860f31be7bb951975ba8817020d2bfd" . + "ee14d42d0039d2c34972796df35242dd0bec72ab37bc7efa8861268fcb0f5236" . + "d463fff2ba983da50828ee925d9a40306708d058fdf059d7ee710dc0e4b44c1c" . + "5b21ac85d12322926f823dc396817cddcfe285a395ce8408733ff9ce82d64775" . + "5a3b9586d5d36bf56070b77f985d73614a267d693a0ec98b3b494627d55f4120" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "30f1e594f1dbe586d14a6c5e5c62d558947b39009804ca3fa06bb5e137c5eb9c" . + "1d531cf0fff651837d8a59cb8e8b45c4ef3d5e500f87c7f6133a04d1a48b1af3" . + "bd62a65adfb087bccaac48a41c804f6487d8ca5879403cf35f55f3f0eaa912ce" . + "3256cc3a1cc0ce8821acaa6dcbfc45356b50cc259489850f2874aeb91906c8cc" . + "4e4de6ac3b449a470b8567b3e9c7f90f4f88de4439bdcec0ebb4ea52713edb17" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "898d4e16f0b1754dae884fb60e51e0e35c18a3ab0e02cbde85364b641d41c10b" . + "4d283ad46523802cf5cae3a3b71e9b78a63a27701f2ca08fadd5d55bc5322c94" . + "801cd20dd86246adb98a201fb97a4cfb2440ee3ede7e03724b67a3065a039676" . + "98cb7caec60a7ae01eb7a291172785b43355bfab8f5d2d3ce1f628fe252099f9" . + "898d4e16f0b1754dae884fb60e51e0e35c18a3ab0e02cbde85364b641d41c10b" . + "6f813bd5536167da17efe3807e4fd56ea6c1a55b06b9caa5bbbd47355d717ee3" . + "e4a400e86394f299f1820721a3517b8c899ea175b93975b70d9971f029ecff29" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "88232e089ba489bba66f2bfb0fd7d1531934dee2b719e5cb559f3cd5f8340112" . + "88232e089ba489bba66f2bfb0fd7d1531934dee2b719e5cb559f3cd5f8340112" . + "1f94d131a4020f88ab6e75d131cbcddfe103e29b776d328ee7ddf9a1f00449a6" . + "cad55fa5f466a4e0ae2ae889db540a673f59f17538f48e3c2667d2a8c4a84826" . + "45c88c8814067e9891d1f8b2bb019031906ea275020748457c870dbadb87654a" . + . + "fa9b5f7b3bdbca9c999c7c8cb1df75a279c8dfa40e363fa40c55c644cde3fa89" . + "a35f5716f11fa955805930bbe2abff58d6db9caea055c9fb15aa3152cb9f9976" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + "baafb9219f5897ed680487efa47121d4cc38881df26d97996c6535b57c71c05b" . + "ad1101297e16f0052c81031c7f8db3acc2f05bdefb7b2a5b07534de7cb9260c9" . + "658960705b52744ea5c90632b8dee6a9d279a4edba2f59a420f7844e3452ea86" . + "03d991442d36c8970dd4fc3e26a9eb8fa07ebcaa8909be7944c61e53694a6235" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc0d51eea8bdd180c4a186a3968b7e4fa62289de6fd12c79f022a7624e1e8047" . + "fc0d51eea8bdd180c4a186a3968b7e4fa62289de6fd12c79f022a7624e1e8047" . + "360f016a0f24122d7a14b4f5843b488614c6be6fc8fe59ec288925f1ca9f9e38" . + "1a1d225700c5e53b3f3407a523804a5bd95968b06edcdf7b40e259d7f36d4c73" . + "ecf79e21cc21d27643d3a835c517ec21e9c63122414e8e1474f4a25d52648dea" . + "93e3fee365a973f4299c042218d9624c7ff85c8b42094140430232406d0e3374" . + "7fee43eaadf1a4084436115121b8e15a4c1b8fbf12ddff4f8db9ac735ce8f723" . + "2fbf90fe75905f6319c066a0bd6ecd9ff022f7d916faf34e81557ef813d96610" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "e01f82952c2ad727deddc336d68fdf8d9981fc4ab3e328cf435d9a7bcf4a1a5d" . + "7662c389cf9bd4cc6124451278c6412f28edffe308046b957af9991ca1dbab01" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "dfe3a7f97ec15eb8229da804e8ce56f967fd63b12d10ea0d2b6eb0669a714d31" . + "061c0c5da6e5612abb72ee4512bf7bdf8e0cad1ff61cb6007d0435a3ecd54572" . + "beb479f3c195101660e285c4f90b75e296ebdc109788a13a3572a8787c2de3c5" . + "0a25e64f13e6b5e3c5869c96084333aeda96e3522b77a62851a787eb91048433" . + "43cd404ad6cd370f5fef6f63390157542c073dff718d32159ec7fbdf920604b1" . + "83e23ac7aaa4e7e771c8e0756f5afce6626b1c47b4ea232d140d3179d69991e9" . + "ef6c357c86eb96f9259e297bee783321e2536bf6185b6bf2927566943f7a282a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ea5d14a355c789090f39123c46beba51c2701a29b77cee11d5f1338c6d05c4d6" . + "e8f6c8e0280bf8e34a9e6ced27b23438d978f918584e01a20d7496d5214296b0" . + "ed54859b869e19d57dcf6774659903978c1fbcdc0e9f8438ce53f4dd1d23143f" . + "9532ac77d91b9b7c1ecf5366f47b6f25e432eeee524535fe42cb90a7ca92a026" . + "d5c8c952c9f5f709d362a1aef562752eea8732eed96b5fce62f899da4dcf3085" . + "611767648689c6c8b527a865ec45183d0c36f37b4334748ba9fd2049d6c0454c" . + "ece318074565987e0c596a97009c718c76d29a0b74916f0842c37e12d5e3bd16" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "74c4355073e856d59f581fc2b95968c040976553c2208e7cfa3fe1edd891cdd8" . + "4b59743601957dbc1d527a2694cfecfe97a3687645a686af3ce623300669ce8b" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "553eb51c2a485211a3fa7876b2c583c3619134b99e301eaafcffc94009b925d8" . + "8bfed9da6336f963594d24956418fed0f37ff499eee4b60ed72572d76fbb0d66" . + "d88408decad29a4b1d3c2d68ed95c11e9f3c6b12b1c3532f14bbbff69db7784d" . + "1e322c9769644f63118fcdc8de077e72254f03533c15b1f87896dc3d71d06d2a" . + "a5ffe85d754d79085648b7d72bb72f246fa1c51406e93ae8a54f79a5fd47d9e3" . + "886d19a3004d14cc4dd1e46437a1fabca36d8634baa0cb47ac61f55939f3ac8a" . + "752f000f6c6a8812211926c32d10a4802f7977263f5fae6b318a9af8d6f244d2" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ecf3569773885eec185511041cdab568f1e8f3eb89a315f96852ad73c2246943" . + "49f1b63bc3b5bb8bad9220d27257f9580641a4bbd61e8131d0642c225751e935" . + "7e2d7031f7e56165895e1f56dbb31bb6df202e404c48634d62414b18fb796a7e" . + "68bbcab149ba7665531946e72205c33b755f5f795f9424c3008bdd850466be7f" . + "5a55e650ad6f7fd82d81fe40f750c43380469c7756a429ff81e77811c9959a21" . + "753dd235a4314f885f4e2d84bcf554799ee4724a6f58345c003449a876a56a81" . + "d713d4b2516966234752a430fff9465c9463712ac9cd2e409b04eecadadd9893" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df0466c993a8ab97e09f30d37905a933aad5dc75a47d2f62f58777bb0e2b171b" . + "d518d24ec44485b9ad7c4cc42318681dff86805de5508ee9bcdb8284cf1ffd20" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "53a0201feaaf955c54d3dc83e8d976680b4f7da323f4cb1cd749ac276909eabc" . + "9e346723afe45ea24c3b1d4924b0a964b4ebb2391931d088731dd4f12f65315a" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + "ff7c7fe3230b4555f476c5c47036acc42554aa1434270d65a6ff019757f76e38" . + "53a0201feaaf955c54d3dc83e8d976680b4f7da323f4cb1cd749ac276909eabc" . + "5ee01127eefe86cd7f1f2c913c322c147049c1a7d068319a8005df2f9cf211c8" . + "23642a37b12b15cf5afd1bf5d23b5adf2da0d775ba9181b2fd5a57dd656043a2" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3c81ad535a146233b7a4b7b08017079432cf0b375d565e670d02c707d0634835" . + "c3028b0de7bf8e0c0b33eaa2b7e9e1f460558e89a62b4481fc0b47236294defd" . + "89cfcde24f7bf11b37070a03edd8a4b79282ee645551f6c2767bfd342f9bc37f" . + "f673f54068d44cff517de44021f24ec42166280a9b29285f0b6ba5f48bfcc0d6" . + "f714594dda2a2307d3b16064e8ddf70effb737a8e611b9d22b8d9273c7fac07a" . + "45dc40c62c7567f994be6e5b51e27a0875e0732b6de9d4d9ef088ba00e9c92d7" . + "6fb073cb5b34f470e8482cd341ccc04a441893da0e0a19df8cabfbe3d08c3542" . + "6a75535cd71b221c17919d569c308dd1b6e107676b22f995e5729a4f4147e491" . + "cc59d2552f87347296909bd44b7f802de4df7354e41a57ddea084453026fed57" . + "cc3ea07ec71c6ecf3041cba65d1839f18c5fc401dd15041e67eae6904d24b687" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "91555276ba5f4476ea6fcc7b420d7f1a7ffbbed98b85c3b0165eb022696f3fae" . + "a7d6a3e3ae48f3909036b6deedcb12496cbfcd129684e8c6878cce8c8865f0a4" . + "bc437b496a8fbf1c57ecc8b5ee3a7d896d5fda32b97904b42df5cd753f101284" . + "dccd96fa970f83c29cd36c0c57a0c39beade2219b1e8d22a6691af112d460eaf" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "ff696273bac2401422bdaabeed3b6c33e74e00555789c8a374cb0e533ba9229d" . + "2e89120b307c3aa9dd7c948f8a321fec0eb77d122edf6d29db3ee7c7db562733" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + "2f5bb29e64391c175c1f627b7f7f17a04f20f151e8f9ab2438dce2b5a2c4dfb1" . + "9f339cb0f05e57de6b06ff9b6b6d240e45dc7973b741ccbe0d557282a167bcdd" . + "b16e8be3920fc7572123b5cc1916fe264f20b8cff7d8afe7fd5091174c0a1e5a" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "22e1fb17202c2af451cdb385855bb333b8d9b486135bc97c4dc2dfab651ef4ab" . + "22e1fb17202c2af451cdb385855bb333b8d9b486135bc97c4dc2dfab651ef4ab" . + "faa441b0793344ba2b8272477283344fee48ac6d00dbc6876b487a956f4f200c" . + "e37e5a863d9a762987ede461df6985d2b3865bce41791a236c846e4d095d260f" . + "1f21ea9347475685546de7937cf9b5136f27865e63989ea5cbb547f6281f139f" . + "45a7b2edc68d7eaf77b2cf3a0587d7b19776c84212e1e111d98d097c047c4a37" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "22396ee1a419d367b78f26860f7f7bfa69d87798de310f9a6362f6ece331ce2d" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "3262020e2eb87848c17384765aa9b9b883894ef5cc05e226ea515103c5a321cd" . + "43998dce85aaaa74d67befcae504dd420d9d32b815732d69384adfc119d0a6ea" . + "b0a58abb77269b32b77abc555f8d66e06ba9ffa9ae2463aac6815ecb5a433bcf" . + "fcb03eb1c5c61e57121fbae2555722ec038aa9976094a2bd46b632c0c3949237" . + "ac58bf7b9eaddd17970ddda79c45359b593005053e39d86e24379fc17beb53aa" . + "ecdb5e45fbeddf786d471168a964e970be4a51e09b8fa1d3885f485b0103a8f4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e8f530e8488f4365676953857d4b09c13086ddb672efcfa90e35d231a446ac16" . + "a4e7604df2b73cef8e12a30f45be488baf0399a0ecd3e79a86170bde38a8b859" . + "8bd1b4b598f23181e2cfb4e24298fd810ac0a6fa48aa5c76b1c4dfd91b5cc9e2" . + "5a7a632d94805503e410f7c20385cef3672bda1b8e6c088a583e84480c42a49d" . + "a45d679b74020ce3eed4bbbe3a3de43aa70aea32638f2127f6c6349274858554" . + "2c97f7e0fbffe79490573ed672433071c8b0ab90fb9fe97b9aa4ab2876bf91c3" . + "7302535ffcdee9afed0ff4e05689331ca52f01b38844171ec4efd879072bb4b8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "9fe2a05c7e2b8e278ad5827121238fe5cd81034bf8e04298908f13f82970a9d4" . + "29c60998a4d964e7db3fef149cd42e4177291208b4b8e1e7edc5f986b6d8db95" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "762783f81b70368f31582987d9ad973e32737d24c7a9833421a9dc95c8229ece" . + "5a18118cc0acb1e697704f3915c9aa4675c0848a213dbfb82396bd642aa367d1" . + "67e69029334883cd24c078494b921bed2c6ae422001cc04d1e5dd04b62b78bac" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + . + "07b5b2c74833c7cbd126e8bfbd6350fd7493980bef1cab127da0c33cdec9d591" . + "a21b275f3720919a251ccc7a832b8a00c542c1d57748017cdb394c7f4204c48c" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "f4337df5267b54ee8f0ffe15909b8c8d8dab98978b77de819cd034f696a2e47d" . + "d2229a0c9c1105c7356c45f380702257b0796e33a965a07a7d7194feb0ec702d" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + "e29291044ff3e7383209bfd03712302ea3d5398f3c9584dc304ebf78f740010c" . + "1d08125b204907b1765a3967167a4879984cbca09525937aee4be68b4575184b" . + . + "1f50efb63708726966c6c7cff6370432af66752c10bf5f2b30bdab2c0d418e06" . + "efeede8a0a89f9f5e2f540e3d3772c29db98bde4f1573d41d25b8f0cbd5f6791" . + "59f559f1319c35c38c6c6ba11033eb95f69f184f904722d234834b40a4e95bc2" . + "fa04cd62b35d2450191782575754afc9af5ab7189d55565233d57cf60d8247c1" . + "68212cdb3e2f09a6bca095d794637328baaff0a56cf019a306e67eb56e997fd9" . + "24bb85c019e2057f7c99810b6626161a7cdfa338a247a35c22dbb4332e7e74ed" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d590cf7961e4bebf71474f3c8f4510114bf5d2640a69b9969540835d9b218db8" . + "60657ff765f8ddcd95e0711a5744863c5a27366f2b44665f30fb55910d09be76" . + "11b78a509fea2e568080baf8431f62f89744fbfb8bc533f255490bede3751208" . + "aa847ec53303ee602abfcef331dc1f586dcee8f726e434f03293d65c8de1a6d0" . + "d60b5947a194bf22e1615f42b955e4c34aa27e69f60760e8f4be1dcf2393c07a" . + . + "681d80d6a1a4c7c91991319dea34df9c70851ba84ddc933f3ab58248ec33804c" . + "546fd0e14601d0ca3b3fabd0126a146e7d9dc8cf39759086879fb89807ea3a62" . + "eae41ab5587623fc82a3d3478d0df95c49140df2f29b5eee74673a31ed2aa8e3" . + "39ab72662ae4abffb10f88c2d632c3c9d64b36b63879fdab2cde2373b61d4e69" . + "681d80d6a1a4c7c91991319dea34df9c70851ba84ddc933f3ab58248ec33804c" . + "6f1485c8074c06b8a8859cbacdb19894413ad77aaf76ef4d3b9adf88558a4276" . + "8035eb9d479a21b3bfdbde9f64273599d5b5e53d63de6699e810d9dc59287d4b" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b54ba5fe7a7748f2e138e968ab703e73be729ab8f34b862a7b064deaa55c09c9" . + "03efd9c380eb074f13f0c53e2b48457c4e3871e3b329ba351a5b281a351e3e1a" . + "e8d760b25469d5aab67e396b422c82a2dbdb66ee8980e1013f5f200d2b88f98d" . + "27a87881977bb2cbd9efaf058cb3680449087966c0766f6b261256eca8a451ca" . + "8b409c0e56af970f25e02389fc653d612524c56899ecf7186ddab546f2357488" . + . + "2d9fe00fa335080ada21802ad072b21eb93490b7ceafc0641116b8e2125ac743" . + "c0305b51cedeceb616d5af290874d1e5927838aa4a34991f9f917f01ad40797f" . + "cea76907e4dc6dd5474793d1abc2feee62670c389fbccefedf6830ee4899e431" . + "76c503887238b94e0cd27716c100b45179667a94406989c66afa95793d35becc" . + "e60cc3d460ec7906b92e461e38c893dbc1b2b72757959b1e9fb65231a32518b2" . + "56d0a8c764ced45cba25f8a6f0a35d91b33c5ab5b983228e5737256ab0c0b507" . + "abefda32719cebbb720a2901f5ca90b24ad53bba7a637d0fea298ee54d914331" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9b43e61d7748670859f39bb2e3fab38fe594223a7d6ac80710ccf22baa942677" . + "bdae92cb6c592031b593af150498627bb630f0eb357d805697d3d84360fe3990" . + "c71697e21dd57774719f68f4074107bee88eb7d48cf0e408394fd269c1a475e4" . + "a9e85ad4934e731ab62c148ca46649b546e867da6f457d3cbeb02255cb8a2ece" . + "0404b084fa4aab4150a93320322e8a4bf7f73e503481acb000d898d5d2b596ee" . + "bb358b84ef0c3523640e5964490443ebefe86175b69ec4f3024d8ff650670c92" . + "dee54de463db9b0dce5c553c653a99f3dc316b2b2d7b7f56da5e5bb447459d44" . + "ccc798a1eda22f72a3f4ae3b74e5f3dd459e4e1537f6cbbccb004eb205a450df" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "64e3367c79672e02790f0cc0d25928140c27ec0a007350ac751237abc90c0109" . + "cdfb604dc410cccef0b0f3956bb157c80f0cc59674893ca664ef8e410ef75847" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "90ac27448913d082498c398402547c5bbc8c4df13ba0a4f1f9a9587b7e28e3c8" . + "8559bf94187f36e3f4f4e4ea297c0340a695a6601ce7533cdf304e2310f5e1fe" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "b42cbc4e8b7ace409dcf948c2aed12db73bef7db8e691495624ea31cb975609a" . + "90ac27448913d082498c398402547c5bbc8c4df13ba0a4f1f9a9587b7e28e3c8" . + "e4514cfc3cf28cdafcd6d9e8b4bbfe89c2edd66451ecc42166aa437fffc23410" . + "7b29930a983c69bd3f457f966addc473888f6ed96ad871b6e19e748db099931d" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "4dfbe9612b1d48e2b08df63dc18f422638ab6deaef6aee468d51fdf389957654" . + "1c78363ee7db218c324400b776173fc4e3c25ae7bbe2ff04274ce783b381ec0d" . + "03de31561cd5c6da3f6ce17758dc3b75c8f856ac339293ac0d5775304c262eca" . + "edad04b9574501703453ccfec13f6c60d61da648fe23006bf3df3f9c1b1c0a09" . + "199bafd6349cd15e46d623034dafbc112c616ce0414b3565c32cb620fd0e5fcf" . + . + "d536fb2df1f9fa9d10449791342ab4a75ec0db4f1fd389ecdf822ac3851501a6" . + "333fb077c9405b18c42f4e96ead3c7cd359d4bb4686d5bc52e72817221d4630c" . + "d05d01a081fb8faa4c94816dd64a11f6bd4928a5bf2ff55b4c25f8d707eb76ef" . + "32ae4d1a8b0faec4f00994dd1b7697ee93636eebe6798c612926b0757cf31981" . + "82376c51ebe274c0423737a84bade1c6f2bc7342cfb01e7339e69cc9dea7135f" . + "5d5fa0d03b639d13416d2194b074d8a394b594a68cce8d75703b3b1d09afee1e" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "db3bd78f130a2de2a29a2573b36418933e288a85ba7d910fa6fa9ea5be1d9c94" . + "9900e1cdba5271d0364280e9639860a923e0207e3d92706dc2bb6e50eccb75b8" . + "2fee1d258f35f8d2aa05b6ed4bd73806d969dc4a067270235ba17edc9643fc07" . + "ada7782856977298a5b0e93daa4c4e1c6ed99c2ff3b2976b14cbe64a262fcbca" . + "d4f59d56c6a9338927a6e52b825fe9e760253502ee113143dfc8f67bac5f3865" . + "e726306e1e74e77070925c556712a31da633b18de8ba48b6a31a1e9564568ada" . + "56f2e9bf1fc050b2c4e5e42107d0ef3bc64c6c70bdade7ecbaeb8a654510d678" . + "591287f55a81b0364cb635583152c9d2bfb4f45b48af585049547b6a2dbe83a6" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "57d8a92cde065e195cb945298afdca86dc3fd3bea0d08517bd041f0995aae7ae" . + "ee2bcbfab20b9f92b1a227435f04e95e3b216986e133848837543d18e2406ebb" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "b6d86fbef72815e92d69e83e0bc20d673164ca09b942f2361cda9f2113371bdd" . + "792e4c42dc59529de1b388f7d584731689212df5fbd79cc7fe4afb7c1dc8fff0" . + "51b692ef56342ba4cf05aa8a5e073edd0ff5090d80bdb39d9415d038f494a82c" . + "59575de9ebdd23a5759b8b02f7b946227e59f7732ab24ebfb170a6490cf66e1c" . + . + . + "2b29d19c76db6f93cff2eb333e10e7ac93a229fa5504923ac06de1464c6ac02f" . + "8f5a1eefc269e9050bb3506bfff8c3924dcb268462c37d1f7668c9fb30732b69" . + "66f85e95df21ac7e0481467c2c600573a1e94622bdbb2234491ea07ffb5b0219" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4a68e1c0fe2c7a27c9680c7f719617ef7e37e1879c1919976bbe2de86751dc17" . + "9779c4126b30455705b9376b5a65158479d3fbd4c73a41271175d0ed9c093bd9" . + "0817150dd30794c092bd973cf0f53a2d95cffbc05c0a2277c343530333b9cdf5" . + "7d6183c19cd7284bc8d57996a0f2d6c5501895322d0719fde69df6d981ffae95" . + . + "5a2c493df4d8a571299f78b452fef9a2aa9056a771d7c50f9d6f95c73d35a66e" . + "65ef1f1fbcb5dc45565fae99b00a7eeef362763d96877a8bd5e195fd15f6e21b" . + "3108ea50e351957bf4fb5eb0a66011a824403be783bc16002cfe151ebd011b77" . + "3362b13c0a2ae5b3f6716091755d1f26d01b2f9a96cb75f3932c6477d6f6818f" . + "6a813312ba8f02ef09b4587bb0a0979412aa5f99521fa8e6641d0f52ead2c317" . + "ddbe4cfe75d69326f891f10144dabdea28a6be0762ebdfef58dd560b5bff6ff5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ceb6387e0cda40a3e606776cf3e554ec2f539a2fc490c2033886c435e1da847c" . + "0266c821643baf3d2496bf51b107bf8b7860d2a3b4c07ba9e38520cb4df1d885" . + "473de6b6cdee4d612cfbeb1d4741a2c3c108f3e2fc4bd71138bff2500869eeb2" . + "4bc7451a0d3f5be2ee9ac61b83e0fe9fd02b070410e27b4cda04e9af38fb9219" . + "d6f7c79a4e86106dcef643b319bcf78db45b1fd2478a89ceb4873ac16c74198c" . + "f56f19c2c0dc821984b2ccc07b8c5dfbfbc72e2bade20961274b97a16d0e189c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "af6ef5039d90f8164472824cc5c6063648ba2f0db9569cb27f3842c3abd70f89" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "d0b54e35eb870f8faba45477792a8bc2063017a6312119eae61f9eae4eef375b" . + "5f346eabc4e50ad694ad96e672affd3dd3a4ea95ce0f17c8f1d798083638be8e" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "5e2aeadb587dc88db24a593c90de8f30590e972f42f0d52f86f4d5b120038cc4" . + "3eda2b6b8c91133700cc9192a8027000601bd14efeb25bc5d6682716d2fa31ce" . + "10549e0eac40f116007eeef6830e0c2563b086d923e978d3f0d9821512c7f4ae" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f127945d786b013da8c9d9b37e2c7edcdd078bac86a999bad2e8c2a4e8ff8c93" . + "c3489bbc8a6f7fdeed9fa91a11bda5dfb6fa3bd71105d216956b972bf75b44a1" . + "9b2e6803b8df2ff774213f1ae3ab094c7924da31a7ad4c1b91b6f23491dfef43" . + "af23239920ab81606b813dd6a7023a6ed2d0e8fda17b8042abcacc4ae2cf841b" . + "66395f2af8f548221eafefbb48994f86bfe6dd18a5d16f797e1ae84f0ec72062" . + "5d732978af3b18d71b144e1b7bdbb9f3b24f5340e09ce67905a297c7de5887ff" . + "e34d642598a4e0872ff02f2ea1ce48b7e6eb7f58b7bb3379f41e6fb9a32fda8b" . + "fe55abdbc7accd80765bab30586f596a41af5af6c0e3156de32f82578f17c7a8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "81ca2cb3a9dd1193bfc34ac0df292a27be6bd1fc2267b39fc96089647a081741" . + "4bab86a1c0f4c51bd3d42ad357cc4a0ae9a078169b9af10f43c9024091689084" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "0294b6176c167643ac1208d2ad32d20bf8db87b3a72a6ee5e1ae9f05418b0e68" . + "de167ae4e280cc55df502d7555fc77779eb7ad53da37b4635de93cbfa7b66493" . + "87d7e45502823619200b13574b0d0bedddac3d1e31e6246d8ce518a8b0fcea32" . + "ccae22c7c4cb0f10526da790967101aea3c00753989955ddb3202f58b201ba89" . + . + "e11fd2611b2f2ba5618025947957cf095d19bfc931704f09dad9ed84b1939125" . + "51039ce8096a0a198b3e48e913f49b57a5f404b62f81066221d0eccbd73dc717" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "784e922048020c0808fea87be51a6a26c5f159dba690336599ada6795848561a" . + "99f0ebdfd53cc05de59d19376a239c1bf1bf3fc89e1b01fd78d359acdd4ba5b4" . + "5553240f5c92184ee6e191b0cdf476756550d344c6a885b644c6d72eb1840d5e" . + "f0f4c22f6d6ca8a4c044551d1fcd4d3f779da6ec5cec2ef9b7928bb8a6ce760f" . + "a919e0bea774b939136e80b107fd1db28ec96e9bfcaf6b9cdd2b837f13522b15" . + . + "7f467cad5a915018d5ba60518a6b0d39ece3dfff8d3e1ca4d817fc5d5e7b99d0" . + "e0ffee92a3502fb95959dd35301c3d923ad70d1f06fef21c38f8a281e89f60e7" . + "78fe9b33cafe58c172914578844edb2fd35543ea84f346b4fc6969012eb915e3" . + "080a18def47475dda460ac3b4d1a32b84bd59102b6006687ebecac485f46aaa2" . + "6213aebaa47fb5ec74c2419ea13a0739598cabc0fbe2739baf00f6312ce757af" . + "9b369346903d4bcfabe77fd5df97706520d01b97fd3bf774460c851ee02ab806" . + "35618b8b67f2e20e990c014b625b2d44b40a6d487b46bf9ab5c208f591c27aec" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3f240febb14b75f13c518a10ebdf650d482905fbc53e5db6bdb461a8a30c7a02" . + "485d1ae73ffe60ae9d80a0aeb4d6375f10364c4154d56470944563cc77fea020" . + "53a2113e91239d289519d1fb74152a083fe6dfefc8e3d927836513c0a88e4571" . + "7e26b2daa71a2b0a6af8315cd7ca2008c37daf8dd83322d94b6d0442a75cf89b" . + "79c54762c7732e1512712197a28ab4eb5320b2f068c383fda501c9e67b42f562" . + "47cda39d6896045f2103bea89a4a1073a12ae051dc4d26604187138dd46e30e2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c1673d84d42a66a3ab09dbe4b645502b9056da6a6963bf39e0c1b03f3a3840df" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "92bff8ea6fb6d660210e0c671c366b8c16c2ccd58a5bac49595119e9d95ae9e8" . + "0b4038e0f6b71754d3e8de7e0f24ad96517f977a57816b7672cb4ec9b6b9084a" . + "7ae73dd18f650dacd17d665a5c06ba64417a234f93514af1a499469c0071bd51" . + "2b1b033b78035df793daa766444b4cf735a0de0e971f87c9707ed6a760a2c235" . + "f2a39f8f93758fafb7ba175132c5c5c49e2f90b20c307dd986125910b767104b" . + "7d8b9ccea342e01589ddf0283ed847b928958148044fb58092fadd6336f51312" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7606cf4bbb0462d2c085f64062c250bffaef9378fb8344ba7dfdbdd3ec44dda" . + "b9bed4993240b5a16ebd0a79e2fbbaccf7b31329b9e2a154a483c2131e4f45dc" . + "bb1e4c23b6e4a6b72e45619aa2010b6a572e39cad5b89485c9fc716fd5110b01" . + "f500b10858c7fff3aea8955888f1fd14019b09684decd901ad647f7509b05dfd" . + "714be3cab9435bbe5f26a40293deb901ea48a39a49130ab40207bb15b01e26ea" . + "315e7ab5b87c0afd149dff39a98cf9928c4edf2c1185733333a96fdc8fbcef99" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c736fb914e8030e19d63089664f16b3ac1c2336dd8e7024244e1abbbc5c04cf8" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "cceb5260e341d2e4acd8b46ae94a063b5905647ab421181e51a4807ad13e5d44" . + "47c9a8d4ba4ae8ee6381496ccd2d9922bb147d29d5bc8962b860994597af9d56" . + "01d1e81abe960c49d9d56c9905bd3459c4e4fb2ae9ac50d4247db3020f39e844" . + "09b7b2fd617267a3e0e386b75bf61e19bb530e9f2ace05e84243aff1a9c5691b" . + . + . + "7e025a5db3b44fa64e168820378da45e318736a0a0daecd18b6311a0c9459343" . + "3a76dcc05b1984f2f8286b74c51c303a8fdfaa69851645f760122d58bf9b30a6" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7a04837451ef4cd7a136ad70281e54f16d1b2223e2cf368148924e6b79c2e704" . + "8dee30b2d7346a4dbb102910fcb82bb1d249a33df1b45818233542c890e6eacb" . + "35e495c9e888d82de0719ec2340e6fe9892f7e51e905ff0982df8b45d8acefc0" . + "4896cd4af58cb83af99bbb9fb98a6936de665a26bfe42aeefdd045960942abfd" . + . + "8cbc626b8405b82bd17281421054da5d3937897ed78957755ef602df212014f5" . + "519588a5fb0ec048ac36be2d38b95f3efbbe533d047a3ab7d7cad4f9ba3a68fa" . + "5013e0453185a74d4246fcbe366b5535b190da2f9cbe5dae51e54a5bf0955f30" . + "1ab59aa82875689d27ebf7734a7726d9dd04c89760523ee5af46f15642d770d7" . + . + "f851b8c245fb8b1d7243a72135684fdee64b497c1afabc5c7a8c8a8e6203fee3" . + "861973bae40ce74772820774c13d1eb27fa0157c9d2180feab751239a44e20fd" . + "4c1568449c795992b67df86ed03a210f8307ac533faf7ccc23fa9043770fb3b0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4c0437b685b726f0930a4db8a86f24cdeae2463149f9f895d7fabc7ab9c075fc" . + "3bf9fbe8aef794603c9b79febeb9ab1b9f661f7f1f31843530b6076074efd416" . + "514ea7b4cbd615a9a89dc23c50633777fefb707e6126ebf46ec421de1e71a4c5" . + "1ade5b462219833a5ac1ebb52717bf00ae8b4caa10b23ec94edb37ba371cdf7e" . + "280435bfc27d36afdb1079e2844a81fdd5fd3171ae5ffaadd838659f18dcf54d" . + "0c2310f2a773268975fb821b72711ed47b83f6e2301adb284d92a79c6875cbe0" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "2bc984539aeadfbba4e5d264ae8534c7d28d5e1c2e16f77dc88db839d4c8f4a7" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "c65b3c95b6668df8eb0031d13bb670657685a3d3924e74bd7deacf6bcd0bc312" . + "47b6ef0a78b103341712bb263eaa44ccfafb1b6bca5341e7c6a13205ff3171cd" . + "95d03459560b3d1583c1d0fe75a205065ed7ca28cc324085e59bb34f25c548e9" . + "76b4eea33e3402ce6b87b77bc228380e2f7149c01d9f67a64a3acc25c08f7ccf" . + . + . + . + "c045f44e76e99832981cf107f4b30e44f7a5f1518a8d0e0b283da9de1c3a6e94" . + "8a0881b9943ab7bfbf83322208776a21fc6e1a8637f3abe985cc9e6fdeba4bd9" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1c1ac9e50d644d906bfd065993aa6470f99142e98d88cd189b5ebaa41b2587f7" . + "547aa58f5cfdfd7795e468c37038f3bca12a12310a795f57c0bcd029937b1e4a" . + "4d7702fed3300b9325888531981215496bd61f1b706b54e0a4b7f0ef2c508650" . + "a00534da700a7ba1ec4465ea3bfe1953e13b16c02809ee78889723f47bc34406" . + "ce16e723040d7bf035132608b0b623959025a705d545a55cd1cebf3fc8437dbd" . + "99c4fe9a5cc3ca15400b72ca2ded91edaf4c285ab90d3ca8381791e2ada34d43" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "96494180a491cf6d57b868dbfc06892ca87e86caa78417644929ee086561a42b" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "3d6fe7bb2d6f94caaf8e626a4ddd3538b8b0ec68fc097a1c09ca1643fb7f0a4a" . + "a5ea02b92b1c9724ab4875f7123acb409bf968f0520e70ba7291d5b2d7decb48" . + "a07ef78e95c22b1c034ca3194f743d49323a9267798770d1c99b6dae572baf03" . + "ceb527c004687a565f1b13fc9cf4400dd52124d6806e81e6aa767cd11ceb98ab" . + . + "3d128df1c86c7c16cb3e35904f87a6465412d165a9e96f2b304ce7b6660303f8" . + "854c9c08baec47e393db5c4810b49eac7c0853ea779f3160a60dc9d49effbe54" . + "1dc7069c25a4f4a1775deb91369570a406085a30da83a392dd324e5a8b44f806" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "30e044c8c4e6aad032a4f3520123545b71749b2a36db1a19611b8c2c887d7935" . + "85934411ef2ff06658415f2ec19c1dbf8d87a902dd7d2c19c5bc4a806fecb6bb" . + "b2397986f0f608f9db7a3af3f4dceadd21c48e7fe1f870fe3151dd1cf22c01f6" . + "b8c265181cdba6f7f3835bdaf84d52d2e7577594da2115f5f5af49dc7c8ee76c" . + "b32fd4fb2099bcc2a7a6bf3f3a2570701ebdfbb31791b1aa2cf3abbaf2c7ebb2" . + . + "6cdf082d04b044722c0a8139b97d8e62eb2872a7690191cb948c3300cff69d29" . + "137c41d3e4f08073a6b0e4945f8e536a2561cd5e9c1d3bf7dbdc9358cdae72b0" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + "8734901f969c02c0b8eca2cc6207125322ada644a09175567d0a19e3ba4e09b9" . + . + "956ddbdb57babdda27cf580d3d5a5f641356210bf0fbd3182d5da05063daf73f" . + "3590df7013864f8756ba23114ef85cd1bb18888c70a5f068457cc1ea5c3987bf" . + "122fa1991a72e05eaf0aa858b755443ac507bf119fa95d88309d8c7d3013392d" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4e2128901f7fabc3061d57af4fe24f7dc9031c202a2f735331ea52fd785c7169" . + "1ff82073c354078e1616254f9fb05abb7fb904923f853a01063e50d026dbfa16" . + "339820351edebfb18a30ad0c105526c4095ad8e015eb4eb1ddf95befbc5f4ab6" . + "522d2ae53419c75e36d6488efdd257f7da18f65696e3aa3a2ed50b54b268f8c0" . + "296dd15c5f905d40914e4d773b93ef0a0cbbb2fbd34778bded6eebeec5590e09" . + . + "1d5c1dd8f6150acee12ad6c02ae2d994e938b102913985b3e2d48f25f6fd4070" . + "7af90b54457e5e7108ae86a92b57db3b055adac9fa49447a7b8bb9239b762d53" . + "57076eda3401912cee7d47e6060e7de34d47ef486193e0b33cadbeb1aaab0ee7" . + "8d94e432f49b80754cb173fabce2ed56e876c399c31d81d4541b532bd798a48c" . + "1d5c1dd8f6150acee12ad6c02ae2d994e938b102913985b3e2d48f25f6fd4070" . + "c06e63914d2fca8b6a9606273dd53f9c091c3cffc90c469f0b26aa76ed06dd0f" . + "660a4cb6055f53e803faf47a0acfdd3f40cf8ad402be4c6857f02f1883f221ee" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26a4c8e55408574664801750cdce33b50ff93fdca907a4524d88adb42b1a33aa" . + "dfc6a6332ecbddd54d9b112bfada11d736c556e5b638e1e8922101fb5da1ef08" . + "68301da2e04583b3e244ea20b6098e17df882f2bd0167a96261bf9a4b0a12bf8" . + "863f28f1c26643b01f9f5ed54c143426d1c68aacd66d5244595a29848601aeb9" . + "2a84f74973623b87ec63af982120fab360e5bf986c8abb4ac33eb0cf3e3b152e" . + . + "35c030e2d5b2d3b6974f2922e0862dfb2d1c30de41487ea4d5bacbfc78ea975e" . + "3cc06415ed0ea832961421152e1aa97ea55ad5d61e46757d6c1e62341e1ed058" . + "82df32e143152c3b0c0e9a9b837996ff37ee87873e6d7fbaa544f5beb6bd6dd3" . + "423d086793cbb17e2bdf7ef01621d62de033cdbf5603e536189bd92fd18128ef" . + "bef9116663e44d21a07c1ab10651b4f641fe0abbac1e27167a0b803f52725c04" . + "300a6374030ada317cfbe154904d15257f9ea1b1b94cf7c3f57dd08271db21b1" . + "a00385f721c94fae5f94b629cfd61969ab57e0e8f8c7fe635b6e5deb39109a02" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3863c432713c9b7b3e2222aedcf1c643728c237df069142c823148cdc54692e9" . + "4642bdbf9b23968c3178ae984d530862d973496e6e4228ff0eaedfebfaaf40de" . + "7c1719b4ac20b6f3e01736f606e080b997ce38ed93ef38aae7d5da82fe3e5b7d" . + "9e0ed319caa5126628ccb1a3b707959f723a06e8198c89b63d4a3d90b3d07fa0" . + "a545de21e176d2dad6cb145e74c57cd3bfc74bf6902476042c1bc35a2d7ed41a" . + . + "b219b943f3432d4e8fc00223c0fe1233c4ac5babfc8a97e6e6ffd7b82e660def" . + "f449ff5913ea90285796cdfdae473a847579d40b2a7b91a6b6e179591a0097d9" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "1e874dc74480183f8017098eb65d03ebff165499b0823db4c9913f68f55c8403" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3d5d4ec93f360a8ae45c8f9ea7722ff4d3e3e62678bab55aa81aa5a6d84ba549" . + "7335774c5b68098b98fe51b88cac4ec918ad455f521e2e437263a62f767b4ead" . + . + "fcea9b875c40fa83f63df383d6d906699d9b7cd6e5fc79686073fdcbd26af37f" . + "7786baabb9cf012fd30f2f4f3b6de0a4ccdce5a19a408415ded5edb9ac367024" . + "e8f7b2db0b4ead99e353cf1d554a2064054e931c809ed8c485c20193c319860b" . + "ce5ccd7c7a854d8be9ace64a119e711c99c8edba4d60b3868178af7ec1ad2329" . + "4ed2473e5a82b8e9dd8612a20edd28a9f772c374aba511487e4866ae5037bb34" . + "93d4aa6641c77c3653f386e19b1fa243bd11ba2fa94313c63f76472b90abd96f" . + "4d2e5b0e0961e514447fbd54a47c2b660794d42682fda7eca96bd0a5df9ad896" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8d8908775f9cf87e0a7043cb5df79d456e168198e0f917c7b8aee1524b15fa88" . + "a0b003c20e7f80ef1c8039f127298f872d4ded6660119134097fa49733f7ed07" . + "0a3016d034a920a286c0b940c89d13e39dad5e806e614b1d8e3ac0472a904c27" . + "977c033d6d4bf974117d3e3b8035490569ad7987a0ef08ce856c3a8e1fb72aef" . + "61598958f5bde31c7d4b4b550b8c0b04fde9dda235ad0712aa837136843d6726" . + . + "611b967ab0501be80aad71cce1dd22f95664652872bb7378f080484a601a169a" . + "de5cedf14b79b6955dc9568e09687e0d1fda53a99b92df049344f1f44a43e746" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "611b967ab0501be80aad71cce1dd22f95664652872bb7378f080484a601a169a" . + "51896e45dfc22611c1b86ef3b0851682c66e3f6f580db2ccf5666bd93b644716" . + "4988446db1edf1ff650918c7f2ec76f00b282fd54c9c9743aa6aa7eb943f3cb2" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "92ea4e73e719c471cb8ff432b13c526d6c5ae28ce86f5f2d958773f1bbec5a0e" . + "92ea4e73e719c471cb8ff432b13c526d6c5ae28ce86f5f2d958773f1bbec5a0e" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "e10a0d6044b67dd60730ced2a2093d9bee5a1a481497ee5d2b24b4c7935e8d79" . + "7f374dcd48c5a00b05d593c9fd9d4c381988db12061edd031438d8e03383df84" . + . + "57008385a27043577e9d5eb90a534e43f746e3c2a7cc5ff494d5ea81e6ee303d" . + "c33a5e3c32fd4b6ddbd95827ca187b3a7a2850ccbf0cb528a04a93e80fc2f213" . + "73730b2bb0aead24790c4d64a461e44f584bb50cb1f818185860a15d5b32c6fd" . + "0a1d0202761615469f2f1c5b7601e9e5444dc6a703640da217609f67f8add44b" . + "03b92f88a1d0f88b5fbff42a7fb90bd3392bb0214a904cebc757d96cc2716be3" . + "48d48ce7c158de0463dabb0b0681dc055083a11e96e475251335e0b4720aab13" . + "e82cf546d328c6355ce57cfb195a8b3f07d781a78169da380a5adf31adcd9674" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "910af3996463d04dee5cb5cffe809e19a9ba947b1fd73ac40bc1accb60e84992" . + "0bc1796614c3cee3010a75580e20b70f436edb29784752bcab26feba012528ba" . + "49c33c744b6f97de00a3c01f12563e405bbb0cde2367ee0288a4dc96cd3e705a" . + "28910b1aaf47742ac7b5849fd0c7b436c799e678f60b496f8a3dd77fb4a4e959" . + "d14b1c0f448df335cf580f4ede4e5ed4d60095cf13f56087fcb3767ccd0a141d" . + . + "a22a26a94c4b4217c6c0491e497cddedcee045011f5d08d13d41f5eb4514c684" . + "b8ed1e1afc6ed27a9d674703ef38f8fee52659e9f5d1cf4f08ff4fc4b83ead6c" . + "43ff21029f0dda19604bbc90a3e14223199db02eb06aa86925f606d805b8aa86" . + "6f2206c9c0455da64e480d2a551f35770f5455b0286bfdc6d5ec9b78df69f8bc" . + "f3478a3aef7f21196a2aec52ee34581ce5c6de458db7afbfb89b2816af40defe" . + "bbb0fcd3c176e513630ad62be215423122fa1a5a6472fed5af64449c00e12d39" . + "abefda32719cebbb720a2901f5ca90b24ad53bba7a637d0fea298ee54d914331" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "b0d018396640e7e2b754984089cf50f0df9278514684ddd97331f376358d3796" . + "f44d109cb29de3b5924c88981c929096f5a78ccee9ad7e460d3e30e9c4f6c4e1" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "4ae55a1b91971f45fb4969735bc40849c385f1d3af0ee10b477870f02295d11d" . + "67c187dc33bc36d25112e40aea4633c1cda571f68fb39a55a3af3d86116a9d7e" . + . + "27bb22bafaa8739978d69c7485311cce59b6603100bb8e779024adc1ff633c64" . + "1f529a38453eeb9a6036c01abde4f984f75875b4ac6914e4d71d158e812b21b8" . + "dec34e88e7399155286a07596b00f05b416e466b6fb1b1c823bf86fb27fa7eb3" . + "01d127d07e651a6cb0878da55c27fe14ff26b391b64ca6e96d32f3c4ea73664a" . + "b01de53bbd0fc6543f67558d1fc2091c27e24f2dbb97038fe674543cab7c47df" . + "920785108e60dc907635e0a2a5456abf83e08a07ce81aa1726885fdea206adfb" . + "0bb8fd4093cd9e46746d0e6005e567df9d17ad3f9233bce1295d93d55015a7ed" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "4b798cd3465cd40eb662a4d48c2ce8e3aa78017a0183a80a14da1f4974cf7547" . + "bc81076962d624ae76be04dd934041a8e1bf63f55ee3200ec1101e2368de1a0d" . + "c870ee7441c35f423c7ba47c7d40cc6716b22b27d1d79ac2c81b321a444fdf53" . + "31d642f7a9bb06ac8b0b06b961b490c16ef145f26f53aef728e1eefea49fac62" . + "24cd3ba35ca9567093c6c399e54f167a072be22f64a1f9b95fbb7ce70a626b2e" . + "a6ec3afbf0cb2eb40fe0d62ea4f6166e0c82a04abe2c7b4a8a726670322084b4" . + . + "b70ace102fd70a43af9e9f528805be84dc3a1b6f86baa1a30d282169ee53c461" . + "45115a71a7ce9bc248c2496195f1d830c1a8159fe2f2df5449d4baf91928d4c6" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "c2e7e288d9314b4b518f7894bbbeae7be941a59bdeaab30cd72481219eba88f5" . + "44775ad03f1772af18116c9aaa0b34adde312f28009e7060c71e01e2fd8d4076" . + "e23d08b8159da97320002e9ea2ceb13769d0a646a249fc2695a45ded8d7c7af9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1614754a3ba0ec508432ba16b9291116f70c777842e14e3ace3fd9c8f41f5810" . + "1614754a3ba0ec508432ba16b9291116f70c777842e14e3ace3fd9c8f41f5810" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "c0da785ac5b8b7da326ee14b57eebcf7ca405673d24b61c34c843a2c25c05b38" . + "4fe71471e3c0b7884806f2cd3b503b8f3d415c9d5d83462d2e7c6ca0fb52001b" . + . + "e057a7e1499cd0b79f6ae4234c5727b50e1315064f1533d73660e3c43200f534" . + "a43c66af26f3d54a1dec0073231080c75f91832b6c8279276660de12fbd544e3" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "b1861769989ab124a4a5054b81c40661367d448a98d6463404419f8854853fa5" . + "d3cfa154f6acb947c0afc0da514287194051b43757da84157aa31a98da229df8" . + "aa8ff2af1e9148df00a8b8e66b56c760377cd7a6598e944ef435f2c0dfc85a37" . + "9d11b666a899fc2f61ee67721593e8d47a7c9df2d34a17e958ab1330329513bf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f263d4ac779277592d748e89afd0ee569bc1e2931717879ae501fdc2538e7a6f" . + "f263d4ac779277592d748e89afd0ee569bc1e2931717879ae501fdc2538e7a6f" . + "49c26ed06c543b71573914fadc4a80dbbc3bda1913b7b64b97a7c2f902080dac" . + "d5a5a90786efdf6acdaecd3073464d9d26468c2a9fb63cf591a32ebb89485eee" . + "984efe139e9e83ff1001ce283015ba78fe6241e267a9e7a8c6538c5d750b6e04" . + . + "6ad5570b94f765802dd29253a2076aae18cea1240ac7df2d778429f006bc0831" . + "450ee820cae2cc2219d73340e7a38a1be04ddff8aa51f20b93b7034191ec5867" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "b50fe0774730198a68b8404a4a1dd39dcebf02f546e4061ef406f3e6c4413d5a" . + "de7093e889e7e76ff4d132cd7ae862248439d3940916a99e16fc29203693876a" . + "56dceec778ff5d2b4924708388f8125c439bd281b9a7c9278d381813c1cab6ef" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "64b0c06dd8dac7f7cdaab6e7a95a7143c8f8304062531d7e2cc3001660e64fe2" . + "e6a39e694b4f27e7f39e8f5f026631c50bc8d5b1001e6387939934f4b905ce2c" . + "f464cd14fc43c86fde02e2120e225c8a4397b766c48dc18a94033791466f0255" . + "a413312a2a1d31e2083559fa7366b98811b566bbd81bec64be3201123bbab6da" . + "a00dfd0ee5060c3f6112d0dd5ca18d4c7ab3776f6591d7d0062b446938c5303c" . + . + "6038c9e0be846151f4b860e1c3890e71e8df61cae72f6657c63587a5f7b12853" . + "d07f9bd11054a76585e3b70442675f599004ed93d6796548e7dca6d5875db3ed" . + "18a919c3149d059d47d177039a15c13d5c74325e69964e958c20bbe26e8029d3" . + "b0d86e92dae4406c599754b16c8a0fa6877d50aef19c500a5d3b6039782a6358" . + "f4fd1df02a3295536cba72d7d64a01d6bc757f9f7e81e79e56566e7aa8583b48" . + "eee8f5c117c165f7e94d3db65f959559ab53490abc7f006f3e79660bce352449" . + "ae4fed8f36247bf64d9f47709ea0990bccb6a2e028124d5d35d96c8e5b644171" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "00d5ab749f6dbca09f3eb5332969a95e7037bbc361a3444897123656a43bb28f" . + "00d5ab749f6dbca09f3eb5332969a95e7037bbc361a3444897123656a43bb28f" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "a746af4cdec1d65b25bb5e1b7da28611a44ad4f2bd1fb1507d8bbbec6863360c" . + "2883245583163835881c307e16371124362e3d703d84ae2d484bd3528a4afde1" . + . + "1c7f775f9eed7c12c11f8a8786b063a6e85d7df371e78b6e8cce08216ac67e4e" . + "559679a37f0052e2798a1548af7fabd5112240312330a503c7b238af19d54430" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "2f90e7d651a611dffe7a36d0bec7cae392162203b0d190809ba8d7a540f49024" . + "6dda693134961c8ff28b84d85d8c5dbc982e695bb55d664587e6b0de36ef2916" . + "bf491b7ca36061e2bd3ecf82d7f9e22645c346ac122e8b17e61f3072785fb557" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2cab605f6f6b1d0fca9038bca547e2f932340020dddff9aa8aaf44a90543dd33" . + "bf029fdabc9bed38c03db55b7d894df50f424b8b9c7c7e6ce5215b90b97e6579" . + "6b94ec0a068e82eb738195c0de02215f6cef514b1db584ce3c5924ec3bc9fbaa" . + "592ee4d0f271b881f47271c8542cff0eac7da24e7ad35ce4e1b345870fd68911" . + "f81332179e6892cddc4d9cc9d1f12541e7e6c7e80ff3ff560dfb099aa5d65361" . + . + "a93ba532d48e3b17bdc1ef6924003d7d8e3fb7aebd4221e8334fb361eeb246f9" . + "3c719d6420a8d10950b0932088598294e48ce8ba5bbb262f4c3ee57a3edc3e8c" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + "81c9d421f3a8d01a40dc730ee3c8259d21fae875b9ba88248763978d17b89a96" . + "9a1a7f19115c3b1307624d85b5d4ab9570b41b2e866f85c1798a866862a01dae" . + "991dff18a47b536759aa68993478f6a5140ca6ff7e1987773ea8bdf07edf6eae" . + "fb8718d482a3b018ca1cec43073d647b71aae387987ba88a74f715526e924dc0" . + "b7c1ccb5006c7aa09a8be98f15e35cd1039da812b04224194c60899958afc112" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b23663793cd3963dcddcd7e2a2095880a4db6db5996b792b74e23ae056299653" . + "60f6e8ab573a93e11dfec534df275d0f8e05bf0832fc0e4a3c7f81712b56cf3f" . + "aba7d4f046b6254c53ce796b8c4bb547bbc913f095f00f407c70d6f029285d97" . + "031b896e074526b22bc7f75af80ac66afe5bb4ba7ea45672532e95cd3ff47fc8" . + "16cee1fb33734a4904672f45f86f8d0d6f4a671b96c831eb193317a3dcf10657" . + . + "e21429bc381abe19d7694f918a25569ad77a3b9e98433e9abbed92da7c8b1c6c" . + "c563c73a82e3fc03534742ac4362b152414bacc3966cd6e760fe8a176005a9c3" . + "54be32bbf4d5a88ff40b381e8260cb76480255f3a334ce9d2688a4c06737f875" . + "245123f74133a54b80d75d9adf975e59f02840c62981317b976551bb4bf53a7f" . + "799a251e251f543fe8c8b14f3cfb8b8a6f4fceaba856d301e2db33fe668dc01c" . + "bd9e6dd99532ae3abba1fb97827cc7a8144f5b4878feebad0a29d7d0e5876593" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "88b1f6d47e380e175380769eb09703bcae013c30bfcd24938d34653020b71ac2" . + "88b1f6d47e380e175380769eb09703bcae013c30bfcd24938d34653020b71ac2" . + "9377b0cd1ccb7f12204ec96970eb88c5b4b212d2e231ae41c556fd591c4cda08" . + "2268448e15a652268d45b8b0e495e5f8b2a592e23285db7928ebb6ab91f8dac7" . + "b9f0fd25d0f0217a3a00021c3a93e3f069eaf5d914dd5bb894f27fb623235215" . + . + "c5f9a9493203fd7131fc375f94efab6b47bfaf0d79125b04ef7865b6c9603b6d" . + "75a327782ee895b9ba23733161d19c1b98222b9366f01b787646237cfe3ce635" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "04ad6499d2719167290de5c4a1e01a7a88e2fc5998e2a5f41c59dab87df77679" . + "25586b98411e6365d3147821377c2ca0a003f1c156540ae111adff4f08f17b0f" . + "4546830d7c2382af117191793fd6428bb1e1769db96b0bf124e54e3389224b78" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bfaefce285e4ed68b9b1dc89a0985f40642b9a45b832104f6fa02dcb26077fcc" . + "2a7b55d9e0befee89d3487c37ed1c7083287397a137d8c319cab771976ae5571" . + "19f5acddfb274fdaa5e2b00364054349b1e0d96a308924f5e53101b7e8c5b78e" . + "cbef9295401811f0cdbf46df693bc5977cf5378ef94650cbb45f8aa3bb1a4ed9" . + "8206eed7f002453c1c920f547d10148c90f62d1151aa1ae32d429d89bbb9bd4a" . + . + "05e12d8b9e56e06a933c0220bc8c6e70f31225ccca570f878acb071c182e1650" . + "1e8f904c75390077e30ef77b7018649924990ed5ff27b3c372f35c440cf2bb56" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "9a8e1bf07a8888fd4de185b28bc72473a9d83162887d6c13e6f11c013c3c995d" . + "99890969b04cc16c13da5d9cc0b1b4a198d18a2e16e5e9056587dd426fe920f8" . + "5af20b20045ad50ad2be9a64aac1e593563840a1c7910b567222673c7525ffb4" . + "d271f7a90fda0b010651c44eb3b18163807def0c8a122a364c5b4d059c5a8c91" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fb99c6ca692ad63e014548492b7139f69e59e59b55f9b0e8c4b88dbf3da9ddc1" . + "fb99c6ca692ad63e014548492b7139f69e59e59b55f9b0e8c4b88dbf3da9ddc1" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "f1706ecde57a7d2fc35222c0787007f17935b48d65b845d606f28e98e6adedc3" . + "e7fe5635b69df926b772d5dcac9ea66be0e75098ce4973f814739720f6daa55d" . + . + "8a7a4af914a7e2933b566532396777e7b6df804ee72704baea85fd6ce7d7e96a" . + "9917d664f7d73659c5621f290c151e383144b29345cf24d4a05a07c42af48415" . + "c642cbe7224447b157b496b6eed5d08cb37b77d59c0447dd0336360d281592fe" . + "8656cfe3f168f253655cdae74e50ec7b537a927887cf77a5c49770bfe93b244e" . + "60d43f872d058cbac0671d41580650c0a0a5519f941b3b999d74cc68cfa22615" . + "369e44f2bb9604e4604db5a9b2dfcd1c8bec3f28e98a7ec2de84d0b677e9ed26" . + "3202407b3cb7b8a67ecb79a891f47fa6940588c7fa7475ff15c3e2387d760f12" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "250d718340b733f4bbc75e6828284ab0c1ce545b15fd073b79a761f7a57e5277" . + "250d718340b733f4bbc75e6828284ab0c1ce545b15fd073b79a761f7a57e5277" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "273952267be8f32ea9ff401a7aec9bce5038f8ef717f5ab033ac317f78ebc785" . + "e9aff8e0c97d2ec563d056b1b7246d48a1268fc20e6ddc176da1033e9d176e13" . + . + "61ec5722bdf1b2a0ee0c7c62289f7dab731c4828cf28fce09c39a1f3cb5b7299" . + "ca21c4313fd84a462e94bec19b1889639fb098626b7710c63a1b6532dec588b5" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "b3913866b767c5009bfbcf45d8491df2eddbdaf81b8cc700ce087ff720fcb178" . + "907fa7a888489ab4bc5987e755b9bac873c17bb803049b4be6b8ca2d3dc17cf0" . + "3e57c6ee5ab0ad65b2385abd237e14558be1ff0e2e3c665691fb0f00ebe8c7cd" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "62bf9bfb433c6a47950ecda81e9653e33d4cb4d1618049024d8dbb3b21b10056" . + "62bf9bfb433c6a47950ecda81e9653e33d4cb4d1618049024d8dbb3b21b10056" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "d0918f59f7edc90645ecc9fad9db8878c73f02e535905fac4d5437bb97c3a638" . + "08046a7b583385177dde30492072a120bebc46c965160e58b9c12f677dbea49f" . + . + "2c1b62e1bdc6edd2902910bf2b01a8a05fe4c96f449fd080f42115a82a073e30" . + "edd9651a7cb9c32a017e4983b12e6e230e6f12a8730f865eab6079b2a2b4fe78" . + "55b8f22ceaa0fc69d4c80c88c8d256f80eab1433ab55f231bcff6c5f9d79e9e3" . + "e0862bcdd1381bc01820ab8e34c796b7abd5d6fbeae40025351a3df3db478b95" . + "8a3e78ac38f437a84940479bad6c241c84ba94c605513b870a6e328e848fbbf2" . + "7f7958e6483e988e5a66bde9961c91d29ace76745cc318ef6d8fd47bfd5cf2d9" . + "2178f810ffdf62bea8cf6b0cd18b3d96db1e5d4920e2ad0b4ff8ed0bc5cc4544" . + "0294769e916ba664d57ad1e4184c18ba754f3cc1609c892bcebe8ca6bb0fe582" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0cb3e2ba7935f44266a1c705c8ddbaf4de0d12da706fe6270e5737c49eaa35e7" . + "4e022128b10e865cc9297caf795b8f414240deca20abb44fcdc056aa420ebb28" . + "86c999b1cea373ff9e45c9712b1062708e26efdfb190bee8e9d80dc507c61c64" . + "406cb93a5ea8de3f255aad18418840cc766944e64ec23093bf081e59b8b9f80c" . + "a612ec0ccba4b5cd02723113f9a36f237ab953235c33335b31acfc546f630a9b" . + . + "bb262a2757cc3ede810fefc21108eb0a372937884b2f04c0c849c24db8185d3e" . + "8bdda513929f9356cd1eaa3e093a20f80501903085027b10101ab1975f3d3d0a" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "155b8ccb7dfccdd275dbd6cef199f12b69f3073efc297dad8674a48697c35934" . + "99d04eddd1c501879b3f3b430ce79061a26270211d82bc632dbf5ceae5a6a070" . + "cbf20ac8d037d75176dccf7f08268f7f4ba563a1b24e27d9e422d84c4a75bf2d" . + "de36005d7317dccd48163a17ff03ff8cbfcf56114b73fcaf8de354a1b47f1fc3" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "06c216d3dd0c75b9b0799540a31aaea41d53c1d1c9bfedb3bf1bb3609d14d4b4" . + "ad4382816e3a30f0f6128175dbe2edea38b31abe71994d9e601de53abd76f2ed" . + "16d080b310b9e96b15946332733f15ab89970f45d1362ed062c5a2915ec1a3c3" . + "0440e9f2381d0e15170c98b1f7d02a09efa6a678a856316d7a27e8ac46a0d08f" . + "3e2570deb81c1881a1ca457476f8680e44c8c4fa658e82f8559fa729ca7ad959" . + . + "7a6a62d6766da4b062e6b929c21d6004688d9db82734a2854dff9000e20ab9ac" . + "9c301c0c0a8f0a9220fe47ca896df61da3987fa268edb754c8c5844c4263c309" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + "232f6c00b23db1104953c90ce3b14f0b339458893084c824dd251c760a8d32b5" . + "0590115672319bdc9d8ed22dfabb8d6ccc53bcaa440de5a9cd1d4c6d311f1415" . + "d24347ce1a7be30ec486980d747451cf27f34f5e8e6dcfbef13177406684dc17" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9c7949ab91dcba5e868f7d900184fccb0cd37ebab798893b8401ba2ece34e757" . + "9c7949ab91dcba5e868f7d900184fccb0cd37ebab798893b8401ba2ece34e757" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "111dcaa249a149b0a409d42937a1df40aba297bbaf2f8215d95426380e282a20" . + "b42f0130523e43d285bdd01bb45ceb50c0b36a7b1eb1c8be6ae3311853aff142" . + . + "7c6b9aea925ba6a3294fc3f23bcbd539b39fc8c0500f89e55c5718579f73622b" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "f75701893ce1722083bf062f127a524dbb86e3abde5c917831a2f484cdcbd343" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "f1ee956db7139b17271b49ad6d7c9f965716aaf03f471fcbf91f09e337f425b9" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "215e06e6dc5c903f0a492b4181d94579baf1be209bc28188f6f829f37eca2d9c" . + "f50ab1dc8a6d65e278cca9c743594a9ba98d137b37d2e4f3b43b6f972064545a" . + . + "9f746c6843e17ec2e1551917a258528e0c5761199d8c118e66a9452c72367e88" . + "8571309807b7661597343ae87726b8be2fa264bc6cc0f82d79b6200b0ee01d3f" . + "7b46c496f852fc899df1a72813ea6842ffbf43966ed814850e86b6f0af182daa" . + "914f658ded2243a6c830da92f0e387c660f9981cb59eed00e7a3c7e0f3fefc15" . + "855e6aeacf87a59651488a6dc521439f1fd9e310d783e14859082a7b1516a09a" . + "309672a004a9405a1f0666fb7d7f2ff11dcde3e94bdd5a04d84431475d24a752" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ac27384998cdae020acbd7b11ace737243990e6e911d34fbe76f939dc9cfdf2e" . + "a5ba954c43bd35c6f77f94d47eb4b9f0ee23996bc68bc2a2cde991e379747f1c" . + "2ed808e6313086c928d600397e25f8199482103109186059bf037617398cee72" . + "dd2147e6414e2814ec549f950415e5226cfc860e0c877f794003402b01cf18c6" . + "09dc427496d342ec4cf402755970da491753118deb07e2417a4be0cf312625de" . + . + "41b6bd99222353ef1f46a08d64f33c9f266d9e0027ac292bae4650c93811241b" . + "1ed512d4a5141825bcf141274a0f5514ffda4137baf4e8e91d9271e1ebda79bb" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + "5934ed58f4999b5910a9a43c46257b09c2fc7978f14150336f28c6046bcf4c4a" . + "d916e81fa9e19717e3d043b4f8f2330156e7c353632963a844907e20b71875ba" . + "5b2dc2e003ed5f6b15d4985ed877784b5673889c714be87fe5c83f8d90d4f698" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6875229a06fe3d7f95c646492eede7a6e7b5e9aaf4839af2816957a5ca2b6fe1" . + "6875229a06fe3d7f95c646492eede7a6e7b5e9aaf4839af2816957a5ca2b6fe1" . + "8fc24b1243345a2e62a089a0a3847b68e663c111f8f7d0806ab6f0ac27395e4c" . + "e3db34f394e9f9865f1b75ab735e4b6b09134068a09d356b7bb73738ae1fbc9f" . + "0743ea2a2c3417f727238f72e27180c75b65ac1233f5cda0734bf8747dd5e67b" . + . + "575bb6a73bbb8e2a5d06d1a6798c6749b7f06eb1fd2aab360a5977e6130e6e08" . + "2a6361aed867c1da652053e1c10f3dcb64aa80a22a1672030502aa2e024a8850" . + "5e2aeadb587dc88db24a593c90de8f30590e972f42f0d52f86f4d5b120038cc4" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "7971cb92825c97c64d06763c2fc7e58c18013f9bf8d0d8f87bdb5aee48cc83e6" . + "c692c0f0518057634215adbdd1c38fb2dc0b1d43606b7d6034f17d70cf3092d7" . + "6a5d34044635f05774066e2a416de6a5a977be5411b6b60523302fbbd850384f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a494af50fb1df16888b9aa2b795ac2b4c9305fea1a2c84ec0644cfca8048b201" . + "e9418b1ce8f7f6253ce5a00acdda369284ce91afab5443b74a4954f5bf9a0a5d" . + "b50accbeed41aba348dcec361065f729c106310845b14abdb6ceb2927668835b" . + "691341eee901c6e72d7e385e2abf812c8705e72bb409e2f64ca9f4338ed2157c" . + "eaad6dc613aec7afafc5770ceba2d35096ffd8e381e1fa839a71259d843aab05" . + . + "7c06a6bf82856416c3d305dccd37a3383df6d7c11cd8f1c65d3d0c7f0805ce13" . + "adc28bd7bfa92d821e64b6e1ef5dd7cd3291ae8d5d5b2ace01f5ad6cbfbb8141" . + "20166b30dd3d68b688197184fc40c9523f10f7d66c23faa013c5f8cc62fc7ba1" . + "6c03987a8b35e51edcf449b7d1b7408e998f7acd9041298192850b0865090c38" . + "e0c4dbeae98a13e1ffb3c443f27d134866b8738f42ba9be8cddc429d474a0b37" . + "5cd8868cdbe60e9e9a28fbd3a4eaad09db3293e5fd55733a45d821326383e768" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b1e99729b40f782f51a9cc2a6c3baa920ed6162ec22fbba4dcfa647cf4c10cfe" . + "4fb2b41dc10c75f4c84818c25a9400ad5ebbf56a3540010a70e707d86e65ca82" . + "744b79f180687a976be4f98c6a65f0f10056d3494091dc506734e86e4e891661" . + "f30b6f6e7b459220895f7b16d63ae219fc56e7406cb395c9a8f30b8c6536371e" . + "8c945f09010c87dc24b1cc197026e60f4d07b5747cbd20bb71d7ff46e349c9dc" . + . + "e3f6fc8debf5fbe4d52129393d0c49df524d3669800030e2f21d6518aedf6471" . + "70b314c169fe2baf384c4d47f1e3a62b9c86f5f7e4524d51fb85c28932d2fc9c" . + "0ef67f6f56621ee6f1f16c2d795b9b4761fdfa3174177c2242f76786201142e5" . + "a2e7e622d9a670ff4b49b56f9a75786dc560dc601551c1c18497332f2757ce64" . + "2b46926ea37dc97301ceb6d4422f16f163111175057ea3d46363cd2af32cdd4c" . + "2c6dec09dea0e11ce05e13bab4f8fb42aa839c61c3b756329b247c33fee26641" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bc49bb7336a2eba292da34689d56f63d444edcb6c4b0b4fdbc8755b218f97ad2" . + "bc49bb7336a2eba292da34689d56f63d444edcb6c4b0b4fdbc8755b218f97ad2" . + "fc49b68379bc5f4b15dcca679088b9d7319f1000847f356de23303ce7e30b149" . + "a54995e9134bf30b9f219ca9fa3d99a16eec2c818d9405e1f34005212dfd67be" . + "9985b9c42105d006cb9d8e7768ab0470dfe6059538c4e8a1268bcec0067ee5ec" . + . + "237805a27f025cb64e0b7b6a2c9eeecc10c09474d6b071234ca3ca82b9eadb86" . + "2984d1607473deb6d6e0b5721f009f5616d5b17507626100506b3b73fde44890" . + "153d9cbfda37228e79442b1b8a8799d562868ef6d58f93f6ce94514ede25fb14" . + "8f4cf5368f818ce7928d105fb167cbb1df3a62f556470860ea35550319c5abc8" . + "5ff00356999644fa7abb0c8ada255feb6bfb25a22cc20c89546e39b842c85137" . + "dfc8f2bb4ba4bc99bbecf44b9cbb6a2da2bace83345d7523ea4823c0b06b3baf" . + "7318d8f67a2d2de2146d2366285ba569b1c8dbb1aac6a13abb78b86e46a918bc" . + "35056391c2a7aae94bcfa73ea1a243ef62e88ff494e8ec66078c12a6005c7b06" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "169dae28e72d7f00f7e23d155ec491caf235811fc7e8d6d7061c27a2ff3dbba0" . + "169dae28e72d7f00f7e23d155ec491caf235811fc7e8d6d7061c27a2ff3dbba0" . + "5741f60bf3ba3fecc81830e60193b6775b4c6f23344f9764839cc5cb0a133ff0" . + "960fe4fd2fe27b22cc60d48862891e271841cba4be0d30dd48d1f767fd758096" . + "5000ef0d62143d371a7e53809e99e5b038c02d34e0b6ed2a1ef820befb4cd355" . + . + "d0f6e11479bf4952ed22f73359693e42b620ce069b256a73b1770bc39cbe29b8" . + "996a99a6cb6900f186b9845c67ce21e3337798c8ed0ac97a0205691f4b5efff2" . + "508714dc9768e6ac2d81455f8bba849da0e95534a4dc3c0ba8f96cfb338e1991" . + "cd97c78fb21e8d6e836089d943a7367878f6ac2239cb74d5c7092d3c12c5e18b" . + "11cb3584d3218d24971f63a1a6f7b9510ae7c501aae3c6fe25d656713c8e9f63" . + "27fa122d103db785fd4b4e4b7ebb97076cc611b8e87842974c63a62118c44817" . + "58c55b1c69430c6c5894424d6b17a659983f0b8d08d1ffb90c553770383cccaa" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "48e17f29d4ea1e8eb4b65445d5487b3f22b4c0137a7aadeea75f5cb931c29c46" . + "3aaed0101dc9305721db1f4ac1937d36b251efa3d7f564654222b3f72a79e872" . + "da15a125ce31d529f0821fd620eb1b2fcd5b3f78007283355ae601181d2b0e1f" . + "e9a9d14d527be66e23b348028c18781ac1aa53f4d36b6b73e32d1926b556bf27" . + "2c2f5be819d3216322edb720b41efbbdce26e3b450e81ce03c6ff1f53d58db96" . + . + "83d841fbb1f714c438e5d49737d8e2b32f89ac48c283db9c9b77ada3eb6bb718" . + "2ba9f020ce64957330e08b25933f29c0499000b315420e8551b4f3a3e684142b" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + "b0e9caefe2d7d085b80d9bec3a79d0c0594cc25b5b3a3cdf36ea13afad34bcaf" . + "ec5c0b5c6d8382eb2f7ae0f73ceaf2482ccf5f29549815a70787f9333eba07ed" . + "3239143263645a30f31841a7d871d8905290371b4354250712aa041ef829ff86" . + "ee6e6b94ee269d5a1d2bd2084164dafcc6168d94337492d11dd02422d8751e20" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "6676e220fad8d98f7fa64db79d6f955d0f3b4e232be7ce341cddfda2912ad417" . + "35ec3ba4d57c729cb4f0f65696307f872801251fb2810ab11f83d5b361e430df" . + "5013e0453185a74d4246fcbe366b5535b190da2f9cbe5dae51e54a5bf0955f30" . + "83eb8609aaa9013aa32288405e53e2bec1b21e214d4c30eef8f8d87d889eea53" . + "40854232bd5bf3afe3a466c62ae96450aadf1f00b3fa316b293a781a4e3c7ad5" . + . + "8f076fb27dcff815f65b2b80e62b4decb9063e94c8c81570965c6b56a5cadb70" . + "5c1e090e4780cbb78553d4374b6c1aee9fb068241577f1f94a37fc878af16eac" . + "508714dc9768e6ac2d81455f8bba849da0e95534a4dc3c0ba8f96cfb338e1991" . + "a849e37435c39a5058333e344403df92f02beb33e908e0a166e9f2a11e7e897b" . + "4b18bf18b398c6d4eb5ec9aade9c24cbaba15d778b832263e8d339d00056bdb8" . + "601e70227e34be1344bf8b43b7f0084e0f4fb61a016ccd95e9c4176f15cfb3b3" . + "36f5a63b54a9bfeb487d6ee9d8526c6c4820abe3d65014e348c93478970f8239" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "8a28149cfe323cef03b054f53d34499432a684abcb085d5e49305228f9ca36b1" . + "81aaafaf091ce242fb52ea7c999c9bdc09542bc55791c7caa5230a0726e16959" . + "271e36ad16e1b0324962ae38bc0cb778c0d733d78f91d7c871d3cfec389d8432" . + "3efbf9ab07255c00a44f589a8cacb9bc68ecdc2d0150661a9009fba586e013b5" . + "4addb3b2865170d6e7d9a624293aedfb60219868f3258fc43553671c468bf983" . + . + "dbf2aac389acc462177663f2025d1aff3e462ae78624939696ca7a0a109d4652" . + "812dab2322b35abaec3244d936659b7517dbb490f99f40f9df6f51ca214de772" . + "bbaf699987824c322fe65c8d6ed4ca0c3829751beb4df4744843840df92fa76a" . + "7660a1f55d599281eae759be71c2324775a4119e0dc8c9892cde23d13e152f47" . + "a76bfdd896dcb2840291ed2f77ffbdceb442982bfa5823bdc88d76e986421cb6" . + "bc67832ac92b09500b19e2f86f70cd311168cb77fb6fc2843aed2bc825b7332d" . + "02b35ae708c6a098e6d3eb8bc6b0587fc60405f29b26b17c42cb3f30b94668d0" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "495a39c0eb3caf34885127fc84d56bc6b8628813729283aad1e1b33a00c8d922" . + "623749c4249db915df9a39fa94570faa198c1c5550cc71e9a8cc4ec0d40b4489" . + "65f14e6eff43607ccf88eebf300c1ea848c20600624e0d1eb346773f3509c1a7" . + "7ec4778ab4d1b26f19e6d81f5fa3312e6018cd22535fc5086100d19945d81a8a" . + "add5b1f20c033d2a7a528f4f70e00d7bbbd6ddc063e0ca1344aabfff30df1607" . + . + "089435b7b6e553a1164849cb613ad5b90e9162f38f59d469ad0133418e58354d" . + "83fbaa74004a8493fa5df6ba0ef4e2425bb97169374075f76b37714608390dd2" . + "278659b6bba5ad7c9d3c7ceb213768f89eeac09ac44565329593f7bc37d857a3" . + "3104a48e4212d0eff2da51d6e8bb08f3b8ba43558c6461f01c3540bdb391dc3b" . + "e0059e3eab66db84aef594ee5c5b4944a325feb4a9ed68e1e97b779c24733093" . + "21e851a159aff3711f0c31ca042e966837f0a8404770993a12c9d53bf8761354" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fee80f7a994999a7373fe89b3790021c8aff4355ce6077a557fbcd00d7887d8f" . + "fee80f7a994999a7373fe89b3790021c8aff4355ce6077a557fbcd00d7887d8f" . + "66f1c9ed6856bc51158da27509ece6bceab2880792e3db6123f864d40ff0caf8" . + "6a617e1f600ad0be795e354f077993665b8359791565cdd9101ea4bf141bb703" . + "2dfa06c1358564633fe8e3ceb06e32adbdd11d8af3e859168354c578cafb5362" . + . + "6d13cb5976197e72ae33523bfa062f5a0a05a9128baa03538e50fcb738cc62f2" . + "3880a522485a00ea8ca78e690a55041ee100aacd1de0556b3ec8c5f85e9c4fc9" . + "d1d6d47df90abd41e5233cec24ba0ba1a02f056e449911e52abf92bb91afb65f" . + "cd99cea8b7d7ccaeb7f60872418fa42972f0459314adebf2645b22a1d306b087" . + "6d13cb5976197e72ae33523bfa062f5a0a05a9128baa03538e50fcb738cc62f2" . + "a313e36252e15979e1188999d7389986d149af3be43c16f349907b39d1bb6fc4" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "177c22fb11c7e17c5aa7b74bd930054b9fa7906dc78117bab26e790625706ac2" . + "202213bb23ecf8dc788f1018fce49e180a45a54cd74e55c982d90742114dd0fa" . + "832a57e51cb60ab7d5b7b56f6f9bcbecc10d03322421791f83444d09a729d137" . + "cdfab15aa59dedd6ab7330eb2a8464262b42cc91226cd16726a8a13e5b4b80be" . + "7b6ab3306943cf9ba06ebbcad98620a0b99e262ed996a754ef2ff6ab4133a898" . + . + "f721d237801e278a286ef918beeebd21e1209fd770fdb42a3fcacd1137f68a4f" . + "eb8301bbf1c68c713e6762da934c0f2409e07dfbe95f3706ef462753d4e8fc9a" . + "c04ecb39182dc99ae04ec864636738e2a6d9e99f01ab4eda3271fd3cc329a7e8" . + "10ee811512879413e2cc432da46aed8bc0967f0c8eec00a0dfd50193e2947434" . + "0af48356b65d46cd9af5485ada4fce884f1da4ded2496ea73facd7452f9e79dd" . + "f1275772b61b5a62ff3b65888b9b5a1d6156f7df62bade44ab16772e3b965c77" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8830d802c7e6210003f48e749b7a4ee3d788e17e3c7f06e20564a39ed4631f72" . + "68a91292953c352502c41d6530b8f01b35f702a7cc0a2130a66653460f715a54" . + "0a14b674527dd969ca0cc1bd9a560028025c543d0b8c2323012c33f2fcd28400" . + "31f5a95c1051fc6e29cbdf543f12f5e26f494a0fa57139a71f3fc78dc8a3dfeb" . + "34b43166db9eca551654927bd488f2552b6814e25e949a2c53a16473476544ae" . + . + "1ebb87d29537a403d81b1bdbb209881f3a9674ed23904880c42117a3662197bc" . + "9962d0603649c4d3e155f4a412d0b092f93bef07d5503138a9d2da12019206a3" . + "ed2add28acf0086c902c2053eeb7771304dc1b091687518ee43c3af6c4a1edc8" . + "ba418b27d99a90764567c9ba0574197e03714934cfdd9eb6f6e0fc0508c7d56d" . + "beda02ac756be630d0648c775f03bd066ff5cb8c47adf7fdf997183b9ad113ee" . + "f953011068d6f075801a8fdfc76eaf3c4acae809b970a6fbb32f9ff780d41c43" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "162e229354bb84392ccb46c5213cd6fb9bad248ab2c433faa257278b9a79cf4a" . + "bcac60b663bdb51f26289e525d8f41af736fcdba367ffc1b58afcc8fde82b8f9" . + "9adcf21b6664bddce15eb6e4c1d69020f0b48099f4421f24df3cd7c7e5f5da0a" . + "0c103fc9c44d15acbc88063166123a81bf83d9a421fe47fa451107b41a0aa6c9" . + "1db9320b7b482627b4fe13e6a9fb6640508edcd4e1d3bb8d436e0c0b48474e6e" . + . + "98fc6cfffba22d97f6267039ee3a6c11fcd5ed3ce8e5d510eeaf93efb8d63ae0" . + "f0e0e8ed84be2206f78bcc95f268281e0ac8d998524426bf2d1f3c5ef2b06c75" . + "19f7f3dd777bbcaf0cc491f6f8adf119a8710a210e81f08fc548bd0567060da4" . + "2a0d7078aab812e568d6ec47ee608e17e3d0453d91e722166def6fa33106c9b8" . + "f1bb24f887c80212a0219f04c5e25bc2ceeb5102ccf63b94515c013095072b1d" . + "a565c968d708ac30c6a02425b2048eefd76126cc59f68a6b78ccb286e530fc9d" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9544b6ae401cc48b658b5717accbe917ebbcac1ef2dfbc6d38a54277a6c12b3a" . + "9544b6ae401cc48b658b5717accbe917ebbcac1ef2dfbc6d38a54277a6c12b3a" . + "6b0bb66375b9ecb8851750f65c7c77d40a89ad48cb3f10c899efdff433e55ff4" . + "63bcbdf9ec30ab1008e7c20dbf91774da3e100b0c834796240fbf3c234fa81cf" . + "fa1ae29c58737402d1dda3a12b150c1d588cb37bfce5ea4d571f3a13569477bc" . + . + "6eaacdd6fc97ac4448274d956eb6451097c3cc3237b496024d24a370a8e9bddb" . + "2601fdff486964d48c3d0fef7aad48a6616be1c369582a2d70ce7b03fa288f54" . + "3104a48e4212d0eff2da51d6e8bb08f3b8ba43558c6461f01c3540bdb391dc3b" . + "45c68a00012cd1492c0c2e75bab3b9e2f31cab4c74084d4478eb633af5b477ca" . + "463c12ee6d9ef77d0321dc3ef38d35b75f18cdf78fdc2e172d54da644a4552dd" . + "a695f7430d81eedfb56a507e9d41d832be50123514ac55aed9f6928e21d69ca1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6dd90f14e277c889a499ee5fa215166bbebaa2087831562302d370d33ad75f1d" . + "dbf766e0131f1aca59412427887c49ee182da27378ba00b0deb9c147c46fdbea" . + "a19c4b809b83af5ef71b70dd27898a3210719e238a20e91a0d7e3eede3136a2a" . + "d560379f67cc4b00e2c0aa3c0356d9782aa1351f07cc550da46ae3db7cbfba17" . + "eb602212078f633ac4c728a35da55b41db644288604d797968e68457e734ebf6" . + . + "9cf5061184bd7ebb85a44470d9427bde6dbaaed7eb7d6dc057c45225571cd6ba" . + "c714bf87afa1fdd3d04f8705331d3f4b751db0e37b8591c7c61a023e0e675c56" . + "89cfcde24f7bf11b37070a03edd8a4b79282ee645551f6c2767bfd342f9bc37f" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "04e68202e283a2c74a93dea77b01d79631b1e89c97fa604f5fa303c7a86ccc00" . + "8ded65a3f6ed4a5ebe08b14bf070a91ec551fa7806b02d59c3be19e25f6d4202" . + "bdd0f7f009fe4e2f8efaea71c6a055f4bd758bca3ca904a75f618d902de68499" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "812477780a258ca87de537e9804b6adf9767f1e6e399841dd9061999263e6c8d" . + "23e15f208c9f1bdc2520f92b3872f17322244c011dfb9d2189db47c6db6736cd" . + "7693d9481fcd8240d68f9e2d2d121e07d1e3dd334b0ad93e3c9aa032d0724390" . + "ce422635ebb17332c571baa668e27a6d9dd37801093659941b40c37de7f6ceec" . + "872635dba2d698482dd2b9ae97f96c199708f1ff646098b6cfe5fb75aed79c84" . + . + "bb70e91ac5fe2f19fea0bcf08892be117f18466b8385fdb724a280aad38d4346" . + "cf747477affd1ec2814f28571464cfa870abeb9ee1819ad52c2f6705d010244d" . + "58dda1a90f1969937f69bcf6a06391fb2d7253744f35efceb609a1b16c54696e" . + "d15d24b61796de65be02005d81f1e199a45861265ccc75b9e16afdbe6eeaeabd" . + "bd8dec395454ab1baf49d16b8aa664f3b364ed5ca73227ae514ad26455fbec1e" . + "363c23746025fb2302630d3741336860f2203e2c18cee4e3203496483c7e7da1" . + "1dfb275dc002587eadd76051646bc385760499a9c2a4f7e1cf1415975e80fe24" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a472484a01246839c08057c77c5456d6054d80bb4acaf12c403a75c3d1adfc2" . + "9344b59c20e869fc2a08d52a1853b575b4f8f42e7f9cc9e257f36c59b71bad0b" . + "da85b7c53352c254f1c8ab2503abd4560a7b7276288bc90bff4d1b094ce69e49" . + "26f0efe91c94184ef214cd64372c30f38cb64f667809337983eadb9cf700da2f" . + "eeedfee3779cd59ee2964f3f85c9ea86c97e052157abb25ee9583a64c9ebeced" . + . + "aa01ea213983be16bdf3b9c82a824b99b6b56d4a4bcd23f243d421df4c62f8fd" . + "22b43f182d248523ba6ce2d6a895629d455afac58e199bc6ec6a651deedb4e5f" . + "980674906345fbdaf4f3591983f8ce3562872aafc7b97266185317d7f9f7be39" . + "8443370a1bad3751b9a3c42e8cef2b42ce5b4f288c8dad950e4ba1e085ccf16e" . + "6285a5a41902708ee1049eb9f0742356cfa0eae55840a653fc2b67f430e3f056" . + "29cf346a9407479e34962f54d192f76281e2d0d508d5ebe9c7fe62652222c4bc" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2480bbe18fa4f6381446acbb2402a4649beefdbc56c4e4d07ac4746fc247c814" . + "2e094f9d8aaa565cc271af68a5d31be6fc833922943d398d45ad5b70de9cd549" . + "a40f8acae76ba042cb5f7ae7832e79bf2442e308d9b4b1f746c76cc1935b4cf5" . + "27115140c8619c73ef42958c6ba38f8f64781d51e78ebd4d75ce89d539564e0f" . + "778b829f9d85ea6fdad23e7bbf4823c4983395dda90eb93283d6bcc1635bb1c4" . + . + "6fdb6fece599fbd924f32820eb3bbb4c41b53a7fc64223c2435302ba33f989d8" . + "122dcd943111129be0ace1c6940503a92fb51d3a98d162e1634263db73395d1d" . + "f4b953e614087bc04251bfaa0125b710d2cdb7f698836a5a8dc3fdb58c73789a" . + "93635235efc768848a09bf57ae728233266f3415deeb565d61625d9d1024eeb9" . + "e0d6154cd5557a8dd0bf8ae2fd285ce61c4223b470620b0661f479ca09d36b87" . + "a4049f1c08136da630424ec7d4c2510b460bc6e91210d76789fe1ef4d30b34aa" . + "0907e66e31d5b1daa1274a0f8c77c956af19d948796d321708f85a50e4ff406b" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "999ac0ab36527226b5b8c96fb55ecf966db053d70dff8621cfe523d5916e60f2" . + "c3584d83762bb31ecaf01bcb788bcc1618c1c3e8ec2d52362beabf72daf8d4fa" . + "e6a76f408df6bfe8e7a47fc9a477357c95915681384983e7ce91aabe4d6a9516" . + "513b99345780d4ea43f6a57fc830a592069c7e689b7c57149670f541d4b91058" . + "262eb806dad16c160db408333f9419fed6f906611d823b48315c12727955577c" . + . + "4ec969a71ab7e11d83f276973537d36ca4f33e0eadad45ec521aad49122a44d3" . + "c5a56ed20d7da8f89965a9be26205350ebdd410b0f0cbf82e7c8cf624a9298ce" . + "e241a5d595f8af341f6e702aec78170b970544e7fbcfe99a6548bc2545bf097c" . + "9567c5c584d5fd050a83e9e6959e061a6b998ac9f9a988576e88010ffcd4bb85" . + "2b712f750c12bd195e3fb7feeacaa4377dc9cee95e13340f4865e23377222efd" . + "de7aa0caffe7cb92b04c7254fd87861faa4523b2a11776434e3a56426839f4d1" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a4f609a9ba58738961867bb2bf2830ccd0846bb67a594843c222ca7112a5f569" . + "cfcc9f913ee1da571e5f8738ddecb25ef89464058c4baf26a619ec34d2278d10" . + "4a0c037917d3a8a6c277f1c48e978ed8d5a998265010439320078864e20acbb0" . + "a21f0af76b822f0e4c93b7684ad38b0c3f3b4edc13b85564a84c70ef3758f021" . + "f024fe110451f7df6bd6d11d3a34e022fc0514ec807557dadcb624b080bec2e1" . + . + "85f4e75df1feb2ff1c709f7512c7dd2539fdaa3accb79bbc2a6ab4dab830b5c3" . + "e33573f27472d432e617be42615e0ec212798bf08d3443523668f85f545b26e8" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "eb68bd1b9a4ba8499eb00e6692678d2b001ca8ffd5948a70047792a8096a1ae4" . + "ce130fc88d651cccd8b5a80c41e9f62782d102694108a1073c8fbbb685799195" . + "07cc8c79eb0a117296e888223ba18ce92f909b2c4da7fa1b9795609126a35c33" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d5e3f78367ccf0e19a510b1542a25536912d698960f2fbf0c952c2efcaa68afd" . + "d5e3f78367ccf0e19a510b1542a25536912d698960f2fbf0c952c2efcaa68afd" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "32ea2cd997cf9d081ad2492bd4257d203413d2ef2548fce5b50680f377748115" . + "d1b81be1d85b351ac3773cb92725f5a71bf54e23124f82b1e7b6ad5fe0911aca" . + . + "6a7d76940f9f6661673947e111357f3fafabbb253dcd86e8ddc59d8a665acad3" . + "f73b579d322562c22476f9dc8248921889acbedc11e5c1508887507ddd74afe4" . + "b0d86e92dae4406c599754b16c8a0fa6877d50aef19c500a5d3b6039782a6358" . + "72ca580519d446c2fac7f21cfd34ef1d83bb4d6ed0a98ff4d22455a5946e9672" . + "96ff77f73f83c815b67cb759191561d53793369af01dd88c137624e93f4de8cd" . + "0fda569542d60ea8c3b5086a651db9a180fb8ad939ee6232cda199d7b325700a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a0b1434cd0fb8d2b4bd9003970fb60d4c77ae128568c32f8b13fb33c8751bb69" . + "7ba553a65cf6801354b7a479f07f05ac3e9071d00f1887af6b7ec147d9d9ad2b" . + "de393b3f21f4713df683dbf9fff738d1f841409a033811253d93f310f227718a" . + "efb4517cc117e750e9fec8569b4adfa3b13c68fe6c6391f65274bf9fbb645174" . + "d8f776bbb0d0f917b165ffb5f15d4dfccf6c680b713dbc29f67df8b0200026a3" . + . + "3e35755176364826bf35df123da6c53de6696633531e507538821114f5e93c7b" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "a12035de1e36ec87be2b66686487c5555437f3214469e905d13cb0d244564137" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9249da7be52b83c0870abe3b4155fa836a108e458b284b0107191aa862776fe5" . + "9249da7be52b83c0870abe3b4155fa836a108e458b284b0107191aa862776fe5" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "653b7a18563f9a379752196084105b8bae3f3d6e44fc442fe83d78602034a41e" . + "138c198dcc242e99df03ae22e31d9d8ec7ffc7582d40ad0b7fbf0a76129261ba" . + . + "8008cea315c1ae985a72dced4de0e5767d89fe3b39b3e0ca47de8cc35fb9748d" . + "3129c8c6ad484aed8b568daf4b0a0f81e8043bf6875b21875d488aef46a7cfe8" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "17b51194b3ffb93ef854ed393e2469c3f9aade6db89752032f42dc4123dbe254" . + "8008cea315c1ae985a72dced4de0e5767d89fe3b39b3e0ca47de8cc35fb9748d" . + "0abd870dad3739f2e1eadfc68861c6ce8e4fc4b4c9c0806e0052cf341fde9b54" . + "241beb2636112dbb4e1d8166a524f6c43ec43d9d36a5d8a05ecec0f26c422753" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c5127a20b544ee618ebea1d0ff07f6f8cec36263eae34ed106c72d0336eb8857" . + "e37a4b2a8cbaf9c85034cd1e4ab8e8b371873dd180f6e8ed4f00975af41e9092" . + "821e9d034b3d11db8ba2da877e20de01053529a10757093c2fbc3ccfac4816c2" . + "6370064d4d17b289356c971602d58ff42d081abb52f87612cc37cf3570c49757" . + "1eb563bc15977a856d64425d5494832d61113042dc508b4f8dbdcfeed062dead" . + . + "83af389085c8bd53022b8b4209d76289eaeac401f75a3a0cb7fa1787cab13df4" . + "28d840b208b5d8633d9c50ebb02aa2ada9f8a716352c0f8e9715037b01c33298" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "768bc869f2cfc3e24ce1a106febf2e85737f6bab18417f13b0fd59db0f284f4a" . + "e2d583645e9c9c38e9a7b8f7b89d1867bcc5417da453671eb96fbab760ade0cb" . + "ad1fe8c89fe1c18b99cfbf9b3f58416e66477e90ce0413eecd689f5c4d9b1492" . + "989ccb0a6c7a94649d6bc37341753f965410de9f023fe7828e11ed62b6d3831b" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "2f74745d76893c1f628cf5c7db2e415b7be5ce04c175954f10d86b5e359504dc" . + "6fb8e221e8bbcc0fcac8491bf443208807669587d82bf05fab65254b5ec3a4c8" . + "4c506add52ad15c00348dad77034b1837bb576584fa0c2736a4cec4e9287d629" . + "24aa6ffd910aa764767e7e493eef4282f7680ce9b3215edd41b541419ca078d1" . + "e20c1e9d14b0bec7bd41b91f59909173ac61bb53b253adedd5f71ac2514cb017" . + . + "fd4a14a667d4f446d3db9a538b91c20d6c4bc7dd8f21ff65f2e38c8d6e750260" . + "c6718a4da454b59df68a1b2e9e1b500200bf75d339b9234047d0264d68e3e297" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "d3f8d8d770b775a731f94cc40d81745b7ed83b748368d3d7f96791c1ce707041" . + "08312e152055e7e524728f1fa4cbe247c6377e851a2dcd02abdf1171e0b2e999" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "6431b001e11523efa22dfd512cb98b19917d85b04701d4ba05922398fa8a90a1" . + "600b713a3e63ebdf98bd46ba7bda8fd40ab27da93220278130ff17026d92c6c1" . + "3338dd192b29bcbd0df4801b017cf7ecdc07b31c57497e99d464e3bf88fb2f8d" . + "7e4e960356c640cafa98663b5234d0d5172db9034fda3421aca2e34fc0dc55b7" . + "9d4a476b4c398cc497269d20e0d4ea65b0eb04ed90591f951fae31cfaeb681a8" . + . + "6f0d370d0d273277928a31533931f118500f9d3df1084ba0d89ee2c18ba06696" . + "bf77c9fb8cb14ea9ff520355a63aee0ef19137b28f007733d1465b12356f73af" . + "027765b8eb7ea94fd71dce0984204350c4e96bb9a58f6a5ebde1b3dfeaa44a79" . + "5240fda37fe275f38ebdb3c6a269755458ccd7a015f67c71ffc7b1b2e98a4faf" . + "bb53abe5736705d3efad147e8f8e090b177f5ea5cb8f92209530ce3bfcaad3be" . + "27b249e384824fbc865a13ed59b355df6eeee7e67ac013c71416bf60ab3a0a93" . + "7b29930a983c69bd3f457f966addc473888f6ed96ad871b6e19e748db099931d" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9e132bcaeb5e2cd6b2f6b8ca0a41f960f0f37157b0b52692588673151b742083" . + "4543eea0ceda26f3d3f807f10bf5ee5cbb8f81356ba22e45e7e251f0fe1babe4" . + "09ab52b556ca4e8f0a7083eb1f14b80364e97df07df6854957e30e0a130d2333" . + "40eb0bf04d0f747dd5d77a5e337c47b318e9c71aae80d288d8c41555f8062cb7" . + . + "189840229b637b3358f9f84d974a782eee98c9ec70123f684d630deed617bb3a" . + "c321013b3ed2d8bca6e0968fc0ba11ed3f50d880060e3ffd8c537e4780b1e00e" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + "74c95e41288639019a3fa87c8ecc63746d347bc57faabdb5375dccf56dea0266" . + "145a9ea473bed66acb9f2f03d1e575b82e20cde9e6098b25655205673196354f" . + "f2e9087af5392ae5f5e02ec2aa6024cf97012c64dbab041ad3669c9fb132a533" . + "7b29930a983c69bd3f457f966addc473888f6ed96ad871b6e19e748db099931d" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "ac5d3dd8ffbd47d3d6de392e853ba8e3ba2b775b2a333afa03c70ed52faf269d" . + "69353217c1922c8b7c7dfde9630c091ff0e8f310dc720bbee6186a12871e391a" . + "f82f5828e62d41a96586de07df9994f0be5184157923b4f25fa6f837dc11be23" . + "285a942be29fdfda6a8cd4c5b875abd78b91f061554359215476379b6a2c76b0" . + "521e42f55cd383c4dda77ccf1f50e523b1bc134e85fffa796f9a9000d9baf9de" . + . + "bcd47629617d85559d92c75911d1ef6b030d53196dcf8e0846bb5187462895d2" . + "3346bf2f47bc15df268aef56200610597d7eb25e1b82f1ee986c0449855dd81f" . + "153d9cbfda37228e79442b1b8a8799d562868ef6d58f93f6ce94514ede25fb14" . + "eda50bea4712a4c052c451510bbfac7e00383dce33209c0ceda5ec9571d9a6aa" . + "5442b1db73829ed994ff975950b8d0a855e93c5f4ac188bf2ff166b7b5c30979" . + "c847dc2bf91d60b1c88513541c799978ed4757426751e1ec482454b1ddc89721" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b89e9e4d9d3371296fcd2669d9cda9c23ed37d7ee8621383240edeaf1a00031e" . + "3b4e06eb1513dcb60fe781cb859b66997366d5d9e17236af5149b6dd4be4f0ef" . + "30f95b068683552aa6f81cf9f7b4bcd6dbbb9d4d5af982421db5e775b1f27455" . + "166089f4d2f01252de83b15d239c48d69e96e2cc1f804fef75ae75d3fe3729e6" . + "625ba95d2bf25f8ae359df43d221425dd11f77044b7b3715851749f5e65fe896" . + . + "64ff5eb3d90a8570909a2184849cf1a238ffde6c91e8c0aa0db63118a3432c0a" . + "2b35c0ffe48ae611501ef5807c181adf5e66b6f62747bab062cb486ac18848c8" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "dbe70f59a012fe295fb736ce59bc2c092063c005b3f4303ec1191528f61854f5" . + "fb03ddf7f7b55eda32a20dde31b09d4134bb797fc9378c9fe96450b54c4d9c39" . + "f6a9da1bf9a1bb70292c9427f374da21ea1fe33b307a1e286c4879cb1916e5d7" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "f6b8cc2bc97afa96e5161c69caa4a94dc133cba15c0633e6445995eb63c685a2" . + "e7b33ff2b2cbdcebea3f8b98155c20b5f8056a9892eec31d1ac84e939fc9cfb9" . + "622074602e86321d0eef8e524f9b01aeec47e417d06466ab99743c99c675c2f1" . + "ab87c59121b35553f2a523d62b8ea519807a32b6d7d4038af53761e9fbb343a0" . + "b056c4869913fd673563348fef52d5cf0fd03abcb7743b1769e4d0f18d8614f1" . + . + "4618f16b1e2cc9555e14ae91fd89a88e2a375913f6621088bfc5c729bc3a9069" . + "4cda6c918c1ffd574a5814f5e32160aea3602d34002371f7ee1760df0ad3ac4a" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "0400f5542b1abcb073dd4d2e7b0d63567f474198f305f5df326b60096687e408" . + "00f504581e3c095d28095535798067d37079de969cb47ab252bc7624df445130" . + "1f3dc3926b1e660e9efe2d11f8d332dbe32a9845cdc6076513a66fd5ae48a7a4" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4040b342d1d29b6fbf65eb64835241374492cfc541ea88a40a7b8089058f88df" . + "4040b342d1d29b6fbf65eb64835241374492cfc541ea88a40a7b8089058f88df" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "b0272a78b5e2cce1e84fd483e370e34056705c983d4f294835d08161c6ce3062" . + "732d6a72eedb3839d6ce878fa10894c993f85dc0ce3954df5dd3cfcc99877cdf" . + . + "1d595f4d4c243e46960cbae602cfbf40504a11eb48630a94ec133b1ccd3daceb" . + "3dee897cf628720250526f41863093a353885b099a8c9f4a8c8314da86517d07" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "4d71a227a27bbee34c174fb418356edb690b58f2a5f1a801379a258701cfc4fa" . + "ba2531cee35f928f32176c175a1464187bb37c6e185801ce7a578e20d6a59d55" . + "ee04d4fb327633df05b869e733645e33ef91eff1ba75c1de3bf9bb4c2318e7a3" . + "5f626765a87f74d99aee4484a9f7a3d293d01b7935fb5d091fd64db53e4eba6f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1e7221b4601b03bfb50c3899f1ef70729f94e9f5ab058519f5ea4e730556ce76" . + "03fb45e79c5788a74f2ac796b0d25441ce89dc415a8c4031aa53fcbd867bfca7" . + . + "64473690e67812c3a71d3215a2da4225c026a3c4a7ed5304e2d201e95132fb2b" . + "a3f5aca8288c9a31aaf8b4628e17730c2ccac6aae19428323254777d51325b6b" . + "faf86e55a16cc3cd1439a66ba5bd866c8aa0d86da42524c99e92bb31a654fb33" . + "4d8fb91bf6029546fbf1b084e131fc8885ebbb6869c2747de75af50b0ef512c4" . + "02bd31b690c5481b0fbbcde8a36a7dd35314d2e0513c5572bc3fbb4fb8f2c785" . + "c1f971e9321e7e09363bacfc3c04d6f936a25d48d28392a8cfdb20f491c9699c" . + "65122e90bafcff9b339f18d3d200f2de2a511568b29514a49b2b8a7f224ef916" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f40c9df19ea658a662bd7cc62572e836a82f4b7f0c9d469c17e00def27bf5008" . + "e2d4c29edcd0b526b8cf1f81d4b26aed4b82fe32e04fd1ce8cce00a51f2769aa" . + "6cb89f8a8f8ccc795cc35b553a28a793eb55b1e1a917c007de9a4ad5c6958b53" . + "322eb2ca5a0bd8a6c691632dcfdd26851a896af9ff46dca5b4f94ceaf6c3cba4" . + "ef7290bcde7a8bd25b25b70cc79c7fcdf607259d3241cc680043639ef17996d2" . + . + "ce4c5075c3fe30462789397a9fe8045fd78cfe8088fc947e11be5b5357a54066" . + "3b677e35bf370acf152da1e11982147aba676221fe660153014e10629c6cbc05" . + "65f515cc210ddded79bbf98630848382b7c6503d82bdf280bdf75991c6af497e" . + "2e2ce74049d0115383fa0357222e1384b28cc0e69902a8967c8234e01eef11a3" . + "ce4c5075c3fe30462789397a9fe8045fd78cfe8088fc947e11be5b5357a54066" . + "7bba3e63fded0f850bb5c3509f16e3fda556a9c71f85619d499ff3f062619bad" . + "a5e4fd26d3d830460340c8e8f8c70e0f1ac0ded6b0dd4c62e1c89afa2cdb1edf" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "74bd397908f29333c05fb51a2fe48f2ed8995eb49e1e159b1091059d8024dc39" . + "c09c31b7ba025c1faff559b533049b8e3f18c7fe6b1c028c3647e8e8b1eb817b" . + "b3d0b0ccdd4e4352af68d43b5066d00858efec5f5ba4ccae308c7d0f47c5dbbb" . + "7f5b9e76b7927a941574a6def9fe9bc89aecc7672adf16fdf7c022c772175210" . + "313c8eff19f7cafc894c5f0afa2d29082218dba69bb6779cec2fdbe224aa6fc7" . + . + "c77ce97bf774ef888760b1a5de543cdb2c76c3eea460657f49cb2da08ca46357" . + "7444a5fb2091a917a28fbab18941e744fbed1823647d3cc4659d35ad0336ad15" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "c77ce97bf774ef888760b1a5de543cdb2c76c3eea460657f49cb2da08ca46357" . + "7a8ad56bc1501258206f6d898f6fca4846ca519e7f0c804faa3589d0e56a38bb" . + "826e3aad25f3771954d73d3319a0d324ee4fef3dfc553ef6a2534cd281140677" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9ddc2be9a3ca1c6f820f41eede030f43a523813fd8c67814f1acf1b0f667d460" . + "9ddc2be9a3ca1c6f820f41eede030f43a523813fd8c67814f1acf1b0f667d460" . + "0a1d0202761615469f2f1c5b7601e9e5444dc6a703640da217609f67f8add44b" . + "ec1e2f56ceb54c39fa560763e924ef5a74225419b73ebf3c68491010767cdcc3" . + "cf4b4576f66137199344408c44a0c6c179ea8aa53f2721e1f93b38352b513593" . + . + "e4d6e4f4dad15e43cd0cf42c77955a06e720fcecfa8a5ec3eb2398c11d9b8501" . + "7c845bc123a21220bfc9958da98d27961a9e7462206f486012c47d88222138ef" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "b2397986f0f608f9db7a3af3f4dceadd21c48e7fe1f870fe3151dd1cf22c01f6" . + "e4d6e4f4dad15e43cd0cf42c77955a06e720fcecfa8a5ec3eb2398c11d9b8501" . + "3c0af2142c14c635316acbc1a764335225c80836bca67efca218877cffebe97e" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "09b7cf0795ddf8106f42ba9baa4df861d6efd2e6a967c2bb3485b069cafa3b2a" . + "c406774ec5d85c2bcc5919c4af08d229dcfc00c4260c4e2ddaabc2358ca7bfc7" . + "a3912af803ff6959883f5f709147de4b67d7038af2786bdcd55adcde4f9ce403" . + "5e0f24f120500b3019bc7b7e1782421fbc895319a1b6d171771c6a7231bff414" . + "49da06fed25f1f8c9598afc19b8a04cdcf51f5a70261946e7a2eeb45adcea826" . + . + "c355ccacbc81e3cf937eb14113fb5e8034df52e5b92b340940b2e05c3b9bca95" . + "b38989e7dd564e3c119c5ab81fd220f1f3b97bc44251724d08d63f5c8fc89967" . + "28b3e7b35b0a485e82c6d2d01971e097716c17f75bdbc351120cd5ae214ec814" . + "89c61f03288b7cbfeb65b380be40ebd106ce53168638fd3e457be2aa6ad9585f" . + "6820a81e422c2c4311a3630368bdedc02f1b9b2b0b257258cd81634dac262bb2" . + "c8c397c84a7fc8087ac3cca1b5d5c6b66325c6bea3dd5b54f85b4d56d085d0ea" . + "47f7feb3c004377d962652358e41cc946a1a4067b159b0e2b37176277714f738" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2f2d355c0307401f78617d0a90fad4ba0e400e9442d07aeca5862dd33ab3d3fc" . + "1badf5e7cccd4c0d548d1624666edbc89f4fff0d1301e5a296efdd9caaee56a2" . + "5a914724fe755ad113b5436d825797b0ce18a25f3d97944af7463243dffdcf06" . + "25f499fee59a05ed2de5434bbff3c6101db7582bfbcb1e06e12d738829dac9f3" . + "f92cf4d7b27c6da20cf496b815cb3ceac7e56ead3f7c958a1074ada0c5f93e22" . + . + "2a70b860f307b2810dc983feedd880e2763e0826efe4f8db4ebf6e5f6a9c371b" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "c78338e8756d7802767ad4ed459fb4e21ae00f7023999678d6b2a5a75a1ec978" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ca86c5b53d3ae7f3429cdb9967680abcb9aaf23b0678d646a22660540759d0a7" . + "ca86c5b53d3ae7f3429cdb9967680abcb9aaf23b0678d646a22660540759d0a7" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "59538616203cb2e5d8fb57ffd7536439d28c515725e65682c4edea64b3d67285" . + "cd8fdd5034d8af5cd8b1318a087a9fec8f604a648f5b8ee968d7a01b00e4652e" . + . + "549daf47d45b7439519725b9196d594084e4499601d440d06aeb4cae078690b3" . + "a6dc394bfe822b5285bce4da1676d80c81a15d8f968fdd21fdc42f58b2223b4b" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "0005c0865bb5e7a1d2332f698cac76254fa310aa107e13b4962906449823b6db" . + "f3df6e67201485f0fcb1b0d1b7f1848392b26eb99ddce9a06c3db1cb65bc527e" . + "3bbe71f60356e7c417862638372c0b76c0d874e11c77dec4cbfbd86803d97eff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "90d396f4cbeeb4b91d55a24c682a59804c87fcfd8fe71c714741da858d99e739" . + "8613196e85a3b8eabdc9340ae430077001f9439a1d0ee3133c84e7bf1dbe03ad" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "477c97420c944b2dfa6cde559433188b1dac0b5ce30960c17d082d930731dc8b" . + "61ed9d70f82e8b94be39efc7afad0511c689c1d4ebe7e0df454678f51355e07a" . + . + "51ff6f1061e07a7567603e8600658eb07dbb7e02fbb3ee60b0117076dce64971" . + "d1127b5dedde229ca79455837f22e7bd69e3f6c66c4952b5d0122e446526c95f" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + "babb97636da11f01b388a26f89749624f98313a99c9f27866be8c3fcaf6a57a3" . + "e0ca79749bf510a23b72d00b30fee1ea5172571c0eb23d8b179370750beef8c6" . + "4699d1c702f7077517c7f7de578f43e65dd58eb2cd4b44ceb0ac5c4da4ad737e" . + "98dead9ca95ff2f193f280a0dc67136d3a7abfcb6cf2658553567d2a46e1c849" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6b76c0db403e0a96f388d788e66181d2d0b9644151b5d399b5ea86cb57b9e14e" . + "6b76c0db403e0a96f388d788e66181d2d0b9644151b5d399b5ea86cb57b9e14e" . + "7b1671a54f68bb3eb15807774fe0446f5aa29660222f8df6109d06940830fa44" . + "0fde23d14fe3ee735e4a0f6b8a34bc449e94c9f7739bc5469970aeacb81c14bf" . + "54a3bb00a06e50cc901963f72e1e308ab0f752d955b7a18013eac63608fdac70" . + . + "e8406782a82c52f093722415fbaecaa0998ce082fcb49d95d0b43d2096e12dd1" . + "a330a307e84a5c49d6ef1343a03118c8ab17f772959a79a9a18109dc4c981fe4" . + "566d1bd5cfdcd9a4826277abc752c39917e1fc20a1d3ea0b254cec48b99f1f64" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + . + "c11fafc6c00e048243afbded0837e30f7bd456becc6c403c8a80f783b16845e5" . + "b4f48e1c1236d63275ce1fb9ff59a0eddae9b6c6abd2a187918fc5a287afa3d8" . + "486dcb1ebade1349a71c73a4f584442909c690d26251f72d0c4089316768d8e5" . + "486dcb1ebade1349a71c73a4f584442909c690d26251f72d0c4089316768d8e5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2fd7bfbe3ade1b02fa21036d69ed4e6ae8da0eefd5b8b97916d95601baa88ef0" . + "24b25668eb4d4be2b2555f3b5e2b62e0b2154b698fed7b6c61c2da481be793e1" . + "90ee4f2b37e0d8a9f06e9314453cc5a4291bf1e6537d13fa10936f336ec0fc42" . + "78a3ebaf04f69ecbb06159a82f68db6cf1c35bf03b9169a14afc6b6a946c6f5d" . + "8eecec51cf4705badfad0ec1bd26401a1639392b360b2d4265bba4446d68010a" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2bcf9464d403110b58c06e61e2588efec247a3aa5a57a47ee85fa5e8453d8bbd" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2b30efc180ccce0064bf73f9fcf86b71326241a620d3a6eaafa19881e863872a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e518023988650cfeb5cc231f65d35b04e351239f7a64d0d502756303d61fd5d3" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "55bde1af2d01305d001fae3c273354406c29f739d9d61b8a590cb86b646b6201" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1b0319ce8f001e593f8e7994c4f4b405e1dc7b77124cb53edc06b81e32f8cb1e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f16ad9fb03a774be3339b0ef79d1d693011a73040488b3ccd99b1b57cb889144" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + "a9b20b819a792ff7363adfaedb739a5eec320b7ed926b845061ca15db9831de4" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c94e229e7f1494a1ed098b269ae4d2206f474350bd1a31e222f3734f78150e3f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9923b7fdc17920f986a0336a8f9551fb40cecf60269d749e6e38fc846a40c5ec" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "626dec6c89bf3d40e9678ab7510adc45498f372f1152ae8bf80cf519c7cab198" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "696431dda3c004079c1b5a18a268267600d0d0d73930f70ca68ebbb0e32a7f01" . + . + "eca6c40481f2c976cc8258c8d0757836e76eeee880a6a5d5ab7843db8c782583" . + . + "ab42d52e74a5beef0fcb3291c04ba594f658222db51a0b7a1ca791611018f638" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "62fe12d0726c780db9197b6f1dddd259301cb40f66235ef6881dc216de332591" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "ee2327b6aa7d7a8c595ab80494f15328d88c2bb9650fc943d542b72bea6ace40" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8db4948f37ac7b813d4a69e388fb053fe41157eb6025553e036fda892d35d24b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "755f278e34e85870bdc2409ebc94b587c979f2ef78f6e8a552ac9c9d2827d16c" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6d02d2f1a04bf326c4975aceb3320dadd0f593c29cd709acd94b6d9df9a459e1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "72f12dec5225a50c7f7da4d2e95e3918000b1bd8be7f7eaaed7dd90b2f35b8bd" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "06b95ace5ad54ad12888b7b30abedcc9f915a39adc709a0a1fca29003473547a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "d52dcdd01b0103c58d319bc9a45e4e64029d6c3f8b21254c125c0797b581b010" . + "ad455b28df79e6a228e1c77711d38a50014e3874990763ce7ffdcbefa9a276c1" . + "8900a63a911f7e9fec2734753f21fcf264a79eab077cbda0e02f03606bf5cd91" . + "47d4548865835c3ace2b9436f471248efeb005df159f20f1d66b52aae360f773" . + "b2010b038ab8b59da78ea117cf632d202e002977bd4be6fd89a33a3dc79c528a" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "619889a70b6a76560cf1cbb1848d43396598cea8229e2c5393219ae6b20a0b5c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "ac216547b09214a04a22536d11574cc16a50ac659cd320ec37015bf95f4f6f7d" . + . + . + . + . + . + . + . + "ea92027bcfbbaac9b2ff4dd26b0b88b7c7c1a1f78a227965ac69750d167fb71d" . + "0bec4d852e416d68325d1ae049921909a3527daf71cb99e207b344bdc5382cad" . + "ffcbf89169b47be69104d41fa552c99a732c045c1e2911919d0bfa754015898c" . + "d384e843555b7f20304eae05a18985f28236fecd2c71db06c0fc4d9e4cb4cb7a" . + "ffcbf89169b47be69104d41fa552c99a732c045c1e2911919d0bfa754015898c" . + "2d761ee598c7695e9a60c09b8e60d0787b0787f41b455e10918a967fa67df85a" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "569dcb1f5a7a9267fe2ecce84db1a8520eefb0c4cd69c08b32617dec754d5725" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "1838e4c5b42b50eddf5e905cea427b7e8b664c30c5d03a72c6dfd70950239950" . + . + . + . + . + . + . + . + "7d484d22ae833436d41fdfb572b8cfca03bc74cb119205b33e769ed1e245483f" . + "c06f616391fe10036e45baa90b82b60dad519f08d6f5d11b5c87edbc40071a8e" . + "cfae0efc29a36fc4a911a25b8b886b17aab871307e07fc36d4aeb4170d1d21af" . + "1584785996113d9267264bc2729b3fced5d158aab2580e12c8a3d0d4fd66e2db" . + "2d85d80f7370ee7397e8ec38604613c3e16d0bdd21bbfb8b9426a376b4ab9544" . + "3331f629f993b581ccb5a49c79393465c5bbeaf5ed4587c2f280df8ccba412fe" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "762f9116b5ba32eebc0514bd41bdc5cdd87e9f4d3e9a2bc50143621d044854b2" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f8e6f590c81bfbac47c76c1a8247a8dbbe721edbc9ff09a891bf05db05851793" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7a4acbe0f2c50b48fce850d7f641c249e4f7d10308c8b0b6927f3bf9a59e9bb7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b27e782f24f4cfe56b60fc47e062f8753c9e0b0508c3f1ce5fa53e35414229b5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "559ce63a2a22b6d1192c7c34b2f9ddbff27a50d275b953276365d52caf4f7df7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "574fdd8c9201c0cecc0e8af1070cd9fd94770725c9acf3f6228d74d40f317125" . + "b08eab77f8e1fded9209737f000550f19ae422a6b83a26fdfcc517d57e4ba117" . + "8896ca892c319efda8134c3633c4e9c7f6839be5adbd5dc2c0177b681ec06e43" . + "f1468eed347ff6797a55b47456d1f4a8697a251e0cdb0b464dc3f128c2f63d86" . + "58ecf479d4d7638b3a6474d86bb1b76174e9418b3ce94607bd78adfd8867ced8" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "e0f4f485a407de22dc01f42143a75d891eeb9abcc2129aa1afbf68ab42090a2c" . + "053217a5b809da5e7acde7954aa5f110234b975ecc57f137a46cfd8fcf283748" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "fd69e60b1fc1719546c9d7ac189d4d5d9a22db5f2e900778937ab77548a1c6f1" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "fd69e60b1fc1719546c9d7ac189d4d5d9a22db5f2e900778937ab77548a1c6f1" . + "72633eb322205983417bb7611cb0ee61233678fdb5b1ace898759d75961ce724" . + "d4510e7043d270782e982ad09d3a92598a50b2c92a8ac5bc907fddf868d02ff7" . + "065635ce3d43ed1acf91c528670489bcfd44755c3ccfb8521d154264e8886746" . + "0121329dc8f08a7dbc28e412214daa19ca4dabe9547fe6aae856ae52d0b10c58" . + "ff938b60143f094f2c07d72adf2034e3cdec5dbb0b89e07425d9ffdc977fdf17" . + . + "bb9c1364c62f4b7958f9865afe496335bd037e5881d0d191888cffb461475bda" . + . + "cc11310c456c3690d5a74c23aa31cc25b4e74cdae146c71e54ad9dbc1d109fde" . + "391552c099c101b131feaf24c5795a6a15bc8ec82015424e0d2b4274a369a0bf" . + "50197c6f50057aceb739a8ef078c4cdb29322690effeef18ed2a0c81fb1b2e76" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "27da677596db19a54ac58d3df4adb78581d0295e8e74b81ecbf0f9ac1a41911e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "216e760f36ea9ff69fb17369a8c3cd2491cdd0fb4771b1c5e4cb0315941ed5bd" . + "e9a82fd52e0de8c01bf5a2d1065c3660c5375073ccc06f0adc20f0142ab2bc3f" . + . + "fb7a98d0dad4d28a8591dd06576219dc4a9184807fd5efcfc120e7cec56ad3f4" . + "df54de99d8e185b3ce03b3752106f286a45c4e0b0734f52f94c9a5a48d1eb5f8" . + . + "fbe600131c25919f79fab089e051e976d0db693c04efe64fe2638254589ee6d3" . + "3225c5a4cc6006f0d6dda32ac8905356e61ad30f0b86202b2607cc6f71fcdb18" . + . + "bcab62418a1260b07fb797f7eb14769b7a3753d7605bed5622f91cb6305c18f0" . + "08b1ba6a3de0295696b942972b951e750609fcc73e3bae254026d37af2de50ca" . + . + "e5dbce876f4338957ea22dcd848f377d2264efb0ec1a1ceb6b35b53ff467daa9" . + "d3cf9a934485f1643849d189f51ae6b6fc991bc23a5db60b8636967bbd251242" . + . + "b8a000750e59db51cf9bafe5e01a406fb2301e8dedf154394df1b8342bc0e587" . + "9d2936563a086ae2527e39980fdd940a97317a1ca30e3bde7bb780642c264a6a" . + . + "c6b4f3c20f9d778666d609a4994e0bd4271045407b915be7ae8494c79466a541" . + "0769568a51a2f1035adc5da6f1ffd93baefa86e72258a20f08767803c96840d7" . + . + "670f48f830a4a7073ce9aa629eb9d644b239c730c9de1c6dbc0596e15a443a7e" . + "cffd229fbe0effbec19097811f73fb96af5bf78a9b2804a49c9963109944f029" . + . + "79ea8457dd2dac91042f9bf00b28992ec6ce0aee29b4926fb730bae0286c51f3" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f6d6b3ecc15ed4d42e961ead66dd37c9bf095d4cb0028c5f5bc4e45cb92d4516" . + "01c994902a4bb25244e946d63bed58794039d970aaa1b7c7d40ba31c3eefdcc6" . + "a012f8b1338ba3200e84d920ae2931714354b9375e99f7cf649638d622a8abe9" . + "df538d1f7a386f105d66d7a4ff3527f8a40d0b7afbd7551567869cbab5e29489" . + "89b3de006883eee8b363ea8522e2df69595a7a5345c887286a893cc6f550b625" . + "22ec4bbad10a6cc97bb386f7e462d561bd46dcae08ef5c43650f686ad6a8383b" . + "885454a616dfc2f6cbb0761b80eb6334a22227a5874662dda067433645f836fa" . + "0a1242241e44120efffee8007e1755baa8fff86fc3832bda7798ee08819466e9" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3584643a84329f4bd7166f14cdd69eee47c5aa3ebe598e11831e96b96f4655a0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "ca46c5dd5923a51ba3c1a385ad0da7c320df0afd5e9a2a2bbfa05e04b570e3fd" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "b3ba7d8aa338858f141b81dd8453f410e13f46f930354934a5f8d6f94eb60d31" . + "063e975b3d855dfe7ef0d420fa7b6f200bd4784f0b3076602aa672a40e520839" . + "fb3a068e0a92927d54a1f6d51bc868d932c1a1c4c072b2132110c2feef866a26" . + "162de0e724baef3eeb7e6027b55cbe7fe57c7904cad2a303ae3d6ca6f9901564" . + "9d5eaf11f7854ef65ab725c4aed65e9ed524f0f854e26ee8e0888cff4960c294" . + "bb97561fc217089aa8976878667641cfaacd7dafeef76eec0772baacec210d09" . + "5e4b4d20022495ca37826a5b8a49e39b78ffafe5585262f52f7099f9a3ace1af" . + "3e201a56042905d6b063ccc0174704704be800b2f82e665e4ffbf33e766dd29c" . + "c7d9b8b08eebac5ff4754a9cf5c5d3f6d998970de5500341c135f067d453b3ec" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5c80aae7f4056cb934b0c2b11e0d5dc744c92986c3d2c949f7980bd26c91f15d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "1faca28894fd889f0ec27cd885b21980d1448b83481f86a85a73e8ae02c71fbc" . + . + . + . + . + . + . + . + "fa989c638994fdb662ea41936ab7841e86305f9a7037bed3bd723046b92d340d" . + "3e976b6b68b8bb55d8c57d2e2b7814ceb88e577b4baa939589aae12e347b2306" . + "11b5ce5c75a8ebaa65994f337e779f4c0a2f559bf66cfd19eb5272d8f815d4bc" . + "1c0364ed664dc8a2f8ab21913c9cd93f4fbf36c3cea54cc3684909a810d723ca" . + "0246beccffb1afa252797068a7986edbc9e7937be2fd8b3c7676eb603f1c2461" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "42fde864c155251330308023d283763f0ce332a56284003cffe3fb05845c63cb" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9b386d10b84e712a494633b7f4cdf17693b55635c0eedbff1ea8e44a32917a63" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bbe65a25633e80657d38cfa90526614b9fbccd7aa55ffc031c871b36f977940e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8cadbf9f5cdf4309162b6300ed7685dbd7489ebf84eb2bc54ebc271858d8853f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "fb12e7af9c67cffda401312c052570053af78660317a955fb2d84cfc5c1145d7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ece25708fce4078228ed1d843e3a3d0d29c9e104c8f162fa7808de4dace7f798" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "abc913688d48c278f62378996e3692edfb40dee5240cbd3558af27867b59abda" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "34f5178adb5028724ec6f1b975fdbb72dfc122d6ba04517264088a20961d91aa" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "6fbe2739d0b95c4ee5acc453b130d300bc14f5a4e1cfb79f2dc1d4c4e03f1ed8" . + "d965ee61e8b8e1e1c879b565f388e5624ffe925ed26355dfa22089af755a6cd1" . + "139fcd8b690bb3c0663a68c22afc1d8e7a4b8a1badd3e566199310bf6d0b349b" . + "968259ab436feab20f9afaded8992503c43f8f4d17c6fd0006d3761bac267de5" . + "e4b7f4d7e17aad92d18e0bee1a8e81c8a29c1a9378a826b01c3d3267d22b1b03" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "d92f283954edda1964f8287a6cfc1da0cf6d4769c2692355c9d1c96d539b02f2" . + "6d31c3545c724c81934b54f5e9430d885b80919ece7158cb458db287f3440ce3" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6c2dbc0a2727f952e5d9ec9976f1f031df8e950231a21f250bcb3335daf0e29b" . + "6c2dbc0a2727f952e5d9ec9976f1f031df8e950231a21f250bcb3335daf0e29b" . + "6d7a24a6c634e35342c50266367fcd4d4c152df48d0d0f2613262c3eeb1b2e9f" . + "9e496a367c79bbb04175efc3976504b30767a4a0a7ca4f616f5f76442cedad0c" . + "045a6e5e7b5722596a6026bf7d219857b4c9c670eb13eff495e599b132ae39cd" . + "6f093897fe0d4d648c5c82ed53407affd90dac921d36e461215037f0914a7e04" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "837533ed7a7506116aa4063c60b188773264e0ad6f866e58a77601a5770e1b70" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "040a1c0df4bd0600c7966bde95a82eba328b1a6f923a8c01c4a6e37ee2970bda" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f008c0498bbbc30202f045c2f4a75dc2f88e93e56cc520643e3a772a9e6363f8" . + "dd129766cc2f050bb46901b6c0e531aff102c2a672792f6780597122f1cba792" . + "08d9be55c0aab5c65a935925bec661e93cf20a9567649b6f1bc124a591ee7736" . + "94be752fc0d770260907e3527a016dba1f4f8827723510aacf4274da64721207" . + "3b3dbd72568574c860e156b06ce5ee80cceec1985bbfc5695c020d1471ea1ee5" . + "08d9be55c0aab5c65a935925bec661e93cf20a9567649b6f1bc124a591ee7736" . + "0754e41239e8291bb1e7ee9f4c5cf8017f2372c76bc4811ce3a3b8a89b80aded" . + "607b1b1717c13e13b015d098be68a88962674e9503786c9d32ef375c3a2f1640" . + "e6ea926922959c7b11ad17e982483666b05f4d17f537a48e424f17f811a67fad" . + "2a10e96b429123b985360348b772198d85de7213aade53fa75d90d0ff29383cc" . + "af329a9659915348db7aa59fe4043822751d9065c2f98eb8643bf357d8309444" . + "24d435505dabbf4f3abf899b474d4912639ee5fa2baac0b30c1d005519eb144e" . + . + "2356c6e48f6fdb00e76be215306754170279675b44969af76d461794a649ea86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cc060221860ec2e5e6a25cbae7d6ad1aace8debd819978c80a7efd2c5e35f713" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "5a088f9e2d9328574332d4e621a9e27bcdd82141542763db2ec0ee97cdedd57b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "574fdd8c9201c0cecc0e8af1070cd9fd94770725c9acf3f6228d74d40f317125" . + "a1b86b37ac648f81f9814a800fd887fd680ac1ebbcd4f0b86380eb912d32dd18" . + "4c6ecfafd9f5dac53014e28ee0316c059e2595d349b087a9b5d8d4f09878f9d9" . + "5a088f9e2d9328574332d4e621a9e27bcdd82141542763db2ec0ee97cdedd57b" . + "a2c2a241c952e9448fd16c5aaeb878eb5f01fb06b3b3c4de0aa2503c69a14a7a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "091da9667877a3a56a0f857f0ebec93114f10fcb901bc73945b57f67b6d9501e" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "d7cdabaca2c4863ef9c76fc04346876239476445d9c544d84232656a0920c17e" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "c6b2610fdc03b4a461de6de5b7523a958dbf96d005c2b117e8b0945cf1a5b252" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "72633eb322205983417bb7611cb0ee61233678fdb5b1ace898759d75961ce724" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "66783d32703910b4038c55158549bbb62783e7826e86a81e7401445589a500c0" . + "fcc4eab0e45c7dff9975e5fcf66afaddec90ba07ecffa1a7f84260b8e64156a0" . + "38b8a3c5650516346939db5abfb341816aab8979da119b5e258f44b363f70870" . + "e30ccb64cbfc6765a0fdf968d7e585adcf1f21adacda412b21350d520a5e5815" . + "ca2bb3ca4726eed44b7e81687df2df1ae72da3a609785f7935c856c48adc314d" . + "780dd6e6e20d3af15c58014d5fc6566e738ad19f853ae9f50682b3b771e528cf" . + "a76052f59b9713519200f609c8fda2b9ee0589937dbf7921fe8d0eb8dc8ede34" . + "8a71401dc91feae2c0090bfe428df6fc6a1a7e19bd42772e2e882a85240c4683" . + "113b93d318546ad460016942b8599fe9b93d1ef2757517d4b86c7a804b5dae82" . + "b940b8039c14e2fd123457c14e359102cbba8a9e2d56971afa606d50a2b72c15" . + "e61d876d40ef7228b43e458f48f2943baa971c78e981af9ca1bab01875dfbc8e" . + "2194b73d8ad1c4e919754879179572863c49659aeb1a6a7dd8eb0642bc8babad" . + "d4536abcb59d238f21bea0dbbbcf2a8c32f9a24308b952a3a9ef1d00a0332711" . + . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "56f45e936ae02c9d3c33a09bbadbf08cdef1adb38bbc5a087b547755582d3bb6" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "6ca8851e919b3ae6577aff6819de62cc12ba6a0e2ccd2da7daa0a9e26aa69265" . + "ec2e839dd4915639f27e89faafae41bb8ee7f8486ddc2a65d5ea83c11a613afe" . + "6a355617a8b78bf82ef1cb03530aa9ead08622982bc1d16dc821ffe5a390f970" . + "fc46e12526503ba27407e70e4e496d88e437f0e61a1231ff93b11916f990d650" . + "85c3f7b45307321450805c74750d2a41cc9f4aa9427c7ec023bee06cec7d36be" . + "9055c96b58180cf7e591b780102fce5440acd75a3b25ebd2fc94ec070f5ad894" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "255be0db0035432ea7dcdaa17de7c6c90648dda2695a8ca7dad83f499e898a20" . + "661449612e907762372d9689cd293124f0c797563d33d536b00d7bef256fc814" . + "4145da0c034a477077bc7c75bb12b4ff3565933cb31fca8ba06dc790a9f97b16" . + "b04f4f1ee8681898a268837aa04db5f3e625a646d8315a769ccf7b497a92e72a" . + "2176dd769b9e67398a88572a00bff30fdf630299fe8b40b69d86f3e6f13e772a" . + "42271786f247f4d8b20ddd45c661b56c47e44f7497f510fb83eec2db42097976" . + . + "6f4cf9398ef83a6db6381de4de2431262d131a06fce1b749c5b036b2400546ba" . + . + . + "dc56ec7654dbd84cee280186c39592cec40760cbb20c8557811d979d7ed9b3f3" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "07c3e2bc6e1634d2709a892623ee7760b4a240dc68dce828998d4cb3ef211311" . + "149e177341461cc25ca8f87671f0a210ef89de0cd133a0cc112990ecc5dae6fd" . + "dc56ec7654dbd84cee280186c39592cec40760cbb20c8557811d979d7ed9b3f3" . + "3e23f431692047ace687eaa4e85821c357cf0912847ca04843e5b13413a78b84" . + "cf3ea66c4b92f79ca425fdab0e2742d5fa9bc23e7bde0792d0d30c15ad2b912b" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "51136250ea7e596545574c936e8d341dc9490cbce051a8552523fc7b47a111fd" . + "a30dfb9449ce1d826edd681d71bf78e7f9b580c70da92f5861c3fcfaab23c1b9" . + "780dd6e6e20d3af15c58014d5fc6566e738ad19f853ae9f50682b3b771e528cf" . + "149e177341461cc25ca8f87671f0a210ef89de0cd133a0cc112990ecc5dae6fd" . + "77a9324d45d078e92123beef53d4ac78a21a339310cb38b3b9250d2bbc2aaee3" . + "d36f80334ea27cbcdb98bdae6672f34f69b8391e665273385dc5c9d55b638f80" . + "7473fa16b396485877b472b40862b0f8568f395a5df834c5523b8e74765b2088" . + "e9d1d6ae4e20b027e0a44f12c7274048e2e4fe9a4c52db1043c880600ee03216" . + "4bf8fe05b49a2c689515b1218e3fdbf6df58d77c5a4eea32efec00845c6a9b9f" . + "d462951541aa7ad91e4d74c288d53a3b40986d956fc9d8f2d23fb9b09bc6d857" . + "0e529f1257d451fbf07fade631a5912792dbf1d6c9883c004b2f3295cf8d1440" . + "fbd0491c30cdaeb8d4b507b22265b56cbb588068cc94dd6acbe35e0fc2b96c9c" . + "64b77afb07fb79ffd877cfbf63fced1f04ffaf8d680c80e4f64a3b08a7171133" . + "2407cc368658e2126427d4ffdda76d789b69659e9a5ede62b96e856fd23529b2" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "4a69f705fc64dc9ce39dea3f1c7c53700a8224a945e1813e693208c0dcaa4b97" . + "88cb5a27bae33522016c57fe92c36c151525baa5460b1dbb7e5994c3fc2fd306" . + "e1d8d98a7cafb7b54c4906c15b087257b5d22d00cda0577a54c2a0a66deb733c" . + "85ebf4ddac9f99bf40ef0e78343194275f5f545c30e1228bce4d3517c377900c" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "62107c322b191b9cfc12e2d840922602d320b13228f640d3118db3ff1ecac68a" . + . + "d524153f8ee9773e4ef1273d72fa102bf1c83feb626782ba584590083bd90d0a" . + . + . + . + . + . + . + . + . + . + . + "fa52502c4cdc5d98780bdad41c59e1f92afc9454d5794932b61eb102014c7b70" . + "ab32b3f4ebb407a1e5a13baa369fe28751a6445b4fb425591c86f6179535e325" . + "34210c461a0dc6ca67e73ded885d7b86f533866ec9177e328cf42c03d0f1782f" . + "42a240d76d1af2da19cace6acf2143a3b9d73a01dcaccb10a62af54b05cf1e7f" . + "a2c2a241c952e9448fd16c5aaeb878eb5f01fb06b3b3c4de0aa2503c69a14a7a" . + "a2c2a241c952e9448fd16c5aaeb878eb5f01fb06b3b3c4de0aa2503c69a14a7a" . + "ab32b3f4ebb407a1e5a13baa369fe28751a6445b4fb425591c86f6179535e325" . + "86413ab57cc6f28dbd7966ee6f0fdc8c4b6baaf4ce4b167fb261464668f8e6c1" . + "91f7c4ddff587ef747585f60396495e8da0ada03b19eddf69285cf2236405f81" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "fd69e60b1fc1719546c9d7ac189d4d5d9a22db5f2e900778937ab77548a1c6f1" . + "72633eb322205983417bb7611cb0ee61233678fdb5b1ace898759d75961ce724" . + "12f4b4f2271b8840c72e90a3b8e609933973377ce70ac993f9e1fa1c31aee6e8" . + "2ad4bae01089d770bc6b25deb2e20291b5fda98646c5dcd93a18f97b8060b79d" . + "ef090e601c6981fc20672a588e7b63f7f7ebc56771f426a11828c2c371f4c20a" . + . + . + . + "46c236c839cff26de06963d4e90d42949f0d4ba8c871923a4b3a482eeda7406d" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "216fcfbe37cf6b1bfedd21d20b4eeaf7159a3e2c025e50cddef4e93da4a3e946" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a493a1057554017b5afa3ea3b5e1929861344f1eab440a6c9ef5994dbcc08225" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8513287d875938d7fc95bf508e8003b357bd3237080c83524eb007510e644734" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "aa4c60e46d0974a428b3ec09335b18c567be43fec61a8f3b8813d337b31d5ef5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c03ecc432cd9c033bfa249316dcb0e7bfa076951be4adf5290523ae6335216ab" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "24b20d63b5261ce8359eb931533f55a7c2d8d186575c9c5a777d92f658824b3d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cb72749fc1e02f5de1bc34a63b9bc8467aa9bcf10a08f481155c35407040e5e2" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6bb6b015e20732a50db1c8dbca262c2999ed3d0c54580df41e9ff83ca96517a0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e6325e97498931d88a7d1f275ca1c940aca7c647ed3e054ef44f902ef34a7c80" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9a3c6a4c0f4a7ad9119094f95918a3654c1eae19e6c86993e97258012ab5f910" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1e754734a8f3eaacd95b6fe01a63af45643dfdd6f0abd7d8eb16f67f1e609975" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e41cbc13ec05751e0154d58fdb0ced3d90bb1cfaa0865f649b1ae8a4d3c274dc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2f95d487d7467b4cf4677fc22b69bf83726e5a91d674e138403e1104ea3df94b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bf7b7591643b5d0057746f4c60690ec4bf3960f8f8d8938dfdbaf7a2fe6cf428" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7381b56ae37d6d6c0be6bb5c602e97d2b837de8307cf922ace577f5b2663f655" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "eea8ae1baacd20cb01b3e16203f657dc86e3bf3dccb2e0cb1e3cbc2c134d7824" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "251d6ed0547b189ee89a773e98fbca151b38ef14e839cedc30c132f981c99b91" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "696edf94e211156ba6a6234ff1df6a30e4e1f05c09eee1564af93bfcfc6a0b1c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "dec578f8fd663c1c716da543789bebeacda31516bd6ea980fd5dcecf3d6a7dd9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "728e761b3c62b33152ff5e62dca6f95793322105ba1aa51b69ff6cce2bb55bf2" . + . + . + "72f59cb2a182173163889c9040cf475e7f6c3455cf0353af03d0239ffc10cbf5" . + . + . + . + . + . + . + . + . + . + . + "64b2c34802fd334b23851a8994c89a18ef65c8fca12b45f8a5271f4ad9f90061" . + "1847363866a0717cd52655d14453ce80d17b5a694aae4c0d4d0d1bcf04d973e0" . + "959321a1c57cbaaf956ea226f69d89c6d7fc7603565428662353ef081b30d79e" . + "b56382760db903b51aac547410df6f44d55ce4168f90289881a20c19d6366580" . + "b69d8f13d8661126b212b9270762b2a98ff64af1ade05e7a4eff106a1b06214a" . + "c6acd58eb0ed281336d45168b246afef109a8878b04ecb7695c78f94d467326d" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "a33c07f11f405376282562fce8769740a72aba7bdbc2309bf9b048452e55edf8" . + "ce729f745178250275b42ca0ce473a0a6b8eb9a38cbcb6cb59ea50716c412340" . + "6357d35eec969c88cf875ea52f6e150aff4c82664f96ccf15d0be94d8252a7cd" . + "05ed5437c835a3d401b53efeace6f004bc559841d43eb74a3249d31d6d5bef98" . + "c9a9b4e6c731cb9003acbf0ffdbf65cfc34155e6ce250d3165f510c7468493e1" . + "1bb4b9360ada9f6e9eba026eb8b83d7822e08172ba81998abefa30c4baff5195" . + "40f83fd0fc8a7069b1df49f1dea6b67ff4cec23785df9d8e0a6235ba7e3a2359" . + "6ed9767f7116daf8f739c6c4dd26c5f01aed7d2aacbee94b475458e45a1b1d90" . + "cc9d9e0401de1648f6f13f22924853fa7bae7917cc0876a9b0c0a82d4096c3c7" . + . + "5c7c4fb4bd96803f2f603e9b1e258da35870300286cb6fe2d0a3106f5bd56317" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "fb294fc103578edad6900c95d088bb950bb9e7ae164c791935b61e3e53f4bbec" . + "c2105c5e484052ce7a4b71f13178b22eecef2e5befe2a5fbb670b775f1c3800a" . + "2026465b53fc9e7844e8c6dc76050e08e6704130e1a75c31e37194e708660bb5" . + "98adc2fdc6adfe90b50ba52707363f90dfbba196d0160d3036fd3c71fd328270" . + "2b31e711b3d8ed42b97aa328ca94f994b3f3c9be98c20d4f441a2a3b18ca0cac" . + "5f30e297c1724880d29cc2e139214d2a5ff006f2aeb7500224b4825794452835" . + "6e197ea93636fb4a06c3f872575a5824d4e17294ef900d55c4aa56dfbe3dad25" . + "264a8168e52f4eb520613bd7826c59ad5c13e39091d775097dcccfdc8c9bc787" . + "b702bff9565c657fd6cce4552f660b51c5d476e42f6b33f10d530ac05b53cc10" . + "4967aa1c20d2810be771c0386329845da35eef18a2456bde01a8a48c6055f6a0" . + "b4e41c46f4453158be1bfffca1ea3200ddfe03fca1bf303ab7396d4131ddf800" . + "23bb728097fccef7d5e4321de82716ae539448134ef2e620a560817eb44c7283" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c2b44601382a8d10a21e36fe822f23bdfcea6989dcd5213938cc6988c76cedc0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "e0f2049cff556f19715680097aba605dadcda051e69fafb88e5c3cf033253b82" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "5181cc762093b4119d6b5e5da40011c745a5eb2e8a7d4a577e9fe78ea9d3e001" . + "3c05f2fd79e9bb1bbf1b0e673bad47ff31981767180d795ea7ae5d6d98fa1867" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5af7399726ee0ef79416e9321c6e2816c61fa02723d2d4c959ec3a7482af98b6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0033d5eb907e60ea5994bd361c6a0589e483cee6669354671cdd272cce9e731f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4a3d7597af0076edadc6ad83159ed5e0d4b323dfbe4004e3b4bcabdd78bbb53e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c36a2cb05f15e22851b87f52b567fa81b00af77c558df72b5338d2336ef0819d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e86ba05b3dd8ad6450d2bd7ae0d6a5259e517ffc9d9a1069fabae9aad7cdce6b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "76de1914330ecb7733badcf58b120811a66b5cbdbe77a9d1c2571efb223a7bbf" . + "b468c0fc31c08dc7a94366a8f8a777d7b3a8974e6a6f186fc1c67a5d766026f9" . + "3d0104a3e19c47e6afa30c82fcc3c6d6b64310bfeee7086073bb681f629b3ee3" . + "3c064fddb27bedd42b9bf1dff562e74a155158437d3749a8b2a3cdc9f307b5d8" . + "634107563bf1895ed43e0960f5b6bbf6f09d0021cf57644b752c5f27b1b0b2a8" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "1f220a417640712f2f905b66e1a6b0beef8e341dc71f798c953863b1e22bbfe3" . + "0aa0527bcfc16b9e613df83b11082b106e02534edd9d2042a8eb6bbfbfeafc16" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a08dd58e05e152526a98b687da6a92f9878800a6b1aa14d60287f4acc14b594" . + "a79c3d2bad31f16c0d76e8de89334ae061a644ee86a155c09d694c31b6c84dd5" . + "c6d6570324fc3150d9ac11c3a16ea617a512c92d268a2bc9862bd3befc8eb86e" . + "c9128fca6e647ce3408add2a54db94c705fe1b003a047ca91fccc4587b9d4467" . + "16e3098f8ada521c330463e06dd1af18d478e1d0e848ab82d787224341300e46" . + "b28aaef498205edf62b165dccda595287e2d08ac27d519af7a636609f7a48704" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "5aa59e0aa6e347e10eb4da0be42bb1570cbcf0809a259725cdf50a7a900aa35f" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "c24ae67f77feaacfa88bfbf124c5d25ba11d1f7c019358d6b899e0f34de94202" . + "7ddee6da8d5cc5a255ad43652642e68b8ffc33e4f632da7995e2322c3db25a3d" . + "11bb9de2241fcf5312e48aba804a85a477a366c8bcf9451a03c11f741fa9882b" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "6db55bf412c8c82b012bfc0dd976f8a8ad431681e2fc6df6870034a6247e227f" . + . + . + . + . + . + . + . + . + "4e3e6b4b2ab666e13b5757f0b067891f9e66a66bb9bffcc03eb70d5d2c62ba3d" . + "deb79d694ea87511225ebfbeb963db41b521f09765a02a3e25fe4ec1da5c708c" . + "2ad336399c482ab9a7cc5b80eb80b48e2851b5d7ae7472d2a7cf3ac185f8ec81" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9e9fce510d637b84c6d01d9a855c0812ed0c51aeb24014e0079d1df84cd90827" . + "2e46ff8881c9dfa117385a0fba801e8874c2cbe78d60fbca895668b55a5ffa12" . + "ba2aca294b99535c90e17af8d87d24765f084d88546364d947dfd555fe658bad" . + "d01fd2cb361e3a35f1dfaad4ff7bfc9cd0a4a9017075a675faa8fe94c576fa30" . + "34027bd298f90c1fc17006dc4f79a7eceb043452c214a39bcc9f5ebe5a6ec865" . + "6a91aba0d15747e5711f3e32b94976b3f8060439088447923fc12d131ee3e4d6" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c23d972f082aea68fbbb9a7157e4e32f39ea73adcaaa9645e3c108ec3d9e78d1" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "719ad1b9a8dc7f62798bfa32a30822e76ad70b954b90480d88022b90713491b3" . + "66873a72dd60e5bef4d520472c3782a11f8d4d59d064ae1f8a553c58fab190e0" . + "4ed567e821bc4038035df1a6360e462958d619d0f21e6d18eebd0238339e4110" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "9b66ff289a0bfd5ef8cca3a5bd30882ad8d675184d39dc72dde85ae3e9dfffa8" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "e6a72f9170413896f1be0921750f2d7e5198295843e68bbb3d8b0a1f1fc289d1" . + "a6832161275f343cc3a9ff84f26a074d9d80fb747ed7a5affe02739244534523" . + "bd53e7d161e75d75d69e0e25b9174c2fa8c197bb0c0184fd9b16fbe2640bc2c5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "10ab5e74b6f0f96e54fdef70de942a3ad12c666478a6b151878046d35f19a44a" . + "10ab5e74b6f0f96e54fdef70de942a3ad12c666478a6b151878046d35f19a44a" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "e3ab3f5c2693810cb5234a3fb0c7df2e9418385f57ddff88ef43f20616c8916a" . + "892b7b1dd00bf39002eec2714f7b39cf72b98e06b31e825c7acb22f5adb574a1" . + "32ea4236493b7b0f4e526f36cfc5f3e1f0baa05ff58702ec42d7854dae947ff0" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "93d04346d42ba7f194a2631f30988cf7e0d9c7454cc36c480ebd1b1a722aec4b" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7ab48facdf2620ee1e3f520d7b5798bceeec18df1753cc1f7e7cae94ea932c5b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "4c63fade0d40ad6415add494f701a15c1b40ef41c539cfd4fd2bf7326ac6735a" . + . + . + . + . + . + . + . + . + . + . + . + "a848a4fb9cb7a442fdf679b120e9f5ac11dfd8ac3c1d7f1c634075d7ad89be7f" . + "cdf89d315ec5de561acec714e722428bb98e35230355c2bdcc57da76c99cbeba" . + "d8749c24c70ad82d05387b804a2fc2f93bcde48bb978b5caa3b9320acc4055d0" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5b34f589fdd56cdfeb9b4bb54d6009ff345d78807fb48154a5cc5ad88ac43d2e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "56f13c5430750d1a97cdc48f31bb9dce8f482e9fbd910b4d7d965f96e2f9a4bf" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "685b1f75cb9caab604f2676c7d21d9f319d81d149ca7f6612a6ae986bfca0778" . + "b1235ff2a99ec849b26d63140ab992b319cc86c545036ba1d6607964c7ef1238" . + "c31c4438c466e1ca09b27ac570bdbf72b0cf1ed7e360f04fa7fca36fb2d750c2" . + "720c8199b39a258d2928816a70744d7c0832e5df6c0780363b1a1f4f60632938" . + "9a08a49d9161a8b0915cd498f4da86e9ab8f80a77753fd547dd40ce384ae746e" . + "63970d100c99cb856d9fbc1499d0f284c68f5f57af519dda627e6fa04e2184b7" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "057dda39a68b2662ff889741b01cd388a4ca3b5fa91623afaf3e0cda2c2c9f52" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "0ca6b30c2546fed4e79c918d54d08043e35d5a635503e73519f2b733ecb2366f" . + . + . + . + . + . + . + . + . + . + . + "a2e95773276d3bb01c4337896a690bb7119d771d2262bccbb052cbd34fa95c0d" . + "1c32a36e9faa68e575cb6570163c882f469c49a32c0c716796020dc544c7e821" . + "4a4fec843f2c49b797ddbd7a8b7ecd5f8ea0a758950863c2e91097a0635c3777" . + "fa3a57e8b258a4e35c07556ab74753c66a3fa7d947c5ff2089cd1b9c96040ea0" . + "00bc64d7eff65af5f20eb0214d6eeee6d9dcfd81692bf2eddcc34fcad9e2d467" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e3b8e0ae02e8bce2387e86c89bfb00e6c4717fc12141f39191ff5a7eda7a46f1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "e55bc23292699b1605b727a88087c13fe7a893caffb3b4931007352e209850a7" . + "c5e724ecbf22876c77e933c11af3a7a8a2fb5c4888b8cbb077b423a2481a59d6" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a83f3a2b29ce8e0df248aca7577d33e85a0247f6f0a237a49e9cf32eebd6f2a9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "b6b5d4741df202427f5fd2805e4bb7ac7a64732522b15728cad29c62f14f88ca" . + "724f0355c5e4b9c08fc1e94cb73b4a3b5171ff8ea419b7db582e35f315884f7c" . + . + "50efc65ad1ef841b239eb849845b13ec4259bb3dfe4e85d7df10d2edb28b12ae" . + . + . + . + . + . + . + . + . + . + . + . + "9c2f60ecc45b84347033055d9c5fe06613cf82981f0e6c7deb3c76bda73e74cd" . + "6cfa24fef02b1b7784c3675fdc68dfc17b07b315a614feea4c908dbd74c9dbc2" . + "19813b04548596b80ebb0a7e4d7a4b2b0b45abb1b84a495abd90a44df4d96875" . + "8bc77927bb31f74723b558433318fd396f23d10f40ffdde28d229de616c5236e" . + "b1e8076909d140a480e9cbc037271b0f3e973b65a39483ba973a4421c1ee9249" . + "fbd4353058538946c64b1b63a6454e34abc878291cd10659aa27b4860cb56699" . + "fbd4353058538946c64b1b63a6454e34abc878291cd10659aa27b4860cb56699" . + "d65c415a257447f4948b3c31cc3c26ea883f1ceb61b115b2981ca8dc15a59c0b" . + "82932ddce217e2199c3cd9ba126ab94c5a0bca7f820ad501ad2f39d4dd9d90cd" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "e0f4f485a407de22dc01f42143a75d891eeb9abcc2129aa1afbf68ab42090a2c" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "091da9667877a3a56a0f857f0ebec93114f10fcb901bc73945b57f67b6d9501e" . + "19813b04548596b80ebb0a7e4d7a4b2b0b45abb1b84a495abd90a44df4d96875" . + "38aced240343f4d84d19f02f694938384f4d3ced8569ae726cea1424bee976d5" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "486dcb1ebade1349a71c73a4f584442909c690d26251f72d0c4089316768d8e5" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "65122e90bafcff9b339f18d3d200f2de2a511568b29514a49b2b8a7f224ef916" . + "a2489885d81cf22789a8fe91a9e56512b079f1ca864485c9bf9fd4c31f1f2be0" . + "66c9bf88f18725517d98c3d73a534cd1aeff5fc3930c50e05fcab426bcc928a6" . + "0f70832b8c7f6bb063d471ea645fcafcea1caf8191d0000c831df9dbc1caa3e1" . + "ace0529adeef21d48f3ddba620f4933fddbae71a8bd74bc01ee203952ee5b499" . + "7a74734f8e72692d13bfa4bf51a6fc41c6991c0bcd22dc9c70f785b485b97ae1" . + "29bea8dd66178b7d96c97c17aeff48eb3f4243b5376c8eb69c64371c5b6f14de" . + "c0e5b75ca646dec900285cae754918b15583ca5029530e7a68e3b11cb96470e3" . + "f5a0437d24e4d5459b4b378c5ea9c43700b02a9348f6ddb68e9eb0ece1ed614a" . + "8713aeca25fa4f7196be293f766c767bcef19fa8f65138999c1a5d4070d88c91" . + "26306dca3f0b79ecae1faefe99420a40bfcc76ad32e9275b3530506734fbf833" . + "2d35c1c3ce97bd62ec988c6ce97bf4192bb403363c09bdc82a7ef8840becbf0c" . + "0951aa16cae2e143cba490ae7f9101c2aa49f8f2f87e4fcad9fdc49217e36957" . + "233f9600f93da416b61054759586ef3421bd4684f6daf5a73f15919a5529b2c3" . + "0c3f3f4a6a3645b0760aa21a5135a87e7378a1bf22710de208017f1626df6b8f" . + "af38c864ca5bfefab649043da1101d048df5f8c625ea74645c8e194cbb6604bf" . + "f0fbff71770ae2d86006120cf24b9cf7d055df200a3bb299882a7260b5967e4e" . + "62e31900289eb7675f8b91d834ddbdf70e6c7d152c51b1581f9cac9723903064" . + "44de048e505fa4cf93d174e3167d1ccf0d50599a51a69beae184e52ccb3a8fb3" . + "fb8420509b716ccc698d9e71aee35891b87a6ca955bbd6fdabd00e7181f7714e" . + "f96f951523df09eaa5da289f5c776964cae139abc4bde3b9379c8d82a6862e23" . + "bce430decc4a0ca777ad6a7a2da4c9d7acca4da78e42c43ea0447e7f8c154cfb" . + "46d48edb99bc26d90f5ff7fb6624072792fc52f94c5ceeb3d57ac835fae82aba" . + "933c71ba2a25e37ed297684b4f2671aad5fc3b85dcf565604ef8840859f29ed5" . + "86fdd115e122b9486d8fa1e6a1d411ede24b3135a737340230dcc3f0ca72d0a1" . + "8344487204a2fbc87516269ba3c131acd7ade8c1ec4276caa0ee9f0fa10a5840" . + "3e36517db1ea8bfb20d34802d84248aa6295ef26cfc56aff2fe9a9f9f75361b9" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "c6b2610fdc03b4a461de6de5b7523a958dbf96d005c2b117e8b0945cf1a5b252" . + "665db136ce7af19ac06095048d5e7b5627fbcc6453094273cb2b1403b46cc986" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "541a49c79a14853073d0e26208847ad1ca0855c499dc3be8f5990efe3bda2c17" . + "43bcb8cbe56d6d46a62c26981c254d5ce6d2857d8f7615e2234ed6bddb5f9590" . + "2af149e8a9b9fcf7e546219c0e860399a24efc7697cc3ad9f0ebcdb2b0847cc7" . + . + . + "92d7be5ff72a8253046d9d21b6f1b2fff7ed86abd845c596ad1fbfa18349af98" . + . + "ab2e212adf330953be3a0511df32ad07a2ff701da0e151bdaa3fb485c84f0c92" . + "4b083f8f2fa0eb5c73480ab5e3130ab006d79350a9daf9225e8151c69ad2cebb" . + . + "87313c226b934c53f6117156734fcd72cc5851513623bb6d6ad45f08731f263f" . + "eac910a7b1be6e47a4e9b3a21897aec183e3fb69fecba562f4c6031a648e71c0" . + . + "e73eb22937604c672e8d0b33c72ff96c53dae220a7412d60607727b69720bf15" . + "7b9cfb7b0bce1429946060d2f6825616c247b26699c17782dc150b6720bec785" . + . + "bbc6d6d1c9af2225257567286727183d9e0df80a1f6e2f00fcce4dbe4eea9aae" . + "ca087ddba287ab79163b0412d10bc0e0877e8c10ce1c5f73572a407f6e0ce54b" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "41ce9216ad414fa1be97f83d47a7ec77a48271573e6ba239cb3af90e7e040ffa" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "549825b9b3330f68f4288ac66b56ea7601a4a859d56b7a6417ce7082c3d0aba4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4254f32c29c0617a3704ca426ee449f0e396ee5849cd1e0af83a042242f2ba56" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "428fdc7fdd96c1861e07a65becd0b1abe1fbcabc76e5cbfef4fdecf3851d756c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "767b0de4deb446cc0639bea226c265900a5c0222a33da1faecba6d32d133b1df" . + "7ea667b6586583049db91db86ae5197ed9d694890349fcd7c1834e4673d2dc5c" . + "34e78e7da3ece9f835bdbda1706c9e8717f7b66e28de7b6e9e2ab8df17af91eb" . + "6644aa7b5d60e148dec8145c282292f79908b99e4fe2ea8f9d4c66423511ace6" . + "023b79fcc880e6c5343dbb60f22c250f9a1320fe41a6d9603d6fda2762b5569e" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7ea667b6586583049db91db86ae5197ed9d694890349fcd7c1834e4673d2dc5c" . + "2ca1f1af3a627a68597dd51818268f6bb365af57000dc475d56bcd9bb0718297" . + "5aa7a7803788a12c6dcf710f045f304a71cc0426e20704784df7c0fbcf7294be" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "677001280115f913f9d1b8631762695c7c36efb28c2bb440f320d5b795249e0d" . + "e418a6a02bfe18403c9ea1fb5e548b2ddf2e8266593ef16feecda322a75e28e0" . + "fa1a579db51f74a1659e14947409a6774407dca50ef30e26c4964754341ec0b2" . + "6c1bd2b3e38c221e54f3bd0c4208216d90a310f46453d4180a1e4a74c143bda2" . + "adf6d281c6a6d8231ca6a49b483581c9344c29e90855630153293f43c0461bcc" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5ccf93660846a11cc05a45429754eacfe843864f5b5ccdc1a52d7c1f59ed1eab" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "061abb88aaa8a173d849d3b1e782a17d86662d889fc2df93bdf44441da50c82d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b4728036172417a0a0bc297c5b9ae7e5d2b4bb9bb75ce9a12c586a34f1f138da" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "508f4472da071f438c3b7b2cf229cfa1b77cf32e755f567107e9cbdf13635a29" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + "9102e745a921a15fe2ccb4073e12bd319e6bcbc5b2c29fead73701885c0b961f" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7fcf59796adec67367c078b5edc437aa5fe36b320e660848c739ae93e39606d0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bc5f797fe3364704fe7f194352da3ff523e1507ba327ee6d57d48c6888ebc6ee" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4fbfb716893c7093d7aa600ecc421cc7b53210b9af5648dae38871b9252f8632" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b664b565c93f9def653e5a69e5e48a5d6f3c8d8ed6b8af1b60da3d9b8030172f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "92072823e02d228c904c1f866549f98bfe52394a7b30f43f208dfe76878ea649" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "97e93f21aa85946645313d91262de753b6a72c2e6e7fad1f89d13adf4d66d61a" . + "a396a77e586baacfc59e9638492bf048541fa0dc925d7ef64dde1fcc9a7c18a0" . + "c8eb2767d5c5b571272176b68216e93e5ee39136d318ddb16515fd184de1fb18" . + "d3f5c72b30f971697226a50d8a0eab0857d51617f83a88db4078e3c49f7061df" . + "cfecb7732131d390aead9d81a7a97133eb6b7adfcb888888fa310b9466acc564" . + "21bdba33e813791092497221a4471ba013f54f97d88174f87aaed510b103dca6" . + "21bdba33e813791092497221a4471ba013f54f97d88174f87aaed510b103dca6" . + "36f5a63b54a9bfeb487d6ee9d8526c6c4820abe3d65014e348c93478970f8239" . + "fbf4e657294924acca4862173ee31b86b300ec94f8c3e0cbf291c1c1921f35a8" . + "7441d67adb563df0622a4c9182ec514a4b48df383ca3b7f1a8247f8b5537ef7d" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "665db136ce7af19ac06095048d5e7b5627fbcc6453094273cb2b1403b46cc986" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "cb25c00a6c0620f124dd389d69b3058648908bb09504929422beffe196c3b152" . + "dfb6d0c179b0fd2ecabef7d3cb4136d93298c3237e060e3b8da48a426ba771b4" . + "ae6c793a6cf210fd16c077482f19f4ca251711464e58a89bbe82abd4319e306f" . + "06b3de965a4c3318f80fc43672e36ba1ea307ca7a1c805f5ceb3e14dc35f05d9" . + "dbfa1785c54a7300ad8ab21545e5d489cf34520b16f809276a1c0595f83bfbb1" . + "6cd321f7885603c904fbbbd5f26607930861686e3a170870afc4ced33f3e2615" . + . + "bff2a5b49da9d0ed8536448a0354be60c117424f042728716ac7a55a0cd1b3eb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "05a42a4304cc1b074f8fcc4906a9901775dab926e961dc666460a65b63b11536" . + "b698b7d19a0b0c353f40b34a1dd0242ffbf5eaab008c5a15a4d8e0ae89e5f4e2" . + "04d2ce6bc8b00c3b5a8a9cb5f8fd931aa05926cd6b1d26c727090c099299dbb0" . + "cf62af88c0776ef50a9636918e1ee981ba0230c5e55bc3e7e87236ec61ef6260" . + "dfc6fe89a1fdfde394d9e5712346130d4f93b2a9ff2563ef11d8bef034da2330" . + "e451006bb0e86a59d7ca5330cea9f715ae8350394fa7b26695b9e37493de3343" . + "0d83398f0a225ca774b13c63b94935c4f726c505f209e0b2acca7c1dbf04762b" . + "9cc816c14a0072519d66656251bff09248eed53e4d1457d2651a03c1c9082ebc" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "a33c07f11f405376282562fce8769740a72aba7bdbc2309bf9b048452e55edf8" . + "b8cb43274e6f607a819d18361488fd69f283a06f878f2a1ee59f80feae17bd32" . + "b1b4cdcd83fbeedda562ebc0ef43517d8279e34c9bbef01d8f964ce5c1b0a5b8" . + "ce729f745178250275b42ca0ce473a0a6b8eb9a38cbcb6cb59ea50716c412340" . + "6357d35eec969c88cf875ea52f6e150aff4c82664f96ccf15d0be94d8252a7cd" . + "c52a5812398d23172dc55b89ccb3f48da21cebd6e36d5ae1488c4977ef6dd816" . + "2f38d9a22064890aa8d295ea6059afc3a15de809f7864c669eaa4be428a01ad7" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6741e8c47fd079dbf74169d7292b02775990dabf44383b40d4c7945e1e7ecbbf" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "e676cb5ea9c3123de668bfc7f58fe1e1d095cee1170a76fcf8782a0ae3ec934a" . + . + "fc28664eadfc34bb53d12a1f6bb74707e54d2da50e0dc44f7146552e3a4ec2e7" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "06ccea69167a176ffbcaa2b93b0a76fd55c3a8f21add3c3c5be64a49e4885d1d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "b45b20ef215e507e4cc94dd0da8ddddc8c85cf612999a5e27cc490ddf9545b09" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "a5f5c47f98af1507de915d665764bb8d6087fd99bb702cec83c49a90f846dc00" . + "e4f98f820d70b8b352d6060faaba1875e0c5f957d92b90793e146f23e830c9d1" . + "9bff087ac0f8d4a04fb4a958f9c78d3f3e0bc743bbe7fdf65f2e5d687d524d63" . + "b45b20ef215e507e4cc94dd0da8ddddc8c85cf612999a5e27cc490ddf9545b09" . + "aa265fc1bbdeb142cd6259d067c0bff1a9785dec3bb89361afcf114b4d9277fb" . + "f8becab402c322193d9eabada9dc318d3b93e4113e847f70ed555da933dd7a55" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "a33c07f11f405376282562fce8769740a72aba7bdbc2309bf9b048452e55edf8" . + "b8cb43274e6f607a819d18361488fd69f283a06f878f2a1ee59f80feae17bd32" . + "b1b4cdcd83fbeedda562ebc0ef43517d8279e34c9bbef01d8f964ce5c1b0a5b8" . + "ce729f745178250275b42ca0ce473a0a6b8eb9a38cbcb6cb59ea50716c412340" . + "6357d35eec969c88cf875ea52f6e150aff4c82664f96ccf15d0be94d8252a7cd" . + "c199c4e40cfd5d68cb06d9f72ecb0729085c593fd27642c44146bef437706429" . + "199ddb6178dc5af99892a35dbc421e849efeeeee44442a3ed0ebc4b3f18fb250" . + "469cef9eea4517fa0e068578b7f8aa6105755d810dadd798d4eaf96dd924321c" . + "0e529f1257d451fbf07fade631a5912792dbf1d6c9883c004b2f3295cf8d1440" . + "f88d8b963c250bae899d1e445d2b9d171650c83471a1aa5a5ed46b907a21d4a8" . + "6ff56809e5d90ae36cfa128476172fb9e29fb7510c3980c018ce2b600147c6c7" . + "1f274212b9e265a26d60853ceb15e1178c824416ac9e59923adb182999ccc448" . + "4a69f705fc64dc9ce39dea3f1c7c53700a8224a945e1813e693208c0dcaa4b97" . + "33cb9b506e3b6c97ad7a0316dcf7adfd9bd924190ab8b82a7818a18b7d8e9f78" . + "bc350dbbb14c41fb9217d91b691b6db29993c88ae887e510b59f5d315fe3da21" . + "4d61f4e02d582744c36ee267b45e22207f96dcd144a931cb1fa0924e2d413f95" . + "c08d6a17334b1ae08ee2fb5b74221d86ddeb37054515af0e43822bab9ac71b98" . + . + "36eebd9269aeb0bb6a62eec495fa977258f10fc58059b45eddb3fbb23554f2be" . + . + "9f15c50f11c913c7b87eb5c496a7078a51a04f48e9ad58aa07cdc78b44e40a09" . + . + . + . + . + . + . + . + . + . + . + . + . + "9dab936679f17db297104593256c4a4cd65dc40a471990589dc823050a27cddd" . + "3ecbba1011481faaca7962de04f0ba395e685308c28d4fe6e60c1ceab0aa9fd1" . + "842365e018f44b9bd938a78d1180a403f0d57985818e7da11c196f80c043cc82" . + "60ede4e825664cc0c97bb081ad43f41da9b2a04c79c47f4ef3cef35525258922" . + "2b1a104231675e08ec41bc8165cdc4a7e949b2215aedb761d0892643a91a2acd" . + "54359598dc5bae5e8d050a3a5248951bb73aa49d3d0a31cbc2c2caa11d718e2c" . + "b7cd5a0b5f47f5a11bda8187bd0572a59549ccfee0f3e1547225df561b0bd665" . + "542fae80622159f5d5acb66cb2977a5fdc53ceb3a1a9c239e2a85a11d6dff6b9" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "486dcb1ebade1349a71c73a4f584442909c690d26251f72d0c4089316768d8e5" . + "65122e90bafcff9b339f18d3d200f2de2a511568b29514a49b2b8a7f224ef916" . + "a2489885d81cf22789a8fe91a9e56512b079f1ca864485c9bf9fd4c31f1f2be0" . + "66c9bf88f18725517d98c3d73a534cd1aeff5fc3930c50e05fcab426bcc928a6" . + "fbf4e657294924acca4862173ee31b86b300ec94f8c3e0cbf291c1c1921f35a8" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6cfd1cf48c9bae2d0222907f413c01f8d99a601efd487292b49691ce7043e521" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "b61f72611f85d5d16e75d10240d79bcc3bace79daba87e0e40b52bce6e2632dd" . + "197b17865db4191a53e3a08c515ab600aff820208d868bc053a4effcdd38938b" . + "168a0a0d4515e231fb8220a4c9d25876d1c56045572f7a444db736c49338f1dc" . + "29990bc4a24c6315450eeaf9410fde4e9c030c6ba4c040a84ec0bffbe8f13cf7" . + "b7c1ccb5006c7aa09a8be98f15e35cd1039da812b04224194c60899958afc112" . + "206fc964996c368f89dff6d95454fe7ab53d687410b498c325680a4284d3fa6f" . + "264579c4cf7c569eab06020d61e057e943e1590514fcf024ded522f676f4baea" . + "90912725206f054a25ea40457f1aaf7f88349bac05d8550ef9b2cadf135ded7b" . + "5cfd48a415b73ae616fc1e86bea703ae52c2476a35261bc0c216cc22f68ee973" . + "9f18f191a5114f56f107f8c2d32bff7f59d71c34253e98f6b6cfbc94722de6cb" . + "b2e46d9036ba2ebbf88f090c9006d3946a59ec16a2f8b4d70d2d3856ce8096d9" . + "60754d8071992edd9350a94f47edd309469ae31126df5845b38478e6f477b572" . + "fa0917954f304e8a28a5fa06eb468786bc6f49082db3bc70557a2fda120ce371" . + "7191afbbfc3f052ac69d467adf198258c66da48062a183c8c03594de688c925a" . + "35056391c2a7aae94bcfa73ea1a243ef62e88ff494e8ec66078c12a6005c7b06" . + "68b50d67416c319e1619be4e46c6966caff3d51bd8e5bccafb27bd33eade9161" . + "00e05839b12cc5859ebe309cede98c03c881e859ed85cc60ae481430bcc11c55" . + "663480ef6d94f21d1e6195840b833287652f31ca71b20d12fc82420376a2413d" . + "f38c66a72fd98a7978b1f4bb0b5b18281c6b05e0adbe8c73e20bea49e92e6da0" . + "3fa7dc5c2c0091ebcb0b404e5d67fbe8bcadd809efc38d1628eda9cfc18d6de1" . + "ab17f55539f6d31098ecfcdb3b5e0a8155d6da38b11f135e3a997ee31f506f02" . + "6661bcf4c88cb1c85192aafe795a5e9c6274dea71ebe905d3115dad22cfd8128" . + "98e4e81e03e160c463d97a0f4ee1625e80e99d4bac788fa293609206f829e0d8" . + "1be786dc5f79367f59cce91f6f1c9632ba23c98e95bc3bdc58ddf23a19102437" . + "2db746695d4b4ca3be3389eaa4531f0961c2b1595c68beebd34534e405ac8606" . + "e8c4d449523d3f0cb5384c756528171d18b5df0a5560a73ad9f85e65e88fbb80" . + "6b16c05edc87bb25adb67570d943fedf6703ab011c9553a66ac835aea0a235dd" . + "5f8328eaa399f8b790d077a5d0e765a92f9d845fcde9e0806f49c67fcdc4c2d5" . + "a81a4789d5a4e0188ab7a2ebce5c3f644a213817ecdbbc08297ba4a353988b19" . + "e3d8f7d1e23fbb377fe355207a05c916014a97c6a91676b2ba99de204d13822b" . + "e028094676795696d758c181eaa73b34c465acb7a436fe31bad2cdfba656db0c" . + "de77a8961b5e81425e7a4bbfbd804a238b9150aca0638ce830daf2aefbfe29d0" . + "06452485dabc9148e7026677e292c62455e0c9387f50805d9f2ea3d260181876" . + "c600a6a044127bd0e28acaebf17739f999f8f40de72f33473a3bfb292d978446" . + "d5f58a3201b9ce71f9b56a22cbaa20b7a9db960fc47cd27e9cc4aafbaffe7a53" . + "ec5a96cb6bd7789236f34c6f6d46d5ba2817bc19fd010b1a85daacf46f7d6d2f" . + "b143f3bc04533be1045be1c7b1935024b92862b2479a46a3b03d5d3cdc0372ec" . + "23b259c11095a29b3233ff0227c8c82c7d12fc5c47b4f1e9d9fc3d0ebafb6076" . + "a04da301011e811b5ad7e3d69855459fea5a7cb9e00a5ccc99cae9ef7b4142fb" . + "4f625141297ce9198df69bd3aace6183ba959ccb443e80fb11fa12b5969a58b8" . + "6afa5c46ed0fdf8fda5747561bbefd25a338e40c4c66911a0ae15b69b06c4e1a" . + "52007be9c65f5ee4173857482b5b809a59e347648b7769ec81c004221fff69a1" . + "43258a1675d8bb0023417a7e5ef6b67e73b058a155b9502f02bb20064bf576ce" . + "85b6481000baae547fe2b16443a7d8507e70cdb8e12e0367ca5e96f4543d529b" . + "885dd0212384c5b462d0f882670734086864c87dfadbc4b65bae35d777d551d0" . + "4160ffbf3c840b79b8957cf44aff1ed08819ddb4c3dca59dc86df6516453f54f" . + "3628597f0ac168a41b50d6cc2fe7d0f010790afe4e0890549af22d3c6442749d" . + "fda491af994665f47a04f4603a56f9c740e240265ff9a06c5c8fb5b4268cc02d" . + "111d3d731b60523c83048c549843b37e4cf231f23248fdf7216423b7eb4aff20" . + "53c4d5147d8c031eb78a1d827dfed85dac7dad030b7ed3170ade61dd29b50c60" . + "482cc14c7156a9f55ecc8842b7e646ce9dffd5a17906af35d06094741b623d33" . + "c152516e2a0a565b74e45aaaccede727fedf4a9422fc5d8d2b32a6d47d0ebced" . + "17be99e482e144a2ecdf55c141a25a7ad7c12230be929ab8d17c99a210b3aff2" . + "7b566e61688ff6e81a1025fd817e0e05fbb97558ff0bab1b84eca7f0fcefe006" . + "ab1cae277975bb3dcbd588d4e449833c10d098363ea8456783522f3ecc015139" . + "9ad119ec707acab8d0583ea830a711cd0a899476877ba0699555b7b60c9dd0bb" . + "e15c91817b7e14a5e5045970f23ab9340370b9a27841ec329dc6a9741a0633d9" . + "eb40ed3bd547c6c0ae7cd1c11e579224e436304cb3476c8b4ea69caee7040a62" . + "ebaf9562f8c23df2bffbf4a24e2ea4242196d3cf13c7a34dce70fe4a5c3397ac" . + "f8ffb45cc83afb6a9516f7d159ad0175cb418412f2fee1586eeb3e057fbf28be" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "c6b2610fdc03b4a461de6de5b7523a958dbf96d005c2b117e8b0945cf1a5b252" . + "f71127181bf1e7089375ff481683de20c8582782bdcc4c18e3c88c82824effef" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "9c7f5d3858f8b5efbd6b354eac828c76aa36abb372c21c098596a69fdc8d260f" . + "a68f454b67dfd8429e41dca15c43c3171a94510b1daeca2c38d0b44561937e5d" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "fd69e60b1fc1719546c9d7ac189d4d5d9a22db5f2e900778937ab77548a1c6f1" . + "72633eb322205983417bb7611cb0ee61233678fdb5b1ace898759d75961ce724" . + "255be0db0035432ea7dcdaa17de7c6c90648dda2695a8ca7dad83f499e898a20" . + "23b259c11095a29b3233ff0227c8c82c7d12fc5c47b4f1e9d9fc3d0ebafb6076" . + "3aff223a6849dc08ac1c96c8490d8f6938c2e9737948034c8099ae3a288e8499" . + "e5e7f001dd2b273f9075393795f712d70dfe260e29d730775c51ae4f3880e880" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "9f3f8e317508fe1ac49b5a5cce6075a73b6faee2a604d15f0a36a74aaf812637" . + "0826fb9bd33ce43c400f51cb87c4936764392b50b03fb659f5fb4d8117dc34a5" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "f7c6cb1b918498b8cdbe998baf20c0ad37f7064f08ddb108b2eddadb1a58e00b" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "ec98aed34a901a0ec8f725716591554e7042e7176c596a3dc101e7d1b4463886" . + "fe3cf19e1d749e2122e9640fec26c6dc364898759a502ce96e900c54a629b18e" . + "c7bbb1dfa0c5dbe755a84168b84c7501b7cda86a83fa5f336f69967ca74fe71b" . + "b8c3e5de9ae1f3bb7a8be5ff9e9e4b45c26b68e58fbeffb7d0d2129f0710fa78" . + "8e098f3694b8c01180d9db234efe6bd84546a7ec6bfafb5f475d4101ba7ebf5d" . + "291acc086319b9600a865662ccb1a5a755057c48aea8cfed7ce4beb4fa0455c1" . + "23b6a8ffe13b65cfc468b687881df29fc3406821469091a07e2f2d57577a39c2" . + "67cefd9fc00864651882b931115ab2c33603569a65c63e38d2d0436479073ca3" . + "19e59635678ac9e86e33ed40e23eecbdbb79e3219c44c43046e94ff634bbd67c" . + "afc94498da100d79da7d12bb999e06c52754b224dbf71989b89395e5bfd93647" . + "0cca93389edcd23bf3744032dcdcb52069aff904b42a1bcfb4fb88b2f6d018e8" . + "72599ab40caf26f33ceccef014ef3f9137ce9175b19222031d46111f40a96110" . + "f44aa767da91a6d60dd07e1f1d9d8408c39dba0046fe7ee51b44cc97652b40bc" . + "6d720a4c198dad21adbcdc44438428e55e50c6c80d6a393ce9fdeb7ac9244faa" . + "29f3c66f44188799acbd8e4e57e794a5d8f9d8e13b035059c697bd90931d21a6" . + "850f49d5fcc6b3f753b6c37a620c1c2b48bbb798a01e5ab55768d61b1c9bc186" . + "2457f97efe621c2eaa152e5ced409569087ab9650e84fd0a2175e5d0f212cea4" . + "a3cbbe80f0d593dfccfbb224093cf66076aa660286087bfeeac43e5dfdc55024" . + "abbb617b985f5b8d37988914dc05efd32d8ed8513ffe6e9a4977357497421a8e" . + "b5aa814b834537f7775f9d8b97ca09f4ae9fa5284ee69f499cd492b4bb73d9fa" . + "40e988574e25dc56fa50cae3b5b6c3c8ddff77e6fb85de73c24e6276b2811c92" . + "b9de2adf96d5f073d491d951cb8bb1b0b061ea021b3770aaddcdc7b42dcb1433" . + "23bb1d849b0b7613106f866b8aac63b46043e896bc763026a700dc1e87d09d2d" . + "51fbccc85dc8436db45de7c9eaba60f2c737727b23a01397f9a2523d3d5e50cf" . + "67c3f59062adbc6c2e5c2dd7688b08f2e42f202a1188a0174419c05b3f680c40" . + "e3ed230ea241d39c15f4567edbf7426d17e066aadcc612fa484e4349064ee139" . + "345808af339060ba3f188fe6aabfefa357f2d687c430e7490561c2c099950c5b" . + "e094e85790d350c411a6741df1ddefe09424160b857769d05d3137a55952a331" . + "61b1339ee11e4493d1fa7f86a856a91224244c0a67659b44110179621c93421b" . + "107cb09d5b20d91f5b06e70621d580038089f8aaefd815c33d7ce55bf99cf536" . + "6a3186ae96f50cbe206fccaac3efd63887699d32fec55fa9d98904f91534e3b3" . + "2df85b1084300f2fb5afe432b275e2cab1582904684b9f3e4892534a7f83de38" . + "0e4c635a9e9628d32f21520bd183d1b321b546284646473dda5c517f02326af6" . + "bef58eb276ad44ff3b737b7d862dee457b9b942b20feb5a52f8b9475d990083f" . + "598cff909d4c4dfdb59078360f9b612caf833e804eccacc0c6c8f759dd90c6c7" . + "c5b8b1205a8acbfc3359fe87e5968111bde065c867053871a742a41a772d5f9c" . + "310428665894a4fe65af2e7cab83f92ef002eb348b7052c378daa5dae9cebab4" . + "8c5733f6913443eab1744a3efb9e86464d2e38712b696f64697b42013b73d354" . + . + "36006b568acb241bc6077a2755c539b95b3947b3ab7aa00e390844610a33a34a" . + . + "c885f490fc0da1aa4b45104137fc23ac2c0e6b2af610a9a484d3b99041ec4617" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "34adeacabd7570c9353f99e994a17860a60e3cfb32f727770597db8e9476f658" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "724823b55e6b5e8a547ad7e17ede06037471f9d38268e20ca6001adf523489b4" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c2b0b83cc44e23f96c3e32fbd1736d344d61f46c514f40efab3b62b92bfad0d8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "d6f76ecd03d0b7749541c580becbd28fa0db1568fe29778ff811446edc853344" . + "4216d9c266ec88c275da498a3651a45061915ea84fc8b05c8fc3e9c63daf9bd5" . + "a7305340d567a133a59687bb8cb2034f55e146968b21d750676c36c004b06d84" . + "63cceda2c5593c1eedf7ebd7e3b9e6d24527a47cd18bebae836d2a78657b6f61" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "77f6f691e2382905cfff24b46b4fcee41ab26946e84167aed72a54779ce9e78c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "bca94cc1e3a1b5541ae7d535628687335b706d1a0ed3ec014b0ddb4492fec176" . + "f7050b4f241bc96f9f9b67f4f72286f2c9737e74957aad8d4ba7c93ea59be6a4" . + "e2ba217d101421a0e32011ba2ed697063b7bc7d4b93a858deecf0d721b37a876" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9d8f407858c9f3f1aae38d700525106d0abb83e9d710941bedae34b487270882" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "03543f40d38dac8046c14508e516024f1987ae9e5de45b70a32a98b84812378d" . + . + . + . + . + . + "77bfddda5faa64ec410485f018d5c9ea53b49403aea95a013fc9652115685344" . + "c999e54ad8d5ede0ab71138bf3969ea178b4fd0ecc5d653c91706d7419d5294a" . + "1ee732722f7307f5d09dcab2cfde712504c7b138118d5b49d2950936e673d876" . + "c993fd333c31ac346ddaa0701817e701fa9e6a7b35db18daa6cbc24002d86934" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e122d28a9c216fb1ba207f23788509ddc68c01fde7e57926b3dd842be671c5cf" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "581e344f59c5d8c768ca52939fecb4b65e2ccfab26cf1ed98617a94aa8e236e9" . + . + . + . + . + . + . + . + . + "268c17639ff6dfed0bb6b85807a51c7fb76a504e6203cb4ed20cc006edc6afd3" . + . + "acd116060c83fe93ee1ccbb2b00ceeeb18f6fee2d0dd08b521027343ae6cb5eb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3e192d833ab7df23fb143e7aace5ec36c1ed1ca803729d4321cb94cfd52f5266" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "991e07229d4eba495c2f24874cc67fd52630f578b422c20da194cb43d3658536" . + "57afd33c6c9b6c7c18146029d311803b940cba38aee38b1f9c5e05882ba44d4b" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b74d36fcf4145342310c025bdc510b8d247db4f44ef5d8f216b05a647923e4da" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "3531bbfeb3fe8206a752bb7253adc467d3a597ccacc6c60dfb51b99a0540cfc3" . + "5fa33ca5f05fb613e4558461515fb6fbe2aac12b4439d9cbc191c504f29a8f7b" . + "b22d0c9878b4bc290e99c48a90f9d1f27f17b8121cfc0bd445f2fecebf83fca1" . + "904959f1368908ae3ebcf445ffb633b603d6e9954cce01bc75e38ede6777a175" . + "d5f8a05eb06fb6af9c135d06a13c63756bedc38f5ad03f64571990004ac0d034" . + "72652edd85987bf5455b50456122328fbedc3fec3552829319e93612dba22af1" . + "9ffd1f42fbe1502c99107422a4964b08f66e9d08f677eb7b019ae941c8146136" . + "91723fed6e880cb43d7220b2f1168b66ed47381258b3199749ac7da1590afdab" . + "29f656717b197fdff199a683e5156f570bd31eeeb54e7ac5201bcbe48af149f9" . + "3e876f0317790a9dd26094d2111ae9818773b1523b05ea8d47d33eb2b0a14421" . + . + . + "16298b9bfe0ef217cea3dc65065e92282ed7120a0b348bc876783f6b73ef7350" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f7ec6e5a84d0af7f13ae004f6b4364ef690bf0d280929d17cd120a2ffccbf430" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cf7c4a7760543e172ed3e9d4230f481fd8b08cf6371028c8e38546128341da54" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6656f12c884b60b5b97d93c90bd036f94f493061cddd619ce75a2c48f07bfc8c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "78033e8c162f51159326a08fab08039c82222349ddf6d40aef4646e169890eb5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a9fa4dd202f48fe22e50a8ee4516576948ebf958e217d5b88a66e076123c946d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0032916f34af58f5bd451d469b9faf1a156c039e59d2182f1e187830dad469b6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3c1bc5546d360b3f708c82ccd2874463baebd6c5c84739dd3cfbb1929b461bf4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "c74cec98962f4feaf618add0875e1b2e03978747e9cfc5e167098251599dbde4" . + "06c82631eca64b52f2340f89be5b1ba1fec13a10732dd3e2597a9abd8b264319" . + "86772815722db36cc310f33a6970d379414139c7fbb7999efacbec2e8ac71df9" . + "f464cd14fc43c86fde02e2120e225c8a4397b766c48dc18a94033791466f0255" . + "34f6da9e4a0e5ef931c1a64916e38e841895ee0ace279621c55a86e73921be86" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "06c82631eca64b52f2340f89be5b1ba1fec13a10732dd3e2597a9abd8b264319" . + "ef2c5aa8eb98b10a35a3becc3529734359f526968955e282d934898ef8e2d9ab" . + "d7167d0af42a5128978269a58000d21ff02ff5f7811ffbdc562d52b0fd34d02b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "408ee91fd130a796d8504c232b94747712be8b2545a6484cd82e75455b5d3057" . + "0b1e23fb2ee0ef0078d77e828da431689078a8cf82ed0b78a21b5d03d45441db" . + "ffc53b64422cc0d0ade195398277a8325cceeddda93df879d0ee55e0c8094200" . + "3e44c8ef003eba70cba4b1177ebee20e2b548c00723ab0d53720440b26e46896" . + "d3ea5b1712e5b674fa1d70361ac0d22c22c3c0c749cf38dd6f8bab4098487f8d" . + "7bd045082411687443cb4545e4f1214f690375800a56149c57f05d95996fb77f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4517250599d087b0d109dcf732abd36ef65e161839ea367845574e12f863bf0f" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9defef431c162f211d29bf226375ce42a17795d8071973d0fad5d9d3ae8c40f6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "eada24fb7d9114c40283e7fa2c0d8eec679f1ef7966d1961f3bf72d2f791e7eb" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "dc801b19b383537334f51c75ee0808c2eff5c1606beae1c84095fdf924aab694" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "11d399244eb987db14ea7a3268897f27cc9d20247bd323b8f15d3438c23316ee" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cc9b95849b6edf5d21861cc9e5a4b9d08325b3f217e3ee9b846369b51625112d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a76da705752368c316f08efdd43d7bdc37c4b1b969e3cca4fc9b33c23f0594eb" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "38b7f3eb055814cfc5e1a3fbbeeb34dc903d1feb45f889fd0217f4f22c15d00e" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "76015958ca01e51b122998d9f0bc897f7feb46713fbbbeed278a6e1d8393b651" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "10fcae276347ada0f81faa00c673fe6ffd320aead1868dec652dffabb2bb7ce6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "64eb8a4b11c8dee91d0503e9ea0594a570b7830cd90d393b3c0ea6056b73d897" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "25cab52c19b387160aa0a0778bf6292cc8a76a5df6a12cab4f62ccfe4d824e56" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "79cd3db3e8ca6d942ccef0b843d33a384acb8bb38c7a5eec29f79e091b3233b9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cc628fe19cf38409a518e7ca586b5fa339e77803fad4b1ddb4c260c9505c3006" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "472976b7555bac0916ca9cb3a35bbfd966352781736b917c21e1f474380e4573" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "023c478219f413a606c00035ee65196abeacae01ee340f85cd6c3e7e88ffe86d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b7f682cab2e6b01cf4f1a46e1d96ee329b56f24f049bf2814b08302b0683d77b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f813ad4da0798bc3c7e2bb6411c41dada41ad7d7fd93b5b79c955ee8fadf3c4b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "58fb90fb44e5990b0073b080f42ecd45d528add592127849f9bb82a00868119e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7e5fb3e4dc7b40501b8fe1f99927f0618c6417ea659c1ba56690db459ca97553" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "121a5c17f54de5059899ac2a88f03ff07ad956fc88e015d4ae13c133f4af6861" . + "b96e8de1aa51e7228568c33f79d3bc2b9dbb7b6ca52c3771d702f3c936a2ce5f" . + "bab13e3d0c7fb1a5bb38e71de8db1810cd41c5003efb5190926017a65a18b628" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "f9c78823ef36f7040756c023cbfdbcd95d42dd205ab6bca6561835f4af9b4a49" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "527921d4b59d532fb7deaeaac6fe486455931006e21948eb2460634365b8e7b6" . + "78c09c98294eb94679b101ed31976d99ad187e28ae6684164b4c92bdf0cb7415" . + "b2472579c76790f01fe6a4c0a4082b00cd5160f3e5bcfd1bb850ff6fcf4dfc1a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "ab435ce27aa771888df5278a1d70ab40e4b8a3ba46a7b48cc7cea87a69626cd8" . + "ab435ce27aa771888df5278a1d70ab40e4b8a3ba46a7b48cc7cea87a69626cd8" . + "e861ab8b73ca35d4237001ad361617b810f985236ddba22b9a50ebe3a61c1833" . + "7e37641ef0fcb54f48a33a0e40eb247b1daf63bac52a8c3a3a32ddaab6ee5434" . + "eef5c8fdd5c2edb2c84441beea88e1133ce7b21d6d41540d5c336ac48e223273" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "df9e92300075db82399c17b4560d4fa4079045542721e32e5b76bacf76cf0348" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "93f733a4e2e22e5327d74db81cc608b94460a40a908105c74503663f0c090e93" . + "a2a77bcbc31a1c663e5109d7d8452508c055b5ae995f36f9609539fac96733ef" . + . + "471f7b3cc114b3cf689f7ea3919cd93556261d395e42162d4f0aeb33a77aa89f" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f0ee41d1a2d4815ad69e6df4c965c644024021b9fd3521f1e5f38395896d95f8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ef5990b51020e2a5818d21759dfca49efd7b908091a2735bf6074b22edb0c8c1" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2e6103a25dbdaeaef06d90003badbdb89981efd5db3af4744192a188591da059" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "50def015339f3836d3805fd9d66677ae8713ac55a1cba28da4ba347791988dff" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "750ceded6335c96badf45ecf90a74600d7f649f91f32ef81ae58370d55370554" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7d9a0de10a73b303a19de76be347d8a841005367a2c0d186c18ee3f5856ad030" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "02a7df565067a335abd54f62fe3a25682ba18ca232a75b844a9c8dd657b28ae0" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "701e3b456fa92eba658f3cd8e28eb9f3c1bb7dc5a88e785bd1832ffb2554f861" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1b3c73646e1166e97d3519d6c3aa3e690a5351f8f28fb5c4c968a9fed44937ca" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c257af0bca76070ff20383a568d277bec5b5fde8130a31bdc9d1811ba390b489" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "09cbf49d644ecee1011cf54622c2040bdcc0cd60ad1c07ddf3f02206fcc1308c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + "fa4770fb0aa3fda61a231a7b2fa6cb0f05099f50158c0db5d185977f7360621b" . + . + . + "440841b9d65e775471e5026ac3192735a1a4afd5f5375715845c42a8a38d178f" . + . + . + . + . + . + . + "bb49fe5ba257bc1f4ee0a98c55d9d58c9926a9400abafa1492ae6b549520ea26" . + "c4a9ab84fba8385de666de3f0b0e76bc52e0a809372ab7df58e1407d2a5d1816" . + "aed847282dc555a1cd8877d2c06a0e5ec61da757777229e563edb37b1f141ebb" . + "20a507b30d40da8be973ab64c1bfcb069ff4d4704d5d6c9988c3dfe551d5cad2" . + "018fd4020a6514def88e49a5c82549ebade64c7e799aa66962c699e261b9377f" . + "20fe5012bb3730d4fcece058bf9723efbc6c6146bbf4caaadb3273bd1b130109" . + "a2c2a241c952e9448fd16c5aaeb878eb5f01fb06b3b3c4de0aa2503c69a14a7a" . + "d65c415a257447f4948b3c31cc3c26ea883f1ceb61b115b2981ca8dc15a59c0b" . + "d6a07f2240b9d4f42560cea6ad2960bd8bb613cd6a59d7fd4f3bc22a3cd79c27" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "e0f4f485a407de22dc01f42143a75d891eeb9abcc2129aa1afbf68ab42090a2c" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "ab32b3f4ebb407a1e5a13baa369fe28751a6445b4fb425591c86f6179535e325" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "66c9bf88f18725517d98c3d73a534cd1aeff5fc3930c50e05fcab426bcc928a6" . + "c0e5b75ca646dec900285cae754918b15583ca5029530e7a68e3b11cb96470e3" . + "f5a0437d24e4d5459b4b378c5ea9c43700b02a9348f6ddb68e9eb0ece1ed614a" . + "36f5a63b54a9bfeb487d6ee9d8526c6c4820abe3d65014e348c93478970f8239" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "197b17865db4191a53e3a08c515ab600aff820208d868bc053a4effcdd38938b" . + "206fc964996c368f89dff6d95454fe7ab53d687410b498c325680a4284d3fa6f" . + "68b50d67416c319e1619be4e46c6966caff3d51bd8e5bccafb27bd33eade9161" . + "745fd3ab09c557878eb817a04233f81bf31c8090c729e614a40d51676cb98eb3" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "6bdefe9cf42f1efa0821aaddc06acb84037a14918a51c17224430a9483471897" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "fe669f671129dbabbad33c6d1266ab471b33b23cc4fc0d7fdeb5807b18d5b60d" . + "20a507b30d40da8be973ab64c1bfcb069ff4d4704d5d6c9988c3dfe551d5cad2" . + "0e746a42ba178b7f1298ad45360ecc51735067a63ee9c4a12f2e930d1ffca42a" . + "5cf1d78a3ca4f9f4f5bde60556503ad5158370821e20196bc104c822aeb71478" . + "40f8c0f5283caa1f921ca9b3ec7719ac66669c065c43d23e36b6bd2daa95a59e" . + "277e86c4e552ecf514fe81bb90d6d05ac69e690b197d2da222b072e61f8fa425" . + "a691b02a572d6f56c59b3a53e3ec8ca193a68c6a3fb38d3bd8c5bcc1bf2c944c" . + "dafe443bc2d0ff48e48e8745a79347dbf38754c28f9cdda831c745375104173d" . + "b4c8a6446e3ef13ab50508db6a5a1d00ff0ba7890c9ac140ba93e8af4f79604b" . + "9b8cc6050756fc346e077819170c06aa2a520f907b4c486a67267acb5067c8b5" . + "8b4a455d82525fd1ed9d8fd60d13a9da8a8ab5cdf3fccad2cf03dbb104744811" . + "34c65840f4daf3c4f93bfa667d1ae71ffaf53e0df7bd5ab09f6ce2f60273b5e4" . + "cd2e6c3c19a1da3d064bfc91445d663386ce842305461d0218a81ba5ebfa176c" . + "1ecd79876165a916aa9496338f73fc96a4cb93f0f34aec152d2226592c23b188" . + "79357df99c07dbd894ee2a3b3fa11f8b2b94ec37e9b6a29e3cb27422d3ff1b85" . + "ee1a9e58a6e628c43e8f2bc15dd46d3cfac274bd252de7d3fb077dd16799840c" . + "870cf1f2bcd435011aa3a68891e5f5060c84e86ea06b87e7c720fd0c52c43480" . + "5ba7d5380732bc0ef21b53f75615f7f95f4be31c1e3806a21d806c02144a7154" . + "743b58e2a45dfd956e273cb42efbb12a70806314ea2e3dd128a7dd2aa15df3da" . + "70fa81a6ddf7a5885c49d8bfcf8b94b6a610d79b137c11c892060378377fbdfc" . + "b32c25a6906114d8b52e7b4e9a7ac9d188b6ee3d11c02061bada3d859252786f" . + "cdc67690e19ebd49a7dfcd7c42dbb6252458188ab5755be205c365d970987c11" . + "4e9ccf30875b552fef19e4d52c94de34a3a70180ab6f6bcacd60b0ca3f754fb5" . + "1b05a7b7475e41326ed7be98a5946125ebf14ff4e548e32f37f0e131fafaa20a" . + "1cdae354c11ac829965602514eb2953a893e27a74c2b750626f3a2af8ead32e7" . + "7a02d5df49130f3d2cfce1f176caced8843db35a9a3afbc489eb33748c32f5ee" . + "89d2b5f8fe8b3dd2a1c5687a1ec8eefacbe0489aebadaac5524ff32ca473af99" . + "3d79b04d87dfc0fddbe69a821c0a8952656ad8ed71eecc22333476ade8e2191e" . + "aa0a314d98711175d4feba7aa2c86bb8f4c55cd7929eb85c5539abd7b627952c" . + "b75490a2a68f42576e50a47983f35a50cf681ba840a8a88427461ba420672d16" . + "0a6fa0f940417df8e727ee1c5d8f40785039b345db32d54788c236516f29ba7a" . + "73d0ec7636331c9183d9d9089b5750c110c100693d1ca6d5ce024d50ddf88272" . + "a7dfd80bcb84c8ae5011263bffe7b2b599728ff981119c0f97c7d9a50cba8cb1" . + "0bbdd237291ca4deb0415913322660c5a439935b24e4b6e6d8abe619c7d70a90" . + "e989cb6b42f77947fea49cdc5185692056586aa7a2b7c369a926eb069a00f664" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "9c7f5d3858f8b5efbd6b354eac828c76aa36abb372c21c098596a69fdc8d260f" . + "a68f454b67dfd8429e41dca15c43c3171a94510b1daeca2c38d0b44561937e5d" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "8a766f0d8dd2cfd6e894a5ac7e64103877192dcdabeb06d9cf4e9cfd83aa0e88" . + "fd69e60b1fc1719546c9d7ac189d4d5d9a22db5f2e900778937ab77548a1c6f1" . + "72633eb322205983417bb7611cb0ee61233678fdb5b1ace898759d75961ce724" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "255be0db0035432ea7dcdaa17de7c6c90648dda2695a8ca7dad83f499e898a20" . + "3aff223a6849dc08ac1c96c8490d8f6938c2e9737948034c8099ae3a288e8499" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "ec98aed34a901a0ec8f725716591554e7042e7176c596a3dc101e7d1b4463886" . + "c7bbb1dfa0c5dbe755a84168b84c7501b7cda86a83fa5f336f69967ca74fe71b" . + "b8c3e5de9ae1f3bb7a8be5ff9e9e4b45c26b68e58fbeffb7d0d2129f0710fa78" . + "29f3c66f44188799acbd8e4e57e794a5d8f9d8e13b035059c697bd90931d21a6" . + "3a198a4272d97d95a4cedc59541dc17198af91367b3054252c92ee8bd41c8c85" . + "e2c3ac3829d6e4afa8c1f3f74689529d279a6b3a7ef8ff9ccc670df6d3771a78" . + "e5c8ee594193d5a71d979b05e27c26dd19e3e115706ecc704ed73a40f4bb7438" . + "dc4af0ac39ff09f56e0caed8e56392265d78b9e536d13637113b79d88a8a6781" . + "be32e343330b2cb8e0376ebdd0ca843b6bd0fdd5103f144755e12e35292f66ee" . + "607b1b1717c13e13b015d098be68a88962674e9503786c9d32ef375c3a2f1640" . + "513c7946352757aed6be631df9583d14a1bf761dd7fec09450de55896b36b988" . + "b8cb43274e6f607a819d18361488fd69f283a06f878f2a1ee59f80feae17bd32" . + "dec397b6184fbb0a4f643f3c7139dbd58b51f3731dd0aaf15bca801859a5504b" . + "a9c207023ae31404b5efeb6e60735901461b0c90f48c194f53a1247a872393a7" . + "d8ac82d24128f21595b6437a15031c3ea34600eb0e537985a97c994476d8601a" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "e2c3ac3829d6e4afa8c1f3f74689529d279a6b3a7ef8ff9ccc670df6d3771a78" . + "2194b73d8ad1c4e919754879179572863c49659aeb1a6a7dd8eb0642bc8babad" . + "4b98ecb9736e4fee9308f1b183aebb232357421a069bd10188512dc515bd68fc" . + . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "7d9716666d818f542ecc0b5964e3ca0f4fe194ee3c6c8abae70ce896a10c4509" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1287fbc478dad25fdc58f27b68568ab5d40aa8b1a23af57dd7c49ee3e7987a69" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "6e097731f0d50fac0e23cc9c1ecfedf73c9056a16f5f4989cfabc5a518302ea0" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "d00614a76e1bb0a01f7c90fc2ab97958e019988202a1a630777ae2d8a81af3ef" . + "813044f6f9fa6c379113b0659c57807b7604b70225bf9bdbc1545e26ae928a55" . + "4ac66e87a3ae39221ecc3d1fe12e17ef32746e47189876a0eab4fa1325f0d574" . + "1a41d04d53251e45d44945af6b7f1e0e30dedf46d1df88606b03406c9c1abbd6" . + "4974cd5ae023f78885c1ab9d415dc0f18cb01802bb093584474157da9ec79e37" . + "5dda6d8c53c46b17db1b9642b3e4ca2f1796f718f15b15b09b8eb84b3d0b5ad9" . + "b0f61f76b89745d0eb9db2dda2e81309ff6c34a667ba8a15784a751dd2af5383" . + "05a452eb2ece36ce0ab390c5f3e87be41ddc6f16512820ecc5581a8e7f6c2ae1" . + "9a419e19c08c0fc9d3217a5b645ccd629f7952757b8228e03ba32a4635dad1ca" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5527cf2348cc63a0f00fceb1e7d1a2bec342657da1333d0c76685da8faff41f6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "22eb380d4a502104f8247c68bc2c61d4ed603243c37274c1a01e326ca5dae5b1" . + . + . + . + . + . + . + . + . + . + "5d694a761c804482384ba847625ea0367a1e0fe3d01c66cf7ee23cd35762d116" . + "decde7b035a3a67055a4912b4c99330030b3e663c22f3b3b4b2efe9fafb007e6" . + "6c85945eeda1c4025df89c4f54300afbfbac5d923c911c111234a138e1a8111e" . + "2ee255020bed3e4c86f0b4e3f8654dfe01f818f85f7268ac2487153389bc1f86" . + "122f0522299f18b6363b5eec6e223b3c4a3b53951cb70321dbb2615df570626e" . + "fe55d188b4a8c60a5b83ea9d2fd3e2371b82650385038dc498bc217ad56872bb" . + "36ab1c79558a15258b981ee70a6e3796800f798b28479205238775b438738eef" . + "d1a0eb5577c4c6cd0448996073e87cbd48cd79ca16a741756010fe64a48471b0" . + "a3fa60e1b717003df57e2693263092beaf2b27572cf7ed2606986ed8dad9a5b0" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7ae3059c774ff9a6723625df15e2f5c9f7aa588ec94a56ad89fd86cc6554e565" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "97bbefce27cd1c3469fc81e72b90db9a6868e1888b7b0b21f77930a5b2b8f706" . + . + . + . + . + . + . + . + . + . + . + "4e8a0646c545385f5e6d748a524e835726e55311578987e761eb7ebd2277c955" . + "f5f7f9a736c82af7fb7a4cd6fdb1aa59c34594dd0f1e387fb3767935a2758b4b" . + "c967e51a477631b1debda85d5b46e89238f8f366cb91adac1d59b9f443af6751" . + "e6a28ca5fcf7f69df7b0e085e8ca0a85fbc27a644787af2c7991ece3cd8d92b2" . + "e9ec6d3768cd8e15081b912677d2a6a9397968947328cb359f8e2565cb4f25fb" . + . + "458641abc56c836e4f2ac3cfd852cbfa94d34731311ab0de39b2485fbb9f687c" . + "8b87fa0a5b4848cc6923c1e830228f3a5f00a43a63500717594597bddaef5821" . + "96999b0b01b4ef71ca17eae2b3243004af3329466e87cb94c208825501552cb0" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2a350c591bbb8dbd5cc7a68287865465b2795c51774e32e8f7fcbb19407674de" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "376ba4decfa14a6bac3af56b49b39e406e36e635026289ddb23a7df2279374c8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "abd656773f6dd2a0f0bac45483fec8c8b3998f35fd58cc52062098717ede3b20" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "65d586b9ed982cd8994751a5f5aaa4ea83b1339cf2e1bb235587afda222abd0e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ed6434ca5429c821855827bab7eaebd63ec5510a97f8808099ad2ccba77509d2" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8eeb3c1fe3dfed7798594362211b33d12fc3bbdab738e0047b0e4642f5c9075e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6667ed28b0c858e50ed2b755526eb0f5795e43a55d8f4e03eff696adb3388fb9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bd984eb44cd7b1239983bfe7b9d1ac2a66069cf794a70f0b13aae13bbeb0797e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3102c54dcb684b7ea8fb4b1f633d07bb1becc4de6373100aaba411560732f6aa" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "767eb7e1715d7396c33873609833cf190ef404a236f902c7e91e87981c3abd95" . + "ac76b35856bf3e1cf88887a11591220610b7007d363da7e9b562ad0a34f74443" . + "8cc70ce1f5d1cc152b374d705808de42f9ec6c543cbeb6d4038fd40bfac571ef" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "91201e01e05afd14d9b694a842ef5c4fcababbf1bf95bbd66f57b33522d9e3cf" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "dbffb1f41f88b90fe26cc19afba4f996b99cddba79a5913cdcd1e77dd2f8f0d8" . + "67bd640de6c0e32256ab7332a17563f19c2bde0fefbf4cece57cafbe9ebfd24b" . + "219162b34f0a93affe7500c3564736850e77368c54bc017e1220a7654cc05825" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "4aac928a448aab1a179a4b28037b59e71fce7ebc6b29e8803c5fd00d42199bf0" . + "b7a386e246c6c8658506255c61158e76e40597cb606ebc3352c8ea532e1d9c65" . + "661356322f8cf020da88d97425a86a664e49f1f81036b010fb8222843c30633a" . + "f7b7b6cb0761966ae9f3bad6e3e56108bc132356e14a69e2f1ab992e5609b188" . + "f90bc388ca82fd9f7a3c07e47d2c3c42aab920a59f8a08f8e084ef2076d42a48" . + "d05bede8f4c95ec204b3553408311c97a8ce6b8a198f9a112d0f78bf5f93a73b" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "364446896bebad858d27ad64703f515628dffd8679e977e9faf4d9721ef580e1" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "69c48112487c88825cb3d041a3f043a8bf9848cbfe97db95dbabd9ccdbd19d41" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "965d2ee8587c4cb6eff24ab408d5f107b8c7d4bf7fa932e5c3a7b593128d5cb9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1b8051fb9ed9fc23cecd3b252d3cf8e436b375324817f99bdd39845a1b3c2fa3" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4a06107ea689b8cb11a4e44bef35b455a03cbd5ec9fa5b0db6239ebd4a0b8f91" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "436e67623eb369204512508e3990c5aeb71c421a26e3d174191620a044fafa5d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "33b9dd461fbbdca410dc7735fd6f23b84ecbab7bac26e9da299487efccea59e1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f2a8c696eec18a59e543dbb027e36ff07019010eeb652602d35e61df53a7e5ed" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9539f3af7c8cf00f7f17df9a2e3a4beedd2577ee176249e73b749c74265be1da" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + "f30afbcb684be6f5913c63485a2e264519d728becf4dbc4d768012d59d78abfc" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d5e476147ae4541525c6a289e3234f5843a5b871dbcb334d14ff1a6fc9cf6c6d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c23fbc4f971accbc8608e10fac408a0b6319d149f08df050d0ae19b4638f62ad" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5ae32eb909aaaca933e1741399dcc53c7031d274ed9faa464002d233ccd13591" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "270e3faad699e9f6cf1399ede846bb829f6976c7a6c6393b73e5b344ac11ac0c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "8113bf14bae48c05a01b504dc1f0484392d2f97629345f14b56e528f6e70fcd4" . + "7f8c77b897afa731d4b1769957e777ec79031139bfd072ca79a53ba746974294" . + . + . + "26c2d29cff3fc5a8b2086154af7279ede71097e7013efae41108044eb180c23a" . + . + "5d733c4740a4307e0a6b738f801078fb62a9e0f421beb952a5610961f8a3b0be" . + . + . + "f31fe9e0efc5fc501076e451bd8fbbfcc32c74c58fed97bc8353e35a6cec4997" . + "4089edf60bfacbd888c92b0bbdf060355ae0ad03b9ed12ee3f076f6322cdc16c" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9ae3f9ddef134d59d932882448a32d2fd51348de881148a3d19f2485473b6f9d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ef5990b51020e2a5818d21759dfca49efd7b908091a2735bf6074b22edb0c8c1" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b3b5bfc7c8a3fba6fc4668e63ab55bf59aeeb056f67fe722b2d355d9e50c9ab6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "32f04800b2db57621da65979e0dac92f932e498a44b90f2789000e0381d53718" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d8e084bd447102cb06431ccc51147c3efa9c3baca1a6dac465bf3eb7e0506542" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d7915c0b4eff579adcf0e94d79a68e8250812702f43d827a74a9f89ff4eb49cc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + . + "61092aedbf2978ca7d81b991164a26d1f4ec0ab9b6b59b0bd2c2cf3c784db1ea" . + "6f6d35105ff21331bfe69b13630a5d87f89d76a8edf8228ccfa99b1427e75d00" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0fabadb1b0db9752cd71ef868f0a7f84c7eb018f37dec3869e944396de60a017" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "43744c4290c968fca62607f3427d23df10c9d052c45179d4272058a67700652f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8d8e66e428bef032e77e111772e34704d0900f8f21c8b144d2791f0155cc0bfb" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4dcd1a9ec1f769b1fb79a03c639ed292d6023e7cd383be4d13cadfc0f42e6ad4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bbbb1aeeb0053a4c651a7cd2c4ee78973dd3c4df16437c2ef6b66b90ed4b9037" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "668f51db03be92d61b9848b1724759b8453b659dc4959df686150bff5a3da9da" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "40308f7b95a87744688fa221ec23eee39c575d3882697353d80c287dadc470c7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "28af17d2c11615090348d32bc03419a3f85d8e12adaec27322e2c7893e4da4d0" . + "ff4418c9e3f15ecb51f792c89d61dd77807a231d3493a73d123ee8354c1b21dd" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e49a113acfbcc4aae1054120f2a9b7a64edc1b99bbce362f50fc3d3894974962" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + . + "e973b16280c7c3b8ea94295dcbc2ee5579c4bebfbd43c8444a22be8546daeafd" . + "9c4ecf2ea13ca6cb6e976f764ac8b228eefbc12268de2a528f10fb28db00e807" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8d58e70404f67179f274cf617bf253421d478519b990d4e208c8df21bf03f61e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "96427fded901dff82e39fa2ebae9902f4a0a222133cfa6997fc2a792dd90c3c6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b90b8fa67211b9e015a3a8b95e127338b87d1525e6c5d97468ed391b16b3c10e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "42c1a0957e160cdbb800ce20a5d024f1630a43edb9ae9a0b467f78a5d113c5b0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b6d1ea1c830eae2111ada30c38ea7b1348cf7621c6a1f88f3b74f6af4f1ee2db" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1622288f4569db1a76944137fda437309e50693a566b2301b19a6371ef3a8938" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2fbbdd27790d3e94cfadfb31494005db0fc883826f11f2f57ec09ecdcf0b0736" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "aeb6d353e108c2b769f95a8b6dc9c7a0e1e48145afb5a524fb588c55d24cf27c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7b79be5dae3787063ec0fae26f3095be217faa8dc2c1cda290618a11e909efe4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "edec3c7c1624b531a1d766fe9f76fa944e7e6482aa9046c293def52716ea2220" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "08229c91cdc48d0a8f7c510c55d3c8ad946a4f51a1f15ce206396bafb6e06e79" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f99f7d8e4edb44a918654086e75ff4f267e9447cc63f93aaf6044ba2f4eca95e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "538e32da31e5b7f8d9ed8defd7a876a09193ccbe6de149a01b72d51c0d92167a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "42fdb5a4050de536e5d422d27910df2a11bc684b95a0b52a7a7ddd537e571566" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cdc37af36ef746fd867fac9384f4b8f6fc193fa10e41d00c0e9ea83026d0eab3" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3ebdfa9a6b753f457814f68132afc9d030d204333dbca863740e9e47e47411dc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "902b7b262ab0ab6218033f9b4c7a2fff24fb717f93a2b482432484c3b1f37b22" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "194d4f5ecc369c012910b46b592532061b2f77a706e687d466bc31689eb45b84" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6d3c4600b33ee49c3dbb042c91b3083021c108932f1439a9a786d1970ee6ccbc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "38b9a365687c0c9265962ae7d53292639ab85a10251bc0e09f02310c58dad9af" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "383afe8f5dbfd2347212abde95ee54027294a4588b550b83e7a213543e3d4c8a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "64ec3dcd171a9558e5e1e81957f7f1d37c27c0673fab577d040511155faa083b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "19610509a217704dbe69d26217b8dfa9e55f12118719c4c135bf00a408a5cd05" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8e037e57d31f0cbcfe0c48a272db279a4d17ff396b85aed698f46be500942a24" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b2bd3cf365bc08343a4f0450f1f16958d87a84ce922a7303d9d5c7ff2f48eb20" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8a5e40dec695a6c742bb2e351843ad301fc335a9c4922d5a9a3be424f88a24d8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b2d50187ee179c197b9ddbe96f905ed11499bba9c8093549f782c05c8a9ffc11" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5260b7cea02c7c92559d8241910c22e44c371325b3af2d00b2b11a19ffc5921e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "463e443ee62f4d184a00cbb44f5014441937c0128c3142f18720aba75ae34c24" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "50156ccb5e55d98392291afaca1eee9901588f64f5f8c250507dc24357cfaeac" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7e1842531bb872ac6633710d73765c3e7bd834bb7955fc6b5a3e60c2f97f3abc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e4cbe4b44cac2efdb4730f993db5d8860363622cdbc788113fb1b26fa13d2e64" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "64fbb1a3f339baac6623913d9029b124c695596167de5d87ab09264a9feb05e4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "130401e9e0c2274ad5b38f421818c7b4e383db0c6bedb95e2fb9a5d4a576cff5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9f29c67c032693f3ad591eb0f3eb81c5dccb53820cad51a345c9e83eaf611904" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "386004e026e3d203a5ca556f4f1bd77572c534c42b52dd4860ae2751910ca227" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "afdadc27ba70c3064e3866425a3b885a2251055196fa02ad6f079e367c321fe5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1d3b379ad42be9dadfdb31ac0a6a54cc1b01f1ee8a7d84d87bad4ff74c7e043d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ceccb525789d94a4b2ed6fd7c2191c866f615d4877d692b91dc3706e53dd9a80" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "4daf2ce5e65d8397b6e8cb6e105a8958d62dfbcaa1576d7786b335ac92fc2a46" . + "ef7411a460225cd89c398a4d46f5e14d0a4fbe119ea6d57b9f178d71e93b2da4" . + "d05470da3f0dd4af48e0f8b6dc701a620280f54a4bdd4a883beb50ab86fcdd70" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "c544aa62e8cb313b7186b00c83fd6e494911dbf755bccc761725314fa7ccc855" . + . + . + . + . + . + . + . + . + . + "8aab8fe9dfaf585a63ae2df1a75567b65a6d93036632f7391d91e0930b935524" . + "ab3437a4f1a56945574ac47ef677a1f39d7bea79a01d97a4bc255916fdb95017" . + "471f7e535bcb1886651cac1069b1961c266e320b67f694ccf83b1566de5c6009" . + "a8d9b113f8941a569ea4142d11463f03c3381b45a9cd8be363a5e46309609be6" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7cc02703600b4f0137d7b3ef01a899f816e04878b6c101304f01b1d0a8db8afa" . + "d72b51334290cd4a30513254a41e87d620afb37513048fef88152deda31c7503" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + "c0ac46338b605aaecb720840db72615d30ce084925e91fd60a94b5acdbb6546c" . + "0bdd34f27977579077a35af00ac0e8ee64077049e63a9d612a2d8c0aaf498a44" . + "6ee9d08e6d4ec1613dfd60c6f3d2fac500bc08df85c3f0769a4fca660d6a12c4" . + "0c26d2defaee9b7f93125e68c0d730c6296226c181e12df920abdc8d929f3ee6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "d72ed4d13aa5a681c081cf0b19673e4601fa47de1b4f45a59517e3b92267869b" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "0bdfc6a6648ee782598820651ef87cc879e0fd227a47deb8c34bb944ca1aa484" . + "99b7b36b26c1ad4f3df21dc216485bc8fdff3889587ac39ddc7af1d3c34083ee" . + "cde2bd069b5e9772dd4b75e943c2d4429d85eaa7c4987f8862a16ca3ed5d033e" . + "4a402bd56edb8ed72cb497523eaedc4672c1e8828479846ed431c3ceb400479a" . + . + "4a764569bb33b880388b88ecd8e9cd18bf8f53da297ead731c671ba25286a54a" . + "9ea0c945629e86eb4b5c3bc64dfe6949a1395f4c5088bf7797831eac7ed4363c" . + "82932ddce217e2199c3cd9ba126ab94c5a0bca7f820ad501ad2f39d4dd9d90cd" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8cfda589ba81265aabee7c7b5bba4d614092b837667ba7403298cb232ca313bc" . + "025c175a032cec920061617c5cdbe71eb1a4093b1627c89a2f680b9e44b42d48" . + "07b1dec88163c8c477ee87aedc3a19160271bc8c4d95afa823aee247f7071d7d" . + "82e7e29a3444125fe833070e75a81e028624d7a8faec09ead5798cf6d60c820e" . + "754ce1628fea4907d35738512e2df4b0df11ddae29a6f50054c1c2c95ae9730e" . + "eb7e7f43b066f7be3d3423698c32a26abb537e2b9cb237f103d08fc6769de5c6" . + "973c3a2bc980adbe411371e8fef18db01ef073b98531f7d70029314374a36b26" . + "21a443eec68467a100371fca74c06e0423c8e7a53724b63992028c8ea5c9724d" . + "4dc7a3a8497d2ebbb024cbd3ffa0625ee860f31be7bb951975ba8817020d2bfd" . + "89328e72ae03df565d9d29bf323d302da3127f2bb1cdb07328e3e1fc1013b1f9" . + "6899d8ca3cda15d3aabc10a39ac200e96f9030b3d717eb5530ad359e8896a854" . + "04026699367517b01d619314ec3f647418485a577360bba9e92ba21d92f8f1e2" . + "36f84d5a28c7b669fd5260c76a612f90a39c4e09a1ec6a80ecd387cf8334c1b0" . + "b7f7b36dbca20c2f76cdc4d7907e3530ae44b3047ae93c62459199d7efa3cbd1" . + "7939e44f639e733f5058bbe6ffb7539df29d484ff3afb22560aa204a8c042276" . + "96e5b09f99297ff991d6e6b444449dd9a777ddbc28989473ad1b61d21115a7e9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "a6a7f345745d03f96da79a241e723526926a6066aaf702d13d8444b8a98145bd" . + "a735db01bd0c327146f044998dcad5d2ae3435b0f615cad209fa4a5ceb195ac0" . + "9e3264d6a9ed6aa7b63a96bc4d7962c2cc089063d0d3dcaad21066ebc13c1b2d" . + "f65d5fbe21e5b40632834a2464efd5dec6b7f4fe127f518bbdda121c875a2465" . + "e52a62e270417fe673b64e6c8e9ecaff190905178f89880f6a123f326a878fba" . + "e6a608fe6c2e49af8b0bd73a0681d8b81825aec245c554a47827cd359edd375f" . + "6a5f3d37162166775766c91dc5585b2af4074bd3a86ea59bd35633d3c5759132" . + "2f2ae20c1308e84f0018045f2fde37e24f2a66b7715b3e32063424f80e6a7bee" . + "51d3e6d4b65ba96d1ac79ee2fd8e38979286d82370c537a89f4b6b74e57129d1" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "d36798a414b0f494d88801623c08381bea27bcdafd303715f4c2d773f58a16c6" . + "67d0b1d9ba7b9c5770e540b5298246b61ef3532019950e1f2ea04ece4808024f" . + "eeb1b7d6f0ce53da7c1112deddb4792074ddb9f291a0e9a0be8ccbbbe8b6585b" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + "a13cc78a7f769517f5200374d87b978897fcecd7bd3d781f2debf6a963d1cd87" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "67d0b1d9ba7b9c5770e540b5298246b61ef3532019950e1f2ea04ece4808024f" . + "78afe4590c75d41e2178fefc626d83441e45532e49f4d955aecf5d3267935987" . + "1997e924dd8eef65e453c90de0d26abefa0da6be847adbedd9c34737de55562e" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d0724f8da6eca1cf2d1b084693d7e367508131550a4dec9fef701dcbc245f5e" . + "8bed7686df67cab54cb4be19d4389028408e5b6fc960084ed2a1eb72855d5db3" . + "ca8f7d0adf9d18f592ee2cc92f8086b2a6c47ac576575d50485acc8ba183e6e5" . + "5ae1510c12752a9a3d62de88009e833074830f44448033f3e4f9295394e6cf52" . + "6a39346a074fbe577dd55b12871d30d64cc9fb22ef9ea506e62d547f00e03de9" . + "17a7fbc023e4fde58f63f796ffd300d9494c8634ad538ae6af0e53e8fc1f2baa" . + "7b2863243a142ccf30dcc463691d992558ca18fa47b611734133b5574087d84b" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "2787f6d99b1e6297b880e5afa083057da8896494d011e7f8302eda4a55fc49a0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "6d8b786302f1a28d4bafb6ca07c40622501a21af6d188986eb47fc25edbad1da" . + "3f0281d2649fa611860481c0dc476a42a4ffe26b678c3762423f94459b8d0463" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "0ae06943a35eb78f5777a9acd24ff25663f779e2552aeec8616e5719d8834403" . + "aaed56f635732561e85208b7cd6b832b52a2d7332133ff817b612463e01a2c61" . + "471f7e535bcb1886651cac1069b1961c266e320b67f694ccf83b1566de5c6009" . + "a8d9b113f8941a569ea4142d11463f03c3381b45a9cd8be363a5e46309609be6" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f98620eb2a89c1a3822eeadf66d90ef0eb70963d0713ef50c838c0426dc513e2" . + "f98620eb2a89c1a3822eeadf66d90ef0eb70963d0713ef50c838c0426dc513e2" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "7ec46cc51defeb9085fbd810a59621bce226602c340f469903da703fa3506b28" . + "962a482d590353cbbec2b3ee85bc7477f5395dcb9d20eee55fecaba27beb2c1e" . + "2d234cc3868ecc1f51ed5fed0b7d7a20d249913f7300191808bdbd3d21d009ba" . + "cf2739dd13c1a65253b18ace67f4277aca7be059151d3e86e5eb6266fa5acbd6" . + "45231cf96a3603d2abba3688add2a10c1bc11fd092d3d8bde3f201bdbae88b55" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "d246c1c895fcc3bd14918133f8c4b5f18d63122d36229417571b8f7cd0426166" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c773674515469572b41d47ed64d08c879ae946193d2aa7aa3ca7986965ca2325" . + "7c80a1837b6dfb1468e3b65b9d060b2c0a1a0079704cdbeae8fe794975303ee8" . + "272d48f07b1a465f707d0c2e61f193b7f5c44d9f3266c55b8050727417967d8d" . + "72c462c4a8d6f2f331d6f10ecca9b46bf300635fb461521ec33b0c7671d77a1b" . + . + . + . + . + "1a75061a290929129fd252d609597de3cec4bf7253efc9e2f47dbdb1974eb499" . + "981b60931cd5383ac2e1ed75121f8373567cd008b084db896882a67e3fd06639" . + "58e6aced8827a720d3066526f402109a32e2b2591bafcfbdeeba7bac4ff2ec80" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "49b67731cb0e311d4712f86773b490b6fc9e2d734fdf1064f163fcd53529e354" . + "641e8d2dbc8b525c3ea65edafad6c61df3c503e30af0dabc714742980d0b39f4" . + "d9cc4726996b9e84dd5c43705eca32ba94ec8d3cfe3e435349dc29bc85c34771" . + "7bc920dddf18c29da32bbe44be46a7e66f62805965c41f7678a15c1e261ec009" . + "e453062b7e1a8faf2e97aff0aab0751f4da6b3a12009f3ce8a15e2df19575622" . + "17094dab774e7487172fab9fe4097a506c7b5409173d34a2240988516ed48e47" . + "9239b664ffeb1baa4b9d6aaa864a470c616e6bd47696b92579f4a7906f858473" . + "b609dc3be5cae953c728a484a807a04a72340113dec4b273c6ac3788aa38910b" . + "e2bf5ea74ad0aaacd2929b468f69366ab955ee397a254e7b9780e227320eb102" . + "a76e35b84cbe48e23b166029b6e9ef9e2caf5e4f5229d60a470be319cccf0b8e" . + "def3858fb4c7978a2f7b8439e6f2eaf446e94300faff47bc76273db937df71f7" . + "bd2250d3c669217084050f8b9c4225f7fd5e137462d8828017f28c6465a623b7" . + "5ef1d15d61e17d805fc4fffb3d3ead684fa0b40cc9ec8910d2ad4681cd2eea6c" . + "45ea09879d9030f11179770f06020db0b8190cd17e6424fe523c98fa145543b9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "be0a64522c4ef0b2ce7fd00353f52b90c71c2803aaae72b3eb2a0f1c0b002585" . + "b25e70e2ce11cdea25503b4dce87e3835beb196f117f040b599486dc980f41db" . + "58e6c4337f184220311df292811a413602132a5de6ebba07917217a732fdbaf4" . + "5d1d6dda8d6dcac22c3d6b815bc1cd0feecf14809c0626fb4bc5489cf5ec0744" . + "78d912d26b1dc611d1704537e4c999edf3bde45c7c9e9d1d49fa1c7a90701f73" . + "1640ba09b1e044938f190a9b37325e5c610c9d1ef57d74fb07f95af34d35b38a" . + "c282cfae6cdcb0762d395a48f5930f3b0752a431c6a22ad6a21b23bc19b00cb5" . + "921b5b8f0c44b83f32da270d11fc36c711a162c34b9ad2e262f3bdd8ceb05845" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "3cba71e2008f8663f05176ad996b4d2dffb3822d7b342d24c6c32b524bcc242c" . + "1dc988e5707763d85bfccb966ffc36055c830ece8f13ef8dcec11ede4d82a31f" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "d81c2da142bca67a663e81fb6eaa69f6185c8e651728bcb1c04a470baccc7af9" . + "5fa38d079ce21bb9d97558c34fdb455858f64118afb984411aa2418c6f5db492" . + "5da23b4a29349cbdffd23bbcd3678192bf5961138a72e1a13eb27a50a65e7580" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a510d29f1d031aa92fb5a3dd61c157392a3e0ef23bd04393aab636359ef9540" . + "8a510d29f1d031aa92fb5a3dd61c157392a3e0ef23bd04393aab636359ef9540" . + "b0e9caefe2d7d085b80d9bec3a79d0c0594cc25b5b3a3cdf36ea13afad34bcaf" . + "3c4e0f491e1f7e0f680e462973ad7f42268b933420aa11bde201257fb0966d94" . + "1e4a38d9b5032d6a7070fafecb610f7090811df467e0322f30f25697877e2733" . + "29cdd3a841923e6c92cfc48a3f5af569939a0db6ce65c2ea55ffb6ad54ce368d" . + "6394dec0fcbb026931c8d194155360393f97622918093c818c4af904d3912f0f" . + "0a4ef44e625fee62382addcffc1e2d1b9d1258c9a0d1f5b5d9b08776fa5a778f" . + "411db597ad869e8c6828d1c263a902969327b218b20780cfbd19dbecbc041d49" . + "dcdb9f7f6e3b45444d19365fd4dbbe046319e39781f017374465dbe6cde8fc05" . + "771e48762b0018959402e80125501ba028fc675a7b8f2cd57ac2b3caaaf6d7e4" . + "a8ee37db2c8c0a99310d2bcec3b924bc379b3ec6da8eec14d5b6bb64151528fb" . + "1e28339ab44ac3b29e897cbe8c6f70960ea10bb013f07b54f483813c9883b012" . + "404491a1ba3350cada4412d104843581acaa6cf9bff2cccfe180186b4ed070c6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "9f537e6fb799f427300e3ece16ec1d55122196793af5ded034868d30c0af73ec" . + "76262416fcbbe201d50a63f51bbf202c4b54295cead83d11f5ccfe9be162c4d6" . + "4f6a5fb040c9a58628134dcfb46a3e303359faae9c97c480a2490c4cbacc3a27" . + "afc17428fb87cd6f291643552cd25179cf0fc49baf89d1099682a7f271356139" . + "1203cba6e3a93f8f1d6b30396f68479481eefee8500fd9789165067ff9fcf18f" . + "9b9411f439d7634734a2f1bf472fe180ae84b3b2322d366157fdb5e8eb7656a0" . + "f6328db27fd3707cfc27e914dcd33f4d5786dbd20e75ada556f8451de455978b" . + "31f8be62da315751699561c3393b6fc5b9aa9101809b94c00e1226f6da0c1e5b" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "807f44a868274f57969dacff8d3e25f063e8b8e352183ec7f85810f4c56f8d26" . + "a5ea73b8e8504ad24f05a17a04da5de4b93e710078b2b00c8c33d9942ea1b2cc" . + "495ea9a6b592b1e98afafe09ac71b9e11112aca42d7e0f56e1a5d1a0957081fb" . + "1f8767e6162dc86df8e45202c2884ab2cb2c954366c381e571b6e7a4e7ac17c0" . + . + "dc2ee3ca8bf692998237514ba300433d450f6911b541480079c161511aecb8ef" . + "d9c14c20fede10ccad51d6bb33ad0021a38079f1fab69dfcbe541d94009b0406" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7c7875e61e9e14b6686154f389c03e6c2c97cc612a927c7e8f705838e354efaf" . + "7c7875e61e9e14b6686154f389c03e6c2c97cc612a927c7e8f705838e354efaf" . + "c1893a02f3b685f1f35081ac7038601a3adab551ac627c71bf12126c547c7fc3" . + "5bd3322028a86b89620b23d2982fd1607f0f0aebcecf8f252b1bdbdbf77b9d34" . + "d6374b4909d3846d575a0111f71e333d64911da3db69594e402e7fd516b0a36f" . + "2fe4cd25ba6acbabf6b7af9f13b7de249fbdd511a108a6c8e83bc3bbc330ec18" . + "45a7b2edc68d7eaf77b2cf3a0587d7b19776c84212e1e111d98d097c047c4a37" . + "5a735026378cb2a19208c88f35094d64eda33f070baebd5897c9a89d9ebf533c" . + "e5358d3c31c0a6814e8b0c50fbfd544361f33bc33306976f72e0acfd78c770ee" . + "07853a45b42a2fd0d474541be03fb860fb62f87be381caa5103f82065c0a1851" . + "0711b9a0772d1385fbe4070b6fb722dd7cc21dd61c6b8c6d409bd799929d083c" . + "03b1e12b50c38ccce258e9ddb97624426dc947917ea3db84a8b5919ad85112dd" . + "b0342923f536df4ad33ef5978d5687cce0adf6ca59cf3d9d5a3788173a4736ae" . + "e4475911e416997b67dcde098f51e1287622eba8bd767eef9dfeb51be2190986" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "6b4b97317c57e3352e254123f021b74bd34725641b8ab92281f91700892d8ab0" . + "9dd0010c0f1e24eea1aa6909b584a978751195181f995dbdd76d28607eb961f2" . + "4cdfa02cb9b9294f78eefaf79cb80119d5354e4b68569ad4ecde51a9d47968d0" . + "3d5b0b803b2d7cc70127227645ce7d7fb7d43b3258d1f83cc4b82d037dac555b" . + "6380f997ebb3926eada39b7a5a9f3da2f53a0f690f2e4954ad7466c373d5d02a" . + "00b01f4152ef0efccbeb726ba16fe2376fe8c558a9732288c6b0c83623fc640d" . + "dcdd280df4053793f68e13dc36828cf6269564093e5e5d24ae762a18d8b93129" . + "cb804637fa70735d1e361352b31c7c0fa0eb421d188cf623037b366d8f6183ca" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "9f7bf04132b218b1478e5723f3f759ac981ba67ff925918e399256bbdaf85296" . + "d14dbf21e4aad528933b121405182ab70497a43cea0e8b891449bc5a6a915ab6" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "ba397e2eecfc731e503321f108b106d3dab0c7409165edb0245beff772997fa2" . + "f7640392bb347b018c0236e4116f0081a616157c03dbc087f175c5338aa5929d" . + "dfc3472de1fceb7a5a39b3b8bb7e64aac54dd7061589ea85ca267046637e1665" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bb6c28df56c84e94e51974e86568f1c13145d9c9530e7adb6d9e540a399bf4ea" . + "bb6c28df56c84e94e51974e86568f1c13145d9c9530e7adb6d9e540a399bf4ea" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "44a2ca9505956369cfadecf7c0f7a81648b179c3a9b842911694dcd547813fd5" . + "c5dd970158f9d1942c25dc60b3361f00418a0c9fad9b4c07e299c2fd19792466" . + . + "0f4425c43ecc2237d6ef03ee2613d3c9f09a77f8c0a21f6550e2f029c025028b" . + "6fb0ed0c7f9fd0e2f6efe9025af5d265adb53001e46b86ebe96dd9b0cf1237a4" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "a42344c7437c8bf3db3918d67e77163f11a1f2e0570faa26cd52031a2733c70e" . + "777e21925b43440c10c08bc20d55d631b42a6a37acb7f1e070132678dd3bd2ff" . + "db10a1d41a668954aa451d8ad8c3c26dcc2d252fa7d0c76fa5961436c933e550" . + "651985a5cd3f183bb064a310c7c922861046ae2adfa862ba67a89062fe7d26af" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d9b2ed44a659a702297e7efbdf970c61506f2aa2c20a993d2617bacd97fc8ac" . + "6d9b2ed44a659a702297e7efbdf970c61506f2aa2c20a993d2617bacd97fc8ac" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + "d9e539b9e09f44ea4bf9324ddb9a737f8981c29df5b162e3a2eb1efb41d233a4" . + "4722e8131600e8ed49feadb7efed4520a4f86522e9a05988d83872b63e9fd232" . + . + "7a1575f203547adf52dea418a17635813b8949464cc9b857906bedbe16025e87" . + "7197ed7b79e61a9828f506e2d4bac0e86360a45116cac7af30ec52dd3ad10fb5" . + "272d48f07b1a465f707d0c2e61f193b7f5c44d9f3266c55b8050727417967d8d" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + . + . + . + . + . + . + . + . + "3d394937680687b04820b7ffd110d5692deeacc42dc08b2ed4c836f3cd42e938" . + "ba3c9ce7c3cb15bc9aaca22bc6891f4f3416f0ac3a4f704f8ee05260d165cfb2" . + "a8d9b113f8941a569ea4142d11463f03c3381b45a9cd8be363a5e46309609be6" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3ab6277823b1d9172a4c6aeb10172e5e1c6daf69a9f5bb0557a704bf5a6353d3" . + "3ab6277823b1d9172a4c6aeb10172e5e1c6daf69a9f5bb0557a704bf5a6353d3" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "00defeb0482021c80ad25bf0d025f76724b113ded119c00638a86bbbe61129c8" . + "dd5ff6c3afad92d98e76bd6d44375a16f64d814ae783f4aedb9f9e575e534b61" . + . + . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "17b8a284afb43af91d700f71fc52bcb224788cfd86cc063af585ffb8ccae9b8a" . + "b74213e3a638d910155cd46aa280a2460b30401b05ec33fbf9d83d130dbd5141" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + . + . + . + . + . + . + . + "5ed87c8f0f334477fd5c81ebb3c8ae393cd7d79b75ba1c14121aa2cf4625dab1" . + "cf186eba423a963818a3a5a31bae161982302e98d91e4ea71ab0a0dcc7627115" . + "e221af795e3d619313cc0c6c8343d3ef38fac0f5bc66fd62a0bdafe0356462e2" . + "2b7b746ee3e908df97dcab843f5f8a638a8010f882c405fe47de62f76cf973c8" . + . + . + "4d15378c0c02955bc71adf9c9859c88a6f9d374b1397f125a88ea00db890c1a8" . + "8fd4016cf05f44a935cd2ab4237af4dfcd5f009285da5e06427f8c9e4966c646" . + "8d4507cf04d0be33bc98eb1e26b6ec3f55d59e51d5c136de0f15c92113d9f256" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0b5ef642cdda956bcd298da44b2e3e0a72e1d7e0128792edde33bd4a85c766d" . + "22bd8c2ce7299dab6c026a83b7e7afa57a92a007a5d1210f88d604a3b3b9572d" . + "7e038ebac258ae66bb940669e531a3f5ba2022a9df71991ff67e628308e2028a" . + "02f1193b3b568299bf8fed97a278546321bb4924d95e52d48b59e8a62c61eef4" . + "02f664542c7048319cc0a047ceab75fa5f672b3b0d9b43477ff22c1468fe61e5" . + "130a02df166c26ed1bd7e2ed307ff7d398c087127a883b9bf0d8c8ad153788be" . + "a824e4c3166aa15883147195dd63b34c8bf8bebf59f5d571facaacbf458fc079" . + "fbb4c95a6f5d7b3ab9fad387797d983adb6fbb79d9c4564b8bf1e4d4c4f5073f" . + "882d1bf3a834aa03b522a0b3e35d59680dc4421322541ba8112d8bc4b6e07109" . + "598bea3ddcf60347a851afee8e935a39c4ff21a369f2a8419df9c9401faea70f" . + "6a0e28eed83b6aee3c3995106a02ca7dead5fd387bf389240bac93af8559f779" . + "3ce076ff3998a26eb982b623098a048897f15f08f3cf37fd1bb64e12ee51aad0" . + "04c2b989788ad5d7811b1f38ddf47a5a72e2f1d629ea8090f7b5bd3f81cb6ad1" . + "fa83b282fcd719505477041051eb71a587c634f3cb2d5d72d120f3924953be59" . + "6fe91b2a6e365053aa3b9ceb3f6dbf7be3ef12872afdb710c590e012460683d6" . + "c1e480b82ae7f19b56767bd6057d2872e6a1bea2fdb5cd9287acadd72a5482dd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "e7c629de375e63333c9ba8adb2c34cdee9f4c89abe004653a056ed015fd9b249" . + "68ea4a04d7960a188e79df019f4cce99b791cc05022e031ee20a6c3100cb6147" . + "a92288ae4711ceb489d8b51b87d9a644f726092ccceeec1035f1d5032deece39" . + "36a7350908a35ecb0c48b99ff1c70c1934e389c8036f3d59327589db28188591" . + "91c8a4404b9a41b7adbee796746a3805e9fcb033a96dd048fbbc71b3cf05bcdb" . + "55db2e5d8a45275cfb72ac4ae22d478f681a931aef4e324fd226141ed836745f" . + "6a3d3abbe9e43d77b55d815bf8b149629d1661e5564e2b9b2bbfaae3c080f1a7" . + "5cbf8921a13d8481af638cbe5ac84f049fffe23dafb3fab7327513a732b879fc" . + "b249e0cfe77911e886899a075843422561cd418b3eaf95534bb96b0eb3dcfa28" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "25d98300d7d56e9b6909f4d245fd0705bd7a0eb58b3e87e52d02b3d5fa69e4da" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "120c950fd0deef2e3ed10f411ea26c9b7758508cc483d0bc760ec21134cace00" . + "d7de88229714fe38eae0febe1061547cdcff3730a9a9cea6c2eef24850e9e4f4" . + "01a7d63972199ed853b3cc04a5d93ac19c673ad3228847eb1e7a5702941a88a0" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "d0a3a1ba651a744b4ead7438183162372bf6c3b7a71e65d4845de2d24487452c" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "e2dab42a98635606933eafd20df23ff5ebfb9b3804a6b0f8d447ce0182c2f5de" . + "5900cdd48bc0ff3c2a1f7a3b7d1e81227a691877f9a63bcc8f97b2923f364506" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fa71015eaec00e83813b2d658af03253633bda88cfa2d66bf1c0b09d272b1130" . + "7ab7c8579a4067f71658bcf914b30aae189ae2bc886cf3d285ca6e6225b15db7" . + "01831a984d95e4cd2d86c7337309f6a817adcec358ed6ced303500a78e42269c" . + "dc2759e4dba7bfbf3f7ac6783a5f5f61c71585240a343d65048eaedf39bed20e" . + "ac99ec01a880d2df46f31f0061cd9cc995e622612a10a01e657db1c82e1c5321" . + "4f53887d4c35853b6ed9cced75799eb8b930eac39ede8f3c68ed6a6866f48eed" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "520bf6aad67d5803a2b9a429d2fb5dd138612be49972480ec18be4d1a2fa9e2c" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "19bf67b7529461a4463b9ca4840d21008d430519ee41458dd8de7607decf29f8" . + "75788e8bc7fe02c09fab976632e4909e664b6a5bf105ace8f050ab8d4cef8fcc" . + "c32258116fc5820123fed50bff6cc339d905df30fb9474f7cd5b5abf5f7c604c" . + "ef70d1073aa06010579b2e4b5b90f2607fa1d174e5b95644726f170e7232f30a" . + "e67a4390ab6f15feb50b2e8bc0df52196f96fcedef2bf5248de490caff0ce232" . + "8dbc91fa53b417cae9ddc09d6c587bbc42b0f1ebfc34e1917d6d1c01ced2862b" . + "542fae80622159f5d5acb66cb2977a5fdc53ceb3a1a9c239e2a85a11d6dff6b9" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65beadeae6ebcc5329d0ef08b6d356354a37afa2a1fdd8f488f03caa1ec4c04f" . + "65beadeae6ebcc5329d0ef08b6d356354a37afa2a1fdd8f488f03caa1ec4c04f" . + "5b39575e44415720f5fe44747dd74d8fce23ff8d3bd59d68f255437e5c0a86bc" . + "951293856ad8921a5fd58b3e2959edaac29645bfdf0089166b56521d5d909776" . + "be5b67fe1a489c34921358cd5503b197b5f10385ab6a11460263052cb0409754" . + "fc2592ec3c5a8a41daadd0f3f25b51d84e5c8b759bd7d0b5398a5ef97f185d35" . + "962cf8fbf8aabe774f4ec54eb4449c80d756b5b06246979aba63b452a95baee9" . + "148a864f2e4a83a2354275c9b138cbf198c79640ec4761bcfc222e47868dedaf" . + "21248ffb6efe3c0e01444c737eb19f5f145bf41eb25e6148ba1a5c1953918d50" . + "eadaae9efe271304415365ed5e984bba10bcfd14fa8c0985641f8c3f0a92b801" . + "97a4c754c97dbc24f4876a45dc67c726459e4b42fe23237e4c2019a251cb219c" . + "6655124372e49512a5460fd6d340c7a2cfbbe89349a7b1b91171a24b4e939d80" . + "7710771a5b0eb94389ac83629f26d942215884614ee71bbd60698f6e34f378be" . + "20faccde5b095aa36632f673bb313afc65950febcd01b6d5188110c56a7da31a" . + "07d4384f8089beff7693d38e034d83b7aacd2388f69f93963e030dcff99660c5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "f618ead583577d412eeda832d4c8315a8540a2ada22d222eb09429072578d511" . + "76f1f95d5197bd323b506a07d44040d4e2b886393f4d29ab4f0b9f32acd86849" . + "1a0fb7eb71a001c567137d77cd21d9e3e00ce922a240d32fc047e5ec3c1a7005" . + "a6a7f345745d03f96da79a241e723526926a6066aaf702d13d8444b8a98145bd" . + "6a0012ef85bf987a6fa3a50c1eb3acea2e96074a7b75d6ac8846624b7da9c7e4" . + "3d19b3fb45d83b6fc6a295b405bce4118b4dbc031f578706f31758c25ef6115d" . + "a69717dd219f05e7f17a81783ae85d50ba7340004dd327245a63fd397355c7d0" . + "3aecea379bddd4f4a73d389a98726af99f51c004c656ef35fc44696961cfcbae" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "fb9618b334a62f412916271531910577d9f47c204df7f76281e080a8e341ea56" . + "58ad2504c0147554b8638f9499c410ccace94ece119af458533fe2170acef183" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "7bae3ab544b5113a4b0839e3abf6d4347d4b21dda782d78944160f913577e461" . + "44ba32571a556232435f0afe8ed24bf9e00fa61e2be7222ad24d3e78cbbd1808" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "457b92a79445332741e04b7435efb9f4a2c17833f15669bd6e5eb7590641da8d" . + "457b92a79445332741e04b7435efb9f4a2c17833f15669bd6e5eb7590641da8d" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "57fb1cfc720febb0adab43b7ba50523917e5bde4251059bf3159f793532285c9" . + "4c25117375b96405dd51200ad732c120e9f6b584f4199340716f3b6b9b64a25a" . + "52f747af1f3936f5f7ff598d6226f6a2ae0c4f42195fccd20ba4332fa0037a8d" . + "06eba8fa9b364d43c8b54c1c61b07ce9e085f632f3e08f15fc7a4c42d2637dc1" . + "26bfffae94a2f439cefd16fdb07a710fd99a5863a355486f96a2b2fcec5b67d6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + . + "0e1643aeead3a2efbe204048a5500c69719c3856e705a229952e9479929255e6" . + "9a11b95d50ff11d0d61a3b0d7fb4bac495691e1475e128337d1bb017cfdfde51" . + "0a0776dd5abb2022fc7c4d82e952c8930f69f05bd5045a78a5d1c5fba9a47b43" . + "106d1bafea2f5d4489326f91d866939a11a113bfe59f42736e4041db9055c63e" . + "b1c9944b19d632e255522ed5bbf4101490051ea0dc78ee460fb7627c85cc9611" . + "fd6d35a37bfc8482dfe774441c31820666098f88095ec76c7374e3dc40eb6e3e" . + "f6fc5b84cb6abb26bdfc32c01f4f0f586680fb2b2539085eccabb3290467730b" . + "d58b87ede6637b32103cd62938829fced4417f61df0ee34396e965cb6eb4cfed" . + "9d476f5610c062622666283b8aabd749ebe1b7d7d6c6cb174bf2a0915c56417c" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "5c69ced51a8d0f1b15a47c2b6e4bd2c12d9e723c49d872c5c2499e503c391822" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "665e00e2c9a55193b60966af95ee3f68bea484747179e2e209092cf806c2dddb" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "64f8f78508193d819043e3d4417f3ad782ac6f531113ec4b383b9b016c147079" . + "e0f1694184228348b4c039b288e358d683b462414bff030a6fecb1034b49d421" . + "192a6b645531f09cbc898f7f7d089ed620ced66dc50ff33112bfa8dc5c9c9fd2" . + "761d9bb24eeb7b0fc7ad0650f0b3f8715673eddf63d254231800b66deb2d9e9d" . + "669757eae8f89eef26d0bd169efec918e8a29becd3d16ae1aa3fdc0baac71053" . + "8851643f7d626fd625a0034c10d44f06bc5801579766a5fee4af47a7774015b7" . + "8ad46b8225281d66799ef6efad65cf367f7799b08c73d057dfa70d950a0ba9c4" . + "cac909657bd9ef5914b4b59a1707dc6a4a4fb193bd32e4bc645ef9c0693a4e68" . + "0f2252e9fda526eb7c5faa37ff93b8e7f7e7fdf0bac1f6218f1e0e78dd73ad79" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "24172c1214c4a2bc1fd001035e771b3d9afde0d25823bb57a05d7b2227a54b79" . + "f50cc3bff3d303d9b470cc1f726a5aa1922829448de01141bc125b0beeddc3f1" . + "28e749e50df57cfb890dc103ee0e9a8e88bdba5360d29e79234f62e83de5c41b" . + "6d35a339272e2bfc9f2b1e9398ecc119553408437d09cb21d462d640718d26fa" . + "b649e87600e3f1fa29f18c0c411169a82cfee39c93297dd5827de7b6ac561b40" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "8092b174dae3abd147b335210bc6b099a4b28003b537b39ff4867de7d90c0c87" . + "49030d7468321834fd167f41c26a31929fb197f3cb9414b7cba3fbb7fa7d4bfa" . + "0b58600496b44a42bcb1250bb250a7f895c4521a84b5d356dc525059d379060d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "510857879d2188670cab573b8b58dfb056cf7c0ba6c64fed12a81701085553e7" . + "2e9b5cca33b25cf8fe83f513bed2687959854e25cdbfa11c846f511f8c1df152" . + "5feab7a2ee51c3519af0ba75400ec4a0781c95295e866589ffc7ceca488b1c33" . + "073680069bea393545bf82d4a608ec5d64e9413a0c59f3b6a94cba7ccb458d42" . + "aa7f95039d33f9296831709e3418abe452a6cf4401a726b2e0ca1e3f0a34887e" . + "6b7e4c0aa2300f7bb7de8bade40a78a0d5aa1c3cc5b71ce2a9519622df367da1" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "b1c9944b19d632e255522ed5bbf4101490051ea0dc78ee460fb7627c85cc9611" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "e77248200eddac96ad684d246d25edc7e9e3c5000d295a5c31cd357294cfae2a" . + "5f140cc6509da130c71dade0f7f83025d10621704aff658dcb6ac6d6b52961c2" . + "cb0515907f4376a9e21f541085a2073a3beec645d8eb18145770dd816fe81f6f" . + "17745a515426841697251425c9c69b3da00eaa930034e1ed7b1ed9ba7d8bee72" . + "4d3608e950b7acb0ee04fc3abae7766e0464d9410660dcd51679ba62e36ac63b" . + "9cdf8bf3fe70fd1afc7e2a00f221769f839a8fd5c26c7a5ed86ae86676d5ceb8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "982f0e645dc94c6ccb640ef19cd87a3558af94c2cbd64bd12cfce57190456896" . + "982f0e645dc94c6ccb640ef19cd87a3558af94c2cbd64bd12cfce57190456896" . + "faa441b0793344ba2b8272477283344fee48ac6d00dbc6876b487a956f4f200c" . + "57d7bc1b981ebc7d87df38786bb562c0c7541ecf758dae481865cc1407a58b36" . + "ba2141c4dbc188bccf427d1644f782fa8ef06c353edd68466f910f4e754dff90" . + "2a5f5de3fe08662e8cab9f6abb69ad6ccaf42eceef57551d3861ede489c015a3" . + "7f76a0785f53c06a8f45c1db24e5e014fdddcc279bd3b24022b69e8a6e4183cd" . + "45dc40c62c7567f994be6e5b51e27a0875e0732b6de9d4d9ef088ba00e9c92d7" . + "1d8157e2e985b4f1575735102b716e126ad10c16572520bf06b1b3136ace8e1c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "f0080b6ec8c5fd13b94bf02b68083cc13211a4a1469a645990fdfce2f445a613" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "5f7f17e37607ee654e0ef7b319c02d2eac75df9e598e62a4657aba7f2713e598" . + "5ef2e79b5b842eb9c360b3a5435d6eb260b024dd6a560542d1dbb73558dfbb30" . + "0f75f2fe55372db30a898c992cf5ce776e3a9bfd76ffa9d7091ef37d22e4f91c" . + "b03c1b2b5858e716273f554adebe91df200596d0776846fbf7014978acc7b57d" . + "25b295eb3ceabaecf61d0e1f8c74cd284d35c14dc201a3c8e8815dfcbd7e5e31" . + "1277a2036f78ccf4753381eb2fc82ccc9416e06cddffda08d249db7763c0d68b" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "615abd594b5403def7bce46da131eac4c9045069fdf064044fa9f0900a606a90" . + "615abd594b5403def7bce46da131eac4c9045069fdf064044fa9f0900a606a90" . + "eb553f38ef5c078de539594daa32541c0981622461ab255187d7111c74927a10" . + "3cd3bb4ab99a3d5aa350a3652fa4c20c8cb9fb24bdca16c1ca9ca9de2fe13c81" . + "7e3fdd886b2160dfb9ddb0d0b1e3e2acd3aca993226e3fbd37ca964068a5376d" . + "20faccde5b095aa36632f673bb313afc65950febcd01b6d5188110c56a7da31a" . + "c9189ea5df8a8f76a02e13076b106a4bae49935343d27285853cf5ffcef8ad3c" . + "1aac6a6677e80f400879d99c0c8292f6fea776dfa4b8f5eb2b4ca570e8d179c6" . + "600ffe0e13f6cdfc43a8e9f8455035a27e73d984df6d04c25f0dcdac1bba7eca" . + "f0274681eb15cd8eadf4e2ecd1c8c474eb77cf8847fd71d87985bc913de3d6c5" . + "3aceb3a830f219ecd505f0603397a8e9ee915ef15032a2a3642fd46487362139" . + "5f01e320429b5f5096a1d0856d7576a0d8b6caba14f611a2e85d3f1e7b50921a" . + "0ea91a1e2a50a8c282f71e846b35287e36fa0bbcbc0ecad427d1a7d5a2af7eb8" . + "0ce8fe58a35962dd3a485c7c0d0cbc6e049101ae7425c2a49b530f1511788f40" . + "bcb18834663277cc37cc91305af41c3966a9cf03daef52f2aef1a4a05364d79d" . + "361f005cfc6331fbfba5acceccf0be685162cea04abfb70db471c3692c5d0584" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "37ca276bb19c3237df250cd4d0665c683752793bbbf3a480a8600fac40b4c464" . + "aa782ec521f9b9a4d563b24cf409caf08f5e70dd3a57b32afcf765978e43f6f9" . + "72a641963aa637df2554192fc38e4ecde6a49df7e54e531e91bf11c12a09330e" . + "761b114bb2a3f948d616c19eb3444af272fda961fb7d104c0f0dec70fddc5de3" . + "1551a792281b45984ef6344c823f5ecd6cb3e7356747cb9ce8cb9de7bcbe9c9e" . + "0998356151c897979579456ee4d4d9705cd1090ec56771831cdc9d9b1ca154ad" . + "c632bcb7203a5380ca763375f13d97b2e5cbb426c4559713e85b672af95a5cdf" . + "485a12576f69d522b364d00505a250feecee0ed99534648f2d2e89257c0222a8" . + "a0c8d1cbc6b7521baf2bb70d32f4f1eddb2c4b933274a9dcc2db8ee6b1321451" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + . + "0146659d61e0f36fb55647ed214a2529990e66603fb058fbdeb2c6e9e27a3c89" . + "c8391d297c550b8678e990854fdc45590ef4e6765d70f607a0e65c1d19351b1d" . + "b0e9caefe2d7d085b80d9bec3a79d0c0594cc25b5b3a3cdf36ea13afad34bcaf" . + "ca8d102a0d958c5e62ca723b250e8d0302914d321bdaa5e15e7b1a7aa1ad2f80" . + "0146659d61e0f36fb55647ed214a2529990e66603fb058fbdeb2c6e9e27a3c89" . + "78bc5beb06ef2b5be15c257a81fdad1f3268168e695b4326762d7bdcd738c1db" . + "097825c064918eb40d9c37de8835a7655b929d80cddf92198ba5226df17983e1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "76ca0166bc1ca969d249075d34df7f8792cec53e6f2186e3d7d97fb2ac2c1a7a" . + "76ca0166bc1ca969d249075d34df7f8792cec53e6f2186e3d7d97fb2ac2c1a7a" . + "eed3e97df74ed27614214d15f227e4a4c7d4f092b3794d329f2716bf0cd69c40" . + "4a6469869e69378ef40c0ebd371485cfece5c6ca7a415891717cc090dc1f3a0c" . + "1e53f0d1e89287d25bd8d0ceda315e4bde37a8b179bfc0f9a82f89b947f1d671" . + "ae7f526cf00a62986beffdb4ffd9c4d2e901d92fda83171d10b37178d3d49b10" . + "36cafe36b06516b16332d0f01fcb53f2f1051ef437b4eb31c5a91aa24e7a74e8" . + "f042dc2cf018439c22945d8c829b63c216a39a97cab73fd1a305ac2fc4e0b9c1" . + "ab97431bc8f4bf4e7f1febc18f404996573ccfb041b64996e84b75a1962762ee" . + "4c8ee56b7a1de31164668bf63b33e0573b39e339302dfaf92fd3a41b3b824190" . + "ad7804f471712801df410b9fd2bd9407c8e28cf5982037b174f76c710a73dc75" . + "7f7cc9e8436627bb4f35dabcb489e6e52b1ea6210cd526e2bbf090ed7622389e" . + "ccb52b53cc29ab14cd2636d1ce5a90531333084e7e4ada4239904af565b70a2e" . + "e604f65d031231d22727052bb9e7c76bb81c146e231047e3a5e355118b8058d1" . + "78fd848b84ac5c5e564acfaa62b1e3f7e6bd2cf74fbb852406703d23a2f4028c" . + "9205abba7fe1745d4503a0e913c49c5d1f6b6db3143adcbba081566d93e5a01d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "92c3412bf2c655f951d859c5c30e1efe322a58074aedb67664ed8a2cb0ba938e" . + "6e31a6998c5d3787f50ed34aa70406f43b9887856b479d793b779325c0d0f2ac" . + "90faa8b62771bcee2f948892fe17301465e6a82a3bfdb3881c870fe60194a0cc" . + "6ff1da4f8538bfa0fd7f0ab1cb30ce4a0f1e7fffc6ab1b2dc41f41d08400c498" . + "4306d58059420253f222d3ae4a432063255c7bd153ee5e9b272028497b0fba52" . + "4ad394f4cadae5c8196452aa5030119f1deaa3ac0434b465d0e30c8a76053c1f" . + "975b3e34ce325138198122e55aab8e11c19d887abb74ada6ec69b4ba96e26d27" . + "44433ba57d318114d3c5e3bf7ed51aef608773b3a140455aab509e756c5e4ae5" . + "fadf93bd2931059dabd0691bd4c1d0eb929fc62fcbde38cd200828432ca7f57d" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "f7305d1e68e0c15023dec8ddf3933f2f9d1a6cea23f79561b90c75d3086b7996" . + "e1f16297186696739932f06df7ac7cf2194c9384ffab7b662d49e6ad161db51c" . + "e7f8e20b953be14f4c60629e35bb2bb98550b449a233cb25285dfd18da4ab071" . + "ede4f36a8a791eb11876ca2dbb66ec73d95b9beaf0bfbb92e05e416874a65b2e" . + . + "22e48e96152303b89e2fa3aeb0c863fdcf6e59e91fb0704c530f7699865a5eb4" . + "f3611d9edafb7ff5d27e3131281bb77e635457e1ea4b847af2fc0e06aa5b1ef7" . + "a653f08a2d3afe432ffe256af52e41c63b2c5232a18f7ac12a7a7bd9164bb0f2" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "945027f2673cb31279ef0ac0b6058fa98ad63fdbe1aed927ae386a1cb46eebb5" . + "8d98e7530ce18abbbcdaa3fcfed1e9526e1d0000a03ac3274cd369fcf0b2e0dd" . + "c23ff19e4f58e941f493249d85fc64803d8386518f795b9017c3f8b12a2c60a2" . + "a6dd043620c4442ead1fb3af6a22bf9c739f819efd4e9b2bfae0b5eb8d367cbb" . + "6ca64249ccaaf816c9fb618bf16054246aabdd1f42bcf15a0d367e2eb0e8539b" . + "7a5cec31f412a3b936073ff16c70e86a22d7ee65ce228f6005c82de92679be1f" . + "fb36e8f3838077d9e6e09da2d2a4f70860d4e3ad0ee5871900d7f33f574a6400" . + "cef40aeaee5fc930b89717e475f8e8f6f2c9e8dd3a1b75bf72e7b8f5817b1392" . + "dcfeb8608f1cc3777030acb1b5f5deda19b4487401b811969b40258dd6100374" . + "a90319a30bdb9377acfb216e4a750d2f6309d277df9088241ab115be6b0d9f78" . + "6c329771c1829b6b03c49c30bcfd9cb567055ca32a244e68758256eda18be734" . + "d44bfe7b71ed91b46afd65bc8c1cca44614f6ab5c0c4d727d1e8161f676dba3f" . + "e41e7ec3a4a49d47372cef952c71391936c8fcea53eaf99b25c5192b33233f47" . + "4315a911b0d544c2e4dfba82e056cc0ca33f1ceaa4cc814ff6f34d927fd0994a" . + "b18821696e809fe0da729780359d85dfa554510d8a70684c77053d1178723ad5" . + "e2cc8eeaebe8d0cf4fc85b087bed24bf0a9bec3dc5988b8c25ba55e99cceb0b2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "2057d48e671ab3c2807edf3dd1ba2f3469f85dd17cbbd7e7739d62b1edba22ac" . + "c809bf40f79998c810d3c8137861dba7628062c2573c8fb1a9e6d83235e1798c" . + "ba8a3dc8f4c55d3d738491f6e4c7ec12133917a93c0c22ebe0032a8b6d7a16df" . + "f925da8124415088fa81ac1db45d860c3e2dfb2b4c065b8825db832d1fff416c" . + "85d597045169fd903c8aed2709a30883404396114d12f0000ce5a68f91a1e806" . + "a296feb453634209624a4550f233b12665032b22c160c14f558796b2581476e8" . + "904c0570c34d51b121bd6ab265a5a2c8b51c2f205443087d1453dc50e2709452" . + "33fed8f1c526bb5e3ed321f166cdfcef76e9d52267f076d3a27b9fc5e2afd73c" . + "9f3d6ed57666fbd0a0a9a91f7d25a3a14ecfc34ef781590cb8452f64a803cf65" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + . + "03ab234b6be6946c0a80124e0b6f41c0574108bd88cb271c7db90011f9392ea7" . + "dd62c72b6a5eb8dee9c2687306a35997d42b0152d86598610bd3385b4a1d5132" . + "227cfdd6a9e505f8221d6da019ddf4c747cb54bc16e9d274010a7d0f9b050819" . + "209977a8f062b69f8c4d3c5d84387643d900a76af65854a065cd0622b5e686e5" . + "b3f53b940ecb9a41fbd8779939cc0138e5573508fadddffd4a1da61d06a9040c" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "356104dfe8c4d66797f8de046ce13ebe500d19479485b05ebc20d44410605791" . + "674e531033922539e5bc22f5b16254c6e9a33835932b54f5740c9a7358b69c4e" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cb72ad08a1aeee22436c611fbb18339235d4717cc94d55c6ca99686c7470a480" . + "eb0b512b21d408528d518fa4ce9ba1c4e651076d639ced23d2a132119ee5edc8" . + "c1e2e6d25c0b920af6f9fad08bb291ece497cada1dcb1aed62ee97c04cf591c2" . + "8f7bcd3f66d1646e83d8f298370bc0b99ed4f06e6fdbefb1fda7a0a086dc751c" . + "f522a91398e9f125f4fd8279dbb44353ee0dbfb8d182e730611807191e9f0e16" . + "5d958fc46175cbee8868b84c01b892586d67eb1e00386fa1e6a73cb0b0f7e91e" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "374ec3734fe166477fdeeee64688e4545c5f2dd15c31164c0948cbbc82d23d6f" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "edfd7ba7708245a2d5d5f2ca420bd610c09b116b2a2678409366597dc7ee4baa" . + "d93c38cc0ef620ccc2235193143ceb0dfff5568cb0e02a9652131c91bc5f679a" . + "1534f7e37e8316ea6248ca39166fbc8970fd3f7387befc2067209f7281e0c1ce" . + "4131b5a1503e4a620369302397ea34a8593db9ac2965aa77f41908d881157207" . + "742f2d801440ec2b66cde5719e75c63f3a49b88506fba3e99cee37c90bedd9c2" . + "374ec3734fe166477fdeeee64688e4545c5f2dd15c31164c0948cbbc82d23d6f" . + "b421410ba04f432d20605df9e0f1d3f5807f7b6923e12eefa56bf7294f1dbf3c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "ce055b1b0123e9a4dfd94636d20139754ff3ecb55fe44949f9960674e15dd9c2" . + "a4710c7fb71a83c2248ebf041937dd99c030bc089ae4df643406fca8b1f36939" . + "0a90e5e6477f0fb3db40d82c789f3e5f744c6cf6563f764101864be78a1fb6b1" . + "2aa8ec7d6e5ffca04b7a089dfdbe7eec5f6ba3106dcfd05bfe32be46b9e96b59" . + "2913140872fd660ef0d6a4b253abf43232fa8a106de9b14f52bb73937ee47950" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "2fba9c606ef3c3496ed3798d38e310a87c7f1664d232a265ce6ffc66ab81d719" . + "e09dd333feb4d63f72487824bb1bdce7b1b5a5f45abaf257be7829f0c2d164e7" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + . + . + . + . + "5ef23caf0ac5e17397a80a468184afeb815cfdf04b5c7810a7f76a0e3f453aa2" . + "a4209592198035f06992d8f2bc520af26bab01442fd973a4aa1e6c2804c88502" . + "8649fda3736835cdd4a13f0ba1c753961e1672b92a50af8d7665dc5687949cfa" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c9aacbdfc70dab784e953e7489a4c2cd4a3d0188db897aa8f1fb6d15ef3b785e" . + "c9aacbdfc70dab784e953e7489a4c2cd4a3d0188db897aa8f1fb6d15ef3b785e" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "fedffcd8b64b0f6b996758df6c8d418387e5e16b0b8f416b682e143754ca3a3f" . + "1ca12132bd5cb5595c740b7c86e37c1b814460a598f6ef3d42621cab7bdd4593" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c01824c189972de6dc32fb447fbbd92b9cb25c41384449464ffc0809d2b557e" . + "139a2568a13fb6433a58b635ae98f446fa6bf209cd7d69b454146a27df92010b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "6a461111a45548c7f2a55fb60746caf502cbf0c8c1f80ccb47dd6a508088118a" . + "7ffbf588d545676ef3714f9c1aadeff098a7cf772abf39f93873f59f1e8531c0" . + "a506ec687f8d54a0891a6034a6c2485ba9776519d39948a619084d8cc9480263" . + "d76d043013dede77f1bfd16714c039de5205fdfed7983e0c0e8badd02ae9e3c7" . + "c821dc4f278ff7de133ced545633fd9da4f261fa57268a49b6fe5ac828ecd69b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7ffbf588d545676ef3714f9c1aadeff098a7cf772abf39f93873f59f1e8531c0" . + "3ef0b08355da09c23c0fdb17edae60b23ff063df671ae3522232f5953c799347" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "62c8f296b6b0cd61cfd3bdcd33029e0067abc9424085f5d55fdde71591203ad5" . + "62c8f296b6b0cd61cfd3bdcd33029e0067abc9424085f5d55fdde71591203ad5" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "8460681d053c0d10f150181383a721c0c4b59233eb3098b4a53a36da4075f715" . + "c2e8d596408cf3a8c3f1888e4ddeaee335f4a38c7fb1c16c463145f35743968d" . + "8515f7671886568ba438b0a629a52cd11922ce004bc19364c23cab26af342c88" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "bc7218c4f0b08f4d1902fc5973bafab12a597e3c7d25cfeb66f2d2de1aa8aa85" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "37de5d2f99d5453cf444cb39770a595227e38aa62372a32ef3b7efd5cba833fc" . + "c934b062ac07d13abf085086465aa50fac7f4b286e416f291b9e092fa9dce0be" . + "a4e2f00c630e2bdef0b08746b371f49f89d30546d6de8ebb955c6c15b3017fa8" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + . + . + . + . + . + . + . + . + . + . + "c934b062ac07d13abf085086465aa50fac7f4b286e416f291b9e092fa9dce0be" . + "9f241e4e2dcf2ddf0553ce818c1152a9d4f60e30dca8c2ffd450ecc8335e3d6a" . + "9aa412cdbc4fe69c4e639542d37e5dbc2f47d0aa1f6b9fb6785f31d709516a74" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "01984b96840a41dc97dc548a15ec9c1a626b083bc8830c65db69196e701c5333" . + "01984b96840a41dc97dc548a15ec9c1a626b083bc8830c65db69196e701c5333" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "4c16592ccfa8aa6de186c0f7474badfc854fade31960a0c818b51ee343a9773c" . + "804ea48a5d8bcec8c4b8bc314a1d1caa8d756d6550409cdb4a0415b351bc32a8" . + "3c5e051127ed747844ef8a5a25a5c638bd2eadd06971b3b4b7efa69aeecd7ca2" . + "164634ecac853e53433a13d998afd28f5528aab4d35636043903336bf652c6b0" . + "a7ab086bfd936e319f4993e2d52632b40d6488bd2813bcf70957c8a66d4abe93" . + "e471e956e7408dce5cf15705778f72b02236d555a4039ae8c4ed2b5aee924132" . + "7e2f6af978f9be11776346f15246cb9830f00a93a38af92086a1c4a871e7c5f9" . + "4d5f523f30e73fd2e20a85f8ebdcc3f6a24142e0bf35c50b81fa0475c275463f" . + "1b9d7736bd8954a5b5a8513bcb8457cae793ff993f8a651bde5a43c36eb1eb75" . + "6d3e3e762b4b06e6b045b208aa9fffff44a460d372369314df91fde8998abf8c" . + "4cddbca13701729c14572f8dfebc2e7cc30b2162ccd401f0fdd4b7a0b3435f1d" . + "89a317084a49b5968b5f01f20d336bc382ccc8ef7c5138acf7aa180357976252" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "ce50f73a980a3c3dceb0fee68bf5fca211dd61f4dd5856ab8177dc34337df81e" . + "c5d375681fa3c040c4643f3e3524792a9f30e7ce3dfed7eee118e1ad56e90c89" . + "ba204c073d7e09c4323c5b9f00d0d606119f44fe604d8d15188bc9fb9f72d9e5" . + "d6832397f18678381bbc63171ffa371e361f27d40ec98635c7672b57045441c4" . + "6e76c9c450e677205047a90bfd0a2044bf4887984a46135dd45e123bb55233d1" . + "604ac8516b086ea9d1f44319c4e92ae83f33b9c551c01d5cdff3d27d45fa5018" . + "9f8653a197702e546fb0e5c6d0bb10f0b1851e22c391b45cfdc1ff5bce752717" . + "af49722ae9ec55bca64ea72bf33aa093490b6f2a2ab96237a4af8aabd648c09c" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + . + "9f21f408b9b2c2ce0581f21fc576d3f02ea8f9b0ed7c9a491c9498b567d48c9d" . + "8a97fabbf3df53bbbf19a5deb6318ab188da2a7c2dc166b451859580f4e7bd6b" . + "7a92254b52842cc3afc6774ddcc339103c617cba557c1fbfc5292f4bd8aa4931" . + "db0862bb2f949871459d37829d6b8a850ad3539b25affd0f2271583151b11f3b" . + "245a218881bff5baf36c1b9fc998c08bdc47b202ccd2fa34e3adf6c7b4d859c3" . + "bcac6c5f51d3b94e39e882a8acb09c271efcb83307b9701d9a6bb1153348b1ae" . + "712e07a4d6cefd925458ffdae3a00503e68693ea86a0c41b9d2d1246709a1574" . + "a0627b8ad34f2504fdaaca43133ae055674727051d1a9a129a704639174dbe8a" . + "53cca3e095e16242ea939dccff32ee2dbf9f3c60bbacb663390ffcb793c493cd" . + "00ed3d835958682c890011902f0a1e4e3c9d6cf69dad08f0692cb4e0efe23850" . + "afc2e571141f23f748a5f56df59f92690ff9a9dba6ff16804607aa10c97e9ba2" . + "a6aff8f9db81c0fa744ebafc761610bdfd05e1b279162e8af775cf7f073724b6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "3beba55a328b035f9d1f7fd3e695dd926f273d9b874361c814bc8b7bd20c98be" . + "6c7c331b387ce63f2ad570dd2c4a3f9383d28390e225c02aa044728873926e7b" . + "b98a1436dd1330741446146ba3446b4a743f3b91ed08f336dee8870489f7c01c" . + "09a0333861dd4a07a9afef8212a591fa18b59f9ffc131d4cdd8bdd258cfa17da" . + "ff9623c4cd5d9b04cfdc284e425266b3d62c25c7f29e268e8b18a6c993317e48" . + "ae4528757282ccb960af39c80030889daf5292de0b535279df4376a0c0ee4006" . + "85b6d2c3399478ecd344ec976090c10b581a1638225079e3f7ee57981497d739" . + "52c839fb0de723996f5260f2e8f45fab8a94503da8a35761212d0b66527fcbfb" . + "8c2492866712db0e19bd0596ae68512f0535db881eeb2cb35b8d5007053837ec" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "24fafe30d1b6c8b94e58abd11d2da97ea0a815e46f4ad19ad8f39eda3ea595b0" . + "9b2f7d27b216556c8cd912eb331b18eda39c5e1001891af837673a5bcbf95fe2" . + "8ec4af613df5f0663dcc3b0525afe9140fecc2dc16ad74a2293b0f1194fee571" . + "d5ea83547add32e0b6b0a50cd81014a650710f8d425d9ce0261883b8b1886a61" . + "fb5c03d77e424d7d7bbe0e5015e06c072c87fd63c114e96c13f7850b83c1b7db" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9b2f7d27b216556c8cd912eb331b18eda39c5e1001891af837673a5bcbf95fe2" . + "4115c99d7949635ecd09bc4c2a9cbe1e486b4ed9dfdac60139bf44407e417adf" . + "99d54c80794bdd2a41b1343d251aec41b9ab2048922e0106515d10f9138a5573" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d4f1381f39c6f4d6b3f8809479c83983882cb8cec0e8a2bb48024c8210f060c9" . + "d4f1381f39c6f4d6b3f8809479c83983882cb8cec0e8a2bb48024c8210f060c9" . + "57076eda3401912cee7d47e6060e7de34d47ef486193e0b33cadbeb1aaab0ee7" . + "c7fa6e3e22e50a4400a5cfdd31d4a8cf59f070155edc8fab80cf8f420b94297f" . + "55cb4df4ec87bb42330fff4ccc23ddbbea8abc78def66f9f04c1d763b91ff10d" . + . + "c398698347aa6cf234ff41f6d1131a1631c6ff6b61ba9d4dd1923b93386f0ef4" . + "1367a52b81efd86315e90f7019bb361c9ab5a111b26398a0868dd921b9e385a1" . + "07048e687ebb5cbc975b742a04a1718033ea2c89c6418743ba744d961f00350c" . + "40da2d32732bb49f71c13d5e3bb8f516c4e36840e097ce405d221f99550d574d" . + "ae4dd9b8b4ec75500c55df8366faf092b6bbad04280dcdfa45d33a1fd875ce53" . + "f96e5c093e0031933ead32ff625f38e93d64b4392676b9c8a7d920278a9b5e84" . + "de1e858375a787d523e95657fe7d0f12ac8bfbcb5a01fd19f9900c8c316d4219" . + "86be2f882ee99296a217e466e744b608b359eb39d30d20515e6d8c61222f8767" . + "c67bd53cac498aa46602ea4885062f1449f6810c6d211fbfdbfbe48bce2b64b9" . + "283d376a89f38d3f2307833aea61a7f083c274a3f6eae48ed5b62dddd5d58df7" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "16ccb31b6b2bbcd961fe8d2bc557c4cc56e5269327cee1ef1c1d1b5de53177d8" . + "65a17a7cc23de3c7595d6420afcdb2258dcf7300092906da0b9c2f9c9b196caf" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "14d1056b08b413088c461dd40879e540757e2e5272a2347de443f387d43692a2" . + "834aa4669137329c1c705aa9c10d6565bc8230d51ac6ec1c3ac2f653be5e7c5d" . + "242726d906eeac20f586d4595e6bfac264412acfea5128004c79df678ce560f8" . + "1f4729a57d79d2f250281d70dff83087efc56eb785195dcfd3651e42fd5e72de" . + "07f887812a7e50940f877c6eba895bbb757ace1685d49246eb216ed91168e0ed" . + "e2c9834f8d316341adaf54755d9dd67827a052218e32a1af06f2b2c2dfc786c4" . + "2f9a359439d326beb9dece7e75c41c62bc86d5a4bf0f11838a8f7950d565f5f7" . + "539c67fdc24a406abb1a34a946eb98d2d5ddd72d99de742b4477ee4b2d8daae8" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "a6a7f345745d03f96da79a241e723526926a6066aaf702d13d8444b8a98145bd" . + "760861e3c0b4ef204a4d1151da81a0328d5670676681562d0b7a26cd7ef30ed4" . + "5abcf9cb62c816cd7d00240a07502301459211235ce575daa735ff331a7e88e3" . + "c168b986a966e376a554d24d3317af40065192220c22252c5d0e0178a2f5be78" . + "d7f425c00bdfb9e1171a6fbc7312bb4a60fd230b5808f6bff417c4944723663b" . + "dfe5752b09c0d05a37f2a16f48a22b44c8f157208fabc839f38fb39474356c99" . + "68c64e0627576881e2aa679337bc2b208bf392f8824281c25471f2787aded575" . + "29cdd3a841923e6c92cfc48a3f5af569939a0db6ce65c2ea55ffb6ad54ce368d" . + "0a4a076a9eeff1e18c9d8cc320c2602271ffbd085e43f1a2ca5fcf660d3c57d7" . + "74ca1bf39ff155c6d2c16218c5510e3ea60cbe152999151bba30704227bfb931" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "4659aa164619da32648a0b1268de6082e9d5ba7a1582449ec8c955b08757b595" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "e440ac159ae3cd041312a2507bf56f0344c558b75552caa7ec69b8d073c5a234" . + "be0a64522c4ef0b2ce7fd00353f52b90c71c2803aaae72b3eb2a0f1c0b002585" . + "d2c554cede98e7b8718d1b8afdb6465507594e883e493d93bf869e31afd1c2a1" . + "74c4355073e856d59f581fc2b95968c040976553c2208e7cfa3fe1edd891cdd8" . + "43a574bcd38f2badc2347a97fbab617f8c6fdf2bc7df322a69e23baee07e4945" . + "68379a72b3b6aa4c32f868aa4f1a53fd0e23310fb0a6c4406cee71ec6f798c8b" . + "8f9851496f4049af5d6f0c90d1f4713e0ae7ccd0b1b443f56d1ef7e8c76adbd9" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "64ac9c1f334753d8bbdbf2efaca68fe3427feec7ceb71e6414f2ff652e59f7f9" . + "37ca5cd4a4b2a3f1b172757f8b2b484c7ae793dac73ca93bd088d3d26bb57021" . + "0251623545cfc54741bc205e6b10ab67723ae1259d4b063ebd8a211b924a7b66" . + "dbea16c5a2bdd8fbbc77848897a1755a9002ef529562ee9a4aa4f34bf1d5e5c7" . + "f8d0a041e092811858741201653aabd264f0cb853a8603e297715be9cd69d66d" . + "5f4730bed19270605b53d7b4a5090384a64781e8691599ce673fda0d0b3fd6c0" . + "ee88d1a1c2686f9c3c1e16a785e6a4140d9cd0a705b80df6bb8e7f99196cd5a2" . + "22dece19da71b2681f22c358c4b66f7aa10b6d2259e7ae5a37f41decfff8a1ec" . + "fe08510adb3328708f9fb7512b24264cfdb97c8d1c7d73b2899a67a5b96a37cb" . + "67bf0a4e11fd87af1c7e545c69bec79aa45953b1b9f24a1ab9642c58c38c7596" . + "9f7ed1478b9ad81dfd799974199b7f5691949134234e9ea0e1184094f403b603" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "ff798977681eaed026ebc738204b70e019c2d67a0c1a21a23ae40ce7a7b84fbe" . + "31132b93853c5ee27ae123de3c2e4b115b08131fa29ff00634e020e0aabe579b" . + "d0e5c028809ebd396b77ec9a8ebb57bef3b2daccd71253be1ff456b9eb3f97a9" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "2b674837f4a1d4fae442fc7f43d93b3af3edab7ab065456f0a56c6b8a2c762a4" . + "e7584f0e48666437e24902042d1b69759f0511ad9fcd323116519453928734b9" . + "00ad7e88c1fe908b2079a169c59f40f10955391dd9ab74e42e0e374154f3ca7e" . + "99f2d84544626ef6905e8aaf200ce580e9c94b247f33eb5bfd6ebbdd80ff901c" . + "8e07eab4a31a59b905df68bb3efa526646f5f440f0cce4631a5cea9fd6b59900" . + "5df61d89393aa15aeefee3f5f93b4a59e8c9b14bb8b16bdae05b1480de636631" . + "896db8cab2a478c12184d779b09b36ef3b70ab88b9b25ffc90f5633bda88865a" . + "f9383319b39d907416b155a81d913b57c303f7d2730a43a959758bde3cb65eb4" . + "28e1ffc18e7d3c0759a14600a9c833cdf39ce4cccbbc67c68136de3329aaa5ae" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "b9813b52ab0b3af0f0c5a70d323c0e3e09b6384a5e93ebd2a7909b7b06e4a4e9" . + "7cd5899cfecea699b65a93eade85e5ef2be9c4429a829e9ab5b533424ef1aab7" . + "201b8ee54a27d836eca8e5825dd13be1eb65f1012f60214d30173755624e4e94" . + "e4ffe4398cc043d8cf4e98755db7795a788bb9ced79984d3e05950a89534b188" . + "3054c10709a898ae81be217951c8146e63ea4c531f4e7812daa2fc92011bcb9b" . + "3fc223fd8152114d548519c24a6958b18635ad78e54bd088fe127fbdc114e4b6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bf2a80760439b52999cab52a74fc4a4da8af9818435f7626f45c0de7ec1a9a52" . + "bf2a80760439b52999cab52a74fc4a4da8af9818435f7626f45c0de7ec1a9a52" . + "d2cd41626da6ad2bf545ff723086240951461c948ac6098f483b9a9170db3d08" . + "46f070b3d704f491998ab6cedd68fb6203dc8028dfb8b108075777ee099116c7" . + "652ebf1a185b606263bce123db983134627f9ea7f5ae70187c1c843e21e0e1fb" . + "fc2592ec3c5a8a41daadd0f3f25b51d84e5c8b759bd7d0b5398a5ef97f185d35" . + "7a92254b52842cc3afc6774ddcc339103c617cba557c1fbfc5292f4bd8aa4931" . + "b1e5f43e516e43aca7b863894810b77f277fefd922a7b1ebe297e2f0b68375c0" . + "22698ce8bfd7453972737b244945e850c9ed7f266c2f353bafc86ec5a9c11206" . + "1ef0881c52f07039baff08cfa4315eece3fb69893a8580ff65953c02a295a5a4" . + "09f5a27d4fcaffb67ea79bd7f068b66ded26ab91a30e805d73371bd2a480762d" . + "4e5f88c29e2222b711aa2201a1dff6450527a771b04b5a364e9c69072ab5d9f0" . + "551f4c62642fa14cdac9f9044cf899d207e1aff025ddecfb2bc128387228fc04" . + "a6b23d00e6d8cff76e7685213cb64cdabff5ba712f562881d814bc70fee1ae93" . + "45ce59757e2e15d84689c5824ca9293209a5ca32c186cc11fa5b3bf63351bdd5" . + "b8265972758762c525cd114135692b66f93fb5de9d21e6c334653dba25f5c3b8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "38f46cb05e37f9ed911a1c3a4451c949c8738250826109b0f3d94a7786f7f3fd" . + "205e1de43acda5aa29e04c1bfe196e50713e8c74c478721822ba7e741e8bbd85" . + "d6d797b55e0488fa1e7885cb89eaebdd7b9fa70ae5a818829ca832aa5909c00e" . + "43f3caf4874f18597fdf9a40e62e01a7ae36d10269c70260ffd639657e51c141" . + "6d30c98847421f11abfee31be438e157ea5ab98162685f4aaa85c65838af9164" . + "a0fa92036313dd0a9da75b1cf67e9caad4bac29c6923c7be67c14bae8f654299" . + "b2339ef25ae1877539170d576dfae000bd2fe432bc1eefc09d2df7c6d47844e1" . + "d237e810e4cbecfedfa506a4e57fee4d17ec383e337b71ff4dc0848358f94e54" . + "f42cc527240d08692cc18718deacfd94cc236b664994dca72140133ce854809c" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "6d024a4f5b55582b8d495b5eeeaab3446e4c33c559aa913ed795282589cd3e04" . + "b05acf3652ccf5985c39d628b5d72034be2cb88fa497d5f9a6f2832dd044dba4" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + "0e045dbac262b8fc1d4e28c1489d0952466ef347fa081194339162c8af51bfc1" . + "efefbdbb3444639cc8f38f519bf92bb759295503d8f895e813bb4f56cfa44180" . + "592564f573a7b7ab80c8f6acc661137bb23a70304fabe5955a8aaa1bdc537d76" . + "1e3483612c8aebdf93ba991e014dc8db384ddd12853b4603ddff220f59102086" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "88bf11724996f9730aacd0a212cfda65936b270900252fa404ec524783fb548f" . + "ff49be0af318c5ad2252b5ccbaca647c1571c8776d7cdfa5b8f16a54e85ec3da" . + "822178d98bd792738749082277cd4637891cf31476cb29710011408ec8b4f342" . + "767ff65cf808ad232f70b64d05d882125c3213df666a130f3650ec001f755d43" . + "1f06da7714bfbd03049c27914c045faf1495ff13b693afe5a252439e301980be" . + "962cf8fbf8aabe774f4ec54eb4449c80d756b5b06246979aba63b452a95baee9" . + "8f614846d1a97c353b3e659a8b8513e26d26dd0fa725458d9ff3ef942669530b" . + "789ecc6814869d40a5edfe156833217159e7b6627fb2bc429d8e69f9065938b5" . + "9682eb4aad9ebb1cf3c96da7292a7602b13e05c38b976a4819425d8acb7a785d" . + "0c06b4ff8e1fc43631543e9649fcd83879b65eafb30aa996216093db88f9a948" . + "223f2c6806413a6deda725d2c557337da2534b1d79858f8718d4c4ee66d4eed8" . + "d43534b43ce8a5f56490f27ce21a98188503183104360c0335a4e0eaa91ed93b" . + "8bbb3baa71efde6da3fa49a90a76c3739bdeac820dda2c37ddc16c2f27f55f79" . + "c0ff7dbefb656c6de3348d8ccc212c7aeb11e966a18431fe1c3419e86560ae43" . + "fd289b6d2d343a60aaf25d7fa26c99afd8e9f54eb5887d98a62719b52941032b" . + "a6c282ef2d7a95fd2e1739d4b5091dd2a4da51d168c703937063aa414624c1a0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "b2339ef25ae1877539170d576dfae000bd2fe432bc1eefc09d2df7c6d47844e1" . + "a66f9f7d9ef1860c9973dfe7b4692b780fb6dde5ecb6dac284b31af4482f4717" . + "9ebbeb34f675fc78ee1da72632a15d4d766931deb48dd3835137051f7ab42930" . + "471e85c320b89e7826723292b8c7f7da010714a4a1e827d5f12b47ae0b5cd038" . + "a7af325692ba4ad1979376a61d2557e8d3e59ba6604513aa5f1f0fce33f90fec" . + "10bb0f0b8f8872877820894a4a8c18b8748c578358a8b7cc8b2597128fc7d9f2" . + "ed43466a7480002509162183958d9404ee54767ec8c4c11f4be3b317cec24f81" . + "e07237800f5e69e831ea288530b165ebf026919af837ec92ce017c0698a8face" . + "00c04ace774b6455b486f6be5408493425cef777be98de51077aa3df226cc563" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + . + "48ffb1dea148574903b0ab96b3b703880d27b596baacfd49ee985841706d216c" . + "06d65b4f5cd7e422e136d3bcefb5fe798c5d0ec3f21e23b0bd8b1ebf95637e7c" . + "745f9313ca586898dec990a910ea9393a6098106698098fb4121d9ba45921369" . + "78cedd80b456f399a427f59d8fb6c1b4fa1126d0d5fd855a11c4b7c70ffd3c1b" . + "f4b761f9bce9e051de790897fe3ff18d7ee1758799bb1e3c24a5b558cd64d081" . + "28a6a7666478da1a06dc67d0cc5680a01a1329d939f184d72c4450865204ec13" . + "a2dec7936cc3cb09d0986d5aa650085815060b70d1b027c9a04ae7ebf34222ca" . + "1f11f4741ef81fe41336cf07f384596b64a0b89aeb344ba89568363dd0ce1477" . + "20e10d4409b83723cdae6d26f0367ae5252c5a510bd3bf8908ff9ac01926a628" . + "1e2991e4d9f0f5103cd83b32595ba47cdffe6bd6bf98971efede08caec23eb65" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "9f537e6fb799f427300e3ece16ec1d55122196793af5ded034868d30c0af73ec" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "b1c9944b19d632e255522ed5bbf4101490051ea0dc78ee460fb7627c85cc9611" . + "9a4fa28025b9d05e12a92e917dc2df3799cd024f10701091cb8136a3fbf907e6" . + "79fd2323d0728bdd9f53a1393a7de82f46d6f6141d2f7dfa4ac57d68d86d152d" . + "74b416c773421658842bd61ac4afddf2adc2f558a2912c55589b194bab0eef30" . + "d0cd7aae303ba918367c27fcb69082dda0a7c10dff4c758ff09c2b743a35c265" . + "6ea83e57e66afbd94b107ab59fe3f865fceb211d059e99f31cd9e6f054f86eee" . + "4441633651a9c5b127b8e41096566b19be1332dddcb64ea1ccf06709e4996912" . + "501d6641050f3f521b80d555b6d6a13bb92a8b587d9225105b953334d25ce1db" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "d379dbc4d9482c59c825c758b2fc74a1bf4c92f19813dfd44489f4422a493fae" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7128c579e477a605e4efcc1a91251202cb0e29ae0bfb7362e97221cbfbc9903e" . + "f0274681eb15cd8eadf4e2ecd1c8c474eb77cf8847fd71d87985bc913de3d6c5" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "41e4d2ec1b627179d0c2d37320df62e78c2d473abea6ff8bc4a047040155c16c" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + . + . + "b4a6aeee4fbdb7ee0ffd889018be4b3d8162868e5315653d8eae530fd4ce75a0" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "d5d8acabde38dc480836e251704c76beeea12430efad7d09fa459fc2ca436d02" . + "40f094991019865ec400f080cfcf0ebac5e9e05a562932f0b5c6013047c1e437" . + "7f29a39671ae7ae466fa52c66bbe8fe0d19e34d1ca28636f6d057b279a0f8443" . + "3151c6fbc0b56e800e9ceefdb5b3ecec74d06772799c5b4cb6ddc3578503071a" . + "22f27ac67a962effea4f0535b8c402fd6ea569887a5508d43e3337dd1301fb88" . + "7c41c2eb19ec02d06b41dcc88fd658c0c6f5b96b0fc0eb359365e306bb2aa1f5" . + "25bbd3fe2a32806d4a39108b4931deac2e177f51379aeb5583a31d846e254582" . + "9d5d32243173ad6348ceba1733332d645127048c09b9da0a27c69aa95f551155" . + "84897bceb3bd72fcb726f8a1273438a7656eee195b862b4548de9cd13acd4322" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "98ee86abb74f93470f6ef4a7f65ec172fbdee1202a5e03a3481e515a27ec9d54" . + "0f3fd6574eb3a08e0953e818cd728e3fe5616aa0d381cf4f60a64fa47d5e1fdd" . + "bd28fa3bb0af1f9f289f29317d070c3ec767741b37bb9016e0be22371778e8a3" . + "71d700a279b680bffea04c9637128601f41cf29f13d02d4c1ce64d8cccfe639e" . + "98916f40f6d61a413deca0848a05c2bda4471976bb266e0e6324405951852c3b" . + "2dd1d14dfaf182f257e86f7cb2dc6d9af9dc4b34887b7973e4dbce1bc56eef77" . + "7a02dddcc33cbac18c7cc0124ce0a97e1aa8e47cc4c374cdc29fe6e778653af8" . + "862ac381f2bcac917ec239b2f3d8e0c5a599b564c3bc7846fff7b9220c516ea0" . + "e5db156cebf77b4e9cbe576e9bd69ea8a6d1101d224d2b3c28c504bcfd191c8b" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "c5bf595bbdd6e2064f56d2fa34a5d7c16b368caff4543d7af7a62ea3eab699d9" . + "60b26096e338a0cbfdf7ab5a4afa4968e99c39d4d9c8059f7c14191b8d498ac7" . + "a2cb18133be48777551fbe15f75a5c63d54f3658b45562fec79ce5158cda22cf" . + "0273cb401b03db8a5d0fd55e51ecbc862a374163ceceba93c624a9e222bb903e" . + "2f4856ec0cd348dbda9fbb46aeb1c5b730b29ba05d85dbb68985e1e3336a7723" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "d911cc709490b4775270a1283df96f697972cdb8d3b168a1b975c8b7aaba91aa" . + "7b9914175e7a75e9b5bd4dc7114010df20291fdd8146e1e550cd25302267b8ff" . + "1b401eda3dcc043d1f8ab5d8d38d82e98affd1ed1b6f14f3a685791fd271f0ac" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b8af4ea0273f0e6f75f0f4b3dd0e93375a847bb569698eb8b79dc4630ce93438" . + "b8af4ea0273f0e6f75f0f4b3dd0e93375a847bb569698eb8b79dc4630ce93438" . + "e195a981f91fb39957df0f7009271afcbc54faf85659df9ac7e8c3868a72c929" . + "05afcc8a78744f88b4db23fb625f221593e8ef42d9db38e0c3b096c5dc200de6" . + "b6e8adc4f907407d4980697016101c27cf1e8101beacbc553d76bbc7f3e91d34" . + "fbf38b7e11c9bc3c2117d7db966f6536d9a39bb7f60922c68d26e61bca69e627" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "783a5005e1b603622c934b80177d23f278c92f3c4c1c91b65900b60e61b5e9c5" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "f765e3788a27a991a552eeeb3eb08571b1b96ace304cbed546c92c181f573218" . + "614a31414eef1e5d50ef653b62a073a41ac6e054ecb5108e61a533506029964b" . + "f26a9f384b2aa7e233bc5a29c19cf99664aa890cc8448ce23bf2e0b8fb406d1f" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "99a2e1a3b9a871ce4452cbf0f48512ab5ea16a94349670bb97cfc4ba7fa69cd3" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "11c3d31de1b28a7d7f784ce0521cc32b5aac18d2c2cda67e5cf52a08fe3d12c9" . + "f1406a7f98d085102ffe08fc3aae62411a040160e73377515e2dd1e8836f7d63" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "adbf58d66f02e72a3c3179d6835056d4eae8d4dc11e39a78510fca718add0413" . + "adbf58d66f02e72a3c3179d6835056d4eae8d4dc11e39a78510fca718add0413" . + "323b9de50985d980cc9e2b18474b5632abfed798123f02aecff74669384c3536" . + "98e85bde0d43e3c302f9355dde9eb4c9880371f702ed8b6e2aee75864b3658ca" . + "a5bdee1c1c46974656f3cdaa35e2ce15d44c78531454738cdc8163d31ce5d7ed" . + "9f10dd6b27985e7459a1f37bb71753e81a922f5b391b2c2d63ac0f70c830f7fb" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "a8ee37db2c8c0a99310d2bcec3b924bc379b3ec6da8eec14d5b6bb64151528fb" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + . + "490efefcec4e7d65ed7b677360f60e0e7cb5feaefa0cbdc4144b8fa2bb3a1505" . + "f242166b5c80f90e2cd0b3421a9ade88e75b6028afc6be5248dc3a80fc482849" . + "7ae73dd18f650dacd17d665a5c06ba64417a234f93514af1a499469c0071bd51" . + "323df71c8909b363da3ece635c07cf203bb30f114f1daa6cfd3a8e5e8a023287" . + . + . + . + "d59812e4a0f67576fa244f69e3c295dd388704a066820372eae574baa8f474ca" . + "42b810b1f4c7f7a7d8cbb1690af0eae45905b8a9fe59772207b490efbcc901cd" . + "9d30ebbea8792cf2bdef718ecc2371a79a8c308b85728411dc7767718f51b0a6" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a629d98b4587048314e12802a7acaf4416cf23517c97adf2853601c4cbd423ee" . + "080fb7ed809aebe94e3bbc4687d0be21fa7aaf17b37b01f437735f554daef171" . + "8fffe328857e7d235c6562f05ad8eaf4e65131debb495f189d3a3caf3cddf615" . + "45d7664ac87faf4c457f96dec2c75925e5ae3f916b5d466532a9a3a2303e34f8" . + "16614dff813174b133a1579f43b743da821164596420b9ace119e04aa3f4b009" . + "0251623545cfc54741bc205e6b10ab67723ae1259d4b063ebd8a211b924a7b66" . + "a66f9f7d9ef1860c9973dfe7b4692b780fb6dde5ecb6dac284b31af4482f4717" . + "7e10fffa65baf7cf3c58df9f096b61abd40d4aa162e2970c1fe63a4c4bf25143" . + "f717c33ef645ce24184c1a463e9fe7b3c3745c8d636082b7af820eaa99ac3af6" . + "ae366bbcf680fb8d9a152d9231accac517ce155334629266a7de5767a8b0ea74" . + "efa1b30beadff726c45eea0a9232ffbaf591c74a6e0dec5338a373dcec73455b" . + "9e0fdfaab02396db29f2c3ce97c144fff2abbcf94b5bcfce54066eae0dee0be7" . + "4bc62676c926ff119bf2fab9230711595c07509411dd8eb2c57730a5ae648f63" . + "e2f3cfdea8ea6f4baa843a632a9328b85e86fc609839fe036e46a8b1b61f4663" . + "84bfd98c0d2f4790825179417f5841c90af6805c7e85a2ee4ae3dbefbdce12bd" . + "400eee6f115f031900d8131f4c3c155a2fd75e5a6d443ef27ece57257efa1d84" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "d01e02df63c154e7ce71bc3f3a54a11a76cc3ba205e92e7306426ef7cac0df87" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "aba10709d4fab2fe074ddee0a8ad9a62b92e96485b9ce1b5edd5e2b71d2518db" . + "de515e92ca484e1d4e8968a4521957c3220abcc72cb9ab28c77467398a2163a1" . + "592df5e2270cb6b3d848bb3ce32906b2d1a42a3c5ab2d7955eab4235df8d0d7e" . + "68a2d63bec218f272aa26c949c6a57f81b4fce2e2f53b19e1afe9e53426b8304" . + "11c3fae437259d59d74c43bb7938d5aa2c4cb7a4570f940701909c0b08a54262" . + "ced1c3bab5d72042adf1069c25240c3c2aac7332c197f07bdb67ad883f7001f5" . + "416ed11cb3c0083c782f8bdb245ad56e37d06e367f8f1f5421b17459d86a3858" . + "ce9a82839d852a6f67329788a36a61bbc18a31f0c3d81d96251d5e6c321eaf43" . + "ac34c2ce4eb473a536b44a8cbf4887d0a45373ad06106f8bf269b31d7e22a23f" . + "4caee01c916389be2b868488f5362e7361869b04382d0bc8730055bee79be761" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "d5926d3a6f0c1f9e740b063d1c1f1642be4dd98c417bb155978091cce628ec8d" . + "2c139e913c15401fdce50539c8f51d3c3ea26030c164176a272a172036fa515e" . + "7e5f83461998b9f58f350e325db5ed43d70a20d9ff85fe77db5a5f6c6a1f2b7a" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "18e388123182b5506d8ce1e57d1119a95e82e09a5e57408876580f558cb8167b" . + "efc11faf30d8eeec80871bae2e732a2ff2a18a77ebf4455121082bd550c2ff87" . + "02b35ae708c6a098e6d3eb8bc6b0587fc60405f29b26b17c42cb3f30b94668d0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d6de4c78374cde64ff2c8a37066122c9ef1f9eb3173658e7a3300bbe5d4580fb" . + "d6de4c78374cde64ff2c8a37066122c9ef1f9eb3173658e7a3300bbe5d4580fb" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "cd60b6faf93cc3bdf9efb0572e958c312feffd077620728e6188cce83d3cf316" . + "18ab013b7785915beb33a21e39aad704b441bb493529647fa333b3ccb4f49931" . + . + "ffcff215d621a173667c744fe35b3f967d81042250086e8de8bc60c335c0dcb1" . + "c594f161ef71afc57074e198d9cc8287f8964f4683d51291b3415633e476960d" . + "f5ae70afe088cb254d1a580ab328f6d8a137fa1bc8fdab445a08327340f811a5" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "72c462c4a8d6f2f331d6f10ecca9b46bf300635fb461521ec33b0c7671d77a1b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "765631f6897e6bfb5ddabb0b2c1d65d135b467b69cf8067243f90aa965b39a5d" . + "fc3b553a96a39af6663ce01ede3ec11deb6f6d278aeacd3ad88d147a66bd643b" . + "8440f3ef5730102f6ed077b4f195011a0786118ec78ac02b46ab0d5c03d93bcf" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6531f1fc1df8223afacfd845f0aee214aef5180ab055cffd301bd4e9851e4017" . + "8bedf2139e38f826fc425c08a14e19bef1e324d6c6367e3fc1819af00c5edd3c" . + "86e89049af8f413b7ee54a5f9c652ce0273aba18baabd83050fa74882b17b8a5" . + "e077298b0d608fb5cc30aa2d087d75bb6a0e99a216941c741b442e111379828a" . + "de464364752def3a241e9e6cf8f296df058feebdd50610dc9d354bb8a8e2b76f" . + "4a9415e6236771f55f17a613933e210c04607b4756670a83b0995f6dc1f7c55e" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "1b4f0a3727ea357cdb8d88138ad3929b7aaf57f51e8331bc34d974209c418c98" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "ccb52b53cc29ab14cd2636d1ce5a90531333084e7e4ada4239904af565b70a2e" . + "245a218881bff5baf36c1b9fc998c08bdc47b202ccd2fa34e3adf6c7b4d859c3" . + "c1df978790e706e1aa9c9cfb02c2cc762cd3c2ac220b4931bbd0d6655f92e52a" . + "4a9415e6236771f55f17a613933e210c04607b4756670a83b0995f6dc1f7c55e" . + "21b130398420b38a698e397a67dbd7489a4369d1f82b8fc40d5e6dd3166d6ddc" . + "3ce07e60358e8d578a1054b66d0306b77d90e538a78a92fe07ac5b9232101392" . + "8fe9fd0a14c4198c9f8bbcfbed1d1213aca72d20e6630b529ea639a5d4d743e5" . + "4f51ca2e99ac62e1dadc4fe7e7d3e284fca7346859bfc233adb1292643ec0b6d" . + "ac46e26f07443e474a9d82a1817261b7ff5305777944f7ccd7f121c79cd0474c" . + "6c3a6b208ced401edc14fb3e7f10a7f68501b129c002bff2052888d3d0a575be" . + "24cbe8562e7d316586731a0bb6883bc6a37bdf3025e701ccd18704abd57ad948" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "0e074afabd62114ba736b8ba8c4bd6159c0fe0fe1b25dd26a96cdd7365e82458" . + "21f47be103aeec551fde540bcf63180165519c11983dc6d72897d9c5243524a7" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "2a69dc36481145e3d8351a1de055af004dd7d2c75a2c2a808b1463920d61348d" . + "d36eac5cf52cd2891cd032a1c06f1de98aff738ef1f95ace124efad2bc4b25d3" . + "254f5068d00bfd340fd3691218d7ec50428cf6642a6dcbf12e6696f383bc3358" . + "ad34e24d4f453cbc443a006b8319d873594aded8186f794250ca110c59927f7f" . + "c38724a96b524d0f1339d84ba1097955047ca1411b849675094ee5b871a3103b" . + "04c16984d12d567e8ed3f06bd8d3a2527bcb0b76ba29c46362fcb1ac64fb62fd" . + "d3baa2181ca8a3db4565932ff5ef017fdfe52723ecaeae620fbcd48942107e67" . + "8f4059f657f08511100bf476a118e43bb17d83327da3cd4245a779ca7da6c155" . + "f00f0f3caecbe0b8d3d93564f94a660b93314650337db09692585bd865cae165" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + . + "dcfe09d023ff142005c82a99a47ccf2215bf19b2d1cffc664b356e0718b1b076" . + "d6d797b55e0488fa1e7885cb89eaebdd7b9fa70ae5a818829ca832aa5909c00e" . + "98ee86abb74f93470f6ef4a7f65ec172fbdee1202a5e03a3481e515a27ec9d54" . + "b04c80b82edae580168e96817d3dd63ffbc8bbeccd2071d613da171c25229161" . + "cb03ef061a7c2a7a72449684aada7efd3b5118e86494b911e88588564bfdf2b4" . + "157f7a388c767f62bbe2c67435b479763e0c183d503e53b48cf83477104d1c05" . + "bdb416fda2f51fd42623b1a1279baa9b291dd3d5212376154bd427cdfb6f81eb" . + "54fbe7518a178d52a9a73e9103817f4da71fedba8459b87c9f6c2419711a616a" . + "1eccd6b1572b2b8b11edbf4d0be7b1774dc7ab7333b619bdcaaef496b79b8968" . + "58c8fe29d300a5020151738e89b4f5b801d853d174813eb9aa7425ad539ad64a" . + "e9fcc719f0be5d0fb357e44fd7ba34573a8fd06203e4b3e8ecf22b1c0e57d00d" . + "c76c50ffc3b6023255e09f0b26837a0f5328ae7a78d11aa5c4aa4c6969e44b44" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "1a58a27b0562983d62694770590d87fa1d8b830313fe1648934a2752965f71db" . + "65f5a838ef2154f2a822d7e84e4111f4ab3f874b9972c1a20f2779d92abab96b" . + "09a1475f07f1f4c2f571cf47aad7e0ff48ee260833b326635e3e5e23564da44c" . + "e415ad0d005f92bce4f797331e980007abcdceb2b1f523b3d795492f2fba72e8" . + "8ee080a68f7327152de69e7aba16e5359f775e3b5163340bc1f5cee006e1a626" . + "d43b1b3a07a16f47003d87324e4985272fcdde1baece334dfb41e8dba09afb03" . + "8e4cf7b558d659caa73e1db3660f89be86ccef396a77734208b59f72f370ec8b" . + "8bc95dd814b54a751e78b56077edc4d2f716d5e0bbe36305d562f2afe9dfa82a" . + "ca31a5cb7bf143834f7313cbee8946d768fa26a3c8ec89b67a313295e4f3754b" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "f4def80823436e9cee9276b0e7f9c1c0632326c73d8d4135e792230ff5d300aa" . + "85bba15962b60390ef269139db41da575dbfae682bf1ef9c09dac9e556ba04e4" . + "0c1b1d4b42cd6a6a0a68b7c75d1b4153336089de9be52f67dcb7b1cd6e9e1892" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c7a2f1bdbeb009d3bcaf10f83b462d8a7a83d5c311bc0cd00bbb21902ed5d381" . + "2b59f266ad327f68714ca996674ae29ab09c9030bbe83cf520dc0192264ef466" . + "f4379b2ab22a72f8200fbe6dd3ee1303366a6c02649ec94b69b57dbd86aed7b8" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5034b6307269ef298ad922565bd07c5d0a02d0104c1539aea2440fb98f81b2a5" . + "5034b6307269ef298ad922565bd07c5d0a02d0104c1539aea2440fb98f81b2a5" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "a69989b476b76efe094f76ab0faf9da9abc260ce048896a2c97f80eab6e22e5f" . + "5bb32b4f5a1466916816a2b604cc639d632ccbac12000d3f08fb200e3455415f" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "26bfffae94a2f439cefd16fdb07a710fd99a5863a355486f96a2b2fcec5b67d6" . + "92c3412bf2c655f951d859c5c30e1efe322a58074aedb67664ed8a2cb0ba938e" . + "125ff9ecc8437cd186e07f87011c3d61ffdfd7e6e2df556b0b3e8c64a0fbfb61" . + "4005c84a6626398804de585a6b1b2de27478b8e7dbd9891c7920bec325e40686" . + "877c858927e2e667b4d92bb16c89be0520c8a5800d7c9f7e99ffffbb7ab8bca4" . + "81be19e412043bc21f8dd0e04c5ec43dbec7d6e81c5324540ce12cdadfada993" . + "8bf2ae62c16e331fa7e0d91717acd2580581d9c54d8dc624ff6ca744c9f5032d" . + "dd809576e62dfc8e599ea531b0a19411c250ee31330573bfe3f3dbf6f9002aef" . + "c9e7f3f2c10229363951ca42f821c0b20ab0346b72552f64af33562a78b09e67" . + "af90c6e64ee39762311afe214af747452ba068f40b41e18a631748cb87602ac1" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "1f4729a57d79d2f250281d70dff83087efc56eb785195dcfd3651e42fd5e72de" . + "f66a7234a4f2f74a9ca0b0d5dec64178bf63a7b9e420434822b6ada1188450b2" . + "ebe139a9fa21ca2953b687c2f5ab15ceba984c28f8b0fca7a28b08462d4f3495" . + "76262416fcbbe201d50a63f51bbf202c4b54295cead83d11f5ccfe9be162c4d6" . + "8f1d9034cb6f6800c1ad5265d104ebb251d3cbed66967e355a9b6ca9c4f19554" . + "089f15de20197661f52aa68396e96cffa30477bc7ace260ffd2ad41969e590e3" . + "9c8c7de272e7e9acedee8115eead5289786f995b22416449ecfbfdb47cf612d3" . + "916ff8320c7ff2af510d6ec5d63aef1f61f37db7b49032070ecd99a404701887" . + "107f04bf59b18a824474ccf50377ed3ddc40532dfe7c34e4bc3509642ce21cea" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + . + . + . + . + . + "e41e7ec3a4a49d47372cef952c71391936c8fcea53eaf99b25c5192b33233f47" . + "42b0202d6f9be6fc2eaa7a81851d6cddb35fa5388c0a56eba5ab7d43dec65bfc" . + "80bc8aead766d2d51c9ef64c471bc0bca3623f98844733e00b9c639257bde85f" . + "5e15cec177d8db49add3a8007f828fe30a890ca99a34211ffa5c51ebf8609a06" . + "ca5eddaf0fe7ba621d222be32076eb295d4d300f9f45180e73c753f8dfaf2bdd" . + "5816a56a0f9c6dc240b465f449f8e226cafdfdc637930e3e153a8d6b3afea01b" . + "7b2f937c8f69d913fb3e47e5df8b0b70007b38b4c70c6d90cab9ddc9ca084969" . + "56258607d564091dd1319810162af10dea0e1fa6455e1acb2361b5473c0aea5d" . + "b3f09d473d951e781eddb46df39c82a39b7d9ba27ef60faaf30dc58d80b70cb4" . + "e22dde500fa4955883ffd66948428069c8e9c8fa16b76c60e5c848d6d7d90fa7" . + "f901ea77f7159b6efd1f99dc56f0c55bbdad461fab65ce4f0e1d43bc876f44a8" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "5abcf9cb62c816cd7d00240a07502301459211235ce575daa735ff331a7e88e3" . + "533163335709f2aa65d97ad8b6afe4e2309ca08a1ae7e4f84c13a992447e2212" . + "c972706421e524a51130ba0fcb5f31dbaa03d85ea5aa425933aaa8237a3fc962" . + "4997f9c8573e2cd75f5430525dc0faa4635974d74d686c96d45a8e933b166f27" . + "c13780a013e15c6206eb35ae979511c80edf1cd1f9e3b8fb97bc4862c9a0b2fa" . + "65418fc843632e3fc89102eb74de921f46cdedf3b52c696a783ec07a42b9230d" . + "1df91fe6b18e5dab44d4dfe0749e225501d72f75bb35a1f6bd7c54e09f65e70e" . + "7f099ba8158195e91ad93b271ad40bfbb9736b36721678e77d70cb024bade57c" . + "2776422569a3cdc7c8cc297261f6ca0b4cd1b07a13d5325cb7121c89c87a33d1" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "4f9c532c6906783afde7c1a1577ca891f5213efa86bede89a64b2e9b2cff2f4e" . + "f27a2e823155aeac796439698c85ba187896c251f014161028e90a77a8cd9deb" . + "6381fa11a76ad30093eef067c857f00fb899744922824918f28f34eaacac8cf1" . + "979367c1e303df7393630678c7f583fbfbb2f538940bb713ff05d06aeed42edf" . + "53535913557f7ee3f3179adc6f41bc52fa5662db85220941ed4d28c62a6a67fc" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "40dba64ddba8e5ba53693616464372c6dcf94121c1c42a03a0d8870c6a05a8c0" . + "95693d486257d7370c3ffb2cd1d08f8dc5d969dd991291b86870142bb58abe9c" . + "07b0ae59f5e32075045243cf140ba15d0a00b7d9f633bd2172501431f5fe9bf3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "81380f088ac450f4f7de3a8a2ce0094cd10ac82d06b02fe5acd89d3c1abec2f5" . + "24704e705db8aa532ef11c61599efd7e7928cdc72a1ef03175081891d8c7e912" . + "4b9b1e4bd324754a1e1966d783d4b78eca42d88aee94811b70fe9917603f0f62" . + "0d9e3fd563ce762eba5efdc8ad05f4202f679ea671782a53dd3942928c9c64cc" . + "73a8d614d72cf359dbb3e73589ee90e99359faa94a6d3166db1efa7d70a30c27" . + "541b23ee30cb41f4f6c8d6439964dc91ede8f0d00fe362945c1ec94e71e7dd25" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "9d22f284828b8642a46ba9f84c05127ef077c89ba9d5769698f3936ec8b2a457" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "271e1bae853b3ae481a2338c2a5bd5ee9d6b3ffb63b181126398568ab79b7b11" . + "a8dc3fc13f7a440a31bf4a289db6382d48ae50c0bcc21d11e295a99a3e1e6a54" . + "88ac44d7e73e0b57678ea59718b74102bb7f2f47df6cdec312382e90429be402" . + "155b8ccb7dfccdd275dbd6cef199f12b69f3073efc297dad8674a48697c35934" . + "c1fa2443cdce35786d680f6c3b113e7d798d76ab5fd175bc1ff16dca9619c744" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "5141845caea4d0ac8716efbbfe07d5c688808bcea30c01077114cc055df0a36b" . + "12981536ede8742f02cb92b43c9d66047a6790c1e13de466bde772a97e6b3ebb" . + "80dbf4c1094ee632af2a4946067565c628d14f976ae0de7d29fd23c8881ec35f" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "30f940cf0b005ce00d6f8eec06a3eb1050e61967389d476f30cfe7c5a9ca0550" . + "30f940cf0b005ce00d6f8eec06a3eb1050e61967389d476f30cfe7c5a9ca0550" . + "c404d5a0a0b824e6ecbf4a47cba7dd9308d0e4b258d597e31c2f8c3ff2b8b80c" . + "f5257b4278aa3ebdf05c984861d160d8aae6717abddd49b61316cdf175179e7b" . + "09baa59afb2cea20ab8e55b289661ada3788fc366d145efb78a2a9e55d7587ec" . + . + "719a294c9586686cd0cde29fc96245a370b64713ca256b5b8a3d339d9a3f6029" . + "08c003a71965c8c9a97b4f128b1247666d352b499859542bd7c1f9e575b55b99" . + "da4a0b13d1c939d015e91b924ca0a96f80a56029bfc40b10df3fee261e3a3e6d" . + "af23239920ab81606b813dd6a7023a6ed2d0e8fda17b8042abcacc4ae2cf841b" . + "9fef46afeee0d1c1ca2a354b9bd85f8cb2f8efe172bf48dab8d6d410089acf14" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "672663ec820e1cb8bd5440c40de4fa9aa1ffb0a49641f679284bd60fec01c312" . + "7ff9276c2d56783d8c97f38f1e3829b885dd1ecdd4a0687842772fddd22bcc38" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d633aa421c0983cf9d5ff9010f65c9054af6bba8506a980c21e74befc8485456" . + "fdddda7bd343e2dceb0cbfbbca6c3cd61eb14b6e98b721142812d5de3bcefd50" . + "217a0ef018c5c7c6dcbf5baaf630e7a23cc38faf130c760fde703bd4e0c2e6f8" . + "f29cdf6594e9a279a0b681523300026e65b221d27eec84b224f3de008faa4a5e" . + "ba4e2d19b787b6febbe273d2d776253b305a3dadb5c70d7c5f3d090c2ff7bfb4" . + "65e79971bbd4ab0a913e8d02e329fe2fd196d51248539a1a89428adcad6402ff" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "7ad58628a56874741cf64d1bf13150a55fd7f185dc860ab7d31c46b90c5815c5" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5515b256d905460408dc72a766eaf94934101226c41a3271c90c0d3cb011ae8b" . + "064e944688716171f89e4424e6ea1796fcc94fc4489c898efd69ebacf63a1898" . + "dcf0df9fc414a1272fc692c00357ee200044ec8ff2eb255b3f6387abdf1f7f03" . + "821ba5a1e698ddf5c09ab58c145b6bd454d7b335f797a5c88ce8d829b89e37bb" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "064e944688716171f89e4424e6ea1796fcc94fc4489c898efd69ebacf63a1898" . + "73a9adaaa8a307a85e1eb93204cbd719acc08421d143eff59b21757235723390" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2a594a5eb993640b19209fe8707d1759a6b4310f738502ec8e3feb56ff877916" . + "2a594a5eb993640b19209fe8707d1759a6b4310f738502ec8e3feb56ff877916" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "99f2298d1122077ccb7306fca79ff37abfcc5f186209842991c78a23643768b9" . + "160ec1cfecfabc6d9c12cf684698414d1c576cc89d70222a1b33d02095d7a1f4" . + . + "e93e4b05a89bc37d4a605eaec34db96730c10c538ba17c150f86a053275e93ea" . + "e0f6fe6fc88d4604c8fb2e76a183d64f333e511d77d81cba7bfea060071b1462" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "457ba8abca7460250dbb2ded124724e7b5d9d4909160de07fb94d57fccf623bd" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "45e4d98a79fa608dd64b1ee7b94d49461fc3d1560150e96dbc41bf63665aaa53" . + "45e4d98a79fa608dd64b1ee7b94d49461fc3d1560150e96dbc41bf63665aaa53" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "1cdb9194caeebce26cb785f67351e12291b2d2910399def5a0f3e57d121ed9c9" . + "d59f147d3dc9a63b6817130e7c3560464e9c1a2c359e2ac919bc9e975d8f09cb" . + "16ab8751169f03e24f8a7c8ce04824e366a697ad05008e759614e907b48e3dc4" . + "a6a3c7f700906acbef160e831083fa26317dc3067ea0ab5e3edc5f3d62e35635" . + "3c5e051127ed747844ef8a5a25a5c638bd2eadd06971b3b4b7efa69aeecd7ca2" . + "226d77afb0bce3e843b81718ecf62ca1542e8c2f7255fa073e4a0da706ccb048" . + "a4ef33b41439774c01fe4b05c9cc7aa7160e36c479c78fd49ac7b0a77c0d5127" . + "2603e2d4625e43eb08c30cbeb66cf4b7897f84e3f98a8b64d9a616818beb2d55" . + "e317aa2b109a8c1fb477fbea799f1f6bfdddafc270ee32068a33dd670f735675" . + "b8468bed49377269f57a807384ed0c767f18ba1cbaee60863f571f00fde43f0a" . + "16b7bc93e649ab6c8f4c9e22a78f19fa2273422866de535900ab8a5e636d8daa" . + "810b6329adfa7cea1bc7bf25baeedbcf56e26b762e3fff8045bf11276dd35325" . + "f731ad6aec662497a2397a730e2b7e5c70f6d394705f10654a7b43454478a9bf" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "b5cc84a32d5895a7511ebd8d044b0ec8050f411a846a810526d871fcb1917bf7" . + "f66a7234a4f2f74a9ca0b0d5dec64178bf63a7b9e420434822b6ada1188450b2" . + "1a58a27b0562983d62694770590d87fa1d8b830313fe1648934a2752965f71db" . + "2bc9c11effb02d6aadc1071001f5252080849b2df0708b67b1b63bcb395d07f7" . + "7e6f13977b26737468f11ebeb50a350d8ebd81ed86adc04d7876b68f7df40318" . + "45ab10cbc0c7a6710260ae2a10f2eda403ae286b9437fed034b7de75bc52b0a9" . + "93813bf25e984f05fc6ccbe896f5f7231e38e7fccccdd659ddfb87c5eaf42978" . + "2a38e0fb2e3f7b559e1a6a863a80b99fb42c14ed1e7e1d1b09ffed807c8b1274" . + "6af1161c120bb83964c13dcd3b3a0f577aa860094c170aea5b99f4811c04c702" . + "27c0804676616e3489406cc820c8e88d1141f7daf1f5d520aec1bc8831d53ced" . + "686bb279e23a4778d5d46b781b2c6d7090fbb00e0c3946735aa75e1109ecdef4" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "5eebf71dcacae81c70318f6224fa28ad4398b9a801af17a67a44583d2f90f91c" . + "99ac69d9718ff46f99d801d3f65d9fc161bf51c4e26584f7e223bf933aa488da" . + "b6884fdc1da98b5a248cdf327ac6b67b5ea1b34f445b8288036093bbd8ee71a5" . + "88de6288a2db69f94874634d10ff82fb31d3ca710e37190c80326602bd864fdd" . + "98e2907c2ff0c75ec588cb8e6abbeeea1087233cbb4569ea7b735c24f8168eaa" . + "a334457967ce070c30510810d78d4555fd92de955307472795dd82ee1a05e8e3" . + "6786a2d26896d08c5efc0ecdc39765936db1c9fe48b2485d889e7d6cd5b6437b" . + "eafbe77c78f8020af49f101d4aa0e6fb8b1ad11958fb39beb58a9d0a6fe90498" . + "771786602cb63c6f6493cddad1429b0c73f80c40ba766a4fb116c01f00107dd2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "31132b93853c5ee27ae123de3c2e4b115b08131fa29ff00634e020e0aabe579b" . + "cf353dafe99b173f0fd5f69b73b591cf6a1ec1b40f8d183fc742dfaf1d1fc52b" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "93813bf25e984f05fc6ccbe896f5f7231e38e7fccccdd659ddfb87c5eaf42978" . + "e2b77c4111baf43ac39bbcc66070f2f7e81e101f9c8e99d42673b1d71cc3090c" . + "26ef4da99f14816958ec363916e8c4a5fe4dce766a4d34df766f38ea06fe27b1" . + "57f3e56270b366d7c062ef45a8e4d93134a6b974db689ceb841c2de39435beaf" . + "78322070e48e9e1c50ae918cb3ae1456d37f8ad49534d6e7813c1c2d91bcb379" . + "8d67e1d2cb42c62ad00c650b92d7ca15fc3ea021d0efb244956391d61c61b17a" . + "9895602219748947777666742f04cf874eaf312edc8b64f6c8ea7b86294e398e" . + "ce50f73a980a3c3dceb0fee68bf5fca211dd61f4dd5856ab8177dc34337df81e" . + "5655bec93f43f879c9387592332e9068c1d25e34e9b95af58663f730eb1d8200" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "0d7f7c92156ad8e0bf5cc4ebc4c602aa844c6e4e449f7f5ffc0b4942e66be6fa" . + "2d234cc3868ecc1f51ed5fed0b7d7a20d249913f7300191808bdbd3d21d009ba" . + "2c4b0ebde33f6c906855efd62e803c3caf58429faf1853e104f56918e8dc79ba" . + "9f2446e243d87d009088819066dc900c94628d1a1949ca2d892088aebf242ef4" . + "e93a80f80c4a9d975b683d39ac7a55d612716aabb3922769de8ebcdde6b0e993" . + "125ff9ecc8437cd186e07f87011c3d61ffdfd7e6e2df556b0b3e8c64a0fbfb61" . + "c0a91cc28fe927c3d656b6c556f7b03641328aac9c08b950e94b595648784a42" . + "4005c84a6626398804de585a6b1b2de27478b8e7dbd9891c7920bec325e40686" . + "46e117e5346ddf390281da65570d37147f2088ad816cd890d9e9b56ccca87a5f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "ca31a5cb7bf143834f7313cbee8946d768fa26a3c8ec89b67a313295e4f3754b" . + "b46fb6d87b0128117b0bb456537b58981db30924d9f0e6c3cbc41ea0cf0ddbd2" . + "315fd61641f0b3706bba83acca51ef19e124a4b8a37b7416a111adb5d988d4ca" . + "4d13af3ce8a6f5a8974d7e472919b423d5a0692b494048368b4ac443309fc8c2" . + "c12ad3bbeae794e523a237ae16a1380cb28284ecd843614e3c598685387c538e" . + "19d2d14c9251ab3c38a21ab7bcdd58e08e74431b6544d207954fa95be9a2fd93" . + "025f9627d9543281a2df7457ac6aea8ebca5b7586cd3abf89d97f52eef622357" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "5b44fbefb53caac4bef4dafa7252eaab083a36c40c0ac14740b0e63f6b8b61bf" . + "fad7d61b5be86db0b3c5d357911d80ebbba7a257ccda09a842c6ae134ffd9b05" . + "e2bcc98472b4eb3aeeafc7857daf9a7dc3e1e169ea3a463a41c1d74d1d984bf0" . + "4bcd7d16afcb755e22b6e2345fbac90dbee4ce6bfa42424ac309b9b59874ce7c" . + "632402001fd54f94bec554059c8c927ff03b624f6c10aceb656512bc692b9572" . + "c3132d5c3bb34f217772be90ae176b73db1e9d247cc696b40fdce9011522b025" . + "6f069c747cfce205731ed29944456dec411c97e7f690114399f2d8f182613fa5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fcfef4752b92e50e8246e34743b84c135e89a41a3e5f797a460a34813c617be0" . + "fcfef4752b92e50e8246e34743b84c135e89a41a3e5f797a460a34813c617be0" . + "0249fbb7f0fa91e66a9fbca876f0f81a69db2054ed0287759fff3be912f1d64d" . + "b39de6d779c3452782abfd9af6c8797085c00e77959224346c310f38695bc62a" . + "a4197687a6dea7a7ac5fa82922c3973da89e42c60f08122dc0a83e733e6d3eb7" . + "bf82fe269747817bbe53cb0b296ebc3ffc562026f069dfe23e70e5f7d9f15813" . + "18d352e56a3a7c3c76177af9fece7f5c4fa655fda2f60f190076e0a0296096bf" . + "ce750c0b7c88fd69364595a228f5a67bc1877a043e0c875c7fa78d7645ace817" . + "404c7f327268e65e3eec2a9698e96ff34737138eddc6cd2d2b791a4394dd61c4" . + "8c6700cac4f74b4c7a988d488c3b86b442aa50893a58c58730273d787fbee815" . + "ec42c141c4f87797977a7c21f923186eee5f038cb9ed60f6a0ffd378d92a746c" . + "b583dc41511458f798fd30688aec99c59b149ca0b65c06af55c1715fccee7e66" . + "137deb2e53547c5634ac4036a68efda8b23033a64c4b94c6cccb42da9809e216" . + "df9ea4821faee381e84e3e174a68e289d7f522e458bb577fb9416437115dad1a" . + "2d62962950bc6570b8007c75b2b518390dbee7f404c7f676867b76b4c0c7c4a5" . + "ecdc64a24a05a3d5d847fabbb7e68c1753a0d19696d1efe803b3f787e4778850" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "21f47be103aeec551fde540bcf63180165519c11983dc6d72897d9c5243524a7" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "ccf9dfa4f2812708034b9a00d6428f3e9255930543ccd3852f6bb7545283debd" . + "49aa1618c01b1f7a78552b6344e31d32a17c6552f9a0ca438c092c66257d7705" . + "4686fb198d4840df2a335398349c20707d2b3e34647ae176e8fb677fdbe10a59" . + "f7bfc8d7bfbbd0ee44b0e5895fcf2064dcec52eb4513742e0e99721bad98aef9" . + "91555276ba5f4476ea6fcc7b420d7f1a7ffbbed98b85c3b0165eb022696f3fae" . + "91d594840241bb752ef059a36c4fb133ac8b420693d1023aedd8d048863d7b8c" . + "405eb80dfe7c8ede7f48ba5106c7a448e01224b7594effe494ac77cdc72bf30c" . + "6e340c3b3d9065f27a7c3f73656b6c799dc2c5835dcace453145c9e338d93983" . + "908c38a2913e1a3cf309468edfb97d067af73452447e84a372560416892cf7e0" . + "4b54b3361993434c4fc9dab2b473a0f3f2d3db149d13781b40f49915b88f531a" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "1602f00e5d2c72d80a085b7ecb4bcf7115d16e6d66db25c9ad997f94deb73833" . + "573559792403af02f5f51137375f828ef4d08889e481668e9c56e02e78ced9c6" . + "11cff2db4c08a4b2422a5341a00f3e5b500211ec8a6588742fcea371e01fbe37" . + "578b0a0f720a4d2ed0f8b358bce3b3d14ab8db03b6e38e7924c0b0fc6d406f87" . + "e52f538fa4f82a82cf824bebb1c13109fac8a3ccc5fd58f291eb3abb7b3a639c" . + "b102607fa8fc524ad855746e509171eeecd5842c8e817e30d0686296a4511f83" . + "d6331fc1a7184ff719dfd08b3a4bcfcaa6a1a4aeeff43c32e143f21acadfad8f" . + "d19686372f7496ae6fa31640b07419938676814fd0d92e4205c4fafec2b41e8e" . + "28b16e994d8dea6ab91ffe42859d6d01a571f70318ef972e508e6eecb53b5fdb" . + "45341c50cb9ba608e04da824908188666a55b9d21965b4ba26f0251e9835af46" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "d0e5c028809ebd396b77ec9a8ebb57bef3b2daccd71253be1ff456b9eb3f97a9" . + "a6e230ab6fc30ec8bcdd0769c21b8b0811867d95876198dc49911fa01021bfb9" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "e7c80892af9c077174ac2117a19573408264ded4f355471b63a740834c281494" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "1f86116d144214900b632c9785a9a28b6ee60fbe899f41aee28910e05c4bfd8a" . + "db72e0e0705452e87fedc65e8cb84242d2f1fb14f89bfd407fe80751035a2354" . + "b6527d50c9563d09daa91f43db11f84a2e2829c45e88dff231b8159935c4d0c4" . + "bc31b7dc4d4877ff9b89687e687192547e911053da6b3d2b86f414cf744c03a9" . + "c06f27aa0e900c92749e959dddbfbbbdb5133590ec5fe984d97484c5e703fa9f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "d6ee1d88625a838304e7744ca69a72c7be84a07f967f213736ee56dc8aa99d9a" . + "9fb3b13e2af25564e8bb8ef9ad81ea858fd8db19363e0a82c3b4bbea47e60093" . + "278659b6bba5ad7c9d3c7ceb213768f89eeac09ac44565329593f7bc37d857a3" . + "2f6604a0ed1889e4b110a04c592ade25db3076f78e9338fe5138a426b69060a5" . + "ecd03ef3110287bf0b24acd052c33c1583273f7bec07b7dd5755fc0741574197" . + "86924d3a982934cda9b01832d31480304a70a2f08bd6651aabc9647ac1897c6f" . + "558d408bea4d0e08f56b1106233469b9a65673a9a73de67a75b45a6310ce5504" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c72975388b46dfe0f127bdc2256f7a88746e1ff6b0dba255e499cdea1a41eb51" . + "4facb59cdf312d944f6d6088bbb372459159d40493b5031fe8563f878b18240b" . + "711c2d8eeabea729206870c307b0dac69d748b997cf3afd9ea1c6194835e3c1b" . + "12c1ec865cbc992b963ef25e34582a641e9832785412771b0cf2f0086af50b3e" . + "c4029f828e15c85ae7ac48326bf4d6acabaffda4c164a318e20217a6ce12c055" . + "222fbd6f5b246881ef72ad5889964ccbc2c394573b856708bac5d1cda2b333a6" . + "1cfea94dca1c4e41e92f0337d403c56873d32c8eba0847efca41155f6f26363b" . + "bb427ee3f868a70212cdb4032cfca5b9fb329e3b6c27a18e6072e8bd930e6ca2" . + "c077a9818f7a4c1568e9bbdab30414a4dad048ea9887f83e8b709eaa26bb74d4" . + "454f0f103eb69e27ef35b3f1ed855f483df7c0ced93f33ace0d4acd0cd229746" . + "75fb8b6036d008a3d4db94faf7f8ead687575cd768cfb810e000414e19b40cd1" . + "5b46d27bb7bb1cbed4ad88380cefb2aed73f7634980c0f22bf9c3e5547de65aa" . + "1b9652863e080027ebe182d233936a183fab4203df717365a5e0737a11b8c20c" . + "a27cf6ad6b1c2fa0508a01f6bd1f8c2d3d5ba1099403873c8d16042c65f1407f" . + "578f89c4364ca18d0507293096c5b79da22c1b541053ff16c26ea159f5e09317" . + "8cb6bf993adc56f8d55034af8644c220be17207b456b0631eb5ae44d1ea70ba1" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "92c3412bf2c655f951d859c5c30e1efe322a58074aedb67664ed8a2cb0ba938e" . + "c32d7af23ff0f57e52583a19ac4a45eac40fb711c5d2e5c07e43a210013d2f3a" . + "87d0a693783bb4e797c5868f1870a67faf3137b61fac70a6808bda365112d292" . + "a065a83624ca3acedc0bf5c3ae584d9c8edcf5d3ee99962e908b0a88b8bf0b03" . + "ac4d5f247b2b3e1f2b5369feb65c99bf607a38b865419b6527daa704a9276974" . + "8d6e472de4ada663632b592f70e86b610d48d95631e29e2376e9b7d34d8f6e06" . + "e1b733bb8d1f2257c8dd24df8f027b64561af03273845caeee3383857a43b284" . + "e5e74e935c5c797c7cf24f46d4594966fb7eddee6873c1cd8f233570b02a9403" . + "68a7b57a7693f0ededcfec7ec9afdd26311f9d6952c2477664a0f1bc94e4a39e" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "8b407bf8c51c4e1514fcf61a9072f28d5d7dedbe2e42ff939a085af19f76a158" . + "6cd501cc37507ad6c6d8b0ffaacfac81dc84f11087cfd58abdb316be2ab55796" . + "929039665c1517840158b13cd461df6ed33f6fb3268d19cb6906b4e7d0e72039" . + "97196305a73957a2bb2a425c96b1c4b1a14c66773ff75fe0ac80b469e6e7d792" . + "517dcf3758ace4b49b77a6e03e3701377b06bd07ca16abda8679235fb79df8de" . + "28ed45708b800cdaca0db6c599c29711f3f92c3e0cff31d38889fcc6077dfeec" . + "af6ef5039d90f8164472824cc5c6063648ba2f0db9569cb27f3842c3abd70f89" . + "0b13e3247f0b3f8c0bea29f8c7815d040f9c33539d82e5891725b53866e015da" . + "7850af25c38b2080f14c6bc9a8a3dffa169d2ee1ce6545e6eecc729ae9a4419e" . + "33c1a8e28cf711a41a85fb0e4ae49ffa451a5a2aa48b4f6219c2f9c3447b5750" . + "0939a9d057be17fdb888cbcdf51b4641f90284b829b2b92057d1c34a1ffb4235" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "665e00e2c9a55193b60966af95ee3f68bea484747179e2e209092cf806c2dddb" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "31132b93853c5ee27ae123de3c2e4b115b08131fa29ff00634e020e0aabe579b" . + "d01e02df63c154e7ce71bc3f3a54a11a76cc3ba205e92e7306426ef7cac0df87" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "e6107a37915c94d86aa1dfeb481c7e2192d481a021aea734e95287575f50e117" . + "e6862a1afa16b962408f31f7ceaf5c99b0f797c9d13ae233af47443a714af871" . + "ce50f73a980a3c3dceb0fee68bf5fca211dd61f4dd5856ab8177dc34337df81e" . + "3f06f8371c5f37940154fe1d40c01c49f5daa7e1a6a506094a2393cf15819e2b" . + "9e15fc11ceb2cbf1a23fc9a7da4324c82ff0ca8708c31c97087420154898be66" . + "12dc24b81363895bb6988605e89d16c0b88a422fca46610bf6947cdab6fbed43" . + "5a79b0ad2a9a06b1c6cce76eed7a0e9ff3fe325773e3fcc5bbd45c53f5556222" . + "09b31a41df9b1e98f60014fc20dc42a5f2f374b314b0d1045d11eda2ec250bc9" . + "ab63a6eb1640fe6db9f5afe8bc199eeac2e5fc1d72615315dbaa9b472ff2cb9f" . + "128990a9c1de106108eb5b46552b1ee5f89f602078b12a901abb03d579f41173" . + "d909f673e7d89336222c5f016cfe91784093461ed4681f751d1536b94f99feda" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "6f5bb6ba98c0d968c7f204a4237ea163f1711ba3a57817810e8a675abd10e17e" . + "1114d6f9732579d65621c499a8e985d97d730ca4f290b76c4f98cd006e101d08" . + "9cdc0c0ac68a154f1fabb593bd636c50447606b005696815ba856c0d57316f69" . + "11eddc5ee5ce400f92f6ff886981b3338840ca1fa6bf6a0d13006915fb28554a" . + . + . + "86e32eee7f51f03d42a14ead994827ee083666cc6db363726e9ce442f083916f" . + "50bfbd7a61388ecbe94c7686b1846c0442c83028f62b3a811264dc1b5d654a4c" . + "66425ff80138771c2aa5a598c4e86dce73ee3c5484eb447deaa2fca8a3cc54ae" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5d455800c6834ccd6bcc828ffe56222c323565329d314108a83510d198852b66" . + "5d455800c6834ccd6bcc828ffe56222c323565329d314108a83510d198852b66" . + "99f8cfeabecc4640a9856c8bf2b8698105a8fc2cd359d8a617b59d671cbe2c39" . + "1c1760e83ef7e58396ec0ac48c6b80e5987131441b3d9c76799810c94296fc32" . + "11e028385d07afe7a4feb0d57cd932b7e4a364ab00d0953a05fe625748a6c340" . + "5830ff93251535101b88a98e429ba83f77be1b0c095a05fe8b77b03ca820513b" . + "04803164d0dfd41c2e140d4608d4ebfa935d022befd905f5fa5e5ec4c8d2139d" . + "f402eabfb24842c8fb9fd8788d53d238e45e3eccc3646f385c9637f7ab582c7c" . + "273e10ca3f7f79e0b16f7e8a65347555cc02b7e51f4d6a38e8e489ef713d9022" . + "4251c0d93aeed14606e24611be08bc2c83f1a18ac7480a543011d6f3122a8582" . + "1f12dc8b143ee60b733d75b524a4acb1db9ec410d8db7d51b94950ef66015df3" . + "16cbf49e18bb23aaedc447a892e98ef44be98981bca4e15471f9413d53fe4710" . + "1ebaa781c8e262f590fa7d60cbf539e470cee53196e44d3ee751788ae5dd3e8f" . + "421e794d0df19eb5c58188f798727188e419709a584a8e419c2bded45b72483c" . + "5351a0b825363054a61d6cd0877eba0776001a01a6bac6f40c779ec4af762a73" . + "2d4acbc8b81fb4764c8ba2cf971156aa8e9e142c24e618fc4219596442f86e4a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "d0cd7aae303ba918367c27fcb69082dda0a7c10dff4c758ff09c2b743a35c265" . + "d36eac5cf52cd2891cd032a1c06f1de98aff738ef1f95ace124efad2bc4b25d3" . + "9397688c91b6c95da3df971364714427a2aaf84dd6313c31fe9a224176f5521a" . + "7b00dbe1e1f95d8d810cba54c3ae3788f4a8e719b35c0ac7ea8ca59360172600" . + "599d6debfc2f71954646c8e9aeb84b07673e988146121c3d55379008243b4626" . + "ff696f5308ac2187440ef1ea95d3afb93e4533157112bc66c06c4cf1f8ab0df2" . + "c122bd95f8140995ac60a403f49d1bb361d9ef07e6038011ac19ac12809faae6" . + "52d408962f81a3f5fd451cb1dc493a6f88c9e10a938165b48832ae67a004dff3" . + "7244596f2153db34da2b7772874f41ee150c76d2086cf69f4f0e759d63e3749c" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "06abd12fc407ddc984eae9fbd626503e2a6e78d87bed22542d5a1f83e2baffcf" . + "b7e14af8a17405cf79747b636ab0b4433a49c78c3cafa57214c5ef7d8ab4470b" . + "916ee1a57de2de9522b2c385a0845da8675e0ff2b26f4ee4910ef9a513fcd6ef" . + "ccdf85515392c092848b328b7dbea256f353408788f50c2c241e720d4af0cb53" . + "23945ce8c9b9ec56176b483e2cebe0be1cc2196a813dbfa47a30d2862e58fc87" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "6ad753e60ab0f92eacaf4492c6e1ddd0e30752521c8cf87f782c457ff1e2755b" . + "da9001d9d0626ef48a45562f69088563345829e91f819e914b0b60f196ffaa83" . + "660a4cb6055f53e803faf47a0acfdd3f40cf8ad402be4c6857f02f1883f221ee" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6f5d486fcebb907e0f67c9170e86ea3cd4b287f1fd1f8d220e12ea8c41f451e6" . + "6f5d486fcebb907e0f67c9170e86ea3cd4b287f1fd1f8d220e12ea8c41f451e6" . + "38a7dc54b25ab3a7e76c69919aaa8e18f157cd959a5cf284a5b5d6c680084525" . + "3f2e14951d74ce5f462a9b95263a4e27274c7dccdfc545a44f1679e088bd3587" . + "c25c58a21bad510cf0bc148533d904fb8b69891cb59fb02888fb7f4c3817edaf" . + . + "0898bb372ee4db064474f00869ea6f2172ea01d5d1ce88c3702e22471c063724" . + "c2b46c0a77ddde5d20357c05616cbac92836bdeb0ddf2739966d9646211ef5df" . + "2e8391b9f7eab281e66adff5ac1efeeeba295a29b62eec35d4f8b5a355d7b0e4" . + "19f5acddfb274fdaa5e2b00364054349b1e0d96a308924f5e53101b7e8c5b78e" . + "c3fad642f9a1ffbf6adefc840cc7f43a3811e43ab24f0c6eda75eeb21c22248b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c2b46c0a77ddde5d20357c05616cbac92836bdeb0ddf2739966d9646211ef5df" . + "63571c25f8496a20355bfeb34a7b622c328f79bdb4c04265ca64c2469514f831" . + "bf508a3718635005490d6ba5e21264af6b0af50aee574d2ffdd0cbd6deb538bf" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7555eaa4cc1ff3e8ee739d2a391dfc1e4d82390077f57b07a02600cc187c41ab" . + "7555eaa4cc1ff3e8ee739d2a391dfc1e4d82390077f57b07a02600cc187c41ab" . + "3e742dea9a406f2ccf0389f7333813beff7abbfe2b460e8c746465985e53844c" . + "6a192c3c3dce62459c3dc22c02ff4667c1adfb0fc180718449cdcc798c8a4932" . + "4fab4cb2ff2f90ba833502234752c771d14b277324ad2fffa944a340bfaf117e" . + "08de595bd48a57d79751f54160110ad78151340bba71ed4bb53f5cde3689e0b8" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "df0466c993a8ab97e09f30d37905a933aad5dc75a47d2f62f58777bb0e2b171b" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "e5e74e935c5c797c7cf24f46d4594966fb7eddee6873c1cd8f233570b02a9403" . + "ad1b34348bff3e905f79e975ed2e58182e92ebfb5412e5edc55fe14a66bc28f5" . + "2c1d1516468fd000dbab801ddca9c96ffc765b04b4104f9364696f07fe50597f" . + "5d101472e21c0057549ddebc8114ea1da546ef8ecaedf8cccff131460aaca174" . + "9bc2f74526e5ef3ff28a81033ff29b8eadfa68599a35f372bbc8bcbec9d547d8" . + "147f5c68fffaed44ab3191269b496c281a4ffe599b70cd8b794cd002fae497e2" . + "11556bceb41cc801fa198dee2b18ff1d50da1643101eabf0ab7db64ca4205bce" . + "d33caca7e009b6cda292b112f09d8b01667c8b2e445effb20cf2698c3ae8efb9" . + "3fd7c1be322b9f04c77fa0c8ebdf694ba56f29303b97069a0ecbbd547bf879e6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "501d6641050f3f521b80d555b6d6a13bb92a8b587d9225105b953334d25ce1db" . + "b6884fdc1da98b5a248cdf327ac6b67b5ea1b34f445b8288036093bbd8ee71a5" . + "abe8461c6bfedbb1bb704d50d09f7fbf43300a64b08a69389daa097fe0eec6c0" . + "768620abcb17746022e6754a593681488e291c3d097a039b4434e100bd65766f" . + "a1429ac876ea690b52a9c792dd922b347b73d8f19cf09c4e67e9783fb556cca7" . + "db64b8cd8627b24e19ce775461e70114640fc9a138281ea29f21744c8a98866d" . + "4106eb1454ae5053ab7591ec9731882e9e7afeefe1a94faf9140f23161427ce5" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "de53ce849b86769feff1f8be0431f7b3978c5c0748fdb9c9ba2f25a9274e227e" . + "742a23d0f9033975c57ab2a9c97bf3ff24f5172566cf4ad7a4db91cb232ccd28" . + "871d125790b034da00f7767225ab50cd9f14e40fc08d112b5d7b6d14815ee44a" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + "3596b040be8d5eb6b393c11ebc85056a16e8edd388e63a10d0be1bf0efdd4de6" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "edcb85a7e2a8a05d4d6764c2f1150bc2e3a3078169d530f354d6f449ffb802ec" . + "eab9a214a37a27552360fc6413a7856ff2bdc048541660ef3fd68d3ea0ded285" . + "89f16f2511f5e8cc212f27859328b20a5fe7a14ed1af6f93dab1c56c3d6d0fc6" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1473f6d99f8a255acebb86bb9dfce8d71497028dbfb9005f76489c23923af0c9" . + "11f51f1a654891d72cdf7e2a5c156412ce45a919af49462a836c7cab7eea507d" . + "82a265a38aea6b2fab9ed1ce1395594d37d37a0d5b4b06374d4e843ebaa5f3c7" . + "cdfde898d4fe1fdcd3f3a3bcbeda83989b0dafbc02c01ad1f43f03c0dd114851" . + "9d58218b455fc5b0353ef135c1dfc55a79e78b54264b2894b18b57c60803cecc" . + "58ed0d972059bf305927d3871d403f8747a5cef5e457e1045e3213e9f7836f39" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "929f28cbfd0a962a9bb2fa1c6efe09a4b1fbabdc8c17f347b50d429090caeae8" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "dfa71dc1cdc451530326ce0976bdf7b45c8db1b4e1d29e36f6b999ca87f4520b" . + "beff279029468c0cd12fd6b90d62a5c6666ea0ef62e794a5e16852249029402a" . + "3af7dfd521fbc1455346dc00c7f0c604399697e173b1cc12069b076ac29b32e0" . + "a11c25cc357ade9adf2dbe79bf2176b42a5bb2df217bcde2af6cc9459535d651" . + . + . + "9f0ded95ff756fc8dcb30063e48bb8801d955fcd1e2fdb9c24cbb5e547accdc2" . + "069993006c423fdc15357f009a64cb308a2c6445f42549bd27e08020b77697ff" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "da58e72c5b56aa7c204ef4061c35fa16ee4c305c276884851ee1447b75d52488" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c884176a36fbdf9876e921e903cf210f5d670638d0f7ecbbc10b79231fb664db" . + "c884176a36fbdf9876e921e903cf210f5d670638d0f7ecbbc10b79231fb664db" . + "d92d7bea2b35aa4fd934066bda0ff3388e04786e767d0148972f60a3b36f9c81" . + "96555bacfb494cf921073dcb6c9c4895612b215b6f45ca227a9ee61f8460efbc" . + "b0bd977993bb1d731ce8ffe0dd12236bbc3fd92ebcbd3b0437ce633fc93c685e" . + "2d62962950bc6570b8007c75b2b518390dbee7f404c7f676867b76b4c0c7c4a5" . + "e5e74e935c5c797c7cf24f46d4594966fb7eddee6873c1cd8f233570b02a9403" . + "017478d1ea50633c3ddf9fbf38f16a0b003dcb45223434a4be11824cb3621755" . + "644ab875263f893551e186a665f1b8144aa997cb364db772f07b5ca9b684a3b1" . + "a3ee8402470d3541ba4e468180abba5d4332103077646da38da585f69d79e9a0" . + "c3c4ceda0df8306881a4b2e7c14117fbe9e80f12bd738f7c590779d669bdd431" . + "19b4776f7d3b4c7b6b36a7ca60cb972849edc2575054001f8cabbc83273d580e" . + "08f7c12f8fac85af92e5bf65ce5a20851380fbbe66bcbcc73a86b3b6f8063d6c" . + "20d88a268b131cc761ebeb746a6580a7fe32ae52264e0850747625a11169df6d" . + "d98c5706e3105b823d7ad4b13523b8695d3bef9a340ea16f7a5649d9e62352f7" . + "78d898f56c725eafddf6ad20c68d8ff8b995a5d2737e9abe83329c684c23fe72" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "aba10709d4fab2fe074ddee0a8ad9a62b92e96485b9ce1b5edd5e2b71d2518db" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "ccf9dfa4f2812708034b9a00d6428f3e9255930543ccd3852f6bb7545283debd" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "91e009cb54e72a400e65b6d3f8ede5807f7ddbec1b5fdbc41c1b15647d605541" . + "47923afece8290109e20460dbc97204d5674c42df61df8874ae29e36ee8c7301" . + "9571d4c898c8b815025f72df537b0b42e760bbd4bf18d907058d2be3f672e2b2" . + "85fe8baac286f5c76f2a4b279ae3df730f56ce3abe0eb26f516ac0b04c14448e" . + "9f64cc7f19ec2eaa15d1f7c3233f65bce18bb9ab5ae24e2e77682cfd6f32a735" . + "19e2e65707a093820ab02a7f5912c262ebd5f0959ee3f292af93bbc6b04e0f90" . + "fb660d1502382874641cd0681182b09a28d7d62df46728e795d2afdfc0dc14d3" . + "35884b587f831e21c5e98008a7c5fc23c7968d85c0484387b3dda1c75aa6465e" . + "56cc2cdad0c348b7892eeafbdf159123d9732391234615a2b8f072b265018795" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "63995df6e6396ff0f25c60e977fb00bd8ac92f570d2138d4a0fac9ba872c7989" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "bb4696626d47f232c9dba964a043c5f0047f9ae4c0cc00fdb5c87c3ebfa48f36" . + . + "3d905b3f1bc60f7543b1ead7cf4d2eb3ff5d9ac694a674b6b5cbf07219c9f3f8" . + "6e90e506ee0c6bdeb0a8c2d1f401dd4300d3e11e355832c37f4c8461b3d5dad9" . + "a5393d3727536fc295fd7edf154241cd6ec87ff40a72f56504417bd16f33a9e3" . + "3e827ea306d9e2a806174cf5450b52ef367e39cd535b7ed171ee378d3e5a7408" . + . + . + . + . + "4f9158f8dbd9eff5733cca08abf0fe4df54919cf7932f87e481a6c3b5331a767" . + "0adfcf9ef00e7329629b9e1407e8d711cb343c0bf9743183acb6f7828a8b90e3" . + "a978a320adecbe64f6e93e59812274be1ca533ed35adebd917794b6d851b3c0a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "efe4c71dc7d4f2c784a74a6787900f37c076ab815221af8b3ec2dcb94ec74bc8" . + "42614a257acb57ff68648c1392c53efcdf469d66b375663fc4424001b8e4789f" . + "a1bfb3d10ff49f6064727b48bf2773db877301a7692982df9a375e0e95e30d9f" . + "671af84a98f554164deebb50b36ce6f81d9c59b0006e6efbc19aefacedaffcfd" . + "880fe9c18fb55c7f959ab62e1d6d591f6966fd30d489dc1171022157b1a44058" . + "a42fdc79fd47bfa651e99dd36c56fc9990eb75c943b5b40b5e0b19b7c9c43503" . + "67b0e5854197cff37a6b0e9120ce80e53923156d78d3f9c3a11f83f10a06cf89" . + "28130bd11b6ea78a3f79e15ea732be1ebd942f9697c21d7945e592d7ec0a2684" . + "eb08951827b819d2226b5fdab0738cbb41c9f813c2b1c70ddcaac363ec70f271" . + "d88a2b6af3537c766e030d34ae93029de6adaf49343d7b2473f7cfb805a0e62d" . + "5eee342ad4e9920e0607162cae6a21b003f84fa8ec42c06a4b367bae42a2e8ff" . + "0fbc0fda1a8c7bc45cfd99658f31c3b86672d5a1f5fac3dbd46383847e0a3cfc" . + "39dc3bb74aea0b37ab091ceca778e4c89fb85a0aea819336c80148c5f68ca8b1" . + "bc83732e1361c81704f38d45064adecd221b253169cb124cec36c254261c1161" . + "7a80efe9cc31367f604a3895367cd4414dfe523e403f7565938b36fe7e8b239d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "6c7c331b387ce63f2ad570dd2c4a3f9383d28390e225c02aa044728873926e7b" . + "205e1de43acda5aa29e04c1bfe196e50713e8c74c478721822ba7e741e8bbd85" . + "fe335564a5f626599d6596309549f71e23f3b8f73473081574630f8a26e6ca01" . + "f87859d35a6d835ec6c57b973204dd7ec523cfca4a17cf8713eb6f8c1dd523fa" . + "9793f34acecaa36143a5e696b45d5d44a4f3a723b1c144aaa1d8c93eacaa0f85" . + "4e3598de40a25c8e4349ef3ad8138ba793332e2809487ce4a09071c822c9f4aa" . + "f2070a0d3998e16a1a22817c12d18d674ecc173b016c454100173a1c58073e2f" . + "232fd93263f260515f5d89e9fefcf134978207a85e670f87f6da4d313ee4a98b" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "14861080fc5cdefe105efa702f172071da98562e1f746499afe9ca078a41a73e" . + "a832b217ba59a111084c9c434712f138ef8c3c6154065ce3191dbd43a2c6dd35" . + "e5ab870ec0e2b5d3665283ba651aa6c566cab0cee74244a1178fc717aa0d7377" . + "706eb143ed3c25d1403abd826af2e0b15d671a4ea05ead5d16fef54e8b5e188c" . + "3658d60999350673516f43053b519d98d46b2c4ec095b02174cbc4fa5c724921" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7275479b944f84af4824da4c0760afd494a8a6edf56c6ef8f2558a2fb078b92c" . + "70b46309b84362d342867e066ad218014e9fbd8d3c9e2d2979044383143d570a" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e9ecd6d300ac2001cf0c82b263e5f88433434c1b86eb92b93585af20a1aad7f6" . + "794a33c46b93aa64db7871d09c5a8b498c203b67c834e2299fc94055230586eb" . + "a5906cb7390e55ef146bb0b39d82d5787e6df41514f614d004af6b14b85c117c" . + "f78b9c9c3e1b33dcb4334546e72512f70a5e8ac9c8551bd1f2e45eab7d4b682d" . + "0c5a839c6cfcd6dbba3dc91d375b46b926e7712531434ead93963d18e40b3eb7" . + "cc7c3975dc00aff89df87088a7927722bc454b27afda033e60daceb96b9cba43" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "99ac69d9718ff46f99d801d3f65d9fc161bf51c4e26584f7e223bf933aa488da" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "7829da36f498202da0b3bbd2735c1edbb22adca71e39c3da6e8a670b71b707ef" . + "9e2982488e3959f3dd7c1793293a117f3ad68730ad9166521d8a6d2521ec353f" . + "ba2a38c2c7995506a39fc00741d35f16064ed0fd1c9d83a2d6ce97749686e3ff" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "821ba5a1e698ddf5c09ab58c145b6bd454d7b335f797a5c88ce8d829b89e37bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "1e820428007f1c81fb641f52763b0659d54bfeae7adaf36feea74a2a00399e74" . + "e3a32954c4d5c5a103e0190a32c8fcf1f509df8b08d0d8ff3dd04eea4550c63b" . + "a7bf2f5f3f8ded1731fc7a69d3cc0e9fdf2c73b741ac1625a27d61bf3ab9fe76" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "801ef175b999fcf5752ccbcf1ab8f4942edc85a30be1ba930a89dec29921ed0d" . + "801ef175b999fcf5752ccbcf1ab8f4942edc85a30be1ba930a89dec29921ed0d" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "b83eda51d2fccb169d96fdceb838e21e2c3ad824df9c6babc62d27549dc098a5" . + "05069cb727ec020dea6fcee0a6d4089834c2410939e62adbaaaa8f6b0466d6a8" . + "586229c767d6dd4004d425920953bd14e50bfe257bd0c7ffd364a88ac4c6e5f0" . + "2475aff64272cdc22e86623fba6fc2821cbaf190990b6a592e56be5d98bd6b35" . + "18146638faab4df5c71aecfabea385f8bdbde1d814a98cdca8105f4a73337e6d" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "a6e230ab6fc30ec8bcdd0769c21b8b0811867d95876198dc49911fa01021bfb9" . + "65e51c793b5abed6a543d71fe059d19ed53fcffa1599d4f2ac49bd6185e8bf93" . + "3e3d0cfe5ddd9b2992ed02a78ecc1ef76ee432099cd8df556fb81c83a38c5e0c" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "d1fe511642e57e3c30ea820a03d3be56d91324000e80381bfa7926ca45ab5317" . + "5e9ead9afa30d1e3883034abfa9b4a0d7bca0357c323fe470333667de52f72f5" . + "b55bb7a3402acbc04a3c6855ba4358158b294b52347f0c863de03ebacb13f2c7" . + "4cf6b5480f3a772a9d68682d10a367f1d5aa797ecbf0d3cc1df210585c1907c8" . + "c543194b8f5a51e9192fbe1fdbc6b1782c34d21123ef604096cb16b6d4890528" . + "5429e8bc0e914d2ee20a6310fb49ae326ca1e6105332b4315e053809c4917a6a" . + "d5c4c8b6ee4e1fe2e963600b869150668038c2c47841fedf4937554827135761" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "3a210fcfa2735d75818b3f3321ecc9bccd21ee7c824fcc386a2071f7e75ab87c" . + "268eaf9e6a369ddd3ee3c8c66e7b8bf975350481295a1167973ec944170bd653" . + "ed54859b869e19d57dcf6774659903978c1fbcdc0e9f8438ce53f4dd1d23143f" . + "a26035b67efa248f2bfd4bdf10b7aac53eb35a92137729060d7f37efd9cbf6a5" . + "827874335c1eb770a74179f0c9f25f025576ad11498542177ef9b90f324561ad" . + "2c4b0ebde33f6c906855efd62e803c3caf58429faf1853e104f56918e8dc79ba" . + "8620da59965e2a765262486cb37d20cd762bd1699e98bb51054d916239d6b1a4" . + "b25e70e2ce11cdea25503b4dce87e3835beb196f117f040b599486dc980f41db" . + "af2c8fb72710710139420db19ead98f186e7a9571d8cd8de8c87b7dd9123d8d5" . + "2defaf1cfd2d4be9fa21d384f0a699c3753b5378183c026815b16777f063a42c" . + "dc73b4bdde5b2df27bf18f68b6752fbaa9fe4988981efe68d24613a0144c78c3" . + "cd0f5601557f90fc312fd90f5d04baa1124ed360e96b31626244cef0ded52d2a" . + "895e9f036cc3ddfe807af1544ae81b05e6cb9c280e566cd70b567eed1205f4d2" . + "0b8fa2b881701027edb20b1d6cda89d4b669656f22a856fc9842aa76ee3ca38e" . + "cfe3cd256c704508e070593dccd12c98340c7bfe73b9a464f6e804ac108ac88e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "c12ad3bbeae794e523a237ae16a1380cb28284ecd843614e3c598685387c538e" . + "cb2d22582cd1982a46d9acf2b02b1d75efab9dadcf82771f715fe115e72106bd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "f75c026856ceb15e219152ac276ff4bd7ebce3dc199abe84c55b643ab7e1f7ea" . + "62cc3774d1801c19e6419b535b074a03ffa42236f08adcf3e73a090c58b9f939" . + "a5906cb7390e55ef146bb0b39d82d5787e6df41514f614d004af6b14b85c117c" . + "5a619b1314028321993fe807477c02c8cd45df5baa61e7a599a96978ee47afa4" . + "d57fe23d14be2952be969a1d0e881c6ef8fbfa82b43e227bf8c3c41e76923eb9" . + "34024be4499d76b8617761d06bbb17241dbf71702abc508ce7fcf10406376795" . + "767d24dbf1bbb07d59f0f1c9ed03b8c21c0de92a6ffd3f6247ab2e248730a18c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "34ef6fa5c512c974e01bec8a9fd00803f54d7fed59b48570f62334240194b9e2" . + "578165e9a8083e7b349f5a579a0adb573b3c578c5fcfbb66d3c22ae8f12716a1" . + "2744bccb59fcf32106b460d4bc533983e80bb8a402e273e0a1cb79ba871f2182" . + "42d39921773df362cb2d9f795e65ad86432f6a1714be016def91f3e204ee4028" . + "5fda013d59895a616b7c162d13c4d1a02a70dbfd4134b64e8def5ccbf8979b86" . + "9ebbeb34f675fc78ee1da72632a15d4d766931deb48dd3835137051f7ab42930" . + "ca21184e22b88df453f732daf66e08c2aeefb51649d77c6e594effde41945dd5" . + "e6398d5ea56c352da17f1dc93785bee10a16dc2383a7d6c86cda0008d074d756" . + "7151325cecb5303a1fb700abc6a73b4aad431267071b71318461dfdd9b0d79d7" . + "30f1e594f1dbe586d14a6c5e5c62d558947b39009804ca3fa06bb5e137c5eb9c" . + "4cc5701ae23a28e679bb55096f45064e74b0cb40d209411c51c26e6e4192279b" . + "1d531cf0fff651837d8a59cb8e8b45c4ef3d5e500f87c7f6133a04d1a48b1af3" . + "c736fb914e8030e19d63089664f16b3ac1c2336dd8e7024244e1abbbc5c04cf8" . + "bec574feaebd2752b278f4fbf247a0ffb52151399ecb568c0246b0a7f4561727" . + "b3cfb626a064157de0d2b0aabb0999b200e9034ec143085b4f84e40ec7587067" . + "670c95076b4f4050c086cadf0ab25d5a6a9749f6ad029d4b7ad4b4b703d8d34d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "ba7479a3e2784114817f1dac2ad90587656c7d2a04a681c4626659c182a8e06b" . + "9a26df50df06a1edbf65694cbfcf10b0f56015e52b595f6ab6d051b9c8e78084" . + "7154428033a084bb3d916617d188bcf355ecdd99767af777c4acf36a29feb5e5" . + "2ad86e015850a8c92566905ceb45ca7fdaca95f4282fd58f3fb99fd428336da2" . + "1182a8c824c760a76cd4b322159190c5a2f5d1081fbaa2245745cf7e07a61e4d" . + "8df1b826cf2589e76b292de1f871028484abba28e20d0de792bce2d110f6598b" . + "3fa62854a0440deee5fcee3f08bda69a2d0007f9fbe01a0bcb49d6777e9a6369" . + "50411e3f6fe32c3639684bbc1bc0e472f2204e3c8477f4165468bf1ba53228dd" . + "1a395e94ee1b968a53b8b98fa0a77e140b94e26721dd4a699f19a26ec17ecd13" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "44d38b0cb40e2bbf34605da4fa40f02e7efdcc205c4417dcbaf8249956956157" . + "3af738d109b50ed9256cd4ea49a9ccdddbd2b413302aeffcb22d3c6ac7525239" . + "26e1f24a7fe3459ca09cd6547a0d6dba43a4807482d03b00f92ed16494bee5b1" . + "3a939550f45494d0cdf88dcd8618787dd67b523bb0eb705ca6b52a3a8b6aa2f4" . + "78c7f1c12db904ad372996b1357df7ccd137e82ccfd00a6288da16c1a9f12b70" . + "e861ab8b73ca35d4237001ad361617b810f985236ddba22b9a50ebe3a61c1833" . + "f83a28e6c07b05ff54c5d87150a186632e17376032f27d813076efb2474684fa" . + "44d38b0cb40e2bbf34605da4fa40f02e7efdcc205c4417dcbaf8249956956157" . + "7df257b0019568955744449b3569c0406b640545a69a497efb8bab1d10e5f3b8" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "988d9cc38df5588a3528633e8b9461237a80a652d57a8e4b2bc68425dac4db16" . + "988d9cc38df5588a3528633e8b9461237a80a652d57a8e4b2bc68425dac4db16" . + "b298d59647c9a8d8e7df3d76bf4d2c010040de4e6e02d92758f552e5c158a6a3" . + "bfc7c8bc2444d3cc829c316bd47ca90fcf56978f46666f37620b31667c4e0f38" . + "bfd02977e60fe90d3c8db0e624256b9845aa27cdf565ea832f0f99a60152926d" . + "fe335564a5f626599d6596309549f71e23f3b8f73473081574630f8a26e6ca01" . + "dc73b4bdde5b2df27bf18f68b6752fbaa9fe4988981efe68d24613a0144c78c3" . + "ad53f1bcbdc1936ff72cb12ded2602da209a289b51e5726c49a4bca469928116" . + "3ebd5d5a4edb14bdad0b8595d73aaf2668d5cdc876941c55b64aa111480f7c36" . + "f92e40da5540c9d5df18328d4204a5114318f12e6f1db9f402b663671e98463e" . + "1fee4f02a743a4d119caa7969441c84b03e9cf11270bc7f3a81bac145fc4e6cb" . + "76053a4ed989563b3eee5e86fcf5dec1ccbf4fbc0fb1dc33623021378090a966" . + "f365548576f1e5ffaca74ce965157d68ef3b65685eae414b45b2e4bb75c10172" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "cf353dafe99b173f0fd5f69b73b591cf6a1ec1b40f8d183fc742dfaf1d1fc52b" . + "6bf1d6430960b5f1395bad95e04d6e7c485f68ab44d2dacc318d7801cb5f626d" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "d01e02df63c154e7ce71bc3f3a54a11a76cc3ba205e92e7306426ef7cac0df87" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "9d43e9772231ff8ea8f21d38ff51327ccc86afd0b46d9112587c3942b70656a7" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "848b98f2cac5e0315193cff02e848ada1e09a4743792da01e20b5a3f51a63308" . + "af0149c38c8f2acbc890f9359b5aea7f96cb733d6ccd26251429cfc4a766afdf" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + . + . + "9b87e579a9b4f7d1fdb8b8c52362929f5d2c5e731ed529163f7cd571ad76e930" . + "d4473db5105dae59d95f19f8603f0c479344aa2b463ebe0827811175565d9a3a" . + "332e6d9da50ff4f3453b3bff011834c9af2a38578aa2a00483018bd6aee9eb89" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "06a4e33495924d289381d7c32098b5ff641cc6ce2269eb36e7ec1e5cd72454d8" . + "06a4e33495924d289381d7c32098b5ff641cc6ce2269eb36e7ec1e5cd72454d8" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "552413e9631721d1c69c4569a80197162bbc51821c214535fad4f72304498d53" . + "6561e2fdb733fb45fa8eaf51cc50a53181a3bbed99924a0e5c8718da4967aabb" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "2a5f5de3fe08662e8cab9f6abb69ad6ccaf42eceef57551d3861ede489c015a3" . + "ee88d1a1c2686f9c3c1e16a785e6a4140d9cd0a705b80df6bb8e7f99196cd5a2" . + "e52f538fa4f82a82cf824bebb1c13109fac8a3ccc5fd58f291eb3abb7b3a639c" . + "dab6fa2c3d396bf723c832ac2cf197dbfc007f0f403e8a5ce50efd248cc5e51b" . + "7dc77ff2e59c57a9fbf3fc5b494b8e3df65c6cb324974671cec883ee6fa7699f" . + "02261612945353b8cd2073f80246b9959688287a425989a8456b1a739ee0ac55" . + "5564b1db36e840ea358bfb58266c3079503a141c68bafb761ee3e1987676fb72" . + "39fe9320b3a70fa5009c50c0e54f59db06b3dd67a9c20a7cecd1bdcd607aac96" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "0a90e5e6477f0fb3db40d82c789f3e5f744c6cf6563f764101864be78a1fb6b1" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "b5cc84a32d5895a7511ebd8d044b0ec8050f411a846a810526d871fcb1917bf7" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "6d02b3206b5976bb5de621da870c94e1855889f91fc4a2c952f191bba058633f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + "42731b8706b44c9c97acc2218afb18ae4c6d12184f5dc452f36ad1d1ceefa2e7" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "608c32de5dfbdf7ed96c1b86ca056cdc128851afe8acb534db6a0fa1d7efa982" . + "76053a4ed989563b3eee5e86fcf5dec1ccbf4fbc0fb1dc33623021378090a966" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a1279cf17b7dc3530c03e602868132fad10c6a2fe1fccb430a8be6528670a604" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "9bd2d961e747f086867f7ec0b599841ee670277cd9113d20f10649e7f2f98911" . + "79561a0af3f32553336da42a61d24ac0d593ae600dce717ecd9ed9cf7d66ff95" . + "0a237cd46bc96ae66295bfa912f9bff64b60e92a176f34b50bf384442c5873ce" . + "5e3c75f78221d52e3968445ede68b17beebc8aa838401586365a2ca121abca5a" . + . + . + . + "6d5a4654f4c34f53b1708653e3575a5efd6a571bfc8877bc1fa105c83076236f" . + "7e82e9697e28c9febbfa373c176646f32779997277ec20fc087af941acd4e490" . + "63446ef864df7e94cd8b04dc8cb8e7d6b84689f6d3c5ab3d5a40cf417295a940" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f9dcde4ad3da426c64465c2511950a22e63dc8875095b51d8c5354e6f5ddc722" . + "820586ec713cab9c83dd1cfd73d1b50a196cf1764f877bfff6468ecd5d5ac448" . + "f6eece07de48fd00336b0782670b90a2ddd255020b306851480205d085702c24" . + "acc00597604aa05d4b7e1896fff1887b37fde0018e962a0633bf0ba1a6598b28" . + "73f43917367b3ce0b298aa4292d404815dcf46c24050939d35d0bd905caabe0d" . + "8a97fabbf3df53bbbf19a5deb6318ab188da2a7c2dc166b451859580f4e7bd6b" . + "3faa8342d656e3a634ca48faef446b16710a3d26dba80bbff61728c689bf2c0b" . + "78982e048e6ca4436fc69d24dd0de91dbbfe809669096e71ff11d17ebc73ed06" . + "35d39e9410c3c27ab053f1eb9df46fac79c6f13701a9abe59605e7712d171d41" . + "d916e4a1ff0bab54951acb62cd271f2b7e9e39587cbb8d6446ba2ac0dd214445" . + "c9aad745183eb490e0cf4f6b0a95c4d76a15c1229759530b901c18e5dcd43238" . + "f8956c0a2f45b28661b18e357661fd90fad7e7431973f7df1a17196eb2aff6e5" . + "71e246881ba05079bc645c9a2fbbcaa0745081b858fc37763a1b3e7212b82a72" . + "89176d3826888c64a9f89e3a870b8b6dc97a7c165ed38c90ecf2ddc04d04b867" . + "b132bce5225f389f300a629a2341365c8c6f6756f7144e3a77e399bc0e8f6402" . + "830c93575a0d0bbe58089be281804b7b4a64cc6a790bf0ad90f98369a41c1629" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "137deb2e53547c5634ac4036a68efda8b23033a64c4b94c6cccb42da9809e216" . + "816e1230f26fed1895475bd196aeb9330d4295e44dfc9010875f79a0c9a4e79a" . + "c809a8395a4b51cc947389e010d337361fb899c1e6d47b850efd14c6285c4a78" . + "e11c9a4d1b045dbbf970639ebccd25d3550b4d94955c8103cd39328b95d9845d" . + "389ed846b4889807f1630633ac25edb18148b00f3cd4ff488d8ed5e6ca75e952" . + "f3fb319e1858e97afb014350053e38ae006b8ec37cdbc5313f0efefaf88386ba" . + "40438d68d3388a1b7a4162ec9f9979fa3a29fa5f19d044bc0d61d8a48198d646" . + "f4d45b965250a4e1d62ce0c7e927a0e1f7079efb76b0272f08f39deb4ea068fe" . + "e8ef66c8efb2cfb9445f3c08fc44f652b939bb66a36a70088bf6886924344be4" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "fc5d86b4ec4dedb4efa189fac08f741792ede37b756452cc007bfdeb452daf5c" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "6e2e0194790595b4d99acbb82527b0ef3be5edaca434e522c0655599bf2840ee" . + "63e97b9934db79481cc04b0d1a7e9efd2a727f80a3bc533582a4f3d3dc34e862" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "09b2be2494345f3c2c6ce75dd8c22d45ea671b41d3e273a6d90a1ce5cb977fe8" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5adcfcce1584c44f42e0303ac9ccee7c32bb4b712e1ec9dbbe402a171dc275f3" . + "4062794f12267c1a2d6fb64884036d7c1c135d61b6aa7064a4f0251d7763c3f1" . + "2026ccca4f3cff99d6886027eddbfc61d6ff59b61c6ea816792c9cf41f37c2e4" . + "86eee31ddbf0bf64e54b62389b261dbb906c31d7e6b6ac9d0d2bb4ce957426fc" . + "3cc7a7601a4f921f363ce2b1f9917ea4fb2628c9e13ec79b0a527240be8b6bb5" . + "5b7410bd0c313e002ebe2321eb746fb9ad3fc6a8e9b9d2f7a871d05aebd56a49" . + "72b477123557dba6c98da4e530604efab9bbb242e5a17f04c1d52153b667d6b7" . + "299382827944c8c34eebdaef3f2d5f9343c1c9bf52041f0c39eeea9037899e4d" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "6353ac459879e2c0df404a6a6883e4ae61fe2c5fea85447f9ffd64c3e5c27819" . + "7777a256ba3b165a14e9028d52f96df6aa65456ffcd908dca01b69c033079eaf" . + "5d2afe73a3037a81927c070aad311dce5bf92bd09b236a04fb04cd36f2b75d8f" . + "985a2dc3e8a0b7acad12a0a621229f46e0b3d4fae43e04069230ec26b15ffa77" . + "17094dab774e7487172fab9fe4097a506c7b5409173d34a2240988516ed48e47" . + "d5c31364c44646daafc2c9b870e48dcc48c22ad87ebc1a9ea38f932b19f6cb45" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "bd19cc9e2c7b1933de6a97faf4ce92238a9f324d8e5fe99a2f3e954798ede962" . + "7f07467e2d33dbac1deddba2e43c706c1617b8b5b7bd7709ce2ea3c79a7a185e" . + "7c1719b4ac20b6f3e01736f606e080b997ce38ed93ef38aae7d5da82fe3e5b7d" . + "5bc6a2dae68017bfe3d6becc12873ef85f52889d679679b8750a421381f84c6e" . + "bd19cc9e2c7b1933de6a97faf4ce92238a9f324d8e5fe99a2f3e954798ede962" . + "616b5f32a97bf45c8ce0d2607d52eb09710d552e685fce7d6fd386d238c99d9b" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "74d74739672d70f4b35e8cf383fe00e100fecf669af29523fd415e2fa6b2ed2f" . + "74d74739672d70f4b35e8cf383fe00e100fecf669af29523fd415e2fa6b2ed2f" . + "19ab1b013de2377ce35a6c8363eb813563623d5f6a4ad001f2009363b99d3d2c" . + "0148d3803ec6269bcf340c834cc78623e76358c3f11782b22a547ae1c91c210e" . + "ab76c6b8979213cffc6d92a7c4257edc56c4500087b6a95b776849734af6d35a" . + "f01c7ff3e3e993b8b39edf00bd829c90738a2e90ee19f69ff62a1fe279b15202" . + "199c0d8553efd26d04068039e220781b6ae666201902e5717957d86f0ef737bb" . + "cbfee6d541b92f1f4db83d9f83e10378e62b2f4855dd0337e8f3c56864bceadc" . + "021471a370f39331fb0855754ace54e757970e5a117e3b87937ad7031a1a506b" . + "e209d1bf88eb5dfbaa0e02addb3a1065c93f3b1379cf566bd14d16a08cbd5b23" . + "cf61637ee06c4c6c05e675b9d8340fd06a18c60dc07e2e8ff45218ce5d15c105" . + "160b88c8056afc5c4bf9587f7d757f286ab5086854f3b8bb24c2866a35c96b86" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "ce7ca2ddbf9c379d5fe3e0955a388482c432f3c3ad69a449a999a92a55b46a0c" . + "667bd6d3768082ffa1f3355496e5ead4ff12699df02d797b804192d642a98f14" . + "a28e4cadef89275016a39e643f1b0f594fbe5029b0ad5c0970ccb4c55dd69074" . + "f3aab76bebd259293fd01dfa62b3c224f54cdbd101e39fab54ff967762ca9e5b" . + "cbb88a9d1061e99d0bacf2e86f51d2a7086ccf60ffb56c08f72379c858d58695" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + . + "aa782ec521f9b9a4d563b24cf409caf08f5e70dd3a57b32afcf765978e43f6f9" . + "12e5a77f88348780618b0c919a37182373ea0be70cf684497fcbcd544da0bb13" . + "161e661c0920a7ec5db77232771cf3cdadadd7652d4ba041764ae8df92dfb8e5" . + "aecebf437140fa60a7260f4b490bf548c81612ebfe2b55488be600ffe69b2592" . + "b90821771fad242555ac59e9e29f0b4555e81b43e7ddfead86f36fdea598273a" . + "8c51309d27657b710582a805847a70183e64ab9f781aacc0b2160f8440aa0d5c" . + "182b5d8cc02b0f4d9618dc24ea38b86bee84b32ca13a3997dc7d0187f464bc71" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "d798d0ebcf6fb60b0476977679393ef4bce87c3776c3eb7e6de1eab3ae2958ef" . + "639523320c18580023bd12aff4e6893ee69c061cc94f0e99df3f0b500d171bbf" . + "75884174c85725ef2459aff0871a55079a7c4f556387d96e4f14e03ac7c70bda" . + "ce3104966228102195b9ba45a146fac673e85fe56f5bef06416086bb667620ed" . + "54c93e5f67920242e23163cc6b13b7100bacbfcb1d9b7de56cbf5775d4ff9a5d" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + . + . + "812431011e1d40f60501f96795e928c22adecc861ba1ee242815ba796ee95b53" . + "5c6d8cb009f4e729d532c850b86f99314ba30eb2bcdc0e1ffef0bd8d7e18d337" . + "f3d88426a12767eeccd66a56e56d11ee1f3c2188521dd3e0638e77a37eef7cda" . + "472656345618dcd71d2c5bbf4f72a3415b61e8bc879e0992461bfefa4632f52f" . + "4b9e7976f1ceea275510b3f78401e0f4ce5bc2e527a47547943cfce364b862a1" . + "dd84392f47438504715047ba26ae7f73b8438845c8ed8ba82b4aef6db044e9ca" . + "e0e0fee86680d1ebc14f4c3e7c3559c1d456858d8aca749d5a8272e84b33f024" . + "770912c1167c75af4fdf96f2aa5fe030f1db14fa7dfc770ace283dc7143895ce" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "ebe139a9fa21ca2953b687c2f5ab15ceba984c28f8b0fca7a28b08462d4f3495" . + "b1f9392fddf4d43b0453839041a246e9a9fae53bdebe5a180852aa48557c558f" . + "09a258eb72f86bf1125a3fba905bc069a621f8ddc0efee4030704960c6905f80" . + "00d3df5105484cf78dbfdc5d5a730accd976de53e2e7a3e236bac2117e301de6" . + "fde3e35e7e5a4c11fe03b40708634205fa64e1d8d2ab197be86c1008c92a2722" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c5bf91fe7cd9e30fe4ba9b3a4b5a3496311b334558b8ae7e253c0d5199d905cf" . + "2c3d7e4df8c7773099a2e7b58254034f17a831c1de910a93354ec54e320e4132" . + "3c22a9fec6095f58b1d0387fdcb67f0fead14108de247ca6ef267a1eaecb5c2c" . + "6a146f2cc14baca6b8600b7c20fed689342c7e2e4f3cb82e0bbb3d59d87e3d82" . + "9cdc0c0ac68a154f1fabb593bd636c50447606b005696815ba856c0d57316f69" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "a0e69f1d5c38f8ac4ec032c17535bb9f2b405f3c739208ce9c1404e68aa335c2" . + "aeb2234f8a72f79eea49ea9d70f2a6d63133196e60932cbd1a4b1897199d5848" . + "da340d5dd825374cde36ce4abca8ebf0966580c94e07ef8e6abfa1deb28a25b6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "acaf479e736ca00951d4978f2f969b07b378e215cc94d0075deb88ef33aa83dd" . + "acaf479e736ca00951d4978f2f969b07b378e215cc94d0075deb88ef33aa83dd" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "39232d11b1662b7f79147dc16eca775961d020d3228e0593821a2cfff507c0b0" . + "63209e0ed992715a56011fc6f8a6e670caabaebc844c6e7a28fb23bbecf91356" . + . + "3918b8a701fb9e91db7b87154ce624940fce74f29604048518c4af896f57f26e" . + "07455e2befb7cb374c0d480b007dc71ba31ed12e3f4eb296adbad3828e5bbc15" . + "7c06415421748ac83f58209295205866ab053f82a6448fad0ee7a95f18298c51" . + "715a2e433f355f7037f8424b4778cdf65716f52e8a5640470498de7914493508" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "bf761da4c62b7d88acd021b8cd92bd3187bad740cab4b12d1dd7e9761fabb1a8" . + "0b1e356d0af643f17337917b9b95340b4e5010fc8f9fc0a5cdabdbb367b5f2c2" . + "eb602ab3abfd1a28d3904db335fa33b6e90d7e584819663d79739c14262bfd29" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b5a4fdf5673e697dd1192119726c453126201f8c673f9de1ff7ae91e768a023" . + "87bc2ae77dd59ce677cc079d10f42366ee7d9c4da6f0f792bcbd05bfef555178" . + "dbee3bc293cd2f976b6f543cb465584f9d531fdf1ed8eb5bc4a99d5204bea558" . + "3be0c7f843eb3aae2a14af55d6a7e882db59c4e7c1d0dac5e5967dc3fd65dca6" . + "4f06bba850a2505f972f499382b7f0f87062ec92c3dcf6513a2d3ddf4136213e" . + "37b559d429d31da94dff2009a30b7fc7c68e423ec15d7a60b29a3684f6adfa08" . + "aca8612004d656fe24b048f29616fa37bfa6bc3f457a6878894d4978e8724837" . + "279e51f3c4b7aaabac8f9b97e501efa9950dbcb4eb31e9dd58e88b852ba4b0af" . + "fe5212304413cf0d0e0455db442574408110fb8c2e1bf8794b924e37882cc179" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "357435538fc7f8ed5a935d26ec3eeddd48bbba14b05d054cf0989a79d7ba4544" . + "9292ff92440c9752a77533e73370fb39b777fc660d0a9219d76107229189d9c4" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "f7b4260bc80f08842e0303221c703a04241a8ba3a467e9a6a1fde1f0726a583f" . + "311988edc12b5611202c1e30cbddafb07d67ac699d0bf4c058dd7a76e46f73e4" . + "99b1abb4b697ca6fbfdfc0f430f6ac09f903d7e67234e0ed1b29c3c7ad066b6a" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + . + . + . + . + . + . + . + . + . + . + "8d236468ac567fa57e798bb030ce727f7a954e63397b1cb75a9e77752b708ee5" . + "6c42ef0917a8e8afd167129d18faa90f9caa2fbfd5d5a63ce6839bdbe42c38e0" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7f4fe46bfbcf988d501a9b87494fd9febd842b4df214c9c8fdd4ee763a61481e" . + "7f4fe46bfbcf988d501a9b87494fd9febd842b4df214c9c8fdd4ee763a61481e" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "731054d221a570e0ebc88f381a6f1e12ceb7ed0eae8ec865096e6bf26a68aa26" . + "0026b73b3e8091f8e27d5b120a9c3a6734ec654975beaff492f3ba4c09c989a9" . + "e4ed7a81ecaf11df8727cc613dc083ecefe296ba429e7599f0a833952975d2f9" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "f07c0c44006a50d771175285afd90f544172480c0f6e5eb7edf233bff06d5ae4" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "1d2dba5a3f6e37a215384c0f1c3a71b1a3bdc6666484720b5321cd82f13bfe79" . + "c01110ec5326e527a1a35202877685d37d1ab35b4bce1fd73c8655459c976bb1" . + "dffcc1b124d2268b6b1345166814da796bfe1730630b6aa47998cc414e7998f6" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "6353b26512124efec73f474a5c3d8540644e119732e6b444bb286c1649e25c73" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c01110ec5326e527a1a35202877685d37d1ab35b4bce1fd73c8655459c976bb1" . + "906dfe7948cdde2228d1c806bd0163c1058d4278625ab1e444498cd5ae3df8a0" . + "6dd47f6e8825acfaff90295223b6d11790eace827dae9796bee4bf29a8cc2205" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "43bb3d6d4888166738c754446effd5eca8a23eb36d69c775f41ac6bec8364bef" . + "f8f59ef9f426830af447df83582831ee1c9eb3e86871e417edf4b7ec13cc11c3" . + "107657727b755c714e119e7bb5c88ca8961c3de0e16acf8073976624b45c90ea" . + "1f7800faf0e9701e26493cd0114a92a19dcbc42a8d72dce560df67914129a1f6" . + "9dd4623b282a2d77a794eaf265d19400240d6271a40eb7a42ee0f82f0cfa1866" . + "7c80e2f9cad452325e2e865b2f919dbfcca1432a5745df343446aa4c910ce9ec" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "72033db5b36148b254073d7c503d68cfa44aae42466301027318f5f5412c484f" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "410563af03343578e3a59414cde9a062115b137c292414f54ede4bc91af96364" . + "c70e4ad18d3b462b41c2d7fb804e1311f999766d4ec05c74d0feb7ab04187608" . + "41ab2f52dc32f211a6714a40590956e6e5071a1a96abe8f79ee44c7354b1a299" . + "e881d20ee1cd2c978c6b6ffa96907753cf5d6b2b623af3909ed36e4fd59e0d92" . + "57563ebe9d321a47cf2f44e95ac3498bb11b9bd6e9770169b8c15d46f244ead5" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "0ba9e91d2b98ee982d81f116dd226782ac7f9b506e1ee6da1d3c9c793bfb70b6" . + "5410951cf0705c35d9b500905df85b56295d72e92925ce118f3765ae95ac0f83" . + "fe182069747887cd77cf5209b72a59226bbe9de2e0d9ad570cb98f351d0a100b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a7ec7ebf45b74ef9adb5c8171c40a0aab9a969d707dce20c90963b7d8b8dd8e0" . + "a7ec7ebf45b74ef9adb5c8171c40a0aab9a969d707dce20c90963b7d8b8dd8e0" . + "9c200f3f134b5bc51598bf1c880431ddd5b8ad54f0b4f2d0deaf43e54f9af653" . + "4030b34dbabf83dd35eaad3249e00143d310e1f60c195401912e7c84d90468c0" . + "393bd52bc5b1c3844326c85cf69cf55a845ecfc8ed85b3a349e41d4cde04cc72" . + "c11676cbf498698220dfd00799f98dadd50e6fd4d475d89133c6ec64f6e2c9d4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0e4675329259477c325b0ef6e344a9a7415db37661c049243c6b126d97f54054" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "e1947de75a684f8b666eb7c875b552bb9122de10f459d482dba66a9f2803b06d" . + "9f5ed452571b70bb2ec0e8b6d6b2b4ba7a981c992c099d6d4d0a074a398a4582" . + "be4b7a70b85ccded6fbc7f9b99de0f9be7d56a3a51137054c5254f7c034c45d8" . + "58a50b63a096cb71bf4f6f622906cf5beb9599ddbe00eda3456446ce8e072ba5" . + "3e992a8c510ef9e33febe5e6fb8bb17ea3da03d46f3d9be4270b7d6246ae0e7a" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9f5ed452571b70bb2ec0e8b6d6b2b4ba7a981c992c099d6d4d0a074a398a4582" . + "6ef00d46cfddb3a1e66d961627f7e56ccd6f7b1c772e536b248c701c04d284fc" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "482543845dd3676306bfa12fadfcec374de38ad2f6177ce2b2b4784992658a9d" . + "482543845dd3676306bfa12fadfcec374de38ad2f6177ce2b2b4784992658a9d" . + "8eff7f228d5c4e4b09cc9b3e11d27ae24a1181368fdca57cb91c9f7e2b605cbf" . + "4a0a8fda66c9f071d8d691bdc693ef6c4bd936099e15568312e675daef9495bf" . + "13179b5b715e66bc3a97e2d6415c91bfee0644b7f6f4d25d2b304dfa5890dfa2" . + "72e678a1644ffeb82f66f3e082d10b1e35f1fd1b6374aa631f1c182c27163968" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "daa093954c68032e6e25ce196dd79cd869fe0f0c099efa23769c5f75f138a2b9" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "58bf2ce12e2b1a64a0e9893ee71a0b16f01b405dd3752317e46b13f6445fad82" . + "128ba02766099117e1ce033ec36b5c773410d2e95b3156455c07cdc2b683ca4d" . + "035d0ded71780cbed8ae6c5785268321c97f717b536dd7b351894e6efac8f34d" . + "c2a846f62140421923e35f449666b365aa0bdc68031dfa861bc3f9ecf2f9dec0" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "55658704611e5eab80e6540d64dc336c1873ea8192e5e5a7e491a567b99485c4" . + "730cb0b0954ac8858a54345bc02efedb2302153e85feb572f1ace34f0bf62876" . + "376cb330e167a66c803b03739d00c8586fef3edab1284ff28d18ab2c4b845068" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e72c683f8f2f4b098668d4c0e3102fe7d3b1afb4b4db140f43b9b9515d8ac121" . + "0ae0eee4fdb65276fc7aba42e0b588cca84d8a85819c004520da9be199382b97" . + "0c6486798b303a99de584fdfaf56f5ea858eba286c0cf4dd27f6f9adb0da603a" . + "798276df582653765d23275b30d931f7c0a42fe26d1087f9fbe251a4f8982aeb" . + "c75e69da9c25b723bde65e3838bc891f1142c41e4af1b4839cd43e927dba93fa" . + "6b0cdc4199773e7598489c433db1e8eb21548b05f3b864058038d9df6cd4d8f6" . + "d2e405f237cc83eccc1ecdfc003419eb5af7058d68835233f1e1b7fc2bea7e13" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "4106eb1454ae5053ab7591ec9731882e9e7afeefe1a94faf9140f23161427ce5" . + "6a12ceaf75a7f8282f7763ab2251c20018677ae1d27c7f68f512ab8529168e1b" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "2f65b8daceaad1124b3c5612dd5efac9cace62ce4424786422353b562f5bbbf7" . + "791ec73e27087d4386e1747f18f95b2874084116797f9020c13174c49712ead7" . + "c527ad9b39a02e64b5644f67032d18c54bb06d6456909433bcf13db2c5bc561b" . + "daf057c8edb0cfe1caeb373197009a50aafb49c9922ca61de1b4f0348c337494" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "be851719d03d51fa49b2b5747847a5541328fad198e1301d193d825517bf8f39" . + "737fd8e8626b437791590abc8900716ee410dc2337173c211686083dea5576bc" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad374dfa479680b64dd92079b15c65a3d97dd92f25588fc26b7925e4063b1003" . + "ad374dfa479680b64dd92079b15c65a3d97dd92f25588fc26b7925e4063b1003" . + "d03c2f6b51843511c3804f60a7bfd39bb5db2f8ddaab2a7529b5c441f46e8b9b" . + "49120ab9b6d8c06c3af7b4095c9c13997bd28b4dad9d5bf760d83e3878030515" . + "ed7fbf081a4915edea3b86712f83e3bcd24e758affc260346888323cf90e5c22" . + . + "82837a0a01de55149bf8e552307a69396f8dccb54b2e40bced98439341f5ed3b" . + "36d1375a44b0122ee70f91844060c37d2c8be844c73d1a1881dcd01923681273" . + "6b4187af37a75425fed1f5bc3c7a875fc3d4a8d1ded8687917c6feb90fca3d27" . + "e9daa000b01f3526411cb83949e4892b040681ee095e83c995c7d890972642ef" . + "f8ac7f5635af874c510712678a87aba4ec64de33d42d6060e6ba49235b1902e9" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "36d1375a44b0122ee70f91844060c37d2c8be844c73d1a1881dcd01923681273" . + "a8f3f53f61973d1a2135475ef552b74bdcfb6c64f6ff61e18b3924f55405d143" . + "660a4cb6055f53e803faf47a0acfdd3f40cf8ad402be4c6857f02f1883f221ee" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6bd2ce1574820003dbe7c5a9851d525503208c968431b87a4bc3fbc723fc699f" . + "1ed8814d45be025e5f081e56e421dcd5b71d4b346af6fc92262e6cd344edc24f" . + "8f336e6f0a392807a778db03887da67b0d967d148aa2232391c0f9635cb23dfb" . + "065cc350db20679fdffcebc88519208425a70899665359d540b260a3935f2801" . + "de9ff1cba4299257df1e70dc7c75c21c19456a6ff15a64f4c9d3df9803831660" . + "11f26c83ecbd38c19a8a2a6aa99843b5edb7e956c9e053e514682ef3d84c214d" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "1681af9404422a4797f85a263cb8fc01021d5ee7e0ca3252c82df753eb1a6985" . + "0b89f00adc76e11d93ae5faf532fb248cea31b50d749d7e8de8a382a3901fba5" . + "258d83872eabe446eeb4e26bfe8df18e0fe76114354f65bfbd3880431d7cf732" . + "e0921e1910dbfe7c3c7bfa1ed4df3fc217a678177154bf2ba423c04f85dbedc3" . + "35eb8177a0b03b547f135fc0cb0d4690014c7787bfdea03a28661055f5d1fedc" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "80b1cc30b4e3d4cc95fcaa77b0f8b6b5a94cad6b7f89da9d1c7a079d67c0348a" . + "e8c1e752dce088188cca620bf5d347f27132880c3b16fc9d1d25205e2c7860d4" . + "f24dffa63d305479c3812eb60abaf9e5579d2322d712c013e26eaaaeb3cf911b" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "527dc999eb344f3355d345c30b6dcea818dac5e8d8c85918b931d45681091add" . + "527dc999eb344f3355d345c30b6dcea818dac5e8d8c85918b931d45681091add" . + "a60be5d0ec629f2a85f9b61b0a6851f07258b6f742c878f7ab7efcb2350dd12a" . + "94c11d776366aea77c6a6854574e4b94834d6613d8074fefe7cf66946ad0b5f2" . + "6d630691c8e8064ed64ba3211aa1c981eb519fdd9dc04a8b5200c0e4b722a710" . + . + "23ed61c019233693ef9c53ae656ac11873319f6d21f9137da3e91c96265e2e7c" . + "33f65859e1e05df6613af3779e68592ef8bea061c2317f35065b2a01d6cf5d36" . + "77cc9f769f46b23660d4f689bf900726bf27ba491582fc03b66fa19f222515ab" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "7c1719b4ac20b6f3e01736f606e080b997ce38ed93ef38aae7d5da82fe3e5b7d" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c2ebe215fb43742b3ed1649775a2b7eacef4027e11fb2f8a91f79ed1d70bffec" . + "e7019a92516da12c62e1536c1329bdfd075a7cd467224169e057b11898da0d0b" . + "89e21f4e07793c735de0bd9f37a4d031dd1d75632201c083ef47b33aef1ac38b" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da8f6a30f36faae87a01e4cb733515fd08364a04470794c87b0c4548122796ed" . + "da8f6a30f36faae87a01e4cb733515fd08364a04470794c87b0c4548122796ed" . + "58e6a1abc06f48070f4001f2eb267dc56d706b672802c57d73ea634f9cdd9c8d" . + "535c265ced445d9da19c7dd3c1effc002575a6d04698e17058f3d06fbb937c1e" . + "fdc3bb63d8ce77d6890971a5a3a1f5cc826f86bb9e62b4df816765c47c9986dd" . + "c06bebe1eb919da7d2b9c06bc4226cbe6767c2f17c2201dc8bf06b87b9492021" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "5724a536a25f1d145545045ceb16a601976cbc64ac261a082b66d322e789b325" . + . + "e6ec92cace61dda9ea80d24b81f6b62a31885ce2596697a227e6772fb6b415f5" . + "576b81ec2a86156106b8c8dd3b7250e84874c4eba13dc0099b80bc315094dc0b" . + "8ccf1e0009d9fc53fdd43dde48a40e1f51b2d738034a2edfb1d8580757021cb5" . + "c84f22e9222680d4ecac3e029ad0ffc5dfc9f1c5b4392f610a7d52684cb6fc7e" . + "acfc7c9a2350e691c432e5cfe74159f79e460da19a23113b887c7d2896d3b1aa" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "fc46e12526503ba27407e70e4e496d88e437f0e61a1231ff93b11916f990d650" . + "c2d7efae8c5b375641e6c965175a5ef906f52977c2387df8804ec35713ea812d" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a763bc2f71f257a4b56b7ec980639ef3d6d75b0206855f445345c46ac312538f" . + "a763bc2f71f257a4b56b7ec980639ef3d6d75b0206855f445345c46ac312538f" . + "a6f9c429c13d1ed2fd6d70029be6c5377c7ff426e118e331dbbee87079e5644a" . + "5fc9400b977674521bee916e6215ff741461b8cb2efd502b69b8b09fd7522ab5" . + "2d0e26274cdd5074e71d9fdfe578e51df7af2afecba41e8a72d2f6d37190e9ce" . + "35b9bdfc80408d32ee0fcc8fdf3cf9aafb2388479b3d26d59d27a7700e826913" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "e11c9a4d1b045dbbf970639ebccd25d3550b4d94955c8103cd39328b95d9845d" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "f3c0926e9feb875ee0a081ec6d1c37c6c409ac89f2a84ad67d575e3002097b98" . + "7689589111f0bd4f5743feb00d57ecfd640d2056914b042856894dd751b9d7f7" . + "5ad7181e314928f65eee913f3bc5058731252f3ecd244cef6f063b8316818e3f" . + "75df9d638e8ff8ad98fb229d041fab5a161f4bf5e2dd5dddc5620540017924c3" . + "106602aa2144f66d0d71f5af40dd87a7605d499351c09454eb8dfefa2e02c093" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "0525a51abef4a9f9efe8ffaaa242f8e9ede77ef8a921513367528fba0e33c57c" . + "54f46e72cfc30738d13d59f0200c3bd2f921a60f400eb9224001002d9951fd48" . + "51648db51d77b8c0c379b77dee2d7108da4baadf89ae31f2bd158e4f4ba99658" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7ade7cbee49b5af9b55a65b9576ddaf8b80e033f44049827c4a7904a9478411" . + "d7ade7cbee49b5af9b55a65b9576ddaf8b80e033f44049827c4a7904a9478411" . + "1bd6042e9bc3296f4a513f189f4881e18bb30c807cead7b8ef17ffdc92410ec1" . + "c6f34e6138da789cfdf7cd890efc5df1a078625a89ca5f8c28fe1db15ec2346c" . + "1ad5b8583f769efb77c5d98fceaf1dc0e16d349f47823dc67abae2936afb502c" . + . + "e1c80b154b21d2ff93bb9ce83a4e5c3950eb4c9e013964cf0fdfa60a1be9c6de" . + "e2a4f4b9a11d6ff7174e80cb2577a8b39a2ffae79ad7a4143573307ef37b91ac" . + "207a686cc5cbe6dc081cc115dd94ea70021166130257e6bf3cf1c07e6bc63de8" . + "9a4177cbb00fc4828d83313de2f1f41fb4a164984ca6a4593605022eb9313dae" . + "bb34a56210dab7a76bcea707d9e0898d2aa9e818dbe9e0a4ce7f764c2f0944e4" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "8c498a622ac4da2f2a9a559e29b1d59fb6985afa299d8ce50086a1408512a089" . + "4096143273a2b85cdec4c8b5b1e31326511e5ac82991e409a13e5fd7e6fadb4f" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "973e2f9a52d60e43130bbdf41f5d6651cd7ea09eb0cc6d118d525c0429ee158a" . + "973e2f9a52d60e43130bbdf41f5d6651cd7ea09eb0cc6d118d525c0429ee158a" . + "d222b5e3c100802bb23fba40af2c8caa6ab7fb856bb0c2edc3d63e705d1e441c" . + "be5ddf65883716202347b1aa1d73dc1badf7408acb2f82ccac1bc34947d833a9" . + "a46a02ca0d541c173451558ffabcc811dfa9013f236cb2f3df91c5f08035e1c2" . + "ec1ccc14b531572a02323c31b7b136e2b35eb255c199f31c79abcfc842e60607" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "031dfa8f89316497933bfe5b723ed6fbc7b00a0c536997e593b65b92ab678be5" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "8bc95dd814b54a751e78b56077edc4d2f716d5e0bbe36305d562f2afe9dfa82a" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "afee71e59752c5739a47157c64aab85b0aa63b2423bd16fb810e82caf64c53ef" . + "49f12fe4dda3ae5f547acde6fa529513605006899f6fa70dd497bf13a443fe07" . + "94ec90f201529de21ef181e189ca7f46b17cb2f8114b3f1f6c133f7a02d55381" . + "0b2d104f967258a041bb02ea358b79d8165856219cab2dca9827f6221278f558" . + "da553ad444c24d893523e4bb69fd416656bfaf33d844a427cdfde3bc3233fe79" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f1c461009ff1af73a0429eeab51a98b9f6ed475942dbbbdd8e874ec1929b3b22" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6067bf6626e91910f6d495c221db8a2dbed0527ecb7b6c9d0e9585c1186f0992" . + "408b0c2faa165354ccfa68b6cfa0c3053ec8e61906c11503b2597e4fb72c8f9a" . + "1db3a28a433590059bd6e95fdf9b8acd48257c67d795a00bf050330206c917d9" . + "d1fbe5099d0a05600f4e653ac452301669278592ebc8e87b32e64f895d796e83" . + "757c0cc95a3e77c79f79f5de49483c9c85f9b51dc94190a9b92ae2919533cdd5" . + "6416934e071f1e274645feca1a39c1c105932d14f2cc7f1c100a9dc6970924b8" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "26638f19e3b4bd24ac0f57824aa34bcc771f663bc1288aa60bb34db1c6f7ccaa" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "a138ac2f58fd2e149a38e5d23a678be3ff56ea4735ffe987d51407b09e8adf1a" . + "f4adc65c08218939f8978dcf5a9d17f787a0596293197774493497184faa62cc" . + "3bf1ab000cb089690fc351839de72d287bdbbfe61813d977d8892a7ebd6e1d0a" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "3a565c521d6c49d194f2cd8e015e1c5eb50d8e7f0e32709f62e5968f830cdaf5" . + "2f871d9860fdfd93689607ea25e7e5ad52d647de2ae3e4474cf034c8c595e730" . + "80a8aaa9308052e3beb0473becc1603b9aa7afb7871a6785480cb9d5951344d0" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c27312342f51c404e6d92bb61435c43e38789012797b7105175bf66753b24734" . + "c27312342f51c404e6d92bb61435c43e38789012797b7105175bf66753b24734" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "2302e9cc283b91b903cb17ad7a0f1e8c2c01ac39a3f1c3ba4a2379a0ae4b1c02" . + "62ce4146289976ad12a6cb1dfe09a49f15fcca4e7c8b95eb20b7057fcb1113d8" . + . + "7d7cbf70faca7a64f7a32d0ba32f114b6a20df38b9a6b4bac094731ccf0f9717" . + "03f8b3f1c2a7de0c4110af25325be543bd2ec87a1d76050fb858af00ee71fb5c" . + "7f133d340f5f91e54d2316873f0944c843b2f963412fc41b41ec309899cb560a" . + "5a84ffb5eb39c03d23c435d423d0ff064881807a607ba3fa6cfae06ab419d868" . + "c91bee449065238860869ec12aa5358298caab010385253c97d285468a892db6" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "507a03025552b0601da1654b0b38a9dc87577c48e0d3787b2cdbfb3e4ee1a305" . + "c5c0be9e33a2bea974ea86767391de672d26c864c23265e111358605e64abfa6" . + "bbd2faaa1f7003577516728cbb9b87b106f02d05173d920fb5fdd024ef051689" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ed22f1d53ae82bfbed368aa742bf548a4327e53d385ce8ecd8d04994dd727ea7" . + "ed22f1d53ae82bfbed368aa742bf548a4327e53d385ce8ecd8d04994dd727ea7" . + "dd9c0ee91abe6893e1f890f8c82cf1537a47096d290806504484c072480c891e" . + "03c8f6b375bddebd1862eff47baa7f0165a8d485c42b63af75a55209c8297014" . + "cac8f9e40355fb42db14ff24d2ad1ccad14b4befbf033f8b06756048a8f81285" . + . + "071943fa1136c2a2f330c19bd9817ca2f68bf9d713f66e4c08a02240d36ba6ec" . + "aae952b6475ae273a9ed4acb231703827adf29f011217bdef3b3e5c2418a9770" . + "a1e49cb15dbc7d9edf0073391fba4c851f2b8f53a21246c41ca98870bee0f4c4" . + "bfb809fd15af3fda6428f355c2f2d97f5077e64a46777b9f494e65fbed1ce9a7" . + "fee2ac3e1f8fc1df251dc375510e93ec2552cd1a2d45a9696cbed47a786d826e" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7402635ec49256936d94e1574ba69b95e561c29d05c131ee5c9b34bb3017eb74" . + "0414a7ab31f410068f331c8de2f9ce1d78198785fbb2d16790c7f442a771546f" . + "dfdb51745c872af24329acabe46aebfb15bebee202323b5fe5bebca4007ca996" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "83ad4fb214e29487d59904db366206c965917acfc581027a00ee766e4f3c8105" . + "aaa2b9c857ff89bd45714c566b0daeb314a578eb0fedf6bf0f629bfd8179d5f5" . + "e76fd9b3a401036888287c47fa8aae235efc629a717149a4ae652722348879cb" . + "b625dfe9beb904f52477616d205272975fd781c9be4db1aa695286128b43a372" . + "91fd08ba2282200733c42dbfd06c0f1ba075cd0cdbf90823b8e7e66bdd151cad" . + . + "f8f8e2a7e4f2424ef2d5ccad9e1cd66969fd7afffd87cfb4358cb8d326ad8df9" . + "8b4136c36c9cda127e76c267653f99d970e35c9f4a7f539551596da950e2dd34" . + "3a301cbf2c814706489b0e946aea8f6479202df46e4ef02a027ef131ab71095d" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "add64350b837330ee2ab603e036bb3c9b72f83c26e0181d8901421d69998ec16" . + "445067f266e3a464323be3807b5fe77d0e0eb1e63a601ea9434d36d344023c02" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc572ed843b78c42a38b79f285060505561fa254680572894463271826b44868" . + "fc572ed843b78c42a38b79f285060505561fa254680572894463271826b44868" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "403af423ad2a669a013ce04df867e663ab17e035dec98ae36abdb406f829a229" . + "c689b8d521e9e7b75dfd606f6d6c4f1a85912068439a61e5ddb2c85351ab6f2a" . + . + "7446018083bdbb704937583754457956633e8a4525245766c387b2bb8192b04d" . + "24b3e95152f0522cd7385cd52de5ef6b8a0bea50d44df7e19c9d642fbfc48034" . + "7f5c29070ccaf57b456cbabeb882340d7b3b71f2bc7435bcb76b4f1313a173b9" . + "4f1852774f1625de6eb3360245cf263a66fa34b660e1245d3b4905e22ace1171" . + "051a7a6db85621a1d5011d536595c39b8c9d54ba249b8423fe846020326db11e" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "24b3e95152f0522cd7385cd52de5ef6b8a0bea50d44df7e19c9d642fbfc48034" . + "32189cdbf1fd2e497eff8b55c614e49e4b1e5c17fbfb7e8f3316b1555cbac46a" . + "1c3bf8741f30f68ee16ee38ff86e63916f7087c316c6f4d4a93219ac7b8b4eb3" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3b40bb68bb1ad8ae6617daa7f5c4a81ed749d6ca89cb649a48f3e5ec0109a339" . + "3b40bb68bb1ad8ae6617daa7f5c4a81ed749d6ca89cb649a48f3e5ec0109a339" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "eb74d1d7552da2aa785f2d828a9195d40e3010a7c595d5cb30704f38e380d1de" . + "9a9e77e8d383218b07dae2521f315427530b72a2fad3ff4332fbfe7b08ce3dcb" . + "a754b1518bd43f285cd8f97267a2eae3434a4f3130df8e8fe280091a1d95f2d3" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "d6832397f18678381bbc63171ffa371e361f27d40ec98635c7672b57045441c4" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "203eb645a953c58ae9a54473af4eed42077549c672094dd7aef366adf18abfc9" . + "e12390e96ac04335bf6294a4be345ff40e320aaa15e5bad780f7e569f4c1f925" . + "2ae99eec07e4dc36c98827896cf8392aad98f1dda535ea7ebc54deef306f01ab" . + "0b2d104f967258a041bb02ea358b79d8165856219cab2dca9827f6221278f558" . + "6297397692e3bdf90d61f3086f261a93d1afb1c5d0c116f440e40a6a64c4f533" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "e12390e96ac04335bf6294a4be345ff40e320aaa15e5bad780f7e569f4c1f925" . + "5176bafa6de416aea1fa6717df4ed9c65002715e5a6fb66df9da111f4ad5d1b1" . + "ee4a376eb62831883285594b5f32c9389368aae416af51cf5e90a9448f752709" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2110cf470bb889d8ef40cd1847cb0a8c0b11a7b3ca30f916038d6a0b23b63062" . + "56471cd0b59cb13ac96ed7339a8629743f60523b87034b53a97066c79d929c6e" . + "53f93241a48932ce4ca93d24667fe7531030eb0351d06e433244e49953ba381b" . + "9886a094e6a3bc55cd5e4a0371eacbd780bc7c4389ea2d2533814b519e4568ea" . + "b4294e07889672d300c702a5bd445a5417a37d2d7466919944964d72f5b74fce" . + "ebce5d6c73da841c9090e1c382000b5e3669f5048e4ffd099deb19c8ece3c5c5" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c86e8e67d84a81499df04f0569d15b9c1395905b90c763b04e5a4651f26615a3" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "cdebfcfa4f2173f1fcff4fc21094e037c4990085bc129f9d6b0844c3b2b93853" . + "cfb5ae15f0f22ba291f3b746975852635a51eec526f94463390a1060f73d5424" . + "a6db64ab85615f9cc57d7e4e4273b17efd78bc620b393e1e4c30dc9d801a0926" . + "09594b7255c1c847d61d899da3070455fb484e9ab56693c75dd302a2215e2ca5" . + . + . + "0100de175ab4576bef5588d272214e201c6f3b5146a3a6d9152d57e84aed0220" . + "7ba53e04b4bd9b7d177f2c98b202d6d4e2de4968ae76bcdbdd2fb9aff64ea24e" . + "b19b83fb6bb0db06cd7a524830e1d2dbc0887d6660c0c260e5cdf827331ab175" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "85214bf32bb39de93cd190a1c6c9ffc59b566e1b4f84499af21b3b62aad98726" . + "f9169be49d5fb73abd354f6bb79cfbd37e1fd303fb09b77bc805e81ed5848ced" . + "453c2c41de691479c46569f3e1fbf4477d8f8ddfcac2da3d465302aff0194ca3" . + "2956f2859bc7c0b461b2dac95e60e8093293fdffe78b328fb9c1b1df34f62785" . + "e233baca4e042d1642b0e948c92f7e66fe31fed2d74fc5fbf0a0c22a1ceaeb99" . + "e4b61014681ae2cd0e0c86342fe3ebda1ad16fb751212aa56fcbf4d1b85ca604" . + "ce31167d1ae13b9ce73aabb5fecc5e51d7484c6fef1b1680f0b4bdf25204f17e" . + "2619265f50da76a095bf9725979679cc6eef78eed3a91edb1a451d5602ad7337" . + "725b05370613a7168a99da593281264ce48a09f5c1c12f5f4ab48e68c515c570" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "40438d68d3388a1b7a4162ec9f9979fa3a29fa5f19d044bc0d61d8a48198d646" . + "29f14c89679b3dcf85f47fc59d8abd33d680525b7b4a84c4fe7ad7da8a8d3053" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "6f2b30e271923cf922dfccd27cc005328f8791251dab360e0339794fceb92176" . + "3493c161e7ce6879bf71ffae421016c2cfcf7da1637ae30b50b043995f0a7e2a" . + "bc08d264c76ffcc308ce8dd72918c454bb84cba0cc2e6ae0f01fd4a99821a43c" . + "f796d1d0fa9534ef3d404315e061b1a606995956646bdf0280b8de5624d682fa" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "fff1384451d2fff64da3ca6536b3a253fde2a9f1db3632fb3e52ceb8f0f4d22a" . + "26d71247b9d193002f38d4d2c6e6bc551b146b8b96b94dfee274faef1358e775" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "6072cd171cf30dd64a874792d0b722d806470cf51455e0322ec956eb84f1b709" . + "e2c776ec520b4b1c27780238a26d6fdbd082939c651464e4688fc91aa70f3322" . + "3cc3b9e131c23469a2c96bca688465bc2a85a0a2334b31e0c09fb08c5701f7ed" . + "7fc217a32b7b718e750c008b804a938f07aeb20b4127c0ace0cf1ebaeaa4c176" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "769fe5c69f71091074a743e73096efab0a7f2e0521c7a3cd7b8177d40a7df908" . + "4162b25f555c2a0546f76da72780a5670822af1730d96d1c306f7fe899f5342c" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "43e8ea97bc70c00826ddb27fcbce682eb74682844c0097aaec0bbc912c2e6fac" . + "85976358ebe876352a6003f67ac5e92f5affc660320d7431b262e29515b5dcd2" . + "fecdd3c5ad934be4377651266953b44775c5121b9e79cd2b7779a90749976152" . + "f147aa4295aaf86a52d97702fcfcd103ed7b52973409bb9535f73b56d1537d4d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "2bc9c11effb02d6aadc1071001f5252080849b2df0708b67b1b63bcb395d07f7" . + "5d2abf010ba190315c58292d522dc5d11c891161b2a585fb695775136b124bcf" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "338cf92f52874418a7e880231f56b291e32161b96c83802e6b5b63f31023b8ef" . + "4d891049c491649ab36fa8276507b1881f4ff5eb61c0525aed958f42abce416e" . + "3a24fab4445a6f93b7e79ddf1937914d426ecb0bdb2d72484dc88af3aa917be7" . + "ba51a36932a472c62ae9d3a8ca7172a879b5ccd5c6b7f710b6f17a05eff39bfe" . + "0ae2202993109204123094aa7faa402bc73b72df9fde67faded118c840f5d6de" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "38c00c4794c38b7debd1355d6197bd946dcb457b1c9b91b860247d5599d17121" . + "5d0913caaec4b793106dc15bf3af48a78cd1b47f9a893c625dd25b18b79b1942" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7a7872306b522a29bf9278e5b05d11b53d5644b59a3d2e9e14de66588329b2d9" . + "0df954a5428f0e0680c1d2fcc61fa43f9ef71ca25b4afcff009c5a733da51ef1" . + "7fcb06ba62f119186cfe2c543258756aa83881f80a45ecf79364197f265568ea" . + "b0c7b7382519b18bdf502aa95efcde8a4294031ddac4d3f792f5b2ee2e4f5492" . + "cf77836c452ed027f0344f3b2a9546a1e1a728f852a90f51b8d90863becdf6a5" . + "e9fcc719f0be5d0fb357e44fd7ba34573a8fd06203e4b3e8ecf22b1c0e57d00d" . + "9292ff92440c9752a77533e73370fb39b777fc660d0a9219d76107229189d9c4" . + "9239b664ffeb1baa4b9d6aaa864a470c616e6bd47696b92579f4a7906f858473" . + "b609dc3be5cae953c728a484a807a04a72340113dec4b273c6ac3788aa38910b" . + "a13fc388135bf0f94047da23a5a91fea579babb3a627b1a94abcf3c91a02d0d8" . + "44cf6b521f87a710cd993495258f1f0dab4d8af67b4204f5c3a9778cc8a0d46a" . + "0af0a8d3fbbf2e7bc3d07864cdccd2573c8ca17c7880c178b3bde3462c16ccf2" . + "d5cd19a787e581a0ec017aae8f217992d40c78549a67bc70ffe997e5eb26617f" . + "6c1ec948c4ff843663c9b131f62db47f23125177407319a3445b66194e740cb0" . + "868bd8c7fe068bfb0fdb72932831adde150ead45179b06b6b1b4ed5837b3f882" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "1fee4f02a743a4d119caa7969441c84b03e9cf11270bc7f3a81bac145fc4e6cb" . + "877c858927e2e667b4d92bb16c89be0520c8a5800d7c9f7e99ffffbb7ab8bca4" . + "1b4f0a3727ea357cdb8d88138ad3929b7aaf57f51e8331bc34d974209c418c98" . + "6394dec0fcbb026931c8d194155360393f97622918093c818c4af904d3912f0f" . + "cb99c151dd8dda2043d3cc2f40cf15fdb2e8d9a6581be6e2308c41738c72a03f" . + "d7208a04445b83006adeeec617e58a4da8176eb176f9fa4d46a3fc8496774679" . + "d4a0bd2df1b6f8bfc44c65cd95ceb37e5c9c95b50c2aab0dbef3ea4ad7c09465" . + "11b9a7c9bd2dd57ac3616fe4afb141878900d85944a117e5103b42a5abab42fd" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "14873ff309472538b22c8346c1cd72c59a175466021624f70dceab6c768ff031" . + "9b64e3960d4cc4b23e68e68c30b9a05f87f81e92761bb7af154026432e4f52de" . + "1f5466f8188372c3752d2a8289bedf7b61e81657cccdbf8caeccca2e49b188f1" . + "a3e35cf6411133196712c1b822810ce448e513c488b4fee2da25d67ff15e31b0" . + "d0aa34fb47f58e6d8bc27b18e5e0a0b6e2e8e1f3d38fe88e34551bc15ce3fbb4" . + "47badf7ac6437b46568544f335d311622c494ac436970d1d9ffa88427ca92073" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "88fe0a9601b3c9ec36c752bd6846923ed1a7e39fe80a4664402e210f66cb3ed1" . + "8d6c1396baf51b77618d60d0c610c0fbb4bbc324dd190a38d86eea93b81923c1" . + "e0611e9a785412e64d72be14d63ae7091845d4f3077cc4a606b111bd49b93151" . + "480d1394dedc7e33b74b8dfea9834a56953db08b460698c412c228b417e072b5" . + "dadab4aee25036dbf7471ec564268d87338ef4f0e33dc97b9eaf1a2659105098" . + . + "789b90921aa5894a6e5fdf3d2d2701f4e3f93c2efe73132b88600d24718d67b5" . + "311283edc18b29e1acf5a9b2daeca3fc4283e09dc5ac9261d8d0a338b8d52d33" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + "c67d1d947d63b8cd98852ecb9a455489916c52290c56e8602aebcaf007ba5503" . + "eff81797e68a96826523ed28920b5f6d918fd61fa9cb1a0a0822ac573309dc14" . + "4fcdd8ab780538ecec2edb636f163467fe6ce09cc9b27bec7057d99a040605c7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9775f956395d5439c4c432ef47c9df555e00cdfdfccea536d58ae7e0525fc28f" . + "9775f956395d5439c4c432ef47c9df555e00cdfdfccea536d58ae7e0525fc28f" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + "676314f75f4519d80462059ff7ca09a0c91586741a5326dfdc1d989cc115cab2" . + "6a1b6fed6d3636c1dbc4f09a17e8e9322543d5f609060b555bd6cd274e9b9cc7" . + "1a395e94ee1b968a53b8b98fa0a77e140b94e26721dd4a699f19a26ec17ecd13" . + "713c880ba4eed65767a71d74beccb758bed760a608bf74653dbffa6b3e60d41f" . + "31f0662068fc79fe6b1933e62c9d0aa8f010dfa0738964a2ad02b9eb463bb1c8" . + "65741d51a3915e4e9807d27d8d025941ce2ab036fd6804d39e7dc10021b0249a" . + "2cf2426ccb6b9746b17be5fda8feae381cf00165d5abcb63557cf8b196241eb5" . + "59393d39792d361ab6262e2b7e1ad1c42d856319af02ee9612819b49854dc2b6" . + "d518d24ec44485b9ad7c4cc42318681dff86805de5508ee9bcdb8284cf1ffd20" . + "dfaf495b233c6ff735f488093d262f95f3c15fdc675c9d786794fef4f06c5dc3" . + "54ce59069c14a4c7eeeb6dbb639c638c200eb233e20ed5e1393fba3f36a68fc9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "2aa8ec7d6e5ffca04b7a089dfdbe7eec5f6ba3106dcfd05bfe32be46b9e96b59" . + "686bb279e23a4778d5d46b781b2c6d7090fbb00e0c3946735aa75e1109ecdef4" . + "fa8b0f5df9e7af8bbb330d78ddef16ebbff20f5811b5eabdc1c1caaeae6c0e25" . + "cca52503fdbadc38da9c0fec7ebc7d4409a9c00277e17776ed2e9c622f0863bc" . + "7faa52790cca09dd044e77c0c25516db4a5afae1497a8cd3bf8cd7adfd4b186b" . + "0c036324e0fa7308ebc5ef27b31b223448ee1c7e7c56c3d5642a491f0999522e" . + "866eead21b39773018eb7f981bee50340f8fe0b14959b83ab6a37b93adc800f8" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "f99ddf6ba40a689e2565a963612c9d180761c71f382891e16f1ca7bdbed2833e" . + "4811306552526463bd880d25dc675c31b6dbaf029df9e62f14077fdae513c116" . + "f3ed393b90957f3a99a5adad03e83acfe9d5488fe046c3797517de46c53f3506" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + . + . + . + . + . + . + . + . + "523f8c21e29d2228cf9b68f08c2422b7d5f31aac3c9c671aa320eb428af6ca0e" . + "707cff4ccb4b3e6cdbe19a67c3080d5d150b7d39dedd63117abc42c39af5a209" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a710dd051334f11713b0f53b0ccf2163dee8488e70e565033a5381657031e841" . + "a710dd051334f11713b0f53b0ccf2163dee8488e70e565033a5381657031e841" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + "d6044109c18020567eb49dbe68f121d337686f429a765ce0ab0bd594c122c97e" . + "9c241c33357f0a5324b1c0616eb79a601995f2c06d38e9ae343ad6e626b5d6e9" . + "1a4a8842d5103046caf02f8661fe57a759d8fcf9fc564b547f0a5f0186be5e39" . + "dd5b6d595627396af9d5e0b7f689f047a9aa88d07b581b9cd9078c01b335cde7" . + "764bd0fced229396c882809c7029cec286786ef2a8a72a1543df680fa1c0edc9" . + "c422b7bb9704acb4637a8cde2b76c58d8efe24f8222e060fefee8df44bce59e3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "d5a640f608941ad2897824d9bffa5eebda7f40f1ddaff2c5ce8e2839cbf11e98" . + "924fc2eb2d6aac9838db1b14c1b553b66baa12409c1ddac4c51411912a14e0a5" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "9de00e82c7f4f7ffed864addea1b8c800053801db07db042231295498f320af7" . + "5ca1fafd32083d2399698487ae09bb456df095ee4a3fa5eba94e2fe8f09f1b11" . + "7fa2c3ce077335e7131d36d7379751dec5b07c4528e45b93ece62bbced2ab1cb" . + "ab499222d02d9fd3284033a489fe2044090ca1d3edc2ff5afdda22f8fe4be8dc" . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c675e832ca9c6b3a9f9004b8d00df6dd8b9e639a7f3cb6cf8f949d02b0258099" . + "bd1ebd26f1f081e7ef3d68bfa14378790af3f99de57da5b8645ab4696ed7ed26" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd2e0f0e6f8ecb6e4ce9af19a0c5bca61b8ca48ed590f8b27608e8725166efa5" . + "a1007f1387258a2ca4b04c621830e4dae253331865bb92b35c862d7d01180c7a" . + "00e7bca067476c46a4d45f0aad6f5778a30c77284568032edd656ac6e34f9de6" . + "5d8289ee9d9f11081ce79162b681200eb8209c7ce672b0b7b34e66ae9ec18e8b" . + "5bfed9cc711b9b163786217751f324e00cc5c242f6e6a332af14664eae7ad7a5" . + "4ffa9896bf1d92a329e776eadc4d5a168b9a2d01e8012d126c295859d7bc5816" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d882bcc57426b3a62ee4c1412c225c84bc0afbcb45654230b6be03a94d421ad6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "4e6516c2a3e0d6585e5a056652d25cbf2d71add34a311fb0d9335666c5d61e5a" . + "c3c6213b153869e9600cdf008eebb95e60ee51231dd1b786c390f071649e7486" . + "5ce9d32141357a113c154f9092bf134305e9640e824bbc56f8aa0aa67af23e29" . + "4f1852774f1625de6eb3360245cf263a66fa34b660e1245d3b4905e22ace1171" . + . + . + . + . + . + . + . + . + "b143283e6cc9a31272600c87e16dfff3f7ebc2504d78c685d1b6a65400cc511c" . + "85195f681f992dd085b2d098646b05bbdc259658e029b53605fe2b054248def8" . + "b88ebe2087399f871d40338743dd75695375198c00c4131baa155f3131bf9c05" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8c559598f5fd663ac7a8765da142c2642a8cf8ee4c697d5d8667113060c04fd7" . + "8c559598f5fd663ac7a8765da142c2642a8cf8ee4c697d5d8667113060c04fd7" . + "114e0757b0ad0d6bc324ba28bf4b55f64cd6f125d957255002c00927c479234d" . + "cd199358d9004b1e20c438389b561ebce3658134d248153595bf1c6b496fef56" . + "4ea709bd5774e3b09332d3dc1f561bd74af1035b571b9128866c4ea7f002d903" . + "3beba55a328b035f9d1f7fd3e695dd926f273d9b874361c814bc8b7bd20c98be" . + "68c64e0627576881e2aa679337bc2b208bf392f8824281c25471f2787aded575" . + "26638f19e3b4bd24ac0f57824aa34bcc771f663bc1288aa60bb34db1c6f7ccaa" . + "b069e4bf0c6d2feaf04f14122a4328d11ee2638822d8ebfa24ac06e6df5357b0" . + "6761cc6146a2047329f2f08426300aabc185cd14797f035d4012a4ec35b8a247" . + "57803335564d9b0c1267a4af4eda4452813a5cd117f48dd9f4db2688d7c0e4be" . + "5ab20d378d334bb5e1ae424947f4c91643099cb8ef78a1d2b0503080fb56efbd" . + "3adeef06c4e2c10bf06d07efd42504e6315341d2a5aca196be6d6c67be98b1f8" . + "549185931850b763df61a108ab22cf2c216746d67b71e0803c9f44fb7fdc71b9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "f9ac7385683b4f21dc21de6fb61504221c87ec6078f71179833c4fd4e2e9773d" . + "3cb649ff0affddd28f8712afac09b7f02ff8186baffcc598c259ab066d164462" . + "64f8f78508193d819043e3d4417f3ad782ac6f531113ec4b383b9b016c147079" . + "0f94ad6c63a736281571d8b35e518e3e4816e46e9a89238e2cf4152b1698425b" . + "90f195407df67511e6752629529aae62559965059e972cc8dc5f26a260dd1369" . + "8a1303616a9e78a78018bd0992378397bdac1991d523fb78a4cca58d646debbc" . + "6763a7ffe32777772cfe1bf92e6b6d220190589599a856ae416710a4455fc0c0" . + "80c09fe4ac0c47db8453f55cfbeb812a95dec376228b96a29c98b3965064a6f9" . + "aba47526df774094ce11efcf19d927017415e1e29b3ccd6cb23db8dc39975b64" . + "e5eaf50895ca1c9e857f1963ba2db6416a010c6767a3449db644cac195981b20" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "d19b99d7095deef96619e59fe7c7a7a02ebb562d9e9e86fa74c1e68e98627b13" . + "c14913d8c8ed5e5513e463e7a71b9c1673c6341a70fca8f3ce903f973d1d6a93" . + "9aa746b085295be78c8737f0fbc9be4f9282e7ab6a60d1461a1fc52937bfdda1" . + "c14261f606fc688af7d7eaa3a5839115d4a98487b82f2667bb685e7a5fd62cb4" . + . + "9f6a59dae00610099e570250e8ad4e8c250ed2c82a602dbb2711164db6f1714d" . + "ec30410c680b52958d0852fb23a464a64ece2b1bba2d16acfb602ef7cfbf5ed4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f55b7abed414f34c7f75073b67532158877c0023d89b5174464ff4353a952134" . + "c6231bc0282ddb40a89647c242669c99e35c89343d6837803ac38aceccaf7d02" . + "555d414fba57b827542dc434cb1eadb3a28009ba3de9dd3cc038f1f79442e516" . + "f09afd6e0265c0f6cfc108856f68fa5093dffe5f35ee0a7f9f706d5f7b7b78bc" . + "d1cfac81d35617787389a3ffb13dce1a1298c18a61788ddfea7e1ec636c997e4" . + . + . + . + "3dba2c17ab4b1bd161130da39c8e463b88eef4f8e76e311bc7b97cd7c83a69d6" . + "0cb06885d75f01f92308fc35fb1a7806c898375637bb21b5926ed26c5bf94ed3" . + "85432d6299d9995130dca41c152f13d742c474349999cf5df3b21c1f66080b72" . + "a25e51db1968e081f84c0d57c1e00ea9a76961339f60483ae89fb52bdc954b67" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "35ee6d3e7cbf86ab2e2942007822f125c1bd11a7b538a9d880aceacda4554493" . + "33a933aedaece32c6cc0898c7c09887fe2f7586182ab088021957877cdd41aae" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "f799f5239bc36c371c42ca1ebe47e7e56b590a5b1c3b86d988b3e971ac453d48" . + "cf2102f2817f4d85427cbf882de6786802d65d451318f9a1644305cb642041a4" . + "12778af8c8ccddd423e6aedf916b1f79eac87cba3cac76008ccacc38e6a00485" . + "b3f226147c4b9272043a35fc04e84b7bd3cf869815de1ec52041652474531ab9" . + "669cbe81ed356c134ce185e8eb3bd36b0875899f2de8811cb8500377a0e4a011" . + "51870301924dada24012c75d13a31334848c671aefb3fe9e92a9841f9d5f0eb9" . + "5abc7f9d21d96c152d6d4cde2b3113f43191b5b4bb289844321f6d46d6ba34ba" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a6096553d9aae9251296fe377f71e5b68e1b83481383233cc94117beb65009d2" . + "1ad3a23de7068e10b9a5656a1828074ba2c6616b8fb7ce9f0f213b7aaa8421ba" . + "bc341da4ab91514832f15049e7361c5d545b37e53496804868459f22a22d0e3a" . + "610942aadc7af8960faf5e9ab71cd33b51fe34dd91faf7b6edd7f00cb0ce5f81" . + "57619ea96fcd48126e12c2ab40f77c9d2da815a7385d4cb05b7ab6a9f334e7a5" . + "4ba1a5912d8176cd20715d390675f76524df2193348e2b9562f83fb0a4619042" . + "8f0d9537f73e8d7dcf7ca4776c8b179f8596cddf78a9b1fde53821a73e57a725" . + "c3bef86b12f5b5442e7d8c0170b34eb689a0ee61c845e007af98d14f719a5e4d" . + "c4991ba37975f59a51e8691064c2e32444b247e1fbbe5b7f71a91c6ec3124489" . + "1bd4f74b6fe9f9144d108b96716a34350fcbf4b66f07c9c64ce38f7a3ba22974" . + "82e731715851071e50c809c2cecb0f5fb4f8c3bfea0084982a40a5ec0054958b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "49aa1618c01b1f7a78552b6344e31d32a17c6552f9a0ca438c092c66257d7705" . + "45c848dd7c7e3e6c67715e0b071cab0b674eafdb0b680373108a7f5afffa1f4e" . + "b057796b6f9a745e28c43c5f300dfe1b7dea1565c1816cacbe3d8271ea7aaf70" . + "a399680f9cf5e5caa1f7d33d5761f34e5a55741fe4ee072cf7b6499233faf898" . + "478143a121eced5d573278e3318599f546e09cbd26b8130bf1bf4da91185f7ca" . + "dd9d117e696ede3fb714d962128090d4f7421d41e9339819805f918e245a74ba" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "036a9ffe0781495d9912edd1cd2b44a710ec10a43f0d7a1985934870f50390c5" . + "216c23670fc55d9b716baf1e672fe661b753837c4d171cc2593cee5188128cb8" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "33a606a6de394124e24fd1df21b58c90ca84921295edd24895c8520e37537741" . + "376876905504f61b1ec0c18c58eb8a7eb98e0de69e444ddc4b9c8b5c91185bf2" . + "944f7b3ae696c6c7285cf99701ab0ed406e92fb7333e3396159212c250c7cdac" . + "e23d08b8159da97320002e9ea2ceb13769d0a646a249fc2695a45ded8d7c7af9" . + "b7c1ccb5006c7aa09a8be98f15e35cd1039da812b04224194c60899958afc112" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "87af7919f066b624e03558c2aeedce094d3632a2903b435093152c62902d77f5" . + "0c8e81979a638b386cfc551f57e3b3a2fd1fb88e115e534d702e636b7401ceb5" . + "7d28bcec63a524022540858bfbeee104787d525dee9bfdd4e86427ae18e220ca" . + "2688edbf3d0e6d50949f244acc736613f7313b76fa0eb9fbea8026f0bfea86d9" . + "e2e985d5acee4db950b295eb5b21d175c479adf848122106a631f0f97dc1033c" . + "c0ff7dbefb656c6de3348d8ccc212c7aeb11e966a18431fe1c3419e86560ae43" . + "578f89c4364ca18d0507293096c5b79da22c1b541053ff16c26ea159f5e09317" . + "f8c12b914548ea9248c157fe2c228c81870f22f90d852f06864e7c7a3691a9ee" . + "9616aacae6f7524662bb1d1fe9b442fc373056dd2606ec6759cbdf7cb0529b16" . + "02623c0ffe26fbaf6e7a09d5daf1170af5a15e020aa2a9c938b7cd13eedf5a3e" . + "37c047f9e474c7ad54db0311d1017981418a30a0f275aa4869a07688ba6fdbfb" . + "b1cb6d15422ae4c4fbf0dcf1116e1a168fca492134d4cd2d2992e31b3579f77c" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d0faad75b3ad049fa9e1206b62fcdfe539e8e32ded128661299260f9aec50185" . + "891de1e7e6593a29bd12eac81ebaa538d1c4b85adcbc5121d9143920906155ec" . + "d1fb8750d9402a0f78ce57c510a046e775dcfba81e923c949bcada846b5b41bb" . + "f8e527a02c6293d47aa01660567106790770fe55d8721ad47d05e5883e6c9544" . + "71bc6e34f2cab22049b401160530add6c38d0209a8d0c6ce6e56975723e8e664" . + "c17b0a18fb80390d8d4297dfbf797c921b2ad87169134f562661dc9b36ebaad8" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "28a1a9511ffd71219672688ae7cd2850f0ca0e47abd0ceead31c00070d8460a3" . + "3456d7825ae16937cacd041f25d1d57c2db34a4adaaafd1d1dee173d8b7ec041" . + "e3bd280368f01880f9353ac90badcbab2541ef0f135abc260930f3a19c535295" . + "26dd68373914fc4b6b39dedfb3cc2b5a1e7ec2c6f342dc2c2f017e4687bb505e" . + "8b14e4f678991c35bce12ca41fe506d3387eba51f5c1c54f1a1390890266e4dc" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + . + . + "5452ae3213d92b4079c3a99b3eaefb1c5d0caf4ca10e0ab171dbad5a742ecb85" . + "b7f54dc289d68f36bbfd00179358a68c996803fa2c743a99badbe4e85735a459" . + "45bba3b3cabafa56fbd5c48dc0c93747075f43ba8886c14a4bf1bf72594b6f74" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "b77c979f83b81d182fd640b4e9d7ba02c7cb2aa231c9c5ce5ad99c5f2b4b7163" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "93197ce89ebcfdd656ec3ed470509bd924929f251ad0f4a0a45270088e88c6b8" . + "cc289fdd2ed9c828c5746fcd2f7529da563a3700b12916882b430c15a7d1eb27" . + "0b215f33a4782e72455c0400543392ebf159a708532ccdd5ee1861a481534eb8" . + "9c798d31d9d1aae5ab6933f3a010aff73ac5458461a09b7d59e46b7a896f19fa" . + "89154ba170779aea2a46fad1c0672b6edb583e84f38e7fb33241524c4afce7e5" . + "ae5b0dec900e1869e8163bf8dacdfa04b92c1583c11228596c4c946b16b9ff60" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0ef480b98ab413ad0d9a948cac69500ebf75fa6a91f6226d849c719fe609e38a" . + "0ef480b98ab413ad0d9a948cac69500ebf75fa6a91f6226d849c719fe609e38a" . + "12c0b80d6388aad8b5c24501d10abb4f837a87586fe4d84918630568fab17fbb" . + "b809990b02878e8e063aa701f888d0c8da51ee53736e68dd4e7abeec60a782ee" . + "011a9baf8dc995be97226564d1d69efd8eb547b5ae9f6a51f1591bf101a61c93" . + . + "9f79ff4ff36e75fbf52afa84bad8e52b1f04a5191cbf21d9fdbbb0642d51cd9f" . + "81e6b354599469f5a8f687111693677010cbb356f4b06a9692e8e7a1bb207094" . + "8b0fd381e11a2c33fb7418697f9e00689e4c496ec5acb37222bf2e17219824c8" . + "59b172f7ef3312bbc17c89a19107bd69a7df3df162a605e0d4fdadd99b2cd8b6" . + "aa8becfe58c7aa97a4ef7ba6eb4d88cccd77e06e34aa58d2a797c90669fb505d" . + "648e0e52a23ae02c2b08a10c13e04a68185131f660a3a44df12477ae28729bc1" . + "3ddcef84f7b43b9a62ea33332ddeb87e27153ec267d3f02e328b0f1813e72310" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "5dbb7c85c29905aebd3e76fd31a2e15b62818e813c133191fffb2107d26c6241" . + "e4402cdc8e7417072a8eabe9a3a662fa37814d7f540890ac3a0bba975a233ba7" . + "2906c48d29909b00cc91d5edbd3e0155e5fdae071783e3197f466470bb5c0e07" . + "9ed80e86f23ab364126c2c5046c58305fb01d84477514e9f96693d32717cef31" . + "39dc8a5897f8ae5764b1fa03b747821eadf474a203137a4b94c6d8f13a0090af" . + "e4ed7a81ecaf11df8727cc613dc083ecefe296ba429e7599f0a833952975d2f9" . + "d0de24787caf2d745918e6f7eb971f7f1861eea8e99e54424eceb2395d8155b6" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "01cfb7a4883da4d3fbd164b40533273ea11e8a5abcb1fa292b80ad5062cfa631" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "69bd0135ba751902941107f89fb222c7cfada87bc1712a19ca7958e120d86389" . + "a20d975791a2eb9d588f9eb38bcd78b164fa09d0feda645d7d2006615071ecb8" . + "d3006fcdb4654832d72ae96ba33e61cb97dfca6d7fcfcbb90ab9fec552bb966e" . + "d7dab32bbe2c2e6747f92f4497cd8fe07cb5b435d5cf415ee41ce9e92bb49240" . + "a303a335c1910f109db74a0ef9c0ad24c5839de9a28950d13eb92b6f9905d476" . + "e3dd534b3d0784057576226e0f0bc21c1a7893512f93152b162a607d32a1b408" . + "49d1473128511b295bce6ed2008149660c7d3c9ed43ea31efd3fbe590ab639aa" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b38ccca6f9f3a7e42b75bd6667148060680f01e77392f36cc444ce04b07f3e81" . + "daa0a86a570de88e12142d8d138f2aa71de3d1148fa750cdf2d58ef671122bb0" . + "2727540e83f753ed59b2d0b42280f6f972b8de17ce83fd6cb61e3ac3fc365cb7" . + "e10e24e3b6f239332c1b87ad447fbf1599d69b07d7238cab68102e2b3ba5f2fe" . + "305f4db869c81403232f2324f1ca1cc32555f3480ab43388bf45b2384c24996a" . + "568cee3cbd185d937409c3988f6a4a14e072560241a0054e5c6e64fdac98916a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d0a09db5a22cf36e8581a19f2342e3d96a4df9f794bec617d427b515f374fe85" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "ae7f526cf00a62986beffdb4ffd9c4d2e901d92fda83171d10b37178d3d49b10" . + "a8fbff08eb69a6426ffb4da801f00856645b3ac252666390ebd86c7eace0c619" . + "2d249b8d63d99595d9550ad4260ea53627391b3adb61ba788f71bff524397a5b" . + "36f55558d35208bd2732842681a7adf2702baacd2c68824d1e84c30ae153723b" . + "deb842f334e3258bc0d20666da684869db6dfa0d4664b09826baf58c367592d1" . + "c6978179d98cf48b9ab8e57a5b45043a835cfe9b3b397093820f47e9b1aac145" . + "2b872e5929f29aa7cc6ba9ec587e168f00a50cfe5fea5e7c01a4ecff849f6398" . + "3ced59e3237d96069e9f5d77b6f2260091b2fc2383cd202fde38841e9050269d" . + "b565631739a590122ba184343d7c07d93001d9f738bc68688d55897a4dc13e5a" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "3c16920d6f13ff646226419811c912a5211ef46680f555cf80fc443098153084" . + "01c0980b807256dbda5c964ea682f94536a6f349079b4c8e6661749f62da126c" . + "fc769566e2b2de22e44ffee91d2753f2fb6932efc44e5969a67e2dbec75b8884" . + "23de5a0a248402f8e5cce6b21162d84b40ee898393eae22b4025b55bc1dfaf46" . + "298eb15cfbf5f6c121c44b76a73ab1e6538bae7815dfca2bbfb50fae0f673f64" . + "8520c5435d97c9d1622f7f91fedb6da4175b613548a313f69707f68afe0a5ad4" . + "5accb99a9f515c4df03e7298039246a35e25de7e9a5a4460f9e122299656ad63" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "e4207c29cece3dd9c9f2c3f686a162256e0d72ed9a7ebf8502a9de6ee0bf821d" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "deb842f334e3258bc0d20666da684869db6dfa0d4664b09826baf58c367592d1" . + "6a98c6d2a714e999cebc433fcdb78aacf441a85628b4ae649dcd479c7db57e36" . + "4e1710bca88c3a77688675b9765b6d9441ac29c0c50fb6225cc80be4205d4052" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "e265ac36ef815689e05916980107dc29cd61fccc3fa34c690898e343dd23759c" . + "037bb32ac490ce0cf4a04eba61dbe7d51f67ea3eb5d5f1725b102aed486acc9d" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "06881661688be13b35e043d0cf869b01b044f985f738eba42443624d3d3aee5e" . + "ff51847efe242f77bd005b35e36218f0f1645f14790ffeb065c9908cbe8a3593" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "b6527d50c9563d09daa91f43db11f84a2e2829c45e88dff231b8159935c4d0c4" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + . + . + . + . + . + . + . + . + "975d7dbe836b61d6ab4743c98af3a363572b66d28205565a0fa9fb649e54c138" . + "e17fa617150ab99b20837ef7a0c7cc00200875082ad8c3266fb78475f41cb1de" . + "265421e7900a93e4cab9ddfd6f135ed452805ab6e726e71f38579ec60128e70a" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "b5cc84a32d5895a7511ebd8d044b0ec8050f411a846a810526d871fcb1917bf7" . + "1957dec81769d3b7830149a17e270b09ccc21235d019581a131b5cfcd0fea882" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "c153a6d75cf4c17ddf1b0793d75f9b2cdf7b21b8cec389c4789740d8f5ccb984" . + "8f23d4b20880d891da617faa5df7c7a190568b2bef2b8acac813bbfa3d5f8a94" . + "1d29744562592179db558db58f6261a59e7f4e004100e34d0300ecf188d36017" . + "e2db02bbab2fb07af33462db21b34eeb874ac050287231ce151ef82040154412" . + . + . + . + "229c3d8350fc1ab15b56451903e9f48b9621086785e8bd6ae3736d196d26eec1" . + "57942d23e6ac24d8e6127c0ffd6914186849cb85cac85cd70cbaaa2525803b03" . + "dce331dfc9dd9336cc446858163f67752b68083623ae6ea569d4f59c1f84e539" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0fb209ea9f06ae5bc30e017c44a607d4790bcc890867053e022f83bf122e95b6" . + "984f38ccf89b77449ff816a4597434aca7d8aed7a108f310ea0747e42e0cb492" . + "d596f93727d6faab5f51a4021764c726bb57ec0b6b9b52508ad3cd056b4d0167" . + "c918d8d503b629f4dbf3a789f6f575a552dec9e8f780971ef63938b0fdb05522" . + "ef005cd184c81a49c0854d721c6e4c67a824dda113ce74c774523831f4c352c6" . + . + . + "7d4323f751b684470055392c524ed684139adc6a314c1c8c3e5aa45d7682b184" . + "80f2d782218b339cfc0763d41f45def3be0bcbbd1f65ebc6372e74eae9a5d498" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + . + "cd35a2a6710445b8ee339f21c3c78f35ece3b4b6298cf496f018e79a80a24653" . + "768c79fb1762bc86ce29e446ef358e78c35cd3d9b96773a92f62e54c289ad505" . + "3b6f6d260da4ad3ebc2f1de7cd2307d614375dae599e754fed26c2b1a5e48fe3" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "63f2991e00d1bf6543861a237a49cc6d75d1301009abba77a41ac6795e72822d" . + "a100ebec462afafb47be4078fc8a3009916a6fe2e2e8d760f69e4ce8a7d1e34a" . + "86f304ab84c71f7222dbaa2b079d0092a11ea4632a9577cdfa9d40f971d89e3f" . + "c57df9353ccc173419338e2dc2fb5541b4310b0b55bdea5b824b6b38657fa48f" . + "93cfcc837e4530cf5e11ce2a6ce58c34541e5809f21898623347e58d34d2fa2d" . + . + "22bd5144f088da8991c255674e3ebef0210c3e34d945c34cafa582d418c334a7" . + "680043ed1e1f19b97368277fdaa801bda01ca076ae38546deb25c4b10ee854f7" . + "1e15ea8baa86e85627790a9e0431f3d8b110a7e7415ea30d662bab7283209744" . + "d412d48853acd781a413fcf308f248b4fe3dfcadc11a54e72b9138a67c867c4d" . + "67f5d69a336a577e2425e0a6654fdc82dbd425e7b3c727bf97ef435e589b2856" . + "48e682bc2b4339423c57e6c48f465c586f2c33408a668c56aa3e5ad8704d7095" . + "63446ef864df7e94cd8b04dc8cb8e7d6b84689f6d3c5ab3d5a40cf417295a940" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9c4a03cde41213bfcb1890248b475936e1cafb4439af91b9e1ede85cfcf20628" . + "e6c7fbf2a01efd1ea536f45b590be3a5ac1a4b80c2c6eb147a0d18164537fb51" . + "f9043217dba0bb0dfc2e175df3a091ebdd4143fd22c5ebe9b11af1d687e64d2b" . + "83ceae5bfbfa4cf1be8c8b0ee1ddbf38a4d916f47bee96ed434f4c2b4323c506" . + "ae3313a8d09129863dedd205924d2d8f31a2d1b0b9c42493228742637247fc6d" . + . + "49822b5755689404a91fb4b7b22d18cfa77b5afacccb2ce5c4af57adc54b3ca3" . + "1f3070428100817a640dec63c13d424c78ae31e367a7d6230140e284ce576040" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + . + . + "f02fc0d37969ddb928e06924bd3ce275bebb9a87e03e67180a603008152b0503" . + "12c28c4aa28b4e1d0544402a8f52e61fbaa54129cd32a9a14cb8fdccc9f065bf" . + "0907e66e31d5b1daa1274a0f8c77c956af19d948796d321708f85a50e4ff406b" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "6a96b3f957974e5aeba09022d62aa62f86ff8be2ec6919a2c148ecf049bc0822" . + "6a96b3f957974e5aeba09022d62aa62f86ff8be2ec6919a2c148ecf049bc0822" . + "78086e86ee14abb36d43f0e5a5eb00babdefdba1ba624bca97e776e4f23dcc84" . + "bd997daa13c2034e17d75231115b252d0224d91d97b3286610c1cecf9f00af5a" . + "2040c7509d4000f8df31e35e7faffd3f7e858c490b1b8d076dadd9d29dd04c11" . + . + "7d571b282931b0dc9199818aa4a9e83bcc6f2df722440d398a12664ea74684f7" . + "3e8f7438f252665133005ec629d9b2602decc2fe5750ccd669dd058ff49fe0f4" . + "c27916a4480790a0de7c09b4eb0623d67c82538118c4af2e2db004cfae2b4dc7" . + "35aaaaa61250fd310204b27a0d526073cc80260f7c2a58293aa24757188a7b56" . + . + "7d571b282931b0dc9199818aa4a9e83bcc6f2df722440d398a12664ea74684f7" . + "3b1990670b6ea15b47de6614c145d66873e4b03648c31e6b076e8954512c03f1" . + "d323fc1f4eae7e384f1b45ce3061970e7a4e5a6900570428d632a0f17a984223" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "021dcfef17915392f0f87c9cb0ed97b1ad8628e4bd7c0bebe2e28724f65acbd5" . + "9a7f721bad02d13a961b77c6b088490278bcaad8d31e0c723f910832b7d93885" . + "911868bc31ac937d22b5662f58421fba885af301c75e79b98745f576c6b38784" . + "200a1c4b232c5fe45939c5cd2e3c7043e6b5d1897e37993f27737a6aedde65b1" . + "2d557ecba90a7a8f3ab61d15a03632abb82d186de55cb187f08c31b70c6633c8" . + . + "936eb2fee865e1d72f327216e2682d3a3b245178de7cebc98b0f543b6c3a4b60" . + "c66f03d9ba55251f06f9db9db3929f052f4fdafb107fbd3dfd95fcc42b123dad" . + "f8eb9fcfd8b9b0e62026120c375171c5d6097d0a138e516b82f171d161c02899" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + . + "7a695c6dd0b968b0e79873e30a1da06a01e1d9cd10760b138e4a3fef459b1d76" . + "e21937ae53c16c631480a41ece34ab3e68f2b6ab6852eb9770206a2ed41ef81b" . + "3202407b3cb7b8a67ecb79a891f47fa6940588c7fa7475ff15c3e2387d760f12" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bf5abac24a9810c9eb0f7e40d29ac958a3f39689fbf593405df974cb8b61c2e7" . + "add95ef8acf05c64239b997ced90d53680e9e4b3d07875178da2378c0b170675" . + . + "f6d13399aa7afc66e6659b213f0d00d79b412042601b89368f01d753364bc6a3" . + "54d051f9135f446efa2602167cf78f1438e0a94a94d1283be6f460001e04d1e2" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "f7e50435eb24a81089a895b86f252d306ba94338d42b8f88369d3bc04a92f879" . + "f0d447bcf59d6836cc7b010b058ae78d9809afdf296d7c7ecb7ab310d907eaff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4b8dfafbaf160d717caf63b9f138bbedba429b47b6cbf8674e9b1a539b50fedd" . + "cf70ba30a85b0109f9f149ef88e1a19bf0bdb6852ad2bbc8ee5f3cc81026fa00" . + "a9630fb437046faf1d2c807693fc8cedf68dc65f8bf14936451b4e6007df7c9c" . + "2914f01481bcf445c7f19021a0c214b52022bc5684bee8f5755543e26e1753fa" . + "9e8146e66fc205dce4ee5def4177a6708f85999ee59d0bcb13f2f4be5a1406ac" . + . + "871baf37888e2af5f041b5b671ca3ef31221a19d99d4e30b09f6062847a475f8" . + "5dc6f377b64eac2626b742ee1cd83978e0925147281dc92b9db1998a3be352a8" . + "45f84e810335b4d369e564d10738eeebf8fa66618dd273a27b79120ed855d566" . + "de393b3f21f4713df683dbf9fff738d1f841409a033811253d93f310f227718a" . + "7255dd0bc107e1c682c620b6e7b87db0cbda79060136c28907853ab12a2f7e0a" . + "52d0ada5c75d3a6c9ceb81a26efab7c0179d147643a7b5bd5b14664cae44bb38" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "967b19ffc262bed74d0b23e8735d730f987b2c460bd2833c8e1fa25d97ac90fc" . + "86efbe30570c079555a97e6f15d844a68d1af8cbb48eab756beeb2f79f372321" . + "a1367698e0bbebd4da55c5ebc65421ff183b41d7d667c5976dc27093eadc5c60" . + "ed49cfa002412f1d69fc70f0910eee81fc821e1a8647e9a72e4591a7bb8dc9dd" . + "96de73a3ae9b05a73493fe79323747989121f90e94411222c8bac9f9c331777f" . + . + "edd63bce528210f3afdbb9594d7f26b9e57e372d30277c6c2f279409c75cd60b" . + "0bc24ecf32007e6df69135d5aafdb8cd3c4398c51f01cae29395fd8d139601d0" . + "9ea03b14983f054a1033742415b25dbc69d7ae889ac55a5e7007775373432303" . + "9225a23aa6be80c622adec59849614f2a13ae85327d3b17a260e52a14b012e0e" . + "5674b248c961157a9d81697f3f0b0f1033c3058498bec748fad15392c7ee9b41" . + "b835dfa8ee967bf93b76fcd33e1466418b3e6554b7ed0308e3e952fac3e923c7" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "314598b5023f725f2752dfdedc3c9699edf1c58a9571930a25d670335eb95ad6" . + "4bc2e88736cd293dc1f1c44feff9c783e8d58a7c301c4d97fb02451ac4caafcd" . + "a276799340a668192042c718f6cd3cb0169b5026da188d77f417eed00c442368" . + "ceaacf951f0727785b6a963677589fecdc92e4234613b27fbc6d3b287e00bbbe" . + "d20dd1eb71a6b06a829c04f1859e3ee13f44e04502903e789a4c94cb60d41410" . + . + "bd54a32962a796f622c9f35c7635f78b72930190f8728a0569cae851ba3988fc" . + "b12576f3c6966cd21fb6da2b43d992c6c1cfbba4eaca1f86a6e857081a65800f" . + "d8ff900de629f800e9a69e4e25612449c8bc93edcaee5847ad97fd539a90c083" . + "5ef52b542c45fc42def656e7b8f24a702b7f5e849655d766bda26a95fc39eefd" . + "5888396fb6bfcaa39a22ef7791d5ac79806a792ac42447cc3e5034f817241d87" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "b66063e61c82311a70c5c4969651714156cbd3b8eec657b96787a9b0152e476c" . + "b66063e61c82311a70c5c4969651714156cbd3b8eec657b96787a9b0152e476c" . + "9cf0732ab8990ccbc27e9cef1c64ef24d211e3f915a213bbf743beca3947669f" . + "414541643f34b23497bcb6620f5412bfc2d21473b95e74c1d17cb5d6793da9ce" . + "8e9afd87bc70136ddb463ffea46d3ddf2c1eee8188447a0fcd582d66d70070f6" . + . + "48ef2cec7f38ac952481f72fd7949cb16b4ce43a3cb9f77af8be829705043548" . + "4ff14d319414309107aeb362d7c8a846f016eb60660c86eef1407748c4de9f16" . + "1ddeee3902f210cc2a2aafa798e473df3134799e3e7486247f0a271fc8677c51" . + "6a0db4931c34a3c0b8c6c33c29c10c1c312da7e62041d974442ab851f372bd21" . + "870f6200167b6e0fe077ccde04e26b2b0501bff6155b4b04fe4c9d794cbd4264" . + "57e32cf4bc00e670d6787ac23a90d326b45354de5856679133e8c3773d5ae636" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "97a2d41d4927de7cb7b21ffcdcf7f5e7b5c35f196cf6dabef77d72a698d222e9" . + "93b4f971604ca682915940cfa351b8a425dc20b23147f500d1a2bbd9ca19be02" . + "ab56be07fd69a9c0399370eabdf8f01a7b361b7d6194c9b51b3f70ac7f649245" . + "684ed78289c2f2bae00ee28014fa91184365bca2a5d19725a64939dceba9dd15" . + "8802e8d2eef7116399792b48dbf1ddf1211f1d4ff77183c12a25a1b47bc03198" . + . + "e71bc845abb704a7173e34fb0dc98b8fe214985fb2c323e65814636c567585f0" . + "b96d127fb17c5a5bdfee7129de170ab0ae80ac7f877e05870558b0332bbba3f7" . + "5cf40774b4dd5aa34c8e1f8e908e53a9d279dbf7c1ea28367604393788aaa061" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "193072aea64723384115d309bf65c9130ca9141981bbbe7bf820f68a23a13939" . + "d2cf789697fc3c3ad75e4b64a7ec0040ad5d1bfed482b224d5d7892231978ea3" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "faa30e598bc7e55436f12af9f4f6643a5507b6ab59a3b94bbc75784c63ef103f" . + "faa30e598bc7e55436f12af9f4f6643a5507b6ab59a3b94bbc75784c63ef103f" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "6101d7ba11819e12e16fd0d15886660ff4a89f495529a0a59e444b22c09894bf" . + "fb4d0e681be09da52255fc66b46560ff87bbe74bb185e6b4835407d4c5ec888e" . + . + "17ce58faeaa0a912a62f0896be02a2e73c0c0f17b1afcae062a2c287d9cf40d1" . + "c3c0e7c7b76eabcbaacb1e80547da546b7800c3c8bf97327a0372dc3569c94e5" . + "f10f7d1aa7a2dda172df3d36dea925016db9e6edfb3b7d85507a87ae52d57603" . + "941137395400c03450cf0681d431b1e644947fbfc672b95051d44772ab3ff546" . + "17ce58faeaa0a912a62f0896be02a2e73c0c0f17b1afcae062a2c287d9cf40d1" . + "19dc02d1a2cc1704ad61b49980ed502b00b58cde405b671c398f4bd5cada2fae" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3be34957cc408884b932955785990699d3c65ff762aac88d5214966351ce4e66" . + "a1d9f139b0c057b4019360f31816d989caac06428722ce028ea386972e6c84f7" . + "f59c1c4dd7861c0597dc966f21f3307d5e443700fef780b735c2acaf766b6bdf" . + "1bdac0ab674ece2eab76fd859d9204d648d5941035be7e9c4bb831a41aee0aed" . + "f50626d31b187569178ee45c2c6a197373d41c948330865cb63e836c08c5e37b" . + . + "476ffbc6483093fe20cfc603709cfa2ba90367ee73f7035932b21a464c84dc7e" . + "6d5065598c5389e27d0bcf61e77ef9e0fb78c4dbf0fbeae95c5dd76f7bd4b812" . + "e899aefa2530ea16ad7fa755e0d7a2cab56b188e1ed54aed9b5ccc9788e5a8df" . + "9dea4ced73fb4ab115f651ec019874204876c45c5934a34447c6d60f96da668e" . + "6ae68936f5f9b8690d8eec8e297696b7a8b51c745124aad2d4901b8df0d23514" . + "bbfd917283ea2d2f7036c49264e506b2a4cc9fb91a7e732a468f86d7e2de461a" . + "03d991442d36c8970dd4fc3e26a9eb8fa07ebcaa8909be7944c61e53694a6235" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "af5fb30ba644a66789115acedf4ae2ebf65e0d0bc3da2270248801d3401b7291" . + "cf73ea4095067d573a726d37272b1fcd8a52c258babca2fc38e31d234cb34b4b" . + "400defb65edf7f5b569f8e54081b624e227401a15740def16c8ec43225b221ae" . + "d840cac2766786e1c1c7c68b7ef77cead1e8be80a58b14ad64134ba6e7c49f4d" . + "482075b38fee03da1d6b14d9d8f6709e8392c8b39213335f0d8092edfa896f13" . + . + "162979e0730bfb1bd9a67b0c88719db59bb566dd77734c6150bc8d89af3e3dfd" . + "321f13c610532afd2d9555b3a05deca9e7204803ca3c059bbb3dc9c531fa6c5e" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "7a4161493cbe1f9f9c7fab1c8a21efc0f1a6f6730382c0a253019e4b7b03a8dd" . + "4d9cb668bbffbf103ebe127265d54612e76e5d6faf20a6fcd3301563946725c7" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "906f0ae6240f004229da6f4c886f19021ed4e998c587471aaa555ac7f4b0c76a" . + "fd2fcd9d5b062ecc1156a0b4dc1de32a8a018f84ccc5c0cbab8a6eb5c978abeb" . + "c1122f24eaf74ddfbdc24eedc472598136629882d1bb5a211d702b67fea15e72" . + "bd8681404bfbde98d16b3605e11097738a36296539c9450449eb98704b53e698" . + "0b151ecc0dc9534895aff22ccf3c7b319f8c7eb219016c705906044e878547fe" . + . + "b9a7781849f42f3b32ff6fafc936bb5dc277b8504bce040081ad2a5429369177" . + "95ade005147a533d72024a43b2e493cc6a7d7b7f7744144f7bb1848f562ff825" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "9cf2aa62235885c1016aa11d160267ce812a1579a973d10f793141db0dc180fb" . + "076ae414961c48c434874e58d234a0e88393f725117aab84d4309a243eb732fa" . + "962280e0993f8c047b523546a19d36223954fb94b1f4281cab3d538ad792607e" . + "00ced3653912436ccd56f65e76b1a49d9a6b7668af8b98fcead8745491194aa4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d5257b9cdc1c50161a6a9500582fd68799ab5d435ac0b99156a927de10fad581" . + "e5704d31a2ae1771696b93156a829b0b6cd09c59cce451aedb276e912ab77f4a" . + "5013e0453185a74d4246fcbe366b5535b190da2f9cbe5dae51e54a5bf0955f30" . + "cd1510720ae0a1bbddafbe2160ac3e9d49be88610bdb553295ed656635eba4b7" . + "42e53a9e5e4f3a6e5d09037d44c76c6af5cab078f82ee66b4c6b5dcbfa6c3d22" . + . + "da886f774ab221d123c931692ead5332e13f80e15197a122def0b261d61e49fd" . + "dce18afe92d98d4c4412c345fd37c15690708589ae1da21dba95a954ab6d7251" . + "3a939550f45494d0cdf88dcd8618787dd67b523bb0eb705ca6b52a3a8b6aa2f4" . + "d6b2a262748cb4bc88707ec78e94e853fc85b341af781b9636edb5c85bf41cc6" . + "81abadaaa2ba9570b8b114f53a14fb72fcc2eb6d78a4d2643c57a4adab896e1a" . + "fb232fa581fb011940110ddd2bd60273fd8f6b443237f3ead9b48979cf4cbea1" . + "d6a07f2240b9d4f42560cea6ad2960bd8bb613cd6a59d7fd4f3bc22a3cd79c27" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "923d2263f68800a8132c159b67d98b1a90273b793f022db730f65df21d2ec384" . + "28528f845a14012051fb18a0d93c9caebbb160d16f2414047e3d349adeb20302" . + "e59c841c57bfe863aa8e258f54c3741596a944b0b8fd79f42ff344c41cac68ef" . + "f5573aa2221f06bd107fff9a51ddc5a4d49e67b0cde1949ee55c9ca57dceb022" . + "17620322d00dc24ed5ed53633ee60417cc5af7e3a20e294e1269d749e69e50bf" . + . + "13e88a0e633bde07ecb4bc02e628e2588173506a1f0ef69ce2a8a97490cc2fe7" . + "407f0b012d9937fdf71b6d971698a6d4005d36d1124138617b95e834a0e72894" . + "f3ed393b90957f3a99a5adad03e83acfe9d5488fe046c3797517de46c53f3506" . + "87802c00d609da89baef2ed2eb7e674096940aa32d04114839a2f95dc9b2d134" . + "3bd0bed63f6b171d15ba3cfdc537aff4e4b9e691ff675e28df28ee6f17dc7648" . + "f0ebe958fbf355345228720030d8075dbca0c274892aca99b4502587771048d3" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "5b6ec5aa5a256d7006663d9027ff395c187c4d779704771fbee7cd4b115a2415" . + "981f40feea032a411c1097bc662d1fc638a78e067afbb0f3d276f1b7ff6e3df2" . + "14bc50d1e7a421ee875e8ef5d0ed2b05ef5bd082674c29425dcdca05af510a29" . + "5b834c41decf1da5ef94c4959eeb48244dd0e240d4d48615541e6d6f21a1d11f" . + "c01f6d4da074881200e762e66777aca3606ce47b284f45e830a61280a7388d34" . + . + "1d269eda6e3b745836f330c3c894b9645348367075635d7b0f275d0d9b9a91f1" . + "76158647d788743a06486883393626bede9f0ea333053d894733de2afc502ebc" . + "fbf019a58589ed0642c314291bbbf4555274cbe810d80f1665c3b4b6d7a6b9c3" . + "214965bca2c51dbe2ac9dd53f90e6dff816bd9db379795cd37e2f63a69965b11" . + . + "81f1d1e66d9e6f50232d2d2c8890fbe500c6defadf17a449fa4d0609b22f3a39" . + "a48e0c6f648b6aee6490290c397cd0839f8a4308a436e2b3a1457c9fb9ab19f3" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bfd4ab98217e2643d8e2c921178a0d29691e2f0c84842e00f83d04dd177a5494" . + "c18566a49f7b352571f9d431de79e79e094f3da1f288b52544487496aed1e268" . + "58803709bd4287711223e4a3e432f9f897abc0d7c4546ba78dec8d7131b58ed1" . + "b7a14e3a116336f9f6d7793f28f43895ba9232617a475a36060ef3055c1f762e" . + "71b48bbe780c6dbcb20ffe9660704952cc7bd5c31b858ffc9eac1d5b97b84acb" . + . + "622f83c9dd3194f43af2d3f90bacfa7730329f83592d0f0a370ebdf1d685e85f" . + "87841e54977b317dc6dfa675b2ed3cc02705f56b31699a95923a1e7c508299d2" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "19f6be1b8c687319ae49c326bffa1d2dfa866fe3092a84674cb5847f34f72b7e" . + "f9e96f9a84c9a30dd0ba90a6307bc46d6ace69ba3193f05ee26c91c894708bf8" . + "52008747429936dad05f12a4dd422d1a7c3e5aa3e2b780d3abc8028f29c942cf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e8306f55561ca38930394b106392a30aeb7a140a8664a8658e4723e18963421c" . + "e8306f55561ca38930394b106392a30aeb7a140a8664a8658e4723e18963421c" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "f8478c29af3f146144d0c5ef4a205d16072b06adb668a9fbf9ff178949eea0a8" . + "12d585110bc0eb6fec5a3e4cb5d703df19c55b50845f7a51dc7df069af3a4937" . + . + "25d5e0cd9e26f47edeb80268cc4c7ad222ed5752e7ce9e7f924820675ece393b" . + "910bb4c828514cf7f3f5b86f3168d5319d54e978b89a033fa1871ad6cf2d3b4d" . + "106274d5389310b9a7b0476fa586b59ee509f722bcd62147dc182bb528f1c0fd" . + "3293d3efbc5496c50f6c409d988b05e371c99166fe64d7531f414225e4d501fe" . + "2558534ab95be1241310ae37b1da4963820f9edd8b96d91ed864b9eca8ef4950" . + "103b3290872b59bffc59a1422c4e9d45b25f1c418161ee3bfd18d2d631f07160" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "632dad731276a64a815ff63528e4d3e789e8b8097ff9fcd6d830c9e20fac4fc3" . + "95605c5e1baf97ffd2bc096a6583055d39ecacc5abe3e7e794b8bf8d092f9a54" . + "7128e5210743b092cb7c0446bfd8f7ceea9b1859f5698437a8ef7bee5595d473" . + "d85c75c564768fb6ca97abb72b9436ca8a9d04123bbcbab3f4ccd5fafbe160e1" . + "339525b55d4c4bd2306360ae83e143da738660b97c7cd4ce3c6b117df129488a" . + . + "f5f44f167ffd85569547288b95f34341b326d96e7a3e5d80ae91700bcc8dd09c" . + "37447415c1a770c6984e04ea4c47c4effebba03e786c558dd657e5f58240125a" . + "73db25f8182b6928d00f0b1fac882c8d4bb3c81e35afb4c751bdd10d264e3043" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "6e290a8c689267a1721665722943a51ce791f04a4f37fc58ddc0b6080ad7d1ef" . + "0724423fe626b43972a305549e6744d13f1937f9a1e2ea0e2b915a38a0e39b6e" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8ba231767b9a57a6588323ba1c83c2448d25c4b2f673626575a0bce68baced98" . + "f0ffb4239059ce79e2dc25e58d0de3069e373f72928a7e02284ee716fb1850dc" . + "6c03987a8b35e51edcf449b7d1b7408e998f7acd9041298192850b0865090c38" . + "7b24ccc3141b0aa794969040a2c9418d0e938c289eeb015735f171f712dd4713" . + "05a8359a76b7b2b2b1e8c8085b22ae44ac1405952d73ae82615e46da632a4b32" . + . + "db9a8b32235777516f52a5fa6e3dad24dd07434da4f551365bd05ed4cf764692" . + "bc270c52660932a364befa4d74940b2b833a066cdd0970bcd8946181a02c8c4c" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "0b57cd77279c5da2078eaee7f576bbb8a64c69811b6fdf8e92ac99b84837f5cc" . + "1e5662393bb89d72d436a3f84e37192964c1aa353544a5554b694bc782e4464f" . + "af76f797d68c12c50bd5bc32e3ed486f638808e09a30d2a1cb74388f3052e60c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4744e727be4aa9257b019c44e034b208cc74e4bea57727ab03b2df43cbc4dcb3" . + "4744e727be4aa9257b019c44e034b208cc74e4bea57727ab03b2df43cbc4dcb3" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "848e3498d07db569617eae75ee574a7c325a1cfa6c6bce31e6e6c1293d75fa15" . + "15665cfd36da0c4c8cb140b068836885a01a27e7cdaa40265e11fd9986e212af" . + . + "d25711ca6480868f611fb0de44ca388e043986b10848fccb235a3b60557ea9a8" . + "426c9c564ad07edc6e71042fe825f34fd6f1979a34d5d5e06bdb89eedaf46df9" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "d895bebb04cd012d596c7f3571078a6369833d4624c048c61f30a7967033f730" . + . + "b19ad13a1996dc71420eb140e363f43e7c58773346e174473b24fe887be737d7" . + "ce0187d072283db5839bdbc4686eccedd8c7db20be2fd06d6b35bcde7872d2b8" . + "bc94fde1aab26dad9a0b73199800095bbcd43741dd354be171fad5df9510a466" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "90ea7304c39b75b6c15184a987bf211eb4b80f7b2d3615a2fdeeca0f938af885" . + "90ea7304c39b75b6c15184a987bf211eb4b80f7b2d3615a2fdeeca0f938af885" . + "bd38c95324568abbcfbb7b82e20b704f4aff967fc3f7501099e2d39dc32ee607" . + "ff33f3f91b208ab803c315650323f536ad4a56e0a3bdd6d98dfb6d87e74f34ea" . + "de12eb9b06393b56fa1c6dd428dd9d02de2fa700384aff3b0ca58523eb09a57e" . + . + "792c4fe419817ebd107511ab7e41b4473131bce7c4344c7ac9ef5366f4b64720" . + "9b05af8586c65e446ac7adb5692aa64900dd3c7079aec4bf0afcc54966a90e9b" . + "72c462c4a8d6f2f331d6f10ecca9b46bf300635fb461521ec33b0c7671d77a1b" . + "3602bbd67c989c61d2be7a7199244ce0c11eeff25eefade0eaa1b630e6f554d8" . + "d51fdc2e7afef0a2d51419b184d92bbe4448b5c689146886a1e84f4dee54a786" . + "9bfe2d82a9b534ad1f8608fafd06288099fc248f4c72276cc82099be1b204857" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "62c97a4764e6540061cf96616d8d51a65b56a2598aebfdb1c918804a2a3f8903" . + "c735fd850b5fd9067c5f7dd78f5cce67990e57abcaa4d6f1a3ab836533439da7" . + "07ecbe2be18872599fc6b8ba36648ca8837c011e610fefac91ef6502a4ad4cf4" . + "3b1c713f3ee297187b4c2c0b5695ce68c8c8a9074456b91ab2b23443f9e5f1cb" . + "6bdcd5e8f3409952e919982bf2fd88b75e46b10f32db703fa83552b4d60ebc60" . + . + "f5a3b92a48683436bdc2a738ae472fab92b7eef7b20edbf9918ee4ee04b312d8" . + "4459fb7609c8b016e80d2e852c6bb5b48a8996906a3bd818d5b804c098e854e7" . + "ba8f11118438bcf612af3ad41f925365a633ce1d9713bdf1dbbc760d3e3d2c72" . + "a99fbf614ee9ae3f84814d6255ba4da3c327acee31cdbe64ae3626fe16f1623d" . + "9ba0bad05dcfa9dfb9a7a8b215f455709963b0667f9c2ebaebc295e828561e1a" . + "d44acabf6834c3ace63ac7ec776f17582f77b0ac6e205b7968dacbcd870ee7ce" . + "fabe89210e43b545728f12c38cfc927efe24790fefe1522ccd352a6b16efb4eb" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "46e0738cc5a9a8c0cc49d043ab5a131e7ac4502eeb0cc9df1bf9b9580bf54cbb" . + "46e0738cc5a9a8c0cc49d043ab5a131e7ac4502eeb0cc9df1bf9b9580bf54cbb" . + "85955bb27eb52947d1de5a00d6c7f3a3418cfd646851ea6308a3c86ae4001b54" . + "48e4a01b73befbd53ebff5fcc94e32f0c28e3471c0b2386853df830f16deec88" . + "96c6fe95ddc0015ed6c4036efc1dfde1b9ea507987a43b29fae13a1ffafc5bdb" . + . + "6c1b9dee055555cfb9ba22c5cec1e57a8c6e935c430d0e72d77dd2800a3428dc" . + "d1cec85619fc2965ed087f7a262381d49b372d8a7d20eea2173db53d09c0841a" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "e03fcdbd1bb0d88259693d516389bb24a16d104f654f7cbea22ba997d3d9def8" . + "7c61ffb48310079444f5a3afc7c7614e00968cbb95e5066bf79f9c113af1168d" . + "e242a81171e51bd722e024e52e74a6ba695327064d6531f31d66a3473cd52767" . + "b8c3e5de9ae1f3bb7a8be5ff9e9e4b45c26b68e58fbeffb7d0d2129f0710fa78" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "eb85daa3e856931972d926d3521e421ba3193953b8ac51bdf21b2952b3c32414" . + "eb85daa3e856931972d926d3521e421ba3193953b8ac51bdf21b2952b3c32414" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "dc1a3a2293b8067fea8e17d1799d063857f0dfa05be97e60f49634b0cf314190" . + "f0f2f032139bc711c31f9f1adffc703a3e40f40224ec0ff1ff6b5b2b5560c077" . + . + "77e26d7ce8c64b81424f9e96448af6f35cf9f7ff46d3b3cda147aa2d07f0dd4a" . + "fa692f17ef0de1fda572e3c12756e21c5704aeb7080c2281721ca48c68de22b2" . + "ea86f60ef63a3a8a52fa92109bd46e26c3531593f9fc378d389e981cd84b5528" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "e17a0caaf67c8c7318947404fff2ef9edb9e84d29472bdc7b6b18cdda8dc523a" . + "67837f84e8086ff9a72c864f7a6dc9faf5e9f3d070fcbd9ced1cc59c06e0f0a0" . + "0328cdc0ada22e242859eab37b8a0aad0711caeb2180fe0f5a0c21de353b6bd2" . + "a767fe2cb91044c55143d6f1d28e75d14afc94d54f4e3d25badabe4c86e35baf" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "9a5727839271d83e500dd4743360c50c682c3e85b08b096f0dd925880e693d78" . + "d0a571f11dbadf27aefe66a1742845e7f4fc17bdf37f02b0df21a2bd26c9a99b" . + "8a1d3cf6ac3eb8674d58a2929c16d8d8d9916e4d226774fedc16b4702ac54d71" . + "27fc545f6449666ef3da98815f2a545d4bbe61cfc6072978fcc6f89f6ba71577" . + "b7fedc90d21d3567cbc99f4d0492ec432ececc3d42252433d6715eca7b7bb7c2" . + . + "60c2af7ec0c2ac867784364a2c8e18cf198da7a9f609c8cd6ed27f26412583f8" . + "ed9bebabe1601ce369f0648586af64a6f0160cec410983f4d7dd5556bf6ae382" . + "89b6baf2dddbace10bad2c222322a595d7f3649aee99b526abb50f2a555a46a6" . + "552ad85d960175fff1a1960a4ec8163480c2f5cefd6dc9537cbee277c50a7588" . + "10d500dd453a8d329468a32621c4603e2bba2247c919e3301e66cbf0727f6a86" . + "647d7e9c667a4928bde40035caff5ba14519555a409d1607067e786ca4d9d49c" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "db2cca6148fa94ff2066f46428c04269e0a630b9a31b768eaa27cc60d3cce56a" . + "464680c10b19fa4f149f8830727c9c4d32eb76391cb4716890b950650e68c978" . + "8e4db3ef290fedc932257d2acf6c5ae7029ac84bbc743c104758ad9d8eb29571" . + "32ee6db74f18ef59f68a2573a1ad540118ec236407a58b35412dd00126160927" . + "af1d7ad86dd70ec4e636d6d457d5ba24874cfb389b8a8d6e9c7d749a0f0fb861" . + . + "a861d5af4d63159e4ac69492b79e5f2feceb59cf310095ffef21efa9326c1060" . + "d5bad695ff873c400472baf838d6696c4e1235d5cdf45c130e378ab657a4566d" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "c919bb135c64c53d662b92713b7515da3724254bd6e4590efed7120104b8b7dd" . + "52008747429936dad05f12a4dd422d1a7c3e5aa3e2b780d3abc8028f29c942cf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d693b0cbd4da0792571d868365f7a99acdce166c60b5b74fbe079606956f7010" . + "0743a249be7c30d7a8ebec59313c3c940d74b3879c4bbd56c0e0cdfed464f962" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + "bb0b6d1a126140709b276cd1f2a50481c8a08f5a09d03275e3bd5925aa303ee8" . + "e291fa352a9aa5c3ba0ebc8355bde564dbc74dc0a72083e74a81e627e7890843" . + . + "2cf7772c3d81d6aa2c2bf19aa44e8793352703c195eaa99e18570db5c6fdf8d2" . + "3f23afa81131ece3113a28d0eb5299664b91d23f6efe81445546a6d90f359dce" . + "9377b0cd1ccb7f12204ec96970eb88c5b4b212d2e231ae41c556fd591c4cda08" . + "de0c0a9e497d02951ac678edadc9ef38e34bc75527438e19abce3753791b3752" . + "716f560990158dc2773b837f04d1664a39b9251f84b84d865a8207b042923e31" . + "d38e1571c496aa2a31d65cae2a931ead86295d411c494feb953d861dc22bd5e3" . + "1498d0019e02bfa4504119098a71728e8ffaa70241c847deeea6e2697694ebb3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6ec5956d09b164a58f30713a58eafa18e888a815b7255288d591940c78fc8774" . + "f11d1ed4ee553572d69042bdf92419999b98bf4ff6293b01d6aba440a76fe8a9" . + "0683b207c09963d64875a6a53d9b29651125a9e16d95f1bb8f28cc886e1804ce" . + "c4c7d2e375e42cce06358476e344077e9700a1b5470dd6f99ac757bd75bafe19" . + "9f10c5bf449007920f04dadc38d42dc9cac73efcd40109b5c436fe41ecc91192" . + . + "406551c5e83fe23c26b1c37b1f5d625c64b2175178885fb84592a1183a988693" . + "2f5e23b58f22a8b2d6d8a6599e2594f3f78e86a98efe0d7c95ccabe44f04b64c" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + "d81c2da142bca67a663e81fb6eaa69f6185c8e651728bcb1c04a470baccc7af9" . + "09a22ab15fe091534f8035a93cb284122d3991844c45050528d62eaa7ea5c878" . + "fb05264f753849484b28fcdb5adc121b303f223098be700c6379edfcfd817208" . + "c6b14d1de9b6331c15a8ead755e1b6b4b45ad3003629d9fc3963e982793f6ad4" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "78c66c0a2b5fdf28453959b0ed2f94c5afc5754ee0ba9541dba6218d674cecd6" . + "78c66c0a2b5fdf28453959b0ed2f94c5afc5754ee0ba9541dba6218d674cecd6" . + "82e7585995ee5f4e0b6e55400518bc8aeae4d67262ec8306fe59005b7419c8b0" . + "ea9eb2b88ade2325c6f1e6e9506a5e4a698959ed5425efe604cb64e4e3b12c57" . + "e499e909496b2b49b739b17fae959872bf5775ea3fca57c480c8523b3aec03a5" . + . + "6bc04ef4e35256baae4aaa73a23273bf335b0ffcdac3b7ec6b40bc5976c5f8d2" . + "ba3049398a508ce94ce78d1b2186966299d471f26a420451701f2d8fc3d9fced" . + "3e992a8c510ef9e33febe5e6fb8bb17ea3da03d46f3d9be4270b7d6246ae0e7a" . + "56d3d3f2e3fd1999de142b054ce915e4a39a7a5ba027d0b641b6250b90ee3257" . + "9163b0b7cfff491bbe3d305e12e441901b4f46e1932989967c32c3aa4117a8f8" . + "224bba68735df463026f642b7d9d773be2ce17f2f1e73e85ba94980b54478556" . + "92c4e5d3811e41dfeca49f1c03e466b922a082236fe10a99fc2f697b4204d67f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "706f9970e4ff8545bcd75420b6919fa88ab0a48bcf42c4bafd37b9de8e3f4121" . + "1800149063b97c222d2819369d31c336a2d4d744eb256421452f1bb5a19929d3" . + "a33756ba595ef3cbc7adf6942eeff10393a9e4fc195716f250360cdd0f02a326" . + "5c57dde48d79a2cd6436600183fb146318a19017492295b64a0914fccffaa686" . + "2870e0ce7b5c87cdc84fb70425a02bf148ad1297c1ec08e7b662ebee1bddcf10" . + . + "c8c2b3a714f5b539b090e06b75186334fecb3ac64036ce6df99e7f3eb8a15fba" . + "d036a7f00261e332e887b94d37626b23aa82c6501e49e48f18f8a509903f887a" . + "90e066af0d50ee82fe1820f171c984fb9c324d4f0b10b4b1180c7e8cd5ff50dd" . + "89ba78fcbe0da4259bf00c3b41e2556644eb148438c353a0aaf8a337c587c2c0" . + "bea5ab871e79a37f0896fb54b97b530d5781e69bef6d0764a771b769c97869cc" . + "ccc0de3dad292ed395f94db5bc681475701736e2380d2a25b86afe397c3f0c12" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2d46ccc759553839498cea778f3ec135a1ea265ce1dabbc4c5cac966c03cad13" . + "c5de7738e47f15eb6f2bcc14906f1736dbd5545ea7d173d8673d3cf0b5e7c151" . + "67de8d4e4c96cf78bfd49019b30ea1191e2cb1260c72a2d356e2f71e5426de96" . + . + "3468d1abec79b1dcff8ec2863c5119856f3f3fb834f37084ef34bdfb06d6053a" . + "11baca8041e27389588439b9796e74b670c7b40e335c568d39e2cba99edf98da" . + "9e16690d06dc729b371bc0a1cd8212c013f2fc8aab73369349f96207987daf48" . + "eaa180e59a35f6420d617db1958de65afa491c8f040d4d17faf2767921fa4c57" . + "f187b8acc4274407e503b9a55e3d68fd1f4c8ed3011e5bc68598e1c59f56a8bd" . + "af47b8052d53f5b70c758cdbf90fad8d341889ce2a1f9959e4d04e1b7b3fe698" . + "ca0c3c830912f1f724c5e8bee3cd3b3ca4e197eda2620ac6ba270e532293630e" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c9a04975b3514f494b7f2b667d99567f748b7f892ad1affb25843613083d5548" . + "c9a04975b3514f494b7f2b667d99567f748b7f892ad1affb25843613083d5548" . + "360922447e0d02cae72a2a9add6d0f93f402b72a3b317dc7755ff79df5710833" . + "de162930fda9d880329998a01e715327e8c996fef04519ef515071364e693b4c" . + "1b80f65768b370a214e5235fa95b0f4f9da213b09a16d1038fd22879ef48206c" . + . + "b674f43ac6e4516f26cc77b4dd7c2bb6496a4516597fb87f56a875638de32983" . + "b47478a19681194c0971c1bdee7d9077bd98f01ed651a04d294d924af639bfec" . + "33e139c31f2a1a1b5a20ee2c560dd9e3b27c3c0fdfa2d12155fed5a3786cff4a" . + "a2e7e622d9a670ff4b49b56f9a75786dc560dc601551c1c18497332f2757ce64" . + "542477aa9ea5deb2496cd57e28f85de09a293875650c73bc28be5974b28d3002" . + "47d9c7e5352f75ca7a1ad88e911d220db7810bcfa9636e154eb015a123843f81" . + "99d54c80794bdd2a41b1343d251aec41b9ab2048922e0106515d10f9138a5573" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a4789d6c36c827ebd5369577f9bf117debec7b851e603317abb60a173a5d5fa" . + "f1a9395c445a2e0c595636625a5eadb17b108ebb420f887a99fc01a42d9256f5" . + "a90526e8cdc8b295be33de5fcf35e032370a367baa6e01c7965c2b68641c207f" . + "5b48bebf016af32cbfbe9f9d54a23b6cd159c344275d5d4f7fefe411b8d74a31" . + "db337025c95d43972946c7563efb497270253d98000b2edf77562bc5c107b0ef" . + . + "09813099f7800cb40766eb0359e84c6f5439c745092c984e9c76dc8f40aed7ac" . + "c2f2f79cef2d6fddfd97e98116575de56312a800a3c7848147632434fba32a24" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "d1d713b43dea90b69a6bd3c28fff56a35d9ea1ffe182f57a3956836c408a1635" . + "09813099f7800cb40766eb0359e84c6f5439c745092c984e9c76dc8f40aed7ac" . + "9a2d34ebc9830443ad9e9d9f17faabd2918bb98137f766e6d2b35b6c25ca7bdb" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ea27f9ca1ded7e2bdc9f4a2c0e25fb65438e289ffefca3091b69f308bac3b471" . + "8fa40f702f0982ba7f51dcccc4c9cf0d00bc59cb702a8a75b841b1abe00af87f" . + "a7fe2edf7a05aeeef1a4ee01d2141ca5b967cc4bc3ecf00ddd464119b41e9394" . + "003ba0edc94a5ac95ca6a43d44290efa24504d6adcd6b3d7c2f5ed61239dbf06" . + "1c4c3e0d1196dd98c70a7be581040408ef4f13f798b28b5a949678478919fa7d" . + . + "7e8b5c2c27345bccc8b0583ffa813d4b4ec7e0e2a13ec01510317cc2dd9a5002" . + "328d8d854614f90d4a66d41488b91d01799444eb96344b8facbff40d44f2a7ef" . + "b940b8039c14e2fd123457c14e359102cbba8a9e2d56971afa606d50a2b72c15" . + "961269721c3bf78fc4e1d06a916a5e48a428aba5e140d4903da8bbc68cd48441" . + "7ca74cabc3055a61b85b872772fd187907d8234dcadf6a295dc13810690c809f" . + "b8cb4a130fa3d802c03a95d038f6fced090476f56ed9756633d5ca69f6ae0672" . + "432b5c61c1c1beafdd562325ad524544e8782a760c2346b25d70e46e2ec30d99" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f83e20b3f250284113762a663e88eb4c89aecdbcc83d6690640385c5ebf54ddd" . + "241fbfb23750d2878035db3e2aa577c7ee3fe3027e1ba6fa330a18e19f603069" . + "6ed31cc1f0e201926650fc0c2974256b744b813991d0040f6d43127253655d01" . + "b53ddf478d9410da61b815c5bb413955d52d086b441aac89319301c7c4b63487" . + "a2d63086170e6d5956300ed0eab7332d0498e760403fc97c0ef3ac26867299b5" . + . + "781c050edac4a45f9b70c6cbc5d602e01902f66f260ec79d3fcb9dc1fc08e6a7" . + "8caa8ea96773020a47cf9c23c7e0a6c00252f44084605cad2333d00d383824fd" . + "815e1153981d38e21bda5a426a16f95b14a51b32433b9b27606aecaffd7aa23e" . + "d42e01f57894c48b1da46579801b823cd5af82d0803a65b0f6641209e34f8e13" . + "cbedc2819a25243b9872ce749bc97e42838f07b3a5af82e74da24c605e7ba460" . + "3eb37cb31338804f43d911c5651b5811c60d5b0d7e3b09c2c2dc86ba1ddbe82c" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40b146c58d4681fe12379a88877c178f66774780d07a02460b7736167d30ebdc" . + "d03a0a75bdaff232e7b599a6dc09aceb2d67c25512fdaea9ccbfa19c38903c9b" . + "5f5559693456faff03d519ebbd26143adedf617b055631514c17a757e05d8aa2" . + "325cee6246f6ff6b31dd16dadf24bdc808a5358d28ac4396fcf9310681bae600" . + "979b1b9a9f58db1bf7eb54b8ba00eb965df5f38e9dc73c1079a45ad01383e265" . + . + "96ad0e7cfabe79fe02ac672a55f8c0310849ba788a9a781c30fe2245e8a5be19" . + "498efa520f70101e2101a7ba3a62da64de6874b5c021374cbfef2e7ebd035d1c" . + "88ec9634a7a54b17a7e612b852fe8bfc60932f621b3923e5bb576d61136467fc" . + "efa6988b498aaabcb1a4fda6431a15f5c4dc2de10925ec8c89fcaafd2f78b57e" . + "f03d0ef30acda815056fd979ee5515b82b475a0d7ff830ec5c4fdd4aeee19251" . + "471adf19ed509846606b49c63d0376a6f44692e9d8ceabf7abe3b7e6072795dc" . + "a0a69181b56e1fc2863a98258a58484ca9642cc2158749293e9e1a5f01a7a9a9" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "507ceb1a326a10a38e8fdef14ffbe4bbb7a0687624b90ee1dc53ce639bbdec41" . + "01a48fd4664635557bcfb5f1bc54381e818eb0ded8a749fcfe8384b6e5049805" . + "3e992a8c510ef9e33febe5e6fb8bb17ea3da03d46f3d9be4270b7d6246ae0e7a" . + "1d8c1a1854b70ee254715210b27c5760583a200aeadfea9bf001dd3110341442" . + "7f05b7eb385e313c21da614c7d0edeea2013e311114d0cc29c6879da1768d5cd" . + . + "3e4c99b455344c0929172be7e95fa6a5271ac21ef203e6895f7f8da4152ba071" . + "27c5be211827c291ba78b9da0d733b65498e7986508c67cc0a7d88b49203df12" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "f053166bcc377bb409f951a535199536cb8064a735fb900b7ead8bfce182aaf2" . + "dc5d1768e5639fbca3ebfdf19dc724df0737a02fc6388c0fc4a0b53d6e7d9d52" . + "65f4d3de36884827c588e8ddaba992fb5f6a4cd0c2d6a3960c4c18d4d4419b3d" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0bef3df8b466ffe6ab1ed9abfac630a0ef2ba8199255d622d4ad65e1f8736ef5" . + "41be6ca75c6fa94710dcec7f46e851d8bf4a22e4658b739a1aa23d8498acefd1" . + "f77ca1531bbd91fe72731f3b168df3fe6050e236acf134409caabeba60c23bf4" . + "2e58b046ad1e5577d392d61f3ca94219524f1a18c638ad15ab19d603c0aeb845" . + "59e50a1aadd78fb2fc43fd524e934b8f9892e47b50de2f4d909c137a46a388e5" . + . + "10f4b43952c51d1491dbcbf3e5fb3a9cd2d1d41a2ceb0b4ccc3a28af2df43ac5" . + "a937efb2edca5e45f9971bab13f674ec14aaf6a3a67a27c34967b253b24b6836" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + "1212dab1b107e82a2af497bbf029d4a3c378585a31bc4a084d935c605cee70cc" . + "2afa2491c8dfcda17a267b78f07d8beb045880dc22dbf8f0477d63b8b9d04ef5" . + "566e4def3fe370816ff4ef2bc8b4c13a5a53e06d795fa2c5865539dbda3d0bad" . + "168a0a0d4515e231fb8220a4c9d25876d1c56045572f7a444db736c49338f1dc" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21371a0cef360437640fb9b34a58010e3076cb6f6583912ed926231ae1d4eaff" . + "21371a0cef360437640fb9b34a58010e3076cb6f6583912ed926231ae1d4eaff" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + "5feeb10e5c7cf7b052f946ed51a27aa7e14f95c8d2d8e8c157dc10927ceb2b99" . + "2ab1b2bcd411dbb6a09968b65f05d58892fffa4a2f6ef102fc886d7f25377434" . + . + "bbc17a2c8a2cb367e3185b1e45e913b209be8d40e319f48c4744773fccb4cfe6" . + "8c9f4c2fa552ce0793c3c20100580d3082f9819ff9c99d541fbbc26ded124851" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "fe30bf1d8bd3d853042ec49b0950e008d90b1258e497139831e91d0cbba354f3" . + "e40568333bf0efd6b4b28843c366f7ce48eae167049b32e8ea2daefa312182df" . + "10c7007949b2ea2c570e5f6049b6b7f59074e4075388ba0baec1a4bc20b87d89" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "27cb1c959562ba0f4bb674bd0cbd05575ffa35f0b2fe334ef92bab4c115dc08a" . + "fdb7728c909462c106d4875d66d263489c9eed7ee0e73c5c1fbd7122b0cc0d19" . + "857d8b0a2f227cb343200ddd6aa78b62269b014920c96a0fd2b2853622d95a31" . + "0f79f747086525aaf8b98a8c5ac14c86f971d925be5ec38ad54e9ecf8549bf0f" . + "33f5ed4f4e3c89d54e8dd2f230a0d621ccaa28670daba6caa62abe7ad71bb0c9" . + . + "d74b8ca63eb76bdfb1c11a38588597c9f841e7d89567d2592369ce9e8d3cac24" . + "caf5eefc744b6fc11d2cf7a8cdfa73962188d19951d09ad0201d33665bb8c662" . + "9a4177cbb00fc4828d83313de2f1f41fb4a164984ca6a4593605022eb9313dae" . + "768bc869f2cfc3e24ce1a106febf2e85737f6bab18417f13b0fd59db0f284f4a" . + . + "9297a9b39ae4dd3bd0efba2142176ec06e2554072cece37eb83a8719037d5d56" . + "bc822ad608e0678271065690081e7b94c80eb5905db8612267014eacd68d2a93" . + "6bdefe9cf42f1efa0821aaddc06acb84037a14918a51c17224430a9483471897" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "85be578519de0e7c784e0d8ee2c540354f5e6edce47c71713c047404793a2de6" . + "e7fc3873ef78cd2eebeebd2181a602e533acc341ab690f8e6b2c7156ecf0dca6" . + "d62a0a9f067da5db7575a27d7515fe696e7ef5df0a076d542d131579ce003fc1" . + "35fa830d7ff6f402bd1396a8e059c0a47088238c1b806b32c5a9f184425e9c2a" . + . + "11a36612551c3fe37f8c0033733d7372517e21fe01359cd84195b3e04c6e4e28" . + "6f36b1f368a5005b78b989bde5006fd02f88be3ecd0dd9023be15f38c4d4294e" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "d4480d8db9af1e588e4b6313311c5c6818c80452d60c675fd5af9a59ffaca922" . + "e17542f5f498d41ca939c3e33fcab4916c8e08d4904381d9bd81f5c93563da8d" . + "7c2e1efe13a502fb8dbd25ab377bd195b3ac9d7646b956c284a9ba00dc8358b9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9abd7bec689e1a5563faac3c36863380a27794a35e6d9a5b1d23478c7e4fa9de" . + "b34a51ce1e4eeef65a6e9436b6095b7303995f5676bd29df98bc45f9dd83129c" . + "a8a2727880b40a9592d8b935d082e841302cd8b4f0c67cdc8d5e545a1ccd4e87" . + "cfb4f7302ebe720a245bd9ec9da2ae4aaece957a5c09cdc64c318742881f38b5" . + "521e1041ee273212b29a16a0ad39a9baebe99d20a7bb9a08b06423903d8d2043" . + . + "fa994461629596841da918345da850bc459beaf708ef7c709e008392921175c4" . + "d4189b8dfc2d7084500c466c1277fefef79fd936f66848f0eba823e92c3c2964" . + "2d960e5c1d4c01d169547374ae83d975e9212c5b23e64db0504f36c8367a7cb5" . + "b0d86e92dae4406c599754b16c8a0fa6877d50aef19c500a5d3b6039782a6358" . + "8e31715ce05f9acf2d52adb86f9d1d9f39925d234d30425904d8ab4dc7fb38a3" . + "8004d2395a46c0538ff5a720662344df1bfb903c1034ace3fd12399832235f4e" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "45bd2651ace7ebe51d689493b1ba8948c20f74595405b026a03eeb502d5affdb" . + "c52f667107fc6d3b9fadcfb9d81fc9f7ae0e6c1bd6b6ac3fa66ba8027e9b498b" . + "c79954f907d30b00369b5fe1c5c6552450d7a8a548afcc46ef073585f558f5ba" . + "030fc02de84f9c993bb0fa61ba75454b95ccba856acb7b5a79f993c2f350fd08" . + "5b895d5947291a39f5186b3ec8298685a567de03f976d94a5768da333841ce36" . + . + "82560236ee96c1ccc74b5a48933b32c54d85f99dd6c6f163a0ce4795396b1fb8" . + "c2467e3376acace5d71c9ffd685e44c31370b74d8fe3336a06cf0c3763b25065" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "0fc8ddedefdfe243571fb1cd4b86530d71161e55de9caa7b91aa1ec3dc802471" . + "db834545fa35480bb320ef63833c4c3e6f3b50c60021a0d5fe51d94380863b0a" . + "7a7c3e1a7186fdcb0ef9670cea3901f4a0764142824c7c311a6be01023043c24" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "20c748f7d8c766b918e40b1aca72ff9bdebde2c5d16b36dd4e33663fefe3a93e" . + "ff6548b7bbf2721bc73f50cb48e0186d63e7faa7ffb05abbb68114d3d949c21d" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "2948c87c596b08fcf5272c6e9e0c6c5b34a28c5c288c6c7e0e9276947ff87560" . + "4f245fc6549e3fe33fe862a4dbb6afd3637d79f3195c5fe7240d7bf3f4530b32" . + . + "c23ecbb87fe0ce6abd87f0b42ae210487085b22931be175bbc1f8db87c89cb03" . + "6c6252949c6d60ea378727356455c607cba45d04b826c7ff3e8829601ece0f3a" . + "815e1153981d38e21bda5a426a16f95b14a51b32433b9b27606aecaffd7aa23e" . + "c1122f24eaf74ddfbdc24eedc472598136629882d1bb5a211d702b67fea15e72" . + "5c133cf6fac6a60d3317623d12072feba42bd8d780013ca652a5040695deb5d7" . + "9d921c3ee4fbf03ea3fd952befe97c6e9fc3a2491e6cfd8a01a493a47821edfb" . + "bc92067bdbff1a97c164bf4cf73a50f34649c53a0e311c6696234cb1e2f52011" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da9a70eb92be13dba9758c989ace11238fcd109989b66a38bf911c2526cac1e3" . + "ac1422e96e258581503dda59345321816657235ed539c89f7550ffa2f1d170ed" . + "ce5cdc507e34e47a86110f11b9e2bedc4c178f5cc2c7bd47a9723c4ef5ac002e" . + "19d7074c3273cd18ff81b6945504e5eafe13d88681b45080331ee2ad2ca970f6" . + "644146d86a58a14ff4741d3e03f5fa87ca79e386f34b2c7353c134985db623ae" . + . + "c7834a8c543f168efa1e7c75304157be2e42452f626f5a8b822f4c20af9c68f8" . + "87599b4d733d70355d88d7608e3513e4e2ffe06146a9c8bc39c7e3261fa31502" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "fdb49399b3ec6d7d59db33d702768bac6b2e5f11d88b56cd76aa1e3b6d36233a" . + "3aa8795fe9002736f03d9a6aa02fc9ad3489814745e213d31b6a25b3b1afca33" . + "71d608e6db453019d2bac482703a3328e40d6b29766c3dec5a3349a656eea4bc" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "75badda38f1865dd94a7f3101ac63d974ad3d58387a0b60498a073d060e0762b" . + "903ac5971448ee99849a1ac674df60a51d69627dd7f8994d1f0b73479f5296b5" . + "3568b792a8802725971bd6fc07a94982069785f1769b66aabf1b7b73674f95c2" . + "88ca0c839ed065ab3313fa39dd102d40db4ce8d54809503b6ffaad6175015f57" . + "76937b64feb5295063a8a4626b16011ab899d503c12dc8a5c3af3a2f33afdc0c" . + . + "49ab0a4b321c585a7ea5ded237179932b6c264a6f8ab4b9bbf36ee1a6a547ea2" . + "e06098e2f2e20cf6016649f683117c7de454ad73c1f245081a798d9159377b28" . + "6f69ca8735970133a3753aa18d7e0ade36922866cceec6cce04234dce7b7b095" . + "3c1f399c9f26db2324ae5757395af3e7325431dde0149543f9fc33f1e63a845c" . + "b116a82a2a283406902a9402f6eebebd91adb7e78a6173cfb6c54237facb1832" . + "3f66b748ea286c7114bd145ac1173c093e69ef1199da900cb7651403a4dd9b6e" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc46c9b0800e6abf3252737edeb40ac6931a639a01526dcdea8cbe705576d80a" . + "76d6fea32e7df403a509f7f74dc97785cfd251cfe3898f111a60b8f91877990e" . + "9741dd32683742d6c4a5c4951ee28de0cfd1fe29190c330c5f0c30d99f8d8b26" . + "33a05278c0c64bcd0d53d21b4e66e45127fd5dac62cd88f926d64af4cb800146" . + "fa755d2a57c0137bafdab6317840fb36ac1cad2cea6c5c00c960bde8fe55bc18" . + . + "50a2dc4918d31b8015011a9c567de70183a38749217a2ec82f6e7cd7e0e3aed6" . + "ab2e1965dd2e55167deb861fa0fa26b918fe3852cb211eb282a8b9c7ed19127f" . + "5b16126f8da59ab516f1dbdbd5a7a04f9355baa6bbc82d8a62d160b725089fa7" . + "1067dd9b5b8322580df7f427f0bc52cd73882c9fc8d2577b52d38129111c39c9" . + "ac531e1748276a421a9c01b0b6408848b12aa2dddb33b1e39c3116d310dd1eca" . + "d4bf3f229d4ea4677c4a487b6df28c3ee9cf4f689894675eb83684c250fd2aab" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ba8a7e5c73f19cff69d38fc39e07b66726628c0d61462b29900b69b08734e264" . + "b279940431379b894d5695a15ff1e691b15c09f813fe8cd98396248dbcc9e1ea" . + "09594b7255c1c847d61d899da3070455fb484e9ab56693c75dd302a2215e2ca5" . + "f796b071b7e5ff1cc19a2b447eb996a17abb23f301a5873c1147a89cef7a05b6" . + "366281be4b933f1db31c69e46cc611cde1af99f22be5d273fa5b5d2c0b968b18" . + . + "d62f2dc444df634c7206f5bc0e134bb70d10f40d4004a899226712e8535ef241" . + "c3a7a30f65d5466a47513ab0a3645beb6b4870d770554a80ef641cf80ae88261" . + "91e6ed0e7e8061b3d8df981205a3652a4ea5e7eddd9e95d5690d1f62385fec79" . + "70a6469853438f2f39020fce13c6531ca9f8357b8533ba94133b45809cc91c3c" . + "49a6c8ac756626cb10e32d8f6e10793b2d119db02909ebfb6e68e31ba048f98a" . + "8a7faa1b9e3f4d81f91803347630e7dcd595eea30efdc27c870877f8c361f201" . + "0b3a9d9328c06ac1a1770caf7afd8231ba9c5b537163162be7d22ad96b795a2a" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e5ba5915b35ef7e3b70694fbdbd81888e8ad5fdaadc4d2371bef8135815a3073" . + "602fec6ae983f31df178a0d01f713d37bf2fb40a1377db0062e6e935f02b76df" . + "54bf2c7bdecc2414a7203a5986cf13093e6367e92d9a6e3abc6e01df0170e5bf" . + "a4b342d300678b1e8e31c18488f0242192f747debeade3a9f396f407a0ae8c43" . + "211a7356c5f8593d8c17c0f081bd63e7a3bc065cee22761a47c80556bdf5fdd5" . + . + "c3a7cc1b9a265fbe89071cac840528b0a2121a8ebe20ba74c402bb5cbb656e93" . + "dee0c1c5a7111177820160e54a872ac632ae2a475489b998f5b4b5163d0482d1" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "c3030184b84c55c6ea4c1edf9fa094a75c2e65e06c07c79f9f7613add3da9fb1" . + "3a2e651acce19f228632f4e89622843ae984236a64ba26268725aea2c4fec214" . + "f4294970cd5c8fd0b6a81b8b2b34a3c60225079e944fad8d7b9b93e01fd76007" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6856190c503ef16a8c549964ba948c6cf6f533c51278e8b4e61366bf6f97eb7b" . + "6856190c503ef16a8c549964ba948c6cf6f533c51278e8b4e61366bf6f97eb7b" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "776e05d766821d0fbdfb7e66c919826851c603be7f865490e1a9d6a8a4483573" . + "cef89648a0bb219b282bffc9939c037ce9ac954b9c5b99438778a75debee9a84" . + . + "575f9c9adbd24b05d43bee49d15741f6295553981a8cd2fa762efed70522e399" . + "8abd9937319702ce2182341855301ed5b1a9d15539bd66998be5476e0155eac9" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "78086e86ee14abb36d43f0e5a5eb00babdefdba1ba624bca97e776e4f23dcc84" . + "b9d6b95dcc0a0076715065681e36290859e2f3d01cafc3d537a9ead1c1ffb4f4" . + "e1a57cb0b3781cbf767b44f402d954121700cda557f9b3f6298e6a5419e023f1" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eaf4eda02d2c24bc8f24bd151e36f69330e67bbdc10c00993cd199016b2dd229" . + "c813299687e1f6220f486797786fbb4310fd0b920e2a9844070dd41a6df7fdb0" . + "a44baed6849f7f188bd4039e1b5d6cd557b22c5104318f68d3c741215273bf10" . + "8ed36b710bbc8ee001cf0be8fc2833669740c621d66264ddbadc3f304500871e" . + "25669a052c19389c741d72836d26f6dada6247591e0a8a733b428706719db191" . + . + "d11ccad2a9482f7fdca5eaba0d5f24fe4c52012400081715bfdc9c385ea0fe01" . + "107f41b024973c060e21bdf2252a865fa41e49be8e90e9872991779fc5fed518" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + "035b0342334035b40269ac37f858945fee4317d3d55c06270a423fd16e648531" . + "16326ce33c16f5e447083551226e933bdb1d1002467e0be661b30adde668a2ba" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c9d3494ce6af41ff02eb5891e5b3aeb3432f131edd395d9249a76e49f2b5e1ca" . + "c9d3494ce6af41ff02eb5891e5b3aeb3432f131edd395d9249a76e49f2b5e1ca" . + "9cf2aa62235885c1016aa11d160267ce812a1579a973d10f793141db0dc180fb" . + "c90356573806923331899651a70917dd026d4f59028dc035bdd374102fa0697a" . + "4c4b8e04fdf238f10bb7e150437e7590fb9213ed4853d977babb6c567366b8e0" . + . + "7807fb2f527eb3f952e2f5d0da673bb5c5c8a01233ca83ed7cb85a0980c3f0df" . + "bdf4d457e2449b877a47e9f73da6c259b340822ccbb47e7442ae2936d79d4932" . + "8df5bedd52c46b9396e6aec1b2c93f2eb866acde39662d3d6db0b12508db6f8b" . + "7ea578b66cd6012994feba4eaa439e9139c359c1362b53a54e84b5bc7a6f6432" . + "2e928e4612f523f34c52a79eb3d8e3b9c50a6f54eb48f4536eba2c4df29129ba" . + "8047f5c2605c148f014e4e10e6b3f11f1007db6c0414f2ad3c4317593a58fa3c" . + "20c87f53723b619a2a0ca29f518795b09e4cd9d57a0d6bb5acb4bdc644b62780" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a98f35c33690863b5a844b32e485a30f6cf4171659ba7e4de6a52ad30dd3eed5" . + "ff1e6909d7c9c141540b9e20b9bbd9ddd9a383fd267f84d004d613c6e53e9c94" . + "f3d13b296d00ff9327d838eaa49ffd6bc684411c570aedf7ae6d0941149b2e76" . + "1398b250260f27a3b4e6f1d68c58a67519857f3806231e301a4ce239f792c24d" . + "8c276c9a09a356588d7b1fb72fc0295aa939d2206b15cf651ede4b81f39cc134" . + . + "a9026378f871d30dd45803b64ed0b0c7cf00dbc8cfe693539fac03351e0919cc" . + "57ffabbd9e20ee36ae60c7023fc62caeff1fee003944ed64cdcc0e25c6074657" . + "ed11904a5ec814782c8aafc5dca1340de8b544d7fbf599825a5d28b581e600d9" . + "47c60daa3c62125513fda5c94675cf752cc28d63d82526c619ba47bb3fd03078" . + "0183106e4b0362ebce031ab3c91d78f1b25ef4d5b371e8faae61a21806db9c92" . + "f9edbab4c0cc47033bb1f895559621519feb3c8b78c3f7093968bf79f40f910f" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6ca641a1aa7491377c1e2912e9e10380f3ccf84c202f69375376d4420ea90a58" . + "77f7fba584abb89d34c28b32be4f096614aeabc3c14ebb5697df5c519fc455ae" . + "5f5559693456faff03d519ebbd26143adedf617b055631514c17a757e05d8aa2" . + "d2a55756e1e61ad4ea15824cee84329fd798fb811c778f4a1c1865dbcf10241c" . + "fd4e8747f6252256baaed61ec42d13a6145dc9422392823f6df513695898fd10" . + . + "d1fcacb49516a829cff663aed62149e3c84968ba45ce1c0227a294df4186870f" . + "b6a6a0b768ba3d4671625ed5ae6f4e73e1f64350f841b70fb5dd118f5b4b9abe" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "d981f665e2cbcb7c7385fbc06ac3c769d5c1bde300950dd49b35f740f9f041cb" . + "248e1e82206dfb8a803b65c297e8cbffc7bdd93657b349a1f1dab560f5afd565" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f48561f1f048f55f416ac557dc4548ae7543e42fab12d9f67e336552b902b23f" . + "f48561f1f048f55f416ac557dc4548ae7543e42fab12d9f67e336552b902b23f" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "f7534bb3f2dbc8bea52f9d277208b58364d5680e4481f17b85a6309dae3b17f8" . + "67c74b2894100034736291c66364d4b2562084a2df9af00ccfae8a35e7fa501a" . + . + "825715cadef27c121c9dedba4806c42cef56a1c3678b9836c57f79e5d7e95b2b" . + "0adbabfb46e185891df2cbc8101ae2e09cb3f019459018b7313b85d55feb50f5" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "e2f456e7371571bd2b825aadfcb149ddfd7ca2a7c4c088aee8027ed5e21ad092" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "75c72b65346c3f45a5be59d27655f3559fc17b7ea11fe6a8ab7edadccca5f0a7" . + "75c72b65346c3f45a5be59d27655f3559fc17b7ea11fe6a8ab7edadccca5f0a7" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "7e9a06e6d55bb5665c5446b2e31cce8fe3efa3e8328be859c1f90abdfbdd5381" . + "3edabeece1f42ad4375487b6ea3a850b32495ede749486bf4bf008b9f1ec0d0a" . + . + "147b7b9565ae7a8e012c40b8e1117c45b180e98429d439c6e063af523d1d1cc7" . + "233623e1a57abb5b99b352576383d949ac35a3a3ae88b5d3245265e7f0ea6ccf" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "90cfcefa0cf5cc53d4b20465ceb3e6850f06ac0fda8a12057d61b56259edec05" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c8a65476a032df753b0a17e841d3dd828906fc070cd3b45e2db9075ccfb65157" . + "17982055c10ea6df8528742169bcd80848b6d034ee74f60b6339c6b1cd83cb74" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "5866b09291e180cdefbb5134409b993b019f5bb0edf1f8601c9f99c0dd30676e" . + "d303f0d547584e7a498df2dc4b02cfb1fe6add311ebb2b3052a1ad5ce5601824" . + . + "7a60dcb1c1f6b106e111e7962b56b5042a6e4af83f53561c9d4a2efd20df2ff5" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "31956c3dbeac0e9d42d572d5cf74f48679574ca10835cfaba99e0e13e0f57ea7" . + "31956c3dbeac0e9d42d572d5cf74f48679574ca10835cfaba99e0e13e0f57ea7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a20cf7e8e4a6996e78bc7cc16bb98989a106fe5d78a975612ee45b84180cf922" . + "a20cf7e8e4a6996e78bc7cc16bb98989a106fe5d78a975612ee45b84180cf922" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "5bbe7cab8177d83bee8c8843a2a3dd1db85f49a80bc78a8395e4610b1fbc9914" . + "10c2d9c89f679f156afbba9cb814742970d57c2275ccac614cf78637d30295bb" . + . + "893ad0bee41dd6ca35ea203af2dc23bb04668a018cc01fbb7cd8b3cad97631dc" . + "c139fa89e7ccd2fc74d6d4c4bfb513c399c1469cf6418e945cfc8b21c9ea069c" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "701d84ffa119502a64b54d2b1b401d12c5bc2491428c546d65e1d5b6414842d0" . + "701d84ffa119502a64b54d2b1b401d12c5bc2491428c546d65e1d5b6414842d0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c89784cb543a1121903987be497254a66656aeee8ea57d88a903d9d34a95f8e1" . + "c89784cb543a1121903987be497254a66656aeee8ea57d88a903d9d34a95f8e1" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + "916f621b0e585a60b5a07ee5463186c0ad874662f3ed79d03f99f404bb166f13" . + "f06f1301282cc345bc5bb71fd963b2a5f91e6245fb381aaa8a9ba5ff00fe1a1c" . + . + "0b8208c412ee8ea100647b9f9a4e307aebe9eab0bd98083bc4245da19cd33622" . + "222c5017d636e44ebcc61bc8078eebaaabd3f1e50e4bfb2ae001b11a0219e9e2" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "e87621a4b9a607326a2999fbdbf7116bfff73aab5f1190533cec620a53cf6fcd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dc3b75c15e1901bafd11e2f2687fe810291535242f1e01f90aa05a93d535765e" . + "dc3b75c15e1901bafd11e2f2687fe810291535242f1e01f90aa05a93d535765e" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "58f3456437217a86b785255880ab1bf8a5f3aab109b40e09e77087bc1b26fa29" . + "e0ee8b6ffeaf341e66e159d154bd2bc21266b06aabd819d0b5ec90b84a49c263" . + . + "a79693613a97838415284cd6403287a20e9d30ad4b3fec83042795e437b9e70e" . + "e8e0d77fc3a4dc6d541e3021851fe24e757d68b70474508707a0d4e0715769ee" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "cec3d7be8403271b5821bf42b5557f53c6caf53182295e77040bb71a67bf0d34" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "07d65fc50b2a6e789193550545dd969c88cc6bbef7d7c4d250fc4c7b420262c2" . + "d897b4f1c56d18050affe9a6dc06431e283f7ebe3326f2578bcee295aa46b08e" . + "6ede6c474419f0e7ae270a5951033c41d7855d47129c701187b95632bc0be221" . + "db3102b2441c7bf88518d7f5c597b1e16f412d25a5a4e23a9b0aa9f54d596e12" . + "3248a3cf360ddebd704f4dc616bbb98157f8e15c85d6c31f0ec2389a4c5b56f5" . + . + "304bb0f7d13286cb2b6295f54e2c171ea67bacce7380885282213833b8ed4b0c" . + "9622b43d1db6d260b5b16329128ffaa8cb32aee309c43256331a4389e16ef847" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "7813e941363c13d1f633d332cbc6c1170d917a86f83669beb3a92bf6f71c8cb4" . + "7813e941363c13d1f633d332cbc6c1170d917a86f83669beb3a92bf6f71c8cb4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be726d16a8a1f8a57d700d505bbcdfb5c7f652955ebe6226d0bdc74018fb8ce9" . + "be726d16a8a1f8a57d700d505bbcdfb5c7f652955ebe6226d0bdc74018fb8ce9" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "496302d2e1fb4744340fa242280e557351b3999b1d54f6ef32e40261f7dccf27" . + "a3bd1ed65169b231a83f5aa896c22dc71030ea3d64a20164ed2432697419011d" . + . + "3d82a8e030faf089d1934e7806d15d7d4698fef12b22268a378a53c87e59d33f" . + "b8bd46a82fdab621f121585a93388d6c46dce5e459e76929ea475fd5dc36d19d" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "ce62b05efc710ef4375fef093b3d28922461c25522f530affd16924d4b7c9558" . + "a8a3b05f140212cd6b12793c3fbe2d8cff1f47eebe175d817a3841d7f43a0995" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "508347d7733f0b34290ae3830ae9965b46b5a378ab7fa67ced0d87b900e2dd02" . + "508347d7733f0b34290ae3830ae9965b46b5a378ab7fa67ced0d87b900e2dd02" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "bd0d39c993d1abd517a29aca75f07e81d08f69a758164813c390e02b65e5a376" . + "d5c35efeac8b876f9158dcf1bc8e7bf55c4a51486cf3b744b350afb7ee8ec359" . + . + "7e042b6573b13e08fcfaddf5bb73daa34f552eea1587b58490dc4ae8d727edd1" . + "2d138d80433d41266c8dd33b9105a12848afd7f00a7e2e489424b864493e15e2" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "2608dcdbd61a7e73160aa79c5c5d3616f7ec42f8d7fbfe13fd1666d4c012c5bf" . + "25fa5c79e78b8e16e1a66de8ef5ae65b218c05beeebd91775e7b70818b155ac9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d2b01642ba536627ba092d35e45f39f4b35c02993293a93739585280fd3f34b9" . + "d2b01642ba536627ba092d35e45f39f4b35c02993293a93739585280fd3f34b9" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "e6d22c5c8f691a1f6deb15547492bdc44ed62fa55ef6b6122f1b0744c0a6400e" . + "e366043ae105cd3572b6751ff0367a2efda8330ff2cda6dba038393f0ab5ea15" . + . + "dc9876b113fe862cf9d04fbd295225eb4d21c97c418dc215f2a84bcf12c9f142" . + "c41e1b044bb3855c17e15e11a653a753a49e585a65c9b6851bc3414c51e3bfa3" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "053f6c288751101fb61d10edf3a8a5e2088f95d9988ad6772ba9a465e5b1ca8c" . + "0e1bea9fd86de991037b6ac67c127a0a1bd00c88c75fd2f3193844507e2226ee" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc9a488fcc5dc07efaa9b8c37f42d53aed6f3c67009327c175fc541be893b492" . + "cc9a488fcc5dc07efaa9b8c37f42d53aed6f3c67009327c175fc541be893b492" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "c0e30b64a6c7b324fd68315c93fbb8252cc86e12d09f5b32282c5a8e7337cdf8" . + "8ff5fc7c83ba5d9b6c25d0ba68b8ca8e9bec95a5a111113d1829488fad4d579c" . + . + "998f04c2b98c3f1e08ae36526533758f2f4e0f27810225e0f4b685380bbc29f2" . + "2bcc183901495aa17d55c1cee53b8afaa8239dd8aeec32616910b5df58582aaa" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "bffb1ec72b161d54d5a428fbd3ed0f52ada45ab1f9f1943cb68fee41ed7bc249" . + "6baa4a8307bc6083d9d59f291cb2a94444ac29e771a9bb9ab5ab6f8b099cc1af" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b71b5e65ea24c36050018df52d7a0d96b26fd58ab1fbd62f58af66ea5475eff7" . + "a44a21c06e9d46e72fd2f1db6bd95b946516a24221742ea83dd3413c70afff13" . + "edc74bb1df36118f152a351d15edb1da87e06599ad9bfc5c2f51c7194cd4229b" . + "c32fc9b3609af7128ce494cf93d9c1364b38d30bf1b2c509c6552ce5eaa5ab12" . + "fdeefd5579358819420fd11953d5c6a35530b72901aa4ee8ad656280b092069b" . + . + "0809f24727228cdaaa371af26f95d6beeca4d5a2650d0e5304ceb1a8f2dbc06c" . + "0ac8abc0c893153ab6505e730039a276ee3fd639e1ef4e5cdaf6ebe1f66f3598" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "fa74cdebc3f3c843377753b9e1750890d1d68170ee25ba53fc10f4ae5b5a601a" . + "b72fd04878e4e72200f53a339a2c1264de355d3ec5e03d3182b8160e744768bd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "386ed334a4814fccdee9fc41e7a461e4714d05bbb72c9e45f536e79b61b46319" . + "386ed334a4814fccdee9fc41e7a461e4714d05bbb72c9e45f536e79b61b46319" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "77d9d9651a0f77eb97f795388d64ba0519f0bf04383863f3f6d7838d80242de7" . + "7d2fb23ccacffe1a03aa237e1937c9d0a606bfa1c548727eaba4710f79a052f5" . + . + "b62fb9a21145d944f81114ff5f0d17ae54d9d339c41d5e10e380dfbefe65678e" . + "d550e68658136aeb424bfb04678022c9af20ed09f7939739eba5a433514174ab" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "97f299ac4299886a6761360b371d7748f1380a408e6af3e9016fc2022b548ce8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "47c7b84534cca83464d4732be50c3eb885302a73d862cff00c640557ba0823a6" . + "47c7b84534cca83464d4732be50c3eb885302a73d862cff00c640557ba0823a6" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "6d1d622ae2cb4e7ca696c916b43e0aa6bd35d8dac4d203df05d957255683cff0" . + "e62362000c4af96796b81f0a7e4c63ee9d6aed1e66624e2278fc2fc62a4f3d4a" . + . + "3f8f51cca10d2c54f31d1cbd62c0a3fdb41492385dc6e2b10c94b06354791230" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "80cddc98c6d72bcca3149b6df38fca60d41f34d1455412aee191689e9f9b9c7a" . + "4d876f8193243d49f273507c91975ec675488136e4d9ea3b6e47ae4cd1f800a0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6b58cf9de9068e63d8c49aa97195ee8249d3407c3c553212437c0ccdf07d576f" . + "a6bf553c4e557d77f9ee9487918833b6c1c6a48a5278a199db5b0efaeb854ee4" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + "a9296250a1c4cae3569d71f96dba92eb172546556b0541154c627ee703e72d59" . + "1a408b9f6bc7bd20f229bc4c22412e271b7a008970a66bd12083e6ce56ac07ea" . + . + "a7e76f03336afc1a72c81e31e104c2226f1b1b2bdb89b2b57b735e24e7e17a25" . + "fddf7f034136c936e4000366153c64d486ce461259a3497a8ba33f851af5f7c0" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "c8b4a049779cfe35148643720fb5b4eec87b246326ace7031685b1b01b145454" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "69c9c7c6d2b6589f7a59efaaa606d2634cfb27aa9560d34425333013c3b51830" . + "69c9c7c6d2b6589f7a59efaaa606d2634cfb27aa9560d34425333013c3b51830" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "8e2866f867717bffcfe54a65277603563b7ac81169a0d8800285e4d32d2c13c2" . + "e1db9253c67522b43a34306f603e24acc6a06b6caca084dd514c76364f3061de" . + . + "1fbfe63a80143055429b35a71fecf6c7a29dad310cb7f1d5a95a4b7cd9d88a13" . + "b6a6a0b768ba3d4671625ed5ae6f4e73e1f64350f841b70fb5dd118f5b4b9abe" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "8c0c1ddde9f1e43763aa404e259c6fdbc8c914056578e5e397e7a235009f0e31" . + "a61bc598cda0b0cf38c848b5950a90f8ffd6394e4e5fca114311a8b306e6aded" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7040bc9478f4b5dfc54b2b38090be3f6a51c1d23b2972c6673c50ebba8144793" . + "0f94ce473060e7c5503d6bc14495551118663605be875c111b20ae9f9a3080b9" . + "b53f937d57bf232ea09acb55e5c31566f814685ac9342f7ebd77c9f22f06f9d0" . + "d712db620a27391600c1d39d611f17b4789557a0bfad04ea84b2747f7132596c" . + . + "6f46c7445faf70c47af49bb9372a30be4a624ad0cb26ce59186d7a39dc991117" . + "314fcc35dcd334da50f371878178e742d7d5c5daa20475c73b23242dcc175377" . + "17b51194b3ffb93ef854ed393e2469c3f9aade6db89752032f42dc4123dbe254" . + "cde2bd069b5e9772dd4b75e943c2d4429d85eaa7c4987f8862a16ca3ed5d033e" . + . + . + . + "6f46c7445faf70c47af49bb9372a30be4a624ad0cb26ce59186d7a39dc991117" . + "4e7ae3b6d6e2edaacc51788c7ce3a613744da97711244f9ff91644e2bdaea987" . + "af29535d15c8c877bbfa75e41fd96b052a460b94d4891a40ab697a6d2a3601b7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "34f44d5c4bdce9dbc89fb1c6062d22a3149b3dc6a28a44d5724e014dcacf9e7b" . + "5cab6ccde5b5018dcb9d496d686c64f86c724434c43a818132811b8c5dad8ffd" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "7fb91963004d3f15418ff400c22b6d729689c740b588b76b76977a90832857a4" . + "dd94eaa8481251fcf45752fa7bd33d32e90fd677477abd898b8b433508d12d3a" . + . + "f4c6a3860f928d4b3e5cde7d777a6b21b491bbc996b4673d2b7f25c678cc409a" . + "05caff22570ea122ba447374f8749df44d569098ed06f570d7916343c142bf7d" . + "6396804246644698c1f7656990436ef69f1f2ce1a784e49658e1188d4afc4dd8" . + "731e11e2179dbdc6149997e302053f4eeea7ca3ef8da98574abc4c87dce97578" . + "b2ab1ba4691a25ad76a74172d2cf43b4539b256fa0b3668f80f0a97bb55de2dd" . + "d7491c923b7b9f219351e01d5145b3166d3671cebe95820fee08c12f0abf6562" . + "6ef2051fae0d097c79d1a273f0a633963718ae2b49a70191b5fcd422f57f5001" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "682e9039a22a0c260d4c6af99bf371af3a334ab52da2c92bca40b6226f358933" . + "b525b8a9856228a2b8f0b261ed2cc3174ac019df542ec0fade8f01dcf1b91f4e" . + "0ccf618706d00a2fcff5519c2e908b5a86657bc29a60b402de24ba498be4b484" . + "a43e3f2c971b2b47719bfeed29561889b0eb099ef167376fa015ce9463f7cfbb" . + "247b25b8be5bf051771c371982339fd6be1023d4083958f31d021a2c7d380fff" . + . + "42da03d90deb7080ea443179c5bcd5bd96bf25c4371d3770ab699d070fb578dd" . + "956c62d430f3342564e35f462213bd2ebef978ba14dd2a6b36699ef9a4e33389" . + "84b470041cb64bf93f76c41810fe2d013a5afd893b4a2690ba05aca7fc41421a" . + "dc5c757dec3618a31813269d312d32de1a67d672bc6edc7293effbf9df98285f" . + "eb9581a696052f5e850f0a6256fc83b8ca571e3490dffb4607f6eb11f7648d33" . + "02f15a61ec1f98a4fe77a2785fbf028234b714a9dd1077e33c276084bdd8952a" . + "fbf4e657294924acca4862173ee31b86b300ec94f8c3e0cbf291c1c1921f35a8" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "18cb10490bae711cd462f34b935d2ee787c205aa6bee27b242c0dc3f4608c0d8" . + "5f51f029b889676b83295670f370933e4fc1c3efc98607305262746598ffc302" . + "cd0e48ba309f49cf8fce4bb93d11c7044f65959863b85ba7c46dbd7556b1f59f" . + "a049a75603787e760ff338f3f4899ee7cf4bfe9220029a73aeb2bc4b4b179eba" . + "75e74f9cc3eec93ce60d78e7d25d697a0e929cbec40206b105ff7c72df46f454" . + . + . + . + . + "66679b39f8672076e56ff235929b91d8a6d5f14fd2b8350dd7b64f386401d1db" . + "8693210f14195870e41acf37424bc384a8c9f5a2c9da91ce9b5010155d3946b1" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "4c69ad9211631c2f5aba6d69734bf3f0185c8f95b354c582ab92e9b1dfaae358" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + . + . + "a7b3051fd579e93022649792d8be52d6b2b44d738af07a29d2875280b5f3f434" . + . + "5864c23053ded641a3333290e46087e1bc7b64ae97946331dfb988f0159e32ea" . + "fb0e98de2bc8f7f7258cead75d465495173005495d53233d9eb6b584d98d9d4a" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "3d93c608d308921ce09819efd4f64a2b66e103ac010e547cfe9864527fb5722f" . + "06e885b8495e91721ed886b60c2ec93ca87415dc73a5bea25efd11f6bfa01654" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "bca4cb4c05b15f32b04ec5278f17795e22886b8a8f4bee7e8f2983c7e25688da" . + "e9898892cd56e6a576826054b623ed57a6faa65f8c57fe0a67c13338b34639d3" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "107ecd322a3ec6622a46d908a516c9b640ca9aa1b6b37a9f5ed6a27d25cd681a" . + "0e698aa9b8c689e955973d8455c7365c7e9791fb4c0896babc26e2b97dd4eeb6" . + . + "0d6580caed17350417b7f06219effe03d0dfe14c29d123e7bd842ca1e9ad32fe" . + "f9a559468aea0968830cba98a9723d6dd2a88903f02336353ed8b532e76cd631" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "a06f7013a4f94f3186748ed3184cceada6014447f1d9563bc4663155b6603a5e" . + "72f4ff7293f43252664b461c4ad3307eebed45f7fc0022d1e0304e4cbeddf847" . + "ad8397f15d86db58db19447adcbffe967428e78f8e9e070b83f26fa04ac0a4ca" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b70c132303c4859a3e4fe145c46acff926f2aa572075d950c0c342f6dc42e794" . + "b70c132303c4859a3e4fe145c46acff926f2aa572075d950c0c342f6dc42e794" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "7c9ea26d5861f35169e4becf8098a2e4bfa856da5f227eae60a081a734a57d7c" . + "79ce38ca74c6766ab2382454c342920ce219912b84cfa2b52059a7f81b236ca4" . + . + "d5bd861b3fe0ce35540fbbf512b80273c79365ae12fdadf4955d1700c7d6b9b1" . + "6ab45ce1168ce50c1a968e1b2a4a16c65a462f4ef259b7ee09633fbd89ad998e" . + "a8a2727880b40a9592d8b935d082e841302cd8b4f0c67cdc8d5e545a1ccd4e87" . + "e7462eb051fd7badcea625894913679ddfa66071a4b1a669f07a0fff4aa10ea8" . + . + "483d89d110c6373a0ff31c133f46dabfb87a236a8039e5a0586a34386c879e63" . + "9a62000be9bc8fac7cf88ab51cac7a72551f94fddcf7d5c2c89924896ad742dd" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3e587a63fb57926231685e2552942b4f5bcea97377029d5f305b7e07eba5d0ca" . + "c1e7c626dd7d814f6572f1a71bb526e566237965d32398e41972f40ad01e721c" . + "3f7929232d7356290d3da502ab7b3f7718036a4d930c0984077fee71a27256c0" . + "0fc8dccfc0cfb132cd4fb795d0ef5b1fa36d582c2c2d63faf6eabc2c34cd2a24" . + "0e26a83b32e4b1b9f0e912a5d1d39d5b3c9003eb65d7c1953d5e7610eabd10cd" . + "d798d0ebcf6fb60b0476977679393ef4bce87c3776c3eb7e6de1eab3ae2958ef" . + "4cc0e8b404acc886a26bee767319700895abd2410457d9657888dc4b982e3d00" . + "044a7176fb50f04594c4de179c1dc7a7354d6b021a1486daf29c61563c6d6833" . + "d1e89d79e69480d45d1251cad68e0165e5f7b6cd0593f7e541e1bc363cb5847a" . + "49e0a394a0d213464e7a06008af8fb6739a2c7e05ca682fd5a709acdcc13e0a2" . + "be78601642048a889d461b77a7dbf180682a91ed452f7863033a46e2ab61842f" . + "7bda844921486a45d2ba6c7d981c87b6dd74922559bb8e261662282c611003b5" . + "87a71f4c6b4f03921efaf3dff19ccba96ce636cbef9d47b6c1e321b7a81729ee" . + "908a723ca2d13ad2457d07d45f092ec2719ca8ee1101ddd1b0ab3aa34302e985" . + "17f1dc21723f55d491a01d0aed756fec65159d7e5c4698b74a48a988299fad2a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "435f035b4fc59a92b8a0ff02970e5a81a381b16e1e6bc7f8f8dfa962292622b5" . + "b02a1a2cb35ed1d65f3e80083b7e3f651ea96ef870778871fd612d39a8a3c848" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "2a794f0da38e0003d659b03b044798eda3a343f3c63c16a9bdf854c3cd2304ed" . + "1b4405144d4953cbb96c999a713bf79a096dc3ab146bc2099481858b3655b171" . + "7949d4f9339ca8dda2315d548689790ef196bf29ab94684e5a0848f8365d3e0d" . + "43ed5e9cba706bb1ec9c0c4d6a2f5e4864612fcfc4e8950507cb5672aa29e120" . + "31a785a63b00537285966acc7ce0d9b317e7efff9ff1595de6dc50aa81b9d893" . + "978e21dde851f482a8f0bbd448edc0ff29a4c0853a55c691c4ca37504aea2b92" . + "c1fa029d2d42ce82d993b766148939848782215d41cccdbfe3fb461b64a477d4" . + "95c164ae580a23f4c3d088a20c661fde2f0bfcb865949001b50b5c21b8a3136b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "4aedca74ea07f284f2aade279abef0e1ff90f4cec27ba8e906ab04a1edbd2807" . + "3836e30a207688ccf94862e70a072ed3133593a77d5a63ad3d265131a8aa71ac" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "bf5aa404c90cc5583cf3a3f24a2c7a8def9e89cbd0830b88ef292f769378879a" . + "4aedca74ea07f284f2aade279abef0e1ff90f4cec27ba8e906ab04a1edbd2807" . + "cacd84b0ce8c7ba9e3fabe6e606728cd704c6378f719bcc96d01ca70ffc8ddd4" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "031b834816014f774d4417bf245a2fffc31315d01d3e3d8890fd08d8a2cae95b" . + "031b834816014f774d4417bf245a2fffc31315d01d3e3d8890fd08d8a2cae95b" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "a983f4ad689111b98e86ae918e2be2a39a7a5a2b69d8935d63aa337a902eeb6e" . + "7bf42bfd035253f1b0f4e31a5424db8e8666ddc76803b440d3dd782d97acf525" . + "83a9d7b3e9c4402766ca1f1d718f4cf3d38137c5a3fab9646903ba91709cd9c6" . + "58b816098b30087261d8d21af782aecd7ad47f467a5a484e21d68772c023efe9" . + "9116570e2ddb473587b40305e0bbaa401e9d951675fe36bbc764d9194f3345e5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d71c13e6ab72d6a4bcfbe3c007d0baa1e6fc859336a74a602eaa9ba8493d482e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8c1424bee9ea6d5c09cdee2225ef9baac3ca6f995749e4d7841e59520dbbd925" . + "fe9358e1dcc93ffe62970fc195691758c6e42c36876dd01c3bb68b817d715e65" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "67528d6aae70cbc1fe7cc740fb3720d13c060f22499148323caaa31ec1670e94" . + "5f1e55ed9e8053d1fb1c79be50892da421e64405b0bbbf54a3ecfa1dae7da1c5" . + "885e602591a2f774af0841fd349f5d2093bdce68d822692d797fdf042d4e328f" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6136c7cd6e58a402cf0727647e6c7c80c04676b62c7d5bee19bd9cfe8e255759" . + "c52362753de3ccf0e56f4451d9f3320d19a66ab57029e91c198097022467622f" . + "f75701893ce1722083bf062f127a524dbb86e3abde5c917831a2f484cdcbd343" . + "bfc9ff1512e61c35915b6e465db1cb6390f47ee26ff337230ecb7769589374fc" . + "737cc4d165b3faef02f66daca9ffcd2b94376e3f5fb3d972c228e110390f6e79" . + "cb03ef061a7c2a7a72449684aada7efd3b5118e86494b911e88588564bfdf2b4" . + "6420e118d078ab5c9a8efb147869036f65c7cf835aec444f4097cf602a0df5a5" . + "8ee781317d8cd43657e7ed92f4307be4bf824053a907888cb463f5911e6c6caf" . + "6953326559682246e49fabf403ed6e6eb2c8622e7b9c446162129204cb13f4c4" . + "48e8e9ba51aa9800ac79babaa1578c8c8c3f0d3c80085e4d4d8602b72b59c0b4" . + "b7f54dc289d68f36bbfd00179358a68c996803fa2c743a99badbe4e85735a459" . + "eccc59db5bdbcf9aa16816daccc8e68f750db0379e8adb32498cf14f09ac123f" . + "3c9037527e6604d2c86d37e77734f52fda3b540bf3f1fcccf7088abe279f2677" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aba10709d4fab2fe074ddee0a8ad9a62b92e96485b9ce1b5edd5e2b71d2518db" . + "d8371ec58bcce6e170f6d97b60df9a0eaefd4c4f23a4e1043f8e0add58787224" . + "84e98ef8a90e5f6fecca6765354b588feb6d254704a9c8b3ae13caf22d6be29d" . + "8c1b7a1d75d4a1a1060a8bfbc81ff2e39418b7937b21318e60adb1bbe7ee33d1" . + "62dccdbbc0d7480acef14b83a432ca5a88597ca18f99544b8f666157b6f89360" . + "594305c05ba5b646a528bc3459e78b279b6319af21d017a647fb38a0a176f209" . + "f4d3d7eff4f08488862618b35f5fbe0fa8d5b54b2f26efe61f69cad4b221c98b" . + "eeac8f5bad382a08c1becaec9f77a8614f21cc82c33863f9bb6ff776e81a3338" . + "ba641c0d386c722d733235bf68f6c8039ad36326cb697fba6a444c6cbc2f0282" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "5c43412d4b4c7a6bc490f745f2548eb8033f7fba5f5f7f0f18f86e5de78d95fb" . + "023240ef6105a02caf7ad8610b792052df7daae6dac02f44b161c013e28c27d0" . + "de5662745b3ae1aa0bcf056f0033c724a5425551f616a82e8a7571950c33b747" . + "9768e0083ec1a88848d75eb0fe02f30e2cb531f6c3ecb55ccc7fa284236b9efc" . + "e6606fef2b33b7dfb9ce25a7a2bc55ad01bedab74cf0ea048b96f0501592f5bd" . + "88fe71843f052c12b28f7762b69b61293fda441276df2ec5530359bd3e7869c4" . + "193effc886ed73ee6dc911f30a8815948da529952a9f96826fadf2e8f6aeadd8" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2b2cf66a9e9c5f2cf2d3c6b9048cc50dee0cd388c686b84ae482bcebceedeec6" . + "2b2cf66a9e9c5f2cf2d3c6b9048cc50dee0cd388c686b84ae482bcebceedeec6" . + "7fb396d993ad2f53edb81938b7ed7ecfaac4bda1cdf7af8bd9ef3804e7d6be5b" . + "910c9274d55d70746d9dc4e73d35d645ca9d4a1d68f12f10dd8450263809591d" . + "9135a4ba474160880eb6b54007a1bc6e971ec0023b2efe92aee34cc2e28938d3" . + "4ad394f4cadae5c8196452aa5030119f1deaa3ac0434b465d0e30c8a76053c1f" . + "814cc04844a0b89986472f0aa10d9328060da918efa1854448acf1cea97c05e9" . + "fc9b72d60ba8c2a2f121bc6c54036c589c77c3d44baa1face243ee4cc773a670" . + "39d82ee3b6f336b89e3999b0238f2b36f8ca5c2a1011cb7f5c82a6df46d6a020" . + "b089a4b53779643e5a747919f902a53641df48245903dfe320c8de8ad3454938" . + "c80fb0fe1903a94266e914ab159ab1b3a7a43773fad88556f0722e6287cad741" . + "b30f67a7d8c4c656894b37d6dd6bf4c8c87eaaab733152ad39b90c7c63bad38f" . + "3dcc3fe4dd10e2eda97b620aa1a0d8c3c4dbb320a95b2dbcda85617db1330339" . + "4cb7ddc4a688918528edef6ccc24e7bb4f9288dfa0014d431526d5801631c6b0" . + "f16553f7f4a083274318ec090a4fc9ce25a796a80d1750f1dfce06cee3ed5aab" . + "4e3d6ebd8f19a130aa7b88cca07af4fde08b37cfcd71b06f40ec248111edfeea" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "1b8ff04f8e825dbe657dcbeb4dbcd09e02b5b604eed667a5e72f02e2abf34778" . + "b28096340b05ee8f54adf208b7dc82c08ef01cc40bb8759c6c87b51a016186fe" . + "1b4f0a3727ea357cdb8d88138ad3929b7aaf57f51e8331bc34d974209c418c98" . + "2a794f0da38e0003d659b03b044798eda3a343f3c63c16a9bdf854c3cd2304ed" . + "364446896bebad858d27ad64703f515628dffd8679e977e9faf4d9721ef580e1" . + "8e0d0272bb95d76dc3558010c25b6520d6dd1d0f6757851c5b7a491a0c9f2c76" . + "f227cb3fe983686f37d7b5ef48e475a75a4c46643adfa1cf4c8b8616d169c24c" . + "2044afa5979e96a2f4468ac1bba079d76a4506f98f902034c28db322e57c7302" . + "27810fb529970574978193b9142c0048f37c7365b609051c15c264ef84f7d2aa" . + "c5365e4788a0380cf00cd1403a85d3dc4d062f955a786772bb1b735480eefce8" . + "c123a4143ad42e44f4e5e930c4740eca9ff931902305c7c34dcbbc41b7c9b389" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "2c79f55906f91012599f270579bc4cce6ed8de3bdf2f978a04c0d0a7543d8961" . + "f34aa7a5e9117d1779b9796ba9f85453cf4d21bb45a645c627f110af45e0655a" . + "da7c60928ed0f5ae3751e05a98bfc9f2373630953ab24755715707e2df7b2dbb" . + "5e6daee77afe38e403312690f95be61e774b2da1913bc056ec95d10347b15eea" . + "24d70bd9be9227952924baac11772ffd94bc5bba5088ebd04b51119b2e198ff4" . + "914713aec57f48a4e70dbf0e676fc63e7a85f19ff6420ea674fc4b769d01a6eb" . + "391955044565fff11747ec3c3c98b2b37fd698c777bdd00ac379b5ea4181b2b3" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "117dcbfa7fe1025efb3b03b6ad2330fbae61ed45599eeab9b824528def7a0512" . + "6a3031679a57af718bbe6bf8ffb2c9704b8438c81932ec7bb3b1b36a1c8e9423" . + "68f56a47b78077fd816025a51d3e28278a81a5d94bbd25249bc6d981a81ef0ec" . + "90f5eb67282852378e6008cfbd6f3531a4439d9ea2e168478edc82cc4c5341b7" . + "34dc6a26ed3369dd29bc1ac5bdec6844750b53648b8f379538bb98665fc20fab" . + "6d46bf081ed10d14a5e0599bbf91292e7cf7343c080f0bfceeabf9cab9e036ce" . + "85841d6c85f7ebc168079120d304eecbf1a2a12dbb33560ac15c4fefb4e42d1b" . + "f3b20e4a09900a09ed808ccf0f28011aff3416099f406009d5c5f8a0df1319e3" . + "0c06de1825e66a051ee88e3c4597027f1c503a23892c94db94865f9b6a0c495f" . + "8a8618725edaffe23bd9ad2c51e07094f309d49f316e14255cc2f53eb5377ad3" . + "a44149e7f4b1773133414ebbd232426bd426368b4edc8d8dafd21e0cb0a4f9c2" . + "e81b32cd0201a51ec2d066a959d50db89925d2a05631d472d2c4fb2e868a7d5c" . + "854b51672c7dbca0fde1db2745115b33d060be4f584a414019ada83399df0a8d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "d9d1ac065f769fb9a2c1c2752e570b8e547321a1b72566ecce0932c6f02383de" . + "2bac779aded2d2cbb3dcb67a1d227f9f06bd037fc0859357d736fbcff1dda467" . + "b1627aaf6a2f4a1e11299868576d1127a1a1d0f5f0542eb899879454899bacdb" . + "5f7f20083a85c05ae837527b3723fd1e9734b4747c3955458270dafbaac7bbd5" . + "3fcaf3acaa6f79392bedf58f57497e0cb8e90185be9aeea0297d81861b6c58c2" . + "e89b527d5742cad3591fb22c9127a8c42f5a3ef898fff41ca6a87b8d28eac4e9" . + "e816b3572800ba9e88b3729d9eaeaec40feb803611ebc0e4e47a35036df0d2d2" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "40f718b49bb7ab9a826c331184b94b2298a8aee007b802d37e864c40107d82a2" . + "531bb581eb3900fd41392ee49b475228ed57e37500e642439e05b283d05ea5a3" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "6b2e156a2d80cc5ebf66759149b85ff4a0641a94ee17e16cee54eae6f995c4df" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "1b5438f0135a8cccb8d269ea721d1e48f1033ad56d3cb98fc69df74d871f7026" . + "d0c68ca3d707cf4cfd00fd3cbc19f7eef617fd8e0108c0202efaec3d8a52fcfb" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + "2b222450a3cb2a55bd9f7451fdf2f9eaa45075b8925b838acc545f270576951a" . + "7f5083b7f6bbd4e88691e58fe64763dedf568ad5f09166794ab088f525ac27a4" . + "0f68a4b6c33577cc959288ba08e28cd12dfec9923b40e2b00cd0130b76dcf343" . + "d46c2f949cb11ef3bb4812e2afd04155ca333335c180e112d6d7ec2777bfffb7" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f3d0dcc078ddd06bc9eaa5eb73e814e0614534e646af40bbd8721896bfd7045d" . + "d507e93d3514f0b785ef3665af5a019d8072cc4aac7c15f2740138a9a5a70331" . + "4631b01a0fa80d0a825bca4ac4928f646618363068e62786bf211008179a5837" . + "70f24238c26bb15711e3b7d70beb6329363275c66f8f5c49592943db784de4f5" . + "0ef580eb86bf3aa35151ed94eda0cc7fd7f782023493f581f9836660bc7dcb66" . + "9682eb4aad9ebb1cf3c96da7292a7602b13e05c38b976a4819425d8acb7a785d" . + "8ef4bbbb9e5ae898ef574fb3380f4ead0333e80d6755673c4771991756965422" . + "7b3859e85add3cb948501ade9fd4c58b4f08cddf251e33e0163fd0b7595df6e0" . + "67e32f83e2fad0ed8f92b7e9b37a7acddd9c703151f4f0f0bf117cab98e72985" . + "7710c75ba026d645d1108f0df9b45d39e9da618e0b5eb08bee77565447a1dcbc" . + "2b8c88e41d378a32b8b6de4c56726bb645ec3058c2dfc0a728dcec7e26cb8dd9" . + "426a3e7347a5f73204eae7861d34d0727ef70a8351b6af80d03b80aab1e6e180" . + "0edb929fe560717f743ff6c84098622005834321772062cebfdf557119463e59" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "ac4bcd963c9f3df53cfcb9fc192665ed819d653dab00013cb8590ca30e1ce6c9" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "e453544e5c6085a95646cf7bd0007daf5a39cf18f39e6539ab8a723ca6bb27b3" . + "ad0f95d19b6d8749eb0d39b0d76e06572193ad6e621f85e79146ae80e2cbe2bf" . + "f8fc66b9cea123c7c3736994d512a7835ed1e8c3a7bd19a67de74928397a73ad" . + "a89c869666c4eb0dcdab6d00d33cc3d0a09752fa3257acab1e3d27b4cfd41d34" . + "0d25d7f98452ec659183c92d892dee02bb26a696c52ef3c6561f9b91950ef3e1" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "7d0174fc306a63689f0918bebce26a072cb5844633b518f8d1f24cd11b3b8401" . + "f0f918342e1d5dc4bd025906c49ab753fd80d34e21edca43fe1b003e30c0d4cf" . + "ea388de3ef832b4e55efa33634dc963f0b54bf1f4eb20da73107a309ef1abe9f" . + "5694b41b18a3e3ecb8f046da5890a4790898f9cdd61d777901bd421ffe6c6588" . + . + . + "7d0174fc306a63689f0918bebce26a072cb5844633b518f8d1f24cd11b3b8401" . + "edd8f67f8273d7aa06b13e2e4488e9dd8d8d6b81586fc074e3fd821d892696fa" . + "e40ff634bab33e83e09182f53beaa85ece83bcc2b54090566f20f41791836492" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e75731385af5393f06351c8d7cdb339324c90dc6dcb7d386b5d9c853641ab258" . + "8b88613fe892720c7c76ab29cbc09692cf996e8e25b0b508750a4d48a8189889" . + "1744ffd70040f3a4540e83604e48ec0053784e1c5b49d63bfdb7ee0227354e29" . + "96cbb209b19db4144618d6b3c70ac3938f683dd266729857584a220e82ad0d46" . + "a296feb453634209624a4550f233b12665032b22c160c14f558796b2581476e8" . + "78cedd80b456f399a427f59d8fb6c1b4fa1126d0d5fd855a11c4b7c70ffd3c1b" . + "5d101472e21c0057549ddebc8114ea1da546ef8ecaedf8cccff131460aaca174" . + "644ab875263f893551e186a665f1b8144aa997cb364db772f07b5ca9b684a3b1" . + "a42fdc79fd47bfa651e99dd36c56fc9990eb75c943b5b40b5e0b19b7c9c43503" . + "01cfb7a4883da4d3fbd164b40533273ea11e8a5abcb1fa292b80ad5062cfa631" . + "3d3946dcd592396a0eb6323c1aee841a9c51173e91ad5766738a8329ae73c770" . + "5c3ae737c64cf010b691a8fbcb6e1d6530d4f1000ef5d82571bf57ededa18054" . + "50aaa49f6811417108ed7c711a77c890140aabce6f8a8a0df2f99c9986817296" . + "1cc2a58f8bbd591c824907c4999aa2841e65968bb5b0de5e657ae526fc0b8f32" . + "ce980afc1dfa87a507e5bc665c166fa71f96ef1e151d57357d04d899dfa733b0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "520bf6aad67d5803a2b9a429d2fb5dd138612be49972480ec18be4d1a2fa9e2c" . + "718b253107bb3d1b830b6ab7f5834d60a2cb4edf895990881495acb9ed16ceeb" . + "75a0fe472d9e9114e75c45f08559cd155090c91f85b970301a046a26d1c18090" . + "b92983a0a67c6a08a8955290c5b22656dcac5a70617fccd159e9001274e2b35a" . + "64e91aa9194a575e0a01bd8053e1aa45bad3b41313cc472f254461de8772c185" . + "462cb4d6592251f8bd8b7891e75eadace9897a35d1d7aec5d7a82d0b94bac98a" . + "9de51862c69a9f9d67818c88bdbe11d9f6f1057e37b84f6b32dd9fc2487f2460" . + "792281a01a7ea7d6383310ee490f6321e9bcecbc3fb5baf61bbac3a23a127ed6" . + "b41a344a484d4d1a6c8d201b3e53822badbf6a5595304f7ab4ada69e14442870" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "c1e1890d11783a57f2fc24ab3926dc878cfcd89db62259d0565a1e7c178ca994" . + "4f0cd6e2681e9964a6c2cb7a66e6c83da93ce6c79bca198165eb001b87b83fe6" . + "1b8cf2ba37092a442491ed70e22da1ed06a2f7c13ca44b279bcef042db32dcdc" . + "1fcf4e2803cd0420c0e8c69f3476077039d4b99642f411a70c59f1884c30233b" . + "c491a2f44b779c1cb47d13f5167cb91d8ee6033fe235acac4eeb7b8bd9d34b47" . + "e50dc62d9fee0ae12a51a9e63fd5c4640c37f1b75c631cf44f068d0d3ae900f3" . + "dd33affa8a41dc7e7cf6e5141256e14c40928436b9dc4907d9e6ad0bcdbeefe4" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3f6d2945d55f24d1c479a45936ceab18a860eb5222df8e6bdeab2a281f762997" . + "8ea3f4fdc83b49b7fffad7f6a8da259c5134d128dc5c3fe9841dc74af19625f2" . + "c9f9d6669fa548d8ea08c979426b88ce75c752fc8c720eed640332ae3f1be09d" . + "9d9fe0e2cc53c425768250d36440342f63194f5206f1df56cbe2f8075cc25fb4" . + "dca27afbbc020556e54898680be7fee099c563d92a0dc5941a06bd9980fa72e6" . + "f4b761f9bce9e051de790897fe3ff18d7ee1758799bb1e3c24a5b558cd64d081" . + "eb08951827b819d2226b5fdab0738cbb41c9f813c2b1c70ddcaac363ec70f271" . + "ebce5d6c73da841c9090e1c382000b5e3669f5048e4ffd099deb19c8ece3c5c5" . + "efc6ed516afb7b5f2993cd4d0b4d216ffdf47047daed943c63c4ccc690392df2" . + "37113b7bb4df93411fad5cb749d3edd0cc60fd88798a6c78433b37ee2f84c0a0" . + "1c9283abc20eb68fc0f3e16796829e0efadae17b23fa628531eb4b544f41528e" . + "ae7c72e22702bccee7b15b2ec006afd88a7e57cb46c51605392aab5facd074ba" . + "438ddb88b337407855313e5a01646fd764be6ea5029f3cc4105a86fd7504c88c" . + "61373d17aea1cf1620c989eafd0a94a64ad4d81b09a8c7b4855b298bf19898a5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "98b41098ec89f3419d63ddfdd15d9dd6c9d23e91a4b30257ab397111e115200f" . + "3f528c4c238ca50d818fcb546e16077002e569a0aaf91db85c901faa82323920" . + "29b454c88b0cb803bf2f85e0a0cc40db0d4641ffab906dbe4b79104cab24edf8" . + "ae3590b42c2db702b7ded780808a4c152f48f28504b24cf8704eb6ed4922f0b8" . + "1abdd0d700864b7579b0795bfcbf486284369908c3c501c0cdc2dd34350e0e4e" . + "396f0c984385ab26f95fac3c52dabb2c4c44cfd67128238b7cb9af70d5e1b199" . + "b7d8b910272766ae7d75cd165c3087be4b989cf6540237c13a269b659a866e21" . + "64da3b4d439a3261bb77a57e35f26a5ef302cda907285ec73c1b97daaaafe3c0" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "67ed45c5f93ee8b2246b20b1f76ae53ebde18f23aecd1eebffaa373e251e08fe" . + "c27bd2a226528114b4b3a9c9c1f026910d3f1aad7bf2e88a1b94c80e07f92d2d" . + "bd63b9de7d7dc16e75f04b81902c807cd7731f8e743031b6aa11e2462e7365bd" . + "dcd5ead43054e3f1ee4b8b12a46f9def588c67123153de2d3fb830397809ab74" . + "2de1d565bc5361f660f72fcd570cab736fc68c9b85c8094ddbf550ee6b1ded4a" . + "214d671a1b2a82293dd18824e156aac3489e1a99cbad4aba98f444e9ad7d994f" . + "5c194eddc1f3182f39b49ecf1a55f6dcc52b59fb2086a2909e88432c3918c300" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d2a3dc40e7b876575ad617f31842514266bb4929f562971fa08bbf35c0cee93c" . + "7a8265f35b014411066e6aade98b776e916d53bfed767424dc82af06d1192eb0" . + "6c9edd06cdf866334f65fc6df6ff01662fd82b72174bb3c3f5a108a332c38413" . + "f64e9af89043a26acac08df167656fcd410eaac65868aeb6ca89c08e5f27dc96" . + "008cb7931394cc6935f34ed0b51432ef6517d710449582ef7ee3c6040c5043e9" . + "8fe9fd0a14c4198c9f8bbcfbed1d1213aca72d20e6630b529ea639a5d4d743e5" . + "6f2b30e271923cf922dfccd27cc005328f8791251dab360e0339794fceb92176" . + "75232d9687a82f0f3c0060e8fe6946c89cdd7b6e4cb6ab668aee28b30f9c7cd7" . + "1e1e3d70e88fcc8a50b3e0dd8591867f0be32111562948e5b61dcfb2967a5182" . + "3128ecd2ad8b1486901e374e32c1f6a304fc758e4ef16d96517736fca33eb9d5" . + "d0439d11e7ef5ab0af0a662b3151a71651c15fd94d57a856cf2f3d34e73a2bb9" . + "731b8de6b190e4d1c52ce6655662aed7d3e3fea8d795b5f3164d8055270cf9ab" . + "9de983f71eac8d46369ad278e482e3402f7f69b44d8d92b5c0f219ca58c5b0eb" . + "1337e7573de0a9c354a3798dfcc95ca031a20e3af1f5038e2e108cf151dedc92" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "f4d45b965250a4e1d62ce0c7e927a0e1f7079efb76b0272f08f39deb4ea068fe" . + "1dd5c11a2c9df2f45b3b72c205b1e5e4ad1029efd8a131448701841ab79b7e0e" . + "5ebe46251976b6e1082b457e82ea237707303abaa402297ec32228b94a778ae7" . + "e1ac223f66b4900375ab43e7a4f79fcf57f39f864abce03e10e1e455f912c432" . + "706fea556dd0565ca60db648cb95a16b0b9bf309cff12f74cdabb855c994b8c7" . + "ac7e8fc5c0d4d87e6be44c3d087e6b5bc2836e2c73d423b7dd9d48ce01e91c0a" . + "832468701d84be7874b94405081ed48404e650f3e4ceb41bcf2d8e51c70f1eb0" . + "e3bfedacc95354e9c25485252a4042156e13c4012a95b8ced388b10c176b9ed9" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "fb1d9fb2966f04f054a29659ae7ecd2505a48e452cefda52fdf9748505dfc1e5" . + "3df95a927d9770dde995b2afa5bd3bcc4f59f0b900c612af31de1e0bde888152" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "49c33c744b6f97de00a3c01f12563e405bbb0cde2367ee0288a4dc96cd3e705a" . + "9edf30592d6f1d3e3ef3b93c13eef55d16d109bec416ad8804f0569c9c9b85c3" . + "b3d4bbb695015c46907ee9f3eb4b820b9cb76f5c77199907a2e6ab9ff7faf47c" . + "949486cdc02a553c218ea114274a9e9d336d0c4010214638c24e20620fde25d9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8b7cbb7be3851a1dbae8091da35d00af0cb1b434da3e819070bd54797fdf307e" . + "44fa1e506fa3d7f171dd40b018ae033a4bc400060b281fac39c6d6e021d10335" . + "0d58a6c752bace76104f66e38abee9c11cf8a6c098a725d53913e76b2a595197" . + "cb7edd1e46004725790608a69f7f348e2ccf6d790c857a73dccc51c110559377" . + "93d6a54ddf016abec295391fd0e75368bd97d8be0151177a7759e300002f241a" . + "22f27ac67a962effea4f0535b8c402fd6ea569887a5508d43e3337dd1301fb88" . + "7850af25c38b2080f14c6bc9a8a3dffa169d2ee1ce6545e6eecc729ae9a4419e" . + "9bc2f74526e5ef3ff28a81033ff29b8eadfa68599a35f372bbc8bcbec9d547d8" . + "10048004afd476e2c84ce585ba63991c2529755ca4bd4389592d9f61dacd2a22" . + "b5d4595cbfe5fa0ab632dc298b314274ace3ab28320b04d4618bb09952a45663" . + "4ebd65e36a030ecf46ac2529a688a16aefd7d2783aee94d4ce7adf1a5ec3bf5d" . + "c47df7ef3f0f0de2f34af244baf01408b299ea7b160ad1540af8fa712f35d221" . + "8a639c42ca9a3764bdb6715a2f18469d934e88ab40051984b5e20f66bf0aab1d" . + "c39e11ca3fc7b132400c5292d6123292d068e07af9687aeb865e1670bea162d5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "07048e687ebb5cbc975b742a04a1718033ea2c89c6418743ba744d961f00350c" . + "1640ba09b1e044938f190a9b37325e5c610c9d1ef57d74fb07f95af34d35b38a" . + "26638f19e3b4bd24ac0f57824aa34bcc771f663bc1288aa60bb34db1c6f7ccaa" . + "fc9b72d60ba8c2a2f121bc6c54036c589c77c3d44baa1face243ee4cc773a670" . + "e2935f0518dcd9c3381f9a04e5e4a83dbaa54dd50ebd7140f41550580c213a81" . + "453f5ab1fa31dedc8a89926c2002b772080ed8f407464448b13df228f3092cab" . + "be622b0b83c684a6b0232e9462a168fb192fe766e2834f23d330cfb1aa82f6ff" . + "8d790b2515e2b1f2a876a2a253be90f7835762f28f442dee6194b9be5ba48037" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "f82c53ccde4a6ce5cd5abc973eb6eed5f618314142b331bd783fddbf61ead58d" . + "0678cd0b57cf47f2c26eb802cf97fd21764f75d04408cca9d5d3c380c96cb011" . + "9a8b5fac2c52e43b83390210c1fc4ff65f95314b749d28efb5c4f2be02739fcd" . + "85955bb27eb52947d1de5a00d6c7f3a3418cfd646851ea6308a3c86ae4001b54" . + "955b9055b1ec01ace3c5c6dbe4b24c3c3cf1e2d4be7678f6907d65097f569e4c" . + "597fdce2836aa5b7231f5a2331dc9a4ef520fb1ff42a5f17c11fbe560b4d7e5e" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2bdc6c94f22ee48a54bee06fd715c12018bec5e5abacfc30589d14139e39a3c3" . + "2bdc6c94f22ee48a54bee06fd715c12018bec5e5abacfc30589d14139e39a3c3" . + "f14926c6a6c11be3ea244d39c8af793312ce9e4b2f639210740528b18edfc619" . + "ea881f9bb1a84bd85ff78aa18f98b255c9b3fa2a494285cb3188a493d6b6f218" . + "1fb0c8ab61b05d2baeb9397caec9d9884284293ea68c9cb5501e02de533e45b2" . + "5e15cec177d8db49add3a8007f828fe30a890ca99a34211ffa5c51ebf8609a06" . + "8c6700cac4f74b4c7a988d488c3b86b442aa50893a58c58730273d787fbee815" . + "2f960005c53462cd27ddc5acde222444079187bc255fac299f9c18b45972485d" . + "213c4cd7fd0f5bd3eeedff989631b9f275ec79e581dddbee23c69fd6aca6e2b5" . + "575d9ca681b4814fe05c08e6c9e63a9b29a3af36ad96368e578d6a063c5c97c9" . + "cb584df78c4b5693ff485e14726a30fa22b92b368c091671f06af069d4357dcd" . + "71df6f9a1005e95c3174bda37ac3876fcfa402d1cf235653ff76dd932b5d1f55" . + "dda8fe983ee3bf7c5b26b7d35be742847438001a057588aef89e5b0ca3f52239" . + "d6939211048fcccd19acd004d8fa244100a5c479e45b17f259db518c80e02843" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "9f537e6fb799f427300e3ece16ec1d55122196793af5ded034868d30c0af73ec" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "ccf9dfa4f2812708034b9a00d6428f3e9255930543ccd3852f6bb7545283debd" . + "dc5f47b8d9b804d3b680e78067a8bcf9665e30d90fab2608c2e78ebe80d3077f" . + "29cdd3a841923e6c92cfc48a3f5af569939a0db6ce65c2ea55ffb6ad54ce368d" . + "b25e70e2ce11cdea25503b4dce87e3835beb196f117f040b599486dc980f41db" . + "d7208a04445b83006adeeec617e58a4da8176eb176f9fa4d46a3fc8496774679" . + "168acc723c849cc1209b9a168f080ddb877910268c173dbe213fd368a0837992" . + "88d5018754d2977ea439ee656d4e55b4c91fc920cf39ffb9468d7c791b0fbefb" . + "e40488b4630199427af8dd12ee923b69bb66067e8e51ad185e580efcef861e66" . + "68cb1f73a773dea10ae80b691f9616e85911f1a3ae1ad4a133ff0a11817119ee" . + "e854b83a9aa55a77a0a3a4ed052d9992579312e1f46c313c0a736dd09ade1669" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "2783a7e2887f156d369c5768d450a250fa41f3b637e675104c4a59adf26711e4" . + "3a466ea30c670ecd7a458149145e627e78a3fd078d23924678f26bdfa0077789" . + "547cd28e9372fcac15f9fe093e075b6d00f0fff658185aafd3fa788fe5e7b780" . + "10ac3e2860f6d273af7abbe5a5a3b106fca5c83ba3a9e124c2dd54fa62bf762f" . + . + "3aa6247d5216dd513617418249bc1210819d56a2215a8f23af60046862527503" . + "5c085141926199a9de98da2dec8e1b8d32ec0753f53f2a8d4234f537498ac76c" . + "27d01464313761a25675f4e6b30804ca720a208100f5eaf669ca55babc94b8a7" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7c271098f95c068a0c45b1091b785d03206924ddfc9c0dbc62cfae1aa7471331" . + "1291b9d63bf64299004da16f551e954c63e00897e81cc083b0f430a01887ac60" . + "769800f6a7836bf513b64c63fd9bdd8364027d75b3dd07cbb44bc77599c407f6" . + "b9725eb5698e47ffa92ab56add50e86aac44e87828c13f6919ad9de742b00084" . + "56ba12bb0a7c291319d887896bc72c9e9e6b5a58a0188dd9cdd9946fd8fccbd0" . + "f4b761f9bce9e051de790897fe3ff18d7ee1758799bb1e3c24a5b558cd64d081" . + "1d531cf0fff651837d8a59cb8e8b45c4ef3d5e500f87c7f6133a04d1a48b1af3" . + "a23e1db56eb5c72d08fb9b50d636764c8ea5397939d1ad3b35d9b3c906874043" . + "d272a7adc328a288571f26186cc2fea93be08a386aea1dc388968fbd23b44186" . + "b3c85d612219b7e9086e80c0727bddb56db1f0fa3ed9162df76717f73ba75067" . + "dcf4c5a7a56e81fbbbd2466e28edc713186cb5ec43094b92d5530bdaa008e5f0" . + "7075e0b3f6cf528d22222e39de0816a3b410d06f5c3910b4b8c65d525ec0c2e2" . + "af5b6aafc926e349bdc6c229edd210340f7f9207410676d026be0496beb9ed77" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "7c01824c189972de6dc32fb447fbbd92b9cb25c41384449464ffc0809d2b557e" . + "771e48762b0018959402e80125501ba028fc675a7b8f2cd57ac2b3caaaf6d7e4" . + "0d200d800fd8f903b3905cbf5c92c82da9b6c56ab05ea339ce4a03c297db0af2" . + "bb6720d0b8ae84400158565f59dff0e957ea9638a39060cdfbb101ec0a03320d" . + "17d0eabb6b52617ae8c71b8441cd38c850a35dbbc69caf4df085c284dd0bb7df" . + "7ec43ea5ce800e0fbffd9229b13c0dd4c702e26e383e6a1532eca37b74d8f982" . + "8837387225553f9d2fdec6c5191b7c9a300e21a5f3f0e7f62920ce91e43e54a4" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "4e3ea321e823364ef6d9e39204eaa9b3fcf8efb7b8a1cfe2a5cb5dded8fee49e" . + "65b08cfbbed668aeebb5e12f274bb5bdc6f9ee5ced6cbd10c061ce5718e222f2" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "995208541b6f1675b2e6e876764a2ff8133babe10c7e6b4213aa833c17d00aff" . + "368cb030b4871bb9b928f0df94b0177094bd83b714517a012b1c4c4c9bfb5458" . + "c39d4378141bbeb00d12c6ed28b2c9df65760f92506f38eac8921084e9fa9853" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4fd40e67c75c569bfbe11d055f7251f504f260f7e593a494363dbb1c5a30770b" . + "260bef0b59ff6cbdd290b83130a6a56b0999a04c9c7176c69faeddfa99eda5f3" . + "70ef2e30db0b07e0b29d691839863cbd241ecf28521e50e0b7bf637a61bc7a9e" . + "d7794ada3ea8df62fa9c5f7e8fcd3b084dcd6eea35fe9a3fce438fc38985fef9" . + "3199df55e4350e0151194847ba627da9a58cdd7a9d688d61a77dfe5b349704d4" . + "485a12576f69d522b364d00505a250feecee0ed99534648f2d2e89257c0222a8" . + "21b130398420b38a698e397a67dbd7489a4369d1f82b8fc40d5e6dd3166d6ddc" . + "d71f4f555d5c7dd17ecf4e50c8c4dedd664c2de5cdbf1d1b8092846ef998f147" . + "3fcaf3acaa6f79392bedf58f57497e0cb8e90185be9aeea0297d81861b6c58c2" . + "5c3ae737c64cf010b691a8fbcb6e1d6530d4f1000ef5d82571bf57ededa18054" . + "c32660cd816b5de81901ef0a54ac33fb823439f8c6d47bb0cba6821aaf3b6bb6" . + "6d71232b1a77a12a35f8bd90028eb84d658d7937f5fbb280f040dad1d746859c" . + "cdcafc298fa6c445bba75bbc6baea127f0688bbbec56041ae6ce9597f7b5fee4" . + "a00bef62ed956a75e6e8846f123cb8444682592a1ed4580503d2cb19f0224b2d" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "108e0f34b56abcbef657564fffced507da3613d434768acd4c0dfcaad0a62afa" . + "a935c31a76f22df50d3184d715d93674b362aa6633b5fa7dc8462981cc77c640" . + "fa24b8603513501f691258b534962e52194ee602c3b9e6dc1a5fad6749af8da9" . + "e44642162d6b339382ba05291f683ed3c0fc4c270c5c49c49faeb7b762f82a23" . + "0b62686771993388336483b31598e3bfabe0de5d0f2e1068ae8d1a007b8f7bc5" . + "7f555df77aeb6374ad2c802d5b6c978111e75d40c83127c890698ab88a01e78c" . + "21ef85bbcc48e33e4d15f7d81cd7b023adfe86013185fdc6314e0442fd1d0b77" . + "9011347bf596dd5c1c248f5bba78ee987904c0c765a59c48e06d2300d7b3ae40" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "262ad985a2c8cceb4ccdbf4ef46ba58a069fedd080c3d73de3b95e608ec16dee" . + "6e558128ea39c2ca9198dc9ef8eac67b946432912595bb1b7be42673c3821b43" . + "944cf39c20bdb22fac82470133008a98c0507659cb3ef8b3744bf09ecb974e2d" . + "b5fc3b5ec044fc79deba86c5167b150700453987203779e46a669839f893479e" . + . + . + "3aee83f6328b62eb2dfa8802636b7c82d2422af5d40f985a2ecbda08129bd52b" . + "0df2f18d10f20c1df95222a923902540728ba4a4a54f0b4edd73330b93890a60" . + "60349bef3326e640ca730c31a320b4dabb6cc5b842d48212f4448785dde72035" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "157dd709e3b0ce5a258a7753246f14d9ff473756b01f970244cc9249fddcf889" . + "4111cf8fd659394d1979a300046be15d5fe796d8c1e50aa2ca9d10722b035760" . + "beeba8df5dac59a45706bee09c1b3781e0b97976de1905fabe6adf8035e3ad3d" . + "8a14db07b269cb71e0baf12c43fdda6ad591c15c257ff451167d99576f109bf7" . + "ed2e54a16119e8b545dd980fd7c22e8aceede787c0d3bb09e045263d297a30e5" . + "e22dde500fa4955883ffd66948428069c8e9c8fa16b76c60e5c848d6d7d90fa7" . + "51dc87e95adcf20a395ae89816e613aacda6a2be2cb67bf27a4ec4f4a90efeab" . + "5faf422f549eb90d271cca71b3421c494011dabb967421d6967a7d6122c2d59f" . + "071612ea3687c810b3efc8f68bd76340b0a49a319c4bb6de8690f77539a63da3" . + "a10dc782355c096e02434bfffa395d2c7291fb2dadb141c3c27bd7343ebf5dc8" . + "f956c9a78e963e60ee55ecbc2d4cb79658b436761456fc6e9afb02c099873d70" . + "6c10bc1cff505de81f66dd830eb785ddb875d9b8ae6d3a62da0d12a6489c6129" . + "22224eeb0fe7460027fc71c1225141e27cbce94cc6e0f72ae3f6d71feef8c7aa" . + "4c868252035e7adb799030eaa3c26cda538781e5c43e5a644cccebc715f505c6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "66679b39f8672076e56ff235929b91d8a6d5f14fd2b8350dd7b64f386401d1db" . + "7ac37d3e23ce73bb9c80da37d6079c643d683d342b78a33b06a8799b2cfbb430" . + "5c1ff792e1b447c215a1e46f9a0f118de8cf3ff96b9d9003e3fa769df0cf8d0f" . + "d08a269a90403a056cce128a73f9736c786ca5028c823916ec7a52127ca8ab52" . + "888536014189a5f13fd5cd578b16586ca2f665b8ce75a0058e9db62bed61ec87" . + "f2f0d0cadc8e52d27209e7189baf58387609859d87917b767301d98180a6d3b3" . + "f5a9467e9b9fe0ceb5bf489a348f10b21ba7043d1e39df5319bf5e7a50b7503e" . + "03ee364402d43b304ca981a5cb47901efca38bc4bdb918f4f01f0244993e8127" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "7607ca48c4fbe487b302d10b263fa3ae392cd65ef866343ffba1b749a3d3629b" . + "5ed550180204cf32365a771f870e22f169984bc068b894f27a52ffea18b1e768" . + "28a1a9511ffd71219672688ae7cd2850f0ca0e47abd0ceead31c00070d8460a3" . + "531bb581eb3900fd41392ee49b475228ed57e37500e642439e05b283d05ea5a3" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "ca3317cdab9ff0029762504d326397fdb3ab5ecfffbcef6794fc70eb2cd7d0ec" . + "61267d3dbe706d34e40852d87f784d44aa09c55a00fe6dc389a6d29b0b2879bb" . + "045daa014617aab6d64110a83080c52c62f2c8b025e7a6607942253819a8eae4" . + "e400df8c78355fb1a97e2dcdde48d777e5c07af8caebf24cd2a28271805e60d6" . + "79cfb1ee39639b66e3e1ff9f3540f2b0a98428feddaad0209556c715ef643d74" . + "1fcb486db0be86262b0bb22e23ef7cfec62304481bf31530c9c2998177773779" . + "e5e7f001dd2b273f9075393795f712d70dfe260e29d730775c51ae4f3880e880" . + "6cfd1cf48c9bae2d0222907f413c01f8d99a601efd487292b49691ce7043e521" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3b11ab8251c87b4229554af8b3ad81e95f03d0102fd35ee6e1818104d48f4c65" . + "9abc7e327b3396a10e29e2a49e9c5fa4d89d0163e883591f77ce381b66cfc4c4" . + "5ee5099e7e3197d4153fd1f4627731f4f74811ac60f59f4647de6106def5bdd0" . + "1cbdb529e96def1205dbfb5182018042b269abee117ff2632409cb6c7276afc9" . + "f5d7f5bc60aa78dd3771888cab8eb1f7db684d7255367b3887cc151227c4bdf5" . + "2d4f5711c09891ab28cbb0bed75d3909f656eb6f0056ffbccd403433af68734e" . + "f8c12b914548ea9248c157fe2c228c81870f22f90d852f06864e7c7a3691a9ee" . + "c39e11ca3fc7b132400c5292d6123292d068e07af9687aeb865e1670bea162d5" . + "95ae11a9aa1ba522ff41f827d06fa59b36861a376f01927ee587506c53cf3124" . + "64aa0ad99efd426a1eeb19eeeed1732840d9e13454edede1e51c0c7ee9c171db" . + "13044b4083c1c53f220a790f7ad384a988d3f950c5e6b1e90385f29061b064e3" . + "2a7ba6b9d2b1e1ce9eb7ebfc305414788bbbe46beba2374612d2888cd212540b" . + "2314e23d45bb265e99372f81fc834ce7b6ed7b8ddd2a84dad43e1c99e84405c6" . + "df2f2cfa03d7c8b8619ab5bbf3050a7e2715d595937013357ed88cd6e869c74e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "6d30c98847421f11abfee31be438e157ea5ab98162685f4aaa85c65838af9164" . + "fe335564a5f626599d6596309549f71e23f3b8f73473081574630f8a26e6ca01" . + "b0d16bec72af0899e2e707cf2e159d918fd0ac9f7e9d070d4376151aa88bfebe" . + "31f0662068fc79fe6b1933e62c9d0aa8f010dfa0738964a2ad02b9eb463bb1c8" . + "8ead3709049bf86bfb66e171cb8d6f5ff4c75ef9b1a831eaa81a361fef0a135c" . + "880cd6e063710dde00450dc99138d7dfcc011986daf88dc7e11a1a4cfce6c59b" . + "557528257e075f3349ff2c9d34cba5d4c18d93b865572ef427808257b96caf55" . + "49d743e21207d9e59a4ccea5e92edbd9a0ac2bc7fa9e708136fe9147259d10d9" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "801c98b5830c89ab3fff9e2e592cb731c68358b57c086454cfcd74f1682cb90b" . + "002eceb3d69ad6abb9b511fafec76a510c093ecf4f61dc84fc9af901374fe925" . + "c642cbe7224447b157b496b6eed5d08cb37b77d59c0447dd0336360d281592fe" . + "28b3e7b35b0a485e82c6d2d01971e097716c17f75bdbc351120cd5ae214ec814" . + "c5d1952972ab1daf10a0081db08dd16cb30f5168a319abe33e406780bc4136a1" . + "8afe078f8d11679a52ab14a54944349c7c52b41395b320e91b70b5ba0dae3e97" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b8d774fae722810bc4c00d94c77e7b22d16d03399a43c8f1a727b9db61d7bc01" . + "395f972b5a1ee4abeb8d3c3f110fc38e5bf226d7d150739ee16ace56cc44889b" . + "4ab030f3fa60582dcb2b1c0c3ea29f8817f76bf762e3b89a9f0bf4f3f8cb80bd" . + "2c9aef3be6ae65cc212a0d62b79d26c37d005a275e5592b73c2d54c0584d3892" . + "4fb55874134422396291d9a1d42f3d0109c8a963ab884268d3fd2b68aa381dda" . + "8dfc5d71e85ae1d06ee9984c216070a573964e132335103e17e73a892131a1ce" . + "5790b65928dcaa6365bfaba7fd259bbd6a08b47076396c2c85e1649f78fd314a" . + "e265ac36ef815689e05916980107dc29cd61fccc3fa34c690898e343dd23759c" . + "73daf939d09ee8ae0723660f62d3c60daaf401a48decf6472ed273462a45406f" . + "d4d43d72bcad922aa0a47b1398d4ea19d0fe0c9e4a0fd5d21f9b15131e2d165f" . + "1c714467ef30e65aaf761e784c0cd707dda353cfc21fe7b88037f4e6a1bbefd8" . + "481f2b024af7fc3c79622a979410b3613e7ae73d5bb8ac8ab8465a560df1383b" . + "1819bd8bc182a8fb125d7a9750867e8110310400a72c36723d6ceb3c6c752100" . + "daffc693b892944e1b94250616bb52da3a652608d47b2f710200a0645c7f5d71" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "ced1c3bab5d72042adf1069c25240c3c2aac7332c197f07bdb67ad883f7001f5" . + "08835464ad8ce7406bb06b4e0290de5fbc8c8af69887e0687dbc2fa8c820ab41" . + "1a8acb1cd6256f86d82804b4225433b3ab4e3e55e8024ea73eed601335261d91" . + "321f784feabea0eca8926cb2e3af6e1365c285fc273060c15b366df48d522993" . + "db2d244bc90c6df8a094083992438802760d6a51266f099293158d0233f0f032" . + "0c81c8912306fc743e9170b3bcaaa47bb78c4a298bb1c4a9710f93b47c13cc54" . + "6b194d715f8647b9767ff140561acb68706f81aea41673f3f8cc0804e1e775a0" . + "c3aba0067bc7088e67f9cfc841b48748115c48cee9e016f56599610ca70ad225" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "f1dd3b457b3a0a18485f89420b8341af5ab4017d7eadec4d7667ad172eb9aa7c" . + "8fe393f18a7d03ad68bc23e9de0e92fd62ec8b9ff62402b4a0aafec74052f27d" . + "5fc91fa3fdaf46f406a9777c75eed41c69ce8719a1dd6ec1fe35c2f4f6a938f2" . + "fdcdb6904edcbcc0310356a73287499c6b95d26010e436d8da68562094d3dce2" . + "02a5c5683074cd99df904fef8439e55c887f72d4ea4701bcc7a36109bb1c2d48" . + "125c2d2e21bdf77e4b361a31137b81de614aa374299c76685f562376ca5574eb" . + "329c2576ceb13969f2ed06679b878e7a72c313d3a7eac562b7f2db7b4cf3825c" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b5969f24f23e5570b381300faccff08c25428644cfcc01cd05f19dbc6c2826c6" . + "7cb4c23c55aa7d9bfbca530e38eb02e3e1674b8aef517e5dd2f28364c9f29173" . + "7f881b20fbe2bf30e3977a0d2f377b247fc0d4d119cc635b569cb240aedd93ad" . + "1c9e5dd7f3eca8ce7a197224f7c6ea0c99a31d599191ecfe675ea0ea439120e9" . + "3aec60234bc7fd5ada42c80acd9b812d476952edccc68dcdb8b034f16f460cc1" . + "8a97fabbf3df53bbbf19a5deb6318ab188da2a7c2dc166b451859580f4e7bd6b" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "e4475911e416997b67dcde098f51e1287622eba8bd767eef9dfeb51be2190986" . + "45bba3b3cabafa56fbd5c48dc0c93747075f43ba8886c14a4bf1bf72594b6f74" . + "cd63719daa9aee228769614a76e37538e5184f171748ad96f2ad563c408cfc61" . + "b1364c0272aa8e74e6d888b1f46029ead25c24d0b76c4c4a9a09768395067d7a" . + "4f0ea77c3f63ebaeb88ce422304c0dc5bb471168b694b08b907283376b246645" . + "ea9fb4b10fb2bf8b4598ad76b2a4868e68d7db15770d6e0d047e59d89f3398db" . + "697c0972bbd84ec1bcd84e64ecd889a35a1e57c514840807a5d3148e80c4f0c3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "b7b530fb74bcce9fe47dd39e88eda33193cdfc86bcd664fa7931136ea9e6614d" . + "0605311fbae5bf6688d84e437dff98b79d9880b33db853292b9b99e22ddf3f5f" . + "7e6bc428a27769c0abad104ead5f7614a4f2832b9fbd3eff51fd4047330c8c8d" . + "ed8c5b915bae9f890b64a3980ab5a34ab30f60503ca413c02ce126646ed82c4c" . + "08b40dc24ca8b75a78f58555e8a52db91833eb42a5a7b2cb9180d8eac630851a" . + "b549245270fc600e5eda91c24802f3fd13257d151c3c0a8448a6e8e16288251d" . + "5cc9ba3f01715b3e44a0a639b3b6faf6d9d4044163da3ba30f93738390905c63" . + "a7c278573475238dd3b4cfd51d01fbad1027c3c3c3e8f7573a8298baf69e520e" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "175ba94b22960f91c1595cbc2cdac58364f14efb6e919da36bf42b7aa4a1b7ae" . + "39b895b5900c0aa8ac23739fd98ddf97dd02bf687532a2ed1caa3a42c02d9b73" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "3aae6587d2f96546a4fe53b732686162280707aebf986018a5761cd0f244626a" . + "74297d1544703954e5241af3b2bc73cca998294fc52eb1dbd7ca9a249f24a74b" . + "763fadf89ae63d9b727778491030a3673d03f18dbe42a6c0f659190a57c4bf59" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fbb580b8251ceab141ecce6817bc03985343d8124c9f666679d52ddb466d7705" . + "01c9a3019db3f4ee49320992cb523741726a221c4a1466fb62cd2bfc08c9ab3d" . + "40d932df0af06dfe520d57c5e9b9f717b869f12fa8ea3941c154105c0b10ef37" . + "f3a8c5d3e152e623a6d176511e9bb2abe5d89f20850a887df27b78c57c05ff98" . + "60926d39ce8b465e6b048f9e4f1abb417df4b0d4f759f97441970925e2621c48" . + "c077a9818f7a4c1568e9bbdab30414a4dad048ea9887f83e8b709eaa26bb74d4" . + "b2c617a5d6cef53f0a0145992f17c99836a6bfb773a6631863345a2167c19e4a" . + "01cd7d061681b427387017376be1b738267445f4c4ad24caab0574b3fd881cff" . + "a9339546f90aa08892b6d2b71e3dae0613a24ff2943cb7f0821fef6ecb163eed" . + "ba9537ad6e8bbea4e4f1a59d107a1a9df12add88dc879842bf027722c8fbf2d1" . + "841c75e8d7c0bc164e1584c2a660691066424bbe52837ae06904f3f4cf18d76f" . + "d8357d16e698a491f77ddc83851236d82bd06e56ee2ddd2e474ebe369c0ad9ca" . + "39b457c6fcd64979a3f21d3152e732e3fdd88deda0e8a4aec05589c633361d79" . + "4b8b39bd9dc49bcbf99c6c1a1ef4deaa71ac3a42502c019e495fdb7023a09936" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "f7e07adec82f9aa02752aa06d3ef1f5dfbe9e55405caaa018b44f50d751f3964" . + "118792913fffc45a6a4ef1175abb260631338f4d303e579d2c5f4e40243a1640" . + "0810b08b6e81c0f77a2e18965f03a7d0d680063214eeb72e9621f0872fcc78da" . + "e004d8bfd2e6b10bc9efbecadcbaa8a2b87cf603a4f0e630c4628091dd79b2ba" . + "b12416bfd9d19eb4fc2bdf218479e8da3376d182f516461dc1cfc212c579bc99" . + "bc1b83ff529765ff5fe0a9c16686791ff5be5801016527b081645f6fc518d7df" . + "40e1594075b83b5066e27952932050348c7c28148ef9d4f1c3d098bb1a28b44b" . + "cf7cf3fe0a57392f8fa4f8e0ff55855a1dff99c500854448c0ddcea285b550d1" . + "7607ca48c4fbe487b302d10b263fa3ae392cd65ef866343ffba1b749a3d3629b" . + "5ed550180204cf32365a771f870e22f169984bc068b894f27a52ffea18b1e768" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "84819df6eaba1a4969b928e8dd13ba68dfbf6dbf407b2f5822065b265ec65c1f" . + "62959577bf841db4149f11f82b7f26ed7ceb410415a8e8d40ce00e46911a4833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "c7b61d59f7d848219585f079f18aed9d605557d7ebacacf132deca2d51930848" . + "fbc54c23f0cf82713fc693ea0d245f430bd734a597db2f1272a610125a6f456c" . + "cc8dc4d67f20fd1942aaa61b1a26cce8d511e697cb8f7680f65b572fab9c1c92" . + "ccabfadd4498eaa1c9518b7c1f87217fa5f27861339ed1eb84f201d9deb213c0" . + "b7e0dcf187498e1a14c112a7a437f957b9d6800a248af425786f2b8e6c5b0ab6" . + "d7e49cf5d83a331771949fa81ea1d585c072e973949ff3877eca2b9593c1deb2" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1139503dc70172a8a40186ceca0447e1571f391ab92ee458c4173e5c501f5c29" . + "1139503dc70172a8a40186ceca0447e1571f391ab92ee458c4173e5c501f5c29" . + "4ad0effc1620c57aeaa6ff039ac827490d8c8b248e07aee4e7d341d5c478777d" . + "73fa784aeab2b63f4ebc813e0817c823ef0c076dc9bb6c8324c94f8d6d4cf471" . + "05772f50cdb3886fe80fca4774c67e175438ed46c1e9fdc6a9a534cb7b0ba2fd" . + "fe335564a5f626599d6596309549f71e23f3b8f73473081574630f8a26e6ca01" . + "92f828af443572e50a13d427d297a3b8e97cc592e20d902535797ecf87dea8a3" . + "0483c374c5073277b0efce6aed4ecc2dc0c62cf604983c334757918122356a9d" . + "a17dd3b3bb1c5fb903379e65ff9563df4757720a56d4714cec802b0b9b7f8237" . + "e86ec728ddfc2a575e8d70ae99ce9f38cd8f9a140259b5f0985df30af9356de3" . + "e74275547b85634f66b69c3b4a8a4d1205b5f3630008154f110325f22641d023" . + "dd0df8659bd41908881ed901f13461dad7026671dc92f56acc01942b1a902ccb" . + "dd56319beaa8f6c880258cd8f3caa954e102cb636eb80265b46480859daa0c0d" . + "92a4e6a0a2a39874dfdbc8462acc0f4a326d284e4e64b16c1def375cac6e97ab" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "e6862a1afa16b962408f31f7ceaf5c99b0f797c9d13ae233af47443a714af871" . + "dc5f47b8d9b804d3b680e78067a8bcf9665e30d90fab2608c2e78ebe80d3077f" . + "bd426bd5800e4c7d9079ecc70d9df1f4439a1e00281a286f726ed51e7878d7d2" . + "296be7ba8f1f685c1125e9051bb41285be90304d65f9a522c32ec9b87fccec59" . + "139a2568a13fb6433a58b635ae98f446fa6bf209cd7d69b454146a27df92010b" . + "b25e70e2ce11cdea25503b4dce87e3835beb196f117f040b599486dc980f41db" . + "d5c31364c44646daafc2c9b870e48dcc48c22ad87ebc1a9ea38f932b19f6cb45" . + "64e3367c79672e02790f0cc0d25928140c27ec0a007350ac751237abc90c0109" . + "922e0d5c70c2145dc803ce89bb2190d3c921576a918ce3b5ed04c30a318ac37a" . + "57850910b0b3048dc4795adb7f9bf7907d3d19f7d355509c22b4d8e17350cd3a" . + "711000fe9ebea9e9c70b00b0389ba55d582ee437466fa36def618ad6d4e66861" . + "d3793b661bc6131c09fd908af0b615d92424074e6e05c18748026f78b88cd864" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "efce7f6cb5694e33996d62485d996dc5aa1691045b85519da23bcf8434b135d1" . + "7d511312dde24f6d1386ed99210a3c0083d1743564e8230d0ad52b83386e83a1" . + "8b2c6bf4866c27cf068ccc8f52107c06b79d66cb53801b7c51b6e282ac439426" . + "0acbf2d73483a740cc3db137820fa72b01936b5f00deb9016e316e54fb933b67" . + . + . + "c72e9a6cad7d19f8109a559d609c088df32c6c8eb3d2630f91fea90e8881d27f" . + "b4d9ef37fa809514d9a3b9fdb82544a33b5db0283f0f0d1ec0baeae43e6c6104" . + "8891ce494da277ad8d2528d704b9cfc82bae5a10363836f2e1dce58f35d79618" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "24adafdc6bf2d47f5b47064d4c8a41075c45bd8d4bd22d2ad97b1eff696c1812" . + "4a53f36c46d9b77a70605599ff910d5f265e7661e255f07a3ef0ecfe00ae1ba7" . + "d7beabaf30a8772a19e452c045801ec590f43316e90a38511147c03bed5b915e" . + "17eda503e49d59284bdcccee294561cfd081d1e507cb7269cae984051f3784bd" . + "a6e7f314a96a1d340894e9806105d2c96b59df1ca77cfcca6041d36d505adb58" . + "e6d13eea4e7b8bd9b256dc5cd85fa19e0f80ccc0dfe99ee34ce5eace3ccd2f0e" . + "5532f73bf444867b67b49c2d1bef65f07ba7a126f40fbabfc5d3f4c651f1c9da" . + "d0faad75b3ad049fa9e1206b62fcdfe539e8e32ded128661299260f9aec50185" . + "c7ce719e78e1923e5a181d5f0ecf561764922d11b43b3b897bcb097273b7b7fb" . + "453acdfc713dbe6cec7d12abf86e8e5be1b7696c888b4b149e9f8e570e4985d9" . + "8c01ae9878ce4ba0503f8b3528eaf396e45e3e66ec77936525693ff6ce4514fb" . + "aa2f2d951082fa39c07fde899dc4a812e41771db0b26a46328dd9e98041a1ec5" . + "3d8d9747b7402bb957f82046cc7a44908ed40ba8532ea17d3bc9ff716a924697" . + "782211f570487cbcc9681f9884205f3a2ccf21cbb96737d72b65c4b08a15e5f8" . + "a0fa836238134d6dc8e6978ca63b9201a2c56acb5aef9e3a16f98c3ec161bef4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "88de6288a2db69f94874634d10ff82fb31d3ca710e37190c80326602bd864fdd" . + "1640ba09b1e044938f190a9b37325e5c610c9d1ef57d74fb07f95af34d35b38a" . + "562a00a0bbeb0968eba4ce01d660409073d3017893540fc6e0060b98ab189306" . + "91bee9e68f5990d1f71f30676aeb77ff0ab30aa8990f1a039b5a9a2e2695ac3d" . + "35d3edc5dd911e1b73b2c40b04c727093014a43d292154f284b7656640083f93" . + "2583f4e41fb5a9107e112912a2d5a747d408cfb82f7d4f8e2389333188076c39" . + "3ea75b7462c9bfbbdaab115cff75ab0152ba410eca98473fe2cb14bd1deea665" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "a15bf491caff99beae8736a9029424e5c1bb0bd76b8d4bd0a3464ef411957e7b" . + "bdb49bf2e149617a2752023fdd113804078db98ac21c2ad50fc9f305e0bdb9b3" . + "f89072e789198119af60f67da4496b6b7d6e5c1a733583e989ea9d4d2cc14c70" . + "4ab030f3fa60582dcb2b1c0c3ea29f8817f76bf762e3b89a9f0bf4f3f8cb80bd" . + . + "6ba3d48fcd12d4342fbc4d0edfc8981375ae9efb509e6772bd99df4b9d90357c" . + "e84c67744c8eec8e209a9d0c8f250d43eb6382f50e6db79bf69096f852c53de1" . + "47ffe97c9e345a52abb453e524c91eeef3cea3407d85f7ae6dc6cf847e1910e8" . + "92c28fbfb617f8be48835b67ff75cde2dec058dc6d784121c0732fd5e0f7bff4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d1c38b3b0ff90a832896a8e701a6064836193d5938fb0e28dc7763d66f1d9587" . + "febf73b58a5a04ca7f4bddcdd9a5bde7d8a830722e0a64c448519d3f6b8d4a07" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "dfaa7dd35d1cf42286d1d5eb4da9e3497abe6e5381bba2f35bc4b7c8d1b93ce1" . + "ef448e6823b7753fcc2e02ac9206fe1ad29a093cc0c4c3581f7dd23b4faacec3" . + "3faa8342d656e3a634ca48faef446b16710a3d26dba80bbff61728c689bf2c0b" . + "04d6b921f13748639c1724dafb5975d9bde295da94e631977582eeb6bf6ea646" . + "0953e0fac226118d0618d4c21e184706ef9c7ed38d50efd9e3c98616b87eb681" . + "4d6dd5ddb42590dc40e2fa7e882d654114d42b647d248aa6543fe937398e126a" . + "de96851d930ce3c6e41396aedf4cf7e12ded4188b94859a7ebcd580de71516fe" . + "c0de269feca2aa61a4714e2e693153c42dba2e5fd3a484158f3c9da48dace23f" . + "d5d2cade8f171ceb9b0a0d89d3673322040e0dbf728f9e8f14bd1b4cf579c4c8" . + "68aaa479c64829013ae226ec1af8cf9aa20277ef5001b8095b67caacf21ea24d" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "c13780a013e15c6206eb35ae979511c80edf1cd1f9e3b8fb97bc4862c9a0b2fa" . + "e3bfedacc95354e9c25485252a4042156e13c4012a95b8ced388b10c176b9ed9" . + "990d3f8783ed6c6178578e3a14305e873c20cb058731c6d940653430eb3bc94e" . + "1cdc8110f87154dcc5d28ce9f98f67a1f0406774b01a0d3acb736fa8480a3119" . + "0261609f6d1d52070f40c7f838c253a622c6033a2722aab782923917321a8893" . + "49d6fcc0ccd21c12ac9cc801558eaf4099c6ba2049538f0daaf27d012498dc5e" . + "9528014bc2c8cc2e0657ba10657f517994c168b6593f75615390526dd04e59e6" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "8242121bddc577fbf05ce6da402935a726e3d0ae8cd0b00e04f27446233a6f3e" . + "557641b28e5a331d6e85a10eedd1278bc9a61b7cbf65846bbd6f7d3de9f0307b" . + "594a2dc9bcfc327fb74c5ff329debe77fcc2464c7d2a9bbc2f94b2656f46c4be" . + "bd4f3b315b8e7f0f0fd2cd2486b1b67004d8f12133141b6ee1f21c4a8f474ca0" . + . + . + "116a6a0bb39d449c1cef943cf242b58e61cf82d204abfe12421ec2f59d1c18a0" . + "c36c283bca66af4de2dba4aca657738305c44e23904dd3bea5fb631a2028687e" . + "3bbe71f60356e7c417862638372c0b76c0d874e11c77dec4cbfbd86803d97eff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b76c61a5e32e40a3896d5a057633c505d3629aa03e321470711d26a9005b0bde" . + "d7dc453648decdf3e5ba6703e35d437242ded1694d08ed48f9ab7c6e3f3783fc" . + "b190b6e87f035d5bd8406daa2b814882997d9226f511df963fa3ce11531629d5" . + "54304f296feca0a283e2b607f2d520ab0d9588d7794c92c473f1be81f2e48161" . + "0f7ada96bdbd661dd4eb58566ad084ced3ce2934a0f05e88781e15037dc47fdf" . + "7512553260de527f1977e288285a730e4fd705b818d4963e4f9b0a3310910407" . + "eee6b0773d735976c9e6d6c19e8e1a418c682cf5d4fae7229b733bf4b536b17e" . + "ccfcc87746df68eefca30ae2d1a2f9cc9fb800c8ccabe49ef46817771107554e" . + "0de800e873efb4dfd9db394d6186e9d478b3560a9c8e050b3008ff1eb53fe46a" . + "d7de19ecfc0cebea726a657821ba419c517df0726b95c60ed913ecc3e559cc05" . + "6ee162c472441fa6ffb4010f21af458df7cebc11b8e26f71ea2e8bcfb96f4bba" . + "807f156924cf43d023d35ae8b50ef6c7ca6c42ad0504f8ec4b4de2d770c33fbe" . + "1f30ef90ad7c346c4b4e89ab21166f18ec509dc874c21a7e95745d9725e65361" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "f9ac7385683b4f21dc21de6fb61504221c87ec6078f71179833c4fd4e2e9773d" . + "d93c38cc0ef620ccc2235193143ceb0dfff5568cb0e02a9652131c91bc5f679a" . + "cd25321611ca4ef465a5f03332c84d45cf334df8bda3583aa93c6058ed8d69fc" . + "0b70536cfe9dc86b6cdf0402abf0a715bbfdf85b241c549d583a72c8e2d54b3e" . + "fd13ed88d5a558550bed8cd17d454fb938522228937f0f82daf9323981bcfb34" . + "33ef2714bc423f1b26d4caf6465a05fe63295cb7f55d050a388a98888b850d38" . + "4af974d23b9a66fb480846ea18e9fa778ba8c1acb7439bbd1d6131d0ce9c49ca" . + "761cef156a6660144d8baecf93fded2afffee49b1fb026e6b3f889fd49976765" . + "a2a5429d9e38bf4009e6d8685f65ae4cf4ed6ea90cc3e88d7bb57f6ab8ab6eef" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "676a8790204bf74db030d65daae66afd4d04d7bd315749ffecedb75abdfa71bf" . + "1b289a3456d98d8f824075aade7b47e528da0ebc78bc7a30a5ed58dbea29d8c2" . + "57e476262d6a5e92c2cdd09b246cc1d013da4fc731efb1ba18f5a9db3832c8bd" . + "3300866e7cf632375aba746630824088e938bd6dd3b78c033c07e8123de9cb46" . + "cc69b6849b9835bb264ce2ec00d92b97f5b09a98fcf7417e5dd4973f6ef93f8d" . + "bfd6ee09752cd445904ee5868d5f1e255267fb1217c0be8d251376ba9f8302ba" . + "fe4065160205e617317ce317a86b044ca4476471b4c4ad912e5ec30604a42b70" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d1be9528556939968d33000c7ef6de60da2aeed0936dfa2129c794cd5fab9d60" . + "fd687f60d404e167c15d0858f12a3cafa0f8955e379e2cf9e80cf33cced8dc12" . + "88ec9634a7a54b17a7e612b852fe8bfc60932f621b3923e5bb576d61136467fc" . + "76524a9696514ce5849fa1e125e2c89d3edfc5d9aa21b8472528965c39da4977" . + "b53b57575f1f3fd87cd911cfcae3a68fc7d474044d306b98cdf619ab5a979906" . + "31f68619b16ee4dfa407fbc76067caca601906e6be9f046dc26f2b5dca51c1fb" . + "83a9d7b3e9c4402766ca1f1d718f4cf3d38137c5a3fab9646903ba91709cd9c6" . + "7bb06ada799412e99c1ea65224cd37cb80ef9535ceba9c25c92c39befddc593e" . + "cb44352da8077fd3dd65e413930181d6a85c1a315f433520b66cd40b14630ecf" . + "5159a36b016a4c697af3ea3bed02e8afb1cf99cab38788b254b761b2479de702" . + "5becc972549dd99a33ed3cbeddd993b3466eab595ca48c52d1cf38745e9c34c9" . + "6abce01aa4930c442726761fe290b391c2b447d614f99f9f18743bfd99d7854d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f0080b6ec8c5fd13b94bf02b68083cc13211a4a1469a645990fdfce2f445a613" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "9c8c7de272e7e9acedee8115eead5289786f995b22416449ecfbfdb47cf612d3" . + "8d83af47468813e862001faf8f92360705666baafa9de0af6f231008eee091f6" . + "1b8ff04f8e825dbe657dcbeb4dbcd09e02b5b604eed667a5e72f02e2abf34778" . + "3242fa7d07b2ded4e703f09455475f4f5a89ee685f63768ac67eb4d1a4666cb8" . + "91c746fd8dd077fda86661912259b1252a2fed99df85e115b90e82fb799ea21e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "f9792a69f1b77f0a6ddc69cb398d0ffea4e4a3f10a399f2d2574bf7050f86299" . + "b43ed8392003ef4531abd4f0e584e020932e859c104efed3b000aa85255db6d0" . + "9429a124933dd7b20fd9f88474afda11067c580ddfbb38b286573859a3e17a52" . + "f039000993cc05fea6752e906fd88782dbb9c1da5675686359303918a26d32a2" . + . + . + . + . + . + . + . + "6c40ebf558c97a6407504ecb83972f1b04dbd6c076eb112f000bdb275b6c216d" . + "55298c30d98b3be54f29d7208d5031d72a07fe3312902aaacad542b6c862e4dd" . + "304d5f905a0495e9008776f8e75a9f0320910e58d3e94c75143e650b2f3f619c" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "644c9268e7a26edaeed128a2fa2b02ecf5d4c2a7eb10531828943c2b7ff3048e" . + "6a7153e352452d9fea0716af42959ef77a9171b02b98af48b76c0ba9a49a4c10" . + "7e8d93f5d503601f017d71ed9b57cd18595153def1a59e6884294c2c0afc1007" . + "ef66dfa1dd37640f8ad01eff9ed4e59369a9f09efbb01955b00605ae60f8f3d9" . + "6465e10dd2fe75efa1ae0c1e72aa5365cc311bc6a83004136f8dfa9b917973e4" . + "1d1fb325589261a956e8645d5ec8e87c9412de8206a4953416cb7c7ba204ba99" . + "008018e3341a6296f9ec9100c6a2e7e025910fc660c2f1aa362321f5c316349f" . + "a938c52505010cd100d0ab474d86554c0bd7a97db9117ea45e9d26b494f44c01" . + "2fbc30268b498cda26bc2c6af1292ac74df156dfdcc4629d89b4e401ac656efd" . + "5061cbd09e6c7788df7470d3a1d589f49a9ec0825e75b4880701fd04d47c48cf" . + "6172f0d6cd98430d8d48d843d0148aa955ebfc35c277929018e2b0bab9437205" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "99ac69d9718ff46f99d801d3f65d9fc161bf51c4e26584f7e223bf933aa488da" . + "e2935f0518dcd9c3381f9a04e5e4a83dbaa54dd50ebd7140f41550580c213a81" . + "6f3079b55c6560ad92a7626dc715d14de1350a032a09d12f87807ecd3c4df41c" . + "2f91ce7acd3859095b92f3ad28c7e9bcc3b14c792f45e11985a32e7b5fe68698" . + "9021fdcd33ffb1379e72048bebbe107b17ac161a99136e3b502db0d7b947b1bd" . + "787ebd7fa98c7e22219000ed6eb7d0be05f9efef5903b8e060728251cd670602" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "245c98f8860185812e069b341e46a20ff5c603b0a3b602dc790baa9f2c14fcf7" . + "bdfee344cc42a26cc6fbfe649a2d6290ed64a5ffc610789042ef1ee7710dbcf8" . + "17b92a1db208a45b4f9d06dc3da3cbd74025cbe92ab8e3e826244fca9f7d8a8b" . + "3307833424b98d4f253916f98dac728881976092f60dcdbe768dab52918fc9d4" . + "1338a60ef042f1a5a2374602ffee9a0901facb55943fe6bc27382ce5a989632b" . + "05f31f1c8f6f86c54bed654829b3bd3f1099fd1a499dfd830d9d0cd32da437af" . + "5615fbbd3f75077ca4da2786a794bd18d1fa3a58daf06ada11e7dc689fdd75a5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ff00d2e60a576d8d2962aad46713b842cdd5202d361e423559a0d4298ba5f418" . + "a2850225d7f6b258dfb6a8c645f47c0a484751f2b0d0627b6a7d489a0023bcca" . + "1512b655c585bf9e844ffbe620da30e4189e9db710a745030c1daf7007c12bfa" . + "9a5ef7382db5c485a8dc5acbad6076f12767c3b697a2b4738bad145c735d6e71" . + "83b273fe40dcc72fe403459371f8eb422f5ddf0cb46390c53726e6eb115ee2c7" . + "fd289b6d2d343a60aaf25d7fa26c99afd8e9f54eb5887d98a62719b52941032b" . + "ee14d42d0039d2c34972796df35242dd0bec72ab37bc7efa8861268fcb0f5236" . + "56e2cb4baadc2577ed832ac7b87822c9aac9aecadf9a4c2dd4689c07dc8855c0" . + "85daae6571888dd9e4d36be9ea850cbdac64d72e2b57b2ff7237325184b6cf34" . + "52591e2c9be9b1441d1457e94936a815792bd1617232d64705b126a1ff6238ae" . + "dca36595270a5ff901eaba6780c2e1963cd829f705704cbdc2225e384140a681" . + "b0356bf7038fdc3306291768131483c049d1f5d3aecbc663e307f3ab31be9718" . + "5c20abbd8c56cfa9a76ab6f93ef9e41eefdafa386e3bb9389af65a0132116e8d" . + "37fed299cb62b33fd1d52f836eec0079ed09dbb366f9889afb66c9c4526f2697" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "e816b3572800ba9e88b3729d9eaeaec40feb803611ebc0e4e47a35036df0d2d2" . + "47f5a2930c860dcf43965bd76864b6d728d7cecd1d782a20ccb2de4c143774ac" . + "7af53edbfdc1ce4c074b75619c865e01fd35f92dc91540540682a82b525275ff" . + "4c97d995a8ca9227724cb2d7aae0beeb90a5a6805c2934992b9d9667562ee650" . + "0f416c10b4b958dadb7b1827b05fc668ae5e57793f881c2b8df76af7f1a3d272" . + "036c715cccb3fcba1cfcfd8c5e471b03f03098e92900e942e03c88f590cf424d" . + "e150f0bcf8072226f3983169b776d9c26ea3f704d14fe31dfdafc8052740e98b" . + "5f60efae042640f8193dabea055a2cd7dd47ad00cfb1ce8e4fe24fc7b8290bff" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "92da3d5c37308d64dc3fa8d4ffa3c6925f700e44c9ee153c3e0797c6128cb6cb" . + "0ef1c5898f63f2e8b5ad59317c0b3dd71985c0b7a87e1785856f1a692a28fbea" . + "c759b624f13fb436160b8f1096bfb4f687cc00f94430de2aa9f0a67a276eebf3" . + "ef31a8a6e3d4a684d1272a5ee8c1af1a6beba1eda12d1048ba5e6af92a75c0ab" . + "5bfb0d6d8edc6c605ee3b47d7b928f74d92b0dca05d454949c78c6199f33d133" . + "484bc41e3dc80a104e87e51db34190c79f380467c9d8f77810e507b5c3a25601" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "afb881307d79b122dc3b63ca47324081537ead75ad8f2bb3431416581bbfead2" . + "9786ef8ed0b4a17d5306df3f77a69d120586a74811e03a6af62b5572e4ff3683" . + "37e430462e33b498a4b08311ef6ce6525b07c7fbdb71c164734a13b644a85682" . + "2cfb9916cf77a0f03c3e2473503f7ba15a5d987187840a8bd6304300397ac66d" . + "83ed127bdd9a0ebdedeb111cc0a29d20b6a878c0cbd4761d97b6500dc9e80982" . + "20e10d4409b83723cdae6d26f0367ae5252c5a510bd3bf8908ff9ac01926a628" . + "a348ae1431130d4d8734d7565582b2218261782e7e2389f8716dc81f09b18571" . + "fdb4dd06f8b59b1eeed702bc983b955c2cb32ade870db4b656d261c57fe56b39" . + "a4df6e0d3f858528a19b1b172b851a6b3dd7868346713609afca4cbc65c142e7" . + "df5d047e17a9da0ab3df4ba7513372879ae2df798a160e55f5eefeb2f9d74f3c" . + "6166a4241980d6e6c1204c58236adbd6dfb6cd035fc531c7257b755279818538" . + "44621ef1355d93198db7f23c4b926ed15f3188e9687cd92c3b6f81aa7e38bb4c" . + "f87bb7319e9bdaaf08f89cc8fc2385273b3f995cdf9217a9bb62c2aa47b4a28f" . + "3a6ab50661157c909843cf226150f899e1c9c846515ff80ed4d36c06a8f994b5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "80da534c4b5803c1e5c49f5ed0ef6ebf31e61dffa766106e95ee27bb85d038fa" . + "4ba1a5912d8176cd20715d390675f76524df2193348e2b9562f83fb0a4619042" . + "782041afa525eda337add7e9910f8ba4ab0dc717eb7c7013151bc56ce30f3719" . + "b653c8d98ec6903a91f32b54a37db3ca5079ff793144d99390fe60cd24d4ad05" . + "0aeb7d75855d540b8b0d08176941b67f302f4957acb3303a3663963e7d9524d2" . + "a489cadf7be518ff64b9168babba8670b279dca64ce59ac9011782388ca24721" . + "8ddb3cf0319fe46f23907e1fde6778eb0b4a484a965c9004f7bbbd25ceadf4f4" . + "5ac37f2669e5bf4e02a22c42b8a613a43d6321d168d608994067fe283d4125df" . + "25d98300d7d56e9b6909f4d245fd0705bd7a0eb58b3e87e52d02b3d5fa69e4da" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "d6bd39c0120fe0f6413f67ba573c2f2646ec5fac437111d4eb22f9b60e6fb27e" . + "a7e1c6ea13722322b897909ee7ef06cccee0dca5226e4cd1378a427dcc1e6dba" . + "2a32631b0ee9103a1288ac279d597837beff6c51b219c71da6db5a569cae1065" . + "599ac20888db63fbdffeac630eb7c2d8c79e44370a330bf2035cf25c5f378eaa" . + "3184c21227385fd2dc7a6cccfd24a2d41d1e9c581aee0a4407120caeb150f4c6" . + "81b8c711caedcb0db7059b1c8a63350e41f05fbf9a55fdd9896e9095fcc287bd" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b5f25f223ab1fda53dbf034aa95a76e71e2e96c56d43e0a3d91b010202c84c73" . + "f0f8a6659bf28418fdc3e2802c4c46ec6ec74ccb1e34791da14a9258501bc09c" . + "b41adcace24346d40e3cbc0ce6248e9bac73a8922b359d97fa1367b5384f0e81" . + "1812a1c6823a196697cd2a1741915ed2afcc2fd43cfd51217e895fe66656b71d" . + "e6e24cbad537135c4caa16ac9ceedeb75ea772d5c28b5f2b9f7a3fd0491d88bd" . + "fa70d27c385a0beb1c6ecc64c4e1e18f53934a16e87b4e639a32e461d0a6a4de" . + "d475177e782af1286376c26165d7ea65688ec1e3d0b680a1d3df4af77edccb77" . + "148b5536888cb0ed4b91a0b2c1c7949c49133484878746f0e6fbe5a1c48f73bd" . + "5c66fa2cc8b2acce83fba9cc7a507e94a27f588611f6d29283a9c788eacf036f" . + "bbad82acaa82dd017646f197b5169dde8d8472d8973ea3c4f65b9f3ccab07840" . + "ee1b827f624087ba234b9c656e11f6f4c48010697c901473b956a7f02f3a06aa" . + "cf6f5143cd4eebf6d548dd0df744be8323e64235d502c3569b3da22f5d2cb653" . + "dd79f0ec1af87e40e488691a5fe1c37505c4469adeefde8cebda9dabf5314ab8" . + "6d3e9cd32e271c56f1dcb4999e7b99b26e4a8ba4ba7ee7e81f19fd15246f1950" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "21f47be103aeec551fde540bcf63180165519c11983dc6d72897d9c5243524a7" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "6bf1d6430960b5f1395bad95e04d6e7c485f68ab44d2dacc318d7801cb5f626d" . + "d71c13e6ab72d6a4bcfbe3c007d0baa1e6fc859336a74a602eaa9ba8493d482e" . + "bd426bd5800e4c7d9079ecc70d9df1f4439a1e00281a286f726ed51e7878d7d2" . + "68a2d63bec218f272aa26c949c6a57f81b4fce2e2f53b19e1afe9e53426b8304" . + "d43b1b3a07a16f47003d87324e4985272fcdde1baece334dfb41e8dba09afb03" . + "0f94ad6c63a736281571d8b35e518e3e4816e46e9a89238e2cf4152b1698425b" . + "65e51c793b5abed6a543d71fe059d19ed53fcffa1599d4f2ac49bd6185e8bf93" . + "34db0b8cc0d61cbb35a4b0f94c67bcc84a66756250559c0d449d19539d8dae9c" . + "8ca21566686677767fdfa75b0c43697aff8e490ee5ca659f88123f9bb159f4d7" . + "9f02b09d03a7e83b02aa3416dc5ad0ce96cceb34afaf07adf55f47baec1b22da" . + "545bc7cc83ac2907ea56c5970d487602015759be84474ba58ef07bd549fcd0ae" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "c55cf94dc8889cbed819272bd06d377db382fd5a593ea0dd3002cf1890d0cf0c" . + "7f525ab3e7b839eaa4ffddc92d78b1a9e2e4f2a39ea92f69dcbba290e0e0794a" . + "8e44cfaa19551211cd4eff6cae9d0af0804a81f5069c7bd665e5b1d110802e2e" . + "a9790d5292228118ef48d781fd01893203b46e9c3ad61426f39fa944d1bd8b92" . + "b58fc41f97a055efdf857cadefcc868991e339a93c21a8976359421b37a2d03d" . + "0ac070a7a67f342867e6a510705d7fd4ad0b880d853a959b339f339252f62f90" . + "60b5a8e544653be6ac8b6e3ce998d825f1a5bc4b197a569007c3bc0c97d05322" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9cd7285091a57bf3ab21219fefed789ca0d03de9526bc25d5f391cafdae58e08" . + "fa26eaa071642c51fe5dd4077bc1a6e07c8e98abbf82b18e2dedc9bb798a61d4" . + "2db6d9554d7707c5ccfaf9c977d9925417dd52c20839c270698e589998040049" . + "1c78b566ff6988daf940ae820d9403b35c48aac30a46eabd90f6cec2a56348f4" . + "7495539cc82245f0773919a4c18b41133b76a033f8be01a110aae3636da0e375" . + "cef40aeaee5fc930b89717e475f8e8f6f2c9e8dd3a1b75bf72e7b8f5817b1392" . + "5faf422f549eb90d271cca71b3421c494011dabb967421d6967a7d6122c2d59f" . + "e7b729e61d2a3537c3ea5b28db550eb6fe15ae739d52f839abdedee1701c76ee" . + "33ca9afa5d479fb8bcc1a465c590eac1500f8b29c0021672603231d1f0a139c7" . + "0e5109d93b859cbc7083829a084c40d48de2da6f57423564d1e3d0ccd4af78c1" . + "6b6ff36470ed7768a35658b49012c29621a80facc63773d2df8e5a70f91cbc3b" . + "83740f45bfc81479b7f5a29d07fb03932b801e1b849e1d36da25c1a7ce627a18" . + "a5a33e237669a16e7de269d8fc7711fc5a7be89019de31587f830835af00d589" . + "08aaca80d9ed6a3e8ac93a8eb9d0139511e2803ff2fb5ebc7516ae87e4b56dc3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "21b130398420b38a698e397a67dbd7489a4369d1f82b8fc40d5e6dd3166d6ddc" . + "b12416bfd9d19eb4fc2bdf218479e8da3376d182f516461dc1cfc212c579bc99" . + "523b053ee54dfaef9b0a3a3959f92e003a653c20134ba0dad09c1975903ecedc" . + "36e04b18d6833047c1040adf89521599bf42c9fd7c733be1a7425eeffb37a684" . + "474c446dd41e51f93115a2e4e979ac9f2b604faca604d409e88a6f403ef0fc89" . + "1782951783e56ca7823a5355979add352bcd62b6a1321aeffee19c2ee99a71d2" . + "75d0640fa28eff9479d0be1f0b5fb7a50c7b5b45d5a2bbb454b20f774e4696b2" . + "9d0a188f4cad070f6207d9d189f63d46a6d929b55df4f04aa7cd7d2fe6887cf6" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "773a410a0afd9901ef985e4dd0467341fc51587c4850df4a92eda009c6bbbcdf" . + "28a1a9511ffd71219672688ae7cd2850f0ca0e47abd0ceead31c00070d8460a3" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "40f718b49bb7ab9a826c331184b94b2298a8aee007b802d37e864c40107d82a2" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "ddbcf52271034453b49d85c3ecc66332e89dd2373f4dee22a48954df37480066" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "941579ccc4b7d7dd425d35a307221428b8883867f2ba071b8f9f22b4e1b956a8" . + "acb0ec1e7dcb62a34e7cbcde33482486c9185054877f0e23879e64a9c91a3292" . + "6a7153e352452d9fea0716af42959ef77a9171b02b98af48b76c0ba9a49a4c10" . + "b3fb1a095aa904a1f2b7f98510feb7e6153b7093b4d8c80291caacf4b618a193" . + "bcd12605ba108380b7791de28a1ee78fac49e6719d722622f0f62ac75bdc2f7c" . + "0a33432c4816de1492c1d1cb471cdc5029292beca8e5b0366b0522d1a457832b" . + "3bbe71f60356e7c417862638372c0b76c0d874e11c77dec4cbfbd86803d97eff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "64cc7ba65178de3e7cb02d63f2e3cb49d361f5e7c6b63c357ac473066abef0b3" . + "dd0baf14797ecd5ed004fe577241fa76c72765e54fcae2914b5c1f59cf392721" . + "eae0442e17b89fc05567496611debb81841a9550fe1d9d818552cffd30072f68" . + "c3e31069d2936c04bf08998c4081750b61e73cce8aa088ded7877f9124210505" . + "133690202181298f6a2d10f2221f1fb47593df266c3c17b92a588bd539c40628" . + "1cc2a58f8bbd591c824907c4999aa2841e65968bb5b0de5e657ae526fc0b8f32" . + "d08a269a90403a056cce128a73f9736c786ca5028c823916ec7a52127ca8ab52" . + "f7e07adec82f9aa02752aa06d3ef1f5dfbe9e55405caaa018b44f50d751f3964" . + "e1e90fe5ebb1d321eabd8d410b64b23fdee0d2314b66b49e2eed35c1b8fa3a74" . + "c70964feb214226c42c0ac561502d3daa517256f0f813cdbfe289afcc9f93407" . + "bec10820478f465eb8f16d9d4d2db1aee11756774a351978aa0498e7a0881366" . + "4a3ca4fb640beb8ecbc239fd07a6e01df96b1a8dd56a98b95b2b0c13eaa2847a" . + "0b53199313146fdc908cc800e1de054689e2dec1fe2c7e943ced5ea2618e3f29" . + "d99b0b6299b51e87b9fa3de4718038fc470789ad90a23a4ccee6246d0e9b29e5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "438b9cc890b098f65b6c212fb580d53d436c2598ac4958cfd943f1b3c1562b89" . + "c318bff139dd9f9f3197c80443c4bfdc183abc852ce27af0c239d31e9a1fe37a" . + "ff32338d452848d6f1f3e29950f83b1e49d5b13ae2fc26c16f40b9d9f4b1c31e" . + "c9008979fba960fc4210aedf076652a4977dc538cff77534971bd64a9249fd7e" . + "b667d02441a8968a9acfee0f0947b416023063c2b40808ff04ecdd92f526386b" . + "a3189634eddf9ef95c7897d6c7f1d1ccdcdd8387ab7559b19ec25fdb129115be" . + "d2cb5db281f18a8180721810f2594e3637140a77ae76ac75a23c0789d66c4d86" . + "3d1d6110aeb53ac420d08dc9742cc6f1a56beee986e641bf8a6f1f9e5e75b060" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "fa103b2e56cd3955cf454afed3a810b05edaac1bb038ab203c78d138625b9c11" . + "b48fb1638b32bc4a8d32c26a77380c6b41471d33e0d35cac11ee8e6529074603" . + "2f8cb696e7b4c50b3dba54c7c0f297b7ab3605233d5e4c0f8a18fc24c755e9a7" . + "95fef341fffcdad725194dcb993b507bd81af2568859bc29468186c4f67d435e" . + "b1867f77ebeb25f0f186694dc32e6063e01e5bcd5d3137bd3a3929e85ae9c6bd" . + "09ad963a00b32bc5d167b76f62a8f2c54b0792fd40cc2059e5b7034bd65730cc" . + "82932ddce217e2199c3cd9ba126ab94c5a0bca7f820ad501ad2f39d4dd9d90cd" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5f1bfe2658a9af19b80456f91d0072e368b4e8de448d434ea9b45873a9729602" . + "5f1bfe2658a9af19b80456f91d0072e368b4e8de448d434ea9b45873a9729602" . + "55e10e2979c154a96633112dc80eb1225f656f9ed65ae502c6689543061c3152" . + "d128cfccb1220eb1041f92cbba96da2dd918ec39bc9234377c5660b65e484115" . + "59935d8abcbe4d560bfbe9e3e971fbedc6c86adc6f312c88f796d950ef02e388" . + "bac2894573690777c993ee84816d890c6e6da2c60fecc062a56028257d64b7a3" . + "e74d588ac964c5329d5366f5df0c80f5f27c2febe0321134aef27de43ddc33a2" . + "54258c1eeb944e06132de14c4df3787a7ae2ee753281ecc64b0e0beab86e63dd" . + "b20f64bdef37c2d28d9380cc157123ec141c05ad9f74d1bb6c4bf11206a967cd" . + "37a1449ebfcfbc097f7fb72a9ffea7ce82290453003f9f8c93cc7dc0bae3fe12" . + "c9d9f928027b4dead9cbb4f6cf0fb746ff4bbcfa1dbfadfa827e26f8cdb9b9b4" . + "227960a2d19607acf9246c3cc376930e75e99998ea92ff798a04eb5b54e00ecf" . + "cacc6bf0b5c2a800a36868416dc9924c71f74450c1edb57d9e8f161445346e32" . + "db7711dce477a9df0a54053381fdfb58e4b0afd7433a41e0847897d10cb235c7" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "db2d244bc90c6df8a094083992438802760d6a51266f099293158d0233f0f032" . + "5159a36b016a4c697af3ea3bed02e8afb1cf99cab38788b254b761b2479de702" . + "34db0b8cc0d61cbb35a4b0f94c67bcc84a66756250559c0d449d19539d8dae9c" . + "4589df39a360398fa6c79000947284e84e5c88982069a13abde36ac139a910f5" . + "f5423165acf8def8333060d5e6e44875a5adfb7f1a1198cbcd735c3c3bea2938" . + "2a7d2597d29f99e4c8cb04092a4b38d34d065775a288b3f271abc3828d163928" . + "47b4174c99f4953a1ca2a1616679a40a3522b8dc06ef2df3eff3070b8ac6bc2b" . + "ef28bb63b6d8e73908cd6229cb9eb9f19fb4a0aa46e6d05601d49f958efbd058" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "185c092c3369388cbb40d144082ba959cf479b7975e10532963f22fc676f029f" . + "8df18bc8f4dc8ee0802fdd7ba291f39b57cee9d3e1d35e1ce4fee85ebaf16956" . + "06552071ea6a5f8efa252ffa62545c82c4236d502e35a8b372ed6cac136b7f28" . + "7db3a15edc097f49a0a80bf5236993b86c684f50054bba9c92fc69145c92a872" . + "4e19e1966ebfb73ec13117d3357c7f8730df2611f2a16649e4667253d0533b77" . + "bf430e32ccb548de0303ca846fab3f68865db6ff5596897e1cca5b64d7aedc9e" . + "608585738998e6cd5755ca55074d66e8f61179a95af217a67c377adf5c7c001d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "297a6c3c24f7cad0b5bf322facb0f54232fa213c5880f59183ee35c8ad33066c" . + "7026d3a0d6a7150117129d36e4768dce491740936fa52b8b35badd6b07781f93" . + "edffb34810561c4e597762b62c415d7a41d8f0b2bf792f6ed9c3dff261c85800" . + "8e045dc8e65aa3e7dfc058b296ef49cf917d87be4a92635d2378c7d810695087" . + "c06e377fb48c201f1a8855652ecd7bc440d2756ded0231bf57ecaac1fef58d60" . + "1bd6c9ea2b093bf7a6f27684ef6aea112ee80bd79dec8f442fb91b4a9e8995f0" . + "81af0b902cd4e163537093be57ca5292988931b6c778e07730027fc0a05a4078" . + "7fe62fdfb62822fbf51e8aecd968217ec9bce5de093744942dd554dffed3859a" . + "59df2f479664e4dbab40bf105f45c4cadc1acab67495d58289036704e2584401" . + "bb4620c7d31bd927b61de2d26018c61ad1e4682392b76ed992532a0a205587fc" . + "29dbedebb01670c3aaffd1f8d3ba18af6d5ef047fc8eadeb9e294c4b0300af07" . + "e5cac86ed488eb97561676af2ff44a75fbac5e990be31df02df599426f487ae8" . + "50e2a0a8c5c02979cb6234b26d62234ff731dcf348bcb3197076b3917599e4d8" . + "06eb7504bf9869f2d7f2348dd5391a912b661ea51a06e0a6bf33a3512f8f8928" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "a6a7f345745d03f96da79a241e723526926a6066aaf702d13d8444b8a98145bd" . + "895e9f036cc3ddfe807af1544ae81b05e6cb9c280e566cd70b567eed1205f4d2" . + "c0a90a8d0bf985ad1d7c8f414a78acdb94df681fef0fed1a12e02eae4ceb6004" . + "4f54e10bdda5c31f9477850db4307b9b1e7a6f3b6faeada5acced56592fb20b8" . + "46e964806f8cf4c905ba6131756407a26f7783d8a18c6caf80a2af4541bdc431" . + "34ddcb9f4840b2705da40c86199e699a6d2c5cd17c21a684209b7244c4541ddb" . + "f957b16552eaa6940c300dcc045be4b6e34d7f8a2884c58b8d7ae95ccfcb341b" . + "e6134c8396e320eae3eb593b0055363dbe3b8007d868acefe7c7b0b21fa57d9c" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "7bd113be439037447be2b1c8da146b968ed78a63acffe5e7100b277552f8189d" . + "7c187808e8fe33786f5775653bd5becb3f6d26fb9780f0b8ae10b5418e4e0266" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "e0921e1910dbfe7c3c7bfa1ed4df3fc217a678177154bf2ba423c04f85dbedc3" . + "c4d7d9ae2d92ecce1c09bd8575f87125ce1959e55542a1c90ea9e34f447d8bc7" . + "cac8ba3273034712e6b5f1c1e8be0a684024531c8dc016a3bf76d1ef93d1ef64" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc9e41f58a8e46862db7a852e933f0ce0df7945b9523171b327a2e1ef04e98c3" . + "fc9e41f58a8e46862db7a852e933f0ce0df7945b9523171b327a2e1ef04e98c3" . + "2d960e5c1d4c01d169547374ae83d975e9212c5b23e64db0504f36c8367a7cb5" . + "2c7a21050e250f00d00977b0768e0b4893d23ab95b03af7339de6288027bc087" . + "8ae642206bfcc0b39672270b12c3116a5d16447d072e669127a98cc0b072048b" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "18f7b8e3a5e453cd3ce5d6f51dd51443002b1955198b2b2d9f44790dbdb610ed" . + "34e66b6d420382986ea0d544837f1c9d61d502abbf3a66e2c10a69b7e35dcdbf" . + "7496d183a232ef7dbf504481521aa5117599f5400a71a67686dce0effe10f04e" . + "e7b97a0a1059cc8fcf2b977fc7dc89ef7a5269f636fde84fbbdd3b47dec97c4d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "212cd8730f6e9186f01e96148b884b356b1056dc0a1a1062ebf2eac573f543b1" . + "f3c7c8f95829514ca00d2e0410deed55f6b203c309c5113c4c473e82dc650e34" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "20af2e875c28723044f78edfc66b46c5ce4b90370184af522992d3ff0ef7281f" . + "2b55347c3cd7cb3b2eefff443167852e8827c140a211f315a729acaa2dbe96f1" . + "69a2077960df86512555e22aef48d93174665e73d9e49f7cc077347ab7a9407d" . + "e0862bcdd1381bc01820ab8e34c796b7abd5d6fbeae40025351a3df3db478b95" . + "33a302a28801e12eceb4fe287d1c6254863f356e803da0c6e35c8e6ce26ee0db" . + "1b3291d4f8faa4b4c4a8535350996c0ce1a5a3b5c7f32f29fcc9b6edc5f44f3e" . + "66425ff80138771c2aa5a598c4e86dce73ee3c5484eb447deaa2fca8a3cc54ae" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "38be3f699892dbcb020144acff33cf3e2a3e9e069a87e87b68f063010c662812" . + "38be3f699892dbcb020144acff33cf3e2a3e9e069a87e87b68f063010c662812" . + "f2cb357af24c13ff8bcb8197b4dcbef4c666c706418a80aa5dd68159e9157e6f" . + "7e739e2270711a0974602f1315d55bfea779b24d2c6f10131b5d9526ddd7ed6f" . + "e127369c6bd9a47ed99b32fb70fc7336bb7bbf67a3f6f7f4628e417a63dcb528" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "164634ecac853e53433a13d998afd28f5528aab4d35636043903336bf652c6b0" . + "a3189634eddf9ef95c7897d6c7f1d1ccdcdd8387ab7559b19ec25fdb129115be" . + "3bd440c5c275b390315ff99235f1a7545c25a6440e82ab0060c9c4ce3bdd6df9" . + "2b4d953599560200152d2781811ce5398e9e47562da45abb297cbf7aa7b22868" . + "5977a27c96e03559669f185f4c0ad37d1afec4c7d61cd0f9f321955d2c901a3c" . + "8e5c075bdc5c6281167ed5ba4437aed08e63f93c5955de6c681ca0e0f5eb3a60" . + "30bccca567f212ef1267cf03319178ad7f62a9663971b81d7bde6cbd415cddd6" . + "decdbfaf0a6893f5a6e8e5a0efcbbaa1eddd8964a1ff98411574cf244fa49d46" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c5d375681fa3c040c4643f3e3524792a9f30e7ce3dfed7eee118e1ad56e90c89" . + "d8371ec58bcce6e170f6d97b60df9a0eaefd4c4f23a4e1043f8e0add58787224" . + "e4bdba72315a8dec65e5449929f0ac233e804bac1d459ddab0f84cecbc3a67b2" . + "fe744eb8cf8f1ec8c948437f9b63a569bc3a7a34585161daf667b630e498d559" . + "0c227ba5e5ca4d328935010dcae924aba32648a03508268b1f25cb5a4f7a4f2b" . + "ce660660fca04b6d22cbddc4737a1606a1905ce187a812a68029e42db29133e3" . + "5a908f1a0b0755d62450c12579451399462779d8158de50148f1495edff021dc" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "41d306f92facd1bff714fa76439c7204747ca39ca7745bee751c19429957ae6e" . + "5308e14a06df78ada56c12ba8585a42fa37883557294daab60c065b7ea0ec003" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "12778af8c8ccddd423e6aedf916b1f79eac87cba3cac76008ccacc38e6a00485" . + "aa1868d41346884881ecd8676b18e0b8bc298c67c89bd783f33f3ccb2c282bee" . + "60c3855c8b3b374e6148bd6e4a288128a4659180b936ede4d5c80e56b20c9900" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "25c2049123bbc8eaf3a5de5a61b288e7a4e71a1c6f3883bb0a4d89430d24545e" . + "25c2049123bbc8eaf3a5de5a61b288e7a4e71a1c6f3883bb0a4d89430d24545e" . + "e9050fdba47ffeb9dacfe7692af10ebb29bf689aac1b19acdbfbf2c5269437ea" . + "068b7256c0c235aaedf02a6a69d1855ba71d91976fc2afff1f6810b800af8399" . + "0fd67a29f9a5737851be8d3cbe89affc3564ae5e561383f0d66573f1ba2927e7" . + "891de1e7e6593a29bd12eac81ebaa538d1c4b85adcbc5121d9143920906155ec" . + "f359386053921d21ee70cd808c83d1d7a5aad10c1c2565baa0e1a93794566bb5" . + "26b50cc86c6d7278ab7287b7c1ac480a27a02fe731ae6c633fcbf2465e8ab943" . + "23149b0ab12a94462f656f8b0de8326d783a251c41c73b090b6b21054951fd02" . + "cd6b385bdc0a4cee3ab0cd1e2aa129c1ba4e7422c0f7da447e1c34e65f103e98" . + "880f6f473dc4cf36ffc6f37020e27d636dcee6baba3ccca104bc1ed11a202011" . + "5ec7d911715623d17d1d06c6393bf03fed29c2e2c09d5634ad80025567fb6f89" . + "efed1a21e5556b661d108fc6bb7be6eca772096cfe0d8536c1830abbd571272c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "31132b93853c5ee27ae123de3c2e4b115b08131fa29ff00634e020e0aabe579b" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "e7c80892af9c077174ac2117a19573408264ded4f355471b63a740834c281494" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "9895602219748947777666742f04cf874eaf312edc8b64f6c8ea7b86294e398e" . + "84e98ef8a90e5f6fecca6765354b588feb6d254704a9c8b3ae13caf22d6be29d" . + "91c746fd8dd077fda86661912259b1252a2fed99df85e115b90e82fb799ea21e" . + "70f97819665326d391ce6f78088df980d361e0ca2daa58cb494fa751ac87aae3" . + "5527076394969e96497c24a8797d56a54269648c73a6ebc1f17dfb782f3ba93e" . + "1cc20bdbd9a1044094ad8cd627cc9b9fab729b71e29f6f8b1e240a7122f69798" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c661b0a9b297cef4e1f2d32ddf1e70bcb28a5a1414a099ac5fb49e32139a928a" . + "6804fa9f19f5eb4e0ed2bf9ee8414fbc19dd1b127ce74a059d08a8590b129fd1" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "112ebbe930d8923b57cfdd2c649aa194a403ca6db0561c7d4bf69452cc4a4e20" . + "0d4bd8a883b460754fc5a859c84a3b1a2710d69d3fb2d63769fa69f750579c16" . + "5e2c2d380dbff2090abc09db12defdf50329004652b3adc8a91465aefe447dac" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0a059ab7b5028e0808fec67592028c616e62c118a3f91712291f9f886ea5081" . + "f0a059ab7b5028e0808fec67592028c616e62c118a3f91712291f9f886ea5081" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "d9a00dfef926c70c4fa4cd08b9affa600709dc84fb7b0319c72e3be09886c853" . + "dd4c9c4bb71d0fa25ab1796c6958f244e48e49843fc1d1509ecb840beb046f72" . + "810b6329adfa7cea1bc7bf25baeedbcf56e26b762e3fff8045bf11276dd35325" . + "0bf6b4419c2d6b088819762e35837655dc78cac2adacb16575d3d3d43e9ee17d" . + "f016b2de58f2804599bb0764c6f15f788c07324b51047dfba261c6b96dc0c950" . + "ab6e98004afe4ef00b9ca5ccf231313c66ecb5624a00bd251ce22610400a4896" . + "f527932df74c5284bfc0a6a657ebb5ba9e8a24140d8c8203f47ba4599f3772d9" . + "26951f3eb70e0b7d21479dbf544d67f34db08fb17512f699e3f7f8c35c455c47" . + "6241ac5498346be751ccfac3e2de59b387393b21b8146bce7123f92ca0c63529" . + "e4071062f8b821b43e2ba1df706a73beb977a206c47a8bd7fc4eaa8b512051f3" . + "5df983452fd9be3f66b8f9f69b4f0af496756676832c3029caaedbfa0cc40fcf" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "21f47be103aeec551fde540bcf63180165519c11983dc6d72897d9c5243524a7" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "3f06f8371c5f37940154fe1d40c01c49f5daa7e1a6a506094a2393cf15819e2b" . + "b93702a9a564dad3d7aac841bf73cac61b87053fe7b82973d7371f8baae71b35" . + "2c2b6e67532b6d20a72e61a88226756af27f1e7b409f8bec04cd7fde9c058791" . + "46812c85636210c0065c8f25870da675eb9983abf163bac03dd18269c85197f4" . + "c3c1b1cb83265f12c78123c02a49c8898371b35ad532abe7f7acaafdea45c973" . + "e7f5cc45c2b84a350e3c3855fb132d51b8a2be191d7e03644013fa7ea2da3167" . + "4c391a7bb31da2f91165c11c46a229de1ed46a7629864b653f431eb1b9c2b77c" . + "d038c3332970d6c450fdbc9c66c34e0657dd53b0f72d3ca75eec6e5a35f421e4" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "dc49b5ccb6644fbd14dd462a0944f19dafa8785595fd696871eecce92511cd63" . + "c71d293d5760eccd569eb3ee81035b5035367357ca55b8382790c8e0e3710f7c" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "bf4ff78b10880659ef94195ab9a6972c5146a9a52c8be2158bc9ad57cce002da" . + "07faee744f0a80567cf8c7e1b9bc156049b6efd587322a9600e24551a52c2530" . + "5c79e701addb4270e8111aeba5cb0350107cb93b736208f3fe6bfbbe5a0d6c39" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1eae9dabf62c746c53d8ee995f2efcfd12bfc3614b44b13607d9768e22777514" . + "1eae9dabf62c746c53d8ee995f2efcfd12bfc3614b44b13607d9768e22777514" . + "18af155413776f483a491c6deda34523126b33c7a41f3d6edbf16c8f57a149d7" . + "3be698bc5d9de9c28b5ff3f3b4f325d45a0fa8ff0614329f3196575d01f14ad1" . + "84a55695bdd44a26a6bc4ea0f318edde04f8f11032c28a0d4c0d82c72e0a12d7" . + "b1c9944b19d632e255522ed5bbf4101490051ea0dc78ee460fb7627c85cc9611" . + "b6884fdc1da98b5a248cdf327ac6b67b5ea1b34f445b8288036093bbd8ee71a5" . + "19e2e65707a093820ab02a7f5912c262ebd5f0959ee3f292af93bbc6b04e0f90" . + "a17e52e177ef7923adc42e5ef116ea9a30b29f5b251882dc739c5d0475a9e73a" . + "4b121913f7d2756b31584dd4c458ced6effadb91321d4bee12a0ac365af57229" . + "e670592b0620fb68cc934df7be7356d6f20d0ac362a4b1cb164caa77f64fa895" . + "bc648229db2273f17a196444016c9f579f8841009cbf384fe3bef29390796f0a" . + "f05e384966b70426b5dcdc34a983caaae09029455c4e56c67a919cd51a2897e8" . + "62aab8234ec770548f8bcb0dc11f747d33779dec019554d763ad40a84aa31a29" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "4d13af3ce8a6f5a8974d7e472919b423d5a0692b494048368b4ac443309fc8c2" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "c1e108fd07a7bfeaea3daa948909a1e0752cb5d8f52d4a52cef731eeac583ed7" . + "8d83af47468813e862001faf8f92360705666baafa9de0af6f231008eee091f6" . + "761d9bb24eeb7b0fc7ad0650f0b3f8715673eddf63d254231800b66deb2d9e9d" . + "8ad46b8225281d66799ef6efad65cf367f7799b08c73d057dfa70d950a0ba9c4" . + "90f195407df67511e6752629529aae62559965059e972cc8dc5f26a260dd1369" . + "5527076394969e96497c24a8797d56a54269648c73a6ebc1f17dfb782f3ba93e" . + "12d93899ba89cdefff566483a474618c32cda11d31418e45a0c5b97dd6039683" . + "94c91af7c800e2668890dc4176d5adda33a2f66b8d8eb10acc70a3e86a2f269d" . + "1b769d114203c35641dfbae731511f94406835137e4dc7517a9ee307bdcc2aa9" . + "ef859425c5d7f531954fa6d239275cb7bae9482c6736308626212be404a35218" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "f4a71234555ad3547af8d8bdb91446db506b953554941d42c1adaf016729e2e8" . + "8cf62c33bbe807e1437b3287107144ecb4b15bab2fb1f9036097f2a0eab8084b" . + "968259ab436feab20f9afaded8992503c43f8f4d17c6fd0006d3761bac267de5" . + "60030e450906e95f0f20af0a0433338472cf2f31460348b0e82bda378d156c40" . + . + "3444e3b817e892a9016516627da7ae62c69335298c3c2aca771f40d42bf6ab20" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "81b95e45f7b8ecaff5a1d185795efcd04ff3761c9c9655b6166ec10561ab2943" . + "5d7a8163fe6e7ec5bfc3214b7557892c063a5d9d44931354fd62530cad07ce55" . + "8b88613fe892720c7c76ab29cbc09692cf996e8e25b0b508750a4d48a8189889" . + "8320aeac8b5466b4cacba6172815505562f3eb2edff27297183221cd52ddeb9d" . + "12020dc21de802c6ae30691b02303dbe6b515c9fee315c15c7f4c63869e6d58d" . + "c734d6080d1d789886f12191530fbd6c38ad69f73634c99accc8beb141516265" . + "981eccbaf48adf16af9d970756643516170cad28a5a5b2787f01d27812e7d8c4" . + "f4e4b9b278c972d112940171094f339432e67a8e42c5c11e64dfdf1cc572c38d" . + "f82a00d1ba33806b4beca83f6c1143767919169c2838bbe6b02f9b89dffe86ff" . + "331832675374e5c2f88c612d22e1d1b7bc956ba6e4253a5482e1443c3b67b324" . + "c11a7fe4a319a03999e462cd5a1deea9ca2c3c30a1661400c0f4416be0d140cd" . + "db77f872edee20250f0ad538829a89dad0b10892c42529b24d653ce0b64b88b0" . + "cb007c1e68b014b9605b496d4b48f802392b12eaf4ab313b0f7ecee5854a07d5" . + "e2aadeca9c60eed4182a76aea6b245b4e1ec34c63ae8d00c0c59eb82e7fd8bac" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "31132b93853c5ee27ae123de3c2e4b115b08131fa29ff00634e020e0aabe579b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "595716453fb2828a67bf5843c53fab0529723fc58ab4397005ba3c37b4f0d828" . + "0db715067419ee056c588f5952e8481d30feb6b33f5a571dbd7ad44e285697d2" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "9d16376cc00c564c5cebf9abbdd7cc8148f7133ce3873505f286841d7e49e71d" . + "d025820503a545bd96fb05fe2fc264f652cd0851684b6c6e37220ba6cba49b78" . + "3f0cb30f81a0326909da7d42e85b90fb09a8e2d5154367137fc06210800aadf6" . + "d0ea0140193f6eb0da8093fe4004da5b81b2f31d5fd99efe844d3975e7da808b" . + "ebddde4b29451fe5fefd01e21c0503343afdf70583fa2b1aa7e9b3cedb680ac5" . + "83e8f77d02713d12486b7343f61034c276b514aa9d07a4b2a73bd04465bd82d9" . + "74b64cad6e923dffd1df723ac0e7d2883616a12c526a45d854ab850db443f395" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "950e9f4dcd2a06d48872389c98a406477488c1e4b52c5b4d73ae35ae8fd253bf" . + "be5f8a0a6d60efd98a1a5335f8a2c4f2fca494be46cec55a70f1f54759e3c3a8" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "e2db02bbab2fb07af33462db21b34eeb874ac050287231ce151ef82040154412" . + "5870a9b3654d4418442c3bc6ed60346893848dca26fe1428fe78b2ce57422099" . + "e5538e37ce823e42a9a9b835e0c10a5f90a12df01c2a88f5a5f5798430a0b9c1" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "76a9093232fd41e69305bb7239238a8897468d3cca73d87a034aa411bafabd9e" . + "76a9093232fd41e69305bb7239238a8897468d3cca73d87a034aa411bafabd9e" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "d4e7c9174fdc29f7c69779e47b00f067d2d9a548a7c0d3db0e46b63c3bd711de" . + "cebb2a23f672adbfdf126d4f3e0c5db35ee026de98953de07c1984a9cdfc356b" . + . + "8d63114a586eb4bdf4bece8b5ab052c51ae17f86a744cd93004c66e0a6c3d216" . + "75c0d82c7b384f7c09489b54d6e49b26c4fa11c5b739174e7d52487a406dc7f7" . + "bf4ff78b10880659ef94195ab9a6972c5146a9a52c8be2158bc9ad57cce002da" . + "e79736ad3242441a9d24c68dbfff75f37baa7c19b7ef5ebc5f8bce61ff196dfd" . + "018e28945c6df5ed6aa57219e4a1c5a23fbaf106fbb72fe4617eb7bd6fae25b0" . + "b524d456e46fe61ed4ccf732961185e324618e0c9c84687086328a969b445a02" . + "bc82427d55908b497666f21ae28d903a9f4641c62e433b7f2064352a5dae5d61" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "def030e6f6326872691f60e21fc08dca12f94c97c47225c978fb542d1ae65adb" . + "b1ddddd0bb61699bbe96673521563ad909a7d5af2a031997accf8781d0b3d0c2" . + "7dd2b19a8e2ae86284e6aaad1050d230b8239b234d0abf862edb711c29b6e24a" . + "63c9436f337c126b4677b37ece0ab067339ccec7e3f9f909e0c66008cb092f62" . + "cab3b7e27458e9e2f6952cc7691d6e78df2f70eec53b1bd7e892ab288d392292" . + "a0627b8ad34f2504fdaaca43133ae055674727051d1a9a129a704639174dbe8a" . + "cd63719daa9aee228769614a76e37538e5184f171748ad96f2ad563c408cfc61" . + "059611c66281ec9cb3efb707db67575177a54d4cb753b6900d50c17b5e8bc2d9" . + "de7b9613ada194cd54aa39fdfdd55c3881a4569948e6418cb0592023fb824096" . + "ad83569061156fa78bec91ecee408340817c0aeb12fdee371776c596c1c07c83" . + "f97a7d897678221aabebfb25541568b56d90fe7a72ff06a7a4fbbc5f8b6b2861" . + "09b3daee9009adf3e754dce1aa51db6e3eec0093ded33acfa6afbd8e286e92ef" . + "627de27d7cefd43d2084b04d7fc089e624fd305689d06c0031020c5b8d35c6cb" . + "b09df83223172a78c5b8bb36602e2f24fd917c58bd24f29f4c4d0a12e465eaca" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "4e3598de40a25c8e4349ef3ad8138ba793332e2809487ce4a09071c822c9f4aa" . + "459f8d74b567ef3b9a55314b018a0c8651563e6a62b9473d15fc26926760090b" . + "cf6f5143cd4eebf6d548dd0df744be8323e64235d502c3569b3da22f5d2cb653" . + "85acd32be7d8e89cc1b62913909a99cfde78227ee920c28c64ab11fd93ea9cc4" . + "3433122e717d3e8e6895189856b2b308d13999f466a18b6d62c72693808de2fe" . + "7a0944e17b42bdd7ee1e599fa0a38083c0852a6b4bdee07c1810c5d98f2f82c5" . + "c563b3b4c3441518ce1598a95e71e64dd88d87ae6597e3b18e72d0f66e478008" . + "731916546b409f606868109f76a5b9439e49f110a0d9b48a46cf4e114254c5db" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "6ae95fce475c6f52c888404a0fbbe71ab7eaeaeca32ae3b9752b9607c18fff67" . + "0132d6e9395f1b9254ba5a3df1d715ce2e28bafdbc1ad50343519fb6aaf5d49c" . + "bf4ff78b10880659ef94195ab9a6972c5146a9a52c8be2158bc9ad57cce002da" . + "4d6b1845431991a74c43855cd191290ce722f1b26f1e0e385d38bdcad09acae4" . + "4bdea30e26f716860e5bf6b9d452a98f441c69a6ba4cb190d994c9da1ee8671d" . + "461de723845006e7a885c137bcc99bad9877add4e4b9ef0d3cd51d9c0b22a494" . + "ea768d3a9a83de773d634a7ddb4060fa61927d8760ea7c738b357852497f3e6a" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9fe683e96fc66bd2c8eb0f0c266e5ee0b3d37fdd8a19b89b7686436a8f66d0b8" . + "180643e64c178df60ee7db428ba9e534149b257a20afa8c54064ceb875ef83d2" . + "fa7e259fe58a8d82e2b571e2ed434b9058feecd66e116ed47b5a2ae8c1c9fe82" . + "6353ac459879e2c0df404a6a6883e4ae61fe2c5fea85447f9ffd64c3e5c27819" . + "c7eed915a1f184aa0b6aa1320b99ea50724a2e76a729782f8a11d71cf4f0e4af" . + "0a4ef44e625fee62382addcffc1e2d1b9d1258c9a0d1f5b5d9b08776fa5a778f" . + "ca8bcf26bd8e9b792495f004bfd6b6f0948fc8972f4b933e355713b8def28f3d" . + "f318f6a995a2f82213f4e64615fb3618be458db5ed8dfff26b9c13bb099cfec8" . + "130258f1bacb63face73e33817335efe48d9a34cc21957a686314b810250319f" . + "f09a5b1309ddba809787aae0a9bb3dd8fe20d8fb1c19dede723b0a7ecdd688b6" . + "c1eec010543a2e6d4856adf3577fc8ca6b299b3d6d93ba4e868d775d43d38a96" . + "d694842b35f3fb7d52397992902b297e12bb44bd2165730f116c0948bd331d11" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "4d13af3ce8a6f5a8974d7e472919b423d5a0692b494048368b4ac443309fc8c2" . + "d71c13e6ab72d6a4bcfbe3c007d0baa1e6fc859336a74a602eaa9ba8493d482e" . + "ce9a82839d852a6f67329788a36a61bbc18a31f0c3d81d96251d5e6c321eaf43" . + "98e2907c2ff0c75ec588cb8e6abbeeea1087233cbb4569ea7b735c24f8168eaa" . + "b7f4bfca772880e624923a772076b602b0d0abe5c161c5d2e1208144c0715f9c" . + "f9659c6d69c8eca4bc71ee05edd9b91b464651afcc04754dcf340fab1622209d" . + "28aebb464746d4591b30f8143f059c5effdf00dc774df72d1c57fb387248d3cb" . + "e263c7ea4cd693898cf9fc4cc78b8d370534d250e19580cf4ed1e542fc2d3c87" . + "b036bbe283f3fff4ec76af541675118d41ae88d561b7b6050a12bb6aa7c812ba" . + "2f771cf4a4dc8c7205941a4c49384de686e530f99c07184fb0e3377a279ea6b9" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "0c5124673693fe516bf60395158efeb7e66dba25a61b0dcea6ac42c56283e0a2" . + "fa97e43684aa4b798eea3e638d0f41368b6a5408083ff3afe303fac941843294" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "882ee8c16e1a8787edf51b7f131117cf9b24c16d34050b384a7ffb71cf2977ca" . + "1af795a781b4068e62c480923b25aed4d425f64870b18bf8dd21ddb16bb191d2" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1162ebd53df0559c7bd7ec84e58ee13acc20409058608f8738e5fabfa378b75d" . + "5c6d6f082ffa5d2190c67d1aa546a3bbfa436b820aeb56992d079947268a53b8" . + "537ff9a6c545f03864fff7b3e2a835b9fad9bd0c2049e28f977050755d4b7474" . + "a0efc75dc4b773a2092dcc158ba3e685e59bdf57f80e125f614732951ba5ef72" . + "03856cfe43c63ca39ed1a8fa1891ee9edbe6571fda1d572ed8e9ad4c4c1c9ddd" . + "20d88a268b131cc761ebeb746a6580a7fe32ae52264e0850747625a11169df6d" . + "ce7ca2ddbf9c379d5fe3e0955a388482c432f3c3ad69a449a999a92a55b46a0c" . + "fc72df3019db5d980c509439d61447f606dc069131d4652cee2615162c72da4d" . + "eee6b0773d735976c9e6d6c19e8e1a418c682cf5d4fae7229b733bf4b536b17e" . + "d21fea105df84efa5d54717888bbbf5d867a5ff6c3f0ff39bf3889decf223916" . + "1cbb6bd24dabb9c50cf3cd05edf18d57cb855e82ccaefab61aa7abe686be1a1b" . + "fe081177d71dd63534c772f61a01399f3ea11b7d1805f3af9bef123cc950b4aa" . + "532cb58fdd016c8297b96cc93f80158e8be7e7ae30ab5ad309e3fbc65cff5715" . + "802750b34f924c29e4750170416bf579301738c7b9110e5d7fde852449f229bb" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "3aecea379bddd4f4a73d389a98726af99f51c004c656ef35fc44696961cfcbae" . + "4997f9c8573e2cd75f5430525dc0faa4635974d74d686c96d45a8e933b166f27" . + "0c72d7c20b7575cb564215274fbd3e5887158e32aaff6269634d9e5c25353143" . + "4bed2e92dad76ae8efcfe2391cf6036ba2d66058928c90c31e07453b85d1453a" . + "3440f0f8fc4d36b58bbddf67dc77d3b5b7f10178ae7fb75b07bb6bd61b44b448" . + "07329c10baae0ab02b01ce3b1153a30b6cf6137ce3d45166dd46bbd9e588f6f4" . + "c10a9789e22efd952f77657aa657df61599a3be21a8d4432c302c3af0e144b44" . + "b3743c31a2ae7e914a839c9ea768e64a3b92840d582a2523bb94c5ceb3dad436" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "60c11c0cb8c79124728cf2558992ea6b3e465311eec6379686af2d415690047c" . + "84d1607deb85f9a29ce1877d825d330065d3e0f77f79fa7ce1ad24561b114b9f" . + "335221c4d0d949a73fbf099c505b78bbe23700a423c7907d7d6c8886b7bbe08f" . + "be3fe7fb878e0ab67787227cc4368994dbc92e0300eee23c11b76230b6caa923" . + "ef84502fb97eab54b0623e4e85b4186391706878f449fecbcc1262bdd79b7849" . + "0e254b460c3af99e09f795375219749ff7b2141eecf62351ab68e25204081562" . + "b534aaa1d2af707bf93248c2b9aca0ced7ef2fbca2cf7402e64840c53875122f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "315d7e21bb130e2511157a1086cb50a2a868692d46eb30f9d89fa1277a941385" . + "6194444a5d1d4533fb8631b93c1fc656ba7ee5a9fa3e28c7877b134d4a0e2644" . + "8628d473c4a48cd83e27c3944640867fa38a34c583bbcb23fc9712cf22e1c3bf" . + "ef321d10b0f7271efe045d23c34c64401e6d5010e20bc3adeea919b37b871727" . + "846ec25062981b1475c96b3aa9e7d3c360a9de01eebd7325eaf7c4510dddd753" . + "f042dc2cf018439c22945d8c829b63c216a39a97cab73fd1a305ac2fc4e0b9c1" . + "0c06de1825e66a051ee88e3c4597027f1c503a23892c94db94865f9b6a0c495f" . + "1e1e3d70e88fcc8a50b3e0dd8591867f0be32111562948e5b61dcfb2967a5182" . + "fe081177d71dd63534c772f61a01399f3ea11b7d1805f3af9bef123cc950b4aa" . + "89a6d988e03601a3cd6068d5dd42ba5d88882a9f7105481eefc9c1a9f5cf0f53" . + "17da6ca859a7d35946c75076895e5107176e8e70b1ae98251c456382a9be4ba6" . + "d3085d4707738bd3aaaa3beefe28a2b5e166c61da929190073b891440b8267d8" . + "abb259c7088b27e5c28a9d48cdfe31a612c75252f31f38e638d19904d024d1cd" . + "0487b2abba3a5ae34e5aa5c05f04efe2fe3a0a4c9cab3cdc9f273116543a884a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "eec54c306712a430ab8a9b06fa2a4c7211b5e162f8f81997d2baeb41bde963f0" . + "3e1fc7fbb39a096c506a6ebf72c26ebeaa58ce74cf0eb5167aef18c6eb0b8a50" . + "6d3e9cd32e271c56f1dcb4999e7b99b26e4a8ba4ba7ee7e81f19fd15246f1950" . + "f09260629e82c73330c57c181f56e5d7c080189b82f319b4173ff42c2245daaf" . + "27bc890055444b8e734121b93826b6dab75fc58199c9aff1055f279e5b39a696" . + "b630e5fcdc525f36980418c730a07e9d82c5b86e9ac04437e1c29fee175e7f50" . + "aa11b72e105648dff1f1a4ed92b51d96105f2b1089b2954626e4f028b0fd42c6" . + "c719b1f2911f63c99496b6b900e05ee5ffbf5526cd894226e9437bb3f61fb2a2" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "6b2e156a2d80cc5ebf66759149b85ff4a0641a94ee17e16cee54eae6f995c4df" . + "84819df6eaba1a4969b928e8dd13ba68dfbf6dbf407b2f5822065b265ec65c1f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "b6f50ed1a1e5cc39fbd31bb792daac98b7a906f2d843b655380efbffa3af63aa" . + "da2440abd455c05c5dc222eab7c030f6ff6fc5386819d7b71effe0bd7e7bcb0a" . + "5f3d8dc16e98ee2ae4126552fef42cc7a06c50f1b1eb6dec83b8062df081fb0d" . + "29e86c783f6feab6b678bba4f6a695751bdff9b8ed3a4c1a1ea365eef2f2bc52" . + "b6f50ed1a1e5cc39fbd31bb792daac98b7a906f2d843b655380efbffa3af63aa" . + "c98bdb2f6216240923edd404c87aaedb32145ba26ab397f959e83f7b1497c8a2" . + "ee9151500120a816c80137d250c4ac673fe27e13347abc43bb7198440ec36b99" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65eb11a839acc237cd14d678ffd6455ec9aab38e0339be837a4f7e13428e9f06" . + "58cb166c909d9bcd711363f155dbe1c62d4504d9eed457c1689f5c3ffaa856c8" . + "36d9260b7859ee921c1b4d943e30dfffe1a658d461d6ba2abfb1108679c27b05" . + "bb59fe6301986a48c878a557cd17660e3acbcba626c48f4d9b5f76ac51047efe" . + "5166f89583d6174cd209973182e3f009fcf525fb37f57cc3a97e6ace9ca17166" . + "fa8d9f2ad69b70b760496a1ad37867ecf284176335cbdf64313aa500b97b8abb" . + "5f7f20083a85c05ae837527b3723fd1e9734b4747c3955458270dafbaac7bbd5" . + "8042dc4255b57c31aa88d57ce67c5d10f6d19b7e8ec8ed84e3618c8a30bd8916" . + "574080f921e429b7113fc5666e177caad683b1183a604ce2c11b05b631907b46" . + "7354df16a73cc8a7d2402bb8cccd5de2a2915c19be2076f44403cc5de05e7af8" . + "82fcb1de74d006db28a56acccbe2f1d12c4ebaabb8af230ca9e9bdfeea5ee673" . + "babd3a2f3603193d7c80c7ac948ca6fdeb5a8a87730f63565f672d7a29e24d31" . + "761c1895cc850180fc64be290e5d8c12fdb292c24df9d16173f808425d316431" . + "35fc7a524d81d301528e4de13c6766f9921b171651b08f08f0426f7c015127d8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "c9008979fba960fc4210aedf076652a4977dc538cff77534971bd64a9249fd7e" . + "2b4d953599560200152d2781811ce5398e9e47562da45abb297cbf7aa7b22868" . + "9bef333cea4d92f67cac787850925d7334bbd37adc8a6296c9363182dd60f9b6" . + "731e230b8b9cf116dae7b983c5630c0c5efdd14632229be6e8891a1d61b2880c" . + "dc5722702a27d1c0ed6490e36a6d45f0c26df51fe5c35ffb10596c9698690522" . + "ac00f3474ca3880c290445cc9673834e515b6ec92e38e7884df8154c26f03d14" . + "86b4ba121837aefbd8408e894f825c363c2797c2840537e4580566b3f1890350" . + "1553fb39fee62293bdee9a618fbb82abf955d8ba14022d56a1feca6ac93853ed" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "6029506b8b92d031eb76d050f63f84ee5ecababbe2f0d420fae76994ac311fb1" . + "8e691d0c6acf35cc038d380fe640daeee84ec0278cc3ae23c45f04098b7a0ac5" . + "4d5c9d932bc8c4a6850b7c38b78b1f395420ad314fb37b75488aee1975bf2dea" . + "f9c78823ef36f7040756c023cbfdbcd95d42dd205ab6bca6561835f4af9b4a49" . + "f1c9cff6780a45cd4b1e6ce68b1ffd7a52df9b417ad6619ff40f82c316119275" . + "4fba802c4c6c6bf149290cebca4fce1b03518b308df5a1c105dbcc8b94b500ae" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cb797308990662ac5c9560c1bdf51080549d870c56e17d25ad5399010a46ac90" . + "017f497d1f71d8f8f126dfecac0883b3784ea2e5b82698150ee53569beb7f78c" . + "6ab4597913a5d82bc7785264c65cd5c9b44e69831c9916bc50baa0358be749d4" . + "ce3c38dcf137320d1fde2aa13e7e2a8145f2d9f894b49cf20dc9a944b9a542df" . + "dc985ad94703c3242f1a4bdcbaf248a2959ffa71bf2911e8fea5f9578205c7f8" . + "33cecd3d52ac4aae431e2440ba9bb8614ff814e2447fd538741ff27feef82a6e" . + "df85a1afdbca58c04ec27ecd9ffcabfa8d675c8c1f0b2273260ecb13962b1007" . + "1af93446b083b8c55cb185dea063d6ed15660cce246815a7ef34456d8fec53b5" . + "2e87db06e7c44b99e55c3c4f236febe205f4bb6eb7d4ed5e94cebece2dd5ae4c" . + "af7f824eb6e712c2f679a1f365311b9246ca6f03015e6d8cb81e6c4fbe13e212" . + "d96a04bb191423ae84447ebe0cc17fe66c20184b3e5420669625dc2b175ea84e" . + "74e8700ad33eb3a070d94e309147126d620bb49aaf8d2b003c3d57ac3f5de924" . + "7797bd0c29d7010e10e4baa923ef58ee7609fd15acac507619aace8ab39f19b8" . + "22c74b6a12c4221380f64b5689125cb9de6c75e69c4f38dcd45beb05ab653200" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "c58e08732372d81210a1582dd32e3d91f54178255c996c3852832307abefbeda" . + "9f3d6ed57666fbd0a0a9a91f7d25a3a14ecfc34ef781590cb8452f64a803cf65" . + "6420e118d078ab5c9a8efb147869036f65c7cf835aec444f4097cf602a0df5a5" . + "59df2f479664e4dbab40bf105f45c4cadc1acab67495d58289036704e2584401" . + "28e6bfe33f60ffa6826cb93a9b35c7310e5b1e771d564c7dc3ac348f9446600d" . + "e6ee2f3fcb41cf475c56685635794f8e23a417f6184f1440edb32bc70c9a9a39" . + "80100d57197e482ac9d23ee38211b2b18b553b81adccdb9e82173fdd21c240a9" . + "d0c704f6a600dbe687b1b53361c28e3d761e2a263f1b34b1da6834993a354ff1" . + "6133679ab93fe197e8cbf699f70778a4d986906ecd3fcb145211d3c66e3e0989" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "4e20e33c6149fc7266b4151a8c3bfa9c0ff8bbd86e48c56908fa1a381564b85a" . + "6b2e156a2d80cc5ebf66759149b85ff4a0641a94ee17e16cee54eae6f995c4df" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "d0df33858aee3157ed0521b5bd0c6d3a46e2ea3195e8a06f5ad4b07c7704aa41" . + "2c911f10cd21a81621151d9de4f4c50e22772fd837b9aca2639b0e204ccffe43" . + "89e62cd368f85bc8ef66a5de3502ef338ee35e16fbb671b6d4901f7de0a22cf2" . + "730033e906d4bb0433f066d1de89136f8fffe60d5687b366f4cbe8c47b062d88" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "27d7e6b699fa00e83f99952a6537b1a19bf9847915d12fa2a2ff1dd847f312e0" . + "862f06252765654ed1cae7a5c8fdfdfeea2e67c72dbed47cbf116e7fd369c4f7" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + . + . + "2378aca6ea6c41fe0e56d97f76dc017774cff0b65a4231a18c9bf6f5502d0ca4" . + "59d4f4ae1fe89937b4d009d27e2abe914b1c801d943ba4c61b5c0241b04294d6" . + "bc038f8a1fc5599b9e3d0931c3eab4fdd18b97d4707acda8739abc95ae055bdf" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "87cdc9963ff0c4fa63e09091bb6c87fa488baf23b9917a85f366315e59b1fcd1" . + "87cdc9963ff0c4fa63e09091bb6c87fa488baf23b9917a85f366315e59b1fcd1" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "bf5d5bb89f6b45a59e27b45d67fe411b603555c856735b315ee8fea7b1e52c34" . + "f2943d088fe4fecca1202cc3e1068646d814e29941b7dbe9a131e9a83cae4500" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "b102607fa8fc524ad855746e509171eeecd5842c8e817e30d0686296a4511f83" . + "4b9e7976f1ceea275510b3f78401e0f4ce5bc2e527a47547943cfce364b862a1" . + "2583f4e41fb5a9107e112912a2d5a747d408cfb82f7d4f8e2389333188076c39" . + "779a56caadb24a7122ceef1b576c72b9f00d594bfe8f6701b7ba451e173e9c8c" . + "284cc6fbbe95497ef167f35536bb15d2b69c9073cbadace4e9285a898ee1c5ca" . + "e79c3df84a1447fe054fbc6b1be4141eaa400ca01c33a8f312aea3464af34d60" . + "1e76b2ea1bfec1c1b9d731bcfa9c0f23ac7abcd5e2225560d8ae3b3432686b9d" . + "4968e11d156f9295f93c9f4526391039650f64eb7021c3b493712d19e8da5850" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b6527d50c9563d09daa91f43db11f84a2e2829c45e88dff231b8159935c4d0c4" . + "ba204c073d7e09c4323c5b9f00d0d606119f44fe604d8d15188bc9fb9f72d9e5" . + "90f195407df67511e6752629529aae62559965059e972cc8dc5f26a260dd1369" . + "3dd8295bc9ceb4e669a6c1a6cb8cf8fd969eb320b3787e2b3911dd47286072b9" . + "dd4351fec388586eb979e55e47a43df935a7fd19cf262d688f442ecad6d7c009" . + "df46a224b81e2235886ec658e14d806adf7de350d582661ee630392feb173127" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "2d6c8f94a20c994f252e402b32a9ce554c6ce7e6ae34f8d78352d94931a01766" . + "3c7668b01cddfa0a27929162d57d5601ffd9945591a58885bfa8de58b665ce3c" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "bec78e2f9d537fe0b7d42a1bb7144eb9f038e09e0c05b4a3ea655a3b1a34ffdf" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "145f805f6feb260c4154193f894525f43af82f566e78cf923dab37364be658dd" . + "145f805f6feb260c4154193f894525f43af82f566e78cf923dab37364be658dd" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "f42c110894d377d9238599c7798f3671f5f8c3fe5b3e583a733fa00027515736" . + "e058085ce9da3ad5b711c2e070b01bc8c1f9a68f12af85e3ccec0f00bce9e6f6" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "c0a91cc28fe927c3d656b6c556f7b03641328aac9c08b950e94b595648784a42" . + "f92e40da5540c9d5df18328d4204a5114318f12e6f1db9f402b663671e98463e" . + "06c855770f62dd8b82f97220b7b8ac4d6560e0311d91863e10ff431be0f5c2d9" . + "83a9d7b3e9c4402766ca1f1d718f4cf3d38137c5a3fab9646903ba91709cd9c6" . + "56c6444c821ece312c8dc432e7d33bde811863e1ffc3f62c0fffa7777dcb922e" . + "0c6a8ae13b45622617e681cd4955df959fb11cbcdfbbe9b5047fbed9166cd7fe" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "f66a7234a4f2f74a9ca0b0d5dec64178bf63a7b9e420434822b6ada1188450b2" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "f53da32d39f3438b1e7d53fb981c0762a51a8a5ffcb99f0713dce38924ba4c50" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "9d742d4fa5c1e452795e879fe8f94d49c569e4b6c3d5cb03c6675f48da1d3840" . + "675495449f0a53ce95857738a547ee5b0039237ded7a6cb65a4c78786f7e5f69" . + "18a919c3149d059d47d177039a15c13d5c74325e69964e958c20bbe26e8029d3" . + "4bf8fe05b49a2c689515b1218e3fdbf6df58d77c5a4eea32efec00845c6a9b9f" . + "1147f13d83de2cc756c9d22bb2c9b329ed1ca9bd9842e65a3ff5fd68ee797fa0" . + "9f49b3bcf40a5481f6e92a74f3d189f82ed03c1bba30c276917c550c440ba74f" . + "86eb6bebfb5d95ebaee6a24caf372fa927d76c5484529be790670afb82bf5d4f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95db40db1e6d717a53b8eb9094ba9587f0dbf80256eeb0501e64f5c7cac45874" . + "95db40db1e6d717a53b8eb9094ba9587f0dbf80256eeb0501e64f5c7cac45874" . + "cb20de4e7972666294eb013e3161059da635fe91c0351bbd26d656d791417c7d" . + "8ca3df17f9d9db190a9d5247874c14019a51da4db4000c3ae5042aff86a30559" . + "1ef7f0d85cd8034f8a03473779fba24ea8929044bce3bd36ba50ca6e71008066" . + "f73da68a6541796bbce5d3daa93cd01819db77f93d5f567d725e9e9b2db8f448" . + "a7ab086bfd936e319f4993e2d52632b40d6488bd2813bcf70957c8a66d4abe93" . + "c138d0a945c70ee7c87e2001a2487d2a6d49fef64f401e6b96b807cc41c12003" . + "e17fa617150ab99b20837ef7a0c7cc00200875082ad8c3266fb78475f41cb1de" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "8837561c8a7d9c3f0e3c726cd4d651f5d75aafaef186eacb504c64c699f6a632" . + "2600a5b83106791fcbe1ff60617cbed91dac741d776f5475fd4ebf4932c39660" . + "bb880821d937ee86fbdb1a6ca5a3756e01e5df3088279305debe54a90e546e62" . + "1dae05e52649120343527f8a9773056afbae379bedc314ff98640e7099103937" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "16ccb31b6b2bbcd961fe8d2bc557c4cc56e5269327cee1ef1c1d1b5de53177d8" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "ff798977681eaed026ebc738204b70e019c2d67a0c1a21a23ae40ce7a7b84fbe" . + "9f537e6fb799f427300e3ece16ec1d55122196793af5ded034868d30c0af73ec" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "212cd8730f6e9186f01e96148b884b356b1056dc0a1a1062ebf2eac573f543b1" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "66e07117b78c678c09e84d6933c5fbe48de9880e7a0e6b5b74d63832e146b5ee" . + "8a1303616a9e78a78018bd0992378397bdac1991d523fb78a4cca58d646debbc" . + "68cb1f73a773dea10ae80b691f9616e85911f1a3ae1ad4a133ff0a11817119ee" . + "ffe5e7f02f10e3012e6ff0d55a055ebb501b0f6e325e43b8fcd037f4336d6356" . + "73d89cbbc8d01a16191039743f5c7fe493058a14c337ba5e355ef72e90741afa" . + "1bf9dbbaf89b180a18d23eb6c6d3b01b933584e76d632ccff5da4f0cb2db87ab" . + "eb68b3623da104a03f6474e002d35da4d3c583ec90b25463dfd9aab5e45a01f7" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "6e70fbb6ed277963eed656f26e3e1e7276fb102531b67153c3e6cba461a3606d" . + "494c264950a6d30ae91065d51f9197524f7d9b676b8f76472389298be3fd02e6" . + "2ab32e2537f4b24b19c7648d7dcc23f48605b9c0adfe75687c15cee13d18259f" . + "0f9f30f18e40ca82a655d94f51f8924f6bebcc2e2fbfbbe557242827fa6cab0c" . + . + "b8de494a362fb6d5b19250ceedef7ff0085b664721836180881c834dfdc2b5ca" . + "7ac1823d15d39f3c07207f3dd14f6dcf0ec9410e2794246ff02ae99b3133e672" . + "53c325871afb452fd57910d334da9b4e8664c1904f0888af819ea534a67c6b08" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "557f096916a2d7adab63c94781a50423e70acdd7f13c0f2d8bbd78e8bfe20aa0" . + "d5229cca8619f9ff1379c058737f927d307ed3037f03b79ea476039a4786a9b5" . + "c7d99537f94f73b46e174c36b6691d4b938ca2485fc37d63131c45f8756fa2fd" . + "c44fab7e3942d9435fcfa7a5285bafbb2c7d5894b6dc9d57186bb9aaf9184727" . + "99a7ff08ccd7ac953d82ff1684bb6b069062b3598217d60779b463aa880c475b" . + "72b477123557dba6c98da4e530604efab9bbb242e5a17f04c1d52153b667d6b7" . + "df5d047e17a9da0ab3df4ba7513372879ae2df798a160e55f5eefeb2f9d74f3c" . + "2d001406b55a529ac395709c4bb393edf2442da753292e586cd87c38d0f9c298" . + "40cc5b1b08c2f5301a80fcc07d8ddfa2af643d4d55de64f5cb58a53e8cd95091" . + "596093a3807f5c658edaded7379895d55e76c827cd9c953d17014cea3ee4aae3" . + "002ffe73a569eefcf938d68ae7955022d621e9ca4872d57b922ba63bb3a1fea0" . + "b26262875581dd0f1093f02fec128e5fafebb5f235c43696afa2d9fa961a4685" . + "6ab54db51ece56a5cb8c293769ea41695c72537bb88cd1e82037b59b420dd9e9" . + "d5cc13571dc88766007050bfdd5c974d87d4ba9c1aa6b814efdb135e0cb43297" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "a00bef62ed956a75e6e8846f123cb8444682592a1ed4580503d2cb19f0224b2d" . + "c78e27bdf51e1d1000b3411c777b45bf39128799cd10506aa23fa9b9f86ce0f2" . + "8c3cd580f83cd030b2cfc654e0e42234cece32ef7d645d5fb43dc8d16803e09a" . + "2e3cc0b9d5ed0d36f424cd239a6f823a139e1b6773473554dfcc4106db5b65e5" . + "19afa8c98f99c53f85e352905b01d048de5dff57466fb5288a770363d65f8f4b" . + "0c968d4a9a3c701e90146a136656e1d3586041fc61eb5a12088e4bdb191d7a04" . + "de1d3a71ac4529c2e6c2723a7dfa6112b95b42acb7ae9744a0f9001c07bc8e93" . + "4fe3c20792a940f310b6c240ce26686ed6e681e6d9bb4ee35778e8376b6eba84" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "28a1a9511ffd71219672688ae7cd2850f0ca0e47abd0ceead31c00070d8460a3" . + "e4207c29cece3dd9c9f2c3f686a162256e0d72ed9a7ebf8502a9de6ee0bf821d" . + "e0d060e2728f89dd75d71458bff9883f2c6d17c09249296aa4149d57a4638b93" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "904f060099b7454c34a6ebf52608301cfe9d23623fb5729183fbbc292a429443" . + "be18ff20cbf416375f774772c338e98ceb1ed7875fafb1c8193a50e746cd78f7" . + "d9ce8f30c36c3bec2971e44f03a7daac74eb6e4824f9ecbceaa75716fefd85a2" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + . + "fde0a49932e1303431896653620579407c59fd3ada891d5efc57f0b61b06a0dc" . + "1f2740bc67c7ee1a20a7e53f30025cd6a9f728a3bf6328713646502f0b135bd0" . + "f800f29e49ed7805a138d3652340de865b763dfd1484aa13750587674fb824df" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5fa69b029cade7fd664607e99b5e11e15537084c1c44a474b1d17b8c1f446808" . + "db2e3982261d5ee6a84b95681bec5b043c90f7efca17ea0b3f64562fa22e5340" . + "2b7c38d3d1d5776a220f8d4757476b87e1a630f28d1abe8ac33ec6998514566d" . + "c8f3a53ca11f757e7a12337f7ec67db4e391d28b9f7117ac5137423c3e6fdc13" . + "e1b3bd23bf8252f7357a090b4d103910b32f30cab31cc2e76fe4076f5b50cfc6" . + "6a0012ef85bf987a6fa3a50c1eb3acea2e96074a7b75d6ac8846624b7da9c7e4" . + "6e31a6998c5d3787f50ed34aa70406f43b9887856b479d793b779325c0d0f2ac" . + "58ae9857a5e3f7e576df0249a25f770f4cf9215b0c035d0fda22160ea23f7e6d" . + "4dc05ae2f4185b267b0acf93e699c37109693e2d575e883dc48875747d23b78a" . + "bea8b87e549af42498cf1ebfca8b80b23e4404a8744179491e5e68bacfad6e99" . + "c67e0fd529cecff5bd0e066386a1c3c92b6c515b6531c7d17538ed5f08ac86ea" . + "d9ee088af531f070e5dd5209b5eda0eb6d2a4b390540ae12758e39a26b3bd6f5" . + "218f1ec8e161f12e8088e3a5d6acf4fe55f24071b4b1d8ca086d8ca3aac86546" . + "d58ba8bc7e2c3f84e8dc19293464d5362b054494e48e7669196b27c6b1f65f2c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "ebe139a9fa21ca2953b687c2f5ab15ceba984c28f8b0fca7a28b08462d4f3495" . + "46812c85636210c0065c8f25870da675eb9983abf163bac03dd18269c85197f4" . + "ed6829a9f765912a9e51384e78533d38c82e95097a8dfdf6e4558ed28c02c633" . + "868001e9f4cab3e40167aec68a944a440b2cd723270df94ad81afb37ac38c37a" . + "4b59743601957dbc1d527a2694cfecfe97a3687645a686af3ce623300669ce8b" . + "f24d1e9a19dd622f1ae1986ffc3b787a5150e733c5eb4ef049f5a331d52bf0d9" . + "859b6c5706e3a601ceea6688eb80d3cfdff01aaf989a316999663d975d45e64a" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "b1620071cc587c44225aef8141f11cb0315507abc22a9a56dec22e2ec27490e7" . + "f4e44a2435012168248252181f44e72457cfed5121cbd81c09d30285f5f51997" . + "ce5cdc507e34e47a86110f11b9e2bedc4c178f5cc2c7bd47a9723c4ef5ac002e" . + "65ad60d76f74a3dd19ad2fae0b83e08c6cd8c0d01ee1287477dca8e13688bdb6" . + "c1e4ed9410f06b65b1687a5b4f934608a4166175d4dd8fca9f12dab69e2a05b8" . + "33d5ff5e1b9e2f71b5a99777b01b7a0310427845da8ca3f0c6b68f751c18ec49" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ddb4b8b400700f1d0fca945c23745b1d79480c84cdc99673bd2f5c67051a441b" . + "1a200ed965fc1e818d5d8642d0b70aefc740dce768be1a40175ea696d0874f9a" . + "66e8244d1c1dfd74d8e19c94afaae0132e3a1fef51cd0df4024483fdd0957aaf" . + "8b65ef8a277d9c1af60a12f4b10608e1e65ff24e60efabfd7010143e3a22be30" . + "5769a60330788f53cb122310135962c1597e45034f72a9e2b915127850c235c5" . + "dfff90f328c84d30141d8805177aa99150d69ac4a49aa3655c4e9bee54a348a0" . + "144989cb434ada5acc5ed6107c7b3b3253c6e5294a26140cceaa5fc07b5fdd1f" . + "c2b4f085d5eeb11f4aa216b106ef280916e71dc90e9935ffb51db9257eabd72c" . + "3830b449e9300a518dc07badd5a6e9836f579d9a8b4d906b5984803d92227b47" . + "391434c5eadf157df192164f0b8f05fdaed892975fa04503c4f588d9cee71a0f" . + "fd6e2dcc4d1bbdfd8927afda77d66932ccaa1907d5723575d7055c73a7426af6" . + "e0359c5348f83877f8349a5702e1918854ebb94ea981b670223bc844fa5a2198" . + "9506036121474991126c44160ea6e3e090c2394d852d1beb0401dfbd58557ca2" . + "429e159d732be0ba27ae07fe78e86d1421936cb605e05d8d923d14cffec558e6" . + "4150d975ad77d38a6a96d909df207f3c569774d91921e90c727b49bd24bc3871" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "e2815de1e36778751481cff67a0dddcc76e0a9e7df256898dff2bf6058e31d6c" . + "d0c704f6a600dbe687b1b53361c28e3d761e2a263f1b34b1da6834993a354ff1" . + "33c5dce09efaa4a158102cff7e77517ce0693857fcfd197ab39080df53874091" . + "6fb073cb5b34f470e8482cd341ccc04a441893da0e0a19df8cabfbe3d08c3542" . + "2d393b83712df9d39da648bc747a3139790bf40ebdafa29c636723a6157c965c" . + "dbe150df787e37db23a58c89cf88b674e9fdcc158a0f59559efa007f7e175921" . + "3d89762b7113adfc42229e6d44cd1a34a2cdd9dae1104610f504e31a817fe446" . + "cbf299ca890603865c3c0ed4ab47574dc64055cf552fc62f0820bd5476e0ef0c" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "6f7c7da31b610a4db0a233630abbed991e350af3a389b9ccb65f579f1cd5030f" . + "adb21c3d2b02373e6aadcf3cd5737e3c30eea08ae52dfde5bffe64b04429a1f8" . + "2567110cb06e83571f3462c7ca69b7df4ec5fa2671b8070754e237d3df13ca39" . + "9ea03b14983f054a1033742415b25dbc69d7ae889ac55a5e7007775373432303" . + . + "027ecdd3352184bb177d60b37cd42f105638b6c39eead831b247eb6e444c611c" . + "9309c9ce7312172dd14b6a70abfedd87f1f45784cc6c3b13357ca40ad6bf628a" . + "3ce77596a9c69ccefb9ad2ce431cf3acbe39b53282021edf9612c2e0a6787dcf" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b9fef142eb84db55a14362434625106a5e1a16a7f3db7e76330ea8e0f9bf7616" . + "eaf93fbe65a45bb590022b1ffb910955379a01ecc218bf0340907ab46f6bab23" . + "74e7be917e71bcd13f488bf56fced4668b6d0ad283aa3463dcb8d8030b438da7" . + "dd4ccfbfb180ed7ff5d8dd0d4e17f97dddd88bc60e46065963b0c94b3f8a366c" . + "5b349df2da75aad6bf6eb9c5a7884d738000aa1acf413a4efd0f7d36e7e2ce9a" . + "161e661c0920a7ec5db77232771cf3cdadadd7652d4ba041764ae8df92dfb8e5" . + "2d249b8d63d99595d9550ad4260ea53627391b3adb61ba788f71bff524397a5b" . + "3d8d9747b7402bb957f82046cc7a44908ed40ba8532ea17d3bc9ff716a924697" . + "18bb545a7d5f6974885833a8753dbca2f6ec3a66ea15284d3aadd82914664f34" . + "376883dcae36402a5e463d5da5e24b1a040e3dfdec3f73758da69a07c2d9eeda" . + "c032f0654942240c2266bb0914765fb4b0011111eb77dbc1f6d4183540c5e7e2" . + "5aebf67a37b7d53cfe63372246280ea70be3fddc9f31b4fa2f96fe47f23fde03" . + "8313a47218c2555738338f9d5a888e0b54c39f3e4136c51baa28f99477332ff7" . + "a1ced873e7abd9e877fe77023057765271de7852ccdfdf9b57cb04d5cd6acc09" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "68c64e0627576881e2aa679337bc2b208bf392f8824281c25471f2787aded575" . + "2ad86e015850a8c92566905ceb45ca7fdaca95f4282fd58f3fb99fd428336da2" . + "33ef2714bc423f1b26d4caf6465a05fe63295cb7f55d050a388a98888b850d38" . + "3bd440c5c275b390315ff99235f1a7545c25a6440e82ab0060c9c4ce3bdd6df9" . + "2b4d953599560200152d2781811ce5398e9e47562da45abb297cbf7aa7b22868" . + "6ad28118428373784e390074efefa2fb374411db94221c6e5eae0e970aa09651" . + "ccbff20b30c0d7e4f9a72d786564f3d9472a765b6c48f4d5477a9f5ab5262a78" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "ac1c72508234c888ba07d978fdcd966c1565e6f61d422c978b0c025e0ac32753" . + "7737c72f2edcb271398b64c1973dc39515438af7fb7090d9f5520c0b4ad76bed" . + "7e2f259e2f27d3b87170c9e3d9270c2c3b842a418da5fa3f6ab486d73a69e4ba" . + "5859536b6dfd0b3b2c334e2b7f9bc7a247aed7a06144d3769ea60e0ba1b076c0" . + . + "9880e1f971637e1766c53214f9a6e56a36d0e4bf1f2267efe513ebb6aebc57e7" . + "c4da55854937998bff27ee74a2cda99dca3ab1e348bc79b5832feee11f3b5b8f" . + "92ba9a20d4f4888030fdcc97ac185687f7a64227b75211402fc5f5d063a68b54" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0bc4a742b6f931134857a54a3c814053c8e66c171242a44afaac062d65c9aeff" . + "95be804e109eb5585c294b222e9fe238274c907d46ddf11f8c531cdb64c34627" . + "b9db31b3bcf836679621351c7688b4341d7c5fc275d669ac1e9f5d6edbd85900" . + "d71303c269adfdb5a0b226074ba0ee242fe247ba199f35f13e645dafb4fd40b7" . + "1c3f1c5f8d2a355afdc3628ce87f0f2b9add77e31d625831dfd5b48602588453" . + "a3ee8402470d3541ba4e468180abba5d4332103077646da38da585f69d79e9a0" . + "efc6ed516afb7b5f2993cd4d0b4d216ffdf47047daed943c63c4ccc690392df2" . + "9058e97ed6280f6f3d67edaa2016948e7582680659078f9c11a88023d53d0395" . + "c0a0fbb7cb2195f69aad0a1ba1a2dc6e326aa2954940413e6002e06400e4c6b9" . + "39fbee0d017322e98f9efb521598ebfa525213caceee24d6dfa406bc87c10635" . + "1448df2c599005c44d47a1458e7934896590e6e18498517bb97b736cb1fe99c9" . + "d8d3788a64e4b2026eed8efb56c73cc6681e61315d4de2e27c7f05386b9ac0fb" . + "9da30fb15f44caaea300f4ae584bd70f789f16056ad70bd14765f2048b934521" . + "a504e3b9ffad59d419a50aae81119891866a0d731787baf5bb0fd87813fb12f4" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "296be7ba8f1f685c1125e9051bb41285be90304d65f9a522c32ec9b87fccec59" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "a6a3c7f700906acbef160e831083fa26317dc3067ea0ab5e3edc5f3d62e35635" . + "a3189634eddf9ef95c7897d6c7f1d1ccdcdd8387ab7559b19ec25fdb129115be" . + "531776349aca0f1d502021d646833d9d39f8497fe375e47086f45cfac5a996ed" . + "7a8a81a71bbcd2bfc9855b693030e18c3104436742b00ee20f8c6836ec3e0467" . + "a9941cb4a12241383bc4fbeedcb4f1d17c58d00aa992f0975833398769debd4f" . + "65f814c8f63a89ac7e2d14b12bb5f16f1286bbbcc81c84b5c7f55cd8edcfea9d" . + "1737a217e216c7b16d571ef9e2b50947d076273ffe25875829802c7930ae1ab4" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "3c3184132ca53c83c301baee5fb4232cbff834c264d2d4b5e200944a6adeb1a3" . + "300ff3b37fc16618826cfed29225d57a0158dacf30cd1499db9d09965cf68a80" . + "c52e6f513b13f965cc8cfdb921e1024708147ed2461bc35754619d4d883ba5fc" . + "aaec19d0985e172d92de1bdd4e108cb5692aded3b3f598c18c824d142c27e3ed" . + . + "08c20fb1a93d27e60bb21db95b1bc1d7363edf77eb223a932523d5fa0f7f00e8" . + "8babe717077486d811459c38a21b6787b78cea3c296ba79dc060332b542a89c5" . + "792e723d28e8a013030d20ed3fca075de02a301270c536cf476bcf14082c4f35" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a59ea8dfb731dbfa213c5c08eead83c43d87a0cb91a9787f2a2e572332d5b61" . + "e0a325baa4223ee40b6a4ee8b1d35c27b951a7cd10d28c44a00bd6cc59b68473" . + "ee0153406365e1a3007f057cfccb3b4306cd456062a8ad49765a0a4257f094ec" . + "7e4997717575151b717f68d4d731ebb9fb72a724b528775313ab0ffa8bd2f072" . + "28130bd11b6ea78a3f79e15ea732be1ebd942f9697c21d7945e592d7ec0a2684" . + "a28e4cadef89275016a39e643f1b0f594fbe5029b0ad5c0970ccb4c55dd69074" . + "aca8612004d656fe24b048f29616fa37bfa6bc3f457a6878894d4978e8724837" . + "e90276b96385f41c62f822fb6d8e926fa81f49a671c1984b36df300da0525fda" . + "151bb37148c7e4ae5e1593205e6697f9127a76641b087dbb48a26a97a0d696fe" . + "9f326f68bfb84f96b93911a626327e778874c1262545e980da89182b0a45620b" . + "da658fca2e413e2067314125d0a6ade4b74b839fc7102a348742b9fa615dfb97" . + "845bbf1ff884576a1b3bba7819cd3f08a6b2e72851a6826e28e04179c89af675" . + "baeb7b1184c52c5d84353f3f81da4d21af5faca6e560db2b94eb1b73ae365f45" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "58b816098b30087261d8d21af782aecd7ad47f467a5a484e21d68772c023efe9" . + "e7b97a0a1059cc8fcf2b977fc7dc89ef7a5269f636fde84fbbdd3b47dec97c4d" . + "626ca114c9c75e5b3c41e598c28dfa3da8db8d4b32bd059d308bd7c155691d20" . + "6f4bc80c6aece022a0c1aed337d80d46da73ef2a00e7451d31a279b3460f9df2" . + "0eadf11beb74600e921ae529f84a932b7c31fbdc213784f7acecfc380272c72a" . + "a75ebc430b19f9e9c958ef4fc800817714fff2e36d15fb6a7081a6598028a669" . + "fc49f600e96e64c84ef0d29a35d69f442e84a36a5c0f3e82357a622dd6f5104f" . + "f636084849a182ae1fa60b488a7a563a8d6ba54be0b217967c7874cbcd0b12db" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "388f870545dd6243e0e9f33575c350ae7ed31565e6ce831127d26db1db16de8c" . + "b8276e10b072271fa968680119edf0cf98631cf905c05ab5af48f79f3816a522" . + "95bd6339157e328fad8829d49c4771cbb3d60588ebf0dbf84c015f794933dea9" . + "ba61d58901d6559e0023a7740aec0115888e352114e4161a45fee4c3072e77e3" . + "e16082af5d704629786f0f36835590c6a5eb2f2608c88df36e0ac173cb7c391d" . + "c25f2bb02e12388d5cbb9b456b6a0e613fab226ca985aa7bac8e80878bb8fbae" . + "dd5c478b1455739d7c054993d2d679b9e690cb3f535e4808faf5d2008da15deb" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8f2bd8911bbb2dce39a90c1697ccebb45bfc909b2ecf07a3acfa773800e3c26c" . + "20c5f4320dfe75773752c58dc88f5c0d9607c5cf020bbe9d4e7ff8c3ff8a4fb7" . + "aa008b418b7d5553a7614aa6b2aaf51ead88ef1145976ba358c1b41a0ee164a4" . + "111b4fb38fcb1dfde330848e9d0518785599456cdd7c807ea3d9bd36c4d2aa2f" . + "9edfec033503a186eb5627f61e62f9a21a35c4e9ce91d0c82373ce7991baff85" . + "b3f09d473d951e781eddb46df39c82a39b7d9ba27ef60faaf30dc58d80b70cb4" . + "e86ec728ddfc2a575e8d70ae99ce9f38cd8f9a140259b5f0985df30af9356de3" . + "ad89c3192ef823d39ef5c4e3958e629340a58a247f2ff6cef5ed372dcd2c28fc" . + "bd727872a1d07bf1d064918638782582a7c7c546350277a72a03be70df74b514" . + "53535e6173fc093b34b65254bb89c88d87b2ba378feb3bd9e05090b6a929e4c5" . + "bd1e957ef882d7614e5c330029c11fb6ece23be556b6bef488873dd0c1af8c79" . + "f9a2d0428191ac6c45aa32c015119e4bfe641119bb87acd0a053a405293a2fb5" . + "79aa00b23e0f9291c841c585b2c6b8589aef3fbfd2e285a8a8b90f7731d4abf4" . + "480dae14649035991c9999bfdabc6a5584fe9b40b29f7342509c0a8a8b4fe5eb" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "68c64e0627576881e2aa679337bc2b208bf392f8824281c25471f2787aded575" . + "f73da68a6541796bbce5d3daa93cd01819db77f93d5f567d725e9e9b2db8f448" . + "512bfd10bab01f7d1551e22b4240dd327bded3ffe218b18722376d6ee68ccbb4" . + "5c66fa2cc8b2acce83fba9cc7a507e94a27f588611f6d29283a9c788eacf036f" . + "d3d10d52a3f20dea5ec54588f96138488b64d822d95e5db61def62dd98f253be" . + "14e7fae8506b4b01f03ea9ae3f121d8b2cab9bf8d0abe7a6300266ce717168ab" . + "da51e7f1b2e5b4e106fd4044055559c90ebb7310477a82f15af07e9b5582d448" . + "b3060b5d03f26ea5361545d481e25175f1c0e80fcdfa792f4ed92360ce314ea3" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "99a2d2849290288c027e84ade5e9e89c26de7fc50f8395602b6b7ee13d915749" . + "019c962ecce4173b526e0fd138534694166c40e7c565ff19388d2d2801a8cd37" . + "f1da07179731f3e5e1c12cfc3ba27a3833372363c966914a60fa6cbb69e75b2b" . + "c0e75f20c4726d792a603a53889bb706cb9e0c09042016afdc679bb4b8e0e777" . + . + . + . + . + "c3ab4393ceb791b718ebc32b896518ddfa7d2fd8dc2e773db71057b84d9d72a7" . + "7a2fec0cded01a41ed101e2f086ff0eee816f6a77fe49dcf999e2fe4ef485878" . + "14ccfb2e01091075acad7674e6c5385d2ec51d0113c68d3153444dcad2662973" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "03766c70219ecf5c7bdb4202d70a998da5475b2fa3fc6d4c0aebd816a4e92cb8" . + "4f28aaa17eb4a80ae5f2ae052c9c5c9f260cec255322510ee7681b4465c8d4c4" . + "1985007dd473ab0bcf610d83aaf04f4aa7536e30cac63552b5ffff2ca2398160" . + "4bc1e988844272a23a270247db664354e946be969f93a0628ae5e6e90ca84126" . + "04c2b989788ad5d7811b1f38ddf47a5a72e2f1d629ea8090f7b5bd3f81cb6ad1" . + "f155646e6e1c30c22cea94328a378832ae0ef284967a2f49135b516ee614c31d" . + "67e32f83e2fad0ed8f92b7e9b37a7acddd9c703151f4f0f0bf117cab98e72985" . + "66679b39f8672076e56ff235929b91d8a6d5f14fd2b8350dd7b64f386401d1db" . + "33c5dce09efaa4a158102cff7e77517ce0693857fcfd197ab39080df53874091" . + "ecde474be05a27611bb2547d2bc2a2de3ebb1ad354252c166b58f7315a3ef9ff" . + "387096aa7686110878fa1dfb865870b5e4bfb9e5da99eaf5420526ef20b7c36a" . + "0fc570752a0d728306aad1b367b1f91107e53cd9004b947ad898c61cf7610294" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "a0e2fee30fb6c1077b529bf79c92a2199c792cc775922d175c0b40916f21cbf0" . + "908a723ca2d13ad2457d07d45f092ec2719ca8ee1101ddd1b0ab3aa34302e985" . + "0b62686771993388336483b31598e3bfabe0de5d0f2e1068ae8d1a007b8f7bc5" . + "0b9402db59078e1776e82652250987387b81f71c5627bf4e5d655d0823686000" . + "3583744951e0441d41217382fc255ecf9a3695648ac00338dc05ebf68a4ac4b1" . + "ca8d9ef4bfd8ff55c66203099fc8c409166274ee404ec1162f268aadcf6c0ada" . + "94908fb8fd81f91538249c14c68d084c2bf1bae744158b510d6620f86ac26794" . + "5d15f42722ee088eac927336d1360fa8e026ace1633949ec942eccd735ee73a7" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "511ac996130563cfb9121da38dd8da0d978101b314754b17361f6a4006260dcf" . + "aef7ec0af27d960c9f7f8351144b4dc37f074d3b920522fd93920d7ea131c49c" . + "695d91c44aa499c4e2226a16a860a773c5531cac34613124f5cfabea25345cf4" . + "e3cd9c560be5d8532a97f100dc00021263cb7e17b0e46247ea0fb48d1bf857ae" . + "916749832fb74da637d7431197abb39d0b6e74324a5becc17c5fc37da059c3bf" . + "7f88fe30a51b845f978d63e3d183f0a77c623e006214e7d2714a9183a12b68a6" . + "4a3742825fcddb038a450c6064a60e92be71a70ecc14a61430fdc231fd2359a8" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1aa88a71201c976d3d65700c5df7501811f71e469c87f334c757ddd5d690656d" . + "d7d4abc68a4f6959d1fafc6b81af24b91fbd39945159db209fec5bd4c370c969" . + "10972bde62d7296e7699305b76b6f2f7473330703b8238265abfb8855ddb8378" . + "7268c14a0c4333e84a440725e8db2091422cfa5e02caeb9892a3bb591ce52079" . + "d9db631ecf236b4228e394717b374016ad3fcc4f3be5becd3bdd01097a7c5225" . + "2b6061cba19aba1729b35d53c9dc417b230ca6cd5a92e4fabd722c564daa58f8" . + "de7c5c9b78f80addeb12228a26982f7795d475dce886e8003fbe746a8f493c43" . + "9717488b6e6dde669e203e9d905e1558f1400c3bdd7e34b1eb2dbb009ebdbd40" . + "001b9ac4c3a3867059756cef626fad9c37f4ab6b46376a25f5b206bc6df0ed2b" . + "6cfef462ed0516f61eeda6e1d48cdb13f793228089f758eb131aa6ebee928499" . + "6db36103947016caa6d7ee6cb822ccdf677ec788440b2a3b7ec53e2e36591a57" . + "f692081f6e1077a7f5a815fb347dd4aa5a42685c6ecb8c733d90c7aa708182e5" . + "293f8569992f44f04293c830a1b84863de3167eddb5402a3b222ffec0bc23c1c" . + "93fe3ed0aa6425293c902e16f573c85f64c7f1e89779ead3a187b50a605cebaf" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "b3f09d473d951e781eddb46df39c82a39b7d9ba27ef60faaf30dc58d80b70cb4" . + "a0feef77c72b93c2ebbc965e50f74931ebacad2c0d8e803df3a61aea45ec99a8" . + "891de1e7e6593a29bd12eac81ebaa538d1c4b85adcbc5121d9143920906155ec" . + "6e71637eb3e374df6f3aa55236a5a08b451b5037c220dd79a1eb1fe0f3253dd8" . + "dec25e1548a5cfc7dffd36c637feb8322a307b2d54b7d9f4e4c48b6d8444cf7a" . + "b8556e47fc23b144a714c84829d27fb6fdd3f1a37bd948d772c1a3813df2a239" . + "024415650097e3621cf5968e8f4cd8d8e08b00ce18188abf5baa31e4eb95a520" . + "7f9a568d09f54a35f9898c5166be6c538a1c49f06b1434ed7a26d6db1827b38e" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "b817a11c6e8e0d2897768dd3131ec6e91899995a9cfb5e3c58ed788094142b4f" . + "1db720ad1ba89d03d3e2a378e772234a7c5f688c270b6f23d3a45b6dabe4eb76" . + "d3bed16ee3ee3f6cf278e08f52658e2b1d04cc1dd1c181463a1e9bd75b4d235e" . + "e9947c6581d9fe57d888702d90ba02ca277b39774902fba08b691b82a7646b49" . + "b817a11c6e8e0d2897768dd3131ec6e91899995a9cfb5e3c58ed788094142b4f" . + "223c70af59b2c0eeaade860bd35e07b017ebc25b59d43d40ea833d8fbbd8cfa0" . + "271aea8a4a53bd388c14b9519d7eecabc4d8f3b632a78527777339c9520a1a65" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "67746d6eeb70c01d46c736286434fbcda4a654ad2c1be4c7baa7d3714191eb79" . + "67746d6eeb70c01d46c736286434fbcda4a654ad2c1be4c7baa7d3714191eb79" . + "cc080cbdddac41c08456c42841304c6bbb7b677975b4f750f14fe8eb4e455d53" . + "618ca66511d322991ca7d74b09054ce617b7e6e0af1b2c6dbfb4ea447735226d" . + "3e09f4a580fb27c3a72ded8191b33e8364a2030a08a0a886fcc46ec694b0de76" . + "4749f4231d5a4f57bcceb3087411d985b6cc1c6b6e06d7aadc472e3eacf41f7b" . + "76326a47480c0de4a9a7a52163b52a08afe88f75e082ecd098f6b27fd89554ac" . + "f0b6bdca25d3e8db64ccd721cada617e5d704153de4fcfd4527beeb143e4a924" . + "36dacb8ead1cf2328d75337d452601f0abd536205d3397211532d63d209e4781" . + "792a9c2950c8930d8bd5160ecbb48516995e60f6cf46bda0705587cb0f4fb041" . + "263f36c44151927d91f13ad1198a6a8b9620402b793cbff7f24708be972559e7" . + "2c0a79785fa829a66c5cfe961dfa669f2a7212b9ea514429926757e74ae68e42" . + "b23da302446cfde9699f4d15feb0412e4e99bffe813a9f161f4ef9cc1d924e26" . + "448d8834930f6968d0d9df1bfc5425cd5922b6a8f80ba9420ae3d566029661ac" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "fb36e8f3838077d9e6e09da2d2a4f70860d4e3ad0ee5871900d7f33f574a6400" . + "afc2e571141f23f748a5f56df59f92690ff9a9dba6ff16804607aa10c97e9ba2" . + "67a9ec4ad964d187f0e976817f4108939cb613e1cfc565739424e527744ece97" . + "9f96aefdb0d15f028b00b43bab1c29bf69756e699b68d522f45a2051b6769817" . + "f3724e9cd153ad8ef1ea4c67243b090cc167d228a9dbe2d54b6e28d74b2ba8c6" . + "ae047901500bec3fa42ce9692052bd0eedfe5f3563fe87f26120a331296a73cb" . + "5cb3d23b66e23e19e823c81aee969125e8860809b9a78c876324fa32c37abca0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "4cf37cbbe0c3cde15e26bfb089256985290bbcc10e5ade0f9e85fcff3356906c" . + "a7e29f6d7dc721bcf1cc80bd76201ef5f11a05f101f6852cf14d772ebb0ef4db" . + "8cd5b5d84a572dbd76a7f5bcf164240e3f77a524f4f96b57a005849c2cd2e373" . + "0e6adb90d2bbe14ab056cb3a32d5d6b4071abd53301ed544a3197c69a2ac24f1" . + "8f9c7afed2d77eb2d24bc346434127720f292a45ef0a45947b9aa69c460e1eb5" . + "bb866abc226e0a96b6abe3ca01687bcb5df0a63ed05662a95872ed2969b45ede" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7174cb8dd219dfe375bcdf48e364ae58e26c38a32f4f87f99d4631c2da31538e" . + "7174cb8dd219dfe375bcdf48e364ae58e26c38a32f4f87f99d4631c2da31538e" . + "99a2e1a3b9a871ce4452cbf0f48512ab5ea16a94349670bb97cfc4ba7fa69cd3" . + "fd1c3e025922ce3c6d92c107b0c0580f16ac4441ad88fbaac1060d594d1d7b41" . + "859cadef6e03a592a294ed5650925764b68399c9775118f60ebe9b9fa4e60eb0" . + "01c0980b807256dbda5c964ea682f94536a6f349079b4c8e6661749f62da126c" . + "fc769566e2b2de22e44ffee91d2753f2fb6932efc44e5969a67e2dbec75b8884" . + "b5d4595cbfe5fa0ab632dc298b314274ace3ab28320b04d4618bb09952a45663" . + "e2c9fb6bd777c8f4ee9765fd31885bf8bc32819da19ebf765f798ac618ebc069" . + "67b16614db4bafdc1a4ec0f8cb40c2efa3de0d3ab62be1622c87d95a2b3d3ad3" . + "a61b5908eb4532d2fa697b2add8c72844e4569a9a9306ffc640bdfc5da4fa63e" . + "3efc939282acb82b72450aec58b166d7d6b466265e21c208b6607332797fee57" . + "3bf887684f4aa18a906f707960fefc882a209ad7394cb2f7c51ef7c99654b295" . + "6c58e4723e1c1ca7ab2a43c488c442c2f7a20845697248f30dd34ed2e4cfeaf8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "18eb134e1fbe2fcade9ca2fc53e44dc35fe3367e7bfd54cb7925d40bf4ae1588" . + "276869cc3e972b57f22d1dea6c3bcf228cc66a478fc34cc70111b216ade938fa" . + "bb655d99b221881c85f921952fc0a8e265bb873d1beb18d1209360985bdc627c" . + "ae81ef7a6b15a259438e512c4bbac79b85d93aa583514ea9f8452d71361df199" . + "c12cefbcbe44def4d42ebf121d489d60dd27e997a5c940f85005e13760c67185" . + "d575d620d81a45dcb359c4665c08a9987b7b569b9ed21a1507a16ce330880259" . + "ef74d6b6d99cce0033dce8d90ed8933ac922f3a7f662f315d5c0dae889349837" . + "56535aa17cb1a79275a35a5610787353a6d4c5d133cc2c23f8ae61e4699ff52e" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "66e9a3d24cb40666a43bd153e93d342097dd30f24aec6ec134e64e406023b993" . + "925a72be9b1a25fadf0cebbafe76c3abb8fc4bf1d893183d880d5d4e399ce37e" . + "4d8e1067cd0434bc8111102f7a76975d353bf7f419d110df0e64c6cd1bfe2c50" . + "4aa9538cbdac1e73b3204b55267f844e61b10712888162c43ab2e51c8ed38648" . + . + . + "94b8cdd5bc20087faf56928d862e2f27fc4b1b401b3824d2718a70b8780320b9" . + "af507c4278743942d9f4985ce1b38fa391f3f1c3694b8122e7a00d26707ae201" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1be500fff198dbbd8478be8b064cd831f1e88f3913100efd02e721ce9fd1ce15" . + "a643f6e9d5baa574ff4518897fb4ee3b3800a18c688a27b39c206ae9c5674256" . + "6a865ae60059ff6652d483218423364622fdf667dc79cef82e76f4b16b2eeb04" . + "4f5a5940f73ea287140f633dee027092742393a5954e1f9c1650b437d6c76e7c" . + "627ee487e6fc24b6e754a3e6910d18f68abcb1c7a69a5c1053cbcefb377336cf" . + "1f11f4741ef81fe41336cf07f384596b64a0b89aeb344ba89568363dd0ce1477" . + "226d77afb0bce3e843b81718ecf62ca1542e8c2f7255fa073e4a0da706ccb048" . + "2a6629163c1fc054c4011d97406b0b7b848d5da78f70dfabac443e398bce22eb" . + "d74775e46e9dddb4b55641f49815822555a2ae659b1e4ab99bdca91db6940088" . + "bd3988708b1f4008d08568cc2d6f7010d43a9f021ff55ca801b684bb81ea291b" . + "9f2019f33ff032007f5b21453c704620654058afe4db47f55bd189e855e669a2" . + "0d3f17257bb74284b96b3c955fbfd3efc8e9c2ab4e5d76f46a3712aacdb7042c" . + "6dd1e3c5bd83224f8fcf54d150fa8b7ed0550afd33eebd574901a3f6a07e92c9" . + "ea9510ff4baf7dc9ad499a730ab73bc25fc3231ab934704970553ef27fba453d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "00ad7e88c1fe908b2079a169c59f40f10955391dd9ab74e42e0e374154f3ca7e" . + "78322070e48e9e1c50ae918cb3ae1456d37f8ad49534d6e7813c1c2d91bcb379" . + "d909f673e7d89336222c5f016cfe91784093461ed4681f751d1536b94f99feda" . + "d6832397f18678381bbc63171ffa371e361f27d40ec98635c7672b57045441c4" . + "b424246489e14f49d466f9ecc58b707aee133d23f08eb349501c24fdc3eeacc3" . + "983218c947937fe596a35b5e27cfe821c7ee66039fb597ce58dccd332d3f2617" . + "485c33a198da5a75a75fac0c8f5ea3bf09f07451538ad4aeb2f902eb27c6277d" . + "365692675aacaa43770191dc4cb59e379f888f18abdc036739522cf30bc678be" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c736eb3238b3c3a3c315d44ae10af6fafd317d8ace444084d38cdcb50fc2c211" . + "70c5c3bbbd064dba8c5e84924cff01c72598ce52e997149bfc77a5506c9e63ed" . + "fcad24214a9a20dd18429d14a82b53a487372886355828be3e3f372f16c5fc84" . + "a53d6bec93184c69261e2363c64e37f18a3f111e2bc73d081694854769615a77" . + "b89904ecc29a6bfa34d87df946cee4b3d168ae4bfb9c17f751312d08d77b7657" . + "fed1ec55d54748eac1eab7738f0cb9e0643713888ab0374c0a8bb10342ae5444" . + "bd0c9c55651989d84137f7d9ae5365955f7b60e2d4bed2224ccb64a41c96309c" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0d4f29408d05830efb6bd319aa5b88b0155b3770247a2463612fc5ecf06bf633" . + "538ae9b074f088460392b88be09b1c950258e23ad3dfd1e97b8f1016d7aa3a4c" . + "79f56e897eaf2215b645b49027119fd416cc2dde7ad25d34d2ac2ef142e6d750" . + "28c9da3d1e380ae0cab159147b778b350840fe6c438167a1f2ec505f092f58fc" . + "5ef2195500fa6aeb161eef97e3edeebbbef1c98d965146ccae5534ad16035420" . + "30f1e594f1dbe586d14a6c5e5c62d558947b39009804ca3fa06bb5e137c5eb9c" . + "39d82ee3b6f336b89e3999b0238f2b36f8ca5c2a1011cb7f5c82a6df46d6a020" . + "6473e192df2c88a78dcecf874c07ebeb314cbbd7c2a6740cc1853d68eaa78130" . + "8129427f6ad08aea9458dfa54c1822119d126ff5d75d72b8e2f287b5735bb305" . + "ff0389c287e92130e8e6974edb181cd2980a1e05ac4ecc26f85825e4c1177ced" . + "4586942943fe448923905bc7adb62c1ceeaf1dfcdc61bb3b051d477cd6d0910f" . + "95f46e523d17e24c71ac20e61327112e93064e2bee601170654e0ee550fb5e35" . + "14be5ce91f40cf9dc1bf812c662eba4bd27cc5d8eb40191d59d14d0a170b8695" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "dd5b6d595627396af9d5e0b7f689f047a9aa88d07b581b9cd9078c01b335cde7" . + "f1e5d95013afcdc070a6d3ece78ae24121e6d52c83aa41cdcd86f29bbc319df3" . + "fe0f2de4394665527755087be08984cb40021cf3e43ab216133c30d9d7fe7dbf" . + "e74a523747dc61a77e4f6e12db35d6750705dd8936794ee7d022aab48a9031ba" . + "4b78e1ba8ea19021ab7aa0e27257c518863f65a1ffd510a5bdf13e0bdb2b325b" . + "8aea0d36efa55b6613fd0aabe3eada60390b8f180f3b1a7fdc282a7d272bccf1" . + "05eb514c906422cf56097eae6a0eaab671ac9e9376b4e3bdb43688b39aab620a" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "e729da3a518aa871da3bb60a4a85f6b9d0fe92214ed77f38fa7ec13aef3813a2" . + "8b8be377ae88664c2e6b3fcb253b907bc38af8db5f0a2c81f310de0afcb1a38e" . + "968259ab436feab20f9afaded8992503c43f8f4d17c6fd0006d3761bac267de5" . + "66fde7836c07bc13f568d627bc035288461e0298b4326493d313b78532661cef" . + "e729da3a518aa871da3bb60a4a85f6b9d0fe92214ed77f38fa7ec13aef3813a2" . + "6f0d9a17877833ec84e100f855d8daf8ebd01d5d7fae8cff96c952b721d21d1c" . + "7d6e905c210a46b8ced0fc2032f66ce8a922cf0edb5f8ddbd71cffa591831f2e" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9fddac05966297fe9db24b4e46649bfbb2e96359533f9a0bea8334ead3e447f9" . + "9fddac05966297fe9db24b4e46649bfbb2e96359533f9a0bea8334ead3e447f9" . + "3e741eaf635d8024240eb73ac67f9f6b844fee0576ca2c60fc084951a174b2fc" . + "f3a58a47b1f4581c3aa69cf581ea32681cbfd07a2f1df879e8faca6f3a8d93dc" . + "c15ab2067f5a088707260523231774b8dd496e6268f576cd9d4d60c4107e360b" . + "7f76a0785f53c06a8f45c1db24e5e014fdddcc279bd3b24022b69e8a6e4183cd" . + "bcac6c5f51d3b94e39e882a8acb09c271efcb83307b9701d9a6bb1153348b1ae" . + "dbea16c5a2bdd8fbbc77848897a1755a9002ef529562ee9a4aa4f34bf1d5e5c7" . + "c138d0a945c70ee7c87e2001a2487d2a6d49fef64f401e6b96b807cc41c12003" . + "7710c75ba026d645d1108f0df9b45d39e9da618e0b5eb08bee77565447a1dcbc" . + "90d5e61ac22547b02b67328422bc034924fda02c253ce68ed7769a25cd77de51" . + "2b891b144fd43f4841633cb3e37c2754e56c2b5d24bc55e1891af3a06e7cab9e" . + "5084e23682d6cc9c3504f1151d8ebd91e7640580ddf29021e6ba317706cf81b1" . + "d8441a0909c04291ce7b696f8e4cac5db1101295eb18f75a1bd00beb29bf2932" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "a6e230ab6fc30ec8bcdd0769c21b8b0811867d95876198dc49911fa01021bfb9" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "8d83af47468813e862001faf8f92360705666baafa9de0af6f231008eee091f6" . + "11c3fae437259d59d74c43bb7938d5aa2c4cb7a4570f940701909c0b08a54262" . + "4106eb1454ae5053ab7591ec9731882e9e7afeefe1a94faf9140f23161427ce5" . + "72cde96c43dc777084ecfa2a41adb078ac4abdee999c262e11b06111eb011901" . + "76ef2d4c663b2420536eeac1b6ee2401bb3c174d405e48ef8845bc2776313503" . + "dc2757872a7a3f6868e56e8d6dca0a65dc93c14d4edc9cdc2d73486817f5fe9e" . + "d7ecb3238aace4af2c5edf3f71c553f90e7e6039f06181f6bcb08363ed0ef41b" . + "e78e68a473b25f9b83a22efa464094be8b444646ee7cb0961a0778cc95b9f061" . + "f68c0b1f09ab82069acfd7eee3389553cef25248a12c153310d41c345c4bf3d6" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "6d48b9975ac1056087ef32a34eb8469928121f7f55dc8ffa1a1d66023f1bfef6" . + "35d072d258c773abb7176bb5efc2402b660001ba355f6cb0c33a223e3da8809f" . + "46e88afe5b6f1c3c1e13e3c1d11ee2646707ceed8ecbc2c4aac68fa17f8fd6ba" . + "73546fec7fb87e1e7e341651d8885ca8ede0806aa40a242d9b385543f6040d6f" . + "39f8ad38b5ece1ec8ed7c34ab2505a534c456f9a76e5632429f2836168ab5637" . + "0183808d9ef63e364264cf056c2f03a5473ebbfec6a819b6a4da2741abfe1722" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f9bb99a98ee57c1fd065ef5cd49254434698248770ec44db0ab03e1034fafb33" . + "f9bb99a98ee57c1fd065ef5cd49254434698248770ec44db0ab03e1034fafb33" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "ab143741b8b6f7e7498ba1e48dac8d7bcf2ebfd2ac2ab5f3458c41ad0832431c" . + "e1a3e79fa4b1390e05b9e4145b8aafae1716be723ec98a0165e89c8454a625d6" . + "1367a52b81efd86315e90f7019bb361c9ab5a111b26398a0868dd921b9e385a1" . + "6436857a1cf8c7168d50f29bef0d5f86400b3140419388fcf3526fd563875ade" . + "fe0f2de4394665527755087be08984cb40021cf3e43ab216133c30d9d7fe7dbf" . + "eae84ac686fb0592c50ffb31a82da0261c5562b67e257f8ccd77044a29293a89" . + "d4e255a62d2ee79c5df71ff67b9e9cacd2b998420137a61e21a052066f9a7ec8" . + "7b67d0dcf945e1955176ddb32ae717da546aa18ec9f7d05c79372a9d08d30891" . + "5e6ef06cd77648158f26324f4f2191e27dd16743fd5b17eee1c0051b918b524a" . + "47e23d0cf1967f4d913dc63d2377570320be47c8c462471cdb92843840b9c1af" . + "f172eea2050757e4158e3df6c775faadb5b3b77659a252f1e7fa663021cf0482" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "2913140872fd660ef0d6a4b253abf43232fa8a106de9b14f52bb73937ee47950" . + "00d3df5105484cf78dbfdc5d5a730accd976de53e2e7a3e236bac2117e301de6" . + "4f6a5fb040c9a58628134dcfb46a3e303359faae9c97c480a2490c4cbacc3a27" . + "5527076394969e96497c24a8797d56a54269648c73a6ebc1f17dfb782f3ba93e" . + "a718c01ca1a4341c17ab24dfba8007366b66d77cec1603b0cfb35d2fa3ec53cd" . + "e80131af8fe5855205b22736a52e1bfc3445f59073ec7e18e3f0cc24f3e15812" . + "b0e5ebf723c21581b76e1f6053d07ae423ab9aaf071572af0c3646e259a03663" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8a12b1506575f7027f23401b3221c555bafe837b816482fd481d20f85c5f7424" . + "129441df1d199ca617ec0de38bc8b2861a338676831dbc19e89a2bd081c1e573" . + "97099bff065775b14723148d70180a18fcd17c410f6a82db09b7452de59a57ac" . + "70725c5bfc7d1911e67012f0287806a9e0a9d47be2bf45442f79d1caa4ff2442" . + "2e928e4612f523f34c52a79eb3d8e3b9c50a6f54eb48f4536eba2c4df29129ba" . + "89d3cc20f01fde6ad44c19a15c774285ad7fdb01f089684d797304e325d5d89f" . + "e2347123010e1784c704019887e805ac8129b8c6f324eece40b6d681943913aa" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eb431c2e5b621ddf44853ccd14ecc0c746a5b5683051211343f03e06bb5cb70d" . + "6784be0952908a10a61730fe56f4270b27c5f8e1bdd4653a5c7cc8d137b3ce43" . + "e7f75000880ba9426340d09cab41765555e9d83a0fb091c238e0aa5b7f654880" . + "b0519c546dfcfb5f68d974f665bf610eb9a56b583fe269a21d595c217c632151" . + "ed3242bf739a5bf53c771c4fa99f4df658801074ac4fca18a860bc00ac13f230" . + . + "4a55a8405865a227640eb9a2bbf7e37d83fd5affaa5249b074150900f3492220" . + "e4518fbe33d59110b5a7fab48876876af385af64881a4fcf0feb93b3df794fa4" . + "5ebdd6eefdcd8e80ab7168a548221d390c2be00f0576e3e65406464ba7a4d642" . + "8f4db0489538b4628307cc66ccaa4f277091b0603832dda3f00e9bfcd5b08ec2" . + "53ee53bdf587e9b87292ec6c980f2231860775d44a09dd39a2168f65bb446ee4" . + "ebba54c654be1366c5bd29029d209b975b3c651073f32d6cee7444459805ee2e" . + "568b6501d56a4900efc966f62d61a675101bca757d4f985cd513f04409b7b9e5" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "769ca91ea45aea1f37ce73ea0796c08e4c97758623dc2c09f95b6d0e228818f4" . + "769ca91ea45aea1f37ce73ea0796c08e4c97758623dc2c09f95b6d0e228818f4" . + "283a51e76038d96cf4831ad3fb4e43433227e83cc35d5badbabcc814276ac1c6" . + "dccb0c05359cc949f4fac1136a806715d96157f254bb2cd6a82ff08dbdf02a57" . + "1bf1b06fe6f027bbb4031ce99af54ab31a720574c640da278e37130efab5d4fe" . + . + "7909c5a677a1d66a8960d8a700d5ccfaf29e1b5be1a801ef5a8caf5bd4b54e08" . + "fc4a3b663e5af615fbb91c6884beda3867035d3a246515261dd7c565d4b252d2" . + "0bdcbc705e945c5bd5de78bede1e23411360741f1a26a4d4b3dbb2aa2e1c9fa0" . + "82ef415545d171a15f6a891c49cc070b3270a1971e814488515947af29556b8f" . + "58c74cad8d811ff2f1a0f1d75d32286a2fcb3c197f43a8b47375faa2b04c926f" . + "8ea2fdfd10de99f0bd7341d115da029231a6aaf1a0545f1649d6ad35e8519ba3" . + "b010d6cd7fb854e565a36f1426f7154346f6d76dbc6f0c1f86a6ce79ea7c5f90" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "8988fa85aa728163ffb02340e752dc494bc182cb49a08751ed11fdf1998876ac" . + "8988fa85aa728163ffb02340e752dc494bc182cb49a08751ed11fdf1998876ac" . + "917ee9f0ee9fea4cd329b8d1a4d194b5ca10e1e693fab7ae13ea0c383b78eea0" . + "a50ef4e651d919c42f8c89d6fb0aee2ce3fbcd912bce2d2edd24217648372e89" . + "0a0407c18d3d672f69144b40ff6bddfe2d5142fd19bb4baad84bcc4dcf698582" . + "dab6fa2c3d396bf723c832ac2cf197dbfc007f0f403e8a5ce50efd248cc5e51b" . + "91bee9e68f5990d1f71f30676aeb77ff0ab30aa8990f1a039b5a9a2e2695ac3d" . + "44e3c49999bb7ccef10a1976f511d88a028efd139ea671ca9cb6fba3b00def7f" . + "41434b0a67529e8adde43e52c7155b835b63ac3c6b61bedd00203e2b57e094b7" . + "d701365794e2a91c8d19f5acee8706362d27caf2aa59f09cf124d79da871f739" . + "5596299fbaf76347b636a7e7c03547a9f0e23fa9e15e55d6f7180661fd3d2d40" . + "2412c0aec85e180be956e4630e66244c597eb7107df808b6239259805dcec159" . + "deaf30523b03b5be138b8fc836be04b3ba0b6b63478d230d23eae54b0a643a44" . + "2c8ae8939228bd19f5fa13882b341292141a5d147c61257db543db7c94bb8195" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "7e6f13977b26737468f11ebeb50a350d8ebd81ed86adc04d7876b68f7df40318" . + "27c0804676616e3489406cc820c8e88d1141f7daf1f5d520aec1bc8831d53ced" . + "4f6a5fb040c9a58628134dcfb46a3e303359faae9c97c480a2490c4cbacc3a27" . + "62dccdbbc0d7480acef14b83a432ca5a88597ca18f99544b8f666157b6f89360" . + "fd13ed88d5a558550bed8cd17d454fb938522228937f0f82daf9323981bcfb34" . + "f3c7c8f95829514ca00d2e0410deed55f6b203c309c5113c4c473e82dc650e34" . + "54bb0f97161fb56035c8864d6d84d599755905fa59757cf6f3d85f520043106d" . + "016a6f2d2d45c3abb36cb844a91a0071fc03e5251d34632811c35fa934b53b06" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "7c405d40264a69b73792cb7c809d606eda8ef822bcf26164776d1a2c6abd673f" . + "330d1a23c89af2f9d4757e7615ffc1da3b656026712b9bf389cbd5abc1108066" . + "a2cabda81d87b31c6976ca218f68b4cf2c11f4d6b7e7f293db88a332be775b67" . + "1fcf4e2803cd0420c0e8c69f3476077039d4b99642f411a70c59f1884c30233b" . + "b404c9dc1925fefbf3a8b7f6bfcec6df601cf9879829b1499ebbd223734573bd" . + "9aa07c7b5b031e09f7198313dd25bfb9ff38e25a79ba774d286233c5ad8ff520" . + "ee6e6b94ee269d5a1d2bd2084164dafcc6168d94337492d11dd02422d8751e20" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "78df79e64be2c3c2c9f9e052d80b841680e5a781934181448ad0125879a94da3" . + "78df79e64be2c3c2c9f9e052d80b841680e5a781934181448ad0125879a94da3" . + "4543eea0ceda26f3d3f807f10bf5ee5cbb8f81356ba22e45e7e251f0fe1babe4" . + "d1fb603c9e5dd1c0a8d978197b8c3d49ac3819ef5fa2e584c9b25d653f88fa5a" . + "61fd66e01fbdf8a07029dcb20b3bd900a76f29a6bcadae3788b6516fde074393" . + "ce3104966228102195b9ba45a146fac673e85fe56f5bef06416086bb667620ed" . + "fa8d9f2ad69b70b760496a1ad37867ecf284176335cbdf64313aa500b97b8abb" . + "db77f872edee20250f0ad538829a89dad0b10892c42529b24d653ce0b64b88b0" . + "1c67860989ded83b272df3d251172f36eab102ad5b1fd1eafb16dd1d0c87bbcb" . + "56d40e0b087c3fd002b9851420e957de1e37a956554c849c20c0216004b5e81e" . + "75b0d66c47571c5e723b344592d32e090f1c9c6cb0ce1180b0bffada0345da73" . + "1cf781672769e626ea64be93e4e8878bdb3398bfefe376cc210ebe103ee760fd" . + "a0b70ebc33972721f207906b76775dd5203f86071a721a23a6d96e90ecdf9a21" . + "fad1ae46593225793eb11aa0ffc820f8612204191facdfbfc42c7ef4443b6fdd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "cf353dafe99b173f0fd5f69b73b591cf6a1ec1b40f8d183fc742dfaf1d1fc52b" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "27242452492bdcb40fc97af8a9e1150fca4140f8f689b6ea24f00cd2e42ca8a8" . + "28e1ffc18e7d3c0759a14600a9c833cdf39ce4cccbbc67c68136de3329aaa5ae" . + "fac6d080b741b2d0cbff43caece643f6d519fc33fd3b611b64c21fd38c1b0950" . + "616360f687e7d4ee2a9c72347a7816d430cb903d6e6a3d0dd9aad86c8a343448" . + "57c744244635cc26cc31da2a9545a5e93087aa5d40463fd2249c75a1dba7a326" . + "9434159183289127a0313bf23342579476640c2c71f31df81945417b4fe6a12e" . + "b4f9e73b2bd26c76355fd5a4d41e7efb1898cb01fde586ddb9e59554a6e402de" . + "f18ffc23384d5c2de5e255891ce619997153bc626336662a4ad7e37a16aa02a4" . + "9944ab64d99098391f515fa8efc42b7d10cae6e7a851c49ba1a9e9cf88682e32" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "87cf07475081a0533744d3b5533dd0c27a9d0a100263b3ac995e0e7872bc7dc3" . + "3465b50326f47f1cfe26a19999f235062660fe68ed4a23b678ece033e78ce4bf" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + "3e741eaf635d8024240eb73ac67f9f6b844fee0576ca2c60fc084951a174b2fc" . + "63b19986be877cdc847ca5898112f8e9e3586c32d9bf2c17266ed573742a3121" . + "805c06a477482d2beb56606a04711cb34f9a75a62e55160aaca1ca49e9594fda" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "09a42d51aa19023a2d0bef6611adbd4b2f42d790d3c3ab6d0ee925c07f1e866d" . + "09a42d51aa19023a2d0bef6611adbd4b2f42d790d3c3ab6d0ee925c07f1e866d" . + "3f33b4128a18e06ed3c3615e3c56d9972fdab3d476b8ee7be4d0224a336b89d5" . + "f585b71f98305608e99ef9c5e83e05e085610d53354c11558dcdafdd48c86efe" . + "72bc826e4d0735711891fe3a284ba4fcadbbf59e8b6d6cbbb028c47cdbd6c766" . + "7f29a39671ae7ae466fa52c66bbe8fe0d19e34d1ca28636f6d057b279a0f8443" . + "a9823fac168968603827aafdb10c95c2acaa965b14baa62be4da9d408badf08d" . + "77c950fd2f0b920a28b18a11b0d4fe3ac257312302e8b22bd31b53e704b1585e" . + "0752b7a51d7e3068fcd125f8a2893213483d88cfe2f42d6f28bd8621dce7973e" . + "bf0eee8315bf0db05356fc0b5d6f1f08dfcaadd1bd4373fca7654721046df8f6" . + "2346bd88a3b9c4bdb86ebba6d4a18a068a107ae34b3026c4f090841937113df1" . + "f250624506f28b0ef839bb5b26de6267ae5a541ecdc45477b548d978d2a6dfe1" . + "cc4d23b5764d79c050497720acbc4e124c4e840a5dbcaaa2ec618b8edc19af1f" . + "319abafb84bc601327a312b457183e8148a11759392b68d03f8a32a5e1d3b8e9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "2913140872fd660ef0d6a4b253abf43232fa8a106de9b14f52bb73937ee47950" . + "07f887812a7e50940f877c6eba895bbb757ace1685d49246eb216ed91168e0ed" . + "27c0804676616e3489406cc820c8e88d1141f7daf1f5d520aec1bc8831d53ced" . + "b46fb6d87b0128117b0bb456537b58981db30924d9f0e6c3cbc41ea0cf0ddbd2" . + "76262416fcbbe201d50a63f51bbf202c4b54295cead83d11f5ccfe9be162c4d6" . + "afc17428fb87cd6f291643552cd25179cf0fc49baf89d1099682a7f271356139" . + "f3c7c8f95829514ca00d2e0410deed55f6b203c309c5113c4c473e82dc650e34" . + "0c227ba5e5ca4d328935010dcae924aba32648a03508268b1f25cb5a4f7a4f2b" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "0a385887bdbace49266ed953e8596cb03eecf323da8b2712b09b1263f22feffc" . + "2d96dd148599c9b7f23cb770efcc7e4b2c3a49c1e69fd6850c47a55484527114" . + "e593f5662db7ff660a0a96e3fb1d22a70d8e041ab7eb22957bf2335685264322" . + "7ae06e664a0f47fba9b43a42485faa19f3b3ca1072784cfe2a0f3dc45ac84779" . + "e623fa1ec720e3ac31bab5a6187a14f26fab7961b4ba92178790ddd2199e0e55" . + "745dfdd98cd5c9136bcf195ea63db350c5079b39059e8791e9cdc0a4ee95fe33" . + "2586c19a354d09959bf49c81d8679e3ee48278b2ec81c70f335bde4398b19ef2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "abbda8933a10261af308b63660a2fd49dca39d5ba6e64ae9be0857bf96e5c028" . + "3a880229e07f20846d8ab697ce4c7cfc6fda0262e5ac2bcbd8af71c66ff33d69" . + "a7d27e0fc8dc80fb20558d07df11291d1c1c2508fd065cd44f249151062e4b66" . + "b69b335224c9f59b6a7d265fe358f86de66a2b6103ed7eb3a8b84578f0b04190" . + "2a827ff87cd0e18394cebac5c44b0113282ffb523355d37d2045fc568f7757fa" . + "031dfa8f89316497933bfe5b723ed6fbc7b00a0c536997e593b65b92ab678be5" . + "7797bd0c29d7010e10e4baa923ef58ee7609fd15acac507619aace8ab39f19b8" . + "9918ea3fa61cf60fce550635e64d982a73d7136ed39d4e83bd84210a0762d21b" . + "41827d027fd93fc851ec823678e3bb107ef14198cbb12d5c8f0ea29c5e402cb0" . + "d6c7787d91a079651a8645d34c74b3848f67b6fcb42a6a2794e9bf2d08bcbffb" . + "447cb6a4e71d0b0b281029b18e88a3ebe6660f80b0a43e7cfc36dec90fad623f" . + "2bd7a3e00500c505b5caeecbe5f454f72f85502877c5e06c0d9ca6f4497dc40d" . + "178e78f33f8bb1f0663307a560bdcda1cfd113b36e0beac75f251919dd066478" . + "e71f97b5dc1055632e75edb3b58ebcea0184431ec44c370fdbd6fec2c02906ca" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "31768e9911bea443bf7104044578c3ebde46a8b6482aa6e4f708d34c35c75f14" . + "48f51a80955dc2d070b7035aa9a03f87baf97742512c6f0f2e497b1d3e843551" . + "16534910a817110ee4deb05660e37775d54e86ecd7b7f99f55b867c6b42f41a4" . + "12b021c4221bc33469bac092a6a60857ac7b0e19eca0d9d97b7876df57e14601" . + "6ba57c19c256bfaff68659e5ca78d4d9acc26b1b72668db61e4f33ffa37dd115" . + "eaf8d50556f8ebfba0331d467d9206dc5861c51d5d06fcb89f2da49d2bb72e40" . + "502f2afecdc91ce373024a78c703708eca1a04b080948da30817a722bbcafe64" . + "ca47049884fcb5f3258a3736d5d5dfa966e37eb9b978ff3ace512e368059ae48" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "e1ed54d359d867e9cccc4f5340063e9f144bb4642ac72fa2e532fed76e65d526" . + "e939902eb7e07ef682952e30f3a6ec19ac1659779b9affd3385974184003e54f" . + "0a00df3568f527e91fda29c31b06bf84acf63fc16f6fe77258fabbe34082923b" . + "0dfe1a8cc0e4dddda837d84fd907656be4ae730474d4eb6e588ae3eec33342df" . + "3bb749c0d69c30db505340adc23318ff3959cf313ffc0bb7dea72cc825ddb4e5" . + "f2f43f5f7d694b39955f67480bb89e25f6bf6a482a1a98286090935225c26333" . + "d23fb09be69efde69caf4e84d5d5bddabcb32f2cae55d7f3708ce8a939d15527" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "66c21464d9153899e7a18f464b9dddb90ed9961d6e1e3f3d99c7cc98cde27b3e" . + "b51ca1264d2556b76cd7250b99b52aa1e74b18aca5a4bc960ed54cbfb7766933" . + "aecfa7580cf9475714fa4a49f59bffdafa0953d0efab159178892b46285e6821" . + "fae1b217c5dbd013689663b6e491b88e5e06a91770b8fb00c2800bdad80432d5" . + "5251d70e09fd586e2c7fbf770c7fe438333dc5f7e8ceb926c5676a269cc00a57" . + "04803164d0dfd41c2e140d4608d4ebfa935d022befd905f5fa5e5ec4c8d2139d" . + "7f9b3261122f7af4aeccde0183ad6de06c489836159ef883c2163a0266bd0d83" . + "113c51b0e2ed5dbf9b491ee8843db28ed24e572af9387119c0edd595d11a4801" . + "466c45f00007c8de96a7fa5087667d389138d354b5d8d9f97f17f30770c4beb4" . + "02294ada3b5b3127c58f2b7f205793026f03f5c9902d782fb0b83a568dc3b002" . + "9ce47da43466cb4c4abb1864ccfc43f978b2c44ab37a47d0d93e3c7b8903bb89" . + "44c1a078ff6e370c3b5a1856b4aaf632adb57eb8dfbdb58c3ba4df6bc0562879" . + "1a260eabfb460beafd70064e41d8e2a73dac7161d682ba5ec006b803023f7683" . + "99071601ee6cb35c6a84ec5f21dc13edd3b38bed388d9f3f7f28d365ce3beb6e" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "85b6d2c3399478ecd344ec976090c10b581a1638225079e3f7ee57981497d739" . + "afc7ad8d97ae719bcf84034367b061026fd443323b21976cb7ca59c9c637a979" . + "d6437145ba27de4b1533cf72408f8cdf454f145ec56c4af0c9baa6cf79d6fc88" . + "04df419a8be94a502122f6d7614d97256007c9022cb9cfa1737eb6141eab4e83" . + "2de163dacc0d7926eb8b581dd954880a4f5fec617ec1aba5099dec4792186927" . + "d8e6055bc141966202b7b2e434377d588de4bd942c71105d959d92c91a06d66a" . + "5a35e423c4da0aecd9dc914f7a22e8a75a22d6ece98474f9505c57a7a926e23f" . + "2b311641492fea607cb4dd2d5ed9f8ba9484aa2014084d6b962c78450ba90f21" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "dc2874e02257571010200e12a73541c7ffef640c556d4183a6dd8d374edb1975" . + "d7e205efb1a4cdf74ed26c4c2c83cc767f60fbd07265714e638d390dcf027cc8" . + "3a795a2558b956482d0c5a9fc9bd3372b7d8f9833526a6ccfdf0cf0391d7a9b0" . + "4d6b1845431991a74c43855cd191290ce722f1b26f1e0e385d38bdcad09acae4" . + . + "dc3c4d9fc11d595c9542613a42220c27b84258ee1dfc66031f56206a11d98806" . + "aa766ba453abc0b8907b3b4c5372ffc6657622a0f0a4f0b0e6c7fef759f9ca8f" . + "091da9667877a3a56a0f857f0ebec93114f10fcb901bc73945b57f67b6d9501e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "77536fc8fcf026b7757c65ac1d0c5194ead93eb7a31549e551e07d652131d95d" . + "91aeef0f6da1bb4f006acf73db2459b766826ffaee23f29228b1329d7cbd5652" . + "7ddbb387a295d71e921ee59c66e7e2892031fb42bf9a89abfa03f4fd2a1ba90e" . + "248c3c98b1b96e1b133e2e753e45c2395150ba375ea651f0361d07bb9d40d0f0" . + "6e0b1d7d2433ef5c59f291a3fdaea9f9c3901c95408075a5bcb38ce70d07380a" . + "85d597045169fd903c8aed2709a30883404396114d12f0000ce5a68f91a1e806" . + "7b1c3548c21a482631afb113c7e0ee0ff194e212a14df73bba6af1406c7aa6d1" . + "4dd348d9793702a80b60afddbca899a658aab9f41b95f8a88213219c7ae11243" . + "e69927384142de2dfebda709af6cb892b390faf6905ceb5a63bd0e524a45bdd8" . + "27705ece02feb5d03ee30d323d44c725b69322ed8d59cbbc33e9357618c82fee" . + "6df722f35d3a2869906bcbb254dd43fb46e92a89c20c7113096aae7600a6770c" . + "729f8a1f509e83fe2670ae9ffdf6fcf3f552de5d9bf90d0a6b7bde9c346379b5" . + "c76ee51f1e44a6e499f6239182263914c2656a0bc4d3e5cf119e9edbc9b7ce2c" . + "6912f281db2dc1a5d13975468996f0486d3a41b3a9b4975c8c5f5b13f0222ffe" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d0a09db5a22cf36e8581a19f2342e3d96a4df9f794bec617d427b515f374fe85" . + "1dae05e52649120343527f8a9773056afbae379bedc314ff98640e7099103937" . + "7f96af764897d7e83b5545d9632b5fa7ef0663106fa5f0fffbcb432f8d0e8604" . + "997a573ff81ede73c9b40a5ba56d4fec9681f4a3a76a12090852ad70be6cc55a" . + "6070ff37b18c77e33716208785c2ba705ff298c6560fc4ec79b9ec74f3e44cc2" . + "8aa76ce55bc7bd2edf0c15861dd23504c3a761862b8d77cf3d0624b45c551627" . + "bf7ab6e9bc4a7899f90596ddadc097ea4e46937bd24849d56f562a8b4f311e9d" . + "4c653758d9b650bf06273532e5c8b0964d0cf25430a250317bfbaf6a120993f9" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "60c2ce0404845008e0ba3d4e3714743c749ae5f1a167689bb66e5f73cae88998" . + "d0b6b7e432fba38336457b7d2e0bcfab639baf9d89239ae67cb1b0698ccfa389" . + "6163381ba6718a9e87e30ee933a0c564f2fbaabde1a26eca10a364caf5f624d1" . + "94af0475c2afbf29bf1a72509487bc64502efb7f8ec5ec9756622fcc8ce39ebe" . + . + "c2a497749a84ca0e13a51788e9a68f247da8d81316b0633aab732f7e8d76a719" . + "971f38d1aed6fced76a78eed220169881b67fee52f08c79eff1dd62a0038fd7a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "72cac7cd0579a4d9843189c0c031ed2d14ee63ab4d8a07e863e1f73905f89f88" . + "dd6ca8523bab86760574a6c984b9430e3c3bf32eb615b3a0bda84e0f0dd74c74" . + "616e126bc5afc43318514b81e24b9f4dd61e91226ed61a4653af107000a544c2" . + "e0ca8ccfc22b718ad58a94a4295e363213ee88707bb3a4813754ccdf00984b3e" . + "d6f3bd40a79218cd1422ed9744235aeb04c3c74df0f057cb6a004149a6375226" . + "39a95585a028ed35bda46786eb143019762937f41abf9bec4d9d67def426014e" . + "85daae6571888dd9e4d36be9ea850cbdac64d72e2b57b2ff7237325184b6cf34" . + "262d83d4bf0284efaa182f41bc916b8d41d10fc5f7d52338e86ab41e0411af7b" . + "bf9d69cb80f0e4bde1e3ddd3c5d5238dab832c379a33c7a2397883f170254ee4" . + "f54e852945e4840fa453697b6b6c0f69709728ac9ee1d3a7253e713e02453a19" . + "04205639b42d98f37935d9b7972190dda955657fc457e9d004ee1843e1147595" . + "9fa057cb51f28eff6ba3384dc37ffc7655bb5ef4fe73a07165acad249ddef2b5" . + "519dc941018b1bc7ded8ba3c0c95ddd5ce0a62efa88e8acbf5e2406c533e364c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "374ec3734fe166477fdeeee64688e4545c5f2dd15c31164c0948cbbc82d23d6f" . + "ce980afc1dfa87a507e5bc665c166fa71f96ef1e151d57357d04d899dfa733b0" . + "f5c2490cc024118929d7a80917617c3ddda1bec5f11d647bf1cb685265757c75" . + "377e47130db2325df1a9e514b3083c9ab501d600a1b426955b2da4ebb96a984f" . + "3b0a970311d54a954f7296cf4c51dbadd8651bf955c22935aa91101627ae0dc0" . + "2c6ab52a74fc9d17c16a5704116e4032a360ce8ef948df2304e8de77d2fccdcf" . + "92a6a43bbd756162dd7a3938515ddba7a0b6f7b7889bc6de96b99672a76c4223" . + "5ab7c727cdd79afa1fc112e1340e26b88ef61e3a45ef851791e4aa0bb1054c39" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "91e269a1223980ddbb35741ddf606244e958dcd4f6c5e34f2e50ea7ddb965ee2" . + "5d47bb9d7b64363b230139857d5c3d4f8368a65453393708deceecf75f9e54d8" . + "c91117cc447e8ade7406e6dac0840e60fab7d5f61066d0c956288c1216e6e8b3" . + "9203d12692a9aad1439e63affcd0d64b878ccf3eed0213ebd112881152a1c719" . + . + "9a0db5c91a9f47ba6ac13c7689f6cf7e803185a9c8b71976c24fadd4284f689f" . + "33338d465aaea470fc042e14de9e4aef590bd3a7df16983b8947a2432cb1cdfe" . + "c33c1f957b68afd4be594f50acb76a3fbeb73cb315bb01ba595982de7578f2da" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "28d4082b700719fad0c7c193a937103de4b2913b19a2313c56bd6731ca398509" . + "64533047bd93a3f46679aeef6ac0b87e68df5249f108afac93c61364d9a8a29e" . + "ce7f098af34cd3678ed8511ed3392c594f54a1cc92c37c656028edc0b42b6f92" . + "fcd94138db7d604db26deca03fd8dcea6a9acbc62e2cd3ad901a09728d359136" . + "52c020e45291cbc3035f7e00a00c6ce855833daaf060b0d0a47fa4c71b634495" . + "73daf939d09ee8ae0723660f62d3c60daaf401a48decf6472ed273462a45406f" . + "dd79f0ec1af87e40e488691a5fe1c37505c4469adeefde8cebda9dabf5314ab8" . + "6a914b02711e025f841e913280301e7e4b050702958dd41aab5ce9da1b7886c5" . + "5c12b7fc73040a62f2220a18619149c348b77669bb7d7989c537109ed199554c" . + "d17837265b2850e6a491a0d52ffd2d630059c36ae454736a4520688ab3a135af" . + "fb043101cdcffdc016d0acf042c664bddb0e998c7f770a56193213e3821bc67e" . + "b89b2f91049be2fb38554d1a20d59da28390142e3b0065f8395c443b0088af78" . + "80de484ef1148b4d055fcb613019d6e50aee18bbf2317abc930f50a2e334adc4" . + "6e2d2790c48fde6c03243252ba280c9bc3e5af136e1c00f051a939b499c935f4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "65a17a7cc23de3c7595d6420afcdb2258dcf7300092906da0b9c2f9c9b196caf" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "7df24300092b2929967e6776f754a6f38312bdfa84992f027c6f12318abdb3bb" . + "76ee84679ba0e32714fc179a20c9a2a3af10f04c609730929ac50021a6bba76b" . + "8ee080a68f7327152de69e7aba16e5359f775e3b5163340bc1f5cee006e1a626" . + "7b1d4f23046c1ee8e181da53a80eb8890e1403a25b262abbe069fa683583260a" . + "0fb06c731a63072f6fb8bfd45bd7d0908155012b14a806f9973b572666511998" . + "4a19cb87082fa57ac8d935fdd44bdd78c2dd25a1b878b7c5af90a777e5e46ec4" . + "e90f7878ee5515be5b460261afd17e13ca12fcc0081abe4725c1462dd7ce101b" . + "6944565667ca9ddc2c3cec657cb809645687e18fde30c49dbf8d65a48183c551" . + "841ca3f31d76daa4bf666d5dd46fb8c707d8e797f3d3569c428be579ab71ecff" . + "b90e167873dcaa4547f662fe9eb99e36352c6215fae2b99c51b4a495951a3bdc" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "2f566030104250b9ce07319f789a0b5c2acb61b282afaab145cefcd4b2180efe" . + "2438e1823b50c282539721243112a9066a79dd6fafbd5652bd5525c271415ba5" . + "44a298c0c8a028626e5688e2b39e80947dbfcca7a3a883282289bbcf5ee455a9" . + "9149ce811fb29cc68ffca3bc08efffb0ebeb47f010395b7abeaa90cf878d22d0" . + "8473216f0f9e515829e3e93815c684300afe70ae0b5328284e93d9c8f3009b94" . + "a79d1018e8d10ecd08e8c247ae0bc0a121547175bbb3aa1d76801b63d78e6b9e" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7a666d5085e83bdb202231adaeae6b654cc9e7c789a3cdb74abe54ade676df4c" . + "d931f63bf63dc11e023119b7763b4ac45756e8b03bb5e9e0e61a77ba1d6c8ba8" . + "0d2fb88aa50641bff7bafe58cd0f9086762995a267bf3cf9ebf4a076267026ba" . + "4f3b588aaa9335a22cb57b20b9efcf539b4843f3d74c81cd7f630543dbedf6ba" . + "3fea71d016d714e7b607cec1f2ed60931cc1fc7c2dd2b191c4915c62a3a365ce" . + "a0c8d1cbc6b7521baf2bb70d32f4f1eddb2c4b933274a9dcc2db8ee6b1321451" . + "f402eabfb24842c8fb9fd8788d53d238e45e3eccc3646f385c9637f7ab582c7c" . + "36e04b18d6833047c1040adf89521599bf42c9fd7c733be1a7425eeffb37a684" . + "2f67a7d8f363d087df0b370140acb83f19186ef71c4a169c15fce3bba520f291" . + "a479a106f4739c19983b5c36bdd81231986209b0db299899f655b89388e1d6f4" . + "196e0308c2dedba76387d8c44fb956bdc57c781b03e0271e41ab6310098b04e4" . + "12edc155b653bb48886f3a7640bc138c154f8a45dee25d69e641f71e27a4d7f2" . + "1ce5753ceb97a741a4c8abc3b8c60db2bfbf209044d26fcae4d5e3fcf13b2ac2" . + "90ed62c85433ac8dfac2cc1819bcba70fa846ab5695a774ea67712ec7a982e82" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "4659aa164619da32648a0b1268de6082e9d5ba7a1582449ec8c955b08757b595" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "b0ba8998c6fbafef1cb7db30f4a787b5753d8afdd21e1e879fed223ab2dbc561" . + "7592e8ab7dca4f807f44f04c7a46b11df48a345591117525c3b0222ca255358f" . + "626ca114c9c75e5b3c41e598c28dfa3da8db8d4b32bd059d308bd7c155691d20" . + "d8e6055bc141966202b7b2e434377d588de4bd942c71105d959d92c91a06d66a" . + "68f98ab294b72dc5cc0771a2eda9c92a367e8b526abff02ca96cf5bb4c27fd8a" . + "3a2d2fa0ec99d78747c4cc4be178b74d2b73c01a4d650241d95c5cb92507a3a0" . + "2d05d80876acd1a298c421468767440f585634ed20b3838e09296497ecf79f45" . + "cb97229fb1cca2460a76c527f7ffc33100b2c9a91f00cd8d4640be5b6e67b724" . + "336a5dfd4e92b33f973d6348c2792388be6693e087b4210ee3625764be4326db" . + "1f7a0d83ea5efe4fb3f4a680396179a845cb13aa6237089e02e0a9958766b9f6" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "430a4261dd830e13c8c6264b8ebd0bb41eb98faa81233c26568acb9e58bf4077" . + "be71b085693f87be4c815e67c50a20d0bc48842f6fc473a07ec288b515569fd1" . + "0b215b66447d5014114e80b0c64fa52d7305306a75799e4241368e1176884cca" . + "a9ea247751a9afcc0a601e780b7ab3114b7a215713fc76f94bd83aaea50cdb27" . + . + . + . + "430a4261dd830e13c8c6264b8ebd0bb41eb98faa81233c26568acb9e58bf4077" . + "864548b2d2de4046acacd59558083d955733c7c4e5f56233cf3d0596a93818a6" . + "ef2078ce0bcb91779d42eef32a760c4f9fb6dad0aec0600c5035692ce5584797" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2820498981379ece0a8579c042fa7880426de50d7858c5826d55063ba0024c9d" . + "ce707fd3738b15bf1d7baafdfbc88504464214ff7618122797c9a7aef7e14338" . + "1790a406491216dbc70678e2ffc9b68e050de93e3df166d2f0f7bd464313b9d8" . + "c9d4fdf2bb2dc9073d1ecfa28613c600a511d34707c3109061a166d9bd4d31a6" . + "dca36595270a5ff901eaba6780c2e1963cd829f705704cbdc2225e384140a681" . + "93fe3ed0aa6425293c902e16f573c85f64c7f1e89779ead3a187b50a605cebaf" . + "b83bab2e43add7d25adfd66f1fedea0b1b2f5f3fb97ef830ff71b1d52794df8c" . + "313f958da3151e33fd40344b432dc67dfa7e86ad36a9e90e6d938b4b0380950f" . + "02855a73a8f8c3afc79a4fa5f288de368af2a482f98c8885ad8b11017c72543c" . + "f92592a18f1a84ef5b0b9dfc86aa5313c82f051832a5aef6d74cd56c1c776496" . + "130bb7947dee4c191cd7d899bbe2cf2f7d841d2bb4de417e2b5efe3d7b70c8d6" . + "a2357afe636251993022e160738aaa8e09a98156650f35bdbef43a3db7ccaeb4" . + "a2b63b678eeb05c837681fcca68973cd5541e150ff11f2da0aba0b0449654708" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "44433ba57d318114d3c5e3bf7ed51aef608773b3a140455aab509e756c5e4ae5" . + "4e77df282caf679428a826c690802bb22847606d10acd3e4d64ef1b9677aeefb" . + "9b21153355e1df42cf74558bc75b6c0ed3aac227180a7299bf161f07ab652667" . + "3be329c281fca7d0f56796b4b9d5a9864d93fe6530b2e4d09034187844ada5c2" . + "07bd576158b9d6471fd02160a582981d87e259bcdb9c3a36511101cbd47e9cb5" . + "e4bb45d45e1c2abd173420b3a5d2d1e9523f9a608451a9db4cc4779231830979" . + "ec4e06441cfc6adb7e2f86be82868a486f648da1e87aacbe20fe611cd47c7b75" . + "8b9f04e7d4155cafcbb31ef10431d04cb6defc4be0b5f33b4ed071a30550bac7" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "851aba0c22b41cd68549b372ce8522392b5f2b000fcfecb9f7672f0210791ecf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "3c41202a5dd01de04a655ec39f4eb114b036e79505b1d6735caebd9f9ef7562c" . + "63fa6dce005750ce4438324ea09ff52d105db23fcdb34485ace0e76adcb3d10d" . + "2567110cb06e83571f3462c7ca69b7df4ec5fa2671b8070754e237d3df13ca39" . + "5e4a314f5bb6a18226c567c9cef9bf24a5616947cb69ca4aadacef7943b95cff" . + "5c9d9fb0ce195435ef1c48e7951e16e16c5904961f70653dbe8fb13bd0402e39" . + "37647b12129d95833ac8cc5ee322511d2573f0d89766fd6fdfc13c8d36fd5ce6" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d621b061fd215a40e8e2f9dfc480652b7a9624c1bbf5a390293011a82782248d" . + "7f8d52232b09c215601e0ab6aeb23fb653fd23f5bcfe249bb20f24daca548327" . + "61f3e73f38dc9b67a162c5ca062c36db2d97a6e2646eaf595e92bbac285ca340" . + "602343bd2c970793d7495bad4338d5587ec32e80cea82743b29dee2afad972aa" . + "404f46abec9181a511136dc17b145d1e6a88e841af24817ef3e2e0e99d443593" . + "df85a1afdbca58c04ec27ecd9ffcabfa8d675c8c1f0b2273260ecb13962b1007" . + "596093a3807f5c658edaded7379895d55e76c827cd9c953d17014cea3ee4aae3" . + "2fa788ba876ced8b72d113a535f38a5bf377ec9505ee3bda97e328a1abb9e963" . + "b67e18bb8e307c41ac665a4f78ceba81a7ccd24f9c7d008274683d758bab9060" . + "fd09cf2f4e389a584d1c96678390e581c2aa300240bcf64323a2f7c6abc204e9" . + "109ffc576d7e6c1448de1177ff73a3ccc0a4aa37b4990c3db8bb145f55410cd4" . + "8403a70e1ef4487d9eb730fbf9f8747e9cd3df79d4367bfa6487fe9ec4d99390" . + "6d68acd3c236e3ca04750524f4d2591db2791c3beb3f9caa78a557aacf26e693" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "2475aff64272cdc22e86623fba6fc2821cbaf190990b6a592e56be5d98bd6b35" . + "f8a01d79b4270b26cf725daf0888fd5ece58abf64eee9ad6ec7aa2ad5592b5ed" . + "48b8fd38f93d1faae4cdf4e40d86af104abe4d2ae5b4d5a7f7521e71bd5e640f" . + "1ad4721d84110cd1f18f34a4dc713c589c828051583a56f8928e9d00996fca27" . + "a8184b4cd640893c893c732772d069d03ba9a58ef278793fd9019d52985042c4" . + "40f53e2b1fe8198469ba4bb57fa1cc06f01cdc132e93dc62496787978c022cae" . + "d3b3606d31e47250dd37f956ddbc58d4f8e6829045d88975b1f38c063bfa445d" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "7eb62394eef43ebf4f6034564489f37c95e59c8fd3f6ad63967cd6ba444c78ac" . + "042a10d51a8f5d157129ed6ad744fcc7b54dab554cc05776e620788d10be9a04" . + "51340421b835bb0713f473205fcd727c1f9931f181ea9895e674ec83f01f945b" . + "eada246249f70976fe63e1d131e1aa4d5e395e6812f9ad860c54a790bded69af" . + "000ca700e0750ba1fba360d7cadcd8e0557843c4f49210e8da12a7d6b5d19471" . + "fa784d15b134ac988f6789d9a4684c85ef9aba2318e8dcfd98bdb6a06e031a0a" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c037810ec56dd837899bb0da6bfab7629597d00a02dbdac91acced13e89b568e" . + "e82c10fac07a25cf23dcf99c6cb4eec5be317f56bc801abf9dfb576c6b8c3373" . + "58b971251314ea4df67486f770cb9068a5ea0f48da43a00a61fadf1356758708" . + "174358090126c46523e76a7249005d837fc8dfe761bfab2fd4a984c811d07a8c" . + "b7e855252633f9b84f768481dfaf85428864aa0d8994e3fa9253a12deea2a7b1" . + "eac5f097cd44c069274676291b9190f7e1f61eac7c509fa1cf0c3c7c9cf328b6" . + "1779e9f96a0ba11a28981a08e0a7880bab02c0b21eb337efae088de368835613" . + "3540d5d880795e28479bd51bfedd4ca392b0a0f289ebbe54d66b4920b2995e76" . + "dc81394560638b3e7f343d07a2281082d633887f1a9f75ff517f001cd4ce45a6" . + "db08d0b4f29126ebc11a51dc730aa5e6bfd83b9f51e969713227e765e039bb36" . + "3d4823c15552798208873ddf9148de86fcf600ba18dbacae6aa5dba627c5f41d" . + "82b1f9fc440ffa0215332d0058ddf86859c8f1817c0792bf2c964ff9ba95e679" . + "d4c90cd600997cb25080646150352f12c3318496e047cc78c45fec71cccec27a" . + "b5ee8b0096e0c8f1651c66989b5291291ae3adb5c8e959a63258c61682af0bcd" . + "c4dcc9211b0305e74ef26ea6c6d1675559ea145af5bff6748e4f0311f0a7a2dd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "148a864f2e4a83a2354275c9b138cbf198c79640ec4761bcfc222e47868dedaf" . + "4dc7a3a8497d2ebbb024cbd3ffa0625ee860f31be7bb951975ba8817020d2bfd" . + "f692081f6e1077a7f5a815fb347dd4aa5a42685c6ecb8c733d90c7aa708182e5" . + "e69927384142de2dfebda709af6cb892b390faf6905ceb5a63bd0e524a45bdd8" . + "50f6d914c76e41b599e03c299420fd0fc1d8e009cc9900bb4e7451454ccf3a5d" . + "224aaa8bc962191c310a9d002610ae323552c911e7c908f97dd1936cc397d41f" . + "b31a8d8a4c614b1a80592c94cd1148a184cba87f5fbcb661b38acc5733dd56c3" . + "df907ebf442d21c3fa597286cde96a666177a04030048978117bcb98a17e8b9e" . + "62959577bf841db4149f11f82b7f26ed7ceb410415a8e8d40ce00e46911a4833" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "98e32aa5eb941e5ce3fdd334c2a3bab40e11d854c64b371faca0bf37ed6d953c" . + "eb3c5ffce9707c9f7ec4f2b92ca544335fc4bc0f0837f810870ca3709fbb5f51" . + "c8512fd7c18374867604d88d1e61e17b2b37e09a5428036e52b082788c0d6e29" . + "e3d5b1d40ae5a3579a5561ce5f127e14c6598d303a06db516cfc64f29621bdbc" . + "4ec3656a3e61e8360dab7e154f4bf6cca1f8fac3018e13ad25853e2162d63865" . + "c08048b531de5723cdc4f12c2aeba1e24597cf7741ed28aecf091c56a2be5b24" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "386044a8ecc6049d80e5c186d0df15baa0963f13b22d80a39ddc64eeb3a9fc18" . + "3c1854617ab59bb9f4c96ce91fed3be882d3a7e9eabbcc0f8f02f74d31d259b4" . + "174ba1079549feb4e13e0033c2f328080b5bfaa7f401946fdf0e2f97c3ddd823" . + "2fd14c76d7f4aa68c6450f66a33030b2e8b959ffc515daefb9b111f3f5e018fb" . + "3819b99d4af188027e49f32b302f22e4d240dbbcca6572829e784c0cf1892217" . + "6c3a6b208ced401edc14fb3e7f10a7f68501b129c002bff2052888d3d0a575be" . + "1640ba09b1e044938f190a9b37325e5c610c9d1ef57d74fb07f95af34d35b38a" . + "f2f0d0cadc8e52d27209e7189baf58387609859d87917b767301d98180a6d3b3" . + "ef3b2a9c76aeaf7300ee722dc1932dc4883dae9b07ba263df94e74bc25f2bc30" . + "2f771db5875542cc19e39911cff974dd4105b9d5f66f6c7612ccd07b06e4030e" . + "2040a68ec77cab5962baa9aed004ebd3e708567d9ecae93ad1ebce282aeb4d84" . + "d2aa57a4976a0dbce50f5d90f83c66c9f8a92321ad3eb3f6a0718c959630005b" . + "d856d1e08902a3f1b5413ea43f231d30b0aec7a24b600a16a7e8402878c27ef8" . + "03aecb61f269cd0e12fd452106280b2b0a7dd19edda3ce6a91b110d8391f5498" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "f9ac7385683b4f21dc21de6fb61504221c87ec6078f71179833c4fd4e2e9773d" . + "1f4729a57d79d2f250281d70dff83087efc56eb785195dcfd3651e42fd5e72de" . + "fde3e35e7e5a4c11fe03b40708634205fa64e1d8d2ab197be86c1008c92a2722" . + "90f195407df67511e6752629529aae62559965059e972cc8dc5f26a260dd1369" . + "0c227ba5e5ca4d328935010dcae924aba32648a03508268b1f25cb5a4f7a4f2b" . + "cac7d14c417364a6004fadb2ec30e1cdfbeb052f18712830fe2048b754208060" . + "32151b449ec60c1e909d093893f7d2fd6402e33158b3cd562d78581ad9373e0c" . + "fac0e361aeb6231cf59f3d9a967c7ee26b5ea4f5dab80a0513050a706c977638" . + "d1894f6a602793e9284bb572354567f4c247ec3f74e34b1603b9df84ed4fd9c7" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "b2239313bb253234ee0444bb6f1f7599fe4259f6e1eb6383cc50b1312e6e2963" . + "6b1c50425badb446e6305d1effb3166ac84e9055175fcc13813a3bdc6004a6f6" . + "425166ad64ebf10ae291ade77c9cd9f7e8d1f084f6fe42e5d0d9ef6697620d7d" . + "77c6985d4b46ff3cc7bd6e888aabfb387bbf741047089a00e1a22973f3ab2af5" . + . + "d747a876d1fa0756327708b8859b76b0c889f6898f319dcb27bd473ca2ec482c" . + "85ee43cc2cad8ad638b44ca6e764dfbd008f8c0857a7545b6c98033a641dea4c" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "11f729b4148ba35d61250d2bfdd6e2f46971716eccdc2b47a8693f1d4c25ef37" . + "f58dbcdf8cdc09565b9ae861282518032948cb8b640cabafd80e9ce93ba0afad" . + "7790185e997f18d85175c75b0852b10557d5a60a6d15335691ee244298cc2a52" . + "dc6ac7f7a7325d480157436c16a1ec83fe8eaad77606f46bc63f1cb6233d21bc" . + "77e381627d687af14a5bc85219719cdfd3d0d50995fd98d588329040f4282bbe" . + "d44bfe7b71ed91b46afd65bc8c1cca44614f6ab5c0c4d727d1e8161f676dba3f" . + "4fe3c20792a940f310b6c240ce26686ed6e681e6d9bb4ee35778e8376b6eba84" . + "bb12c9344c87f64a2f3001d0507a54cfb2a229c2af661a458120a916e0ea8409" . + "469d4685069db7e1d83bb336ecdab2ecce9804abe74b392e0638b0e3a587cece" . + "1c83c76ec0da27ceddf8ad74a664cc120b28382e5f0c17dffc4335fab46658d3" . + "6103e90791283b28a8a52ba45b1b838cae87528ba5f0ce0d350311f5477e6d57" . + "d2811891834f08021ce0a29d7687b5939ef5c29daa69774ed592b431fdac2c56" . + "0cbdb89cffbece29b72d203e8f7c200711d73f062fbeafd0546833c521ec968b" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "0a9fcfdb49b0e2916f62713f692082d0ced2098405c35acc2f25239706d67ddc" . + "2b674837f4a1d4fae442fc7f43d93b3af3edab7ab065456f0a56c6b8a2c762a4" . + "ce50f73a980a3c3dceb0fee68bf5fca211dd61f4dd5856ab8177dc34337df81e" . + "cd25321611ca4ef465a5f03332c84d45cf334df8bda3583aa93c6058ed8d69fc" . + "4931a6887e34d08460b1595409635ab2ad40ee211bab9676f80087dc31eac93f" . + "4eb3cfe0a032f0dfa40b80a61d82ceec7b3a9bf8bfec6d74a2b31137ef658b8a" . + "d208c0b7fe907fc5e09b39dba516b3dd2871e5fe5c1e9827b7a6eae48ed4dc1f" . + "4d70f2be40f245e1d834c8feb7fbc22f27415cb987b69b3d6128fe9a0c40520b" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "d841593ec083775935085cca89f7d2ae994d92835b60b255f21ed79d76d9dcb8" . + "3714c028438ba3755baaf37c544d35f935dec060dc9c7d41564c57accffbea42" . + "b781b62f5b1f1967226e72cea5da7bebf41f90c9e9f2f87bdc3107dd966e47aa" . + "90a7c4202c3a25eda3f1e6f746fe7368496b302a6a389be86894e4d4f29970ee" . + "82d580b861ae32a0d804f419f5dc17caddae87d7d896e8b25ad0f6ecf81522be" . + "be70a5d9491936f916373c990b0fa4a79554568bd555388817428951354240f7" . + "6ae5c137c2b50ee272395631700c2c0f6233ef29cbc7b34659a3c50928748fa2" . + "51648db51d77b8c0c379b77dee2d7108da4baadf89ae31f2bd158e4f4ba99658" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be40e2b5bd34fb07af7b3b26b03d00e06fc99ffe8729fca13e0aaf58172c60db" . + "999f4809729c5b9446b6df861a071d7bef40dcf0c3a35c854ad11b21dff9354d" . + "026ef8ce86ba8711aacc738b7cea9f5bbc1ddf5320d59f3d68888ec24106c399" . + "0c0e02ac9fca386d1e66af3df6c91c57227b7f1caf0fae94652a552b022de0ae" . + "326ab7bfcbedfa2badc5f15a9f6ff4b93dbae27e5c042dca27a6919c46e06b07" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "5eebf71dcacae81c70318f6224fa28ad4398b9a801af17a67a44583d2f90f91c" . + "23de5a0a248402f8e5cce6b21162d84b40ee898393eae22b4025b55bc1dfaf46" . + "c318bff139dd9f9f3197c80443c4bfdc183abc852ce27af0c239d31e9a1fe37a" . + "d4fdd32c1716c88b5908081545b95f0beeb360bc811397293b7bb06b3630182d" . + "32e74f35d26573ee4ccc7dda571a25cdc1f8f95e15933209c6f4fcd79a236c82" . + "5c39abe75294a6de3c76c9cd1a4553d007c03130582a017a142ece77356b147f" . + "3686337cb449ace3a19ab3500b01b5ff29f08ca19f2dc093acccc8b00bccefd2" . + "6526f6f8c022357f61d39911a39e20b83900a7146b40ba5b40bff2ff761798a0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "31132b93853c5ee27ae123de3c2e4b115b08131fa29ff00634e020e0aabe579b" . + "d0e5c028809ebd396b77ec9a8ebb57bef3b2daccd71253be1ff456b9eb3f97a9" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "9b13cea52c3e40398aa62b3b9b73ad8a331dfac25521b99cb0e2edb07d1c58b4" . + "20797cb664fa9dbc4f97eef73832f8ff07d46b3c4f95ecad94e08f13107ac9cb" . + "d6d8a95f5815798a02d1c1673542647c1064f43eb35645a5232e9fcb0ba4991c" . + "57f3e56270b366d7c062ef45a8e4d93134a6b974db689ceb841c2de39435beaf" . + "78322070e48e9e1c50ae918cb3ae1456d37f8ad49534d6e7813c1c2d91bcb379" . + "12dc24b81363895bb6988605e89d16c0b88a422fca46610bf6947cdab6fbed43" . + "0b2b835b2a384737263c5de422d337cf70f0346f58d2bbe3e38366217bf28612" . + "0c036324e0fa7308ebc5ef27b31b223448ee1c7e7c56c3d5642a491f0999522e" . + "5bb5020aafd64a18dc8d0134daa71f4b0dca70ea45b7dd524d9becad777ce52b" . + "d92eacb420e395d7d577f75e06ea04bd2ce327d13906d3e25e61d11939e0d327" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "f41cf583708144abba6aeb881f45dcb787602623f41dfb13502ad3d7ac20cba2" . + "01d43040cf231b6076722652c24945ce3a70c00da8a265f3989ba2956657f149" . + "c23c830cd2b423c42ca56b32d590e2e44d30413981b81fa38b0a04ece40e8c58" . + "750e866abb9ec0abfe41e157c6b4a69d3f9fd07181d480b75bb6a05f38c20968" . + . + . + "fe8a6ab94f1c37ae8eeb2eea8d45027f796361c6eadd8fb718b872842bae6741" . + "f3e945f6e831e459d5027f0ef5ff35238ca632eb38efcb250df295d5ae7eddca" . + "c011896e250368bac8101a7ee4ba767725e46c40b64df22007c358498c9fe587" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9355b07acec1b27b84cacd887dc15cb4d8ffc6f7a53679bd01df26d5943e7649" . + "9355b07acec1b27b84cacd887dc15cb4d8ffc6f7a53679bd01df26d5943e7649" . + "5b9fdb530f286b1bc089aaf2b16cbbdab6c6636120197f5e63233f4989fa2d5f" . + "73db35122dd8bb7e41a07a5afcc25ea66b71df0dd6b6eb7925c078311627fa61" . + "a3e91ff97bcd2a7353be5558aec1667319e9146fb21971ea6792e9e175511099" . + "f8c12b914548ea9248c157fe2c228c81870f22f90d852f06864e7c7a3691a9ee" . + "144989cb434ada5acc5ed6107c7b3b3253c6e5294a26140cceaa5fc07b5fdd1f" . + "4c14fe8cd79ec859f736b2e1a872baa9465283c42f09eba1a056c46aa84b0054" . + "4ba53b441711d2e13173de51f6f5c4e947e445fe072870d8f8ee4058b8a4cce2" . + "524e7266412bfe36841731b75fbf2e015c16a1e8cd6d36c7ea7220adc63095b3" . + "8ddb01d85bb9af564216e9023999885d7d8dabc93cc01c1af6615e48e49bd3d1" . + "8eddb61083acb36e3c86e200f390ce8d098fe0ca8574b5f1a3f9192be16e3e00" . + "45f8bf30aa567190ddc737db15f63c52ccbb61cc26d7705bb051b7b2ee404261" . + "4e181b3e060a895ab6761bb09c7b56d855e4bfd15103a604fad56eadb44b23b4" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "d43534b43ce8a5f56490f27ce21a98188503183104360c0335a4e0eaa91ed93b" . + "449d40f862ea7ddfab29660df83e12ed70bc0eada872bcaa95466ad31af8ec7f" . + "f4109492d8c0827a0c48ca1d2ff6d3c5bf89b7afc07484cf4aab28a46195eb0e" . + "2e57f292d9f53b4cd7929f4164ff3b7fe3e2ebbe74dc03774b98217154110a38" . + "911aedb121b76dd9b8c1a32c2bd8a6c894703678be6040be7ce3970e4b80649e" . + "d9bc4ad7cbcfd0c5d94f77627aa692fc18a34026ba6becccf5f8395a0fa925b7" . + "19cf97dde6aa395a6c0a828fad9ea061d1272bec3c46b8f5af33e270f6a9d3c0" . + "bc26a38cd4da2f82da1026f13587d07ea6dbb524540064bf36f869318ace8f01" . + "ddf08399bc178f19002360fc13f35c66457f468b9b9b84e9482ec369bc9b2244" . + "4e20e33c6149fc7266b4151a8c3bfa9c0ff8bbd86e48c56908fa1a381564b85a" . + "d71f4f555d5c7dd17ecf4e50c8c4dedd664c2de5cdbf1d1b8092846ef998f147" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "fb0a880e18002959d5524206911b4abb552474efd1c271f828371f1f846042ad" . + "e1361270a0cb30028f3d9fb78786685ea3a1f02086afcd91c989d7c882e59cda" . + "88377c866dd212ff45e3eaba57643b2c4e77faf990e33778920522d494048c84" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "9fa2690ea6146831f9738947577d5d876a3cd735ffdf6d06620c6807274ab3d4" . + "a2156570f9ea5ca1304e33c9c0183b144f8a268763f31af7954ea11ba1609554" . + "27d7c61819002d137fffe479a8a42a5782d535b9b3e609f44e613fdf67fe6ef8" . + "f41d90f58bcd124d114ff5308a3dcef36df803444ce434545b38a3e51cb259ac" . + "9fa2690ea6146831f9738947577d5d876a3cd735ffdf6d06620c6807274ab3d4" . + "b5c4ba218624abe89d9d2ec1ad6436763bf7ba43eb584852957899cf8c02e67a" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a0ee33df4bdf6583b3cdb870caefaa143401253294b98887c3dfe0bb2cb749a4" . + "72f82376c643f50a2d83000d3ab0072f739b1d9eb9efc6c3b2ce8717f85eb72b" . + "b80fee7903e74068970d0e954ae7e0d282fd2758864fbe47fc34c5ced1092ee0" . + "6d0c291649fcf48d6b4a50dfb0d7f6f496bd453cd84eebb1a75f26b8102d9d96" . + "d75c876d39e0076ef3d633248cf7aaf65a734489e13f3384d72c7b8b5381696d" . + "11fad8171dded1fa383776fb0038a184e3e5ff53126c0f5037070113e20025cd" . + "7b1ee67a5d1c65637665416a340f8fa8c9846b620d732f7b7f624b4c040ee7b8" . + "a348ae1431130d4d8734d7565582b2218261782e7e2389f8716dc81f09b18571" . + "9da30fb15f44caaea300f4ae584bd70f789f16056ad70bd14765f2048b934521" . + "a2f07dae390ef7f3e8a66c4fe279fc7eb8e91f6abc149d1f4d24aafe4bf64711" . + "acde324d69151498142edd800c04dc26a331c43969dbc9fa4f4a5a3c125bcd40" . + "f21a49f6cf566d5c5117fe1caf2d7d079d2e0c9067e3154d2fd8d062632606d2" . + "709468a56e55d5ffc190eba02dce1a1723d42ab79609f49264142ea6200ccd57" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d6331fc1a7184ff719dfd08b3a4bcfcaa6a1a4aeeff43c32e143f21acadfad8f" . + "81dfd5c8dc88dcaa3060c018e787a56cdf773b9932d3bf9d1a496c3f8fcbe380" . + "968f356b8b2c69d6f2ec6a718f653c1493e9f61f7ad32c46cbfb86d66e8659a2" . + "94518bd43de2cea4cbb9f89fb490d1e7b39a7820d7aa68a3094c15618eccd8bd" . + "b54922544d5c69ac6986dba8e709632fe2d8aa7ecdaf04d8e55105c831bab2d7" . + "54b4f057543bc44c0ee81b143005d4af077f11ce8bd6be628a7d4f0a5666ff82" . + "a395d0ef26a2049ccaa87fbf26044e2327e27868dd1f4108468ab000610b9086" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "1c5e79ada0a7490c465dd7d4a953b4c8fccfe2d38c42cb7b29712ae992bff342" . + "21cb26b7f0dd851ab9758f8683d625116710a0989b01f204867082e8b06b80d1" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "78c7f1c12db904ad372996b1357df7ccd137e82ccfd00a6288da16c1a9f12b70" . + "73b6c8a17942448a9c50c3a5bafcafcd119de91d4bb1ce24787e9f352f37da0a" . + "44236bfd4b70efd3c7981f9816c9aba6079e51ddf655f7d8b713526e8931795d" . + "5bec8ed2b536bc1a55dbb229ac8f5cea91222af8a929e08687de26daec838f85" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dd34e83633af5376472d69592cf72a0b03e9b8c1bf0b31a2986790ee8f9988a2" . + "dd34e83633af5376472d69592cf72a0b03e9b8c1bf0b31a2986790ee8f9988a2" . + "20b9be7807fe9750a6e36951f2dc43eb16dc1613cfced3e62ea0b0a17c791619" . + "6f26441b68ff38b2a950fa3014dedb4f0f89a684e751e869adbf7dbae827e365" . + "93fa8b959ae6bc9cef2d3871afec6c77af1930d8b53ab4e9664da69e8d09d450" . + "fcce2de1aa960865e8dc0e48c712b9c1fc9e3a394f1b7be9667f7a182e4dc73b" . + "29a1b4e7da6aa4fc7d3bc60924f606b15d09ddde5fa848cd8cfd16bd57aead94" . + "63772c198771d7f46755e7f5e2bbd4b3cacdba1754a86aaa40e12b22f38a1470" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "6cdfe21607d155110a80ab2575ee517e75f931ed6542915e079123f9a4556f18" . + "d11a259dd71b3c91b9e3fe3a35873f8bf72ed9795d2cdac6c2baa750a6f8c500" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "324e3c8e570c49549af1de2ee9cbed3c53bf583986ce520c5cae42b942104d92" . + "73d066b5b7193405a5406580f96c3652dbf62bda43d79afdd81954638dc7b0b9" . + "7d090b1d7ca951538dcbe500404e1ea9f0acd11475cf709f85198aed1169d39d" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + . + "a205cfdf8548a076e9ef5ed686d179aaabc61f85b198bcd576775250fbcab0c4" . + "ce53497543f777349dd1cc4b5491459c5b168cfc66c4e9b0fcc4bdb76b73ca68" . + "41103506cb87090f403ed8efe0129d247138ee24eb7f0aef740bc2fc16096b8c" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da06a3a7ba545a125c91959490a7f6784c0f074dab3d388d586125f1187e7c99" . + "f6553e692860a09a20144b20ca5b8cffa25dceb6cf05d66afb9fdd120b61cd77" . + "fa8b63fa2406a82f316d4d60f79f8291ae78c83a4a4997fa4bfd82aeb92f7b52" . + "542685708f3f3dd0fe731b69602408a51497bbb9597d216c3a30cc874019aaba" . + "5ab485d1e01e2834f7bb52c2baa7ac877a137ef0fc677464000c356d59782cb1" . + "21dbbf4eec020dd49b1f3cc66060a9f134c3c36664c16c8c756a71e6554112c3" . + "dad5620ea34745aa44a75f3864ee12b8657ba7ceb771019053a6659206369d24" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aba10709d4fab2fe074ddee0a8ad9a62b92e96485b9ce1b5edd5e2b71d2518db" . + "d73046062d383ddeddbeac1f5b64966a7b67d9c221654c9c6cbff5e73ccbbe18" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "826dfc21122364fd8d0c0259a1d3ef6f0f84fe800eebded40935855c2893c7ee" . + "258280ed7ae4823d4b940f43acb14c30c726ac669080fc7d26b9a6b3ee2c6448" . + "871043f36c9e4c425db28509d8ddcf051260e69fa1638476843d0efa554c0fbd" . + "135f7f483822d0a8c6b2c8bade5e02d870ad4a0a9337cbce897797d43ca8abde" . + . + "a8ad52026ac2a897667675cb28b83a51f4dc73cde6139bacd853e9cdf2d32927" . + "aedf26e737801685c9eed31c14e5321b4e03cfe233d079b6d79e960eba8349c1" . + "e899f29364461dd9db1cbaa0756954f48406ae8f04ad4633c26e96120e5a74f8" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6c740e2ea406dac566b443fe0646e5faa68127c8a3cd5b1be1437518727bdadf" . + "39667e09acd41f8070e012ae4530db31704daa5dd495e830767f9e05009c3840" . + "477804b8c631a79663d643dd29be09bfd0b574a292fa461aa2908fe3cd40538c" . + "4bf311259fcdd6e8d2caf7c84c94c475f4e668c15afdcf1c4b8e065c15a06a82" . + "66344bcbc52e737da1aa5d3f9778fac8d305535f0c3489cd6513851700acfb32" . + "954ebb0f343a7ce469a8ec2f969ec2c6488589c88a7999fc6f61ddf03cd4e3fd" . + "299cc5f0ba81cdb973208c8ee3d6015d18ebc28f4000915995303305243819b0" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "e2ce85b65f39beff1097931600f6b470913505f9cbecda3e9da61738d37d4198" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "309294216a4fcfff7f2e4a5bc15dba6cdf697c496e16ec8ff417e6d1adf2875f" . + "212a378a27c05b4befdd2199765a8dcc44af70bc3c620d484d120771817cccc4" . + "89cfcde24f7bf11b37070a03edd8a4b79282ee645551f6c2767bfd342f9bc37f" . + "e7462eb051fd7badcea625894913679ddfa66071a4b1a669f07a0fff4aa10ea8" . + "309294216a4fcfff7f2e4a5bc15dba6cdf697c496e16ec8ff417e6d1adf2875f" . + "ef544d48a02d88506a9711e87ae6f30712c47adccb461ed86d0aa214fdb9427a" . + "b8c4da464ed2b944d42171c5fb9c51d0ac24a307375c983aea5c6e0ec7d9d9f3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "af940ae061fe5beceba8fbea6f95265b4e3460ca65afea1c5e455e0c3a2a712e" . + "032e18ff73023a4158f3a2e407696b0f98ff207b5c51876d680d6aa09b1d56d7" . + "b45eb4a3b9f0b58cf4fc4dab558798ff0623ff04a605004c422bf53a88659f47" . + "5fff3524971d8e4a310f7efa3820f00ce84c437197a6645928bbde5031abb996" . + "95c75b27d24cd38e08d2643736833324300966c6e963e5479d80b52a62366d18" . + "539100c4b35884f67ad171e5c6d70fbafe99370299f056b2f80afa92755565be" . + "cd5059f888954972ba9b635f848c45742b5006dc074c9e72e72c618571b60082" . + "92c6ceff791058fa7b5b3a533b350269e7f98d9f61d2aa767bde14792b493b65" . + "d558b72f6c732a9ad20ad57d553ffaf4517b2caf631c74abc66f2958f205a998" . + "434ed46861ce35509e338c14670c58341f24e35ac209c2c6a8d56c00d55f45ce" . + "e4e1adb29f8c2f972577e04e8495ffaee45b68727ce28a9a519848164f892b49" . + "9fe3ba10c3c3f1c4066427e52b9001d95bcce3b25023d8b720a84eddb193cd1a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "d01e02df63c154e7ce71bc3f3a54a11a76cc3ba205e92e7306426ef7cac0df87" . + "cd6b385bdc0a4cee3ab0cd1e2aa129c1ba4e7422c0f7da447e1c34e65f103e98" . + "6ff55e5c3efec242dd3acd61e806320ab609526d878cfdc2b783ff2e8d5a47d1" . + "e59b4296607711156789f0b06781dd140c1070c7cc0e63cfd20a5528cb727c0e" . + "b2bf0f75d299869fa7e2f4ca7cd05770b24e4d55b206625fdf69cb4ad42e3db5" . + "39d558e92f49bebf36f7d10f23140401f3d9d9f73c4869c92493ad5e6a69c199" . + "929503d3e2bcf9bae9f6ac5a62920332568b89994103be8dea651f35a9675378" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "b176b00132da3bea2885da1c1b83e4bceca5c9dd117d3b547c2cab7dc2d9f4d4" . + "68fff71a50ddace04b8893cc927c9b677ecfaa0bf5deb31fed417c90192e890b" . + "571fef046b5221c66852243f622178305996c1d6469550997cd5ccc97047a389" . + "31026d686221cb775654c86ecdf77c0b43c262069581182e67e10bf42aedf3fc" . + "ad32a91825e9670a524369779667b86a4ad114daf51bacc141afc96aba3bbbed" . + "7beedbb34325e0e5f41f616292349747c018711757f90bfe477200c70333bda6" . + "47ca7dd8e4cd2703295af98818b48e9384e076673ed89040bdd420acf0e95fc1" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0b8b99fa490cfb25edc3d60b4645acb796f4277dce2ff1cfc2620840e0ce73b2" . + "da54d2b128de5343d7b98d2bcd012a872d57ea5cd3607269386fcbc0149789a0" . + "653d4b688ef06e71ae56a1bbe1e091eddb1ece285a84e712d3b865a10cee5035" . + "8db1be53e2f6c471d22eddef8e770f58c58d940e5777a270ec4bbf1fc68ecc01" . + "df5242a6fa59ff8a61a3f94e8ac72252ececa41083570b824720d021ece3730a" . + . + "a1169b6028c34e8c41fdea09f0e579da33939d8d9647138cd4b1ff6a3e26392d" . + "7c78641bc66d2c19245b69b113f9a5ca35b05c1ecd7468f172214fffacfeea11" . + "fdf2a7ba84030f74258631dccc859548af074636b8fccd0159b6e3d37e8f6cb6" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + . + . + . + . + . + . + . + . + "1cc83ebdfb72257d401c6cfe1517b1662dbafca9e19defcef45e0f3f5cd6e32e" . + "d418531896cbf86e4826707eba120eedcf13edd0de1ada00312bf0e7cd080015" . + "77daa11419a7c5dbc496d33cc65bf23b25abba7481b4bf56589fe438444e0bef" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a49baea8a924ec33f3f16d7192a541fe884a81d836bf1647f11c620bfb20277" . + "44d522e00d361adcf07c31972426edb33345a1144b02c9575611a9c2c3f55f24" . + "f66f9aeb7e2fb1165aab92f1fc5b6a311b7f345803b38d64d6f5d395ed082dcb" . + "949ae97db49b24083b67a3ff3e4bd079917fc54768b7bc89ca9d6b1c1cdc6ae9" . + "2306cb39650bac1926eb2e95147400788a2945d328db52d7abe2c73306798fae" . + "5cbf8921a13d8481af638cbe5ac84f049fffe23dafb3fab7327513a732b879fc" . + "e2bf5ea74ad0aaacd2929b468f69366ab955ee397a254e7b9780e227320eb102" . + "4f54e10bdda5c31f9477850db4307b9b1e7a6f3b6faeada5acced56592fb20b8" . + "312fe89abe66b4a15dafd4b70eec0878d90ab344925095cd3c283f8358d9c4ca" . + "b2bc29800fd6aee4f84545a5ded09cd1b5cea080b5b646c850d86a0a4107fcfb" . + "2169fe8ccd74ee0c1782d37fc782ed2c186c83449f919c7034261a6534d93cd3" . + "f5903f1213c5069981949946d4ee92a86d5fa84d007a1035d89933165041aed0" . + "618f872ec248ab519cea24ae42a5475898d5de189861169862a47aa3b1d3eb5e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "e7584f0e48666437e24902042d1b69759f0511ad9fcd323116519453928734b9" . + "f68c0b1f09ab82069acfd7eee3389553cef25248a12c153310d41c345c4bf3d6" . + "5a3817f314e3f3495df5ef0f14d4db7a7d0e10a2c3c16b80d69be410d7f116d0" . + "b0d4d0270a778c4038edd42c2f518ae6924181ae18a580f0c4d76561df5fe303" . + "7255b30264da152c810a8c522cfcde0e4cf9cf77ea7168df00d4e4465d4ddfac" . + "2c58b87e47448da6994accbaead1aedbb94f166526df32016b4d8e63b8d943dd" . + "1833b18c322eabf1e4331ff42f000c473f1f3f73b8c66d823c65b0d4f64aefe5" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "1ca53ce8cb51d61d33deb65627a6a53e31acae1331bd5abf14f3eed7c7a21819" . + "f5baca1108c8f327805676b7af77da9f5c015aefbfb764436d2ace8e4eaec145" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + "cf671f94334faa1550bee3acde146efd0801878ee315e55d9709ffbe16422e71" . + "239bf635e78ca226f20624422189dff836e53bf1384fd57665aa221faf0671bd" . + "6cef1257190052c43ba9aa0899ef7355e18b2bc4e3632657934d7cd243bfcfdb" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5b22fcc119b98db291f87f41c3d89e15dbab82f97dd32a32fc792a47a0808fe8" . + "6ebb3a8e4454395427316e1279075aceedd4aae57364e0cf56ab162eeff68ebf" . + "ac5577d14e5669931d53a38e72a738102ff31b0940e0d1496829da6bf384fb73" . + "28bd8de6589d4a60558abbc63e7cf5df48c7ae8fe5de72f41dfcf3257cdfe723" . + "38cd87fb2949b706a83fa6686f3a0d6011b3e70347614d628a97f637fe39568a" . + "e2c9fb6bd777c8f4ee9765fd31885bf8bc32819da19ebf765f798ac618ebc069" . + "ca47049884fcb5f3258a3736d5d5dfa966e37eb9b978ff3ace512e368059ae48" . + "ae59a757c2375c8db12ce2b1a6c6ddf4337972fa6fed5935e73731143066b7ab" . + "f1511442e1c083c4df6a357e26e2c4ae25993574dc4ae6de5125a9fe0b11ce71" . + "8d8772dd01f75133cd8fc1a1a4dd6700f54f5e8c44dead80b3f79f43aede93dc" . + "41f6054280579a0b73e46646e4ac902c382e8cc2a9a6e5d163a78b39154079a5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "ccf9dfa4f2812708034b9a00d6428f3e9255930543ccd3852f6bb7545283debd" . + "100aa01f39aaddd94e75dee658c41d5bda3787f043b7fe624425a6e51b1e8789" . + "2c41947f7eaaefa88c17b8fc15184ae96e5bcabc7e28125c940a6c7ee11eefc0" . + "99e62eef60cf62572cb1385b92511e14c8452af2b54196ee15397b20a5ee9fe1" . + "b26b8ebf3d366532bcfbc36391e6397bf3ebf45dec257ffc72418eed13a2c77a" . + "086b9713b225302c8101a843158f9404a332ef9140bd674fa6b3a3946e5e5547" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "7b9a7c35b4baf0a3fb955c20a15754e40ab1e15c62d38bbd345dc225697a0c52" . + "b2c9c4e51a429bf36ff9b7b4dc92549626b5cd1fbe9ef07ffa1f7c5740072720" . + "821ba5a1e698ddf5c09ab58c145b6bd454d7b335f797a5c88ce8d829b89e37bb" . + "f3ed393b90957f3a99a5adad03e83acfe9d5488fe046c3797517de46c53f3506" . + "f9d3c24e3ad8c11546bcf1209c2188aebe6d0d6e02214626eaea5d8325e0769a" . + "03cc02d8fbac98e6db527cb82bb360dae58a1f5c63efaaca854366f1082ac7ad" . + "9d92e39f495017efc46693c68ea487b612f7d138bb30dc0b262bf0d941255519" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "de5f426ff2ff8cb3b93b2032ecd94d40d4f0c6807cd325e1089c8587677f44aa" . + "d79fdd689e982bb33c90914964475440adebee9621660fdc286c06eb278fccef" . + "fd059280689e02e9008ac88a76805177100b9d0161f2a4163e9431c2632c3be2" . + "3f78ec41ec77b7767da11c2b192ced510d9d2e67cf9981b42483d0d27cce21a3" . + "dee967e45c20d20f703452f51b0929b72a1a12dc61a5c7aadf9f52cafd48aea8" . + . + "a62f95450e7089f87737509130bfe63a710c988ef526e0312fc62051592e9b36" . + "c58d1f496fcfed146c6bff2bf9a479973b61b6385d5c3d3bbfe42dad8b6cd5ef" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "8922f270f71a0468c02e9b498430e50f1a2b2eb16d875ba9bb4683153000e28d" . + "fa7190c15eae6bf451be2c6155fec3ad0683d1b07ddcb76fd009ff80d0074030" . + "52835f314218a63df783110e81c455145faeb99a407bc1ace5ea5fe400476c05" . + "a600896d3296f7674e570a19065762d9052ef860e8eac5137bcb859408c349f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3695192306507885e121e87c4f78af1061a3969b70dbbec9e61c3fde10f825cb" . + "3695192306507885e121e87c4f78af1061a3969b70dbbec9e61c3fde10f825cb" . + "fcad24214a9a20dd18429d14a82b53a487372886355828be3e3f372f16c5fc84" . + "e6528af805d2ee7934fc1c9181e355e9a93289d573c6b4f64ae86e3c56a53ffb" . + "da6733de0e33b2ff04b2a85b312836c7b9dee1a60053aff9ea12ea83d3a6b4c2" . + . + "37d46c5213a1a195d99751cc7629702ba5015b2d56c6210db098cd0444131048" . + "a6629cc2739f3cc8bca937a688fce90d55806b20e581dea1220d285ad3e1266b" . + "7b06acb4e96263bf4e0a1b21846da069e6ca9db827a83e24969be831be422e56" . + "2fa62db37491d7228cab8ab7b5ff0d1d163b7115b8c46384d0f1d93460c1a390" . + . + . + . + . + . + . + . + . + . + . + "03b8e48f8ac9115baed4b3155665dd350dc54cc9848cf3c513e7dbd6b0e85244" . + "afaf58b00430e7b2f866ac18c2ef07d21d9c7e87bb13db74736d1600942d4174" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fa799b0ce4b9ad9d34e7961348a0abaaf7903fb5c57044cbb25a375540c1faed" . + "35ee3e2fdc7bc4021812892cb582d65e787f9a4a4012733953ea7f9bd0a0943c" . + "6271e3e33ea2b759f0218b5f23627358d8c5a81c034badd85b1224d9d5997235" . + "732b9e0ac9e1088883b3c917081c961f09050a7b4dcb419d6c24aed820f836c5" . + "76ee82fb105d19bcb2fa0cfec87ea234d3b5848ed6b4b8adb02ef7c8d0af5c1a" . + "2d4f5711c09891ab28cbb0bed75d3909f656eb6f0056ffbccd403433af68734e" . + "ddf08399bc178f19002360fc13f35c66457f468b9b9b84e9482ec369bc9b2244" . + "c3a21d059b871519528409cb4a3e19ad2753378cc8619f9560d1e2c46ef3ce71" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "eec54c306712a430ab8a9b06fa2a4c7211b5e162f8f81997d2baeb41bde963f0" . + "22f538864e07117fa52d7547f367d61bc92925ea90a0d3618dce30d367eb4c22" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "95d8f84aa718e542127bab1f7367b46286955d5d8fbc88ae1c5402ec3bbc0d2c" . + "63238c470a068370378f998ec1aaa16548d18d77f7ba6d5975ddd37300ba3078" . + "7274d95c7a559991c2d894da47944dae404797644c01769e6c75cef0977e98a2" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "2a25cb2f0f636d3e76b3518ef6a99f3ad9c212e16f0a73b29ff8bb1945a1ee3b" . + "31d90be74b05526c7ef14df063632b2e3b634f3cfd3418f8734073ee345cc0f5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f34f66df4ae3121639084e3815069fb581748bf16a769afbdaf12365996c37f7" . + "f34f66df4ae3121639084e3815069fb581748bf16a769afbdaf12365996c37f7" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "672dbcbaffaf85774d5a0161732743df9276bee0b50d5c0d0fb0aa7d625422a3" . + "fe721f167288499d7eb3332c525b6c7eb0d7956510c4fd50864fbb28f97d16b7" . + "3951e89bc7f836e51ee52f53b0c7cf9e217218ceba61b55be3964c3595fa8612" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c8d80ab87a513b051e5002de68dfa7ad43af110da8b011de540c8c4e284f970a" . + "e0470436c3ebc2ff0a370a7372f3994a177f5630fb9b2c3621a1fa466c2f7e02" . + "6c8a3e9cb5dd62b780312f28b9bab298e953281eb72952879327957f9666461d" . + "d7bc7203123b56bbeb1c0b082e7ba0941d9ef46adec4163416e52b27f9c83672" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "956878a581107310d995556839331f04d21014958ed9b05269094d14430c1eb5" . + "fe482109c9f5d93336dfd1f5206bd2e85b3a40ac350e6395cacf44b06486f687" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "10641d64ad0262417b8956b07ae2d03cbc734d9a97acc4f1590e9c5247cc09e2" . + "10641d64ad0262417b8956b07ae2d03cbc734d9a97acc4f1590e9c5247cc09e2" . + "360922447e0d02cae72a2a9add6d0f93f402b72a3b317dc7755ff79df5710833" . + "4dbb1ad90f6c4ae4a8181334dd0abe798112a622a1afe4999dadb3571dddb7dd" . + "37289e3f6aa459b1b5109ba8ffae27b6db5adbf9189efcebdce16f2dc59f1baf" . + "4b74d712c6257f5f8ebf7b32ec15040ef9294bf8ff43014c0081af410e435551" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "7929a999692f6317be01302ea8737bae0f5ccf6e3e05b4890f415b382942706e" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "51ed1a734ea2fcc6f3afcd953fe3c320189524002dc406208b19c2d6ea217750" . + "45a15dc5a9d8e0179e99bcac115f9ce2db164f58d837e060a6b0f92262643efe" . + "e68990e1068c144bd1157e5f2d52a791349dc7c8c810a1de80afea522bf613a6" . + "138173d8289e855bff066829ea9862c3f5f28d45dbed0b4f2b0cae6c1c8494cd" . + "17eda503e49d59284bdcccee294561cfd081d1e507cb7269cae984051f3784bd" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "45a15dc5a9d8e0179e99bcac115f9ce2db164f58d837e060a6b0f92262643efe" . + "764cc31c297eb39732afe9557f72d0214f2ef3a0e1f8e66b1ff1cedb8a1059f2" . + "fa834533fed5d1689bc97caf01f77c930f7bc8a4531890f490ba746f1006a171" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "def3b99306faea9ed192586db1dc7d28dc49b75faa030b2811c5969872d5b4c1" . + "def3b99306faea9ed192586db1dc7d28dc49b75faa030b2811c5969872d5b4c1" . + "4631b01a0fa80d0a825bca4ac4928f646618363068e62786bf211008179a5837" . + "116ac7ff4b3f03c99290168eed44748931ba48799706a79216c978f247002d60" . + "0c0bebe846249901637c2c9afbd0abf023a9da0f6454bcf31b378ff90f942a40" . + . + "2f302d740b7a2d97deae67d9c65f065ae3f074d176f489339483f20f07b185ca" . + "7ced64d16ed0adfa34d4d78caf72322ce71fe6f8d319427508dcde09d21ed69c" . + "5a914724fe755ad113b5436d825797b0ce18a25f3d97944af7463243dffdcf06" . + "0d956e3d91047b07dc1c132ce35a2fdd881180878f80a60620f8a24b5fbfc771" . + "2b40486bfbadccdd6ea3448bfbd37d77dbf66dfbe6cbbcb452e26b267d6c9cb6" . + "54b53861f270ca9b13c096a867a715fd5e7abdf048d4a8fd91bdf4b980073b41" . + "365844ed5fe357bb340c0404c23140b98859a941cc66878ffb9fb905e04729d5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a767bb7677dfe1798124d94b7f40235d82d44eb0706fcb0f303dc92bd57390c1" . + "55395fa5000fab1f54ea38ce4c8a9790a60ab6d6b93e4d84861c3c61e332f3b9" . + "fa61ace0859362eaed3999d10999ed45bda97040f113c65552a3de68f9ed30dd" . + "7ec68c3f39db2ac2abf8d56c52f5a1c64b9f08587eb284f8e93e2896a4ef1d92" . + "3885a88900d341ea192eb73272647b57fdb501717cc7fac8048196061b7fdcec" . + "2c97f7e0fbffe79490573ed672433071c8b0ab90fb9fe97b9aa4ab2876bf91c3" . + "47b66d2b22e04f3c6239509447fcdecfc3f62c5f42e44d31caf9c4ecfc666266" . + "16f8dca4e0824886e1539615cc9b10544c9f62a5292e3be724e5a2c7f4d4984c" . + "0f3377dd643a087654a280d284139f661a4abfa8b3e1243b012b5851f26db240" . + "2b0a69cf3ad8d6de6d1923a48b9ec149d84aff0db12517915e14fcc60d87b781" . + "c971c75f78373a29bb00964016d0d5671c859455040d946dd50775b48edd958d" . + "683025019f4541dba76ccea9ad15cd5b95b5a84b7ea11d31468b1c0a605561e0" . + "e9cfa729a6aa5b1e19e8d570029946c87703e9abb0b74aaf0698068b0bf81fcb" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "e4bf8bb8fa02ff6d0bc46d9eb5b97d6763830dcd2f771f7a7ceb71e0ea1f1831" . + "d952e0d70717125761317704c4edaa13f78a3764f2c2e12d0ae8111abd98d2fc" . + "2b8f547f12c73701cfc617713cc3d1f41d7e5882c147f88f5e9f8e57d7cec626" . + "a18dc797521b017e264cff936920dd1736e2a1900bc7991a9fed7943afbaea50" . + "2a8cadd29b595bdde38fae7588e6019c49eb58c720250f0c064c6bbdce8f2fdb" . + "1f2008ef4d2ff426a84c1faed25c3d8bc20737571d91efaaa674bf39e9f00b1c" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "8cb16bfe35467bab19096a9af0dfe596d1ed15c6904ac6234f2f23883c82127d" . + "1d19b3e0d58ea288f664315a45b247765e784bad1aedbd7a4fc6811e8251fb56" . + "777be93175bc9f38ba776d15f2858e8618a9a6c5d277d421179ca533da4b0866" . + "f90650e33208f4ad39b6cbfa69ae45b40ae10d356863d42fd9eac37e80569daa" . + "af500860ef81866022d72a7adb5b80076ce09f245384d1932f7248d5524d9efd" . + "60f4d555a37998fb60287a0e03b37eafb967743e04978ccfc3f0d4a48e619eb7" . + "5649bd23a39d1f5bb9b09ddeb83aed05a96e879ec79d918af243802604efa126" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a445c9aeb241ca3db2f7439c624f5f16e064154194f20df1b360bedb8f025fa7" . + "a445c9aeb241ca3db2f7439c624f5f16e064154194f20df1b360bedb8f025fa7" . + "5f071f8bf069a92588607dc365a5e1a8c492666b8faed82c60d70cc64203adc8" . + "a815a54a757ab02dbbc5b7e75539468c5318dc7afbf4bde135b577d468eeecd4" . + "b9c6b1307f91d0f0c699bc11e42f83104e1196cdf2df77bced6187e561ad454d" . + "7e5e29b650361dc86ca877b45e524b30e5ecc019ad1161ae3ac64f7b61d39b10" . + "0db9f71b8eae2082a09805c71838f23199e4e0b6cc976688a6b6b79b4b81f46a" . + "370299c429ff345e936535db4d721051d0e67dc60a69a0016feb6a15d213820c" . + "eaed2cbe831aeed5e15b35f7853b04b37f1a532a77fcc0b98df64c849a16e120" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "6ff1da4f8538bfa0fd7f0ab1cb30ce4a0f1e7fffc6ab1b2dc41f41d08400c498" . + "e6398d5ea56c352da17f1dc93785bee10a16dc2383a7d6c86cda0008d074d756" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "f1bea9e96d7aabcfb8bcd8898ba7e94189d239358debf37fa9ede11f3ff6c8ca" . + "59076bf1e6bdc3b543c140a4746126a7b94cf13cf224a4d215e254be7fea5bde" . + "c4e8da17725247b855c4a814fc40f08c544674a262b2067ee148331e209aee7e" . + "e96b966e2987760f16657fb22132ca5185544ae6061497ce7672bc675c73b731" . + "f1bea9e96d7aabcfb8bcd8898ba7e94189d239358debf37fa9ede11f3ff6c8ca" . + "a6ac89c7d9b5fcd79de04d603b50a77ea37fe0460a9364e08f59046a5e609425" . + "28b0b0890cc69ba7b1d91db4a6dc12cc8d1fcc78c05c141f5d96f04edb31f531" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "433020614ee58d465c33c8babe17df621776a973f19911af9c4e7619e4d47dc9" . + "cf200de4225964b16871046052c564a878b672da471cb64ce26b7ada0dbfad30" . + "44b69080b764f07e3ee70c8de656f8a241618a36ff67824fa635d10a213a0525" . + "532f881bd0d001104594640413002479f6a897beda6011014f20df9fd6d71d81" . + "30612057d7967db9b9771f5b30a2b9cb2d1528e4cf5c6d33927dbde1bda850fd" . + "08de595bd48a57d79751f54160110ad78151340bba71ed4bb53f5cde3689e0b8" . + "b4f2e967fb0de34fe0ee5bef7567789f1b9e4b9325fb179d11f87db8c3a7dc7e" . + "0918201a977b59b5ae8015b619582abfc16191c347c3a3468247fb6d73564c95" . + "22fd53c722974e255d004cb56a1ba37cb078deb44b9998e0383ef3cbb3b1afed" . + "51d9342fd8ce33639e7b1c0a79a64b8970c860847bfa88502417e824c89a1222" . + "c8f28303450d87f0d41964a5074d0cef8208f7e677f99f74ad75e95e4357aa2e" . + "7b1c0cec1f63ff7b204ca8f61723b2ccc72ff5424d5073f9107d4fd97615b820" . + "ad1b3fd90efd889c987589813c3dd943d1f8d093d5263c1864423d3bd621b836" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4a9415e6236771f55f17a613933e210c04607b4756670a83b0995f6dc1f7c55e" . + "52b07707437ee2c6f9550e8318bb9e8f184ea2158ea2bb78b6d5c3f79aa90ab1" . + "11fad8171dded1fa383776fb0038a184e3e5ff53126c0f5037070113e20025cd" . + "aa8f3a0476ce762b6863fd49bd6544e0be28e8f571116b22d5d158ed62931ae6" . + "a5def2c1e0bb66430c9767fe5d02c7fb7de04bcf412af3e9ebd8378834925175" . + "363525b27f909e85034ff4b4345e0486be1471a8af1b13ffbf996be6acf4c7de" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + . + . + . + . + . + . + "92dd076b9daedfe6d1571be8be48c069ab15ebf2337cdc650b0d80c40590e61f" . + "e5e74e935c5c797c7cf24f46d4594966fb7eddee6873c1cd8f233570b02a9403" . + "e4b61014681ae2cd0e0c86342fe3ebda1ad16fb751212aa56fcbf4d1b85ca604" . + "0786db3315ecefebd37c4c635475b958b8d4015f1e29544ca6d305910c154569" . + "76829d4a0d4572ccb843ad9961c97826bd22d680137b14c7c1a1aa7bfec97065" . + "79e113beedeb91b804dce78e02dd74422b75e47462bf32710d60926be1e6532b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "0d7f7c92156ad8e0bf5cc4ebc4c602aa844c6e4e449f7f5ffc0b4942e66be6fa" . + "a9823fac168968603827aafdb10c95c2acaa965b14baa62be4da9d408badf08d" . + "3573df399e5cbf7b87bdeccaf12bdcb2c933656be91c76bf4dedcdfe76c0db19" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "2211121d5c550abaeb8a15ca0bed516f752b6df9ea433565b2ae4e70a7912055" . + "989ca7b287b4de20e9c0c6f04fe19d8d6c1cae39b0c269402756fca13bc51303" . + "046609023ebf7ab8fa80e36d1793b7a82f035cacfdb3ed2a5f21f415e90c4cf5" . + "c2a389745ab23f9a9f12f99d35fe98c71557371bf46630c115cc483d6f506f72" . + "8446ea33c3cb0c2402f9abeb71ce59e05cee9e8d66fad102fdda22465e4b2ba1" . + "61c2c5af461aa0104492c894a72fef3022a552f98974242530df8a582dd9c48a" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cee029118d0d283554d1f12179310b28e87193a5bb962a1ab42ebbbd6f29a34c" . + "cee029118d0d283554d1f12179310b28e87193a5bb962a1ab42ebbbd6f29a34c" . + "837af5d00ff9367b0850c35eaaa8bffea772dc2402e71b61969dfbd802168080" . + "e4c3c2169739d206d970458cac04100ee9728082866c09d226621d033852bfb3" . + "cd10512e148d6f6715c340847202a7b225a1518d948fb37a9d5086cdbf07b03b" . + "dcfeb8608f1cc3777030acb1b5f5deda19b4487401b811969b40258dd6100374" . + "b66f5d2ac90616664289e741cdc3fcc9ac6ab1012575e879baae4d5a29db0857" . + "a0feef77c72b93c2ebbc965e50f74931ebacad2c0d8e803df3a61aea45ec99a8" . + "5d8f3fccb08724c035bedea8e3716ab29d022da8f1716cb53e7e1fd5de6b2162" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "9d030610a7be99abd6ea67a369c4f3646daed633868523e6ded0ab51ee493149" . + "1ad557464c50a7271dc9ec14b2d23dad5d384dbff209471b595e5ac692f82a0f" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "542486420aab57f893c9c03817cec874b836ea8cef5f88b56a1d3f7d632c0e57" . + "58ae9857a5e3f7e576df0249a25f770f4cf9215b0c035d0fda22160ea23f7e6d" . + "d08f227a83e746083312d8f919e468db5d77620a8b7980a06237d4c501e60260" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "f53da32d39f3438b1e7d53fb981c0762a51a8a5ffcb99f0713dce38924ba4c50" . + "27c0804676616e3489406cc820c8e88d1141f7daf1f5d520aec1bc8831d53ced" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "e90276b96385f41c62f822fb6d8e926fa81f49a671c1984b36df300da0525fda" . + "57fb6bf37d10639619f3d63fb9679f9b688fb59ac8ca9f49ed0cd1037808b7c8" . + "0223ce36e4edd3d46ae909069528490d304aa5607b88c077cd9d1aea5d1ba18a" . + "ccb2336b9c608bf97a1fdddb7ab006aa3863d5d950e1b32991710bfe19b856e0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "5845d99613e01f5d890b2ba841c1054851265b42d5a2dbe80960025025677a96" . + "f7fc3f5797d3765813c2dcb6f899b9151c7cbc5f26e947dabf2270e8cdcc386e" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "52d408962f81a3f5fd451cb1dc493a6f88c9e10a938165b48832ae67a004dff3" . + "31768e9911bea443bf7104044578c3ebde46a8b6482aa6e4f708d34c35c75f14" . + "660eba508a49bce153404fe036b3067cd6baa3f921942e611b1932f255fc6305" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "e9ea166625521fbbce844f497b9bd0a75bc1718fba650fe138f14d8fa2b50c45" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "923f549e3fe56c21e765fad13da8d4f18a843d504856ad0980b266cbd717b797" . + "31f68619b16ee4dfa407fbc76067caca601906e6be9f046dc26f2b5dca51c1fb" . + "6420e118d078ab5c9a8efb147869036f65c7cf835aec444f4097cf602a0df5a5" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + "ff7ebf036709775d015b385173db53498270d2f6d03620f8fc0c8b90eb54813a" . + "33ee31e603fd02df498493d67e03d366a65457f55ef243023c701815c68fae7c" . + "47f7807d324b355010f2b3188cf7d82caddc3cf9b974231c06c4c6fa2e8b96ce" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "a0877029f72e3b4d99ef835c27240b4c8d2a80adfb263d5e1ebc097d6b95ffca" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2b76eddc2ce22a20f6c31d95210c1c72f1d76b46530ed12cf9a724894db34310" . + "a6e1463d4d9c87841ea395d8744df99256954f547dd38aad763b8f685726604e" . + "6e59a53d7b8aec521f176d53c5a3b8d2daeab6f8a35f795e94830498928663d0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "63db2240d20f6841398d1df6aa8ecef97f5d6e23945b512db5d9c8003fd76919" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "4a1eebc35094dab4a720a1dda22f92b9afeb9ede31e666654502acfabadac614" . + "2cc1f4ea829aab631065b14d77e8f0ed5604aa43fff078781e096a65c8d3d5da" . + "1c735216a81ed17f800b313478caf9f560187a44e08fa7e238b38755cc087048" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "aba10709d4fab2fe074ddee0a8ad9a62b92e96485b9ce1b5edd5e2b71d2518db" . + "e6862a1afa16b962408f31f7ceaf5c99b0f797c9d13ae233af47443a714af871" . + "49fee760dff2348b225097700dbc6e64cdcc41e4ac81577ea64c25717e5ed940" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "254f5068d00bfd340fd3691218d7ec50428cf6642a6dcbf12e6696f383bc3358" . + "783a5005e1b603622c934b80177d23f278c92f3c4c1c91b65900b60e61b5e9c5" . + "642c0af42a83fa3aa846b079c47df49f8079e411b79ec4307a59c1f4290186d2" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "ae7f526cf00a62986beffdb4ffd9c4d2e901d92fda83171d10b37178d3d49b10" . + "31a4e68145f70ae5964be280997a722951a1d3479dcdf3dd997f720a5c854b59" . + "18ee8ee4401cef7300bd1f4ec89a1b3e34d794eff63b6ef97218711669610e38" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "27a1e44eb020d9238f622b08b7f7089fe133f4ae663737ead4fa090bfd649c65" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "6b7df8a2a585614effd4b213487f5187fbca961dc442ed210b29cdcef43a1a91" . + "459f8d74b567ef3b9a55314b018a0c8651563e6a62b9473d15fc26926760090b" . + "0eb7df5412d734c208dde79500db3d823ff8bb9255f5f7c9155b0df5075212a8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "bb3dc0632a23b2879936267e87ef9f6f48a0688a7036bec027904a741ca066e7" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "5f36da7ea5ea5cb0d1a225df19f425111ecff8d86277962b0704ea12eb2f5374" . + "6840a7dfaf0e6306a9737958243f89e63e2b88675e773a6eee955715eec156e1" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + . + "59e26f71b041e2ce6abb872d506827b4cdbd459a75b04a4565feaa8b7c64c985" . + "dabcab9589c156cb33548fc063edd1ca256c22a02b9097330fdfe60576e8cbcd" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c082176ccc498a9378f6983f85ac1ed37626321ee1ee687d0202fcdbb62ffdd0" . + "c082176ccc498a9378f6983f85ac1ed37626321ee1ee687d0202fcdbb62ffdd0" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "3674ae80f9f7ca07881b6f97a58e3b9c065e8cb7f57c3f6548b5592ce9972f23" . + "e594cde2b661b7043dc1750c930af7d34fecd0a5a7bc30fed0b758b21db5496d" . + "8dfc5d71e85ae1d06ee9984c216070a573964e132335103e17e73a892131a1ce" . + "f73da68a6541796bbce5d3daa93cd01819db77f93d5f567d725e9e9b2db8f448" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "926a308e3494e35fd30ba8b8e5cf835e1c4c0242d14f6420efda7c623d2213ae" . + "aa6e04ee7bf74d19244d64a28799fad76744c02c200796d98a65a9183fbe6330" . + "f6f550c1f196ed8ebf8ad744365bfa245179e65a3cac7aaa3d014e176f3edb57" . + "403f2100b5bdcc375d641e10c6375babcff4a6df6d556f6558a1dc3bad5f5973" . + . + . + . + "5217c0e6245b1cde6e3e9c9db1b3cc713d105b90c9deda22d95bb9d04ad75bf3" . + "7bcfe3d17f87916271c629dd759b694835e1f29f7d1c8d798c51761dbb1dcb06" . + "bd15ddb151fb1547aa8f6e3bdf952440b4ac489b4ac1f6eca3d28934c745a7a2" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "204a78e4a5dda662aa9f7995ff597dabb6273fb2a607eebe60066b512380ef38" . + "aea055e65bf20bd42cb7bada9457ab354d2cfee1992624d8cf02ebd287f0a87c" . + "83aa8a3e5cf8941d93b7e80859a4c7d19f96ab4f32d150436312ca40b3bb48fb" . + "734f2af9d84f3de115a9e666bb0b7310c095c5b038e29438093d7c0dea9493bd" . + "6dfe760248a40ce13169633a16c5b9cb7dc65435d7798ca22e00ed1e18658361" . + "1a0fb7eb71a001c567137d77cd21d9e3e00ce922a240d32fc047e5ec3c1a7005" . + "d3baa2181ca8a3db4565932ff5ef017fdfe52723ecaeae620fbcd48942107e67" . + "2f960005c53462cd27ddc5acde222444079187bc255fac299f9c18b45972485d" . + "108e0f34b56abcbef657564fffced507da3613d434768acd4c0dfcaad0a62afa" . + "fecd2c4b9b718c9171dcfe527ccc99fff7a6b2a406bc67094e4a41ae0f8e43fd" . + "d8fd4ed30a2b65a903576d3b3a43f1690f559cc76318343064c6c02d1db8d36b" . + "c2079355d524b2bd8ee4ca1df4f22d9096787abde823502fd232d4fdf02699a9" . + "24b32701ad9902c59e1ec5229bffa09215cee4e07f39ddd2a06c1348508bc7d9" . + "03e6485d2154c7f97d4c20e2e362055c85b90988ac141c1093dfde2bee6552b1" . + "a724920cef9bbd53594e7f6dc24ed1770ca92a496f7682c428a71d75e62e7565" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "5386a85692aaccdfe4f6d211ab04d280d21d9c72a9986727148c426d73e58b05" . + "83a6d61550b4b44cbd74b31eab89d930aa152bbffab21ece0a7fe9ee0683ce3d" . + "bce7cb488529ebeb53ddd102e611bc253a7d99292bf907310a027f7b22370545" . + "a2311e1a9fa1aed52fe174cf522d3fd40041a63177429e91e8fe5f1864879eec" . + "a323b1bba282aa80e025aefedf61453cad581dddcdbf4bb1205f1c9956894f42" . + "88491fa0a2e891e7866fb31c49423652c57c1250f3e63cb79199ad835f48a76a" . + "71309091994c1fc714a92331fe00cac00bad93fe62ac5f0e3778104e0f2aac38" . + "ab3adf01c1b36ccde00e3c52e8020cb92ae71f2275f7e1828abccc8eb0d9b652" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "574959c59932198dfd6a0af6603884220852c57c5db96d7fd5d4e53ff158681a" . + "45c920fdaf2a5108e5870ff1b1a260b66a1e1c56e67aec7d5bcfdc38f481ca86" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "47a7a9d0a634bad9b003cecaefcf27878791d1d79f8b1b9f78ab65b1d0025711" . + "574959c59932198dfd6a0af6603884220852c57c5db96d7fd5d4e53ff158681a" . + "75cef94a9d9e1d194b210b3e20d981b75e4cceff22967bb5f5ada7ebdfa098e8" . + "1b55b26122b9f0bb1d72f2506b96c20ac4e1aba5e486c5297522df8de1da87b1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "abbbf6b39a798522922417082e8397cd6d20eff5c3a9824cd3eb4fbcb9b06a41" . + "abbbf6b39a798522922417082e8397cd6d20eff5c3a9824cd3eb4fbcb9b06a41" . + "b39a766ca6437fca9e0c6e04e9b02f4b852879145af0442f72a2c47ae02a992a" . + "e9923492d75ab856ac8c39dd51c78b568418c1cdedf295af599cb378711ff64b" . + "720a0bbd50fea267bdfb716d2bbf471686224d2f25c81862b834c37bc2f1b1e4" . + "2023613b7a13cdc79512a0f2e3aa79fa56d3433c7edfadbce254f068c0557540" . + "9e6ad48673dd3bddce860ea3830ad03c9a93eac1e6468646a9027616ddfd36d2" . + "023522361090eedb0439053f3d675ef8729f1410b39bf034afb54aa3fd8e71b5" . + "788ec162d8bc395f3447cb0a276ffb17acca8605812e31cd71ce56869c805bc2" . + "6769d062f378958c9c24204575746b47c4ae449a0040c62ee322ad1ce59ddf02" . + "7d525bdd1dedd94473ea091d7926c6ce40652158cb389e56f8f67082b63cdf1e" . + "94105c2c4b189a231db13847a0dcc2c1045db0edb7ecdb07d9a6f5a081ff2575" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "d88a2b6af3537c766e030d34ae93029de6adaf49343d7b2473f7cfb805a0e62d" . + "47b46d713bf2465bd961f63ab0999364354d5a033e5b4277a7432384cb6b4a52" . + "bb358b84ef0c3523640e5964490443ebefe86175b69ec4f3024d8ff650670c92" . + "7b1ee67a5d1c65637665416a340f8fa8c9846b620d732f7b7f624b4c040ee7b8" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + "12e5a77f88348780618b0c919a37182373ea0be70cf684497fcbcd544da0bb13" . + "796dcdaadbafe4a44f2a45342434e066069c4292aa3165ab2cee024a2c99be51" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "808dbe86b8dc048aa241d51ef2eb4d68c79bb89677f89ceb9b49d9290ffceadb" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "ae453e3faea9fbba031ea28aa93c76cff8edbca5f3b66ee4ec68e9a4cb1c373d" . + "9d8f9c4f3e3d1c31fbe656f321f40fecee96e8caac40c136e1a2d99b1ba2b5cb" . + "afce873d7f207ab19461f1ae9e2499006d112bd9aa4cd63b953cf2d1fab7f2bb" . + "384fdea2b04acdb618d53a1075aefabc950fd23b9aa1b7fcabd3d354301ed4a6" . + . + . + "c2d7846924549ce7658fdebe9d37851c2a1039405552727135393e283e2a8c66" . + "f632461558dd61b33c498e40c716950a4809eadc2fdfbc53529ac59b9c2cfe15" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "06cbf99b78a63b5554fd3d1d059bdb752cd8f04dee3491fede4c2843a732e81c" . + "06cbf99b78a63b5554fd3d1d059bdb752cd8f04dee3491fede4c2843a732e81c" . + "67528d6aae70cbc1fe7cc740fb3720d13c060f22499148323caaa31ec1670e94" . + "dfcc32f505c698b1df862d8a31c711b920aee0551b7d820c44dce8283366eab7" . + "7f6a227ba15b13567ef31a0d55f8833aba0666f6b8e69e7415c000109f9eb692" . + "5790b65928dcaa6365bfaba7fd259bbd6a08b47076396c2c85e1649f78fd314a" . + "a2ba66f2bf5e0704ff4969f45a0aed4eec55166a1cf638fc912d5d9e2c6bbc81" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "a3fc34af46867c90cd068e4ce10c53eb52a2427c606c248dcab8442adc824e1b" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "b97803181a92a8d55f4b2e5475307cdbee18a702614e5363fc238c636b58cd52" . + "c721da7e4393351d5e0d84fb59ae5702362327b7c70d254eca7203b146897c1f" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + . + . + "b6c24cef2fe488c634e21da58c2fca1279042c4368157a0ec3921df05207643c" . + "dfaa04b3276e2ebc9544d07e477895633e3ad8c225e8f472fa4c72a63cc16593" . + "bc5f71fb6dc0745b9aa5bea891db52990abde28f8320905c954f49d29f1090aa" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "32a97bdbb037d9fd21a9056f4d5b1b9f8f90e12e75dd4b28a4e6887c57b41b06" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "913f52e112cf088b93d76e7dcf9cee5f9eb399e3a7416d53270f0cf43ed749e6" . + "a2c808991a802768fd8de54c7d93e000fcfdec78c52fd33c0a3ddece23cf39af" . + . + "de0cb8721735c1dc6d071a2e10f147534ea41efec0a11305eeda3fe1bea12f39" . + "d7fdcf372f96ce87df3d4d182798559ea503e25a91808286c1fc7b90fed75422" . + "f56f88ac9b86692ec9114883ea83b2b7ac75c9f2e4362b328ac945a3c41b5d4b" . + "0b431da068680bd412fd8eecee7067d10ef529def76937acaa3216f947cbb227" . + "dc02a91eba1fdfe282fc25a8b5c657c7c9c4fb88a7c661744959de1438ba5bb5" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f02a7deb80162751fca015dd5f48f4a72e82ea3b62b3044b4fbc18c44eb0a529" . + "f68497c78d919f5f9b07f51b8b35d4d4d3c6bfa57c8b9b0554632dc56d8905c7" . + "9c4a6a95607394baab04ab3aa7c771e6aaf0e20616cc1c5a5e56406e8917005d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "71df436740e314ab5d9d34d5b777775b72eba76b932d7fd5bd1d0a7284e9365c" . + "71df436740e314ab5d9d34d5b777775b72eba76b932d7fd5bd1d0a7284e9365c" . + "a4737788cbe782f4855764969210f0fece7821857e8538ead41b059af526cde8" . + "14ec41f8891644f33c71adcf46d8693310c88d8f9082a677003d2a4e16699b41" . + "2b0e2e33abe72e4b061c30cd2ee5e05050bc4b59390c4a4657073db4d45b98e6" . + "e14092593778bc249f82d991966a667a3604554fc7cd8c3da65868a0d72e50a7" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "1059220aba457bac19b838dd477ca8c9bbf5e015f543b2e2dc2db09b0017e24e" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "d04415ca70674830ef86393778a0b434bef05b188c901c7119365ca2a034efc2" . + "932b2a580c6df0fa6edb1c0588b465ef874298e57698c2860176e06e21a2b702" . + "473c9b41273439562bdb46f8036560e0801042366d14bd8fbe67c816b1bc9159" . + "d2be66257a086c09c76a9e1fe6a0f6d55b1bd887e4b97831c9316ec55641892a" . + . + . + "af052ee8e5e862a9218125d58348e4b7b7b69fe49fa2f1ed6a336cf3c9713232" . + "5d399850e62e6a0d7b4e019cc2e665b8f8a181502ce5db8eeceabcbe36dba0e3" . + "a6b714fcd190bb8a2a0b8f5d31b42e5a230a98223f509bbfa8f532f2ec8cc67e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "de968ca4069d5a9eefce5d9e7e4fe51f6df3d776426fcc0b79c66202eea431ad" . + "0c9714212e97978f443aac4b54bccaba135457779d059a01f39fb9abeac04e65" . + "6eb6460b5415326f6325a223973fee5953d3d5458ef6490d7048adb958b2ffb1" . + "baad83f5ad64d97eedc395ba6acd4337588488ab98af5f07770992e543ef3a0b" . + "ec62b202b50440b559cc3981cea308894f1cbadbe547d3bfd696b0c6a019f633" . + "b18821696e809fe0da729780359d85dfa554510d8a70684c77053d1178723ad5" . + "2b98755dcd9cfc0b8f4ed3209943889442eef6e63d5498140ceb5ed0cbb5dee7" . + "ed6449300d997aeead17448bec200bf0eb05aab4bd110edcc424b7e0bdf82cdc" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c2b4f085d5eeb11f4aa216b106ef280916e71dc90e9935ffb51db9257eabd72c" . + "752c15e127d7b8f893cb039251fc01d9e9bfcad8ad5167bd41de181406c7ac49" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "8866c436553ee98c2a51857283a7a504dcca2f3a69d8de5e005f99dcc0e17ed3" . + "ced71dda49465fb52d8a2b4162166343a034509c5df70ec52a29c6101ab010d6" . + "f5b98bae1cc2e293f4259181611db1ab5c39d09a4a39c2ac8af1f9277092ced9" . + "980674906345fbdaf4f3591983f8ce3562872aafc7b97266185317d7f9f7be39" . + . + "7839016f3a4d6aa25f519959950d9ee7ec09bf0884f7cf6ee73ea070267d8695" . + "7150b477e13e4fa8df3524ddd033511cacdcad92a156a60fa5f3b5510012273e" . + "03d991442d36c8970dd4fc3e26a9eb8fa07ebcaa8909be7944c61e53694a6235" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a78cff5d91a2df97c86b3db0d30b756320aee26d49028acb04f36d3466f53ce" . + "cd1efff3777d04c1b103576141932cc2d958c3546009e7944601baea33ccb5a6" . + "477804b8c631a79663d643dd29be09bfd0b574a292fa461aa2908fe3cd40538c" . + "4ef49ce8068cd86fedcfec031a62254c76e4a28dd579b8af503f48e36387728f" . + "2eef390df64924b9fdf05df0824f6675a4cf23a0831e1dd79b15484b79abf7ea" . + "b3f09d473d951e781eddb46df39c82a39b7d9ba27ef60faaf30dc58d80b70cb4" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "3e850903a07c6560f430ed0348b10a66886458f91cb78f8aa3384cc2c3615608" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "0359c2b178797fd825d5a75739f5586701ba09171177a3c7d699d6bbe2af9b95" . + "55c8e1c6735aa8863a5cf46d401e73dec09946bd342318a6f1ed509c75cb62e2" . + "bc90cd3a568d440fd0706f77b1399ebd848016dd5852fdcf41203eaa587de582" . + "783e6a04c7965fd9ef54fa349aad9a9f48b18cb211e8e5703f63dc35289428b8" . + . + . + "6cc5372c31aac297f7f6480217b300d319a8433a5095d40e5f221aceb28c73f8" . + "3982c7d8a60ef950b06572cc934a4d1ade51a65234550f39617f925baeb49291" . + "5a27623f87094e918ec6e03dd8e182d2da6a610585da768b127173d293b00e4d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1d645d0365577ae2c957402a2223ad2fc472ee3151c1825ab84e00568d38f531" . + "fc8b5103c98f8575079f369e5d6301b6213570b7d5556cdb25b8cb657bbd9ab2" . + "19479f0f711b8ac58745199de4e01a22e7ee00d73ae238bf0c53d1e46f55e4ab" . + "ae6742ae7e35e11b1c12e9e1be593f9ca60eee0f0b6301b8292ae73d3997c787" . + "588c74686130f4e344979961712c691806ac69eebe87fe07501e689825a32629" . + "a90319a30bdb9377acfb216e4a750d2f6309d277df9088241ab115be6b0d9f78" . + "a10dc782355c096e02434bfffa395d2c7291fb2dadb141c3c27bd7343ebf5dc8" . + "0cc92731470355ebec0a079bf21c80085fa57256aab5524aaf05ea773c611adb" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "1a880217de5975ecab2a4fe6a834a9950d34dcfd67cff897624c756ab9b69709" . + "23e346a14e3969348176a883149634e6be303919f50aef67db3b31ea703deeb4" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "f1c54fbf98c47df0d67c880fa90125c675fc891a4e062b66062721d633f6fc0f" . + "76b31719c891d9b2cffba5aaa9026b17b12dc80851734d656e15e468c0088a5c" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "e30262c6dd556c127f1ccbf69fab4dc34e487370cd6e932da50b6fd64ea6c646" . + "bd27ce3dc7fe31ed7f4cd5ba6a594f6596a37fa9a5eb3cc405f4fc03216c15e0" . + "1ba25749b0d993968a5f733793a2afc324873e9c0fbd794878f115499552b5ba" . + "492d688706313fb6c9527082bb5fbf95a2435c7d09394638dc509c2b916392dd" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1a9efb68176e97b6fded895b1d48c33165e259476f971f36f7f8107390144e74" . + "3496825c78facc5795dd612b5044c6d1845626a965bcdf674dccc37a71e6194d" . + "54526585d156586c00b4ff0fabc216027b47bacd36f63f33e81bc701558144d8" . + "9389f34fb2441f41ed749fefce83b315b6dcc7b1f2880112e469060b609ef3b2" . + "e20655f03f7511df98c4227e8492f020df000c5327bd03a5c5994f2172a4ee0c" . + "eb08951827b819d2226b5fdab0738cbb41c9f813c2b1c70ddcaac363ec70f271" . + "72fa5da52f7342380fc623c03ade1330c3a6ea6096f690991886ce7808bc7c80" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "2d234cc3868ecc1f51ed5fed0b7d7a20d249913f7300191808bdbd3d21d009ba" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "85b85d2a2ec5e2dc5e4e0e385fbb5a12ded701975272a66457c8728ef4355516" . + "544eac02e3eae83296be702e2c0a98983f92cf47a6a6fa8e3f908967fcbad432" . + "575f7600a918d28ddf9b85bf8b1b404c1fedbbe5de44d637437da5deecfd76ec" . + "a4b06101d3228ffff24eab4d232d2e50cca9b0f06f58d9beebc3de512dbe8b1a" . + . + . + . + . + . + "85b85d2a2ec5e2dc5e4e0e385fbb5a12ded701975272a66457c8728ef4355516" . + "805a18cb86dd347dafe38a6ab1580a6181c7e03db6f04191ee35c8882739f52a" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1ca62a7a00bff84ae63a6663dbe26c66e949f666f843508c08a32ad6e52eef5c" . + "e183e4ad227c3a79512ebb7fb4a4745040b96317db39462270f55a705e7b7e4c" . + "577c73e45f3a56a89038251bbdc0ee522d598b5c9c3be3cb1148a5b0f6fc34ed" . + "36d8aaccddce78424de117e2e77c149abbf9aaea44eb5ff625bcb0e0f3939d5b" . + "b67e18bb8e307c41ac665a4f78ceba81a7ccd24f9c7d008274683d758bab9060" . + "c62857dcd4bd0581cb3e69727d881dc79056331820571b4dabd2baaf0654aa4e" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a768bc21abab03c6d883494965fb316bc99dbba457caccc9dee8d5d6c0e9686f" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "05dc44e6d6abee3195cc3a00dad8e6895a6967b62d08c576b0b427b20c3facdc" . + "6c6da19d20f80dcb4fd54802297bf1d96069a213da410587e8139cd6926871f2" . + "a9630fb437046faf1d2c807693fc8cedf68dc65f8bf14936451b4e6007df7c9c" . + "b8b7f2e544265fdff39ae6bd5c3b7c2d63d452c94a63ba6d82a0145b89a0130f" . + . + "af63e977438d1cccfec814291261b4c518493290014e5d8efcc2c733e15e3c75" . + "0f168c5cf83ba2a2a4b88c914154d300f66ab9bac0e232efab01672131fc4267" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8671447a2a49a7f0a5498849136cc4f497d4513b7edae00a04d4af32a20ce588" . + "0877c262f96ea9420e63c28512a54a5136b53a5ad50dfe80d81103b1c0260e8e" . + "7abe6b77f0edc102d58c30113a0ce1588c5ea8ee4035dedf33718319430237e7" . + "181623c1ddd79e5667a4300eeb83815337db9d5b99935cd72b730cc3fbea759e" . + "4a18c07acea66a5682a1c1865f77a60793c25079bc7dd14ea7803992ada8b2f2" . + "60abb33a8e4dc30d7bf12028262b5bccfc81a50c7ab0b3e353bf1ca0de4e9337" . + "fb3355c0fa26c490a6b6aee36920c724eb95d3790a140f112856db69a9d88f4e" . + "ba91556b9fdd6e5f78cc8801702492bbf0270870ba2e6900bf3e3a5351e21778" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "8129427f6ad08aea9458dfa54c1822119d126ff5d75d72b8e2f287b5735bb305" . + "232de317c40557906b925877dab380522cdf38922df6065835aea1a1f7e37a05" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "7cbd1453a329f7e96e149e72ef10834ef092faaeeb3b2dd6b9fa6ab6bc94226e" . + "da75f746715fcb0915d15825f10e31a7c9c635b774c0abdc4ab91d935ef10f4b" . + "05dc82a60bfb04d0194164443c3f83bc8210abdf213b98f82afa4ac6ccce7b8c" . + "fee2ac3e1f8fc1df251dc375510e93ec2552cd1a2d45a9696cbed47a786d826e" . + "547d3efac2897935da812fb345af5d19d661228f5c786fd39e72b211f7f2543f" . + "9c787cab58b0834a227b19643a625d4861ec9730cbe462b66fb7220a0dd60bb0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d6cdacc20f89f987b04429f0261d69d788af16c6278c25ffb8bcb18e1f9ffa6" . + "6d6cdacc20f89f987b04429f0261d69d788af16c6278c25ffb8bcb18e1f9ffa6" . + "e6392c3860839d6334e57a5b735fbc16e34c0ff96e7880c62e08625989b80306" . + "6304bc0e23d35f7cf4dc1b394e895cda280953ec1c6c3ba5a2bf53d93b6cd895" . + "d391651add08236c220d3a395e7b3b5e297dea5781277471d4bed7500bd86568" . + "5f85429823694125527b3c2d63215b4dc689c1a24f5cae7a9ded7c5641d73128" . + "5ee7b81c25cb60b770174632624652052fe5cfc14aab32313af33258c4bcccc2" . + "829a9884980703555c1f9e4de4b8a87fc9808b7dc15c458cb78bda8baea4f015" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "fa24b8603513501f691258b534962e52194ee602c3b9e6dc1a5fad6749af8da9" . + "f45ce9bd0e5e9f9d89b9f5269f0869bb66d8e73330f942c28f200f7019b97c80" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "0a550ed0e2671adcd3ef7ebaa865ce0758ee1bd9c661aa331f4a471aa48e0867" . + "8fb06a69e6833646a641caa25bbaf8fd50fa5df019e65246ff039d01b11203fb" . + "e9050fdba47ffeb9dacfe7692af10ebb29bf689aac1b19acdbfbf2c5269437ea" . + "3c7d6a0af1e2ff0a38fd5012466d8e76328ae2b85f313b4c16fee0f70df46354" . + "a49939de8cd3bb1a02df6a608e8e53c6f93b5771a57773afd49b799c9b25ea17" . + "8807751d5ffdc0a6e57d350ce8d21797ed36cd4afc0c9c87e7cacd728f94f9d0" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "89b90a595b41e2e34b50e17d082e3760e9c42b98b017d539fd026247a10d48ba" . + "e1dec935913625b082e201d520eb9daa532c5faa19066a4c556dfdeaa595aea8" . + "5a48283c960c11da51528ba1b68af4ef3add85e83fca5ed5280dcae8d61f7354" . + "1dad0cf507cc6e9b98f0e60ad3b8f6a9a5a382599c29d29dec65500eab40eb0d" . + "39dfffe182e4d106d02037331346da0c3f0a17895ec66a99f71cf5c39a664b09" . + "92f828af443572e50a13d427d297a3b8e97cc592e20d902535797ecf87dea8a3" . + "75d0640fa28eff9479d0be1f0b5fb7a50c7b5b45d5a2bbb454b20f774e4696b2" . + "c909fe7cd76e4381e7916717a561654cc34e24f9279f23579c8051c8630495e4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "9aa86e4777741d93c5c0aa470d9ebccefa5b39a1eb8a35531e0500a8b14bb14f" . + "647c8cd5f82ebf7ea00f8ea635aaaf04f18ea272dcf35c850cba7caeae143bdd" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "3bd40873a74c68a9d87c35a2ee656e0f9c5baf6ecfc74c3be87fe00c724b90ae" . + "63fed2dae5a2e13f543b073ca654a2a92941c2a51c5b0692c114d3fa142d90e4" . + "a578f00c9b4c8e5c863f99c93aef900246113b1ad1d037d6e29dfb0228cd76dd" . + "d8fd11425b096a14662a314fa299fdbf2285c7e3fb2fa32cc8089fbc15c3121f" . + . + . + "c8a9d2a5a8564e76500e0f7d1d3c1d1c063f1ddefb21e2d515b4c4b61e30a710" . + "b1266710e0ac6f99a6b46b43fd0f798b08856fd63cb9244ce1dd0f1a12905000" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2af79a62f3be93f48534ad54bad627a8d359e71362c4e5cc3cced286869b6873" . + "4432c918be02701314a906879c88d8d30bb1da1623cf877298a9ef9997724e4f" . + "0ae0eee4fdb65276fc7aba42e0b588cca84d8a85819c004520da9be199382b97" . + "3eb07687cc8c4bb7b4d0e63b6afa47a09feed1aac6da3fd697866cdfbcc18c99" . + "9ed2522bb265c2c6953faeb915fb6fb3836a2d2883bda2f0b2af8e727acb2a15" . + "1fee4cf43a0b34171ab9ce2e512fcfe75f4bd4272ae6bffb519a37e3beebe8d4" . + "9e9cb39d038b27de9069c0e811b75abd2502ef5fd857ae1706639949d2ad0c68" . + "303a4a3520e5ce8118fde65c302f73e66e7b09dd25ace60e20a9bcffc9de3f8e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "4a73c30f45a74d2882838f45ff3e664f1153bfd201214376ba9dbeeb0adaf971" . + "83ac0ee613a9750f47ede123480e8046b3ee2f938f308c6a5a5e6347726cbf72" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "0e4546039a2c42552f25ac3a330198e33e79161d1fe9f29a6440bf6a924d6cd7" . + "41ad12f03cf4d4d4cdf45f46124f16698b1d4d87b0bff9fa79e09d68d90b029b" . + "b3f226147c4b9272043a35fc04e84b7bd3cf869815de1ec52041652474531ab9" . + "ea088b9765a0bae104902994b80efabb58e5c73a1bac39270ac2f6fdd8ff4f1f" . + "fb91ad1b6b43e35fe9c18e46e67ec69e3ddda7390f680d4d1339a1c3bbf40734" . + "2a657b60c4e8499284b3344776775c9a17793fbfa6bdafa46374ab748c1e3f01" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "505c140f7f8ed7f27f6302407e27ca545853ac7dcdc5203e5106fc81e6b14c38" . + "44eca0d3a67fbcf22f7973025e3e095390ba142066d8feeeb796cccc7aac5dc8" . + "1d29744562592179db558db58f6261a59e7f4e004100e34d0300ecf188d36017" . + "563af0233527fe66920141acb341f0a7932807fe37e5e9cdc7b5b5b096b9ed77" . + "bcb9372b2535c9b466269385d97f719109c338e3dbf6a2a0d17d1afb9df5ab49" . + "2fe4cd25ba6acbabf6b7af9f13b7de249fbdd511a108a6c8e83bc3bbc330ec18" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "5a3817f314e3f3495df5ef0f14d4db7a7d0e10a2c3c16b80d69be410d7f116d0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "3d50e8dfbd6e9d98d503dbdd371f0896b67b6f98884de6b1bbc711bff2508994" . + "3f446e27e3f4499a5f3dd967c7d2411d8473ef47e53d3ca9fbd83a3364039a86" . + "2a0303df99074833613f4a1a59b92e1d5bebcb51a527f3f115a14c8107a358e4" . + "6eb8a0c3fce3ee720ea65786bce45487dd535417d84994efd144b3fc5c5d8328" . + . + "b6b2a753947af185df42cb187ba828c9b58831aa5249e965fc8b6b0edd8938e3" . + "1fc92f2c4d8303d866de54556f2470c335764569c2de0e5cf6bfd186bc456cc5" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5717790cef846983f0c8323bc7770a86c492e810d0751f7ef66ba523de8cebbc" . + "5717790cef846983f0c8323bc7770a86c492e810d0751f7ef66ba523de8cebbc" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "48af8b33ac17330d3ea1e7c04b968ac148aa03fc9f266ab61a0185a8413e0108" . + "1ffa2fdb5be30fed10d354941706dca507d2ca45e0022b2fc91b2e4a2c12e715" . + "7a607b0577763757b2ec73ba303c4678dc9ccea62a1cbc641aee40dfca822bb0" . + "2a03515ba46ce3356b86de4b49e872346cfd50e252bdddb72e72f5ff3fa69521" . + "2e38a82737fc342fb74e7e155118ce8ec23ddaae0738a185ea94983296f09bc0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "7652f385679875a6a6d587df790bd2c371b8c80a27d44c8601f825ef63d27f6a" . + "c752415d27e9b27531cab38179f1e1135f90ae72f194213fa2ba0650a967af07" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "c076a43310a8a755e12338d8755a422c90db09a9a2744584259a15213ae145da" . + "dfecb0da64570bc32478c0dcb703e61c1786ec6b6c210171096df09034654119" . + "b0d86e92dae4406c599754b16c8a0fa6877d50aef19c500a5d3b6039782a6358" . + "b55bb7a3402acbc04a3c6855ba4358158b294b52347f0c863de03ebacb13f2c7" . + "9c9d99a64f985d0744737b9119a0cc1d52a4404dc855071d018f63d4355640c2" . + "a8bd30e71bacc97b12e8d8b75f8e10823e86f3047d7e41ea138425580295a1bb" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "07e13f7dc0bad864b28e5b1d7dab5fe533bf845aa8888be89e19a66eae5bd3d7" . + "07e13f7dc0bad864b28e5b1d7dab5fe533bf845aa8888be89e19a66eae5bd3d7" . + "5e61af98f8f14a58c5827f6b411e1718b1381fc3f482eb6ab5d4b7eabebee58c" . + "83ab108794c5ece8c191c16fb93158423975a2416a7859d29b87178b3b640ccb" . + "cad26d80d2b4c832609315760b25f53ad869e8a55e4e6c92acf3d6b703036380" . + "c3bef86b12f5b5442e7d8c0170b34eb689a0ee61c845e007af98d14f719a5e4d" . + "12b021c4221bc33469bac092a6a60857ac7b0e19eca0d9d97b7876df57e14601" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "5df61d89393aa15aeefee3f5f93b4a59e8c9b14bb8b16bdae05b1480de636631" . + "dc2757872a7a3f6868e56e8d6dca0a65dc93c14d4edc9cdc2d73486817f5fe9e" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "850ac0dc6814ef9fa574d360ccc84c816933234ad52a69746770b4dea2ee242e" . + "366f3c867a1255410a422ba772b01c3f068a41bcb25543f3890fd5ff918d7d7f" . + "3322af7d3b9fed43de42c37551d7db25537d8932e21b3855bc172db834b4340f" . + "7034e5484f28e7cd21b2d925653713a7867f1fee5c80757af76d16b481994b7a" . + . + . + . + . + . + . + . + . + . + "a9c32c411b7ff8c8be5415004d9c7b9d8a00ff573ce0696ecf0496bee35e768a" . + "d06ca5f3c88da7675c0fc619c279030a1ea974ab4b65e3c16ffdc89dc1ac9ccd" . + "65b378b0fe38dbf550ee1d0cee79e719d01e20835caaff155a09a6cfd0f389a1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5db7fcae13abf252a7c03a4e88c2e6d23ecee858a851ace4284a5f5c3277cc8d" . + "1a8bda322f0581b018d80a501319851d1f05686b8d947662bf16e435efa6c379" . + "907bd32a6e05d3c0e4ddcb50bba45653c2d76411e323502046edf07163baaf4c" . + "a00f8fc9b59d5a33d39fe2a4a23d20626833114b2ef48745bc8e67a31b8fa797" . + "4156160f4ade38f56c6ca456bd5a66ef5b1514b273e9bb0abbb3fd1ce1b46504" . + "cef40aeaee5fc930b89717e475f8e8f6f2c9e8dd3a1b75bf72e7b8f5817b1392" . + "cf9f48f94b251ca85b7622a918cc0c9a949feef38713fa6c8f5f384ecf276e58" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "e4295d205ea0bb4bf0ff6586a161f80714c1d189cd59a3644952cfc48b5ba58f" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "2ab6900e12202e8ddf716a6bac4944c485161fd83ec821d019fbe111e1f0c487" . + "e21ace1d84ee7cefcce459f80cf696e8e51ee91074c4e84240a7860a0f79a167" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "e3ac7152a4d58e15de8d215f780aa5d52534948b196c08600cc9140da25a3310" . + "ce6735d836bf8be9f3134001a695486a90b98ad41561e3f014eb51698e90b46b" . + "e73872d2c471b02d945fe3800f7a6e70381a349343307df60920de4a1ac0cadb" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cb7aa9cb31fd8977ffcd9b061a8e970b0fa427dbfea8f8e8b1fb76224633c5e7" . + "a08853d6bce93c5875d93c42b85e0e3b05da03da926c99d546dec2984b4dc329" . + "2ab32e2537f4b24b19c7648d7dcc23f48605b9c0adfe75687c15cee13d18259f" . + "b7af9f20eb7c614dd834794ab5f35743d26003b6fea4547739181b5a642f685a" . + "8da0a128fb6d708a2b85ab00aaeba217831af24358e4549b1bb5183f8b7c1227" . + "bd28fa3bb0af1f9f289f29317d070c3ec767741b37bb9016e0be22371778e8a3" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "c087133a195a960b6bf88b774ecbdf02ece79bbc23c8811b89fc0c1baba7e2a0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "59eb495ab48b0a2ffa5b860f75de0ae5653f8139fe8d4e330015d29a6201366e" . + "c2d94bdb5a3786bf6390ae5a719fc85aa6cdbe98969f0840d3f6a94757f5179a" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + "c91117cc447e8ade7406e6dac0840e60fab7d5f61066d0c956288c1216e6e8b3" . + "59eb495ab48b0a2ffa5b860f75de0ae5653f8139fe8d4e330015d29a6201366e" . + "72613acf4541ad04ef8d42fce3fe26a05ae01418453d153cb3b80bf6af92f44a" . + "9f18f191a5114f56f107f8c2d32bff7f59d71c34253e98f6b6cfbc94722de6cb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ecbe783cd45c14d3360a6fcc60ea56480d0704c2cd634b4d4a3f8ce99800a7d0" . + "7517bb63fe05ad023246e436a8487fdaa7f53f1545bb85f3f0f4745c85ebdceb" . + "f24ce0c7935a8c7e4daf2bb04447a1c88309bd48037c97c8bc66bda277bd52f0" . + "d78fd592b26f184950822c7464cb83903d708ef88245667b048876a24c2a2218" . + "4bd58fa636498f9f11ce0eb1d147c44d1d261faeba45faea885858ef57f18c28" . + "a1367f4f1fd6a637bbc5fb59e03545c213edd18e1328c85a4bead85999ce45ef" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "716191ae382843609c13a32c56105ca863f6c193f6058e1a398c02fc18fc16f9" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "3b09b38702d3567259efa50330fc606979620a95a9be9477c7f14576d0d4e026" . + "4f4c394743e136320a68185b7521e23f2280155553a60ddf2399825d34747347" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "3b09b38702d3567259efa50330fc606979620a95a9be9477c7f14576d0d4e026" . + "baa31249bf3b14b4d2673c9c939c1583abe162566c99edbb327a074fadc05206" . + "4050fcb9dc5fa91d771dd3073ca043f76997e5b42618c09d5d932c9ffbc1fbdd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "971c1d0d05e93d42ced9e538008dec6a0ecf77d370efb357dfa3975f024bfde4" . + "971c1d0d05e93d42ced9e538008dec6a0ecf77d370efb357dfa3975f024bfde4" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "6ed0d45f7227e01452fcbaabadc317e73134670e42c741024107a491aa00a5d9" . + "b27b7297537d245df7e088fce27d9df4d293b3c6f5fef5b5a0550d0c555bcd9c" . + . + "64b8a40016ce3088e345895fb87c080b9bdbb5f0e8f297eb70c08f8e7532ce45" . + "cbd91e22af1cb3316cfd91c16f91a089dff4ceb375ce10c5c48dcb59c93422b3" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + "bdc94e1a2def8524561974911c59888ee6eab19279d197d8efa3f9f5a018d957" . + "8e086a0b7a351bbfbf12e4f81445343543b71823575ad36b568c1e680f8b27c8" . + "c52bf65af3d1f64691d7a59e5d81cb25c75b9319ea918791e2a8f59c449f9880" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5d8f8428cbb8ff955f7b6b62322e1e0c59b0a39e07744690ec6c3c8d33b7b077" . + "5d8f8428cbb8ff955f7b6b62322e1e0c59b0a39e07744690ec6c3c8d33b7b077" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "76dd0cd1ca300d8fc617ee1edfdaa29b6e582766b5fe630e0d18b28ec0006f0a" . + "ebbf5341bfb166fb7acd3482f20a2fdb3799c68179de2075df43e2d66b43fede" . + "54c93e5f67920242e23163cc6b13b7100bacbfcb1d9b7de56cbf5775d4ff9a5d" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "1080cf6edd2ed8c0a1a5c1a8a05aa818dc27e58d6740c1622a67c0e4e4833821" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "d9dfd94ed3965c47899f501cbdb5fa4f1d9dd40d861c1424c609c40297cd27ef" . + "fa7556eb5b584c7e45a2a815f83fba2c32a094ad853d4b73373392b9334599da" . + "4a844a2257c9ac26139e641ea17b3bebf2feb3f49ee77a5e092715629a4de1df" . + "12e45a55704212fc4868f9277895fa119ff7d60e8718a45d18074d3604ac9244" . + . + "97c1b00a76102e916ff3c9759619047a05f637bca4f7154ee8276fdf87972507" . + "3deb5b241ac3a23bd555c2759882cf42a6f0ef7e7733ddcf5f6398728ef21358" . + "adc640e60b333d86e42efb69a184c873d39717b010a0e6fc1351e0df0c24dd01" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1a3cb4100b4e08297d83ea888ce2a76bdeb02cae123f79b738ad97ef4ced0491" . + "a19e9f901a0818a1f49a35638ba0ad6a34c574d348ccab4aaad63e7dd63c4ad3" . + "914beae475e561fdb7ab3c395279679ccd68a57ef1f21f18efd498538ddd9246" . + "22f7aa86c35d86d0be74c1a9f666806ed7fbf528f7314b6d921c9630e2b520fa" . + "515ba65a45cd946ef69ccc774a513ef13fbbc302c4bddc111ce1774badeee898" . + "ce4008ad74fa965099775f83ddabc5f5978632bc2283ea702d42e295249e46d5" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "0c72d7c20b7575cb564215274fbd3e5887158e32aaff6269634d9e5c25353143" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "ba286827b5b3a28f856e57686673db58b94138414644917da7c0cbf6e2e670c1" . + "0244bcb1436487357e5b418b23a2a75b548ac8748d58c155ef9c64466176c335" . + "f388ade5c80205d90d1109cc8d897fd16a13b74b0cd992ed47313c4091620035" . + "22d3ddcf65b90ee58344074ee3af7e26b794df122ee6ca5a5d193a839a28e038" . + "7d536fdab0acafc4b1938ce20769d3f925666d94617d6dfef6ad833f7bf9f754" . + "d170e6ff6420e4df934497b873a74f1bfb20ef3fda92ed7351a5fb4f224f7798" . + "28f7c5ac47414516678ff2012b03ce699207f8b0709cced870bf683ca7752598" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e51ffa5dd1a3498c02f887779ea209afaddd024dfe41f413af92a1bc6899599c" . + "b1e14317a6391ef28ce7f60edfeaab62dfcfc17b7da3239b8ca10757d818d825" . + "9aea0dba72e7cf28c02bded3223814ae646c7d03c515946a37f6fcc8ce2ab686" . + "221292f7f916b23e1e03a9808d9583bd86520b5c74f83d92ae0d37a6a991de02" . + "506256968f0a0ac3e98c3022f2123d61b77b2f7b6d90b707dd516f7f00ce6dc3" . + "8335eef8d309d094625b0fa69fe1af84327de179d5023122e9ffc32ed52025de" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "7815134999e0d72791d283494f12b5d86298cc28a57a01b73629178a8d02c56e" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "7609beb7c2730d61d30a4e7eb16ac6fabdc16a6da5a72877dbd8051ea952ec92" . + "9bc45150d4fae55da9b0d70f03cfa298440ce8998209b11ba64186b5215c93d5" . + "3aa432cc19fada9c5c25c2b6a17541074effc542da63fdd4f05ac56f69f6ef9a" . + "03102e7a1b076b34dfc4ba35675e0c59a8ed373298a4e27220d51f14dd431889" . + "bc8594f41d5518932bd3439d519112b53215dc302d99eda8ceaa98275b1a1aae" . + "d93cef2324ca5e39184ed582dcda00001f7391b98f4d0c5a2f9ac11e4c75675e" . + "e95a74faebda2379a1723e30e7d80d7ea2e953a46853febcddbf13372fb63398" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "140afe16f2277f57f022e39f058bf47ca22e151969f19a3a743c1d2c578738ff" . + "f5eb415f5f2757fb6edb67abb7072a0b337a827db182df92043297f50cc1f1a9" . + "6ba11ec951f4b399b7660683d6e1726399f2e0051b3b22ff2107304147cdebd3" . + "d707a26e6ab572c45d5209be34627de3cf3def3815bc749a6abcce110bfa23ad" . + "3991b60df3ebcb6d1f921883d656a3df966b8dd4e38d3b3b718293bdc99bbe07" . + "eb6546aebdbe06e6c58a047ce80470a339661eb3f845c11eb26635ed79e4fc0e" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "1e85423fde266ad9865eef60a41df4abf6a4f2987cc5c290110c7f6be5b4721f" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "c97d9dc5740a7353a193fcbbad0d7078d68956094dcff4dfa6e9fb5f9954a120" . + "db7e66611ba00237d6592f5a1a9e32876611b7ae58f471e27edc4cca6fc1e1aa" . + "928de5e15c88b01a90d9adbfc4bf51014c49bc48c5a718d52ef29effeabb5c3b" . + "fb9519e6074d5d27fd529e11a778bf22fc117dc780f207b18b25bd04d1e21f3d" . + "c97d9dc5740a7353a193fcbbad0d7078d68956094dcff4dfa6e9fb5f9954a120" . + "9987f51aba584f81c349d0a84da0c13d4f5ea7c5dd6c87d67dd7605d69db9164" . + "62a053567aa960969b94765a6f024aad8e3f9199e465997e0cb41a5abf94b0c0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d0af02d22935a452a05c1be9d12a04938d94f6cca6c08ec926c640487ab7a6e9" . + "d0af02d22935a452a05c1be9d12a04938d94f6cca6c08ec926c640487ab7a6e9" . + "d88408decad29a4b1d3c2d68ed95c11e9f3c6b12b1c3532f14bbbff69db7784d" . + "d13c2ae2b183a192c7258d01312ecf360d3f083e0e927366909203d1d3554f51" . + "15060c21f8e0aed9a9645943d89aa5787b5ff4d6f7028f4f3beaa27b9e7466dc" . + "4390e179dbbbeb3162c4f75a34fbb99aa27ec37143c34778c0aae6805107c89a" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "12c6cd953c7213abd117a6e98bb5bbc315365acf1647f7c81b342887a7af30a9" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "4384908356dd47f151db32b9beefc57a2d2767ae8b60556afabbcf416bb8526c" . + "a83059d5eca162e4aed394a9ad5eb9e2b6df4e751e5da744ef6c68fc1d480b03" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "be7f6dc27352cee8bf0460de0c86183f236e116b7000b67559bff8e5ccb2da9c" . + "b2e428dda652f255822e335204995c586cc3db94f01dee21da2d46af81ad64e5" . + "3ceb971bfb593914c2cc6fea280d4f859be749c28d35edfaeb17f047eb36de2a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f39c0a282a17153aa6fefb3c08d5796857fa0c0b73c7fb7160af689cee53a900" . + "f39c0a282a17153aa6fefb3c08d5796857fa0c0b73c7fb7160af689cee53a900" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "0d6d9d8cf26118c0a85c1052c49be9bc0ccba974adb337c434fce7e0a58b6a08" . + "0f6e144b997b2ab707deed8293496b8e1de797e9d41d91c3f8cb50dbc676aa81" . + "bac2894573690777c993ee84816d890c6e6da2c60fecc062a56028257d64b7a3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "c426fea0e8a3ae248c8d3b75d6c1c49990d215b8fcc5be3b29d283ed40decc6a" . + "2ef47db783a37a39bbee59207cd6c572c7a2b9f5a646f1b37834f7e49604ef9e" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + "c8e2cfb19046a97811e45631c5188038fe390642e219511888ff725b3d5314e6" . + "48ebc1715f5192f3e9449b0be62ce449579e49380eee4217f063c8ee61cf7aef" . + "d50024c11194606c3f4493d89ac59cbc9550bfe57d61d65dd6d6d4e48556e397" . + "fd9abc89b20cba4f7836078ffb81d28d7652493226c7e021b71c931e465adbd0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ac5fd1e5812fca544ba43e064ae30a59e85294feb5a3fad691c9837f058d69c3" . + "e8e31d07a34208aff45a247429a1ab5bdb18735cb85e7adb0dfc8595b988e94e" . + "83420e9fc964e58d8394e3eb990a1ef08a5f683c21526df05bbdf784942a792f" . + "d4d1919568bbdcb7a9331331dd7433268668919cef74ff508af7d14849af9bb1" . + "ae51a08c382e968cf1592769fabe1fe75038d479b7559c19b3b53d05eb26e871" . + "312fe89abe66b4a15dafd4b70eec0878d90ab344925095cd3c283f8358d9c4ca" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de9ebdf450abe61fdf0f950ae9993940568e7fc1427c89b4a6607114e30c569a" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "c7ca27249c660da3feeac2477cf00e24d256f57c8660a051377675e351c733a3" . + "cbef6e9dd59c4926253876045dc38c462f0a2d1db2bcad0796117ead8aeead26" . + "76f48c971f231c7b48b6103f67c1ad1a309e1482d40406b262d26d6cf0d7aafd" . + "3c2c3138ebe4ed7f02a347d8fcc8afcbc14720ca45925b49fcff6616b5f84b83" . + "be97ab447a186f80de3ad90a9b72b39a7c4579cea844ccd84a44cda4ea7dcf46" . + "acc09abb7d8baed5317a17bd78639fcc6ed1d81927197b6d17d0344f064e2a73" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5897bd79f5cd98cb6cefd400089dba746efa64e7d171a2427377535bdca5c33f" . + "5897bd79f5cd98cb6cefd400089dba746efa64e7d171a2427377535bdca5c33f" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "43f9ccb7bd522642cc64a09151d2b424d446cd8f0cf6ce9dc39d439b382c821f" . + "5d98b6a3d20969774cbd255ee49868eb6edbc27795ed8f78e33ce999269c9512" . + "0ffb6e33dfd22c9800b698720bb7f234bf7fc08dcf634978c206810ec5338bef" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "e80131af8fe5855205b22736a52e1bfc3445f59073ec7e18e3f0cc24f3e15812" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "c8d286707d15c2c054666b58e161713cc271a76b2437a96152ae4ab0aec5b7b4" . + "239dc584b58da87b8e771a9bf5d8bdf373bba483006d8e8090aa13114ede4d22" . + "ea86f60ef63a3a8a52fa92109bd46e26c3531593f9fc378d389e981cd84b5528" . + "0a237cd46bc96ae66295bfa912f9bff64b60e92a176f34b50bf384442c5873ce" . + "6fb6f1c3cc52658897af99cffcf8fdfbf7794d586642de4155bd4e0b7c40d28b" . + "8080922c03eae080e88e9a827313791a0c3b451c4f347e3b4bf11ab205c3a1f6" . + "80a8aaa9308052e3beb0473becc1603b9aa7afb7871a6785480cb9d5951344d0" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7175dc2062a5ef22fd8e4412673df193ba9d0799055a7e6a99f86b0bf323a1d" . + "04249f1ab1019fe51337806b7905b89e0cc28fc4103c6ed736a07967aafee187" . + "af6506ae204db5ea48babb2dd3d2138ca8781dea4dda98ecaefeb50b40b07a56" . + "98dae323a6216a9f3067e787fe8cb8c288b31644fe1801847d84ea6f92bc4613" . + "f32e8874d74d4a0f8b19103dfc99ffb469b2f096f2427c9cb52597afbd9ab769" . + "cb584df78c4b5693ff485e14726a30fa22b92b368c091671f06af069d4357dcd" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "fac0e361aeb6231cf59f3d9a967c7ee26b5ea4f5dab80a0513050a706c977638" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "ddaa01130344235656e6973ff0db3f7d837dc651c584094ec131484f4ae401d2" . + "388c84dca846e2edc9248fe67538153df5342f43b7b339aa883c2cd1ceb16508" . + "73db25f8182b6928d00f0b1fac882c8d4bb3c81e35afb4c751bdd10d264e3043" . + "18a919c3149d059d47d177039a15c13d5c74325e69964e958c20bbe26e8029d3" . + . + "d63ce628c8e7794c900c0c2b1068470c493eb2ab84b353f8bc6f2c16c6153a80" . + "c27ae498915d4712e7ab8078c84fe5bfbaddfcae5336f18ebc1383e4823565d1" . + "edaa91b66d053307b3b6ba29ea10d8aa781158b1a9a383cecd86dc5941335e38" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0f682eeac475d6819148a99781d936d02a06251382e41216482cd643ad27a547" . + "b825a05f925d646361afbd06cdff48175f4aff91e3307342bb619631305ecce8" . + "6812a1a4be8d18be55c2930d6b7e94925d6f319d547b684acb4faf7111b51024" . + "23f34f626d3042585e9465c2fee64d5d645770c3b2a0d7f788434c5acfa43ca6" . + "3e7083673f17ba18eb24e865c81a8939728f6e69e5e95c4b7e453e9b83d0e574" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "44433ba57d318114d3c5e3bf7ed51aef608773b3a140455aab509e756c5e4ae5" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "a3be2c669a13424fef77b6238a6b8faf440c56ea01c5a0e8528cfd31a576775e" . + "bdfd04f2a07c189cfb7994b39ddee207fc6ffd3c7469e41b84be7334abf92dd2" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "fea89c9ee611aa3b349c85f6ef4f1f70c80bed0653c0139516ca8f0930be5da1" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c9de7fa01b1135590e0bc379b3c324fb76d106ddb0350f61fe28989a2d5fe636" . + "e196158c169d0fe63a21da236e10a9c8aa4da1bd7cc7c693faf449908c9cf1c7" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "841abd1c8f65c1d499711f885a5f0276da9fab8571efcfa194811e2c990fcee4" . + "0a615ec11588ffcceea50543cb50d8a6f6a7b2df23a843713d8ca73a210751b4" . + "f527932df74c5284bfc0a6a657ebb5ba9e8a24140d8c8203f47ba4599f3772d9" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "19c297ec7fd065878c8d8bf5647e8823f1eae2a921c36a712115b2b055c5aaa1" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "0296ee500e2b980190d6e0af459bd8b6b6abc168d11a05b4d197fe5d99e7fb85" . + "8790b6d770cae3ae4f7b58f09319a81b2d2372901030de2885428bf6c7a2789c" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + . + "2187d340999a6598e0c0dd29bbe45c6b5cebb0a5c6456106004420d6b6c364a4" . + "5a9b8b177ae66554221c914e907124f068c088cfe6649fe8d2862fa8a23cdb71" . + "b8efe6bb61117913c77afba64453182ee036ebf0ecfacc2d3b6d8934cddb23b5" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "acbda46ba051229128fee69dda699f0f792dbc449c546dac051dc57d62d7b833" . + "ff96deb5b76ef37522a38b16d19b482fcd3692588c43a082f0226ad2352583e3" . + "d7b53784f6689de27411453e96da74be09877e323b1253c090d7a437ac673073" . + "6570740fc4f1bffe24712924214ae8d4d27eaccd9f4a0b6a7b783667cd484ff0" . + "983b91b4515b0ae65aec2a61bad99d5083e7a9f3ab5dcc84d65d51debc03cce9" . + "b977e6cdc05df91f0c81a0865c599586926fd8bcb32609fdc44667fd8e5190f7" . + "2639f9a602168076971d3c0686373bb8fcd68c1757de40b0193c047606c7f027" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "514d46d1d40d0129deb85b5000b19dbf568f6a147ef3ac3f048ec2ad72f24dc7" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "224c2f2a1bbbc1e3695b2d468d52f176355129f2e9628983c7e07242b6196188" . + "fa4de5e7000073f38d136b4d5f0c42ad46b2b0f91f39160f512eac125da30045" . + "c32258116fc5820123fed50bff6cc339d905df30fb9474f7cd5b5abf5f7c604c" . + "d6e418f003c7192b59c28d6dae9ee43216ad0857020e2c2ece7378593972f0be" . + "458fb91997ad41a231eb1dd3fd4dff4d5bc17c5a89d1c9da2c5a09f90de1cdc4" . + "9cc6e9795a0ce8d2ba8c21e522a94582919194bd9b3cb2266b1106ce3f7a72d6" . + "c43efcb5640e4aec86f5470e327e20fb56f4f389199ca750c8e8872909ebfac0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44e5fc518616da6f9c6bead634cb06b916bccf46eaea53429f4fcf358a017403" . + "44e5fc518616da6f9c6bead634cb06b916bccf46eaea53429f4fcf358a017403" . + "0b215f33a4782e72455c0400543392ebf159a708532ccdd5ee1861a481534eb8" . + "5fa5faf505054809a74899c8933bd0665b0a2c870650f16fd926bbbabb72ac6a" . + "f1e0ec01ef640c687a86015ce788aaa5c83c15cd8866219eab776e85065f25a6" . + "46f745c660cbb8c0c0a91f430acf3b47422c58d50dff6bddaa8f201d2ca3931e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "2180accd7b879ba4efa073adcf8374e5346cd63e8e7f35dd3e5a9ca828206620" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "15de77033a9f0b6765524518aa5d24dc2be3700d72455d737268edac8e87d222" . + "fa997ede7d5164543299835f673276ce9df459f85730900d091ca874d7617020" . + "bbaf699987824c322fe65c8d6ed4ca0c3829751beb4df4744843840df92fa76a" . + "64d11543dbe44e34e8721740fb933cca58fe235d8bb4516d0b666d3b38e04b27" . + "9f130b40cae8851aa7f4e9bf0366132442ae78d5793a28a2cac58f807fe4a0a2" . + "752d5eec5581190bb30af169a2844305998c6a43690b7927b2fff115ece58de1" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "025a17bed0e4c08f00e442eaa585b7e7271525a91ba388a549eeed7def5adac3" . + "4faffa20accc6231966c2c4e3759be3f8112a5b56affaa847e9ead776af875ec" . + "7a34f348d0cc19aa303fcf94f5eb31268a6d7919c34e7d8b6dad21c50c3d0fb0" . + "c72f1a3f356afd04c31ad929eb1f438515507c45d3a6124b6127f572853c4a3e" . + "2d04a5154a4da8bdaa67cace3894916d9576daa53a9c12bfd0ae3c8fa0bc4032" . + "0e5d1a2405db3f4d816a6956cd3fd140c307625ad32e0862099c168756a535f4" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "2b734e2df0b78a32468965b877c04f00a7a50e2a76c22c231060a4c44c0f83c8" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "1b123b54eec1e7d9e4ce0310f847b6c99052aa8f50cb7aea7072e163b73bb739" . + "3bf6f50a308ee666a1245f91f287bfa7efd055ad8a1583be42a1c703c10982a9" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "2d0ba9b40836c4041af16c0ab3f31c9eb52333d6d18fcbe4d1ee2638ba7a9a9a" . + "43981a1966c95d8c6d87e6989a3d16cfe8faaeab7168a70db0c73e48f7ec084f" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1eed5677cfe5a33c91d7a6a9105037a1b6635ff5a55de0bcdae147e73a018a3e" . + "1eed5677cfe5a33c91d7a6a9105037a1b6635ff5a55de0bcdae147e73a018a3e" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "9727bd82da9af5d5e6203f5a77fe8c7f0d9d0f756f8d678014366a21d2fe18c8" . + "94aa68e97aeeec614cee06c05d48f94e55fde9ed2d26451b7b561e917fd26b82" . + . + "104267c6f7f9f9cdc02114f1a1092495804c57b146616ba9c50274944b75a006" . + "f75afd1f5016af3aad706414fde28430ca9e24362c2b8968fd966f07ff582788" . + "1e6f94f3cc7d9fdba906791e5f85b605164b3fb9f9ce45c6ae46d37a34902809" . + "ef48532444b498701b765bdf5612b38b96dd3d68d37120762f2d2515dd4ab77c" . + "6265aa4b4d89b92e059ee3d9db62ffb4dd7483c254b38fe9ef61f63bb62a0cd4" . + "12bc4f56458f0adc36fc38d038b01acbebe14041f65efa7c6a38929407988128" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7ceaf7e4baba3ade3c5029369dca0d56571f3ad24f9c7f581c665dbc65fed447" . + "09b7ece918a62c8dfc5e2c3d1e56e98749e17a256cc0aa8455264551edae2752" . + "0077c260e006417be7469c74d2f7474670459e72eb5196be1a14d767e95ec5d6" . + "43d8f12f3e21f7d2077772450a4021a6bfbf2560cfc4a11ec6926d0662c032d4" . + "43f765b99b997710c8411dcdfe4e253ff1dd8783e286d98356dbbd8ac2fbbd53" . + "1fee4cf43a0b34171ab9ce2e512fcfe75f4bd4272ae6bffb519a37e3beebe8d4" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "2de163dacc0d7926eb8b581dd954880a4f5fec617ec1aba5099dec4792186927" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "9c9f14dca231b69efa1bceb53af1976892acb4690d5a4f1999a0f01ff370733a" . + "312f32b014c24b5e6380d00b244f3291e545a569456ca9a14d550a4c364c4fac" . + "278659b6bba5ad7c9d3c7ceb213768f89eeac09ac44565329593f7bc37d857a3" . + "841951424363366698143331a0af0acf3eebab804b9942976436328edc0f0859" . + "d86edb233e49856dc833d963b0da46a28f3ea4f1eda98e48a63dbcdcf214de03" . + "dee077a5797ad7b3e5713b588a483d3cf0ab87cf24f96f85934266980ca6ecb2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "60dad652bc52e703e2423bedfdf5fefbaf66f986cb2856abf285ed99de8e28fd" . + "684c0003787069745921e59360a07b90e62d852c8ed8391d08c7290d595a9a1b" . + "2be0d4965d2c38b62a4d86c364b2b9f87a9e9e842e87a7e8400a80cf21e33cdc" . + "dce79c2d3d05226cabfa3c16e1f8ed9aae4374e1eeae9af4c7d91a64da267e62" . + "31d6b113ca7a0d63724151e5810c14cec98ac12d6d03df13ab3ef03842e45a77" . + "934483357a01e6b742170f1792141dbe47368bd9f423cda50148322a7bf993b5" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "9b1a1cfdabbc08f7f6e73c05e82912a390a26c6af25f0e120f05d1870563308d" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "4ae888285d4461e96006b7064153f71afc539b54aeb40f85fc6efc2879008507" . + "5bade83b5fc2edc2587b2887fe5eff4300cae04c1bb8ac84cdca3ef71eedca68" . + "e03fcdbd1bb0d88259693d516389bb24a16d104f654f7cbea22ba997d3d9def8" . + "caef7f8939854b5f95e2c6519f7b5d857fd853c051ee8e839e115005ca2ec226" . + "4ae0564817c2b954318ff930c6a53a206d01b5b427163ea9d97042d1953c94a7" . + "ee2fc374d0f81325bfbcc16f8a016331e4e8b8d9c81b9d244a4ca37c8f1898db" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6ceb1feae98436ef3442b0a40ac064eb5760dc2e027f852d45d4c15a15e53bfa" . + "5645e773ea758ca5f6499e9e2055235f9dfc78fb4c4211cbf7fccb832497b291" . + "77b9c4da073ea5a969ec15addfb7fe131553c5823e44de973cd9da331a0be31d" . + "d2dbe49f4f4069657ea80022cacbbac0c0e94e2e0eefef9335fc961e15574f7d" . + "f93b6926e897169867259d7d5e83badbf5956afac8990c8d5301612f2569a840" . + "1f47cd734636cb5a967ab0f6421872796465eb42cd8a2caf586f8c3af2047c84" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "bf8ca6bb1b5580470099a8037724445fa65a8f25d9d765c67d2921b151f05d15" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "41cfd211c24c990c971ad3001d71ecc6dc500ad7924660571aea78ef0e0f1106" . + "53862af88960634bba3b83b44d64da5f6770cd0b3871837784c2cb3d5bc99fc8" . + "ed99858befcf857caee6b3a9183a68077c85cff5e0c0ef92737fa7315f142ce4" . + "39cb6341a9782bb577ba867f16889d0a75df361cc4ff3e5c66f43ab6b0abc6e5" . + "a9c511e57b74e66eea4782a32fab335a6d512ec8523cbf05c5c8b6fca42fb8f9" . + "9b1a4b6855147e91106c6a6447845a092db2c5452f8ad7c96d0a955204c7cd63" . + "439753969221dd9dfe8873e0c7893a44426463b2d4b55ba641156169b66f6801" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "139fc00535a83a13088ca5b766447ace612e18bf7d838973ee6cfdbd5fdd2c76" . + "8a3f350bee532f918d851dc55ca61bb0d2ca3e806073841fb1ac7434ebdbd745" . + "011165498eef1440bfd00a0858327871d54b9d3aa087a955a0ee1e3a49260e95" . + "9d476f5610c062622666283b8aabd749ebe1b7d7d6c6cb174bf2a0915c56417c" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b851cc90d8b1f5ac226de040184b02433d8dc0a09d14e37d2f8cd361ae142f20" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "b62c0edc7e0d9a4ddf7eb155adc7e3f17187262a51a242aceb6c1be1d87a48cd" . + "889e1af51dd7860152e6ae30df181fc1e7544105a3fe353dbbfd076da8849d0b" . + "a99fbf614ee9ae3f84814d6255ba4da3c327acee31cdbe64ae3626fe16f1623d" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + . + . + "d4324c9bf8e0905078f18e20b431eb66f4f251ab495aad48970a0bc315555fdf" . + "6c51e5625fe36ac8b1638e105f61902f8ca2b1793ab98a06eb57dffc4b33e239" . + "24170f5927c8fd937fd786101c75448b1c18bb7c42bcac54017a170bef97b138" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "09792631029a6275212a0a0d73c8d70c13699724227512525c9c84faa4cec7b8" . + "1721664760fff8571cd1bcdde4d33bfa13c7f42e8e8f404e42d2064ac5a0829b" . + "f8bd588429c06ae7e0bc33a0a6013b03a13ef72a49662056c5f98fa4370200ae" . + "9be1a762cd055c0e917b3260fee4bf5847927de259220ec45c4b4d6186440610" . + "6d648a69a992b7c055d00729542e75128d8e027e6271c5da0c449376b17d06b6" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "846ee723fc21567329ff65648908b853fc66d96ed18234ea64a11d372bae8a18" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "9b7a2c146bb932553849e0c8967add272463fc75b4cb6f392610991824f8176d" . + "720af37c1ef811ee5c2081d4bd6f283ff476f07259c079a12e5601b0fca45b2a" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "4f7b234bb842369fa39f19161e812277e247f2d4561c89e149f84ee79e608e6b" . + "ac9b7b7a3cee306ec41ed4551814ab34941aa5caddd82d7f3209a36174b74c78" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee1e061240d79720984d88bb1f38440c3f3fc8e442394bf9e02d6fa9cfcab913" . + "ee1e061240d79720984d88bb1f38440c3f3fc8e442394bf9e02d6fa9cfcab913" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "b7581ad263d1afae247e80877c1a55d7a1ccc0db7e8a888efab55e68652a1b15" . + "ca0cef9747e8c6a3c53415a34252670795d4fd295b2ec22bf997076eeae153dc" . + . + "62a5fc4a356407a51976532bcd205ba4ec467b0104f97949d74299be81e40eb1" . + "a8fc50a8a3f11d4c5413f4b3a25008c1f2d1d77c7d40ff4e49e8f4f95fc074a6" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "ea3a327da37f62c16f0a89996bd3415a037a80b75f67a332b31056b5215178ba" . + "2aeb687d6150d99d14ac9eb8e5e44eee4587f5325bd8733bf753a57ae3bf49b1" . + "d6cb4faab950b70377acae52e91530bc8cf0bdc4cb993edc2cae0e3dcae28121" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6e92cbfd0c37fe999e46f89c5b30e6d443acaa8756580612ce6c691f48b278a6" . + "6e92cbfd0c37fe999e46f89c5b30e6d443acaa8756580612ce6c691f48b278a6" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "cdd2b38b9023946bca3e502f70f0e2a7cb764efaf9d586339726f170b6f8391a" . + "d2699ce84e69683ade08fb5b71fe3dbe63c1e36f0089018c60f1351bdf65a494" . + "3c83f83c622568f90520011c11ebc455f925e8c91fbee0cb61509db2a9413e2e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "823fe0f10be3403c6448b1a31b12a3d04e2bbd85a0438082f2d77a1d1b736b02" . + "3fdff11bd99eb5dfae0189409df8a7336e41b32bc297e410e0c72ba17079a924" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "a850c11b6e09e46665efc634bb2570b514fb5c30538838cad467d314e2b9cc71" . + "9b33c04e473062a48c013c71313e8eafb84c1b10eb2ef50b1d298e66ee07b1ce" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bc57b6e83496b4d0035f22322aa356499aa1a1e5ab5cd8bb33a119123cb9621e" . + "bc57b6e83496b4d0035f22322aa356499aa1a1e5ab5cd8bb33a119123cb9621e" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "c6c0c83a46370ddc5c68706fe302c05f7c514593fa9dda350b79e4089c1a3770" . + "ad8402678e3dbe3980a3afe25a673182c0982a97b60ff3fc62a90bc7bb0bd44d" . + . + "552fc586e4431a2b94909fd2648d785dd4d25c4ec59bb7111edc292f33f05fb4" . + "bf922d126895efa0a93a906f35bfbb0d7b6122de3888dedeb125d09ec147d801" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "1814ba5a9c92651c25a770b1b47dcf847300a3ad730d7b15a181c358942bd96e" . + "21507f7f44be6afa8347a966885f313a0aaf7474ab72cf1a074ae6f3e53bcabf" . + "36f5a63b54a9bfeb487d6ee9d8526c6c4820abe3d65014e348c93478970f8239" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "516635915f5cafcf67447bf99b61ec8b5555d5ab4379f9c6ce186c867056ea51" . + "516635915f5cafcf67447bf99b61ec8b5555d5ab4379f9c6ce186c867056ea51" . + "112ebbe930d8923b57cfdd2c649aa194a403ca6db0561c7d4bf69452cc4a4e20" . + "842bff402c659ab7ef3747e2b25f1209a46305126f9940fc6f87a6e20798ab06" . + "e2c725bd102d1dcec042fb9bee5d4e3a5b1161d58b4b16ef0c5c557fcb9a8bb2" . + "75855d9707b21551689d19fd7de3bfc36291a4353e30db37595efad392228130" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "f05ea07f9e1705c440da31f1970eeb3060e36d64940a701f2afbe5fb2be1a0d5" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "3f3a9ef8f3db5a2e250c1e726360d140c36fa2d28daa2067130ea167543073ac" . + "e189a9e42b169b1f6388986b80f567feab5a2a45bf742a8b0d26f02c6f4b25ab" . + "28b9594f0122b844b37896ec9d3cd3d9cfd858fd9485f704489dfed55a4d53ab" . + "821e9d034b3d11db8ba2da877e20de01053529a10757093c2fbc3ccfac4816c2" . + "b0bc2b722cd28e330ec6c83ef4701007617ecf721c3e992da12b6129dcf4f211" . + "f42fc916fca186a07cf4eb3982a64517906ce1f020e0319493c0783c6155355f" . + "99d54c80794bdd2a41b1343d251aec41b9ab2048922e0106515d10f9138a5573" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "16c82dd6c1258b54ec0515894ab02f4554747d6e3356c9c379bc9d7cdf28773d" . + "239521bcdefc3caa38b52981d1e43ea217cebae8c4246876082622764ab3862b" . + "d6c7baf7fe2336e528ccf317b0cc32de3820e3a732849f47a539fced39d1e1b3" . + "0ccc9271e8801d941e24828547a084bc0e36b2d03d60c674a5d47c1526e1d868" . + "8cfbd078d812d7b461d941140b65f2f529967a63e82b6bf51d08c26a5ef63e6b" . + "767d8a7b03b6d36975039980a0a30e70dbb6ace2b2645a39c479f1258dcd61a9" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "61373d17aea1cf1620c989eafd0a94a64ad4d81b09a8c7b4855b298bf19898a5" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "b5b66a975a47b1d337440f813d6025f84c0cb56e06109aa37b13498f3a315067" . + "e66daf7a82b1da29820ca23425ee6af707f38b09cc2aa17b029cd21ce4d696c4" . + "56b341278d8602a6c4173f59160bed66e923d04c68abf2ca41347d52e5618fe9" . + "d6f52605ea40f900227ae805c18f2145bd3e52b19972ec0ce0e8af69c7231adb" . + "7fecf4dba62aaf2fbe888ed0845bca3144cee3a51e7babb9a4278d0e561856a6" . + "5e4ef02bbafc5171f04065cb3b609cbcdb5555852b60b07670889aa601ed42db" . + "32a4b823d3fe2dea290e1df3d4020a69cad8e20e167b2da6ced3c0ea5e8c350c" . + "486dcb1ebade1349a71c73a4f584442909c690d26251f72d0c4089316768d8e5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4073f4b516405e79cbf7e4acbaf161d40248d4ce703a0a3cf919b8ae6dd2c082" . + "6597ec75071760b8edc02f52beba86dbbd60d7fbbc4392ee58342b8e5e4de4ff" . + "2a8f01402587239b8dfbeee1be04159b7b23fb3a802396875095f2cfed4dc221" . + "b99c0a891cec4f5fc55082b62e27bc190e6e7f6710b13a363761dcf652f7bcd7" . + "41f0f16112e28c69fe5922c96c4ff2dfcdbf3c67fbe707f5b4c820c1f71044b3" . + "5061cbd09e6c7788df7470d3a1d589f49a9ec0825e75b4880701fd04d47c48cf" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "dde1fbdd0e5ed459dbdac246744914c59e253a806d3cbb24931e505bec3f974c" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "793961ca4999d83d0d8fd2246ac4f474e3820ea153ad7df328823cc95158668e" . + "66cec7765e2e367e7e799aa10480b9c2858fbc7d3ef1eec89aafb097fb58779f" . + "056a04ee2f7ba67124a0e7070addac176bce3cce7be54a165735fa1dc58b2ef2" . + "962fad6cf1b2c58f2617b784200b07626e7b956d064bf2ce93f349f213d476b5" . + "d8fa4ce94c106bf89d2c1bd3fa6b1fc7846f336f76455949f09d324f285847a6" . + "4041b014578dd3af011557a5c570ed501ee2280c4c590326fc66e22c39666226" . + "a7b23fc78c0b97fe0ec723e737a95f975fa55b102bc26554a29717de9e810e22" . + "1aa6252bae37926536ce56c83104358bc14caf33ff6b20c9bd7b97afefb62f25" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "df9bfe4fe29eab1891ed8a0e6d2c5a284924dbe6316641ab2117dd1296c914a1" . + "21a05a3e13a9864fd95dc10ec5772acf6e82aa1e5087a739f6a38484c40d4b26" . + "6f8f50d5856694d314db6c78512032e750fc9eea1b4ee99ac876f8a8d98d3312" . + "8047b584492854d8faa44a86f52f1eb880a037b536661551e6ef26c476b6aaa3" . + "4a55dc8c6510c1a5e18ed4500e097ffb172ca3b152c17fedef8f1e2f1342c3b1" . + "ad1e2b1ce4351f984b4e288adc7ea211cb8c3f779825fd7b2f0a69a4184869d7" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "6dafa9d1ec9d50491b01c3a45ed6530008d2fdbd83362c93faaf2b228bc6fe08" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "b6bdf391ec1ead4f0206d9ae48789d9f43df04c18f08ed08689cc176aa12b199" . + "47ed7c2a339dfa3d916e0a70fa6e5406b29a5dc4c8543620371e5abd4291e140" . + "ada6624c34cba0bf403eb1f278c516c25b8b098a3ebb25b400b9282852d044ce" . + "52383e3509b81f2fa56969daf84d035170be666b50d1e791ebdd22e89ef24577" . + . + . + . + . + . + . + . + . + . + . + "9511686e09e1e7e8b4f3eb9059c310b8153a04adfbd50125df05ca776f0703fb" . + "34e6b1fb8dd85b8c0798d918962a6cbf2799c558d8a9e689a5843078adce53e6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8ff849d677ee2c683d75c85ba24d547f46ec862219016da1ff07a5ea8b8e2fc4" . + "51340421b835bb0713f473205fcd727c1f9931f181ea9895e674ec83f01f945b" . + "f973c19367506c5aeed49929039674b0aaa0e58d2cceb0190ee8db74c35bc15a" . + "1bb73ef0abb49d86731272358abb2dde935926d4c329b286b413a29cc5bbd753" . + "cb22a8d2f262cfd1a02511e3fbb26b53018322c83232933348535b988a5fc246" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "40438d68d3388a1b7a4162ec9f9979fa3a29fa5f19d044bc0d61d8a48198d646" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "8acd0ff262628089ecdfe02bd734af86686aad20b4ea6cd7293500350c895c49" . + "51e636906ddfdbf340b22c29ec7bf0fea58006589b38987ba56c8ab8fba7f3bb" . + "244ffccbc7103f800a4061b4d0b30c356730560419f6e959307c5ee6c298a2a5" . + "5d119a42419341e7a9a24d5189c13ab3d649183c9a9a8c2df517a0130a4185a9" . + "b13bdfe0db050f83afc25a629692fa15206c606528a409f66eaf91fb8128c7e7" . + "637c87aa3d6e6f69bb2110304b2d02bd988f4396b727ed5b990d3dfaf2d2c329" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "43079c1204b7bc9e9210a9d025567b2452f7e6dc4c44861c57690f9b6f7bd7fc" . + "989942322ce6ad0f1f0fdf49b23ca09a5f854b043b284c6df78236044e2684df" . + "14eb0398e3aca79d37c27b2ce5de3baf54142b1370cd6582b1b741f146048518" . + "e73e53ba27c09ff3ec7b9e2147efe4f6ff34d010ca8b9f43e31e531d6b493e85" . + "61ac325c4682728732be543b775757e650f172e081ee73af308f486bc80f79f7" . + "e14092593778bc249f82d991966a667a3604554fc7cd8c3da65868a0d72e50a7" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "bf0eee8315bf0db05356fc0b5d6f1f08dfcaadd1bd4373fca7654721046df8f6" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "ed7f7c5c719e23876e5e597bde56f914494e89634f6d4f2e69880586b75e528f" . + "dd5420de56d5f13e3533ed56deb7f750d2f2959c9e94070581e655a2e0dc4792" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "72ca580519d446c2fac7f21cfd34ef1d83bb4d6ed0a98ff4d22455a5946e9672" . + "7cc4141903afeb9b50cc5c4771b67c89d4e3921acc82bd17d7065996fe26f320" . + "3009a3c8d997e8d60521c1795f5cc346fc7fa0e3e35f91f9c9d0d49c042976fb" . + "ec98aed34a901a0ec8f725716591554e7042e7176c596a3dc101e7d1b4463886" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7fddf2da947fe0ad570a7d1392879ad11cb3e11b3d5d2616fb3c830dcb8487c" . + "b845afe528a6bf2bb462faaccee7ae60ae63cf8f8a0246505b74c7030238f71b" . + "907d492a532cdab962f52fdf1b10d821858fd017afb5a633ba04e07938371fc8" . + "7168e834164001cd20656ae5f1e12ddaf979c619e946d25ae2dfcbfa6a969a9d" . + "9940df6a906ef58264b59bcdaf1442ef419c72c66069b64b6af40a0c58bf4bdc" . + "6f4bc80c6aece022a0c1aed337d80d46da73ef2a00e7451d31a279b3460f9df2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b6cfe8d081d7969dd4883bd03728ba6ad2e5c6bf5a3741b0f0abccfc8353a5ec" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "2f00014f17bb53500fd7fa675f9f66898df0e62eb62f28142c6de6d65b839b22" . + "9bab2f04466078fcec557f5e7fbd3e534f0555faa0d09268091c602d0572b8f7" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "b3d0b0ccdd4e4352af68d43b5066d00858efec5f5ba4ccae308c7d0f47c5dbbb" . + "1943fa85a8143953e6adbeaa6c69038b6b1b3e9c7358e3cd0e3bbf2bfc83d034" . + "be36b2097db487df49ae0413e7b20affadd4afcfdc19893b402471579dddd362" . + "03515482620338df2d398c6bf29fbd393e2ce010ba295935b59e683ef8ab090a" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "daaefaf0239fc81a4d54712be9ed02d0be3d582c967d6e6aea0ac36825ea328b" . + "daaefaf0239fc81a4d54712be9ed02d0be3d582c967d6e6aea0ac36825ea328b" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "8de13a410d3b268ff036d3bbe2777d0c7a7c5dd1fd938532dc880cf0c152ac29" . + "6fa7457561485a7c896d56549e29232877db1348165424704a949845066d2977" . + . + "c15dcf61a26a5853a4de998b89d84b79221617a546b4d4a84d5067d3e7121ee4" . + "b92da3fdcb3b610b8649e0914ce4783d2e222ada476b5cb2a9c53eb6265ecd1c" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "8656cfe3f168f253655cdae74e50ec7b537a927887cf77a5c49770bfe93b244e" . + "6ae29279336a7565bd33d027c94ab004182954aaece732c892d4d1b494f51b22" . + "234f76d812b8a4505d4b338e12acb832155bc5ef7f54078fa521786eb2c5a084" . + "e83a3e9ab1830fe0116ba1fa7251cd4085a4a5b157261f8726f902c50e65a391" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2999f013f32a590fbea1e4d8b6dad9897824d6396a16c7f164c5f7dc19acef8e" . + "e120d6b5ab4697a4a2c6491576d03c6ccc4fee3e5b9485f1d0d319245e5fc417" . + "e3ac7152a4d58e15de8d215f780aa5d52534948b196c08600cc9140da25a3310" . + "d733576522f97de6af153809e21047966a792751c955c5998f6abd02c33e4c10" . + "71a9eb2ca62abcd2b872d9dfa2a2e95873ca9c1dcc097662a5c1da4cb62181c6" . + "9ffe9530ce5b97b2c4c47ac0ecf7381b6458421d5209ad7fe42229df8115acc9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "17b69e2b8d8055a6703c8de35ae9fc8276640ded7f987172c0b797eaf1175daa" . + "4a960c5d52d4e9d70a14dc6c3d057ec5802ed162c41457efc4036c7648e27a99" . + "b35a9a20f133a4aeb0717fcfb3dac944e5da5429e5a23f3d8bbb267f474319d4" . + "5d19f13cf17ee38d2342de7d70e0c36a69a2a91c776e4cd85e29bfea9d50bbec" . + "34eb673b4f60b060120f0cd382eb9a102084ca3d46b77fa2ff83fab987905cfb" . + "3d72f88e304cf9d58b04072c12e09ee43d152a7b8d06b06398df744154861861" . + "5f33e42a4e6bf2743bea4f758ed28e7a37f6001eb603bda92a02da4c84b7f19d" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7ab2d84ad8bd39841b5552086a3cff6912ffbe211082b43fd074f4c225337f91" . + "62f3d70872a7de603c02007a28cf95a7fe2782f1e8b3c4634931a697046b633d" . + "c623c91f26f0612ae585f0f95401fa150e848d8911163dfebcfc29e135cc3d3a" . + "057659a42648d48ef2b9bf0964ed463b4775b1fff7b57f5ef4efc117e346ccd1" . + "f7f9795a38b9919dc57bd89cf96221bf93cc037b3b34520b02702608fd544e71" . + "2c735a079aa2311ec9c438d3718d40fb031d85535f845061ede6aac52050f76e" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "6ff1da4f8538bfa0fd7f0ab1cb30ce4a0f1e7fffc6ab1b2dc41f41d08400c498" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "a16c7b020d25b27efa041838654ac52334e2902b7cf4a7e890dfdd07701c2ff4" . + "8667b483892f901286bfe878c793987b4009eb357c4e6d7f86d7de35af738bdb" . + "ab9657b7d74ea3cd31894ce5eb651eb8e20073b1a1b1c9dc77f3c233bde70264" . + "0920411430d5b357c5b32156d7b805b42f66351bf326f15dcc49d3487dd0354a" . + "a16c7b020d25b27efa041838654ac52334e2902b7cf4a7e890dfdd07701c2ff4" . + "1903bd9e4cd3e5bd330fdcc7a4fc0865b3cbbf05956f87b3673447ecc445203a" . + "91a44e20e7f4605b8c4ac19bb12ba76f454f4318cd81db6e356baef480bca1c8" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "e85ed9a9b8e025c151b88d6439bf6b4d7ef026e06a280b0b251d71068a0d1f68" . + "fe77d2fdde0d016c8ff3582ca2b0ab6d232f35faf4bc038fb6da8119c6abc30c" . + "6f2206c9c0455da64e480d2a551f35770f5455b0286bfdc6d5ec9b78df69f8bc" . + "66b9c3aa9f95c63b9042b9687b4939e82f5455d4b261736f3d004c401dde353a" . + "de40fa67c74ce2ea250bf3e16a840058dc48a618c391f3ec0c1512f56ed2cde5" . + "5816a56a0f9c6dc240b465f449f8e226cafdfdc637930e3e153a8d6b3afea01b" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "d9837232cb4cae019480478485d2bc52b727f343b3720db48238c3ae17892f2d" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "83588e290f44b372a92cf64282c838810f97a171727709c9243475cf93e489e1" . + "fdb093a2770b9bbe573db621a0743802ba2f938ce5d76096c942c9292f849242" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "3651e5b49871afd5a1112023faeb31584ae983313887ab5656742c60a845c133" . + "da5827faa0937965e0ed4857a8a7187fee527b498740d20cf7bf4b73b54c0809" . + "6424cb0f66151d84bb905c285cd84d96aae08091425fe0a75240d6a9b88e83a7" . + "5ead61d3151c67832cc310bd19ba3a22a7a8c74f2f66dfef5d6a7956c9413d72" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21f3dbff01908644badbe93cbe55afd21445773c981a90ae1b858b1e6d0b76e5" . + "21f3dbff01908644badbe93cbe55afd21445773c981a90ae1b858b1e6d0b76e5" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "0103110998ba188bafcfc65a7d7bc4a8ac0c8975283535e0a0dc43d66a18616b" . + "166798c018632475c339ccd0ff9c23c5b0d05ac5f21c34895621a31a79098269" . + "fe88ad647a29424093adf97918f612e4f878d693bba60c30848845d09c57c360" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "37c7c311ca17dcafbaf85d5ed7f4193fa926b173e35039f779aea0ce49204433" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "73d1e1faee7be10ccd0424daaf67eb166124daceddfcd71a170c3cc5677da8d6" . + "6d6e829fee707879a85b8202d632e4ac5be73787ff5b7ffe8c3f4caf3834938e" . + "a60be5d0ec629f2a85f9b61b0a6851f07258b6f742c878f7ab7efcb2350dd12a" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "8139e4edff9d2d79268c8c98e876dc505efcd12251897b732693e74d68c40b65" . + "4987ed8d6426a736337bfd1a162bc516e9850bb48b71e232b0611696353dc6d3" . + "757d7e0a1c04ef7b04e9b9d75da90a130fab271301a71dcf470040e5b731f262" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fbb174941e9e04e1178243f8d32261bdcf4e5303703f92e2476918d1f76ba8c6" . + "2fba13930f6b8a2840accdbd442be2d4b20caa8c0bdac21765d7bea40e33a70c" . + "e03fcdbd1bb0d88259693d516389bb24a16d104f654f7cbea22ba997d3d9def8" . + "8cb4e9670d514ee9fcd0df0ae482e7e0936062db840a51bd1168fc74fa4f7446" . + "cb2af22f0953d0420803d2631b47e4582cee6fbac43e0e602ad1137c3ee56985" . + "e4207c29cece3dd9c9f2c3f686a162256e0d72ed9a7ebf8502a9de6ee0bf821d" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "e3bfedacc95354e9c25485252a4042156e13c4012a95b8ced388b10c176b9ed9" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "4b88b81e32c9e2cd2db69819bd6a9aa8142443342e41162d6e715add52c4fefe" . + "c1068b203958dcc5923f3751fc0896b5d96aca4a3ad69cf397e6359d341eee69" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "f37f763959548f87b52d9ef3d98eacf18eaafcf23779e205f0e2bc982cd42617" . + "c4776a3bc5eeefe8bf1958810203106b3e43d253e5dc19984b03a793e253baf8" . + "0344eba644a44c2229b526cccf210dd38da77221db2a7610135c2be75b6069c8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad6873c9ae309bb835d2e8b4bd53566a3fcc04dc35f10d86c491a637b4e3008b" . + "ad6873c9ae309bb835d2e8b4bd53566a3fcc04dc35f10d86c491a637b4e3008b" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "f9d7cb3a1ebbfc3e6cd7d8484c509b30ba03d2b329eed30de2c6fec179b17ee9" . + "5b29aa4b80547170065f7f31e71f1f3e44b2f5bb7c9eed926373e5476d50dd7b" . + "9b208076e6d50bfbb1fff1c2b1361bdba89eed7fe5bb6bc128f438ab1a5e7245" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "3573df399e5cbf7b87bdeccaf12bdcb2c933656be91c76bf4dedcdfe76c0db19" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "99f7bfa9fa356a3772dfce515a9c4081317fbf44353feae02361b9991a8b770e" . + "c623766adc9e5d6793dd04d3448a84da7891d78811efcddfde15df8b6c7deb95" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "815e1153981d38e21bda5a426a16f95b14a51b32433b9b27606aecaffd7aa23e" . + "08e6837862ad39866de7c32e32fc1229690db4d15ff57b10239d84d8aeba7900" . + "0a93011c5aa9da1a5bd7216d940fe6a804cc08c0b1b6c5bc14b4091631436f8b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "41e9ff69f6b0544cdab0b4120433654de9e25d0d7dc8f466adb9a84f5b911d4a" . + "41e9ff69f6b0544cdab0b4120433654de9e25d0d7dc8f466adb9a84f5b911d4a" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "f4b9a997a981082e239dcf5bf4127d6e208854be525173e30f98442f20e84cc8" . + "937e2ab7e659878c14fdb1fc772c74cecc3d0da2c7657622853257757f311d55" . + "08cffb3e0570823552104b1f190c9e16b0fc93901b9a86b48b69be1fdc61a346" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "1c6490d3f5a6b4f8720137de9d0c89be3914f2898bd646ab60800bcff375e5bc" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "7f20167ec64c42eccdc931a66b9ab0905a962cc741b7a5cb77d61506f95d8ad7" . + "25ea7de80bf14613a1a4e50f4a1a297ce1bd0e1d2517b986486ad025a94c8b96" . + "bde387396220fc3da3b4f682e92f62253d6a405611d4d4c20097eb067af9d7f8" . + "a97d72ae42b9a9a959866a5988cde1bc414a84505465f589c143b0254467d9fd" . + "7f20167ec64c42eccdc931a66b9ab0905a962cc741b7a5cb77d61506f95d8ad7" . + "9f8be4714a618c7bede2b9232bbba5147e306c5870f59627fd2126e0dcb260cc" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5cd5ec79eb1bc0e4e1e5b091d0fa358f643d002e451a25ff5761c07a369bf148" . + "5cd5ec79eb1bc0e4e1e5b091d0fa358f643d002e451a25ff5761c07a369bf148" . + "1aa45dc0ecd3638bb726f207ce2ddb5238c5711cfb53f611d2faa752fe95f16d" . + "24dc56686b72592ce5358d8fa196a1f9ddb89db8b3586dd4f02bb4cf71b375b6" . + "55520bf1e149f69dd4209a47d52b8ff8762f8e1498052b92fbe044be7a53dfcb" . + "bc83732e1361c81704f38d45064adecd221b253169cb124cec36c254261c1161" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "29a1b4e7da6aa4fc7d3bc60924f606b15d09ddde5fa848cd8cfd16bd57aead94" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "998ad46822f7985328ac9be742c941b36f5a7aea0604395e3250ef8b5d498892" . + "4f8c77eda71409f7b4811b413d553b751c9c70fc5b99bd478f17c6d36301b6bb" . + "a8d22cf2e10206f36596f5bcb90f959e4ebcaad9c8fb8d820175a0dba57d68cb" . + "0249fbb7f0fa91e66a9fbca876f0f81a69db2054ed0287759fff3be912f1d64d" . + "608184355a93712e21726c5e434c4d65f12343299a4e2fc6e3c33df763497ef9" . + "393d5fddba70e636f3482856e4e2f52e57c539abc07c56b2f823eb64dac2940d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65838f653958c9d8e2debb29c63cb16b6f3390dcd949b2f45698869820a4fd61" . + "65838f653958c9d8e2debb29c63cb16b6f3390dcd949b2f45698869820a4fd61" . + "7bae3ab544b5113a4b0839e3abf6d4347d4b21dda782d78944160f913577e461" . + "b695bb23c40161e20803885b0b7cd25ed6d4606f7f8835731b49365c956f9400" . + "e9437db7589a2bdf4ed6b27358467892551a833f94a2fd45a9d4aaf7fcd1cda5" . + "8df66190c4252dbc8d77f81bb42d7762c5f7660c1c78ef294b12ba3f20c157f5" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "7f0d0a4ad8bf76f8c8a2df696d50848610c938c71d0ca820215fa31568867999" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "61703f97634ba44eb95ea0edb289f03a2cd81c5179a780caff19861a28486d70" . + "27061fa0e2c58ed30c78699249afd64e774d2eaf3c853d1a4a29a1046ec83110" . + "93863dd15860de1c31b34e239aa901bcd5d210d037ac6368289f534dc313bce6" . + "01508bcc115c0da28d7316f34cbd0d95aced0a378854467250aa32935ab7c14c" . + "61703f97634ba44eb95ea0edb289f03a2cd81c5179a780caff19861a28486d70" . + "59e81e3d4b7ae9d9a1545f00081b3d11360779f5f044e51a2fc67a91986837b6" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a409fa8191afa64da149e926e79c4fcbf6b3356c5ab299db435c8dd56a3696de" . + "a409fa8191afa64da149e926e79c4fcbf6b3356c5ab299db435c8dd56a3696de" . + "b98c4ebe8b3a93764ba21877f7e8d784808dfeb6064914600d3f6090a1616bde" . + "09ed5977ca496ee148c23014bb422e493c93ab1d81acccadc9d712dc6fa43162" . + "5342055931283f09d2c6a9fac5ec14b71e44ca4d8214ae45f8288237a979dda7" . + "e148f8f3adb7e7fef035d779d50a945efc3156dab474cbaf90c386fd5ba38e76" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "2cc1f4ea829aab631065b14d77e8f0ed5604aa43fff078781e096a65c8d3d5da" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "2ce4a408a1a19cc8b56b4cee6f0ac95b4e7cc91d7d539c3fe1a56f71ae523bf7" . + "d71e033a494475b9184519e462acae19b1e8b8bae07cda469b86c4ebd56f6d55" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "e5c2e788d6aa1289b8f2f9cf38b912c486054161c779f4ae187d84b90f8315be" . + "07f1dadcfe88bd1faba3ddaf580b3186068fc6f9fdb75266803d29f486174d75" . + "e13f53168afa276532ad89c9f4e897e657871678b0deb4e543571ede4b8cdae4" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "75967aadc9e2142b0cff517d4bb697a7530e0ce7e188fa5ca04d9d365515d429" . + "75967aadc9e2142b0cff517d4bb697a7530e0ce7e188fa5ca04d9d365515d429" . + "0573769400c68eb6f1b816e8dc76e3173b58e7549f26a5511b4b5fa10f95b65b" . + "42c5b9f4746323182515631b09b43b2e6cc87a0f406bf1dd1f8c2ca63df2cde3" . + "42be482201939ca29c4508846493a14cf6784ca5aab950690193562b2f394131" . + "2f960005c53462cd27ddc5acde222444079187bc255fac299f9c18b45972485d" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "107f04bf59b18a824474ccf50377ed3ddc40532dfe7c34e4bc3509642ce21cea" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "2dbbb1b2c5e827b4f2b1ea566fa90f2da8db9f011d5832bcc02273c43514736e" . + "1182d9d1e35d1bafaf1bab50c365f1f80d96d883bfd9b828366fabae59a0c57d" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "fc0d72ee21d1e4764d445b3de4ae88e0d9a66b09e65379a597e5021842af68c9" . + "f3ee2cc026b6f8cbacbfee371be504c79ae718fbb17a00eb9f5d406b4c336d96" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4260e304eca71c15f39e44142238cffb2d08b020b1a99e31fb91500f43b1557e" . + "4260e304eca71c15f39e44142238cffb2d08b020b1a99e31fb91500f43b1557e" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + "d2bb2b991fa70abc39ea9acbb47d9aadee1044ccfa516f62f4171ec779da60e3" . + "e87076c5a36cd4819af05cbd33ce77988a06bdaed8b84c83cf175cb2643033a0" . + "3fcaf3acaa6f79392bedf58f57497e0cb8e90185be9aeea0297d81861b6c58c2" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b851cc90d8b1f5ac226de040184b02433d8dc0a09d14e37d2f8cd361ae142f20" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "0868d868f62a8ac3217890e1ff381e20050baf5b17a17dd5a526fbd4b824a22f" . + "95cfca038f5e81b46843b613be77fd12a14f8f5458aaf5ffa4b82602168a18cc" . + "3e594cd0d4d63ac7175993cdf944cc4229d6a8aec7658516537afb3c9f87eb0f" . + "3acfbd27bf64b8e63919d011507403ba22550cf1306f4e59a9f71e1c0441f8b6" . + . + . + "81cdde3fed79b246be7b56a228d8d64bea5e1ab5f7e49fbe52e0f274411cbfec" . + "b987c2803442426ab5cdaed038a03bf445e6200e78b9e1491ade690334ce5a33" . + "80d3bf8aaf84cc7636d02ac1aa8ad46f9b0bc9ad99b932012bee1d71d7fefeed" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7036941c9e813a665e6809fcfb29ceb13ad3ce7d172da6a4de817e8095d9bb52" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + "ab0a8d77fafa7146eb5cb694454fd4e73782255542fed925142ac5575e0f1372" . + "bdd2c0ae105799bffac2aff65c3e0cd9af59b99e916dc53a2af2b7ceeb85f5c7" . + "ecde474be05a27611bb2547d2bc2a2de3ebb1ad354252c166b58f7315a3ef9ff" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "0c799ff8a2df4aee56c97029d2180320c4de67b99b753229241b221760c728ba" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "ef7d122bc4953b97430f353cda60d1198180c8343c853a4f14ba47da406526c1" . + "74a3c4eaf49ef3f057662f812ad489281c88f65c8450a68db2a84f6a148fd724" . + "b2cdf69e9019dc28045b091335962de150dbaea6917e57470f6a439b3469269f" . + "a901f34271a8af2533c0b98a090e527c0adf887645f9c6cffaabb6716f80220e" . + . + "28b0db3978f8cd3c7a6f40688a71442eed46497ffb64464da5d14e19e276fb74" . + "e8075b4586c96dea6e2c843946461a531548e2c8bfff79568be697a21bbad1a9" . + "597317a5c62f22c77e433d0072028a1d40ecbc9a69a1c985821e16cdc73b9307" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aa0ea67eab10dbfffbd1faf26f63a598bef712749316c9a84b9a703bec249a0f" . + "84db50f84ebe2a90b875276a8b9caf650c4b5a8b175b6695f36e4bf844c37d02" . + "7cf890985926e39337120be0a2110fe116e5dc2f2514b6af62cb25c6c9012665" . + "1eceb50c71f22bd07c5029f281083acc52c10d03c99ffeb0fcf9b90ce5b587db" . + "81a22f1ccc890eb51285958db9bdc56e5c5dc17f0cfe87b390e70a1baa4c58f7" . + "4f7de041cafc1dcdabda359742d13abebdd8f5b75ca85361ab7b2abe2189c9cd" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "bb61a602dff3fa4feaa13baa409bc3a0d3fc3976bf3780b1760a28c96bd30474" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "2dbf7a005b73a1553dbbbd1f71a2f5154067b9a378eb6fc5cf8c2243772c6363" . + "d9b441f06fb2178fea79a294c3b5073be8b17950fbdd0cc0498060bd3702edf8" . + "24bb2c7f06c9760496afdf12e7e25fa7ae8ed18b108775cd9ec79f0fda5ca6c2" . + "708d462acd45b8c45a147ebd9a99cb404ac4c8e5be064d97d16bc620ca8e3418" . + "4e81691c593245fbfd57d1c9ffcaeb0c94ddd6d18455013b72f36d22c6eb5d74" . + "a7f18f921fb5269e54d8761c5ae20fb57805e40fce741e1ca84dfd68ba0653a1" . + "17362aac4e7c49c2a4ae46dfff82f4af721a34c9eb2837bfb02b9bf09dda468d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f3afe6d40b4aae7045f0c9ca428cddb2f8a1c60bc0b8222e1e91454e972daee9" . + "03dd95e0c7efa34c6fc3850c9c8020bf784603b268f8c79d244104a92053cd56" . + "520bc165a3086723094ab37f35953962a609b4ef3fe38ac4d38622ff48834366" . + "36277ad906b8833a5e67d907c9966cc5f686ef92af7ae5c2e392dfb658d7148d" . + "626ce317c34488b57906a3a0354f363be28bece248453695da350bf2d29acc63" . + "2f67a7d8f363d087df0b370140acb83f19186ef71c4a169c15fce3bba520f291" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "5c4b0e2f9ffb2274842b1b8ef559870581357f0f16c446f5615e0657437291be" . + "fcf82a3a15aa29180f4a156019617e1dd8f02c30d5bc504e60755d53449fbc9f" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "af23239920ab81606b813dd6a7023a6ed2d0e8fda17b8042abcacc4ae2cf841b" . + "7b9e195ce2cf60526a183f0810fc6b05c78fd7274d90fe926b9c155f22866ea4" . + "45a00693f2b2eef4cc04a2542d46aa316c0260b8d36358115ce14ccd470d06e1" . + "c129816f941689715a725cb82caa4b650a55fc6fa3d76b01012d62141c1d1f44" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7067dd5472fd8a580a899af712d22037c5d48460cd3b23343e84828f2645bba" . + "1c3a25d4b384a1ea2b84ddba988fca85eaa11ce0ff59bdf7ce2e814f5f85d14d" . + "c306a383f0883b60f603b3b2cf318ddb02d90266a701ffcd3f90e471c0434c8b" . + "3c33ea06877259e5601098e4ca5880e6a618ab21bb764e1df723904b90cbaa77" . + "672b1091f95daf1c797296db21eb4c91b63a00b556cc3663c42c764144164bf9" . + "4251c0d93aeed14606e24611be08bc2c83f1a18ac7480a543011d6f3122a8582" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d6a952b7d59f552cb03d1dbdf409fdb210c8bbdbd601b1d1e862c793a28f010e" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "55c4f0fc9de2d89c18c0850ce48c00a2651da25c7c8ad2a65b7b86cdd82b3342" . + "da5ce615ea64a5c5826cc26d85aba444672c07503d604f0d9ec19966ad7446a5" . + "27d7c61819002d137fffe479a8a42a5782d535b9b3e609f44e613fdf67fe6ef8" . + "cc8dc4d67f20fd1942aaa61b1a26cce8d511e697cb8f7680f65b572fab9c1c92" . + "611e66ba7316164189b26ad82beb72906ef26bfcb5c619a18a50c950375a212f" . + "b69693bbcef3b0d2362edb3bd917f80b5821390d6e3c6ff4c1ddd6b40698fd27" . + "d7167d0af42a5128978269a58000d21ff02ff5f7811ffbdc562d52b0fd34d02b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a39877ebc3aa1548980e0bdd76543ad47af5aabc0f981eef4aebaff88dbf189c" . + "a39877ebc3aa1548980e0bdd76543ad47af5aabc0f981eef4aebaff88dbf189c" . + "65f515cc210ddded79bbf98630848382b7c6503d82bdf280bdf75991c6af497e" . + "32af8b22cc81148f5a27d0cd3c51111ed3d97e10e1f2c14bca3790f263bbf3fa" . + "d32adab1dddd6e0f7f2cf2b31e994c46b3bfe653655770b3a506e1d2b894fcd9" . + "47df98aea74d58198fa1ec19097c99e48fb93c0e122ca2308c3e5540348b8ce4" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "e3c1b94725782368101a311eae4b9d114703bc7ea125181600413d449f2282f0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "7b719d5a52598aa9da8975f6468188f7144ef31c353891c61eb9ff9790b23dbc" . + "a33130935af697a3a0cf3315e9d3f43cb0b1676015494fc0f75ca175922c3fb6" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "f89072e789198119af60f67da4496b6b7d6e5c1a733583e989ea9d4d2cc14c70" . + "30ae2337e7550a79099c526a8d59d55c1172cb831dcac71da3253e966c4b9076" . + "ffcf909934d1105177e1036ba28a1f5ce2f6f08219bc676cc959430bd85b7882" . + "9acf0442068f2724042dd1ddcedaecb2be0aab7f71523f049d805c117368987b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc88193951c515a55ec9844416af03afe1bbaba5d6ef63cf685b12abb50f9728" . + "cc88193951c515a55ec9844416af03afe1bbaba5d6ef63cf685b12abb50f9728" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "357775208fe840f772d24a10f0a11b70fef370ed5f1e56e1fd70717135fc34f2" . + "d3450e8235ed26aa540842ff00b4e38ebb747549889221b13af92ee2631d9865" . + "d286cc9c9da6a00b87293e2a5464288f051eaaff582d212fcba9543dbad43c70" . + "129873ee7ff3d1db5108271f71504179512a607fb55298b807ccffde4c8072c8" . + "bf5404db4b8e9637c1461e579e1b4011bd20fa8e75d1e4a80adeeb5300681b5d" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "29cd08190e381c73815e11ae37b0fe27dedad1f92baa48e222f47204491df79d" . + "a8201888e55d0cf2bfeb994172e139bb7e62fb64efa2c84b75c909dd4653cfc1" . + "96c35cc982595f373eec85a1254bcd4b93ea8043420b1ca57ed3154304ef85ea" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "620c8f9d91888c78e893d08fe4599d5cd317acdeced6465bafedb940a8fec0f9" . + "506632d01f757bc3ca0b80b13fef318b4336cbaf2fd56c769ba508c8cb4a720c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "88dd071cd672cd444451f4d10097777b1205d4aec249d52f98502674360b858e" . + "88dd071cd672cd444451f4d10097777b1205d4aec249d52f98502674360b858e" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + "71c85054edcadb05938ea78f8f464d51048d792e061ca760da48e8b95f57066c" . + "1fd4afd53759f0119595c501b83f72eb47d09312e234125933411bc02d1ce7f6" . + "ad48f1e22e60d3559499abfe21c41ffcd5198c2613bebd7789df042c1ebab341" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "a4710c7fb71a83c2248ebf041937dd99c030bc089ae4df643406fca8b1f36939" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "9406f5f49bd1b8e4fe6bcedeed6027457b12b5293658a63e2a474a7677c5e460" . + "19f0b7220f858d5b7290dfc22d0ac4b45d8d21fe7c001643f6b721074cc8d985" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "338b68f9a6b8550950cf201de3ca72cae3fd9503b6f02ff2ce317a0e97ae22f2" . + "904fc95a107b72d82d6337c27a80c49d14cfaed8ca6152603f783ebd3c95fbcf" . + "b728a657a8abb353929ef44bdd2be35d6f9db3b1fa5ca61edc00cd5d712e7641" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ba4e43e3dc6ff1ee80de8d3c9c50fe0696168934082804c5b44839049e014605" . + "ba4e43e3dc6ff1ee80de8d3c9c50fe0696168934082804c5b44839049e014605" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + "3f81bd93fddd5555d9ba8e40ae40462d93a189472b1452680e667bb6963bb7b0" . + "c050a608e16382cecb038b0c4c4895e9138cafea2a41ac7dde97fc36fbbac85d" . + "0e4675329259477c325b0ef6e344a9a7415db37661c049243c6b126d97f54054" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "5caf71ccec93a1ebd96f495a75ec71c4e94389b8b3b010ff7bd668d50845afbb" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "7999fbc53b3979cb3774ab15d79b60fc1ac6e1eeb961a2de27931cbb6c509849" . + "181137da6b30e8faa2533383b0a9af118e77816362b56159001baabfce8d6863" . + "774b2276440b5d3796d27c6a6612d7190df580c82bc53d603f736b1fe312bca7" . + "2a8a651877fc08767b0abc06b4802bb36b19861880d692d1fb5db8e5c730c8c4" . + . + "2107d5878847712663756c457fcaed1431deb07ece1ccf797969207cd4b25cb4" . + "fac87347e6e73a26f93e4eb48151e8cbe0e20d2e29ab0d9d9d475b215b60ec5a" . + "0979f48aa827f20532c002e14ac4f7e6c26feb9281e89dc061d63c61a6ad4ec0" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4476ef628df51b6b4b07bdda206e3d4e216a70b8eb5591f45d6f6bbfb053b290" . + "4237182b135cb41f6aefea5b401022d28fc09f0d92b59360856a3121dda4f691" . + "d946c3d92080328ba422b0b2e2a6641265853d41e33a9391b5c7ff1169261331" . + "29e8dd1bfb2bb483de6d2ee8b5f02795fc764e79d397c0a51e02057ff348106c" . + "943de77fce3bfbf6a96595ad1d6b2bf9b98067fa3ca5d7787341bc640dbd8290" . + "9146841ee3856e066736f7ffef9a0b22be8b8dd27b88f924b923af9538c7bf26" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "9f7ed1478b9ad81dfd799974199b7f5691949134234e9ea0e1184094f403b603" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "ac6a1bea7691618a3f5e0be292397efba71d54f1cd3bd4d5c506c43862e2ef52" . + "82358779fd0fead3eca6a50193a32690ad69ab6bec88dd27ddd4942ccd581af2" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "4dbcf6785f479ac57ab4f02742aa8acb0ab3a534a67a3e70c64e0067b66630ea" . + "cd0dbdda246c630bd408165b47888ca60162f4f761451dec1e96d17fc14a4a93" . + "43b53f491083e7ec52bb62eb3dbc90b7ebcd2b596c901e158c2919f47828b963" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a7dd3da6f251d636ce9a7d2e9f09233959499811cd6bd86c390772a622e167a9" . + "75a3ac4e2434485d793bcb99df77d9fbce71fcaab6f698c62a1ec2f51d619952" . + "b1d386adc0168d017cec4addc6f2e773b0c91e7762c5ffe41c150bccc24e3dff" . + "0f141333a088ba1d48672829323a510af2d07d9fc86eabca4be43d35d9a6d26d" . + "1788494af3a9fceb73c71111db8bd2cb9cdeb091a6f862105ac5beb438b54efe" . + "7d6870ff54d91147464762e6a0bcadadbbf385ce26d127b34630204812f513ad" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "07302b34a101c34aa254e8c1278cce9d53f2b99ff982297c9f5d26170838352d" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "e72d3655193fad0e05029fba37c95cca629be13733057a38448786b1171b70d9" . + "c88fb3378929dbb22091320bd367fe35331fafb80a6b2c7b0ecd5950eb3773b8" . + "b3d0b0ccdd4e4352af68d43b5066d00858efec5f5ba4ccae308c7d0f47c5dbbb" . + "40198f48ac0a1fff2c19e1c97bd3f7aeaf0ea939ea1ed3e0421757092257cb42" . + "878a868eb9a9dd88b0822238b2165028586060f5151024ca1318682fccd37e78" . + "2f1ebd83b717500992e10f32ca3194b52148451a619ba9617c9423a8c9485890" . + "ec7674300537f7080610a03abf9c420a2c262a3c7361b77fbc4cf6b24fcd4006" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a1931654eefe3ca15c43df6062ad7d377e36d4ef366fb9cafb2d5ace18b1c48a" . + "725c34de2c1a399abb782c16ddcd90ba183968680755af8002fe5b0be4f599d4" . + "953f923de72fe791261c989470b4a5916bd699672380b4ee27cc4e4933a5861e" . + "d705bf837eb38577f82b727dd1ef65bc788902c4f5f981e6b94d1533db9f8b8d" . + "b78f1dc8a331277f5ffc4e84029753e29453ab2fbc8e837b1727b7a6c87733dc" . + "b1364c0272aa8e74e6d888b1f46029ead25c24d0b76c4c4a9a09768395067d7a" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "7949d4f9339ca8dda2315d548689790ef196bf29ab94684e5a0848f8365d3e0d" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "a68991974c5ea38df4d0a2864a5f4e3ca43f1cbe4860b70cf658ebac35bfaf87" . + "7ccdbb80826950c0f83a19a10f11917cd60560dc3f2adf5b1ef2a9356e61a2ff" . + "58dda1a90f1969937f69bcf6a06391fb2d7253744f35efceb609a1b16c54696e" . + "36de581302ad9771c27e689c8a2660b657138cee873fcbee2d96a31c3966f1bc" . + "bcb25a3993c4a688b22b58fd4e67dc9858776d6cba7b1758716900152ce66afb" . + "6bcfad18fbda08b3574f007fb2ebb6fd5605d3fe4304a8d834b7ea6f0fe9e521" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cf6c23a7a342928c51e5d900b9c8eb9021f3da30fd6822bea16bf5fe3ba869b2" . + "0da2a11069ab7f38e0016ce0cba45dc7a0ecd304519f4cb871c7056d841e4f7b" . + "28826b0ed600d6fc7c0e4418b936c99a6833039b235bb45207f1a942cb45193a" . + "01d10f6c46fe5d4a6f0222ba250ec999c689a2cecd18a5fc998ad17269d4ba9c" . + "e76ac92749aaf3d02eaa8c2216135293ded5376959b0bfac1061fa9f7cbffc79" . + "89b619fbec719c387709bbd6431f8e8f0c5160135fbdf0321fbecb48cb6f2773" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "88aa80a4c211495886712f7cffcfc99eda8902b0f26f0a87faf96cd1ab6934ae" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "318dd9826c59c76d262a5d149fa1391fe4283629695aa45e864d8aa86f596c1c" . + "fe2dbaaca3f8b027b3e0631091f04d591f81cef556bda94bf08cb37cd435c009" . + "2218d04d47d5167bace77fdd27cf1e663b12f4fa08f2801004cbe35d17ab1c9b" . + "68f7b9b7b86255f70984eadef797450eec561d677c155ff101f113898faeeac8" . + "bd18879f93d252ec86ea8575eea1c30a3b74be32f6286a1971e9802d202baa34" . + "4ee3f26c812181f2277ef41b63385136a06c974d02b0501e80ecd1e7d64615fa" . + "b19e8a94d02fcf3ba39e74de45856e0ba7a21f79a92d44a3d58878e9d8a662e6" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "150ce268d3402bc97e10e816787385b2006e9f9d07ec57ae5040bcf8f05b2ca0" . + "6c6b96d6676695acd7bc873ed2b8979361b5886dc35c25053212f9ced9465943" . + "7f3721bc913033d7f016947c85e698bbfa240dce1e43c755f0990ceb142552fe" . + "2583db9cf67393fc6254b72cd3c2049d6ab5666dd6efd21e30f85ce107a5bd27" . + "08a50591f6030ac44cbdf9d5c84d7f56ab383652978d68f00cc067a8e1002627" . + "21c1f9da831449f7b0b7b6d76539c5a0b298e7836ece46f6325f38fdc5dc6333" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "3cbc8a5dd057036dd50995a60fd43a30821d7c0491ef3c41a5687f624ecbb80c" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "ebdd45f7b85433f8a90870c6e6c8d0241ccbaa287165efff76353399dfe6edc9" . + "75d6e98b891504e3add60942e0ec0b78300bf58a25a66bc9b2a4338cc1550e0e" . + "20fe5012bb3730d4fcece058bf9723efbc6c6146bbf4caaadb3273bd1b130109" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "95a0e0031dc8fb049a4fb954223daaef5ca354475e04cbe69c7c3d2eafd921cb" . + "1ef968426cd29a9e54a2c7e1cab1bdd5f3b3125ea92aea136a90b75f33ca2035" . + "fe669f671129dbabbad33c6d1266ab471b33b23cc4fc0d7fdeb5807b18d5b60d" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44fb9bed4e193c40d0ae65c7ad0446ef42ac108d1b0b77f6e3207d7239fc32eb" . + "44fb9bed4e193c40d0ae65c7ad0446ef42ac108d1b0b77f6e3207d7239fc32eb" . + "89b6baf2dddbace10bad2c222322a595d7f3649aee99b526abb50f2a555a46a6" . + "98b5d6877c78b4686f6e1c57cb053e519b7331ae341b9e08996c79630f815e40" . + "28eb4cd0cd91f3bcedb0a1bc3a68926dad6e6f0e047f9ccb526dae05c3a22e64" . + "ed16f8ca942f36c6fa6207ee57809e1730d84463c270b1645d64a59b008d0e10" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "6763a7ffe32777772cfe1bf92e6b6d220190589599a856ae416710a4455fc0c0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "a7687e42634dbc46184cc25445a002dd459b0265b593be77ab12c626376eefaf" . + "620636b72d79ce73abcfffbc1c1deb17255508b22c881cc03bac952c3e14d02f" . + "d0a3a1ba651a744b4ead7438183162372bf6c3b7a71e65d4845de2d24487452c" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "3f8db07f361d7439fca063ca031cf8b23ba311358149e5b49ad94475a85b64fc" . + "19d04670f8ff2327a96de46c8b7353988ade713d1140c9e277b4370a4e39c960" . + "ceff435a35e0da603723f3961340fda61bc542c8f5a58700b5e4394674a2a14c" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f61407bec3069cd727cad60403ba970d7d93daa041649825831bd99e5791b100" . + "8290d50f036307bc3b52cf80db7748f06301385cb9eb83db156571ab5d8b9cb2" . + "9793f34acecaa36143a5e696b45d5d44a4f3a723b1c144aaa1d8c93eacaa0f85" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "5f4545b8420855b4cf8b8df9bee41d2ba31ec193150ed9e93043d56681f51113" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "52fb4a0ae161b445f38ba9e04c4b667941639624c6381e85b283163b40e9fdfd" . + "621d0f3395939b89f53fac48b6be9a360742899eb1b292c9b756e6d8001af665" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + "846bc82f1d6106dcd8448edf03647faaf6b007d928527bd1cf1114dbcdb08ee5" . + "2977772886e1a548f47eb92d51d1b7a0c01c872bdb0b78bf86f0bffeacb847c7" . + "b563ba507ebe2aef66f7397e80455aa0c6351b06c12175cf15923c9f34e23b9c" . + "bf813056a98b1ecd8cfa68a86652f11f9d9b52fb70dd6524ef5185269c63077a" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "baafdee9d6985cecb2620fe253651d853d85f9adc5d526e21db6848e1af95c6a" . + "590fa9d973caa6ee652e2b50d324ee4bfb3b090bc7f4d48f85614d06117f636f" . + "97faeb6bf698903f226e492342e3fa4e0681c0edb004005174eaeb8f53d8bbaf" . + "f98a942789f087a5672d1180787f9e5e71082ab4fbeda63bac15b2dc6f59800b" . + "28ce1dbe100f3f46bb7f728d4349210e617727d06a4227c4520c8f164494ea1a" . + "b344f162fe9536b4c37588aad0191e08e2f1d6a03e43a065194388ffa516e885" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "d47efc6d643dbc81d8be56151678ade7f20817ecdc523a0d03b4f1f1d09fe147" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "3e80c4f8e33880d88ab449c84517c4e2bdee5d4a9c4a2d68d316d7215a48b6f5" . + "d093524efa3dd5acd7adbb3cad526087584e4a1eee878b3371b1ea1a6080b53b" . + "3104a48e4212d0eff2da51d6e8bb08f3b8ba43558c6461f01c3540bdb391dc3b" . + "02ab32f24c24a4d0f408da8d5806ce9b1605191b50a8e8075328261bcde532dd" . + "7279fa6f276ef595decac7f9d206c2c8508632fcf4620985284400bf374a1ecd" . + "d3dc654041bdcab3273e041bd140db428150684afe9271ab163a6bde816c6ac1" . + "7d88436f379a6bdb215a55005aea74ddaa4b52795874d0c1d519fb23a2f4b7ca" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2af82ca3c64c51ad9f928d40e577bf8adc785cec67935792146107e0a7d4ab67" . + "2af82ca3c64c51ad9f928d40e577bf8adc785cec67935792146107e0a7d4ab67" . + "82f4287c2478ccc072fc759950ce7c3ffde510bf5959aad00a2146166a935d9f" . + "fc9214f0c037e5b4da9da05638c6050da707eaefac4e4cbc4b9661d861b3cef4" . + "e76498c4ce82caa53d5bdf9454e748808fd5a1dc9f730dffe4691d3e96988250" . + "a0b70ebc33972721f207906b76775dd5203f86071a721a23a6d96e90ecdf9a21" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "dc5f47b8d9b804d3b680e78067a8bcf9665e30d90fab2608c2e78ebe80d3077f" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "1b1d9b8e2848edb7712adb3baea54b5f25d6015550c76321bd956894bb66b685" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "6996fae59714f0a0365e23409e9a5056a141c5954bed3a961bfbe8bbdbd0c611" . + "9c077e166e7cf879e578ded5a5cb7783f23e43f86287ac0928959fc63f63e73f" . + "79bfdd59a7a0557a19a5b3bd91ff1fa85155ad96a62923aa5c12b3e76d5a5b7b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53dbc1064dbbd0181ca1cd18f55b923044ca1127cefe98be2391479a271f06c7" . + "4b51432ca5cf7904d01346b4903a7c674062611f0dacf6786b5143e2ce86446d" . + "f97a7d897678221aabebfb25541568b56d90fe7a72ff06a7a4fbbc5f8b6b2861" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "520bf6aad67d5803a2b9a429d2fb5dd138612be49972480ec18be4d1a2fa9e2c" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "99f8a712dcc9000e85916889dd6c84f4f99b10f1b9ed583ac60a020fdedef102" . + "235d2a4f5ebe3b66f2e714f29946e011a987ef9749240b6846ecc6d9b93750f2" . + "5bf6e3be012784687a5cb18a3afdde5a4fc6e85f7d05bde3ff13bc689236e801" . + "028a084ea5cb638c3df5aaa1c0f65a5297f8cc4abbdc8879da470f1c5d98d618" . + "2f34501b9430bed9fa47ce1cfbff7a159bedeb2fa02b150872d79c9a87e701c6" . + "2389d37dfa05036df2644c3a9458110922d0c5bf242a1364198cde1b1673fe3a" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f6bf1e9a217a20cf980fec77ea0a286804b7d7882b2edcc4c4052df2f73f2217" . + "55c2b0d8b6f43e5d474930ce88ba0a60de65ed0d6fedf41e3610f3de401aacc2" . + "b86a532a496d2410251cafa7054c601fbc9ba1b0382cc379639ce3b9e7049319" . + "6bcfc5d14f2495a5a9f1e878a7e01ec209733b42f17cd418f01a3ee6d8900148" . + "8d2939f75c2a6b43fa08a98e4bd874fb57c2c40c0833816f09c35633e42f81ba" . + "a9644344e1bcc402bf56f6b863f7141ff8d20b9ada7776b3587c4ad74d1b63b1" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "75b25411c2d5c0b09fed482d49392ed700811696835f78aa6648ec6c443314e8" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "84d980dbcaae1f52ecedad798304c96890997f5a8239e9e37a7646bd6af82c71" . + "a8b9ee5673926118e43166f8e21f319c7ba17bcb23b88c05768fe5e351424c9a" . + "f89072e789198119af60f67da4496b6b7d6e5c1a733583e989ea9d4d2cc14c70" . + "8443370a1bad3751b9a3c42e8cef2b42ce5b4f288c8dad950e4ba1e085ccf16e" . + "e1cf5d74694e1be7b9e2f94bdfb1dc87b45cb5d1002f464c856a0179ff029ef4" . + "e317784f7d3186d9d958e3fc9e01653000b5404971642d7628f7716db6e0bd09" . + "9acf0442068f2724042dd1ddcedaecb2be0aab7f71523f049d805c117368987b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1fa1c3fee924248c3ca0eb723dcda3ad23a632ce74af78f736824413bc703022" . + "1fa1c3fee924248c3ca0eb723dcda3ad23a632ce74af78f736824413bc703022" . + "5a5a9658f4301fad791b3e1fc3e5dd73f37a2019c72adbea75e5838d0cf7e1c2" . + "ce583cad5b3ce5c723da27b6329e096c5a8c410ba358e442526d4d94c7804af9" . + "0f7966ab50963b61bc5dd7b20224670c7580413f4363a076026445b1e8e03fee" . + "6b133d9b37900201ec5e071543613315f968cc3af87654c3feb2815f95c53c07" . + "8d83af47468813e862001faf8f92360705666baafa9de0af6f231008eee091f6" . + "5e196e5745448ac960f81f36b4ad2a4ccf37ee89445425928d49367dec248e42" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "1ec69428ac2c12d79594becef5c01d1021b85669d9c97442ab7b7ba2d90e95f8" . + "93f3db54a2393667bc497cf7dc81326fd8347a692e3623cd0504471fb15b5e95" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "e221af795e3d619313cc0c6c8343d3ef38fac0f5bc66fd62a0bdafe0356462e2" . + "65156f6b161007522ba0a514f307844bc48272799485bacb0ecbb88dbf277616" . + "f6e6bb59acafad28f3785183776e542e1c0201c4b57981ada9085d2e09caecd4" . + "3c9524c1682cdb91358a2f0c80cba4c34f8cd975c77ed55a831b5162043354b6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "af1fd5235845d5bee5553f2373cd6220859beeb49d3c290590a05076976878b1" . + "f383f2f09368c3a17f0da1a6325d69100e10e934a22cc01c03ba5244bcb087ef" . + "afce873d7f207ab19461f1ae9e2499006d112bd9aa4cd63b953cf2d1fab7f2bb" . + "c541c5c2e84e45d2ee620cc91078e52cb8be7a3900c97614bad05bbc085019e4" . + "5078deb7fa3d85a4a83ece7fbd37618dfa550d8de2fdb74a77769a2b692fd943" . + "0da3d046f0180bf2b4fa948f43dcc20702e0e8c493fa092900eb8d67625a65ac" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "20859c3404bb40b1ca777b0f4b0d7c436be4ff5ec8d1b5adb8bc1d1f764d963a" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "a3d80c8dcba7fbfb067f44b94d1c85f3309cc30902dc254fdd13d209a27e8cf3" . + "ad1cda8e88087ce22432524338f78bfcfcab84324f8cfd8d7774d6fdadbaf69f" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "323df71c8909b363da3ece635c07cf203bb30f114f1daa6cfd3a8e5e8a023287" . + "7aba1f37dfde6750b416da0900467b13e2370d6d9275828ae0fe08ed89830cb0" . + "978374970f0bfa58ebdceaba3721170fd5e713405fcb3aa13c1f0709dd2699d3" . + "6f09e2b7e48146415ca44ef39f0f88c6a2d61f5bf7ad543e220626879aecc16c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "43fdd09067f52905e8edbf207a1f126d71bc8a739b7c8ef49b4e1e13176dda89" . + "43fdd09067f52905e8edbf207a1f126d71bc8a739b7c8ef49b4e1e13176dda89" . + "cde83d6c72c8247850857d37fb01fdad66d5071ebff8d49be328c028bbcf94a7" . + "d891023e9c842837d4e4984ed5d2bad25263e4ef204805037cd63b232604f52a" . + "d262a3dceb301a636c09c87d1c9d1f8c9f9de5b1dd27aa931953857cf05c0a96" . + "0f31da0d335ad5d97fc782088b080ee82bf9545c24722f4a2d213c4f3aadeec1" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "0a99b86bcea7f7465ed0fb1d67e01a31f9d1e2875c676d10adc54055df34f0ff" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "675d82d009312b6551b5591c484ec291dfc114da245793a38e740a7037ce402d" . + "0dfaf02f50f904c3d70f33e45bde2307b3282ccfd386f35dd7e92dae765f8989" . + "da3bbd81c8025a238f4905d1cb6301c0080fec6856b4ed9d92b94f40f90e6521" . + "cd28c05b5567ffa739d1a0c6f6ea7bb0b8abf16908bfbe3442e111f881d229ec" . + "a57767b0fbec36be8f807dbb9ca933cf97e47788b67e925140aad04ec7704cd3" . + "8bd60db2f53c40ce2ccda1ee7900bb364baf890a9569ff20e9aae5f92f9a250a" . + "943ce123d0e38135efcbc5977a87ef29382e3bfa2c8c7040aa04538f4ba5e230" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e0ab80a5063be41e1f0efb92f13e01859a9c0354d296b78830852ab5c47faa95" . + "4958d002cd41d2e4d8a1ca1dca57dcf806c3f9f47d96207a80922dd0a199db9e" . + "fccf8bf3b7f496b8dd5ce458068461281d7d522a8d9519c3ad77fad111193acf" . + "c7d19003afe889d797dad2bbcb507fa8200c3176b0d9ef89e9c829e5a097b50b" . + "c1a044be27aa139f67fa0d2f1aefa4d45dd137730a6307fa20bfe3fe17c48ac0" . + "16c282e9c706ed0a5576b648ee960f82c21a4659825249ed2a3696e823491b12" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b3f09d473d951e781eddb46df39c82a39b7d9ba27ef60faaf30dc58d80b70cb4" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "b6e2bc8c40928d9c877c4ec1197812813bb662da2c89ab808e55f875700a818b" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "bcac6e7563f21395386588722a3d80a8e71927f23ce0499e3a8178e461d4e9f0" . + "928266cff8a72a6ac0e67513b043b340a05322108bd41fbf527bfed1e8ccb739" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d10a53fe373f13b9427a04366f2563640b3da25728a34b0f32e6aaf6e9e9540d" . + "d10a53fe373f13b9427a04366f2563640b3da25728a34b0f32e6aaf6e9e9540d" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "7d9c44e18d0a41e41184fd60392af24822fed4e6c096b1d3ac6886923cde2359" . + "711365fade8b8b2139f74c9582125b616f44cabc1462fed08b6babb2e3cc6a29" . + "1af77ed0125c8e39e9301c2cedd5633b48ac0471b19767ba6470589839cd7e8c" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "0216447940ec9ba5bf561bc656f655baf1d1c9f27609823ab9e084d29d161ae9" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "24f057395c4efd8e249261fff95a65e7836a5d76743c7d5c9e4b86be70dc7ae0" . + "7e65c846049d8ececf6bb2b0c7a47040b811eda42e6ac1b2928d8d023129ba6a" . + "3af7dfd521fbc1455346dc00c7f0c604399697e173b1cc12069b076ac29b32e0" . + "e3f60b970c2cb7174d2302417369e0da6654f5e44ab89de1ac08e8db831233ac" . + "7622194904f5e67a55200e22755a646ca4d232a642919d7154cc854cf1e82648" . + "532a2d4e7e3e84714dfb5973c2c53e27844d8e1332f39b16805659f33842cc7b" . + "8cb53f946072ce1615e3533c56a4ededbbabb376a178b25efb73896816aadb30" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a19f0840867cc9d193f91f3ba845db81058542faab96a1c42ca21d50c02a78af" . + "ceb58c2638fb04eec5cf55ba47fd9a373febdbc7e68ac05faf307b033bd6b999" . + "5be40203bac78a6f81ba7f21a9a0fec5011de49092c48faeec34730a74c7d369" . + "0d66eb5b09150592b659439f1e4b13b2ee84667a5ff8722b6fbc69ff125af05c" . + "45874434c28652d21fad5b788a4ae704081bed93efc979493b982736ca8a9491" . + "802750b34f924c29e4750170416bf579301738c7b9110e5d7fde852449f229bb" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "e004d8bfd2e6b10bc9efbecadcbaa8a2b87cf603a4f0e630c4628091dd79b2ba" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "81e6a8ac2e389b1ca5f6dfb523817b8938809c219287d0836a4d546e6ace3a45" . + "466ffddd1604f7eac04b3b1ce458a1ce26afb7a7ed4d2c92b0f74bd813b9d306" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "946e17b6483d3f6107b9ea91124459ba8c90a60d433113d3757165b624bbb3cb" . + "2e1734e71413769e20b3d73fa387b6f00d2d1f419e9d872caddd75d63c66b451" . + "fb5da3230a3d36e41bbd3049758a6d722fe0921caf5ef0e4b1c09f9504a1c735" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "073ac7482af0b6a911979679fdcd850698dbd5d84dfdf024282a6834ef446159" . + "38b5a9ba573d013cea9ab605a317ff26bafba83c3d0461a763e4faa694eb9686" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "2f6aecd8a5cd839a8d244e4c38fa6a3d5685f0af7e9b26fd5ce2fe235e4dc5e3" . + "32b358991b6b7948f440f2eb49f90e7531a2ed07b6f96c12a284c2315aa69d12" . + "0f75ea53ec36f08191c3712b0d6ae0f659fbcb8793fea0d12dbc495d00a0e906" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "fa0a774deebd9e1358ed87582102d288c9ad60700ed80722fc1e93530f5c8f1d" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "c76a4435c3b583224ab8343493b47079433fa488973386bfce72b5b42fe8d8e2" . + "3d4126065f30edbb3ffb3f412bee4b62b1c8c0d1812db65b06e760b3eee4f28e" . + "2bf9c1c7b679ad681fc1466bd4c63cfc9f1315a791ad3bf86e080a7586c1db7e" . + "08b3a5a096e587359598da24f6ccb2bf168b8ad29ae4982b10769466b3f6113f" . + "cf745524a8a432cd117acfaeffe5957da4c0f9a3a5be0e313dd31f43e31e03d1" . + "2d786db023de5bb06fd216b4a6933840f6d5750bb50aaa7d9998db1395e26b49" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "09b94f1b875d75c882e73c7f334fb0ed3adc04a98ab7a47e9a6f64eabe2fc467" . + "ecaa89bc4586a8451789aa27d679ad48540a9695937423b5be21144de6b49b72" . + "b72c87839dfc4861233cc291324df74292c32a1a1c23aa2159b886af9ea2d930" . + "65f23494798bac14a26618fc7ea594be5bf2bc65b9125b1951df5a33475a1381" . + "a703d4179b555d814c3b6d2589781aba05d6e920c8166e14b0c0d8b041d2c946" . + "22c74b6a12c4221380f64b5689125cb9de6c75e69c4f38dcd45beb05ab653200" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "23de5a0a248402f8e5cce6b21162d84b40ee898393eae22b4025b55bc1dfaf46" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "a3d057b56fb829bcc8dd3869926371b57094265d33b274ca9f3334fbfe13dd2b" . + "6bf86b5709d2258e9b6db6b5701077ec11d302e5256509f50c34275e9c59d942" . + "6231c555ab29c38e22462beaa07a47072bf7da0db971d661cc7af67bdd880681" . + "c8a07d1704b76186e12f016fa3b12299829d542c050bfb4d962d9e3f55cada2b" . + "f6d12e2b329c8d07e393a1583d7680adf8405fa13dc570895b9997066168d1e9" . + "6e25ae02b137135d56df4ab777feb6d4a147d15bcc2341730f94bdecedf219c3" . + "0eb6639a96d588742afc77ec991fbd467047857dcb05586af81d60285d08931d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7be9447a81148d9944810a198a3ba96b8849e4ac6a5bafd0b1bc52a383c85b9" . + "2ac8df13ff060b38982dd65ba13d855eb211d0d5182e95a671124e631cecf785" . + "590e43bd6e0a5a1f50bf2622a79918a1ccdcdabc654787dceb23bf295d5d09db" . + "60280662aa59117be3f2a0a779a7da3219134532d9b231f64582dfd9da18c377" . + "b205c1dae4f05d39c2676f235408375e31681dbab29c3f4477c8588d1625633e" . + "8f110d82563bda4bfee2d74330af624af62ca97e7f44ebc7152b8460aeb95143" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "5d1d6dda8d6dcac22c3d6b815bc1cd0feecf14809c0626fb4bc5489cf5ec0744" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "143d69eece118e53c28f86f99d669879bbc213ea02217a5c60398873a524e95e" . + "008fd866bb2c7f4ea475869ad0fe3b3da97333006e7345b4ef79adfa88453aa2" . + "cd99cea8b7d7ccaeb7f60872418fa42972f0459314adebf2645b22a1d306b087" . + "9c7117005a047013712f6eff470b3bfa3ffa834200b92bb072bd37a496ee4952" . + "d605c7824a276beb12a8e95ace7d12d5c9d6290c3143ec6fe457874301d18bc0" . + "d6d5c6bd53c7792b17b740413bda001e69ecc693b5aa7f19a89c3e83480b83fb" . + "8137a0cda7691202861b637798caed84e570b08f88e1c219d6765a7520323a68" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad4d0bbd102e44a147c659bab2abc360cc5dc87f6a9b5a3ce627effeceffc9e4" . + "ad4d0bbd102e44a147c659bab2abc360cc5dc87f6a9b5a3ce627effeceffc9e4" . + "69ee91c1a4065df22cec6532c0616185d24244abb4606803be498df927b2504d" . + "c3a9407fc58db0c8ff8ec8168561c1b998714aaec46e89fb3a2c297b52ca75b1" . + "8757ecc54e574d1ff2e9ceb2030a80fe34f98a545d3a57cafb7e53bcdb71f424" . + "9f326f68bfb84f96b93911a626327e778874c1262545e980da89182b0a45620b" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "94d69539e406e603b81d87e8a8714b3a6d0338d9f91771a3d91da6761fa3c5d0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "35012f4310ba4972ae35b83f13139f559f37f5f41317fd2730dde10dffbad3f0" . + "d1589053557b5d407b4da96f7f05d67a29f2ee29692baade4908d80d70cd5a61" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + "87566fc4186e90b4ebbe2aad3594953296dde1f60d516314ece52422f2c2fc15" . + "401cc74bb238ae5b62199c89ef5c0036966e7ebf84ea5530b6ce241196c4a213" . + "c563c46ec59a7bff5b78426b7fd83e316e9894777c1d614800b1421df6bb2af6" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7d64364aa5a1909025e0da587c5a2527c4f865cca7876ad1db422e794f3c186c" . + "4402cbf1f05c7f89328d0b5b63815484262ce919d3ffa7fd4eb8d89125cce958" . + "4d0f119fd6adb425760681d8fa6459e5d665690183a0ab04efc2d647ad16a9c9" . + "a8c57bfa0955a6b4a20ff0012f1f864242bee68b3630104f06c3dee417e588f9" . + "236c889f7452715fb9ef0863dfbfbd76f9a2f7b4a4dbc652dd5dcd07a93c39df" . + "644ab875263f893551e186a665f1b8144aa997cb364db772f07b5ca9b684a3b1" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "4bed2e92dad76ae8efcfe2391cf6036ba2d66058928c90c31e07453b85d1453a" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "6c0f063c7b58e3c8cd9c8ddbc116f869047549fb1e489e7bd1b9b8c522948fda" . + "f73392a0051a1e4dc602f3f9dcba0ffc05dad1341f7a34df2880d6568f7a0863" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "214fef0f8749616653e545e859a701c29b90f5dac96afa1e05b8dce41d50bf63" . + "5067af339fc3e0590959139db61d29b0d7500afc86ec9d02607b64f410220fc1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "87d29d3a0bd07efdafae7164d3fe662435a1013a84a61916fcb393636e2247cf" . + "6404ee7259d791a75dd348c648bf68c9844f16b94a004e510eaa1f5df364f525" . + "6ddb17a81e6dbf16ab235922eb6ec03fc40bc781d88243789443d19b0d31c619" . + "461df5c7d74eb4a3e4809be75114029546376b82d1a299e06370df5e53c88402" . + "fc7ad26518377fe4bd690ec87fac9a942d7fbb4f37c34eb6a824003c1d4e8ccb" . + "f09cfeeb2b904b538eaafca88eb69456f5ca0cd1408a81daa28b1e1026740a0c" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "48b19c92ac57d31c5faccc162b43a967356321614ac8386af5b18e2213be62d8" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "52e8258219652c85f52e774b31490ce52b11511190553988ae96011c493806f8" . + "98cecdf9241545d43634154050d8ea5c44a1e61b3f979cba320acaad4d359fa7" . + "83866e5241c93c5f747c98798b0b4a82e8e79aed3dd66f6374e0d9596560fe96" . + "3e75edd678b4832d5581046e71d3b9a5bba34b1a84b35dcd927ae664872f35f4" . + "5a3ab973ea6038e3dbfff743fdac0643e85aee291713c3a7eee1e36bfb9a2c29" . + "d6f31c9278880493573984ad9f11cc0487cfb3783993d7182c2f2913668d28b5" . + "d753d3341905c9d5e55c4c66995b73f8eecb4965c9ca5ef242331fa12b6c3e3e" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ac6dfc69b127506e60caf268238b19a2130e0380a18110833fde76f945f0bc30" . + "54bc0cb2ff82e80d75ceac8d95efc4148053789fc971ad2d5dff9dded7699784" . + "7a7eea16442bdcb8f405407a722aabbd8132af344f94bdb7890c79892595b15a" . + "86607239c30d3cc1e659b1491d07ac18bc490fab4d83917ce4abe6f6b0e010d5" . + "b02a113cdea75264e4fafbab765caa92ce27be9484103ad1ede83336c3832f7b" . + "64f78aa39e12b1ec5d5bd2bbfcacd7da8e6322d007917910398e39194816ae75" . + "6fe91b2a6e365053aa3b9ceb3f6dbf7be3ef12872afdb710c590e012460683d6" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "ee3544396422e864809d6da8fcd462698e4b5113e078ea2df04e3017fa9352e5" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "099efeee0fb96ef241f499e1bc416ef45eed777f5f0dee3d1ee4420fecfdf2a6" . + "6795ec8a76ede8340af6f162c2951ad15ecbec3918cec985909b7c16fa24ee51" . + "e44ae713f3b34e612ef31438a077455f5c8ec5dfdc9f1d236e96731a02fbd24a" . + "4d6b1845431991a74c43855cd191290ce722f1b26f1e0e385d38bdcad09acae4" . + . + "37520f8df92a03cb91b373a269c2f425f53baa3759433e04fe3bfef725e805ca" . + "cb3cda0b037472586fe9046c0cee90c89d22a8e46e2c5a4b7a9c35c87d8e8ea8" . + "ce527e5719f5d81270d4445602040380770e131ce2d57f6fa7c04defd0861594" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bc5f9db97b994303fa3c208aa2682d4c46ed10ec42db279e433607160b029f02" . + "fe4672b40a4e907abf1f9e208522cd630841d68ece0bc82c4a9cfd51bf8696b0" . + "570c2f6d591fff1c0eb80de0b4378f3a630f299327b45315c65c2641341c7d55" . + "8c1dd65f670967028740849a7adc9d80dac13d755297533a1727e026efefd6d8" . + "7a8f661f1f5e20df57654db825b40d70965a59de9ddf8a832ce3278670f65243" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "81dfd5c8dc88dcaa3060c018e787a56cdf773b9932d3bf9d1a496c3f8fcbe380" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "7c3fc56805f9bd85de6196e522f6eada540a29b9c325da2a68d4a24598b26386" . + "60b068182aed5941a7b0cc52e959ca32721fabdb8fa9a955cb2a8515e59dd970" . + "d81c2da142bca67a663e81fb6eaa69f6185c8e651728bcb1c04a470baccc7af9" . + "7ce05616c7e3b03c63385da6c68ca96996b9cd5b65bb9195ac63de635cc9f209" . + "5d2dcdd88569f0258ab155ea80f9056216512141c1adb86b533910d7e4de1ba9" . + "0939aadd3f30988f5ecc37d7d55b565412dbcb92eb7940cb5b659710018201b4" . + "4e75dfadeecc294ffbbd950cdb8fe1780c261df4112eccdfc943822c40baa122" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6db4d790551b6b7f576c762889cc30a56cf5ccc2d509d7464e8a3652faf45ed9" . + "e2779a529855405e2b778a4a549d635aa222233553cc37512631d7c13acbc44c" . + "56996efd8500e9cfa253031563affd7492cfb61c17854490609d1b9870d2078c" . + "ee28bcd318b885490af566f92cef3f619945d87e31d17c394885229cb1ea7b1b" . + "4c0aea857609af92e3f5a5ad9bcd622d0be68611069976f27d163ae41da8d7d3" . + . + "619f696d663fa6ef0e4e12af2196eeace7b59df31f80d79fbb42c2826f02552e" . + "5e1e315188c7f6a506b354b9d6a079faadac24932ccb2a1b1290373fd836b47a" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "f9c78823ef36f7040756c023cbfdbcd95d42dd205ab6bca6561835f4af9b4a49" . + "3124486c8aa1823b91fce55366dbf035617a8d69dfef46f9bb36e46f33f5cbe6" . + "4c82b4bf7fdea81c1d6cb591845d1e12c155b0defc9d99da953cf9c49daee229" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c4d535ea681a650946a8de9578761e1b00fc3e8c84da6ca0f55b0318fb982ffc" . + "c4d535ea681a650946a8de9578761e1b00fc3e8c84da6ca0f55b0318fb982ffc" . + "c1893a02f3b685f1f35081ac7038601a3adab551ac627c71bf12126c547c7fc3" . + "f7ef9759d4a6cbe10d0aa145cf053c688d306a1ce2d6cb47fe8762fe4de541fe" . + "5f96c042517d2e9abab09cab143d1ae52feaeb87a903951610b30ef74fe7bd47" . + . + "f3a31e972b8146bba4d9fc623cc9ae313892acfe8f585c907a850cbe8e29b1b4" . + "003554961b4489c368ddec945534918cf700c71b406280b2d747d4530312d1f6" . + "e26b27528a9b12d958731ef0d32360e3a6f1a9b723b5fccad495a28d7342eb31" . + "edf2a0c924fc489734b1032f0ee2ba91beda6d1ebc573ac92f0515485a44e1e0" . + . + . + . + "65dc82001ee4548f675fd6b883e21783d8efee8ef09c6666fe7a4d55ca406e26" . + "768cf26677397a792ab5edefacb8f9dadeb1cef95283185c9bbf8aa9c3a61227" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f52350e8ea642bad6efd168cccf62237c53f771c3241ad16c10786125ad270b0" . + "338b68f9a6b8550950cf201de3ca72cae3fd9503b6f02ff2ce317a0e97ae22f2" . + "f16f1b69559e8c43d6dbe1f52b0858402f58e3cba9c71b18547dfd0d56e5705e" . + "a935830ce50bb62c1957877fbdc6c07f5e108d860e9a32f32a76b72fe563e19d" . + . + "f736e20c6df4e217036a4582521fc203e5a561311ea0e4bd60b7668e30f4240f" . + "be526456bb79da93cebbd8514d0f8e21c85ca5c1caecd1cfcd53bbf661b0269f" . + "a44f3d41823b1e9ea5cf26b98e9bde24b46b545fe5f67c94033f190460b8280c" . + "6ee5770ddd98015efa6b416d31a2d742330e1df0db259800489f2acb5a7f046a" . + . + "789ae597c362fef0466539046eecb4155ffbe2fc32619d84b5a2f228e6609c09" . + "5368e6bb52c7d7b08e9e16bda7c5a277252692e6607bcc945d75564855d0707e" . + "22741e49da91659721b78fc06c132a4672bf64942dc907fc350bfe03ea3bab75" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f2bd87bfe92f714217993ed9b04d17ef2b319cc4bfab229fe2ea2559762c898c" . + "b886a5a663d0f81d38e80f2d037f784fdbe4de05fd63c8e0c499b306e8ddc68c" . + "b0f0d3d61ded3918bc29bd4d4bba039116b8f3ea3cbc05693c670b534ee27327" . + "b957395bcd83eb7dcdc89169d59e62aa9d686cb1549f4a2b67322f3a4444ad7b" . + "22daf30d2174ec16a6f7631e54c7af5d88580eaa60503a89f84b62c0ce073355" . + . + "ab7943d251b010931bceb074cd5bbe9bbf0576738038183fb4daad1ae007da7c" . + "1acc83920a40b5c2b84451f2ca9da6a808f13e416a74babb45a04e8b156d5f2b" . + "2ccbaa9f1cd96fdadad41b139297d91480420ee9ae49b99f8498cd067319fea9" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "e9885e2026a8d87dc69afa362425e6adfb9056b3d4216bfc6132e775ee1c9614" . + "618d24cf710126fe74fbc67c6dc28aa2feb454543464477dae12f915a2da300d" . + "e7bf5a6f4ae40adf6525a771f8d6c5aa64c6f4f2e1a57c21acfe0bc50636694d" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7fae882df9ce6f950c45d2087c34bb481499733db1795a1694e17142695b694b" . + "7fae882df9ce6f950c45d2087c34bb481499733db1795a1694e17142695b694b" . + "a99fbf614ee9ae3f84814d6255ba4da3c327acee31cdbe64ae3626fe16f1623d" . + "457ac78ca45f46597c40bb18d73bace3d0beb79437feeb66f1f4233e2c7f4f5d" . + "e070d3b43fd1071f99b384fcc0fd3c5ad4bdb6e5f73a23d9347734ca08075553" . + . + "e10f735f702100d4571b004843dd8a6b7562d880934be9d075335f23aa6f7dcf" . + "a83e388e36f6c72dfcc43557d3d08264702c32f68d83608ec78362d39cad2685" . + "a37ff197b7eae203d41ba8a5220dc50d374b106b57aff2f952bc113e83000e94" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "a302509f6723c714895334defff4cf25054aaa402b8f8322c857f80fd58b0a8c" . + "e4db3ff4d72cf4e93033a05b24458da775d80ffe3ae9f3453e4eb2952df97814" . + "d05fd3cc8b8b0cb4638bdec8990ebdf5b2e60bf7a57d25b42364de6ee7d575d2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fa2eb2ca6dc6a932e93e2808f28929ca18303a3f396b6e92429a385c9bd5e944" . + "90cb771bbb302cb40356b0e95571d987c8ac4e7c42d8f588243d950ade87a774" . + "615a9db56f8588738db0236cee996613293f9be2bc3514e809e979bad6c25b30" . + "90260dbae8575851fe4a322623bf3623b14c5b1f624015c21d43cc301335af2a" . + "586d1bdeb5c78dddb93be5c0db1b06e3293ecfef0c9f91a19e8c733e2e52f27e" . + . + . + . + . + . + "d9ce36cc5f8b004f2d72b2da764409d97bbdd9077c762a71c8ac3c420761f65a" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "2cd3ee1382adf34b352f790584814c6042cf48cc688cd31e7b040aee03159895" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "2ea115fb7295ffbfbbffc3a5816e40e5f4f610d6dae91a1ce085d47a341d171f" . + "6865db571c2aaf4a2095835bc7233caa4039ba1483d66b124a35811255fd119a" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "95dc3c91a788690333a73da451e04515ec924a8697d8fe82c5d600407a2f269a" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "ddfdcdbc2144ed876d344fb5e7076bf64960e5db2c0888e6347b0005da3473e1" . + "265c873946f27d77e54500cd321cec22db45aa1e3a084f243b7a6da0c2bf7bac" . + "1518720c6a3e1e1762b39ada6bd9663c28e63fe0b8d1e40728fb8d89a4cbdc70" . + "fe8ecc5a976cc6327246adb126a98991abc6aa962aa23f039a29f281fbf5dcc7" . + "ddfdcdbc2144ed876d344fb5e7076bf64960e5db2c0888e6347b0005da3473e1" . + "cfa0e82cc6c8dc336f33b4b8123f5b99b40c171f0248282eeb2f6c4318edd774" . + "47fca8307d323e48c1d26b060fb235fed55ba8ec2981c45ed9167e786af6a1f3" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0250818508ac319359f3fd07ec4241708f06a99e99386d833eab3814aa4528a9" . + "34cc7291d98df39359d51ba76fb1b7e81dc9db7f975969e598340f6398d0af74" . + "3300866e7cf632375aba746630824088e938bd6dd3b78c033c07e8123de9cb46" . + "508c2d819bbcfc6e9e6a5b9fa84373689961b4eae523246e7c87dca8aee58329" . + "8aa917534d57418411db72a4baf641ab5054e5b228bb3a350b1178992cf79df9" . + "0560d97feb3c51d67cf0dd3fdb566d4210abd97d1bb4019a8bc78865723d7ee6" . + "a72a283691bc22b066e67ff05918bfb1c2b9fb74f0213ff038d108b4933ffd09" . + "7d3f52118e067538ea5dac5acd509d8194b2b1b968d778d172d1d0a7b9d20c52" . + "984ba8a72f368658fc26d2a7e57909b65936ffd54bf30749bc991cd6f6915fd9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "e2c776ec520b4b1c27780238a26d6fdbd082939c651464e4688fc91aa70f3322" . + "279ea0d55b0ef83097568f7f0ba4e9e9ae5f939ebb827a7f1605d1f307dd5c8f" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "3d15f20a544fa086574c7125227bd32f2a4c93f9278d6142eae8c8f26b95079b" . + "311f2c7797fb6fb8ee071f7bc930bb23d1aa21e171a63374eed06f49a737aa60" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "67259976e3ce1c595e57905c95d27260de1dce9771553e1f04919610702a944d" . + "41ffafd874e4439e4d4b98104b4c8a44da02263e2f2a06a42a84d8a3454d7bc1" . + "a26a0575172da0ce41e6a69e115d18c4547810ce00d149cd1d2293bf0fbcd990" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d61c0063feb992ef2ce0631b4cf5edc0159a4e3ec78cd7ea1fce69c171c4830d" . + "123f6af71ff89f7037ebc3a3a9aa35e09ca4451b518422f3e6597f36e12591ee" . + "d6b2a262748cb4bc88707ec78e94e853fc85b341af781b9636edb5c85bf41cc6" . + "6e6db53cc9f418d58888a2a855db3e802a4e6b612620a1a3f2e59683e8a837fb" . + "ecc34ee94d07f542e1b6df9cefa0a2862e11096dd76100c632e6405d0da38d69" . + "0cb8939ef203be708c579688c3ab914eec44bf9648bda378b66096aff950bb85" . + "36450799fe347f46fcd7b930fa22e1842b9c3b9511b5f201d05b8f49713decb6" . + "f904791036a76ee0b385f559e5aceb47882fda4fcb03a63292336088268bb1c8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "6436857a1cf8c7168d50f29bef0d5f86400b3140419388fcf3526fd563875ade" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "ca6ed1fed65a1bd721fbe93d846fb4f88a766812d7748f34df34313d5a298a03" . + "2128a43ddabd72ed0fb955ec3195906c6fe24f070883f860ae22228a1519b91e" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "3338dd192b29bcbd0df4801b017cf7ecdc07b31c57497e99d464e3bf88fb2f8d" . + "4cdb0ff695be5c165ade213949a61aa0f3cfd18db2f0c33915df486ef80e5f66" . + "874c72a7d3c6284a3f22727568bfc533f44bb747a1946a1138b0f5335be46ddf" . + "a6d4dc422262ff37ac1ee52f1c12f2da7acd5d309b1eb33efe8f7f23ca5e8c04" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5971288e13ad40b9cc029f91d3f0be0238f0835a22ad9aaefe3a2ba777b7287f" . + "5971288e13ad40b9cc029f91d3f0be0238f0835a22ad9aaefe3a2ba777b7287f" . + "47723cf8489982abdf0fbc3d84c35626cf89c7effa8926039333d189ec7e0474" . + "fdc745822dfd2ef65ab40aeca6ec5e0385da0a61e6de20086e4c11d8c4960d9e" . + "47777654727dff0f1efbaf32f476d976a5f18151656870b2489515e5c6ca0694" . + "ad91c0d2a87bb68da62cae6eaa08cff0b16fc967915cf9074bc5c14f3a00552b" . + "9524ed523ac75273b2a506958b3aea0d6b14fd385369dd2b6af78f150c43144c" . + "45f943353ed1f3420e8a1f87ee1bcfe657b8657181ce07794798da685d9e5884" . + "044ad05226d20a6fd0b3e86aae8a1f95170fdc303ac6e9f48592c5fe5a817247" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "78cedd80b456f399a427f59d8fb6c1b4fa1126d0d5fd855a11c4b7c70ffd3c1b" . + "5532f73bf444867b67b49c2d1bef65f07ba7a126f40fbabfc5d3f4c651f1c9da" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7607ca48c4fbe487b302d10b263fa3ae392cd65ef866343ffba1b749a3d3629b" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "94c8357ef4daab21ae7d3b5df76be68715adf720a23d305bbd667e2c83506ebf" . + "1123552c8a98822caceb258d437424329c01f5b1bb47bf23314b5e828fe229f2" . + "cc3ab9f34ccc79951d61bfffaebc79cfdec7cf9c84575f45db495e235cdadc00" . + "7309066d76a422dede360d680b64ac567d747f7f0a3e8130c35281ac2d3b7b65" . + . + . + . + . + . + . + . + . + . + . + . + "b45b20ef215e507e4cc94dd0da8ddddc8c85cf612999a5e27cc490ddf9545b09" . + "cef6dd851fb19f2219c183b3e22094f9400260dc4a0752f0e20dce3171fe129d" . + "33194de76afd36dc77d8614c7e8e83633b31ea97272d9fd732b7bca374c75066" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "63e9db32019de69bf3bebc74b313b600f37da03b8ac3253c593793ac30e11ed3" . + "a0697221a7110ea9df36226ec90988ee8bf47a849da967a1796046dddd263ceb" . + "52395b90c79a3a9fb0df47d17b3b8db880fbb8ffaa6be7ce345766405c93ef28" . + "67ff35380e0d906c6ba0a786654ca16cad8e3ea4b0538bdb3d5ed207ebfecada" . + "e921afb99dcf9f0ed15a1941f87bfb04b971bc5009f4cb96398e002aa6e3f725" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0af0a8d3fbbf2e7bc3d07864cdccd2573c8ca17c7880c178b3bde3462c16ccf2" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "a532568377fe79b72d07c9c4e7e4f290e99b7b33994b532fad7c12fd8a91e856" . + "4c6f1f835c8720ced75d09e33596560dbe495cc27570ca7e24e2adfa46693265" . + "ec9625d5cbbf3ff69e97b528e1fc17483a25d1df8dcfdd5145db42361076c827" . + "ce5cdc507e34e47a86110f11b9e2bedc4c178f5cc2c7bd47a9723c4ef5ac002e" . + "b5bd47b26b071a084e26cde25bebec268e60f16296de379089419fc0942723a9" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "efab03e1a6e3f66404b39442c6d44092770b4253408a8b24ddcf9cb4997dd9af" . + "a1559bc690b71a13b01c4f12232ed3eaf0436149be516bebe4375379080c73bc" . + "af16272ac8a9f4b197bf08d38982e78e35f1d58328c8b922955a4efac6db13f9" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "df3bb7dbb61da233bf60cb506c2b8fef49d2f19519981b2cc6d9bc5393b01784" . + "df3bb7dbb61da233bf60cb506c2b8fef49d2f19519981b2cc6d9bc5393b01784" . + "6297397692e3bdf90d61f3086f261a93d1afb1c5d0c116f440e40a6a64c4f533" . + "e07ac5b72eaa8948418263e0da7e9b3782d401d73431d659c2aeed79e5230a82" . + "df14cb726841114063be64abbd4b4b621179e566f16e565f2ddb73e3df0d4dc5" . + "115f59891eefdaf6676ab19cc6ec9b77579f792f0781842c7407cbea186a89c7" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f8b1599dc11091b061841a04fb607b1dfd3375d761fe3f198575924278dff640" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "07af8484ed15ed4d077c390fb95387f9f97201a15e70e0d91b67bf2bd3b754b3" . + "01cfb7a4883da4d3fbd164b40533273ea11e8a5abcb1fa292b80ad5062cfa631" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "60946e5d73a63cbb987f3cd3f5bf6023fdbcd731c4714034f7c5f5d28108410e" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "d3d22675132df71870c9c5d81968682440505d2091c66d19503550ad36bec510" . + "8e54d2467abec7c721614165b7fdc372b300629d60a694e577778aaccca15a94" . + "b9bf7319f5d5ad2b5fb6006a99b7410e8fb0f4e89dacb10b1ee17812dd6dc2a9" . + "7131d3cf4e55afad35a0dcc5d0d96d4aab2b966ccd99fa07beff22e82f7de5d9" . + "00b622a0b7bf768e82cc140ed074aaaf4752fec749005be0d454c7cbf467711e" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "8e54d2467abec7c721614165b7fdc372b300629d60a694e577778aaccca15a94" . + "421080a51ed7619dac0485c5e179f0b9b16c7a67910d2c3aeec3238bb4f6a362" . + "5030f9fed3e01903eaf8b65c6482fb2c439d5df6bc9206ade64036fd38248cb1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "119173673bf3410d82f6e07ee5a124bbaa3421fbb561839c86bcb964efe2a9c7" . + "119173673bf3410d82f6e07ee5a124bbaa3421fbb561839c86bcb964efe2a9c7" . + "a464deaac0cc0618733eab1aa6cf264da1fd406c570b43d7494ec14f3c022932" . + "48c805f745616238c251961a1c012913328517b5b745de2f56db10fdb1fa9292" . + "d939c193095f48670966c88d1aa1934050afa08ecb6cfe40ad3a2cdf58a73254" . + "2b872e5929f29aa7cc6ba9ec587e168f00a50cfe5fea5e7c01a4ecff849f6398" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "226d77afb0bce3e843b81718ecf62ca1542e8c2f7255fa073e4a0da706ccb048" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "39fe37bbb9eb775d751c0ce7e4cd4b18a447062dd8f6d31abffbecb60604f328" . + "9ece66b1ff627ebff782a3e4ffe4e1f2076906771baac31bb100ef1987eb3865" . + "2001071b904b6ce6cd639b7d09018d748aed96175d82641d6c86e0b5ae0a7d7b" . + "0f7b124798fb0609521a103893a44b30cfe258a46de22dab6b19c3f58adbd461" . + "90df63f283230b227e677a6f542bfc9b7bc08a0ab676c989190b91cd7fbf78f4" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9ece66b1ff627ebff782a3e4ffe4e1f2076906771baac31bb100ef1987eb3865" . + "3d3063100ad1bc719f24455a6a5d7130a2ca1db0365054753a4b8b14203aaf1b" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a248d4841357a277da0a39087fb46e99ddc5aefafc3e47dfcdab067f041c9808" . + "a248d4841357a277da0a39087fb46e99ddc5aefafc3e47dfcdab067f041c9808" . + "0dfb3fbc3b9d309827789a04bab9557d5a15168db5a56acfef28922dac4103c2" . + "71577ac488128cb5e0ba6f216919776a2e7bcd86d73640bc5f326512da51a5d0" . + "85483c03fe9f140392121288139bbd360dd8c68c9b32b6f57d53eeb6e3e85b06" . + "5e3b9e8aa1e4d212d19511779c872676819d8c0e5d4e943bb4c3854026e95a01" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "4390e179dbbbeb3162c4f75a34fbb99aa27ec37143c34778c0aae6805107c89a" . + "25d98300d7d56e9b6909f4d245fd0705bd7a0eb58b3e87e52d02b3d5fa69e4da" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "20784cd296552251d68497981b3f633c4a22d45c48e82ea2f326be9623d7161c" . + "0e52ad3532ea3e30be7c92892e2ebb8f8c59c7c3c2b3f45613eb60ad211d69bb" . + "3b1b095368f34b815c58ce173b4ca7db3b5ccedb1924e218c55a23bcd0955bbe" . + "8d4077e7a697866d311c0c1c6766720cb6b6e91d1a53a53d818fb23f7dcff194" . + "1b8cf2ba37092a442491ed70e22da1ed06a2f7c13ca44b279bcef042db32dcdc" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "1b978e1dd40e60d53a8228bcc522d6b3809af767ccdfe7ca81590e5aa2b5a1e0" . + "dfd826e8c80236c1b8a8aba8d26cfb0f0e0b0c4023e9cf6d4fa5f6d24ebff616" . + "1946f08f7ae8ade3318d9419109966c8822bbfb7a2342db58e82fe634310b5f1" . + "51648db51d77b8c0c379b77dee2d7108da4baadf89ae31f2bd158e4f4ba99658" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "08b4a3e25e94a3c9cfc21a8f8dc6dac2a3ce44d0c316896082d290e58e1ca604" . + "08b4a3e25e94a3c9cfc21a8f8dc6dac2a3ce44d0c316896082d290e58e1ca604" . + "82303950736d869108968e6ce28687787fcb51f9c2dc83373e99d4d7b332585b" . + "ee9f93c3917777f918487ca2d68dd7bd7e8e3d9b3e3bbe785097bf9219729199" . + "de274fd7fe15331b2f5ef84b846a3c017b5851d6e7ec33bafa1092fa71debc44" . + "d916e4a1ff0bab54951acb62cd271f2b7e9e39587cbb8d6446ba2ac0dd214445" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "7377bd5e5d7cbf20164968f5ce20bd7338176f818d7e4ff9da4ff980ee0c894d" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + . + . + . + . + . + . + "b878334b38a7adf1631f4d310c12669da262372baf89d23400dc379c1c060c95" . + "5eee342ad4e9920e0607162cae6a21b003f84fa8ec42c06a4b367bae42a2e8ff" . + "5a6f53d73143c311a572ae507f0400d1c83e7c159a7655ccf12574b003a8591b" . + "3110ae1741e2bcb5262e8e1cc41097e5eeaa3c6c5757dfc7b859c51eea6cf9fa" . + "e79d0acd401050479d552532f4a5d3cb4845e569f8716698d56719a29c703df2" . + "21c1f9da831449f7b0b7b6d76539c5a0b298e7836ece46f6325f38fdc5dc6333" . + "a9013d2986440a9a8fdb86304028def79e6356e99b725e81f06445864396de25" . + "4be133deae015f8f2ac45b1c4950d873bdd77de240761b9e4e1bc4e4e6fbb8aa" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "b2339ef25ae1877539170d576dfae000bd2fe432bc1eefc09d2df7c6d47844e1" . + "b653cfff6eb5f71c4e1e23083c74051fd78d7d08a2aa55cb115f0a6749002764" . + "c3723ed2fd722d4530afd788775d7bd5ab814d5b93218c104c39139e43774cb2" . + "2e8a44880f74ed0daa7ae5caec2de4adc9f52f943aefe540f8311c0a1f0d3e30" . + "11f89b0ade7a783b6c36620ec492e3655dc74133c896930705a784671638303b" . + "893b226ffe47dca32ae93815dcb40accb648d436e3be737da6e6e3898a03df98" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "3e52311c4deb2ee874defcd44527c24ae11cad12dc773b315113f42a84320847" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7749dcf3cd93fec94d249035948f587621c7f9f984e86f242c297c0e1041119d" . + "716139f37a4abe3c7835e04c484f5a4bb67d173b5e042d2ed6622439792cdef7" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "19197bae12de5370222be1e50d35d9a90137a621b1fe17ed48fab158702f5475" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "52a076d76c5c3410107782a977d3bf9545029428d1f1477129116e1db113e67b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "55d2eae6752900dec33c44e88f5efc420b58d5b2636336a1d538482f10b751c1" . + "40e03f9d3b2095587d1543de272383808549d002f702198b930e4ef332d638cf" . + "5480f928dd1d3b50fbaaca4ae79ae975e0daceb9508e186308f4c22c666d22b6" . + "c47769cbba4d656d81f3d602848a150ae021d58c2083709aef7f5bc180240bb0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "d7208a04445b83006adeeec617e58a4da8176eb176f9fa4d46a3fc8496774679" . + "9f92d56c33a99e4f29271c1c8ddf2e4005426a4e73635f84a783186fbae9bd3f" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "a6211b8e4463bbe7cc1d2088d0f24290271cf513662cca78e29b42c402f2410d" . + "47195fe9e065fb242bd2294f42a63c74ae430cb69a96ed0a2dad8fccea10d5e0" . + "1b2f5ba84a92bc301fc1b9f40d9e2fd0185df022c41276e54c0d2ce8b2a44585" . + "2c9a43420be719dcafc65566ba685312585030c07573598fe660e902d37888da" . + "1ef08035f4e1cbf73aa1a78362d43a6acd87e871b965a81fc527626755e5ad8e" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f7f3aa3dcc85a93d457f3b490560f69efa602bc755c23b98d148de7ae335dd27" . + "2b8020263b53202709fe0909ab57c51981e1f3ebe4b2df71c105a2db9090802f" . + "fe1f4acc9beb842be0a81dfefa11e651db54484b387f7eef65ad5a52913a3954" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8ccb60dde6ba77dddcf9a5ee5b20bf81d73da45fc296c5524f9611778143576c" . + "3e58a1c2cdc7b47e231c06531f3dcfedbcbb80a16be10b4eddcc846998ed237d" . + "51bcdafcf433202a4fe2b08c05ed47efb06b95c7bad29d57912382ee8bd2e65b" . + "64cf3cb77b39f68dfcb381bf84954b0504ca94d987440368cb41df86ecf0f1e7" . + "84d0632513aed31df1726f1ac7177faca2475c4f279f171acf925483d9921d49" . + "b0356bf7038fdc3306291768131483c049d1f5d3aecbc663e307f3ab31be9718" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "2d119a58486c7ef168b7d7d8af06189a2ee08ffd3e71549bba7a0f09cdea478b" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "f84fb1749c760a7ad50975b40f4c24e9c21f487476fcd4f09e33e93183f6309c" . + "133fe37ba5bbb289bcd9eb1ad9b42ce02608c97d84ebf7358621714423f1c23a" . + "cd231cb5edcc72e05c9d73f0cbd5541590026040f6b19e95f84648478688ecd3" . + "1bf2c9a9ac509db4b66b33236df0fe223b2a1484e6389ba0d096a9d389d6420d" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "78e68b7896c2b3e0d90de39ea7bcee9c509b467a9232bca1229aa58b95eeb6e1" . + "ed5ff45864eb025acca934bd1eaf6113d79c8a4d4b4f85df137f2abe01b6a6c6" . + "f8f225ffb1ee898c7755e509023eb2ccff5b4beed048a1bea1bf0103e8af415c" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "57762b6634a714c90d51f63b2d7053e24af786033e2797c080e219a5753e2d5e" . + "57762b6634a714c90d51f63b2d7053e24af786033e2797c080e219a5753e2d5e" . + "5a5a9658f4301fad791b3e1fc3e5dd73f37a2019c72adbea75e5838d0cf7e1c2" . + "94c5cb8edd8391325c28594332a801a3e005648decadd889c0e9a624bde942bb" . + "e3af0c5dd8d4e620f244bbfe326b75acdf6b66b3714b3c021572084c2465e661" . + . + "fac3e7c2e77865db5ee32e139fea1cb4bf1dd561ce98c53208fbf90f5f9ad760" . + "6a2a5afdb1d820c83720c9b614d9fedbdaaaeaa52dbf87475f16473fc6d34c3d" . + "5bf6e3be012784687a5cb18a3afdde5a4fc6e85f7d05bde3ff13bc689236e801" . + "b8202b1f7f1852f24df6b47116ca7f45fdaaa87bf0ba7e4481d188de3be6ec4a" . + . + "f43d830f0ee6991f24ab9c5479eda3ba4a8ec51f1c60aed1b8a19751eb7da7d1" . + "bcb7181503232572ef558b0280c6089ac70bdb199352e6396e71bbaea79db904" . + "75ad31b0831e1ded16ac12fa061dc1c1b7682e598ab901ece4e6c16eaeeeed84" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1bedd7be8908832fb0b16d33dda5aececc20100a930598745c0132abe47ebc02" . + "1bedd7be8908832fb0b16d33dda5aececc20100a930598745c0132abe47ebc02" . + "d16da8c24cf08a1c970d1e9f5d00fe82ea79bdc6201f79791035f1649ee7ec16" . + "24dc62c1c43668cae7cdf779e331643366d7bb64d4aab7a8e9f48903ba355242" . + "8637aa096bfbb235c5130dec2eeea32f221fcbe1da826121c7384d4f821b5db6" . + "cef40aeaee5fc930b89717e475f8e8f6f2c9e8dd3a1b75bf72e7b8f5817b1392" . + "cc6121ed26c63fcc35811b7e64a69a98e0cd7c856ccc5bfdfdf8952d001611de" . + "acdf3282a2dfe5d4a72d9371ca45a364f5131acd669b538b5d35f4fe1f550b56" . + "5ae6817002f72ed9ac767ab87f6f1f96f477b56f5045dfe467e47ac95d223886" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "1d0c0bf08999fc1e00d3b4781ec2f0a85439141b782800378d29ce628208182c" . + "195977b22fb25485b2c1ed9ee0a1671520eb01a2a0fe897467981110d2464325" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "2a1cbadd15c3a26098b8cc13c73dc0305f518fbc8075754da96633497efea2e6" . + "b310473c53fb4d6585197719a006e7b88d48df8c054b4b5548696965cdc97028" . + "4fdd8ae1f952b8be4229343b109b3a1bed9d55235a2d0a55d607efd4561fd7ac" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "b310473c53fb4d6585197719a006e7b88d48df8c054b4b5548696965cdc97028" . + "84289e95037e6f746c8604e850bdf57ed138883bb5040c40b942f65c1c4c1055" . + "80a8aaa9308052e3beb0473becc1603b9aa7afb7871a6785480cb9d5951344d0" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fce013142bc0d78d1fe3509dfa2014a878083d5c4e3409db7469e7f25bc8db88" . + "fce013142bc0d78d1fe3509dfa2014a878083d5c4e3409db7469e7f25bc8db88" . + "112ebbe930d8923b57cfdd2c649aa194a403ca6db0561c7d4bf69452cc4a4e20" . + "b4170977b297b2af438a9ad72a2837ba342d7c1a33728a1637d9d2790ef2358f" . + "f16c35917363e51c1a86b9912b0a1a916536778f452f0f7e1b545aeaa5715bd0" . + "882eb053356533d6eb858ae4ff475c127775a6d2035b18b40f20d0095ee6422d" . + "f53da32d39f3438b1e7d53fb981c0762a51a8a5ffcb99f0713dce38924ba4c50" . + "bf74c88fd55b31d3212cf85405693be9c91ff607fa7afbd9f486f5ff292adf59" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "fae82cfc0410f56f96df4684e523695904c9e78bc525f4588ab6714682758ce6" . + "b91aeba7277f527017380ea59be8456550429d7f14b4aad7c4ed0469c7dbe2c0" . + "30f95b068683552aa6f81cf9f7b4bcd6dbbb9d4d5af982421db5e775b1f27455" . + "420b1d8493dce3681d5566a40d783e2e8c317038b90c17de62be46f4eb47b270" . + . + "e9a8fa0601d082d6c70cd7f8e24c29fef9d5e0ad662fca41cdb7a967e9052108" . + "9c607a976668e7cef55f7d850e486dd2f691b5fa0f9d3e047f5b5140d44c53c4" . + "8acee96aabe4437462e5bc05fe9843128ea2c14c2e891013a0eac794b4d772a1" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d58517ec07da7d562d06f5812dde8b1cfa0d7f73b618d6016bb9f6e741c6792" . + "6d58517ec07da7d562d06f5812dde8b1cfa0d7f73b618d6016bb9f6e741c6792" . + "38236c74976ffcf0390da249841790af22ed339bd55ffcbebe10294b7f5c46c0" . + "40f8b5c1d1f5249c052502eb2d37f5b67ef60cb66f1b726163c40e1f150b7abc" . + "8d5cab96ffafafe69853e777b7c3b7dfcc047a9dcfe5a55c3b3ce9d1b49ec72c" . + "973c3a2bc980adbe411371e8fef18db01ef073b98531f7d70029314374a36b26" . + "39ac1984504b87d61e560e048d682d89cb73996a44559424603e98d210085b67" . + "9ef24abd24de8a83cc1c8d989fc4a5372a75da48d438b9878f07dc3d75380ba1" . + "7154081fbf9eafded3b6a030ac3308be2a633d65efca149a769bf2268f546fbd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "dd84392f47438504715047ba26ae7f73b8438845c8ed8ba82b4aef6db044e9ca" . + "8e43d4590b3a669e228719f2edfaf8f5abd9f298c9604727cc35995d443cd067" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + . + "b0cb1856ef8bf91dd1b167032f3e4ab0b2acf7ca200b686555eae57ded7b7ea2" . + "1b8036810425d99a72d427540794deb0b925218ae6c0ecd40c558143cd39ce8b" . + "01f68febb3c3bab9f5039eab394030110f83fdfa1e38412c74e4b8144d708828" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a4710c7fb71a83c2248ebf041937dd99c030bc089ae4df643406fca8b1f36939" . + "0b2b835b2a384737263c5de422d337cf70f0346f58d2bbe3e38366217bf28612" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "7a6f02d59049f221ef6264ef9e335dd8d1ef19f1f8f4d39809687ea19aa63558" . + "58c8a74d5e500c86d063ab086c6a72d68a64b11eb69dab2090f0c4b846c4b60e" . + "a03e1883d279a2503ea62aab575f643b1c1261b93772725a7509bd5160931f3d" . + "0948c1851bbc149f96239962bcc8db38cd074f820aaab3bae8bbe86fcefbafc9" . + "dfefe49a1d5403117cc7f7e0c24ebe7b47c7c4d5ba89e01714262156912099ef" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "91ee78890ff5fea7b387def47785f28ce571795584da8dccf7c46b07a40862a4" . + "f1ef336e3776f74882ba46001c1edeb5b55818551d77e197320a48b9dc8db436" . + "c7b2221cd6b9ad0d7e272a8e6b6dd2e6ff85c1baffd92e2f2516046c8dcc5200" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3fb4d66f30418c58d835211af338739cc61ebb6d51aefce43b76a201301bccd5" . + "45cc6463dd19cc5e51670b10f4592dd32e958533a2da0beef4ae70563befe49d" . + "ef0bd3518cd1cfc91cdb1caa08371baba6dd53f11af05c3cc52dbbfe5cd9a5e7" . + "a566917ce8bfe4b83468d7d31841fb2e424927a00d4d91cb69b835ec3cfe2150" . + "8c461dbc3aceae48e81a902955981706f415387e0914d93b076a7c462c43f222" . + "9b69d60fae9645105b108c19b821fb81fdab9a8fd91710e0271eba9d2a14a5ad" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "ac4b992725befd85a5e710244384ad4a20f901a2258a2b2649c2c1ba2f7b2612" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "e31dfa6b0191a12d4ec671501ddab11e132293bfc4ed9f421787f5b2167b40a4" . + "ac78c3e5217d724ef7c7039959c758f025d76a32be96274676f307302b55dbfd" . + "009b4d9e2fdf19adc2f6dca6bab779e55ee6de32111e60e170c824367297802a" . + "d964759e32499d69d4aa476059fa9c55e06259ce97b33d0001f8b6ff339c5c15" . + . + . + "9f78a59aba3cff1cd69895184568d7768677f6b74263d688343c0d8e77c2cb7a" . + "9759458a5f5d59407c35d992f48d06aeb1b7d4c25a1c3984da424065c0fab8f6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7abbdf7ef4a5a736c70061d8f02176984818e256d0ca5735407a6617450feb10" . + "7abbdf7ef4a5a736c70061d8f02176984818e256d0ca5735407a6617450feb10" . + "0fcc19c9f32b7d0ad5220c6637efaf430c6a792e84685925b0f62931e0341aaf" . + "d2da3b5b9650e82f4d751a9ceee93c4a7b2ff57843b0a8690e1c17b3b9a10777" . + "a10f5f1f54210b6547603efa53d4e611ffaa44a397d9a2e98b0122233166d718" . + "f402eabfb24842c8fb9fd8788d53d238e45e3eccc3646f385c9637f7ab582c7c" . + "0da3d046f0180bf2b4fa948f43dcc20702e0e8c493fa092900eb8d67625a65ac" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "13bae16d2575215f76703c1029c5eeac17abd4a6c5a9a3574bd559c8f62736f0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "6fa5a6c5173208873be88a18828761e84e0b6fab2ff58190d3a9ee39374a902a" . + "066d7952db709062dd902446b663523a6a7a4ac0dded61294bf98ef5a31ecc71" . + "8c8333c0d1b6e834457650dacac6c4f94b215c3ba963660cb38a03dfb3f93be4" . + "463418b8aa7201ca1a6883a6452ac9a32779cc072688b29e002bced50e6db04c" . + "6592350206fd2a907d36271b044d3f6af1b7681164ac680750057a0c78ade9da" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "066d7952db709062dd902446b663523a6a7a4ac0dded61294bf98ef5a31ecc71" . + "ee310c5d4139343c4ad737ead9cf55c7f20b691a52baeff4d5ba2fcb82c70d66" . + "423f6e66ba6188dc3dea317d012beac0374938ebd3490c9fa8f38a87dbf252b9" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7287159112003d31cec5d310248da2e7e63fa0acd2610ea58a5d0b5eff244f9b" . + "7287159112003d31cec5d310248da2e7e63fa0acd2610ea58a5d0b5eff244f9b" . + "616e126bc5afc43318514b81e24b9f4dd61e91226ed61a4653af107000a544c2" . + "66561cbd7a009de74ab556f90cda9eec8c4e47c271bd30f2762b3c2c35032531" . + "ad3b5adc70e403b1045dd2919a08d13b82042c311c83cd01b6cc2d020e2df356" . + "9ed7f5e9145da575956cba405066a6764af438e0b336404090e2fe68b420e526" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "1d531cf0fff651837d8a59cb8e8b45c4ef3d5e500f87c7f6133a04d1a48b1af3" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "8a0e0e511f43990a5ae047e129d49e77463d3c137706947632e57cc1368cddc7" . + "88333e969135b76a3fee642eaaff837afee7df4c5417f7dfcec3a2b1559be9dc" . + "f464cd14fc43c86fde02e2120e225c8a4397b766c48dc18a94033791466f0255" . + "91e6ed0e7e8061b3d8df981205a3652a4ea5e7eddd9e95d5690d1f62385fec79" . + . + . + . + "bd919afb651128fae1821f9c4e9ea1aac8d4ebd4b1c1b366145e4f845911b5cf" . + "28699a71fdd9b724db773def7a3481aea2542132a1d8bac63c3f3230c28647ad" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "91e30daac544c256026d2cd067ad3613187d1e3d57434755dfd5221e2eb037e7" . + "91e30daac544c256026d2cd067ad3613187d1e3d57434755dfd5221e2eb037e7" . + "66764329ae8331bfbc1666fae4f69b1dd72f0377e1e5bdd20df0c8c16e7aca31" . + "93b0a2fd91e153195b5ce57d55176ab1ae308addf9690537c160cb9012ee56f5" . + "c322627e24f2af9e0644ccc27d48c5bf29947da02b80c24e4d7209c1f56cac83" . + "80da534c4b5803c1e5c49f5ed0ef6ebf31e61dffa766106e95ee27bb85d038fa" . + "3e1fc7fbb39a096c506a6ebf72c26ebeaa58ce74cf0eb5167aef18c6eb0b8a50" . + "512bfd10bab01f7d1551e22b4240dd327bded3ffe218b18722376d6ee68ccbb4" . + "72cde96c43dc777084ecfa2a41adb078ac4abdee999c262e11b06111eb011901" . + "075cc53d10aa6318604a81acb066a746c97bfaa9f6adb514578d8e8562657c0f" . + "848eebea5815bff108607f506ac1a9c1b4a3af4e572cdfde345a7c2d614a62bb" . + "f7fe7145446941842a77185d85ae5634de806ae6b07751c63ef757463c4225e4" . + "1cac2ddee42dff7502d58e9b97fd4c5ffade2fa0d4f622f875cc0099ef76310d" . + "8583d5b90cb606d7895a149b3fa0bd15c90ddb01dddaa378c68658ad013c8554" . + "119faef82d29c3add385b6c747dcd61ba51caa5fd983bdd6cbf3d1f30269d96e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "9f537e6fb799f427300e3ece16ec1d55122196793af5ded034868d30c0af73ec" . + "b5cc84a32d5895a7511ebd8d044b0ec8050f411a846a810526d871fcb1917bf7" . + "c12ad3bbeae794e523a237ae16a1380cb28284ecd843614e3c598685387c538e" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "c1e108fd07a7bfeaea3daa948909a1e0752cb5d8f52d4a52cef731eeac583ed7" . + "242726d906eeac20f586d4595e6bfac264412acfea5128004c79df678ce560f8" . + "edb4f5852ed9da4304ad5ada3788272b99f1908218f0f9268e1f15ea411e3762" . + "b7f4bfca772880e624923a772076b602b0d0abe5c161c5d2e1208144c0715f9c" . + "0f94ad6c63a736281571d8b35e518e3e4816e46e9a89238e2cf4152b1698425b" . + "a271944e368257088fe5fabac860d7e43d7762d145b986b46cd8aa944c116214" . + "bfe699295173c4d00ac47d27f984f619d0245e6a1ebac560cc922ac08004a7f1" . + "8538a445f8c23aa21d59affdf37e7a6bca31c075e43f47b48e1fe38be6374083" . + "709baffb575ec96b68131613a7b547ce67e64554da074f952dc5ac4dead41a2b" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + . + "06c855770f62dd8b82f97220b7b8ac4d6560e0311d91863e10ff431be0f5c2d9" . + "73a34f6bd51f291cbb7e3372d32e23678df58590101da7ae793249f5b4897ea0" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "dd9ca2c1fe6b46793a6df19419a7851a78ed8a7d9bb76704cb32d30da1cbe38a" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "d297a85e109d2b5c154ee0a05c762938bd84cf53d7628885c5717bc4be8305a4" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a7d6a3e3ae48f3909036b6deedcb12496cbfcd129684e8c6878cce8c8865f0a4" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "6b0d1ae380652ca416a029bf96d540960b56c184d4ccce204ef76a496f8c75c2" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "c12ad3bbeae794e523a237ae16a1380cb28284ecd843614e3c598685387c538e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "fa8d9f2ad69b70b760496a1ad37867ecf284176335cbdf64313aa500b97b8abb" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "21207e2eb7b5ca1b7b0f72f3865c7d1cf703c798d612fcd2186550f16a2888af" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "6f9663f410e1103efb810fc7ea8ca1ec268ba399257cfb91fa9b19ddee5ec246" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "dee54de463db9b0dce5c553c653a99f3dc316b2b2d7b7f56da5e5bb447459d44" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "c045a555fd51abe130a8f94518bd15491ba1c5b2bb652ba03707cde63dc072da" . + "52957c3fd2c214018371d7420ca17dcba6b88921841f0d43bd2f9546b979c021" . + "495ea9a6b592b1e98afafe09ac71b9e11112aca42d7e0f56e1a5d1a0957081fb" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + . + . + "44058d75dffeabb8840bcdb8c6b80d6142f6e68a68b5dd098870c0d05a4033c8" . + "8c66c6bc3f4a88fea727b747f1e95dd28dc994d4dd618f24046ad4eb067171a9" . + "9edcb84e7cbff537fde4721484853399330460e23e6a86d5e1aff7892de5175c" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "260e5a8ca4032b5d916cb8040c257096d2bdfedc976aeaeb80aa338fe20afb1f" . + "4a673e34f4b60e20305dd081358a3b85b106e465201a44c2bd82a5dcbbdf1434" . + "2c21346c3718992111b26ab5ec51a6607dfaf0fd1a9bbda85948001c35e91727" . + "6f7a3d36963988d863e261ae211374a58c24d470e2e8bbffc0ad593f7a24963e" . + . + "320448dbca835a75dffa9a332627d67696ec23801c0089d7dc295d37585b413d" . + "c7d1ea52d5ba69ac2e5149e1b886318e3dbccf1b73c5cd2b9c0528a033e4103d" . + "976580da84964e711737301ab51410705a48bf7efa24fd2bce06e4f55f6de412" . + "a49869fa5dd88235578f0a5c65bfc1abf1831222c7a939e54b40354adcf88127" . + "80f84969df614afe51f568ea55cb2c63b2d2fded375528f1359e4658b4c8465f" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c7d1ea52d5ba69ac2e5149e1b886318e3dbccf1b73c5cd2b9c0528a033e4103d" . + "9928ff73c9cc6c94e8eef6fa643da0b26367f1a9df615d2af52ac6d91e8cf076" . + "3bbe71f60356e7c417862638372c0b76c0d874e11c77dec4cbfbd86803d97eff" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "78d9cfcc2f6e91b186e7c4302cc43627ce776792eee491131d226f3f91261723" . + "78d9cfcc2f6e91b186e7c4302cc43627ce776792eee491131d226f3f91261723" . + "dc2f00df510feaa9b7867e0d533eba7b554cdbae91d599e99140c25d8e7fd76a" . + "22339d8caed5bade1025bac66e6fc3dbb9953ba72cdea82b05bca25fc532e0ca" . + "ab9a8ea049179f215691bf84ad9597129472ad6d063ec7ec56e67159e431d6a3" . + "8a9f5648bf1264a6d3acc882ae1e2c1572017455e908b41e304fcb4132b233c8" . + "a6f32e2cf38c1928ad995ae5759f8cb4c14b2e1b6752f35806db8d4835488b18" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "109ed974262aff50bba883e8035a7bd54dd42f5b77ce990ecced1ea13e95da79" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "ec4eb9fe7e67f28f4a592cf043b2945a052120f0ef7fc29e85ebbf13b8de7f26" . + "6bec7a48d5083afc12489d327cf39b1ac33a9eae32fad0badc6d433010b732e0" . + "35b5799f3914a48026f7365c2beda06c0b0ac5f5b88784a64652da30b704b98c" . + "984a55271d780bfc8785f899f79cdb539883ddf63779d68a48ef5f8858db6eb8" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "24ba752bc4c45e628e9aa75bce585ac5d85ded158f19d887282b8f16563ebce9" . + "f79c5b0bec36a5d49157e64fae10ec1d86c8d2edd0a3ebbe6ac9639b152afbe7" . + "dbae9e5a636d2a87fe44f6e01118cf2b64053ceea260ff4b65325d9700df08bf" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "56ed90cfa98983eca67b7bf7565a412418847a5a5975059fb3dec59314cedece" . + "d7ee7d9f3c0aec8a2ec33c651d3a3e836aec512b3780d503501b1366f37077b7" . + "17b51194b3ffb93ef854ed393e2469c3f9aade6db89752032f42dc4123dbe254" . + "ab2fad38bb0f1e03c3c579b8b2d0dc38cc883ef2fcfe0d312f87cf626dad4fda" . + "7028dcfa38ee4af7a446ac9239fd0aac8ee55e9a91dd3e7a9e6dc8096bdbf705" . + "fc72df3019db5d980c509439d61447f606dc069131d4652cee2615162c72da4d" . + "977615f80d7330ed465df763a6089df71f387f51451ee4e3d93dfa0c5eb1977f" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "326bd37bedfc1f59a18c645231820e07eb77d78aa390c2e5406f5526d728341d" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "ce9732feba18d1c0f78f5cbc4aa87b242413c1cc3b0ccc8bfdd95071b28f0cac" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "09b5f027618cab3b7b5adc01903e55fa31eca89a8a2f65ba0eb92c200b2694a7" . + "88700bdbe592652e6ed940acb483cdd1f1ecf9cd1e0500d9786a62118c18628d" . + "112b84e389cccde2110ffba1f9c6804f260b5cb9add513d0f50e3f288d24d371" . + "739d5688b68f50a81823440da19b4c0dbbadcbd49766903eae5f3841a0fa8ee7" . + "ae7d2ff483a99ab3fa85be0ca8fe0881269fd573990efff9457517aec3381543" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "261faf607049751b1e8f33e87438bbd2bb77f58d9b84bc2bf3a1beec8dce4771" . + "7d4cdd3d3ceb1cc32a9b939a5c3bf153c3a7954d8d332b9d3422ec91587aabe1" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "60c5f5e2524df0856f401db47251e417fe3e04f808c29faf09a5a8cb3c8bde0d" . + "60c5f5e2524df0856f401db47251e417fe3e04f808c29faf09a5a8cb3c8bde0d" . + "05c7fb51b11f5b0272a1762ad58a3353a7baabbd843b4f47d6ce14ac797feccd" . + "07010d29e55dfb602c447bb12adfb22c7a5c021e6263ccbc8680e386cfbc86dc" . + "6da2e779a06e55be8520def815fc9dfdf00bd60081c850e11ecc325bceb9c5ca" . + . + "c96f545c8a4e89f177b034e5510775918ca8157428091249059446cd21ee5aa7" . + "9f46f7bf9ad5ddc2b95b08a2cb413baedb04c4f191c238258771a1c975fa88e5" . + "6b18167a2a603241c08f7b94983bb694201145a226fa9549ebe485b8df8185ca" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "7ed0cec8cc0acefbff172bd9f53c86c4ee381b770e81026cafcde27cd750d5db" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9d410b77582498a582bd12f7d9ce666e74f206e0e8d6ca9fc416a016544a530e" . + "c2c2496aaa688da2e5eb43bd81433e11b4ed13b59292a8dedf1f5f45b5e70b49" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b31f3cbf38cf1c4bb7d86c78da5c2a1ac0125108358a4cfd1a981c3eef051cab" . + "b31f3cbf38cf1c4bb7d86c78da5c2a1ac0125108358a4cfd1a981c3eef051cab" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "192ac5b3b6a2248ec2b97c7057ff32468bb28d3a642fce5ca5ec47a209d0863e" . + "30b9e39fe82ea4e91407831736744416d0bc8f5129e8ffbcffee81e007589241" . + "fe08510adb3328708f9fb7512b24264cfdb97c8d1c7d73b2899a67a5b96a37cb" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "8d790b2515e2b1f2a876a2a253be90f7835762f28f442dee6194b9be5ba48037" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "5ec9f5a79138541bd21d9fb8f991cbb675cf201aeb7c0f93328fbcf60ef59884" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "77b80cf53e956477dff07eaaff9486812f49848a8a60e4d40ff06108a600a2fd" . + "ca5eddaf0fe7ba621d222be32076eb295d4d300f9f45180e73c753f8dfaf2bdd" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d4a0bd2df1b6f8bfc44c65cd95ceb37e5c9c95b50c2aab0dbef3ea4ad7c09465" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "e9faf730391cd8c2f7bece593d8bf0f2acd31919ca6c8497cf261623f14bdc66" . + "c7b3df096686502812ede4badf85b93293e04a03e924649370c764a0b6b652ff" . + "9f31a4664ca850c3e19fc986800971fe2e476da62b776f9dbfe0acdc8982dfa0" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + . + . + . + . + . + . + . + . + . + . + . + . + "50d54e1cc62aeeac35587c9ae3aa825f21aa448a690ad9c6df426d6872da6cb5" . + "fc6d16760c779cd0b84c71333b060689f8506c795110f89c91f8e3f4632fcded" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fe1004dc2644b73e9892405755c0dca720307be84ac56287c4a191c0caf95e31" . + "fe1004dc2644b73e9892405755c0dca720307be84ac56287c4a191c0caf95e31" . + "11598226d6ab575b96e17a00b7b8f8e743c10c863e74d5635952de3baf175f80" . + "ee1408d811fb6cb323c82174a2979b32830d1fea413b9ad823d277241e0fe1ea" . + "4c4b3a29e885e8b78889330df9c110f727d20bc9a365a072ab7ef0c1f458d866" . + "c7eed915a1f184aa0b6aa1320b99ea50724a2e76a729782f8a11d71cf4f0e4af" . + "a0e2fee30fb6c1077b529bf79c92a2199c792cc775922d175c0b40916f21cbf0" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "5804604ada3572262c12a4256ca2f8c3903d0dd441e9d89a9ce78ce77ddf3143" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "0fbb14e134e04259b64ad3162c92dcbc18f6d5dc166e26783454092cb6ef8e0b" . + "8838829c4bc630661ce35d291edfb84bbad716e2e4d24771a573a61ac7837ca7" . + "d5ee1d44d6d5fbdead8de3b65f8b284b1e5607a14291426b5dcfe68b1cd6b766" . + "6ddb17a81e6dbf16ab235922eb6ec03fc40bc781d88243789443d19b0d31c619" . + . + . + . + . + . + "e8a791f140a7f99ee392e38fab8327a69491d0eda37c1ef2b7d2ad052430ef00" . + "d19bf0402228c98c78e085ab744fe5c3f2a36df20fc269e1bf09759607fc647a" . + "85c3f7b45307321450805c74750d2a41cc9f4aa9427c7ec023bee06cec7d36be" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c7888d82c89566f3e8c9eb52475463d0e4de2c19721e8dfad351f7d39cfb3e46" . + "cbab58d86d0e1eb284160a24b906d54408a51a2d830aedf4ba9056338cd4bab8" . + "8ec3d5eddf96592337379decef00a4b8569ee42f46a78f9fd81c76e396aa7288" . + "42296aaaad76b85981aa57d28901c34c0dfe6591c86eacd3073fe9e8c98bab4b" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "24cbe8562e7d316586731a0bb6883bc6a37bdf3025e701ccd18704abd57ad948" . + "2fe4cd25ba6acbabf6b7af9f13b7de249fbdd511a108a6c8e83bc3bbc330ec18" . + "4cc0e8b404acc886a26bee767319700895abd2410457d9657888dc4b982e3d00" . + "f155646e6e1c30c22cea94328a378832ae0ef284967a2f49135b516ee614c31d" . + "7f9b3261122f7af4aeccde0183ad6de06c489836159ef883c2163a0266bd0d83" . + "17542b9d4fe8feda9683172097d08609a76254e7d14cf1a35d253fba2f5b9751" . + "b2d5f599db6eccf80af9fc4699ac680ca525be0f778bf2e72032007a476f3dfe" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "106d1bafea2f5d4489326f91d866939a11a113bfe59f42736e4041db9055c63e" . + "efa1b30beadff726c45eea0a9232ffbaf591c74a6e0dec5338a373dcec73455b" . + "314db5d7194574bf5e3f451ace2096946dadbaa72dbe349e8ee4e55aa4611468" . + "0f115d5126aa3035466c3a399ae8fbb4fa16c6fa3bd40a197774f67c0d876a49" . + "3fb4b703f488b607c40202be852e703f981d868943e3e64896e1aa888cceed35" . + "26b769de4fd285ba8d39659bbb4514973e61864003d4c10b2aa43a6097a13094" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5c60ca48585e6b2e417c33a750066633a6f3e20e55ede365caecd129f14ef5e7" . + "c9919f8cf89ece59de1ce99d4994153200533606bf73c2b8a295947e5b681875" . + "dc90c0a63ae1e868770513c1a3c0dfbd4c0107c4429cb8add7f84891846a484d" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c9919f8cf89ece59de1ce99d4994153200533606bf73c2b8a295947e5b681875" . + "5e37f2edf64e8e470a9bc4494f6c7495fb31d53eb1054905d4567a3286c24dfc" . + "dbae9e5a636d2a87fe44f6e01118cf2b64053ceea260ff4b65325d9700df08bf" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7551b215bd599d7d245edec4a2c3a01703f41a960d3cc0b1fb13e73b41dc8049" . + "7551b215bd599d7d245edec4a2c3a01703f41a960d3cc0b1fb13e73b41dc8049" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "5c4472b88fa0aad9183df9a76136fb30b5c3cb2cb93413a529bbc047521ae1e6" . + "c0dbd30b52b6597f751451369cf4842dad0bdcdc6998c16491c3f9c5f7f3d2c5" . + "f29925785960e5d129e863f168f6a2c7dd90aa87cce0ce28c218af9630b4d580" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "e9da22226a3c56465fa782cc6fef76914c16bddcc077741e4a90246e7caef785" . + "0d6c279a46eb2598ac8d5cc698af8a8cef637e859a0a6d27f7e86ab14f0f7070" . + "3f025d22ee5cb480e21b75b48826d057cbbe9ca2d5390a1e441837ff3854e83a" . + "dec34e88e7399155286a07596b00f05b416e466b6fb1b1c823bf86fb27fa7eb3" . + "ca6a0d6b4f2845d9f18d2d639bcfde49323d4e68ad523d9a4cc5f912db30daa1" . + "90535344565caf889217e49c7436f155b9aef905d77003c47706880a9a6091bd" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "aa85f0503553124de16bfda71e245e1699fa7c1425a285264c5f3602127e02c0" . + "e0ec93365f9a6343f168a62ad73e0d624d09751925f4230fa68d5b2b69ea2674" . + "7b5c2d301674c095c1b77f6c353b2b429d474c8866dd41b0522fa8507e7b1973" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "df0715971f046a9513670cfa0075df5d7ce8dc0b1d9bc3bf4b4816ca8f30c508" . + "df0715971f046a9513670cfa0075df5d7ce8dc0b1d9bc3bf4b4816ca8f30c508" . + "e775edde0136382f2058ee316c6f78b6b81fc7fd37f71590649c25d5a8297d05" . + "a5a7df96563d3bc3c6d00471b28597840f326a0a0a9d0e35e4f1caed2142127f" . + "d2aeac52191c758872afa5a4d35282cb22fe00539052c95415493373e769841a" . + "44dceefd7df5488c7ce75f0b4928c7ce39814f5ac89d6ad4c4849c3433eafaad" . + "a1e1deedfee563c23d609cd93a12dac737c01d213b490c5ca8b67fc6dc50d767" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "e2ce85b65f39beff1097931600f6b470913505f9cbecda3e9da61738d37d4198" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "730736f01260c58d2ef4071830b583224ef9cf55c9650df4a6711f9751c99c93" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "54886bbd5e02ebbf6618d9753bf7b90b502c03d20fa16c1cfa0ea19c11bc16af" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "037d2d9149f17e92db6b5f944b6bcee351659e99124308ab6aac2dced84f5946" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a85fd8b2cae6567d6818489c493c62cac6b84c83fb9a579dfa252d5475b49bb2" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5b06c8527c0161dc7de8409250fbe4cbea4120d56cfd7cf6c671d3afa0808e44" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1e6f2bd0047ba5cf46e257fbff615c0713e09e44f61b4ee4c324ea866d47ea3f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e3099dc9ccc49ae8841fb3c3e639848a83acdae2cf9cade9890ed98192018002" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d4d3b025b2cb436286eaee04f24fc2ddbf6fb389f6d832a22ee435b1d99fa326" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "efc0a1b74bd66b716031d55b7435e3b21a22abdb5790827630fe003e6cd4696f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8c1e721bd1ac90dc4765f8db5830067ff3b2a15a405962fc018cdf3cb90220d9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "a7e15a76d6ef35ae267c7bd119730c5e576482622811dbeefdddf364ff11082f" . + . + . + . + "a8708403aa931cf5bd9898874f5dbe45ca23fcb31aa5d7e3686eee76993cff1a" . + . + . + "75a682849b7e6081fab6be4fa4b7cbbb00b535bb4ab8532a02e1e39e19613099" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "16249ecf3448ce7a1d0ca7507af1b2822d3dabfb761be87cac41ef9e7bf0c855" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "849079ad918022f4250d2efdb18eefdeba39f3c4398cd26b98e940bf9f477b1b" . + "85b88d78b0c2bf4e4fa5d7d4eadb810fdd3e06d1bccee64f59db2b6b1932e5c8" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "76f78d3deea27c0d759ae4f261c20d5a484ab97ebae47881ee79589a343b6af4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "68860f995f04ebf2cfba4e2254b9cfb8da7a4cb031806bbdf47e73b615a44dc5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f1f6d90d5a43bf977fa993ee7318a6779e2293867125c25dd4bf3acd350ddae4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "76a7d63254241f8c93cc4d62cefa0f62c028a2804494e3a72b3fc789cd6f00b9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "568b24b86d962f8a53c4a76ac1cd3970115d8575aebadbbfb9c8bc1d1d5daca9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2443113d4cdc1642dc3b5571875766712d8a8e552e25e3ddf88d8eb4ee53a5bc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "55b045b25920b398e9e18fbc753f6f443f31db705f93bd97d8847f2ba2bbc8b4" . + "0e9ce119b6331bf5c0a91873240aef39e2d8db17d760c953044c2bec2db889aa" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f0a3993dcdc64f8f1c3081b9bead201ef27d8db1fb092815612889fbc7565b0d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "fc2be5a97fdf77ee9b322d330d472383c5098ce7dbbdf361bde4a5fbf2db9814" . + "962c081d7473a77ec044cf6288156d536bec8bb051c71d7290b5639a5a06cb3b" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2b6feff1215bfed3f5f7da00607a6e0e8c047607477da575e1f4775f6e8a127d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "8bd4eaee49bfe18c0b40dc549fe8e2c5f34fcf271b801569eb987dd4c791ce1a" . + "471d07166beab13798cf198335fafd032d72493a88e1aad1c7c8e7182ba14f46" . + . + . + . + "9bac5f7da568d73e79304834fdda4050d7d1ff8a7859cd1c129ad6020f3d23dc" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cc470c3d53f676112e2520971426adef818793188158969ce2058c74aa1d749b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b6040bbc53f97e14e6e62ee681538476ef91f126fd9abc07e940f0839081b33a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2ec930e11aad13629f09607bb46601102726e1a92f3bc78f77e02be55aa471f7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a8952b4de789d1f8700bc2b00e511ee57db8f685baa7b8c72fe11fc349642b7a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "0932375aa784123164e80a363d543b0ece85859ab60e380e65df50527340a0a2" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "55b84338b877b3bdd6850babd37d4fbdd37c4089d59baeea2873019a641453e1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f1e2aa186f8e594d70a925068dd8e224129c108d9c877baa1ef6980d8c5df012" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "99b8ad0f078e8c72d5c2f2c51d57e77c0dd18088d6c46bd9e44f014d4c76a0df" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "23f27bab353efe99a61f8055191378bc30d9a033df223d6e7f490fe369fec4d9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4e012284a9afd4c6c6f3b0ce7a7139fcbd9180bcd7c06b1c0b2eec74f64dfc5c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "7880aa15af9eb76490aec2f6375af796ee5d8b0d9222158a3fb03538f55d73be" . + "21f2a5e67bc390f2bac460c5f54fce1be6a61be0c20a7fac23f6617f89c194e5" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e6f6e2ecce682555a5efaf777d5391276d262c2098a702fedd5b8ddd32420a5f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "d3c202ee98cba4ce93c2d4cb73554bf85961cb497955f1ba7b81542436ce0992" . + "a7ce8c4d3f8a31ac5e4bbcdffd47bfb00c7470f2ca05d4347a6b18ccb0f19331" . + . + "13dc41036fd012c6d7589eee6265b9623278c1a9dee769925a29343b0a9c1d20" . + "5ebe10e2e99a9c2a104ac374a488c214ddfbd2807d70dd5e07c19965c93658ed" . + . + "8ae6e2810c03c2fd82c6b595a97d6997d39b8a79345f29a1f8d5a296e423e19e" . + "ca30a71c5ce561a94b4e0655b4a2180d52761dd31b280f58f47d467eb156e7a3" . + . + "aff3cb7b3f9c165f5b33c00764250f9474827b38437d91793a73b7a6b4cbf51a" . + "4911578948ff34d6c36a0a0357c2eded3da6992944f7cac4c8d2e85ed0b78fb1" . + . + "a96796ce92a924beacee0a983d49ef729d031c0fb06f77a2c7a1f88a2583613e" . + "eca07c64391fb245132cbad77d828efa770443b4ef27725d583402c336b1c4a9" . + . + "9e4295266fa6adf24cb6fa2ba6c5633c6bee891ab3eb710b101c22125cea0c7d" . + "2c894e133796947fc81cc4f9362aee68a10f13ea90c42c8c9cf3f910708c7da0" . + . + "847d85a12edb6aac8ff6d36f16afb827d288a9e877ec330eb9d7ca5f702942bc" . + "e957eb84b451685ad1a71a8dc13de57c514582ee432c903b49fb991f61b00b26" . + . + "e20af69c87856b62b60741c7d6043034c7a0010f80f8e1659f715fd5d11a8147" . + "2b21a7e97a173bd35837ceb9e50ca0bf21e37d332b5263645d929d26443442e6" . + . + "42b78022742142a00654273ee95ece68929beead0bba2854d0c650829071b0b8" . + "c58e63143fb115c052d47b50b3bfe79feb91839e01b56618a813a3e1e2db00ea" . + . + "5a1ec569c527fdbe6b88eb7d796b386407ef56b7c0a6f62e6c9d296c42d8c37d" . + "38303a854b11e01b00084c066fcdc21ed532467904c2fc4c465b689b5dbe0d11" . + . + "675ce1979230a7abeb836ecf4a3a7e890ce591bae9f73fc94d7d410667884c84" . + "55af3d48948f5130d7f3df7116a9b5c8ccfcb7ce43e8fd213ad10fda4d5056ab" . + . + "7e671ed4c7376bdc2cc1e9f2555c556d718d0aa7ace5b39a36ea1b3f1a306e1b" . + . + . + . + . + . + . + . + "46d4b3c8a9e761a95f2295b24d0ed9bf7fe9d105813e36496df3bcbcee1ce339" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0ba6b744c0e24b0be7e47be9b5883fe9b77c1141d6a30f9afa08e9489dcff50f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "5d63798443b6774bf711d8131a7b97410141faa8310c7b254dcd9a3b370d419b" . + . + "7e658ba90d5a60ceceb18f83d6608e4274b9e6d71b95fdebf4fd98ec7c792a7b" . + . + "24fbb210823f49cad15fc003c5f341c8aa75df3f69f772080728eb4cafd963ed" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "66ea76600073955f2e28661316dc1d712ca6deeb398de0f2de32fdec5fd20659" . + "84b25445c3f68f4c38f0a7076e4e302b0a846c02e85d7ab6ecc0a98575c1932a" . + . + "863216630e4bc0afb871fe90ce3b697a9a7c8d61876cf9e3acd264925cffd661" . + . + . + . + . + . + . + . + . + . + . + . + "d32d8962a1703b603b126eb4cbf05c4658fb6c40433c0401ebf1a5edab6ea080" . + . + "27df115242827a4c59e476905ce829c9ae8512e55703834c0edeab13270cbfe7" . + . + . + . + . + . + "cd0a2db62b028d6a5f2591a8bf9addcb54ae9f5cbd82a9bfeebd693ccdc1bcf0" . + . + "886f086eb55b2e44da0843e8f42554efa2fb0dae756406734a5ba63df7637762" . + . + . + "094ee6201cca8786158cf0ef785e8b50ce285171adc908210d373e4f28657697" . + . + "949cdb543209c28e21410a0a03e39dc09176861797e18ceb6e83229da2a79efe" . + . + "3fb1a46512a503b3933c743bb66843673b2d64e88973ac9c7636872073a5c861" . + . + "16a084d0094954fe783225097dc07cf4f3513118808b82cc0af1d1fde752e1df" . + "a0d405b663171dc5c8ea99cb284a130b45af98bfff0382b75606fca3ca62b59e" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "98035295b844392b3fc7652610804a3d99a5e01652f4a3d4eb0786bc65f00800" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "7ac47e62aacb1ac71aa7b3a288ed68c40b9cbacd37c2c38f5f500b298ebeddc2" . + "7b632ebf8ec3a448e7f627d9f23af8607e3f92a546f0c3461f89ca083f014fdc" . + . + "3517d6d1c6774eeb41c316435a5b243311d290973180ebcbc0b8097b4344c24b" . + "475df19363527063107c2b36e724d7accfa15a8ba118be39994986a1ef1d508a" . + . + "f8d56ade7157ca6335970d30fdb98146ded50e7da954a20264a4791011f5b6fc" . + "c7505cd8734da899fa1fe5fcd7a6f71bbefa090180a7349c909df8a2be746ab1" . + . + "cf19a49684ff4c73b37ff1e826a563ab12b22e5707dfff3ea6cbb1282b0a1c7b" . + "14971ac19220f67faee0d43dcd3ae289aa924e776f49d1ac7b082f6f6298f9e7" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b846c6ab194d23c6b8d02629e6d285fd7271615d505397b6bef02c1bcd85e8d8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "318be17e9f56600ba30cdfae1d0b3c418e2efb5e4f63e021c2e1d1493a3eef92" . + "cb369ee96a57368cab8db8fd4f805b98dc99b2843f47b4f59cd2aa0a4aa1a59d" . + . + "648a9db3082257512c1f00309cced3c5316a84d9ad4d9a5393bc1a9898b48ca3" . + "6cccf376de8e49d61a535e2e94dce5b2e8798844997d5991c4e866065e3bb9c3" . + . + "e56ba887c8995632f48285042889d5e270f033418978a1ea79a5e47e6361c41f" . + "331ef26d446b3603a0caa66f926933304dea373d4dcf0c78e4409cd5a0fb3345" . + . + "6ba19d7e543535554c1c406af29f29c8f672bd26e5fae6df3e4009a22991816b" . + "c8cb4f62db9e448b6ac3aaad27eb454f8202f53b2df0eabd05633710e797a83d" . + . + "bd233b786eb863204c406eebc4c6047f7073497d63be135357af10975afd212f" . + "c1e39d800b9c05096651ccf3cb2f331551dca176472b2853a86399a2bafccf5a" . + . + "6b72ef7a047f8a86c950c837ee8c9c057aeee329b8a3c0305e4d2133872edf65" . + "6b455532823d788bded3fd18cda39ea9b881003860b60fff1354adf8d10224d3" . + . + "ab4e9ede4cd8738ee878daa3e1f7827a6f253f5adac8d37e47d733f40212c03e" . + "77fdf99fc730db94a40f0e6400a36c9cd58d7f4c9a8721fb5455edddd8eec104" . + . + "805a2e2e055480e60fb6daf0429329901b460ea687a219bd7d65ff0bda85dfc9" . + "65b80d729b5fc348835bb506f86e0c12b9feb6f8195a0b5dff9480173d234397" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c7d25a60cfd0f83375538a18ef82ce1cd8115640abf8cc49d154ba5befc76559" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cb387211a6e50bac5068d21f5b8edef8df9acabb75d6ff42185580d378c21d1f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b8eb5a61cc582684ac90f2fe62473c648cf00c74f782ff194c2406971bdfd1ba" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bcd1c3f7a08c725616b1bca5d0e10adc387bfaa14bdc1947091a729e5790b441" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "48ca29fa9a9ab7ca9801f0826e75c67627780250fc8d32f21b717878ff84354c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "52724c241dd9e5529d556d158e25c4f4ad1c94cf7677924eb167dce151b35f19" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "794eb250cc5796821ef06285dc67ebdc8d7764e4064b751b4aa6075006e1e483" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "24cae52066cb832b5565f6f1adca9a91da25236e8c229878428086b36c4bb97e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "09ae2aa172e302d8bc2fd873abe01d82b3d88905d3524e83cdb0ecde77bb0286" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "065f31bed1ab2b28b64454da360fc56e24cf24dc89e5799b5448cb27a72dfeb8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "661d193b64ad13ef56f2ca0d717eb45c519ef983d2656a0e31af5006c5e6ed46" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7c55c9d2e1fc554913933d5d3c2555581afdcf2c26f04dfb39a9c8c0d05ebd82" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ea801b2b8c2b3c6c9f6e6ee52bc36b5dfc671e16ea8248d3adc0bfe8cf226313" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "70b5c45e42b7024b6e2821721833adf974d3293b83d5d745bc28c187bca10f83" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2904d53058a4c3713952cfabda7da01cdca39dfe12359e01eecd475c022604fc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "556d9957e60337192866429417d159eb570e70b5fa2590deab747e8065fe1533" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e95b27fb6674cdc3143804d1767a7f079478c417150c33cbd94d9eb7c0f037ac" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d504f0b4da5af7906965d3647c8118040504abd812194c41d72d8d6e3e35585b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "61608b98c66074533cad455366cedfc45dd6297b7b9f526950dd96aa7b2245d9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1b12be790f43d42603c2ef9868e13143e4c11fefdf5802e3325d7c2e8086d747" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "e37694b162853fc3df81974204304fe837b1ad13a8bb199bbc941c301a52cd73" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "67fe56cbfc9bdbdc59f2dd909511dd612a30c7ecc91ab910f876ed23a40b8bdd" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f2c5dd6aa03057d197400f6576edfd510b6775cbd0693cadc00b95522667552c" . + "f393ca3c7cc0aa9534b3f4de93c6895b30c1f239bc4754f90436c19c6ba97575" . + . + "1d059bcdfc8bf9a7f35f09c57714ea78c05125a59118d2e1a02f17f2bb7e211f" . + "a1c17dbf6285dfbb0252a0bc857a2d9ee24c8853c7bc05fc52c1c88370373344" . + . + "17d0f510f7288a146242dfc5276fbaae84ce2e83cfe2bd8846a88a91b3f9620c" . + "f6cd73e466492727a752c4e3a5e4ba82ec28b0bf510740a913a85f577f558c30" . + . + "f7a52d3d4f8f3e030fceae0cf0ad8f7c3aaccf0926d9bf7fb5aefa73032dc5dd" . + "23ad1b13d91ee9f2d2c2da7458f74236c52e3cc07cdf89d37899b9d0e9003188" . + . + "09e46ba8d1b10b4255d34be30490030fc3e593c440faffcf99c5dff6f94af533" . + "8b8e04f79b7738e1a79f97c4a7c3eb3c13d68dd3921f9a1a5d4a346c64a8dc30" . + . + "9cfb149bb77b1b4451d44a035c5700179c65d5fd89d993b8332ec3d516565138" . + "51f85e486ead3fb893f2ad2ad8dd619321c95ad7a503b96aefe5065a0ea71ea8" . + . + "f307169b974c5da448a993dd5a12f945d538bdbe2bc0598ed8e6fc16beca96b5" . + "804ec78e4e9e00669d26cf3e199e016bb3e4a12bd175c6648f789379a4aaf5d8" . + . + "164fe457312e04539d9d5e9e9dd50fb928ecef9a9593c11a43b40daadb0bfe44" . + "a1cee2dc9afb2c843458c39c82c25fb241c7b2f351f316f31d78fd2a185d3c3e" . + . + "7259d4f625dc553c362d7463bd3594569d5d757922bcf52a2984aee1aea7683f" . + "d0571af43b883dc162ac59ae958a9f80bdad6d433a49fe52bb8f4c407de06818" . + . + "d2c50b8a8d391a34a6bd8701d1598bc00480c86b7b16a14bbcdde3144220f81b" . + "dd4e5f5b38deb71ce1e45991c1deb6d17d533c423c99255ba03f85c745f88059" . + . + "32c027e7653b2189306f9a0df43c6deba0c2c7fb04bc7f33a15eee1bbd6c9361" . + "1e2731e1e992c92023d56ec5d6ac31ec0439a2550d09f5e3531ffeb7c5d0d21f" . + . + "b3e502520a588cb11cb65abb5189a4d497c52e78e60b40f10a0ed47d41522ec6" . + "29fba8a0aab82ce8780d95376934b8a3e8266b10c96066bf2f1bf86b5d46e216" . + . + "d4e41cdc388a7e964cbbb84499a54367402dd7a3a50d084b96968ae744360b20" . + "cbeca5822a7a9f8a62edf1a1b0de7dd92dd48906df03b52344a05b3e0f2145cc" . + . + "ca94f5aecf83cb9f4afde1a01a38700391c3196f97699c92534b50699269d36b" . + "64a3a547c6afc084398063946c098b315eaf643b357e28462664511732403b6b" . + . + "1d1747892334162efc0f8ceb48126a63c9495b1b71cf87b67d76bc80c05c81e7" . + "db2161a3f42db9a3b2f3cf3974058fb8ac57e900076b159e9296ae07d143c2c5" . + . + "cd5f689a18033fbb71b4ebe1fe65645b79b078543ce25f8215b5c0ba4e9342b8" . + "240709ad10c07843b9c84e54f7687341832797a893a2a831b82ca3f037609c57" . + . + "d273de6bc96562177b44baece4740af01bab44e1d99ecc519eba834c2eb98ca1" . + "81c33054493a68e2f4f5cd781853d09d58a1adddb329ee517a8b2cea537e4167" . + . + "6e423cfa28f00efc7186035e751d99b1804db215d47badf39aca11aa1b50d85f" . + "03bcb6d9ecf64ec4d0309221353a9c8579b8ba90fd964ba9db0f42a1ef87f8a6" . + . + "dd1ae307a7ebb528b33146d8345184aa8093bc348c7c4c8c714d18723ac294d0" . + "f5ceed63b59a92f7e70106c7eb74eaf202ec30b5f9b8b4ec15d7771ac5d16936" . + . + "29b7e092f48b9579ffe67db4c4bce1700303eb7cdafc6a9b031d357dbecb3525" . + "d717fe4baa9c88fef476c7e5c2dc70400dacc85aecf771794693a6eb4d6a58e8" . + . + "35e404f7f2eb6f7d2dba129adfffe824a3386a94adf25d19995a1a64a1120e0e" . + "9a3893085de8140c9128570059fa819c0a945ccb4b5d625c10ac322cb0d8b8d6" . + . + "8f1bac0a84e4f578a67efd159f2389df2bcbc47fc0d219f09233a87475a1ce48" . + "3ebecba23651188489e22c4d02e8094edbab997c12a5c4e26e89f6303e2981aa" . + . + "47ad824ec9277fb35a490835acf791699ff3bcdb6cdb2028871d565f573a0bff" . + "ce8cd9695f0220b1d91587408e11a17bc904b2d5687a4ae4e06c91d16b884f14" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d0057c743386c2898b5e05883631c237e258a4a465d23c73b7c1eb0b7800645f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "d685a2c4c213ca521f5ae51296c67d67d7d88d32af72efa142092c4dcadb7f41" . + . + . + . + . + "e85c072a8498882e5dca156a12172e2367d326d944dc31d22df240c343ec5a9c" . + . + . + . + . + "83e6665da6957abe2e42a5f3629f7ac3468b8aa9af8753c44180bd3975e7651e" . + "e6b06d5a73449af933c4d2b0746f664d2591788baab8417e13c38800696cf960" . + . + . + . + "eff7e31169427e44ccf94cd2d158c82add5303bbd6b8d038bb115936853c8e59" . + . + . + "557492a49ab922440076043cabe412bde4c7cd37c4add6f33f22fce0b7670013" . + . + . + . + . + "0977a6da52973eee76981e98088889281a04ff349462259bc094c4f3f6516256" . + . + . + . + "01028747116f6cd75d752086d4f3a3fe12e0f9f63732ec059e3b49e04e370c32" . + . + . + . + "ef54c82331ed5bd006b8fb0ca5765e3594e2833c5c11482dd7f9becf39712ee1" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e2099c34a441a515615ddce026af5e4355a54907c89d2cdd56ecaa12131b91bd" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "4459b7f8373c258adfc55454472f59723380f7622b092803fa8a85fe2371fc3c" . + . + . + . + "f4f554490ba3929b97d1dec01bd396ccf8f018a8a8253d0efb0b41e7aa711da7" . + "054693e841cf6f38edb2403d002722bf4ae76052b5b51f0c62b26082b3328a2e" . + . + . + "87d763e64918daaddb7a9cedf2709fbd583a4eb89f5f2972bdc7cb7380788cfe" . + "119acd128885ec13ba9789a8bfab5b64e992466ffa05b4bf504357894fcd45b6" . + . + . + "4d4208a9a1f522c447c76923e2f9c80ac79831654d369eba1069979547601f61" . + "7b36f9102e66d17195d5eab992b563598e1a291782b12fe748e41a21a2c9e623" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0a822e9e7c074ce8528f2fb5eebfea02e6f2a5cd863501e0fa28c83353843ec8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "128112c9636721c7b2e2d0ee7a8d462a0188e1640b3ce3f413914f867e9db959" . + "8d3763d362bf123baeef53e86068e88af8fa958c5fc8ad69d8370894070954b4" . + . + "82508c55cfe112bb31a0bf07221e8633e67716454324866c41ec11c7f565ed4a" . + "280d08789974551c8506e289082bba272f2c15c905af88e2cf67d8fc335a8b94" . + . + "379f0d3e9501569dcfb0129ef3574df17b388e36576c1e8ce5b5cf689d87811c" . + "4d6dcd874b6d68dfcb951dd885b43a9d534720d8f7243bd3ddd3908fff606949" . + . + "0a24f2e09123ffc18e1e6f8087ace44ad1c482c8618d19fa2fbf205550bbdf5a" . + "ab2198e1ba8c1b3737217d20994635f8b071cb58d6b3e29c222eac20d72e2fce" . + . + "f84c5d85fc1f72ec36466a93ac20ef318b6557c1a37b7652db535dd353329897" . + "ded4c9beabe216953a5933f3ba7e29622c330fdd88fda31a5a59e081360e0013" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c1d0aba22615dfab8c6275bebe6028520430e4a7075e390ef162ac1e6491c9ea" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1f7bb9fd910b8376810e65557de519e4e24f4e171669a0a500bc6e83793202ca" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cbb60add89182411c64e0b40bbc836897b4fa53d7303676bd72000b6daaacfda" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "fb3c77458dc39f789e73a830e4f29734011f4ae144effb09897237e19cf48adc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "67a537e1a104dd6d2531fcec07d7513faa3f90dc57391894a93ae3e94053ca97" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "1a30f81b37dcf5a33c3a3b1897b4f23902da897e5c9ca3f2d4d14c2e8082800f" . + "d6842d1a2c31028ff78e46a147dea2e7f2055cbdeb01793fdea08690e3657cd2" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6ba44b479298681584cef42f778ed0efe6eae0e029bff6c2940ffba367078bfd" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "7fce1b405820b1db1292e959666c6e315c7ab341bea059a827c535ab4e069ddd" . + "ff31e61e7c5f133ea678ae363e427ff69c1953aaedf5320473d0e7eef02b28e2" . + . + "e8c0f9f92abd09942d08a4401cae302d0197d939a71fcbf801ba7c95e9e72515" . + "b4f5b6a3893696aeec568b1fe5c7ed5bb78b83655173ebcc7a30a5811f1f5641" . + . + "427eed9b7a691c73617bd268637b60f3a5e72e0f20d8508240b636fccd34195c" . + "7ac58bbdcdfbfc065d9f6ca62225efa645ec13f755246e38ca8ec3261891f9f2" . + . + "fc47350c13f6424997be6502afac941bf5d8c5ec3f96d38ba162f14316d20f88" . + "903527ed4a1f6c3383761d3345c2916f44e71e892fd855ed2d320350e44044d6" . + . + "5b90641ccadac3b36235891c4eee84e78eed35e6579d6021f4bb9445776ba749" . + "e6583caf9ab7d1a9acece95cd7a3872b63901ceb28f29d755d2e176ab4030008" . + . + "c50ac6e50349fe02ba5765e1899d1ecf26b5db431688640bc87417bbd26a2cf7" . + "c4eccdf3e251a859150e7945d502ddd995fc5afaa509e393cc1cfc8b005a36f1" . + . + "2cca560c2e0afd1eff7d1c142a40d8faaa42604a67103f230a3025a5eaa9911f" . + "d7f10df6a8b01b1ae543f0f23ea7ea76a15093fdadd453f106eb7687c66f0e9e" . + . + "8624ea0bf4fb209c9fef9055c86e9f4e203299ebb546cea4d72ddd62073c8d8a" . + "1a60375377c2dc0b9cd945dd384cdb71c8598acb4b9ca9f2c7154f193ff144be" . + . + "18d82ff6261c2488f3de85a630453a40a9147552ad28c9903a22b41b0c4af78c" . + "548be898427cf09b992f49abf8cfcf926b9f7b8e0f17506772b86a87c7202182" . + . + "ef11e170165c71f6f0805e5ae4931fe32f0123a3dc9711901141ce9db159b48a" . + "d2502bcfe3234a29b3fa85118598f1950a9fb4a189fd89e010222acd80ca16ab" . + . + "61a113c0291be723735bc1dc7cb80592e71ea99167c337b2446b9dbb36d83a8d" . + "af95cc61d82757dc126021a54fbb5edc27b4debf2b2c2a628ecdcef0e2ce7022" . + . + "329943c0e2619a5a6d05a1018d15bd7ba495a600dbaf97539c4ef9d2cdce7854" . + "ad6589e599328875a3e9ec327fec3b48ee0cb95acfc6e0484dfdce9a88006c83" . + . + "e442b8c8577b97ef7160202e106ddc67e01156c30acd90b9cd4d71f7962d0132" . + "e50d697d15986d2397ac62421baa36c48dd149d11a3cad62b007b24ab2f170a3" . + . + "b29b484cd61bc54fed8e7bd7725db548f24722004cd3a960e760d8cfb0779acc" . + "17b891d0d7dc480f91cf399a29ce73d0ac90694a90e05ae43b5b825f5763e466" . + . + "c6a29e6a28c840f4daa40c055b4b9ac06025e2c97ced25092bd7e12fd7f3c9f4" . + "e6b26510a9a7b4340a24c4e456f2b12a835f9fd7059de6cd17dd113898ee8b67" . + . + "7aae3e0df4985e7a824e6f30f18c1c587b74a055fc6e2dc16e012ed518a69f62" . + "4d6f199cd6b876ff8602892f6e8ba8538d6c1e85b98e5732d10fa867f2ae9f1c" . + . + "d8195e968de973695476b6cebe6def0b1528e413a201fdb25f3282ff73f34587" . + "71881b3e0ce92e554b9d7b6fbc48ef34aec5721e1611d4d114bf1eec85d1b3bc" . + . + "79c1f116fac0e3f72d99ad820007671917cf6686a0d0ed2cc018b1b311db75ef" . + "2a1ee143bf82b1e195c36ab627c39356e5b4c62ef39aea51943109332c1b0712" . + . + "dd724181b2ce0cb660b6c886ff2c2d6901f2e8dfac61e41c19943ace4057924f" . + "1a904c4ed592b98a40179417e187e11746f72eb645c02c484e4dcb0eb75f2789" . + . + "3ab28067aaef73e441770305836e11206f3c03307158105dd0336b419e5a038d" . + "e25e41a2b6cc5f608364e065df920a0bfc388cf2e17b8ae4dc325e92d5807f04" . + . + "2e4a87f1da6e3cb30548402975f3d63e64e26458188511f398762fb4956b981e" . + "ebb1f4ca803c2c3806b13f328493e4e3b4c2f8b85668d5d0cd2ead3762baa5f8" . + . + "45bd4a5a0918526af89781b2c535249c6e13abb321e3f12b9b4b02ba5478b79f" . + "0b896379b6b1abe4f8863e6b8ac5fccd68d444f776e8fbe7cc18a61fece3e5f0" . + . + "75b20cf61adea13641155b87f121ebd251b2171de5c6a4d2ce5551200d575de7" . + "f4c87f1e6dcb529b413e8bb17d4bd46c2b3c10745c8e8f6f9593ae0d59386600" . + . + "7592f00f181429f314bab7e389490a865a89e4253af1d2457616ca42cf4ee3d0" . + "5b2d8ae2924b361850f7dedaf888b3de395b57cdbc2405f709706a9e3084b5fb" . + . + "27b5c701bb031bcef990700ba17669a645b1cc42ab856b0426e8bc7c2675943a" . + "6c29b966844a1a216480de666f2e1f637169ea2ae580ae4c3c2e3555e26e2839" . + . + "6ff204b487fd61a4a43fd0429450a2c9a2c31e5e435d89a2d0ce821c57cbabcb" . + "c5c3496d9ee69cc74e7692b9913de4f7dbcf66c0a441ab540e4be8a9a18131b7" . + . + "9bfa45f4324146b75f80728e73cf35ce348efeb885807b5750218b0b45107a69" . + "bd73080e5afee655fd9c7a4f8e13ee76bdd63a43fd2b566d0171260992fbcd14" . + . + "b7502b7d7dbb54651375396a09435b48c3aa25368d14f540e7c77628213536ba" . + "9918371215e491d6587a00bf882abf9a8b6bfaa9265e5cbb300b221b95e96365" . + . + "7167599bc279c524c6f32cb30d7acddd2cf0821aaa7c035ad2356ff511e6c672" . + "066952498e7024b6905b4c9383ad97f30f62a059c5fa4ab7c4a170107d42aa69" . + . + "aeaa0810f4cc945a413fa039dca2970787ce931889c396659238831e01f179be" . + "5a04b3bf679f5287a2b2053a334b88c5ffde8756bdd0a83471f2bc6d04ceff27" . + . + "b696582a369b216df29b3378dac8a4ade5257c9381f499a0d7021a5326dc3b04" . + "037ce9468b69211d1526660dc7b8773be1a62699b67ce8eccbd93d5be8a2734c" . + . + "7072f482c663cf86bb8cd7caba06ca1dc2e299f834011f80ff843a032c2cfe6d" . + "d9c7506fca0128483c4faa35a3d2894943e6c48c4f8a913aa63fbd3fda22bced" . + . + "b90c99f9a52dc74481fb8cb1d40c70e3904d3576d42331efa33a68dd31927c45" . + "88ba2c4dba0e9794f4968628a059f7b7295949f8ab5be4463badfc9372ce2e9d" . + . + "63c4532c7f510a97aa8784f986714c411ac1e6bf9adb1e49f3f7edb11b42fe64" . + "27f0bbac5f1fa9bb395032f3f112aa29495737d30d600d429a5ab7a25482cba5" . + . + "9a6daaf9e563e9c18d3f11546d133dc47d355d2e4b18b0083e8c71548d464fb3" . + "aee3d6b094fd9c965108c98111155ce2fdf91974bad18753e0a5c992f4772d36" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b9a32d854f0d24a8a68203e2cb4b49b882ddc1324ca871a07927e2415b6c095a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "27cd72cdcd9a6efe45911aeae74017af8ecd872062a4b29507f45cd66db24003" . + "755aa582c51dc5005fa66dc57b1c43f8d33759eed5ef8ec9ba773276b825b9c0" . + . + . + "72f66ac2a8c4fee325565cbe0d90560d00e8745d823f832608fe57b8711a01a3" . + . + . + . + "76441f4e715b3da02576f73ac8e568ca9f2aec4531df5860b19d96e8bb7536ba" . + "0b3b66928b6309027bf3b7a4609c93f23ecfaeaa8c417cdbb3e901bb1e638573" . + . + . + "e4500805e91b5dd67b3cc6bb7084841c7c0c9e4ce64bb45bfafef5ca4ff8884c" . + "cf4108e94b2ed2e587428c45f697999dc0b8c74115c4e36f668d76b52035a5d2" . + . + . + . + "50a3790a80e4686cd97d0ec99cffbb072874580b8fb18d949803141e67f767f8" . + "31053a74557ed5a03494ffb36e319f81ac483912cb3b7d141bc59339ecaf9a66" . + . + . + . + "a2cbe8b3e633b6c1f8930536ef9b549abd30ce74b8c6a4431d4f5e3aa7ee1ac4" . + "1b159300f310c05ffe7ac4dc637821578004b330e8d59e8efe7a8b2db925ae03" . + . + . + "c02b4f83467e356d05326c0dfb51e8510a9d33092f6ed12ab1debd528503a658" . + "b4cbf95045eab2271bf5e11e1f4a703682d1f65505e3106600828e2be413fea2" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2dd901acea0d274d5bf03a60d4171bd7682534edb142f029ec5bd97fe63e1aa5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "9e7b284324273a0907cac02d802f4c5bdaeb02d548ce76ad83edd3e994edf3a1" . + "2244e515d2beabd690d06cff18070cb0467f32ef2db84426046043eded15cb49" . + . + "9e7237a7a74b6523b79462be05703b7e9fb81e5420fce40b5cf01410c1ae1809" . + "27c38fddcc204bc512eb5db445ca933d3230913edcf5c6cdd7b775666102fc53" . + . + "ce1429556f57d7eee4a6ba341182ce3668bebb5d9cdcf6b6d0dbe8c98d746391" . + "111aa8ce3cc112357424b7f8569c5082c5b9067ff98f43fe54e5e3574427f141" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "201f6b522ba6790a5c2cd0ad4981dc05c2559a738c40d51b9efe43693d5eb45e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "994e8364823f2ad53a2302d79131af89443cd3ef565acbe814a21b9adab15b36" . + "0ad02603fbabbdc655d28cc4e20ca7f80c789e40444e8c48deb8e67034c581f6" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d38d2d3488da5851064ed875a1d0106416969c592d04cd8ec1316d1efe76cb63" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5d3600af7798ad7e6837c25d718f282ae86c326a45356fdb13fc294a350dea33" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "72a3e0b9e2139df6377c4821419131f4b811b2758d506ca540bc7a57f2df366f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bc0af692de98fb5029a87609ac1c8de2619dd7c0cf4e225c2a8d08f63e7163f8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5262b2b636c3595914b29aa6299dc9910a9874fb65c0e8a4d79584aa5872f129" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9b5ec64721dba48a6822103801dce32f28ce9c3122001c6c1015854af5c855b0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "cbcd906c87be467dbe53ec5f76a35d9b0d1d750581461f3ae286b2dcc0f0d029" . + "11b9a555aa1fe68dd3014255b0de431397c7316ceb7f5dc113002cf57a4dc101" . + . + . + . + . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5c967fe2a170b99b73ac6c37c9e8dd5d7ccab687e9f29c086291eacc0671e9d1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "1dc758ea1dd3c9807ea73122a7b7bceefc90b5fb5ce4e80d09303cff80b9675a" . + "011fc824cda3c6773ac556c7d9826b6b2add5396a1c25a0cc57fe4ea8e2279a1" . + . + . + "34d8292c8001773a792ac300ed26aa0a6816270fefa6f2c0ce0478f8625d0973" . + "ef1aa818b4b3c03911d53ace6634605c0f185234ce33a67a37979f68aaf436e3" . + . + . + . + "2cc1a639fa8108d3b34991e39889d4a3f584045cddf22b0ebfc5fd6cef2b39a3" . + "df21ae5cd429ec8a9171883eb7bee371558f2db4c62474978fbbdd67d7810586" . + . + . + . + "3142888db137aa2051ce22c3ac4dce4ecad11efa967f6f6c8cba1c08fb89ad3b" . + "948d7e32a7cf3e8753a64276fdfd88de68601af89e2c03bb2df9ad024c87488f" . + . + . + "76617205c1d8ad807cad6674b8770a49604f92cda7494eb971d68592e9be8290" . + "19c63f04f03982c94179fd4cde104eeb1cb7286fa1d9c67c58d40b0e8650ba67" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0a50a8af1349dab536699e4bf5cfc7c6e336082bcc6e40a96a87cb9662a937e4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "8aec9731dae31910c0f84029e656b208ee1786deda6626b62ea13293e90e749c" . + "982023e99a480ab63dc43530307e8b0abde5f0c3c00aab1f7e95ddead08781f9" . + "1c23dd7adbe032072d5dd5c378161e50577864c4f8e413eeb0997cf4367977d6" . + "d577404527e14e67577603c9279812d5e59bd6ba4017d1f5b3f59cfec2e1afe3" . + . + . + "4ff5b7b0893b78169768941e04f0759d791e03411c3231477845c4bf73adcb2a" . + "96a906d6258a5763894d4b1344f95368612ae87c82f71176222ce71148a3b5d1" . + "259856997542c089aa890d5f0a8e5dcff6b7152bbd58f5308f64a12287002c8b" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5907791eaa0baecdd8dda074103e5801c051e137efe576efe410ad0875adceaa" . + "1695cdb954cc003476e56c16cd3cecad6bad3208909d427590bcc76a60d8184a" . + "1f5466f8188372c3752d2a8289bedf7b61e81657cccdbf8caeccca2e49b188f1" . + "ceb0a057882db536a54e6b1f39453919873a7d14cf1dadff0c6c7892a5a74137" . + "38c90d9d9e72e10f159bc8475356c68665711105335a497bdbe99474b4e9594c" . + "3110ae1741e2bcb5262e8e1cc41097e5eeaa3c6c5757dfc7b859c51eea6cf9fa" . + "4d7f122e1cdaf6797d0bf818ba0f053bee8f49ed6adec711a02a64b3c5cd92a4" . + "5af74b0ae6df1caaf22e544ceddbf4f6423bdefca2e51a9e8a4c7dd1a73dbc29" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "43a0b2df61424e17b172554f4772f32f4e01d17dfd2209cde9a324d3aef7c658" . + "7e9183827cc665283787129271ba85d300a5176c9c1d9bc548f8e9eb4d79e7f5" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "774fe6a30abdfdf15b4c1eb00ff48a87f76f817dbb37f942c89b6b7b22f79b1e" . + "dc3e79a7227bf612ddd2d17814a9f0562d42f9765f3cf9030e45005aa9b57c93" . + "9f8aee6e05a0c2a3573ff2f2cab2c609e0c66b727dc8d752c3368276b666f9c5" . + "012901f7d4ebf54b82aa4e3346034fce0d1edca78cf853e93fe26d4b319d1cf4" . + . + . + . + . + "774fe6a30abdfdf15b4c1eb00ff48a87f76f817dbb37f942c89b6b7b22f79b1e" . + "262dbcb72b27d4601303761dcf999df77d99a68c9d50d60d539936a31b3e4f44" . + "3e356a00cddefd1873e96840e6caca01db8c258f6ddef9b511dae23edec3b699" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a71f9c6318a02e42e70947bab16b63623de009d0bc0b710691a92aa0d074b4fe" . + "64aa4070bc3c729b42fedfb2ecd86492958c95003f8f2612e05b6009f38b76a9" . + "cf1191ff79130d5811fa29d6a7b7e74f4345f6f74db21dcb25606ac3edb7f4d6" . + "0543508b5b900891c1999f21a3111b1515c04371f0e68e4d6b4ccb08b11dfeb7" . + "aa8f3a0476ce762b6863fd49bd6544e0be28e8f571116b22d5d158ed62931ae6" . + "18bb545a7d5f6974885833a8753dbca2f6ec3a66ea15284d3aadd82914664f34" . + "931387a6daec22bfdb51db59906dc26691030cdda8621015597bccc724c7b3e0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "e6107a37915c94d86aa1dfeb481c7e2192d481a021aea734e95287575f50e117" . + "3f06f8371c5f37940154fe1d40c01c49f5daa7e1a6a506094a2393cf15819e2b" . + "6b9f7f30e63604f34d7878aef51f65e3b79836c8ebdbfcd0b8392efa0f1100ff" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "0d024244f59fda94db3e35ae3e17fa117be39e734919c5dcf2219662f81f930b" . + "4d1773f003701ee86cf5dbb0b6323b88ad39594eb5f874fcf6aa3ebdcf1f0eac" . + "42a7e17c5445424b0baaf216f213d6f76b97d1ffa5798f646a46530e0459fecc" . + "76f48c971f231c7b48b6103f67c1ad1a309e1482d40406b262d26d6cf0d7aafd" . + . + . + . + "13f349912ea08afc7deb228bf526a96723b97738f09bf1581469124ba2e596a2" . + "3f48de4284560f53dbb3ca92d40b440c96ccfcab0e1a7017c557df96be1d6bfb" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9ff9c4fe8d4aa9f8fc5469de80f1f6ffb00d48b0ba0dc60712785242424a61fd" . + "5d11c7fbcb9f50cfd49d8042553eccbb55d05a20bc701e774d8aafb513340022" . + "d95ddec4dab8273c3b24243a8a23c945a0e5d1541c4a7b71ae26d5fe8fd47e62" . + "6eb3e94ab27fef045aad9ef4920de2a1547e2468ff5c308d6d34784d625fe20d" . + "ecfd492b51ca64be056e2450fd0456520541a22b93cd5e0ad25f30b452529aa1" . + "dbde6f69980426eed960dc5459a061c99547e5f091adfffb8c3b4be6e75c5b92" . + "705b72966b97df13e4c8ab2b47acbf879b8e34d798224fc1ca5dac80886fa798" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "dc5f47b8d9b804d3b680e78067a8bcf9665e30d90fab2608c2e78ebe80d3077f" . + "739562e17cdf1c915ffb38da828727eeefd3107d304cbd02e24028426a9cc162" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "b2ddc59cd4b6e3c7e7a4268a3cb74f51861734c642d47110d2337a94e79aaff0" . + "75d7b83553071018f764186a9ab4d5fdf688939eb1cf0c75a8d912038600f776" . + "a91dad2e631b75b945d827cdc590ba953d43386f1f42f1baac1bc03250551645" . + "75a0518f9f75d2de17aa30e59668358c8b764512d38b85c8410902d2b935980e" . + "4117b139691f8568c7088551aa1821d3829f8655a656e67a1643096d1790cca8" . + "799555b6e301eddc18578ce7f52c884a422b7826ee76cb2c54e4a3a90c83804d" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "56cf89023b960bd71e7b3f6e4ce9c732e40de3f4cec9f2320e4fe3ae21963bca" . + "88b0d937aee913871a949b25986dd212839e05d6384afd84feb8c01a7172bb72" . + "853af52b083aec88ede579cdc69013e285a444faa7aa8524c46d5871795b3711" . + "11cdb6916a029531a343928fa3fb882492aa029596dbec29dbaa15e5efe9df5d" . + "387e6ff0d6a07a109e25741438d4d70103453458eaeb5b2eb20ff06f73a24b6e" . + "d0faad75b3ad049fa9e1206b62fcdfe539e8e32ded128661299260f9aec50185" . + "3e3ace24e8656bd9edd50d8e8bc3d081d7f28b08a5ad8f0823cae9f51dc7e9c5" . + "0ffba8e217b443307bdbb316f8fd89242776984374179224f9e2362b50b08d03" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "a92288ae4711ceb489d8b51b87d9a644f726092ccceeec1035f1d5032deece39" . + "c63608fc7507a2d64601b604fc54ce0147409fb737123a11fee3ce2e95940b46" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "24e0373fddb9ff3006f573094774dbdbd9be748ef32442981f0f5bbb26a71fba" . + "de9398302105cad0fdfd2fd2a8e7cf395227277a5c45c3880e4e171688bda1d3" . + "67e69029334883cd24c078494b921bed2c6ae422001cc04d1e5dd04b62b78bac" . + "061c780ee97558d912961803f85758ccdca485d68ebf42a2aefc8275607b4ad6" . + "1ef8d4c3581883c9fdc2d1355d5f5024e4da3b72b763596cb403186cd9026e69" . + "b6955b0337b2d712b643f88b875744663c74c841372067eb6052d15cd08210de" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d6de1c7fcfe4d89c5e991dfa42b1c579c513128f71e7e73c3d2a99f3d0124614" . + "58048116eac93ea3b7d0e561cc8e055a451199775b437b5bf96c72c82c959159" . + "94d6ccb55cbaaea43b90cf19cdece24965c18ea9cdbd950551177d9369ca0d67" . + "d23c96e902d05b7b353fab241957498f5ed9899e55520334fe70ac6fcfae6b00" . + "9a102efdeaecb4a4ee57fe732069aa0b777874087679c21d190721b45f250853" . + "86edf76b8c9ecb6bcd436c56a50f7d2a37f4decebfafba19e42b3b10a7767643" . + "2bb94d35bdd1ef6fbbf8f4161b21595afb3338a8dd1c4b52aba0b517d2cfdc9e" . + "8156eeffce647e56d72ece30d228cb66593f017c8d92b5ecd8c5a5c35d883cb9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "bd2250d3c669217084050f8b9c4225f7fd5e137462d8828017f28c6465a623b7" . + "41434b0a67529e8adde43e52c7155b835b63ac3c6b61bedd00203e2b57e094b7" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "81b0abe5f1f683c9fed88e31cc57df1e70bd3b4608af4491c481e221f50c8dff" . + "26d49c47d873d10800751bce236b24f372f10a99f1d697a3bf8d1f50b72cfed6" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "559134c86aca986535242ef39e235c6be2b2117ecc1a37b35611ad168b99e6f2" . + "37ccc24d0314cf15717465c33e7c364ca86c36428b5ac1480eaf208db13d6604" . + "ca1e2d45caed772ff1912a2b6e691d65c5fa00c708cb5f7c40e9c5a621f69e2f" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1fb46a26a63e55c6dd8d16c33483268626959345d699293ffaa0fdb95a7bcedd" . + "dcfb8510f1567ccb08af4c5cd0d2d2f3378ea093da1877255353eadb4360e8d5" . + "78c7f1c12db904ad372996b1357df7ccd137e82ccfd00a6288da16c1a9f12b70" . + "e7f4dd6a6057924bcf0648d4e1a624c3cb8142b7a4c3009bc1e31b9eeb6322f3" . + "417412e2ee4bd6dd5856043df7acb856ec0adcdeb6ff280f2fb3cbfd1bf78ca3" . + "ca21184e22b88df453f732daf66e08c2aeefb51649d77c6e594effde41945dd5" . + "9e3264d6a9ed6aa7b63a96bc4d7962c2cc089063d0d3dcaad21066ebc13c1b2d" . + "664e23f733d53ebaf9fe69dedb146fdf1bed71eaa80b9c2445f58169faa55607" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "93c12b5153db6b37ba571972463e6f8bfad1bd554a25fd2db5f96a50e4147292" . + "b48814bac31f442a24232b7c974ff04f027fee7c0ab7e485d7d69e392a5b0891" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8c74b831dca0c9f6df66061182edf1e1e988fb0dc2fc3fc4237cc9d1ee401537" . + "3c2d8953891fea02ac04661849039467a1cc7ae17240ec0421e0ac5b4eb4b5fc" . + "6964adc15507503e561c977d74ef9dd6c3db4d840b7c2113c7c19226d5a763dc" . + "c2316c9bde76c00b57051ba68dbf87ccad7aadca31fead4fdf4c91ae9f7655e1" . + "2bacc6e2a1491882bdeaf20155249096f180da9431073cad537d130a55213846" . + "a73416ee445a00ca0249fecb0d58377f4fb96292598750b986eb1866a704c57c" . + "018dc890e3a4f724c602c0a68736eda3afb6bcc55f5199e751cc421eac3628c0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7e1b440e0b1890cc1a14be2fd5e8118e2b621f8f9204b05a47e9162c8b04ace0" . + "e5b7ed8a27eb293bed165adb7bad9ae5905e1a265564df74811e9d2161f2228e" . + "f635ac02e4b873a9f159d0b9b91c99ea2bcf2cf9552db558dfb7e665bc2ede1e" . + "b1e5f43e516e43aca7b863894810b77f277fefd922a7b1ebe297e2f0b68375c0" . + "5d1c73651d294808cd67a63165d224c6efa8b04996d0100e7ae32ff6aaf449f6" . + "53b9f265545d1fba911a9b9e984b81c90fc34a2b2e8542028a9ad286bd2e04af" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "bf0eee8315bf0db05356fc0b5d6f1f08dfcaadd1bd4373fca7654721046df8f6" . + "75b4af840770c10eff382de53363bdc7268325aad1abceba99d7cb4abefe7225" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "da836f530db55b44054ae59c640773958761f9da64a1e1c0143355de7964d449" . + "697960b2cb6401d13f1bacbf1cebafa6875004abe28c9ce0e4fb5e836126316f" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + "0573769400c68eb6f1b816e8dc76e3173b58e7549f26a5511b4b5fa10f95b65b" . + "b5512533d6462e363cac9f35db39aef86a6c70d9f03d62a3aab4c93f98623eb5" . + "4055ba342a3c4d47fd24832f0856d054a35bb375dd54200d2f13db2ddffaf4f6" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "87d0c809411ea6a3c0e777093ef41cdb1495a0b6bbd36476518fdb759a4b94e5" . + "fe6ed5e52c608c4d6d4c2378a030a1e9aaba8c7903cf32952982817d30c54277" . + "eda50bea4712a4c052c451510bbfac7e00383dce33209c0ceda5ec9571d9a6aa" . + "4fb9e6aca98423cd576d69ff70a9c64974b35c47a516191629c35cd1ddcad5dc" . + "bffaf22c1ea13450c5d4d086c570dfdd8b58d5d8437277843d6c48c4f6726684" . + "044a7176fb50f04594c4de179c1dc7a7354d6b021a1486daf29c61563c6d6833" . + "56aed7f65af4018ad6a17d1f7186363fe65d059fd8188ae7ef2103be84c64ee7" . + "6be077f84be4f0417628ddfdf3e016626c8128cd948f0a8abb673c1d3b012f44" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "d0e5c028809ebd396b77ec9a8ebb57bef3b2daccd71253be1ff456b9eb3f97a9" . + "ebe139a9fa21ca2953b687c2f5ab15ceba984c28f8b0fca7a28b08462d4f3495" . + "70f97819665326d391ce6f78088df980d361e0ca2daa58cb494fa751ac87aae3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "01ced0b94bbc7b87573b8635954ef911b512f3a8179606f0076aa99bc4651958" . + "fb7a54b5a57855bfe3972e481eba023cce075154ce5c7cb27453e4a7ac06fb43" . + "bf89455b33df1752aeb7bc60d8fc5a229a59a834ee564578fff8c1322d07c200" . + "ca79a7ae19d694497529bd4a7647c54d262885be9a82306f2219ad12db4003ba" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c2af37c6b08eee29fa00d5fd3d1f4fc1eed1b432c76cdae2e493c5e051dafffc" . + "e7d3bb07258d2b0fa5bf7d40becea0fc95f39fd211e17c3c2530c601ed8221d3" . + "936a8807c6c84da9db6074df16842a442cba03c87feacb646897c3d5e9091a05" . + "1f05ef0c766f1d781ee845b7b3cba9a78c97ad271dffd791e6bcc43e245d241d" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2aab540176bdf64b9f1c2b998d322cae37b7dfe30f72b25fd845de4b7af38944" . + "cecf6d04757ca63a4a2afa58e7cf465f5871489847af4cff59852321c1ba3db2" . + "8b8515e2db3d24bc364a6bf7a3dc296d44de93cf1379e466afda92e47a5fc53f" . + "d628c311c9388a7ffb4671948d33efc10ecc9e1753669f0e73b7a005cb950f9e" . + "ff191aefb7149f531e545b547c7ff8ab9d7072bffd99838d616270650d8445ce" . + "39ac1984504b87d61e560e048d682d89cb73996a44559424603e98d210085b67" . + "9146841ee3856e066736f7ffef9a0b22be8b8dd27b88f924b923af9538c7bf26" . + "ebfac56b7ccdb3002fed624b132787afe63a4cbad42d882aa70d3b584941429e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4306d58059420253f222d3ae4a432063255c7bd153ee5e9b272028497b0fba52" . + "c70964feb214226c42c0ac561502d3daa517256f0f813cdbfe289afcc9f93407" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "98a1ddf64ec6304513d83d9a66cbe2c40e34b11bdfc1c4bf11d2be145368e34c" . + "c5772953eb097ad9b5ba2d3a158f286410f4167d607d9a93f0b361ff283bc813" . + "61d7740577304d9b7fc3d47774e320425e87b13343625d00343bf4a302c83a64" . + "3f8a3413035fea3b9befe5aa12fcb11712abce9ea4288987da6f7da10eb5218f" . + "a9df01b36151101890e9376ba0d6d91a8932714988e4aebcabd2c748c5ae04fd" . + "266c6aee86e53873fa3ba11497c06d829e1480833fab2cebb8d376c61d090b47" . + "4250c3c4d69ae59dada9bc4d5dea6248e10edf7c859a1ccd18516698e6353f0d" . + "ef9778e1a89b48cf40d8c9b697992854c7db35f67c6867898d45d047bf90a4c6" . + "23084b274236b478fd83abb47b2837b62df51cfa4636e2705174270eced87127" . + "8f2c7084ea0d94d90a8fbf34ee41a5fc64f287825b243c54eefe7b2e7b08602d" . + "01282d573ef277af811355aff4d0ec203cb1ddf2d3cd485bade418fe717eda67" . + "f9e27369b2efc646d1c36884508f3885e8df97d7a9a7b9c8a3735bda43130869" . + "34bc5aa92ed1ba5917d9a07e20e436f3582c08fc263eb81e974b904a33f5b371" . + "4f4120685601762a16b86d37da9c14a195f40dfdb1594c88f247c01f5613475e" . + "5cbf8921a13d8481af638cbe5ac84f049fffe23dafb3fab7327513a732b879fc" . + "6655124372e49512a5460fd6d340c7a2cfbbe89349a7b1b91171a24b4e939d80" . + "4ffffeb81766829f6508ad9e9d88e837afea49bc0bb1054167c7e1537805b49a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "f5423165acf8def8333060d5e6e44875a5adfb7f1a1198cbcd735c3c3bea2938" . + "f611e7eecad6452f12018fd3b91a865a0c27bbb94d765faa3317dfb559660592" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "3014b05636121b8fdfc493073300b9c1e4fe1af3f5bb159db8a21d723119250a" . + "5a9df922e92fcf5b772ca57bbb562cd4ad28992401a9e383070f47d43fbd4b08" . + "35eb8177a0b03b547f135fc0cb0d4690014c7787bfdea03a28661055f5d1fedc" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "83ddb458e76505d3fd4d90660d184184fd9a6f11ed3738fc768f2d9a1c6f9c01" . + "1e40c093baff8f1b48025daa5b94ad9fef4acb5ba58e5cc46892eb3378176c08" . + "240b4c3c8fad2d1687eff1ce66c810f7ea1852af5447796230213526e8f7c055" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "af2c9bc338d80866547199a8ef6f3a16f0cd3b362e803b1b5f429e8f90a6f000" . + "af2c9bc338d80866547199a8ef6f3a16f0cd3b362e803b1b5f429e8f90a6f000" . + "1c3e7ae592f5e1a90b8d869b4ba178ebeb720fb4f4a3518b90904a779e445b1d" . + "cfcd613f3dec709518b7deab8311da34a2a9735dd4e24aaa83f3b3259eb4dbbd" . + "c54cfb38b50d3750464c2b61cdf71b0d9fc2ca20670933561436dee1e91efa56" . + "254f5068d00bfd340fd3691218d7ec50428cf6642a6dcbf12e6696f383bc3358" . + "4768d8c985488170daffd98c280be2b8d0b0176e42dd1db2a68226ac89d4eafb" . + "b102c79d5421b74fd386f33ffb40f4f3a3a3e944619a357aeb67ae3b0aa0a651" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "7d538cd462ba9d9e04ba17d9fe9a2d313d1da4edf84dac9e2ec0d6f825a69e3d" . + "fc00732fe1a11ef425748ef9da99fa45357942734467f1d22e4d69e9035a2e16" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "0b85b89ca3b8fb36665ce95712d301290f0e6ed2950d0d148a799665130d62ad" . + "f18aa7b59dbd0249bb426d0c93bc8c92922a3e6e5573133daf4e2862f71cb484" . + "27d7c61819002d137fffe479a8a42a5782d535b9b3e609f44e613fdf67fe6ef8" . + "4d71a227a27bbee34c174fb418356edb690b58f2a5f1a801379a258701cfc4fa" . + "2b6266ce2b78f553a6094ad78acd7c1bac5bacfa82a98d1d0a3073eab7ae4272" . + "9a638d930e8e64ec91311c812361c4a2a313a44a81bbeace36606af776a2a8da" . + "0f7cee29348c4f8e5ff3780c200c96f0ae15fc4cacabb848a3e6eca56f90c744" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "736f344f8cb8c9f5683daddabf06932b3013db4108f060ecf43653435a4ad5ed" . + "538d008961fc98bb6bed01ac14df9231ef4df245466a94b1dbfb3b9d22a6af76" . + "0b13e3247f0b3f8c0bea29f8c7815d040f9c33539d82e5891725b53866e015da" . + "356accb4cbea9c1737be07d8b2eb7fa6dd52ccafd50c8c8d2a9a35074918b5f8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "d246c1c895fcc3bd14918133f8c4b5f18d63122d36229417571b8f7cd0426166" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "d21114995f86b73c20ed1cd0eecd814f7da4b11f0235455e77f41821f887602c" . + "f383e02934ca169feab8a5cb5a63901abb4c46b0ec4efd5bbbd8fdb14f0044fb" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "e2d56cadb250327496b142fa4f60c3e1a3e8342772d3f0a602c1f6146c0a7d89" . + "e590a167cbf0cdaf54e89982ff4f0e5a6d4aac887db77274ae0b317c66640c55" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0efebddc27117a3bcea16272778e9af86727a8d9102d6245144b3fc925da59ba" . + "0efebddc27117a3bcea16272778e9af86727a8d9102d6245144b3fc925da59ba" . + "46059d28bf12855a55f2b961880db94cf82f5a8689015a91d4b6a48664e40acc" . + "f186d91c7e64484457b0a4f7f5c042ac911210c9b047b3c5f898193664174ec4" . + "d5edcd2f369f7ccd981a2137dafd04888ca76071243ce1e00dba781923ed9e63" . + "37914fca657d1a754dfe3465d6e56b804231706fb07ef8dcd864bf16c91eca98" . + "660e26c9f40520c272d69cd81b8c84e693ccdc33eaa11c2f843d8dea257aeea1" . + "6b147945d89b87eb967ff6f769ab0581796f6e4fa80a9ac497deb2911602a812" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "242726d906eeac20f586d4595e6bfac264412acfea5128004c79df678ce560f8" . + "19d2d14c9251ab3c38a21ab7bcdd58e08e74431b6544d207954fa95be9a2fd93" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "dcd46bd9dce5e33ba2116db10e71db7dc44c817e5fdc023624ca44d357518aff" . + "ade0ff7ded486d1cbdc8f331b10c5a89a4ad9bb7972e443b0046452de32bf090" . + "0c322a8fe3aa0904f3ab49f65317d8d020dda46e9a482ebae51b8df972e11e65" . + "980674906345fbdaf4f3591983f8ce3562872aafc7b97266185317d7f9f7be39" . + "54d0d29f36b09017802885696d9c306576511457dce6903424b3063db93d2843" . + "6c4ef45bf1a2e9878d144a1c3088be58e498ed2795c7009fb8d1d58009256d55" . + "975576dbcabdb9ff196af2bd020feb10618dc600989741d01a9cba666564f164" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "324310887dd91dee00167d4d71a0034a71b754c37f708e2790a9625aedde07a9" . + "324310887dd91dee00167d4d71a0034a71b754c37f708e2790a9625aedde07a9" . + "8b2f9068a70f4af7ad6388bb84fa906e841dca0c21867a597b1afeb38fe1ce04" . + "fd19ba2952dba55c6808c71806dafb9a9e363635907300145dfb1b9ffe147212" . + "ec4c6743127379d328637f868d3582d9a74697d41e5b23d07a1fb9dd24c197e3" . + "2defaf1cfd2d4be9fa21d384f0a699c3753b5378183c026815b16777f063a42c" . + "0ae0360dcd48469dcae3e476c9f521e96f0054a48723d659684af9c42dcebaba" . + "21331051926b1066710cae006b4d2bdf0172a214d3e507d21e29a1a4b99eb02c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "a6e230ab6fc30ec8bcdd0769c21b8b0811867d95876198dc49911fa01021bfb9" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "a5a3328800b9af284ec9fc4dfcb607448acb588f862fa498b00268befc5d34e0" . + "44628ee89bfa6ec1d81282763efde4183efd830c26f2c7a5f92d2b62e61fc73c" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + "4108efe180aebd33738f9ed8c048cf3d7d11a24967fc51b65a5929ffdd149006" . + "02799e38c010824541ecdc4a915d9fe5a136e9f648d9df4bd9a9cd3e6370332c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9208b462db88cb26e604aaebad00af0f7f9c0598fe1fd59cfd7b3115f2808868" . + "f13a53ff91652c830ae73a4d7d604413cea47474df1de31ca8b6df8980a9ce2b" . + "a19c4b809b83af5ef71b70dd27898a3210719e238a20e91a0d7e3eede3136a2a" . + "f2519683ad5f7b846c562b955ecd50da5663796733398250094f428aa95bd96b" . + "4a274c057d00035e3543cb69bbf568cec1c180071fb6a1c87fca8a2c0da48ddf" . + "749e5028c486b9d6bc34b8b05a4c6793fca1927f0c99f6e5f0314cac96a1ec5f" . + "097329e82d7fef7eca5cbebe63add482b032492102058801d06283dbe87a5a46" . + "d2792859dfedb094b7ca6d2d274095e7c4b30e115fa06f1a2bbf58d677f2f8e7" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "00d3df5105484cf78dbfdc5d5a730accd976de53e2e7a3e236bac2117e301de6" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "61aa4eed0cb3372f0fede67aa1cd50c4971be766c2d1d896bd1ad2645b6b0037" . + "04ea0f0b9125cfddd19c96edf499a412663795ca407af34bd4d5d98f90023252" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "c02087e9d039d252400771bd78e8f4eb66a246537fd1dcf6947504c6cc7a4296" . + "bf5530a92d1fbf9d5a17b5fc4dbce9fb18a8fceb65b2f9745f9b5303f8bf9fd8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a37ae289d96c657b96bad5d28bc4ebdabccedeff890cef454f010207254d0446" . + "650437681d537ad5c6a6de87a65caa3631bca1382836fa4fa981aa935adea318" . + "b0a7d32965508b1ed546ba507bd8d33a3deb8bc3ae8b883c375537c3089322e8" . + "3dd71abf5f301bcb59ad00376fbbcb827c3515fa7a8a4133e7e72564e3a00563" . + "3b8125798a652d730d04659366a098ed0f0583cc8b7801a263fa119c5c9bc7c1" . + "c168b986a966e376a554d24d3317af40065192220c22252c5d0e0178a2f5be78" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "95d5a794e13046e14fde3354be162eb0c48515cbc9b798d3d3d453a573b425fb" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "b03cf0e5814a096e1acc0186805bcad1e6eb7cf15846bb68eede5f5cbc2f7b4a" . + "474d4fe643dd74ce8d1fcc5648687faf27d87d169130012652b4ae2279aaa095" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "4e6d6cae96d42c4a414d899d3e5fe294526d7d12e94b2c57515978aef00c63bc" . + "559ee2229354ec29ace6da6690c39332e2f16d207d3e144f1d6cfaac8d575e45" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "bd19cc9e2c7b1933de6a97faf4ce92238a9f324d8e5fe99a2f3e954798ede962" . + "6e0acdf4233750fbff4c8d851b6077bd51b929dada2d3cc76e3c17458047d26a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40ca90c302fa315e099fbb91710d52e45b69d68bb6ac212d9c3cbf422abf574d" . + "d8a249683480ae155d8091c127186899431f278672e172a24c03998d15792806" . + "7169d9d121266a853fa999ef048b7181d8c400181c380142b103a8571cff842e" . + "e46ff1219ef985b5f0d81c2cdad0bcc8b6fafd41409ee6e6a74327ef8eae4140" . + "9860bf5ec9f0b9c2851443feeba2df891263ae0760993c3727636ff102973c7d" . + "0a4a076a9eeff1e18c9d8cc320c2602271ffbd085e43f1a2ca5fcf660d3c57d7" . + "9aa86e4777741d93c5c0aa470d9ebccefa5b39a1eb8a35531e0500a8b14bb14f" . + "ed3296920b633cffc7f57b5065b839388dea0e18f2a67e6577f9659c99291c9e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "c5d375681fa3c040c4643f3e3524792a9f30e7ce3dfed7eee118e1ad56e90c89" . + "c529b854f5487bd1ca2013926ad4e8bd4ace9d344620909d6581f7727b8dd397" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "44f84b226ba73a0d44ce94eaa1892e9f68178141059d27df314aa1209f7dc53b" . + "cc1636f16758c1d11931b59d2dccfe0cdab8ea5072b7088abc2b369a82d551ec" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "7658df422f0323e7b9d67a440b465f016bd1191ed90b1f1d78bd93bce9941116" . + "2e1b46c877585852391af3f64d8daa5c9e4ae1345d573b259a33641cc1328c9f" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "94e598ba6012724e7ae9304499d008ed3e043dd75269f058248f52aad368730f" . + "94e598ba6012724e7ae9304499d008ed3e043dd75269f058248f52aad368730f" . + "8f4f20b1c51c5440beb6d412abf11ea17e3f74009d425cf752b15c24341bb063" . + "5aa532bd8656eaf88e192fcc2d35af34ece6fca0d7f8535426b94d1dbf140eba" . + "82e41ef1674ead0a08a09d9b45f9ba0906f9646193179c1b952525817118be98" . + "54c93e5f67920242e23163cc6b13b7100bacbfcb1d9b7de56cbf5775d4ff9a5d" . + "65710ad887b2765e268db41ea11716ba6f1bf16b497c98c74a9562972c5fde48" . + "21a9bdd1799ae2e163d2cd14e6da20e08f9e0f687967c0581ef24ba5ff9cd405" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b46fb6d87b0128117b0bb456537b58981db30924d9f0e6c3cbc41ea0cf0ddbd2" . + "9f7fad13393078b89b1939c4e077f952eae7fb4ef8bba61d976448ffce614bc8" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "1b818152cbf0c87dc9610215b79e8c32d7ee3051d6e4b5ccda4e96903c0bd3ff" . + "a5c4a70061e60b525fba41155fbdf19df843de3ac862509ab7fd283b1990b23b" . + "0e8ada6473f82c354f5654458e357a1e769a27e0f8f06eb68fe252c6947eb036" . + "33e139c31f2a1a1b5a20ee2c560dd9e3b27c3c0fdfa2d12155fed5a3786cff4a" . + "5f96de9085430e3c26a99a6787b53cf3c5fe76013a02c39b24d327bf0a69e5f8" . + "73740e347a02ad45b5b47bbdf7b293e4619a8a1437a62a62c6170563e764f850" . + "f68733449b3cd524fe0b3d848c7dda32349021c742103348e8e9749b478d3418" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c915f4f28593667cf43e76a14447e3abfc9720eedc36f6b65d875e0238ab7451" . + "d7582bfb30939c39a3992d527da8cfe9df47de741ddd438c1bf1706ac70b14da" . + "76f48c971f231c7b48b6103f67c1ad1a309e1482d40406b262d26d6cf0d7aafd" . + "223522fafc49756641d8eb9abdbf11618ac3fc114cfb888c2f760451b3a49cc8" . + "7973b98835dff1463d9f3fe13472fdd2525e19e744635b69011a094bae5a2838" . + "786219fd1f5cbcff432178af13c79208a1526b5acf950caf287b16eb7dc81504" . + "4b9c60080edd423de4cbf40529e17d921ebe22b8211d3927848d3b3443f318c3" . + "cfd7c575f7043e4087499c9a1a0c1168ff85969c3c5291fc89f24b010b097b39" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "5f4545b8420855b4cf8b8df9bee41d2ba31ec193150ed9e93043d56681f51113" . + "870ec9d550ab5deee28db577b9bef5c644146d632f732a8165aba250731711b1" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "4936785b8d05defce943244a3f23c0708095f2e7e66f70a114d84722192550e3" . + "3afe7b386664ed6eec64a0caadd2bbf8b8c936b4e0538609cc525047bc907fdf" . + "e2bcc98472b4eb3aeeafc7857daf9a7dc3e1e169ea3a463a41c1d74d1d984bf0" . + "75dcc8df13299a41967060e54056ed71093e127c8d5fbd3ebbbed7c15ff34ba3" . + "5be30e642d654428abbde43e7708a2cd32b471c6dd172a354a4c3887755b9f0c" . + "402ddaa379f872efad063ba2b80ab1ccc24b4ee0e7aa3f9a51bee3036224b548" . + "ca826a01d1c0c46da716cbf6f07ebce4d3e94a5df87c2ac5e334c1f0037368d3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "347e825a55439959c180fe8382c2d29a27efaadddcdc32410cec442174670907" . + "347e825a55439959c180fe8382c2d29a27efaadddcdc32410cec442174670907" . + "8f8ef5885d414dfc07abf1a8894c33c3b200e5bfa5e8a22d215afe1dd80a8ba9" . + "574d1dfa533da3186cf322087a0b00a08e60568986f0629780e1f3bec78a7ee7" . + "ee889386c2b62dc4f8295336d9ea031c59b1c91665f600b926e942c4a974cc02" . + . + "cfb0d2a671eaac474a87e3fb33354339ada68adf26f94fbbbd78daa7b53cc252" . + "382f6f1278f3775f7f46def9887bfa8074e34a59358e94052317c445f6c285f3" . + "96c35cc982595f373eec85a1254bcd4b93ea8043420b1ca57ed3154304ef85ea" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "6149335e49f0c0966b8c652f95ebb7326add5abf2b7a69a521066095b73ede70" . + "b55194aa18e297038a1ef1c6f9c7dfa23339f73bcb3e8324e20d38f97ee99731" . + "40f832116cbbcb4eb0d07515cff0d0bfb6e4f7fa0b035d86204d89f2f834c97e" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "352ec88c5766a6a22240299c57cf7ce615b2f1581d1a094564d3a9ec1230d2e6" . + "bea499394e679982a141c2e24a9fa3fd643cd206685e72606f7d9d042b0eed2b" . + "01862916a7378c7171be10e8e42a2c8fe83d2e8343306cf70b3ac95a72d2752b" . + "a1eb521358e79df561de6d6031eb4de61404155a14b4fa765e5b619dcd3a9150" . + "0d23f8479ec4a5d27a98670ea3443cd1dc25e9b8ec3fa524d3b07e5c3d4cd7ad" . + "a4de25a2bd30352f6b20ca18aea1d2ef42ddc7d5abe3371142e037dba409ce8e" . + "8f42800982e083c19ae7462813e395a44fbe05b1ceda586df300d9942f9ff8b9" . + "737048848ed4bf123d96c0ca53bc83d0c54b68070513b9bc4f0a3284608ab4c2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "78322070e48e9e1c50ae918cb3ae1456d37f8ad49534d6e7813c1c2d91bcb379" . + "6b9f7f30e63604f34d7878aef51f65e3b79836c8ebdbfcd0b8392efa0f1100ff" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "5c719e8287ea131c2b74f01c57eeb5d0873f47f4549a9eb65ea2ed4de1307c9f" . + "c07d45f51b6ad52b96a4af207e4b6d1f468a2f1a9757f511b3057695f45c25c2" . + "be542d9fda2eab3fef617c26b256ee969b7c697fea5962b818867f04dc1276db" . + "f26251ad363bea9542998f3d2e4d111ee224119e3161c97e7369d87f9d1769d1" . + "a93a11f267f92084ec2b1ecf7e0199a4d7a568457b64247c65235aa60e5dd646" . + "782c64f36df6241681d62f5fcd0e452477250f05b36fbb3f78cf736bcb164a56" . + "9f3f8e317508fe1ac49b5a5cce6075a73b6faee2a604d15f0a36a74aaf812637" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "17ccbebda30d5ff86d58d7598e5863242348762a70539334596c9823aedeb309" . + "f1fa22657ee2639fe683d931d6415233622d1bf95b78e07a41d56089305ff34d" . + "d225109f9b77c078c1a7c33bb2136267ebc41df292dd2c056f2e3957ec7b2da0" . + "15d34a8885e4b37101edf7a3bae83ecb33826f6ffa6529f62da4873f20ad62ce" . + "1791ea9da6d79613c03845f3abc63a7257694d044dca194ae95f29bd4bcf29fe" . + "c719b1f2911f63c99496b6b900e05ee5ffbf5526cd894226e9437bb3f61fb2a2" . + "15cdff60d8e483308ebe605df1a696b5f2f18d5040ad7725dbfad52503ccf093" . + "257eb1f13a3f55566e41b37e5929c3e5d7e23aee1fd11d15388a92586b972759" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "9c8c7de272e7e9acedee8115eead5289786f995b22416449ecfbfdb47cf612d3" . + "595716453fb2828a67bf5843c53fab0529723fc58ab4397005ba3c37b4f0d828" . + "025f9627d9543281a2df7457ac6aea8ebca5b7586cd3abf89d97f52eef622357" . + "0b2b835b2a384737263c5de422d337cf70f0346f58d2bbe3e38366217bf28612" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "7c1a115a759c9f1b0367106411e542d6de2ae3215ce28e24db4006812f1b3b68" . + "e554a1420046e2da316c2bc2fff0ad2d0c8cbcdfe9199f276a50018e52058210" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "1d5475c98d7f2d0a72c079cd7f8487e7ef9835c6d82accd9318bb0a6e5cabe47" . + "10ba609fab32083604e151ed9f4b96895b8ff63af2f25dd68c1a9c3b05da8ca5" . + "5af34a571af3da20f2591fdedcba18831aebd3818d6baff93c156d4eb601f42c" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ca2c3ef42da39561649722a190c6d91052122513bf7c8014cca8af1696926484" . + "ca2c3ef42da39561649722a190c6d91052122513bf7c8014cca8af1696926484" . + "4be683760c571155c942134cd90ad344c8e2af45e1f34170608548ef2a3816ea" . + "336599bbe358f828d1b9f481ce9f721240300fa89e2f1ad75e46854bfb6f66e5" . + "2f318d1db168b9a26183feeba6228302f86bd26807c8a52c703735fd7f159e7c" . + "2a5f5de3fe08662e8cab9f6abb69ad6ccaf42eceef57551d3861ede489c015a3" . + "d6437145ba27de4b1533cf72408f8cdf454f145ec56c4af0c9baa6cf79d6fc88" . + "fac09beb0869354fce4de572df5bbef79a9b4d343ac1b08ee47a71557a85b89f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "f641b720d747f6482f19b15a409fb04b3f4764c426cc5795f79d94c15425e927" . + "ee5039a3508fd5145e09603935e800489d46c0269fe8088b2e1be0f43ac1c6ca" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "78fe9b33cafe58c172914578844edb2fd35543ea84f346b4fc6969012eb915e3" . + "f6dc55138b928f3408924f7523b44cf90d80a2119ca4a909a79e70d2aaf5d54e" . + "4d1eedefa671a2d866f32e32b8ef6730e732de355bb58b1b8b0e0ec66eeb9665" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c4feb5601b88fd24e7d43bb0cab2eff3a152ade9b753d24b310dc7ac1b21e2bf" . + "c4feb5601b88fd24e7d43bb0cab2eff3a152ade9b753d24b310dc7ac1b21e2bf" . + "da7c60928ed0f5ae3751e05a98bfc9f2373630953ab24755715707e2df7b2dbb" . + "5ef309fff5f463844a335350859bcf0402d31ee2bdd4fe1ddfbcda717adefc8e" . + "8d8739b518ee6132a1a8c0277face34819963d20089713b2b5ce4ad49fe7cc02" . + "6530f81e2aa188fe348e74c9b2b906f15a14670d090bdf861757b3f684d92d61" . + "8d9e12aa3c2ad4d4e5813ce59967c9134164bef6ee73313bf392002b48b781f2" . + "1a3cac4d6ae4d3f325675f0baf2aa131a48593b31ffd57920be42a91ab78c2e4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "e2c9834f8d316341adaf54755d9dd67827a052218e32a1af06f2b2c2dfc786c4" . + "5527076394969e96497c24a8797d56a54269648c73a6ebc1f17dfb782f3ba93e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c8bb4b8452c0c4a6c583c8d4b9746907e90d901cae6c95db3401081047ba7e55" . + "9149cf0be2738e8678e15f2cdb38434608ac0a7c2d8e70dfb0ed5e8234ded6ba" . + "244d8489f4457f39bc3857b831629b1e69291c286dd80eb711b6e2ad75653a8a" . + "0db1e663179b1ecadd333b0e873dd8daf752385484c252042bb59e9a68f8f386" . + "fd14105b47521e708f9606d138e68d9b6da9f130c4b40eb897a25a348fb53c19" . + "19456cca67afddbf06110813deaf7ceed632752ea3bcce0dd480deee802925c1" . + "58dd5028dd4f2268250a39f08ae6a55f2776c30b6c8116aabe48068d20a7fd11" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b45b5d196a43f71049eee793e3d7ca57b25f9049ff2ab817487acba2bbb13c61" . + "ca0f55749e3e36f93c887afb0fa28ead2ac5ca99fbe9235c41a03e7eb70f8564" . + "2bff339f4f3811c4c00c15fd37142a6adfd65e9aad96c2ad6e9bbb28021c07e9" . + "ed69c370674c9c9d291443b7ef5a891185400dd0bfe8908dd3fc96449da34d24" . + "5c2c8fbfd3109574b89d9d9a5c902f5d8cd26ac723ed210d8243dfa498b88ed6" . + "fff1384451d2fff64da3ca6536b3a253fde2a9f1db3632fb3e52ceb8f0f4d22a" . + "a29f1d62ff760c4b7dd17fb6ff1623005ad30c285af9844b8eac2140c794c0a6" . + "b0ef31fdbf7f9bacb5794e611412311ab5e70004844fb9a77ed7b3c45c0bd984" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "86435d3e2fd5f0ae96bce07240d43269b99f02756d46b3d3b1452d89db8db76d" . + "724445c75619cc899e135b3aa1f7386a0d7aa755190e4c8886e79bea7cc4b396" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "bc7a57d8338d6899799a541709371b54cb4f4c7f22291fa447e55ed7d93d8bfc" . + "978e227bdad6802a645b4054ac8fadec8d61c71ba11bd35008e5c63700c10ea0" . + "02ab32f24c24a4d0f408da8d5806ce9b1605191b50a8e8075328261bcde532dd" . + "5e2aeadb587dc88db24a593c90de8f30590e972f42f0d52f86f4d5b120038cc4" . + "620bd6bfa6f11c5e5a877d93440f6dfeb1cca36ee0ca0f9df0e64e7c0fe28e7e" . + "db4074493e0c70a83070962543ffbce510d3f6fbf365adea2273ab620ed0eb73" . + "0826fb9bd33ce43c400f51cb87c4936764392b50b03fb659f5fb4d8117dc34a5" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f95b02c8ec8da90b5f3450526f082f0da7cdc9310d8f9903283b7477814ef5ba" . + "9a73186b86ec489dbd888659579710a47cc260c3ec93b49f673ae77b7061b025" . + "58e6a1abc06f48070f4001f2eb267dc56d706b672802c57d73ea634f9cdd9c8d" . + "8b3726c4c1317bf4e22f1bd0147f5d5b76fbc6bfd643c5e4757b6408985a5eb7" . + "712b97d703af7f770be49c4170d48cef7fcffa5e6e04649d99a4cfcfe56f4511" . + "8f4059f657f08511100bf476a118e43bb17d83327da3cd4245a779ca7da6c155" . + "fbf3cda1fbe45b96228deb25d3e48c0b09e4ac67fb8a8922c1f7cc2272f878c3" . + "7bba9fc52bfb701900b6e4b3f3e5d6ffe53c0d1a71ea0012d777dae1c2cbe004" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "4f6a5fb040c9a58628134dcfb46a3e303359faae9c97c480a2490c4cbacc3a27" . + "83dd9957529b255aa6665d51e8a81522c58aacfb79b243c490a5ef8d3abac06f" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "77753dd6a1a37d16f2266356a7b8193eecb8338195af371b3e19e4c58cc6f30a" . + "76056c1396ae98982227c0297a4a624169ba3e64266ffb74d3e06edef7230cce" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + . + "0805974db7c6e8e0242271eb732f710aa39f9ed15cd9e296c08246a22ae091ec" . + "12caae101b78ad49be1b95b878b8c3873310550c12d19359137531b3f291e338" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d3443c70ca7aa5547587da5bd88316abc518cd758faa4f21b63476ed904723b2" . + "dd22264480f401ea192df22e8c980ce1936e39da435b976d0054a149bbec48af" . + "0c968d4a9a3c701e90146a136656e1d3586041fc61eb5a12088e4bdb191d7a04" . + "17266fa4e08cce08ac41d404ad5b0cdf5e3b7a26a81d4eda18bcd3dfc318ff15" . + "6a75535cd71b221c17919d569c308dd1b6e107676b22f995e5729a4f4147e491" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "e6107a37915c94d86aa1dfeb481c7e2192d481a021aea734e95287575f50e117" . + "ba204c073d7e09c4323c5b9f00d0d606119f44fe604d8d15188bc9fb9f72d9e5" . + "9634daf09b6750f44fa7c6962b99d6b0986b3fdc681be865076809b66bb006ea" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "4cb6017cd29cd5915ddf206f537731cad81f4e43bcd5b1cbae1ed4b0686f2a72" . + "073ad4aab3e7f37edc5dd7b29b1e47fb6555de5f1887e5bc8fe7aa88014852c8" . + "24bb2c7f06c9760496afdf12e7e25fa7ae8ed18b108775cd9ec79f0fda5ca6c2" . + "d3d24769a2f2f7d03c84e7685115a1f3fe4c906b23e98b68fe3f77c5754a1a20" . + "f1b6d79b2db81de9920a75ac34592c26bcb53361de960fe15e22d252abb233a1" . + "84928c58af33989b1d4c106cfdfa2e12d0624a3d3970fd2755d9a7937fa787d6" . + "ab8133c70b708c5adc548bacbead80495b06f63e7b0bb83f6bcc77b77c02e8bc" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "899f08792be53ed606cdff746b2c20d758d2bac9edc8854ab0d001e9dd4c80a0" . + "899f08792be53ed606cdff746b2c20d758d2bac9edc8854ab0d001e9dd4c80a0" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "aa7dd807dc2024e8786a3d25426e8d32bed2580eb1da980779dd848767ba242a" . + "2083582b998a264ed3958d242e92fd611fb07aca05758240b22c548bc6010800" . + "1fee4f02a743a4d119caa7969441c84b03e9cf11270bc7f3a81bac145fc4e6cb" . + "1a317312fe819b2105e024a6ed3924eb9bbf95d17e8b54916b02fd68aa34b68f" . + "0ab17afb2088543331c308525d06b1be9f3df0dc934d486a1b25b740778ace8a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "212cd8730f6e9186f01e96148b884b356b1056dc0a1a1062ebf2eac573f543b1" . + "129873ee7ff3d1db5108271f71504179512a607fb55298b807ccffde4c8072c8" . + "18d6c634dbb8fd80a71e1d621c03dac47db6c1cc79d1ef0997db366151b8b8a7" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "d461d7b8dbefa215e4801ffa9f11e9d5b5db3a9f4dd8a2c62d62a70ecd35a020" . + "3d0a9d8de5925599c2b95843516f95f094237f08ae7e9e8696ea929e0f7ba7d9" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "22568efc19be76d2c9513f632799cb8718820c4697b184bf577ef834fa5f9cdc" . + "768750fa4ba4e5252e900f77f0fa43edec92d9f9d7a5bd85a624808e2a9e97eb" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "4b798cd3465cd40eb662a4d48c2ce8e3aa78017a0183a80a14da1f4974cf7547" . + "cb637585f30c8ca50053feb1b471871fbc6de1f54d9ca2b1ab1652d2084e178d" . + "cb637585f30c8ca50053feb1b471871fbc6de1f54d9ca2b1ab1652d2084e178d" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + "b2e51a6077199655788dcb7fb05a1fd69c2513d309d0e864addd9fa2e6f92d27" . + "e6e0c62ec0990a5487c08f12d398668b0fb3b102cb5a7a5e8257287966168566" . + "702f2a22deb8bb61931cadc6a08c8884eff13e84eaeddfab5eb797234cf19cad" . + "b6ee943a9bf229a9a0fd2a1a22e4eb1a782d6e03181bcf335e31cb371e96208d" . + "67893849888d9d202bc1c6879c795845df5a775833353e79fcccbd85e94c9b3c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "d882bcc57426b3a62ee4c1412c225c84bc0afbcb45654230b6be03a94d421ad6" . + "d49013d559db92cded82c9208be5781f09ab634aa9d8d3f5ce41ade9d434ec10" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "fb2783270ceb95b5f1d539cc69aff8f61db6f100d61e23b4491ef7bba0edfa9c" . + "e8d2ee04090581e5d459228b8baa00f92669972b1652ac3238264e45284cb127" . + "0b215f33a4782e72455c0400543392ebf159a708532ccdd5ee1861a481534eb8" . + "e44106445113c9816ebb15969d270e8cf5f0315eda5dad875a62e54f4098adf4" . + "481ae4f5856aef150341ca4770399abd822d705bb82559d6d8f6b397a53123d1" . + "24a82f7f50326c240b59cbf237a10d3876ebcfba64e8fdef2cfa2a583db6d292" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd72ce7ae2ec4e18f4fb238b9bf5383d7fab1f25fb9ec2d78639bbe5e1c61a3a" . + "cd72ce7ae2ec4e18f4fb238b9bf5383d7fab1f25fb9ec2d78639bbe5e1c61a3a" . + "01862916a7378c7171be10e8e42a2c8fe83d2e8343306cf70b3ac95a72d2752b" . + "730e0e595d7cf2883bb7a1cdfdaefc6dfcdeb2759675cdeab6c17ec85a608667" . + "4ee4611a5e8a57dc13b3efaf9c5ccfe6d4ae7e64770c63df92c02869318166bf" . + "2b674837f4a1d4fae442fc7f43d93b3af3edab7ab065456f0a56c6b8a2c762a4" . + "c76c50ffc3b6023255e09f0b26837a0f5328ae7a78d11aa5c4aa4c6969e44b44" . + "94c8d401cd51e41bd21dba3b6082da910b20c08a9c0eada6684e53ea3e57c72a" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "f9ac7385683b4f21dc21de6fb61504221c87ec6078f71179833c4fd4e2e9773d" . + "d01e02df63c154e7ce71bc3f3a54a11a76cc3ba205e92e7306426ef7cac0df87" . + "2e4e92ed427f2284ae25855389b1204469e2fa47891726bb147fb05990f9cb6b" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "4090a489ba4ea1238dda923c3a7c8ee2e2ade6310c15f7b76853f5d5c4c65eef" . + "1364a9a8382cc782a285144e0aca3545afbfae9d04fa49be6c729ad82884958a" . + "73730b2bb0aead24790c4d64a461e44f584bb50cb1f818185860a15d5b32c6fd" . + "c11ebb80aa5e811a0bfac3d222beb94bb9a8b816456b73117bedb06456d4bf3e" . + . + "481ae4f5856aef150341ca4770399abd822d705bb82559d6d8f6b397a53123d1" . + "fd4118251d1446849fc3d8cd2b4b1d2eb7e890f778719a93ba9e423328c5a61e" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d673ad815135b801bcab83a9de576a9040f8f76614dbb16c6bdca286400329d0" . + "b37844347037104e5bda4e2ff110c4c09e5018b88c823a9a04fa61647db9be0a" . + "6368ed9392b839fa3f31b375a414ca7b944f695bc8316fd9c17e8d03dad50b84" . + "5245e5cb91458ba2b3c63795a1fb40bda74e4cc6d4d965ad6ee2cb02d5f5ce85" . + "d9c895b387d6c8a5808a35cc2f75d1d6f585f6a9016ba89e555cb1e97f2833dc" . + "0476d9f14060a1c4ed51554999cdb41bdedc58088d4b5e546f7f916d3601d730" . + "4a5452f92a34206835f33835a7b5be2ad1bc0ca815d951e884ae30d759124545" . + "22db7aade7092fff91f0819b5cf171a75a2dc6cd7e363dc5d1de953720d9f458" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "32481847e03ffa70dece8ec78438017393dea5a8ab3e7c025bc0556eb081426c" . + "d713eeae77b7de3705064c30f8fa987283f824898ae35373e5048a24508e4464" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "88260def63ff9aa8281562877881c504585e36f16492b9109be8c433be921824" . + "7e0086352a18183bf68f863a6fc719ed5a64c4a03c437ad6325213cde8b19818" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "e3ac7152a4d58e15de8d215f780aa5d52534948b196c08600cc9140da25a3310" . + "be48b45e831195735e90c7826f16ee0d66f9b4248214d4d74f2328cbf3da0555" . + "11c0d1e471fe93c6db1bc1c26b2adc38ff5e3584666690d1d7c5c85241dbfab0" . + "904517e27c833b07ab825c617539163638854072fb6b53049912798c047602a8" . + "901f069930e873a24923c2b22388b2cca4edb1e21393898421f94837d5e2562f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5fb131517dcac320eb96eeb549811188e57578ee11cd0ff371fa26eec3f89ae6" . + "5fb131517dcac320eb96eeb549811188e57578ee11cd0ff371fa26eec3f89ae6" . + "735f2f341e1f6125dd058a00d7988851a8d7f72b45ce5070c2e499ae37326661" . + "aefa0d25334f30bf1e7bb0381d6aa43326e12156df3414ccf712977ba101e7f0" . + "03fb5eddc03f2a64514ede84c5580108a04ef650b8be3fd1ea18f4cb8910c74f" . + "2603e2d4625e43eb08c30cbeb66cf4b7897f84e3f98a8b64d9a616818beb2d55" . + "29395c404a3ec8334c67f241210db97df104c000d6533ad6e9f500b7dc4e2cd9" . + "075a46d57de2c762dd629dd839698775ae246b81c0e2d5ffce95d0ca4d067e05" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "afc17428fb87cd6f291643552cd25179cf0fc49baf89d1099682a7f271356139" . + "b02a1a2cb35ed1d65f3e80083b7e3f651ea96ef870778871fd612d39a8a3c848" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "d6b71f92ff213d2e887d365b7c97de1a62dc5a21e93540dbb633716efd25adfd" . + "23162572efdf1e70cc86ff9f64a280c768c3381daf16cbfdbf08ed427b76e2f6" . + "2f90e7d651a611dffe7a36d0bec7cae392162203b0d190809ba8d7a540f49024" . + "6fc42bc70817b5a86c9be6982dd12e0d31a2f005b6bb61b249b196f91cfb6901" . + "847ae1de2895e0fc57d566944cabe7e33c7c61282bb8bd26f3ceff7a5b718205" . + "16d5c4cb8cc05b8f83de6a416be4fbd18ff6e835b4c9d53baf5a39ac69b1493d" . + "4b349abcd23cf570152b1c75b656dc79a1a6e9afb700f20b2f2edcd9b54d5a9f" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "aea0d31cc63be1bae425ed79b3055ddb0c8ec5706157169dace382cae6a75f8f" . + "9607ececcd0ae1ee99614c7bdba13327711a6f723732c95950a62b5f43b3eb1a" . + "3c6f7efda453569f0871d90a8676f2cd2e98e40489667d9cf1894f28ac7ba6c7" . + "eac349e69bb10f32058bc03913dbdfdb8cf2717b5b1703c6c7535b3c9a058748" . + "19b7e2d1100e0b5355f4ffb93b4b3a11ae22719327480ac8b70917c7e86ff6f2" . + "9353f76227eacf3b3d20b60d7086399d87e0863ac5a9170070f274cc3bf4ab1e" . + "1444cffd945936b6073989216549e49713bb1d5f290246833a29148a48c631d1" . + "6430c962714c336a222084bc36cc1e82a4d8c20e37d326a34cccfdfd912538fb" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "58557c4b8bb7f8200495adfe2ded85ac9e062f5a12efe2b7886105686f2793a7" . + "3a0d610c435286300812fe0ce0ce85e3d9354c5e2d75cfa13beaa9ef6c7d3e53" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "8cd3dc0070345ad193ea150cc88aa4676df02521751898ac38a569d8b1672ceb" . + "4bfe9a4630dfa0db26664bba9ad938bc2cd04f655990b500331c5a133d0d3f01" . + "643b9b72a4067674d8441d074a3ff8bc87dda4c7dc5ed39a4e54f8de29de45ea" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "cd8912a4ebddc10da0b94ae1d7c49424b0489cc27172bd3643c0471458cebfb9" . + "54411664e1ad86bdabe3519b4ff364cf33d8e780e59d217db4e96d6028a913d5" . + "6e9e52dba05c06429449ab96eee9c409188bcf04d949f072afa3aa068df3e277" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0b453890f6d107f1e21480216122ee1ee7e7ef375fdd49cfe6b372c8633886f4" . + "0b453890f6d107f1e21480216122ee1ee7e7ef375fdd49cfe6b372c8633886f4" . + "1572791ee2e6845a7e1beda62bd2a200b9c9c401c543ccd7e72fa4d9d7c1ae7c" . + "657220c384efe11f62ff4d093cfe4e6aeea433509dbc40cda79c050207b50e65" . + "dd4028500698213c4ed7b98313df322987692c2ce13cab811c567e82d6964745" . + "26bfffae94a2f439cefd16fdb07a710fd99a5863a355486f96a2b2fcec5b67d6" . + "bb655d99b221881c85f921952fc0a8e265bb873d1beb18d1209360985bdc627c" . + "2705d977842af344218b1db8c467dd910b9c057ba3a40defbfefadd4b6e3a0f8" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "ccf9dfa4f2812708034b9a00d6428f3e9255930543ccd3852f6bb7545283debd" . + "7d538cd462ba9d9e04ba17d9fe9a2d313d1da4edf84dac9e2ec0d6f825a69e3d" . + "dc110e931e3cc0759bb9eafd37dc6e635105cff765e445c300924965a53e0e7a" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "b1bc7bcaad97245500e2a8f95571ba3915bc3afcd24fe1a6137e5cb49fa3f3b6" . + "f9418008a7c245c1667a24e6cd343871c70dcf24b07639c7fe1156f63c725a84" . + "0c4a81e30afb8ff53cd237bba8704f62fc458d95529f8ded120c8849d123259a" . + "51263000e4c11ecc95a462a8071274751cca21c0324df397fa9bba5b3097b4b7" . + "92b6343f175f39935e5532218087e6dda05dc674105fbbcfc176e973761bf422" . + "35ffbe8aaf438b111d9dc83deae5874711ffe10427e76555997ceff46c347fbf" . + "803f3082746aa63defca2e99bce6ec5966cafcc8f23c501895ba6934e0bff851" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3fcabc81fad007ebd4527b62a317db27787ac406a744a8431f3de567eeccc0cb" . + "3c0f98274adea540ee689eef7516944da9ba7a4f987272f012f36608ee00711d" . + "29bf7250fd687c41542557245baa5a0ea36172f0f7cc8a025e4a71a02c775337" . + "15b338845389d9edde9ccbc4023687a71ebd99b8c66b258df6199c901728527e" . + "99930683ff28e71b7ea9fbb8fae58e8635c1f77d74670708be221e7b63a8bbc8" . + "8a97fabbf3df53bbbf19a5deb6318ab188da2a7c2dc166b451859580f4e7bd6b" . + "90ed62c85433ac8dfac2cc1819bcba70fa846ab5695a774ea67712ec7a982e82" . + "f3ba1c55343303dc25ba8b5cc44d465f7c616393c5297eb73c511f8c7b64ab70" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "1f86116d144214900b632c9785a9a28b6ee60fbe899f41aee28910e05c4bfd8a" . + "0076004ff180226ab12886f9002b482bdea35baacba532bf673aafdc10dc1d9b" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "f1dd6ae770dc4a5f4991f6ed878a5e4213e563a61a624d307786c631073e4ffc" . + "70903d1173832e6ba8c26bbeea535f7f91ef86c4495e9205e501fe5472291ed1" . + "0a1d0202761615469f2f1c5b7601e9e5444dc6a703640da217609f67f8add44b" . + "a8ca84174b2891cc52be27f68ef475d515feda8915301d0489e5e6d2c52f5680" . + "49e758250b1714c352d71cc881d0d7b719128e82896014937e20d8bb80c5590e" . + "c313bc4eb390f8d954a8aee2038067afa63dade6f98af80fca64cd860c8c5334" . + "b1f1fc2ee574a783a1063f1fbe6ce6a4d4bb90ea2b7d6a238481a55b7812485a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a06fd9748f8b16b188407fac8515ea58166a2b679fb54e4c8faac5c994633408" . + "7d06eb9835b6c6dce0e8d1fe09d1d85733eafac2d49830ffa355bb9a5235250a" . + "1a18cfd553ef3e22aff7249a7c04d2133e36a16c1e82c91b7363029ff34a2c27" . + "3f0af0573b2cf9ad2a1da90bc439d79032ebd414de1c66b79c7f30c18576a3de" . + "4c8ee56b7a1de31164668bf63b33e0573b39e339302dfaf92fd3a41b3b824190" . + "fb36e8f3838077d9e6e09da2d2a4f70860d4e3ad0ee5871900d7f33f574a6400" . + "95be12d79550c2a9c437316df3712997cea0d9ce494eb57e55d2894aedb8215a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "2744469abf6762a6f255eb870a9847e6a1b69ac0b711f5d9969c1632e2d51442" . + "f1e4382cd71ec590618be1825c92810a4a3590297fc2f21f3eda37f583051346" . + "531bb581eb3900fd41392ee49b475228ed57e37500e642439e05b283d05ea5a3" . + "ddbcf52271034453b49d85c3ecc66332e89dd2373f4dee22a48954df37480066" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "78172f9ea98b5f2e4ea1642fb342227f8e890a89f3bbfd368f1d606476c3114f" . + "a4de483fe5208fa099931a2ae2ccb2a322410c5113718127790b96ed0b15846c" . + "44db225f66a360ecd83bcfc157bcb5d0bb6bfe4b9b7e441d3b52dd998546ebd2" . + "9a450bd66fadbbf37706719bc303b55100db3f60b9983b2bb4f99e46b2fd9e6b" . + "062461fd6ee5a99c955646c38bbdd8fb8b1471c43f21574841e9028ec1fee273" . + "6c960927223b13dbf29f1c8733e5a167f3a28d2f09fb5802c3ccf075322580b5" . + "dfd15d8659c0dae63589df13f06d2f7843ef7a2d98ad39f1cec6ae70b6952c18" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "eb6df709b9f967859999d05427643f07f6ed9309cb12404a6c241e6196bd32e5" . + "eb6df709b9f967859999d05427643f07f6ed9309cb12404a6c241e6196bd32e5" . + "eda32dd69e1a98b8108bddab5c019471f8ed3477aab78886a2e8b9d1cf16fa0d" . + "929317d9e1196da0e764503069fcee1e1d8b409665bd0be9a994bd8879ba91e8" . + "59e27cb455897e71a0fbeef3c1c9a8b18fdd708a96b2d151121e5dd7375db9ae" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "0711b9a0772d1385fbe4070b6fb722dd7cc21dd61c6b8c6d409bd799929d083c" . + "dbde6f69980426eed960dc5459a061c99547e5f091adfffb8c3b4be6e75c5b92" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "ad51953113cc34c5206e04464408e24fb3b4c964154f98692dfbc9ab24af0345" . + "72f6d36afe0ff5269e1d60cc8f7c9446429bb19466d4c4f5d42b149608957152" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "3e8b56907c9bff1d49b7034c8e616b4788cb38c11d0064813e20beecf23511eb" . + "f4e7ce9e581a44a83986b6ecd28bce8bbdad6dccc93d8d7433dcfd440cc42bc5" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b2f87439d80b7649a4572997829906b7df01e7e7ae0f0e9f9f8c955fc6864611" . + "26e583639975385b5f7fe04b442e7ef0e7ef9ea1504acd9fbbf1cb712c6db21b" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "432fa4ef2307a0622b7eb2c695f24b6ad3faf3385a982c941032ab5377c7f081" . + "a1f49a69a0cdd7f9ff95b0230e7308d4bf598ec5d50df423bdd7abb46c648fd5" . + "e5db156cebf77b4e9cbe576e9bd69ea8a6d1101d224d2b3c28c504bcfd191c8b" . + "810b6329adfa7cea1bc7bf25baeedbcf56e26b762e3fff8045bf11276dd35325" . + "aff797a16822a1c8e2eb719a5996c4f487ba1789f7cd264b54bf3b97df5f34eb" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "cb804637fa70735d1e361352b31c7c0fa0eb421d188cf623037b366d8f6183ca" . + "f4afd48d4ef7dc85e913e0b52c1e04b2896e54ff653d068c59db53a0ef26cbf3" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "96b64fc506a398b355de4e300e2b490e2ff2157addd93de63b8fcf70a6017974" . + "384b2a705bdeddfa5ad37e9f2572d2089df41ab42beefcc3c8f4f51a186f327a" . + "88ec9634a7a54b17a7e612b852fe8bfc60932f621b3923e5bb576d61136467fc" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "4fb924d08563213784fd03a0659a111269728f3fd793a223cfffb17e15dfbbf1" . + "de5c2cf53cc5777dde14175085c27f81ae1c07bc5c6d31c0f456c3d60154fba0" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "446312ea35b7fbe0f9d6f0201bd2cc81e5ba88ec744a31f812c9ced40ed31788" . + "b8227737a529a58052508785c0bf16a5dfc27ed5d882a5081fdf24999deda42c" . + "3fa9cb2825077d6a024cf1470d59b659086cba9a244d03e61c651a1ab44caabb" . + "3d143233d6f81ef279f2deb594033951ae0ff677aa182cc71e12c7c574326de3" . + "ded5826d430f21594eec755067d1e190078402f9f0bc9c62bd18c96096a877ea" . + "04205639b42d98f37935d9b7972190dda955657fc457e9d004ee1843e1147595" . + "25ee43e655dbadef9a0e3f13ba00b1cf9c1cd024fd03ee4e9fe8c55012d09f57" . + "e7f580c5ea386a966158c0fd67b68b27585d1c1a4bcba0da1844d888cf88cb9f" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "b71f63f3ad2483a1f1d4369f2433a70a3ebbc3fc62af087578408f297b14e8b3" . + "f85e4cf6c23bc676d6161677a602ad8cb6dac4d038732656f11cfbcfe3e8c6c7" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "8d0d3bbf8bececc06dcc5806e66d9a922c086f4a891ecc6b2d79c63d1498f5da" . + "490e8d9c6bf101ca2d1e662b6735e270eb195e694ac3952141a624e1adeead14" . + "188e0d2c8bd98e90d47b7ab116aa5d6c0140863c90231fc25b70ff6e25338ec4" . + "bb10ac23deedee64d71db2eb12c9d0abec7008392ad35ffff806ab948fffcdc2" . + "9a3c4aa76463b02aca055207d778fb20b5f67776fee8e2830f4efc07af39a4db" . + "ff110e789e1bc6e66288a09f7833fbbf3f31594cb3ef7ecf8cd2419c96c7a9ca" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e9ad7f17551cc099db2014172f1af3b35f3f697bc9e7bc79202092dff2b3bf7" . + "5d455837ae22ff7e97a2bd2928111276c802a8ede60c957aa0f09680d29d12cd" . + "6905cae3fe76fbff89643e3b92f8461d68a5bbbaf055aec2a1bd990a28142a3b" . + "8419f810ca25449c05b5aae172d82ead7242a41837ea93d203120e8b55e49b47" . + "734e14d139ce55f3e9197ff8717d2ae68fcd78cfbd25a36879aad52579c6d0b6" . + "8c7f37d4da3457db9fac140799b1d5f82d6460cda50ba64a14078091dfb20cc8" . + "c95c0ba61c71399ad881659512ce1702570eb42ec4962230fb3e26338e038a47" . + "9bf6b955ce91f5be095fbcba5162e9b235038be0b23cba8f6347c40f3a033ae9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "9058e97ed6280f6f3d67edaa2016948e7582680659078f9c11a88023d53d0395" . + "90ed62c85433ac8dfac2cc1819bcba70fa846ab5695a774ea67712ec7a982e82" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "117b17b63884f55511bd83402235a6a9cf95ebea39a4c43b535140dc79731e8b" . + "62c249c7914f524320bcc5226796006d43bd8f3455350c466e5b130138c2256c" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + "21ea415e97f213b608b0416406f3c913d1878927fc99a4ca8896efe2be271f89" . + "141411658c0384f32ce49c2d4bf9c518df99ae4529bde95c0d4bed38617b3f4c" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "15cbae5d2ebc6469d8774082d911d8c33ccb8309c78e032152e6b15c356752cc" . + "15cbae5d2ebc6469d8774082d911d8c33ccb8309c78e032152e6b15c356752cc" . + "9c72708e1391a61aa9272a4bb15d3d229bbf6eb5e9ec7a99086f23288d7193e9" . + "fecd1f75f25e6352b904679ba26d5c369fed37b43844a50cc7c43d00886dedbc" . + "705e8ef374aa4e4a6a6b8eb96ce31d29d5f1584f7a93196de45eeea3a1d9b878" . + "3151c6fbc0b56e800e9ceefdb5b3ecec74d06772799c5b4cb6ddc3578503071a" . + "ca8bcf26bd8e9b792495f004bfd6b6f0948fc8972f4b933e355713b8def28f3d" . + "129645e5e6c739af515f2803887633654d1b8006d467abe81ff42b61d642870f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "07321fd01f2cf906d249fc74629c3b149dd13b230b8e9e08e223dada833e66b5" . + "5d66435e2d700af4d16b1b61cabcc975c23719068a31ef60a3514249951408c8" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "4b777330471666314de3e1344ee7e01d48044016b5ad71e2e736401964a78d27" . + "77560da95e2c452dac20c767f1438a0b91cc71132aed7063b6296b372a9d73ad" . + "6996fae59714f0a0365e23409e9a5056a141c5954bed3a961bfbe8bbdbd0c611" . + "c46f92a5d3fc157df70029e24c6b8bdf27279cb878dadc3cf689e92d429ad404" . + "0cbf1b7c989a9cac35d1c9fc0ad844f6be47bf6edb5ea4b9d3194e897961f77d" . + "f7961e4470b62aa6aa8c1b293dd01e7d2140182be12913d74b797b9263491447" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21a77a412d4d31eab2b607fc80201c0a93f50294790c51a5d47e33d66f6ab242" . + "21a77a412d4d31eab2b607fc80201c0a93f50294790c51a5d47e33d66f6ab242" . + "da8839b5563c6eefe7398183ec47ff452fe475be102c453bfaeb03f6959c1ba0" . + "6b3899335003816b51f13c82d2b9c24d25873a8ee919040f7210e1a4c8634899" . + "4897709e3cd0c44ae6c549b51755116b31edb7dd71af2283ca3fc40e355df5f0" . + "b98a1436dd1330741446146ba3446b4a743f3b91ed08f336dee8870489f7c01c" . + "895e34ae2269460965f5d394030dfa7f6a76f8a3fe69d38ba4b5a809ad66fedb" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "cfc639aa4adac0345cf58966e057857804fa4ed440d32dddd3db55bc4ab6b118" . + "e07316f69244f340998d89e7036463ec637538f4e1d7eb8d881b715b8dda6e34" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "4e7397722118d827d0f132f5fc415896efa1591397865c83fd3909af9cd9f19f" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "956333481797dea3be7e388bcc6ecc41a0927c919b37617f00edd4a20ff4dade" . + "956333481797dea3be7e388bcc6ecc41a0927c919b37617f00edd4a20ff4dade" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "64cfeef7a84129f476ff3b0c14fb37b4d3216735b4159ab7b4d18c5f27611ff1" . + "a309c65cd9e9e3324bf229cdffcaf86338a552c392fb8871927e63ae6f3de32a" . + "2a5f5de3fe08662e8cab9f6abb69ad6ccaf42eceef57551d3861ede489c015a3" . + "9189c2a83dcb6353791ef76c04882741a691123b502859731b631c981cd83e6c" . + "9e0cdede2bb5aa7e6b75e01025ad82482fa3e826113d4290a2f90b51caa40853" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "35c3bb9b5333477fd5521487df3f6c465e04bb704ef6c6070efb79fc88950bc1" . + "657c3a15a8e1e4abac8b67b605bc0f8c7f49ed29c524e9ee3348178648946488" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "ac235391bf878ed012c8ed241faf68dc016e0ea83b410351bf9510106ef39a32" . + "35c3bb9b5333477fd5521487df3f6c465e04bb704ef6c6070efb79fc88950bc1" . + "061cebec983050b9a5e8b89f1cb1c1b6cd60c25eaae7f5a4e0826615309093f7" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e4afea71184da650e6bf10abf85579751f45e4fb2027d46bf03f01580a16183f" . + "8d854968aad696991fa62d445e1ec690f4881800e00e6061d626e606830d59c2" . + "43859937a785fabc965276b4fc8c7e715470201cd62c51ff55f7519a54cc6885" . + "ed90717738a5bc3dc17554f5a4b0c72ef102fb3082db53b63f0078ab62221816" . + "9eb0fc6be7abb74e6039491064ac3266689383762a4eaea0e06fcb328cd9cb74" . + "1f47cd734636cb5a967ab0f6421872796465eb42cd8a2caf586f8c3af2047c84" . + "92aa8319d4ade229e8ecdb9ac12c649edcfd4a5aa7b95444210f6522e95b89de" . + "8c0a5e20a362b3b8624509bfd283fef3521205f65a12d29931c1396b4ecce319" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "2d47d7fed692719224fa3481f5783b644240d4aebe072eba5cf5018f2f90a16f" . + "04e2c3077e92fa4fdd5cf4c9174fb491130088248f3ba2a423bdb81049667672" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "6a45d05433a2472462201b4a5c85b5d44817640adcb1eb9a31fc118f55ed396a" . + "c642313ecc58fab504a0a5caa7c96e56ed319037d1ff3e24f33c15dcb9767a1f" . + "2f202d1a93b3a1c21417b7b4e9e6c00fc330985ef14070ad7f5433e1dc4ac5c2" . + "19f5acddfb274fdaa5e2b00364054349b1e0d96a308924f5e53101b7e8c5b78e" . + "036087ea5412358f0d756b20ee303d9e84f96698413e73486a1108d29b4ce37f" . + "1f17b1e56ce9f02f410eae466a7ff58a92b2dbf5f749c47a668071a215b19976" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1fb48b7de5ee07cd80b25b086ad8cca2518e45863933de56b56e604beafb87dd" . + "832546e680c63a0d344f7fd1c84c68d9acbcb095aef3f2d8944b02f493e29c79" . + "77b9c4da073ea5a969ec15addfb7fe131553c5823e44de973cd9da331a0be31d" . + "8a41d49b47937a7786d9ac24cc32bee4b8211457d87d5cebb5a44637e9acdbc3" . + "834da6fae84411afa5316fe281e3803b89919c47e5c3890edf617cceb857c10c" . + "58d5ea4dd0bf5c59d1f9aea15a7a92f58c3d47c246632e3bacb287c3aa3d2928" . + "5cdfb24efd93c22d02773fe4fd4be418cea006eb3009940771cd72c9c39a1287" . + "f8f1f31c7fb840f5ff8c031c585f8e6ded1c499691403b834d1a8e0e46586eff" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "57f3e56270b366d7c062ef45a8e4d93134a6b974db689ceb841c2de39435beaf" . + "d5536ba8d7794a61ff61f9f1bee5c91117df7e48578462f32918a710dd06f3d1" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "95f950cb63580aff1e1d87757ba22491c14322c61c5191a6dc9fd0a2ae0d143d" . + "849f48adceec07956b06bb83c80affe4caaf7f6745b4e5d6f061aa09a2a20343" . + "5edec4f05188e6f28cc682c0da743f787392640555a280d0dd4131b52b608681" . + "a3467c754d364c69d821c19779beffc7009f8828a3e318d259e99c3f2eab2962" . + "80a182587700a211968e7460abb717499ac3558c497e4bcfe00c3c8659cceca3" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c568a29d3638541323e7af1def87ee559b14a9898617095423ab94ed4364f761" . + "c568a29d3638541323e7af1def87ee559b14a9898617095423ab94ed4364f761" . + "195656cf5fc6d8110198485fba1dfe27edf5dab33b4e2b9003811e3755d2e3c9" . + "0edc8cc19747ffbb65a9db08fa6b569b45860d67fc953a12b2be1ab28b186152" . + "ef6eb55ab1939c30b61b35927e1f5cdb75379272a301689afebe4518e993f60c" . + "6c5b74dc32400a3c528127a14ae79ec0e045cf7380b3283ce8c6638e56ed46e1" . + "8d26434cc99ac91ab0520e73f02f4af8f527039e5584914a255ebe925c9e5b6e" . + "87f3c171ae5157406627b7c1f7b977163a1083a68448960defcaad3bd5b8ad67" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "3443043acc73c609ed746bc9c622f1dcb92fb30c0602ad937a8746aa84e50c7f" . + "868bb582dd023d925665e8478a62f90652a5ac0de0607209113b1a3d841fd2ff" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + "f67dc23393b3a1fc24576508734a08a3ce23a022732d53d6c3fb012ec0cfb822" . + "659d9465e02796269cde54ada530d2092ed06c1ce519431df1f0f46d905729a6" . + "0581f11e831a1ecea5b624816ac6336064d0725dff29db88c6b582e9b3f0a1da" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd3e8dbdc608749b62f8b452353b4d34aff9577e9f0b9b403f05abdb51d07076" . + "65027b27a882800187a5aaf8f1f6e9ae1ba2b913aec0113b336097472af11daa" . + "3061206595ed107f28802e9557012c776a6c5b1ff29ec07a824e8fd7d57993e1" . + "5bfc83e613e48a9b202739bb4d28b4d1005aac964b0d218b42b11a9375d539b6" . + "30cd33e607f2e5459096f4ff521a595fb7576339519a00ca41ca92192467c658" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "f598d799527b7cbc9c019c6873f5534dfa0ff7f4a9d424b711cc7b868dbde9dc" . + "428b76724fe0d187f2d66e9ef77c63f590feb3d2a2c2ce0922c04dd6a7d23586" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d11a259dd71b3c91b9e3fe3a35873f8bf72ed9795d2cdac6c2baa750a6f8c500" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "2c9600aa5c868a39461a83fe0a2f4f3aaf5315412e06f458d7bfe9db0ef178df" . + "42d479d30217ca9ec7079339b31e7914d1a6bb761a47e0511992335594cf16e5" . + "890bef6277e989961212b6ae69d76040fd3c5bb314d5dabf56f8ea2356cd8bbb" . + "995208541b6f1675b2e6e876764a2ff8133babe10c7e6b4213aa833c17d00aff" . + "2c9600aa5c868a39461a83fe0a2f4f3aaf5315412e06f458d7bfe9db0ef178df" . + "4c4c2eca8cb60cc6a10493d6e909387d0a77cad35b0679be267ece725c081676" . + "a165430fbf389a662ddd16eb93a754ac131511d856f51baafce2a8da9fb1743e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9ec59c803c958c71de5ca65946c17b5678f5477da1ab31ea19af32b95b274717" . + "bdfc17a8ddff67a7508348c203b8d9738eba91248b651a363725b097c5a3a026" . + "a875f4411f038991ceac5f09c895268d17e61d340fd3f23ddd28d41ed9491219" . + "66f6181badb56b220024f0a2713fbcc4e23ba6217c2962c9125b7715fbbbfaa3" . + "d50938dda023de34cdb95f433beaaa6d2a9608dcc96b6484aad5c7c28a6fc5b3" . + "a7af325692ba4ad1979376a61d2557e8d3e59ba6604513aa5f1f0fce33f90fec" . + "6ff55e5c3efec242dd3acd61e806320ab609526d878cfdc2b783ff2e8d5a47d1" . + "98e4c3b2f45a8d291f2ae7d9507dd0633d3966e7b7b682d93c6f165361cb03da" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "cb2d22582cd1982a46d9acf2b02b1d75efab9dadcf82771f715fe115e72106bd" . + "b1f9392fddf4d43b0453839041a246e9a9fae53bdebe5a180852aa48557c558f" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "6376352367366b5a48a81ad39e47b9f174ee76b606ecd470ec0106ea53a94a7b" . + "693f96cc3b80e6cfe626381d6131227e70c37118044ad41d4b614978a6afc34c" . + "e03fcdbd1bb0d88259693d516389bb24a16d104f654f7cbea22ba997d3d9def8" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + "1d58d5bddf32fab0035cf7d9cf32809a956983c493097a023e35711dd972cf2c" . + "ee0d7da254fcf51d8b9e7324f4e132e1b9b58f5a93acee76dc6813c25a9eb79f" . + "b1b19ba5fc34d06c453ee206ce844d3aac92f9131792dd14c4dd1ba0095c34c2" . + "10a53c5c8e6b1702cc0db87f882a6e22bcb4b6349322315d8f7e76f74b299ad2" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3a513ea046f82ebd7b81caf883ab538a4506d4c671919e346800e97304668ebf" . + "0fdcbe50e259fc9a6aa9f9cf190c5654a3d92d3a072ae94e27e693afca4876f7" . + "b7c0dfda890ed1d2a8c5a78191e945b3086675938369458836e4e68362eb6ec8" . + "22b1f6f3d35121490d4860ec6ee2cd91881b0f15e3de6461ffb103d3af969b63" . + "759eee244579843e9b909b5378e86b4d591fbfae34f2ea074b33e39e4d2fc583" . + "5abcf9cb62c816cd7d00240a07502301459211235ce575daa735ff331a7e88e3" . + "6eef6e69922569a0597db5c84338bdb9051955a5c0888584f1dd3e0cf5c387cd" . + "25211c74124ee06b745e614c1831f377a566b0b7649686095b8c5d7f5e5360ec" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "6ef7ad344709a90d58214562deaed252754fa4a012af8c42a217ae3626390256" . + "1c5a09e8145293405635d42565468be5c9574608f003469c2dcba6e3d05422a3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "515d963ce1a310935f498e5ab52f5afb6d8275902ca7d594f0297891d8e6783b" . + "43ffc6f2f3f78399ad306a728c63dde747ed1ced6d8c3d0c9bc3f878a8252ef6" . + "3061206595ed107f28802e9557012c776a6c5b1ff29ec07a824e8fd7d57993e1" . + "4aa9538cbdac1e73b3204b55267f844e61b10712888162c43ab2e51c8ed38648" . + . + "050e9dbf31b19806417f5cd3cebfdd6bdb89ccc26d23e085bf379d721e9a9b5d" . + "b01b6d1c057b423e20e7da780899068dbfbbe38ceee847d845e208d971f26dfd" . + "38aced240343f4d84d19f02f694938384f4d3ced8569ae726cea1424bee976d5" . + "d918e21e6845359780b08a47926dff2cd90a8b0622178681b9886e1f6d4c342b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7bff17e7d3a33dd063218e11b7ae43d717a1572b97d86e5aa032f0cbec8f9f75" . + "7bff17e7d3a33dd063218e11b7ae43d717a1572b97d86e5aa032f0cbec8f9f75" . + "baa85c87f746b25cdd35cdc4d36ed561b371264010d2ff7cda818db6a2198ad4" . + "dc2ae0be8835cd368e76851aa83969fd4ee623c8c0e53ebc6a79678613562307" . + "0c1e723dcedae72c4768d07e7a1eaacef7a8af77096e151f0824f648557802c4" . + "922f74eafc8062cbbde3a7fd98a7c393b37655d00c55236fb86f21aa4c1d8473" . + "b3e23ad41c3c073a86ce076a4b0d9122e89097b4d4f53c360d0af1f887aa9d18" . + "5c0bf0696be0f8a5c9f911bc5927c76e543eb26fb30393e52bff5c115c768f16" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "d8371ec58bcce6e170f6d97b60df9a0eaefd4c4f23a4e1043f8e0add58787224" . + "4dc05ae2f4185b267b0acf93e699c37109693e2d575e883dc48875747d23b78a" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "12f14b7b26392a4e9a3266b3075a1da0269f2cabb28638e65493ddc779c1bad5" . + "6d6bcb24dc737c821801c1a2a27fb017de42848f2092c03b3cea9277e5014ffc" . + "d19e0ee6ce9dea5e74104063987632b179b47d1979b34e7aef5824536eb1f294" . + "5b7bec0a7de50082e677c6839b7deaf90bd26eff30a3947bfff1cdd912e9aaa8" . + "bfdf129f795aad4d33edae63cd2466368d5cb2a6df1699dc2f2898514bec707f" . + "cf5c6d71059434f53cb3aa4c2fc5dcacad0fe5dd87c83ed85153c88952f8fcfd" . + "5c536251fe3346f7d39ff153c968f8a2cc57d76a7b59fc1bcd8ef968e028e03f" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "91821a5e4e029cba4337a50a1cba5dc59310d15874cd9bff69c87e85808aba29" . + "a5ea2bb4a366abaa68feaaae3d064a0df29b06a15884bdc3393581ec2dea110e" . + "20660a8e764922c1113dfdf50bb7edc7e5eb39b4e87f56dc44d9c78b3fb82483" . + "cab5fff7746ba7e4ed22568c9c3810ccb19c2e846b7b1ec51508c05273ac0536" . + "02b4edd9a4abf4a92b28f1940ef85d1af2d39db9128df2c188976f7ccf6d0688" . + "449d40f862ea7ddfab29660df83e12ed70bc0eada872bcaa95466ad31af8ec7f" . + "a7c97869d0c8c34a8997eec25adc89d791ede3e9a7ee43fa425210815b739622" . + "87d33a5ae3264b6cbd544f5927b66ef745c9eaf8af7457fb8b0bcffbc1844703" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "05100d9f06065c22ef6c27dd0542143e528eac7dfd9d91405f013a35e951bb9a" . + "82aa4674934b181d957015e94db9a7a889b06f3e532f2e4fe18f801f5764264b" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "bfcf1ef4e988e6ba4dcc75304b56e9171bb16f5fcca31569c916376ebc6738ed" . + "d47239ca380c1b75b5bdc3cf437e5cea1384dd0ea68d97d20407ef1911be8200" . + "7223e171bc393a27019f00209e80c4022528d023e339b337645c8cffe564fcca" . + "5f737d75bd88b8c40b0ce6204dcee752314cb9bad7385d651c40f66f5361c0a4" . + "78d9f6e559a1d17f694e9f404d7931e9fadb78c58b056d16997bec60207c3436" . + "e57236f6782b442b4c3efd2f581a92bdff5b2c5b8991d5fa820847c0e7069f60" . + "13dba608d47d7c3bff8b82631741d1cc0ce7e361ee7ecadaf35754dba87d17ee" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0ea65a2867eb8fa22b5e638ac6212a038368123b37ea01d0db53f9e56439c42f" . + "f87a34e98460b0ff01b90522d9585f48a4e478fcb356e2b976d45a465edeca99" . + "258c967f52bf894aedd8e28e0ce9ba3cc3cf5eb89a9119d5192eb218c10e8c36" . + "c6406927fe916f339fc84770894f4486e2f8b1ec2d867cdf0c92c86d455223eb" . + "18e8170d5014e6f9720a516e170aca443a7eb20f85383d200b55f896a2e47ba8" . + "718b253107bb3d1b830b6ab7f5834d60a2cb4edf895990881495acb9ed16ceeb" . + "94529a017f53a1a025afb0d2fc9bff5d3af067ead46a813f4b0505a33f73c919" . + "40a840f3694c89cf96d75099a48902b7560c1afbe238f5813a7ada6f280751d8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "f6328db27fd3707cfc27e914dcd33f4d5786dbd20e75ada556f8451de455978b" . + "fd314fc7e9b5d6013fafb9fc7e9d4d254027ca5889dcb2ff00df9d0d3b889e03" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "66c2d82b61c7bb5b01fe11c137460d487d37f334fdf1e8a4dd33d0b57b77cbf7" . + "8a153bcf4c8b31597a0062ae0271bf417ab4b237f9af89f941d4235a4242bf44" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "80fb005aae3a9c0e9a39d6d2aee9b7be155a8fd6e0ee206f4b833bc01da5899e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a14d2be86310df7f35a469de236af8ab370e08bd04b40e274441606816762112" . + "a14d2be86310df7f35a469de236af8ab370e08bd04b40e274441606816762112" . + "4cf6b5480f3a772a9d68682d10a367f1d5aa797ecbf0d3cc1df210585c1907c8" . + "cf80ee4b9bce3864b54af533536d6fb17673017b22bed05aef964d54aee36854" . + "1ebb5ae03479d9733e026f42209ce7c68eb4d5bd85fb83d7aa93f39147566390" . + . + "289ebff16d6cb69af6265838632240bb3d66912491040a85ab1d3d3e3e56269f" . + "6f1b1f27ab05fb0a9876e42f7d3e76aaf82fcf2148dbf22139833d041722f1ac" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "1d6c36bd21c34c9e22c018d723b71c27ef352c44ac3e8908de03349b66ebdf3b" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f54a39dcd6f4f5990e2789e184a37154cc199d881c60c96ee6634befc49a8869" . + "f54a39dcd6f4f5990e2789e184a37154cc199d881c60c96ee6634befc49a8869" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + "e0f5c0066da24b5e0a04db4a13deeefa331b9ff85019eae815fbf707a29fa9ee" . + "06cd91192e351332fd436cf9174884c15bbbfa5612a179bd912c6d5d40f35a2a" . + . + "95ba24c1e0bb545255a6d8010ae34536d03063b5600c1b2b0ca5194e5e032f22" . + "587a9b49ec5664791e2dd10865654d1f7bab7b167ea057693088fcb0d242cafb" . + "0b431da068680bd412fd8eecee7067d10ef529def76937acaa3216f947cbb227" . + "51ab61ea69ae598238bff6a26d853b846036b9cd1f284b9faf39f2e970b92785" . + "e18c50c8631a6b5e2ff035f61f33210e9a2f83ddc8900f2e114bf6e000824c46" . + "84e29a14123aa1fc5ec44cb32e2358d31e89e025ae47dfe821e338cfa1ac5797" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "56c208d3f68e5cac2e84def40cde7acb2d021da29a6f0c0b11457b27301db8ec" . + "5e1f3e96eafe21b59e0f83979810e81c41ad3b399cca8fdfaa2ad79160dd5e9e" . + "4e2075c2232704f7c866e4c05a3e0caa9304bab4b39bae371f197e01a90e78b7" . + "bd07f06410cfc67aba2c0dba30ad6e023cd406ba02d74ce92c1c713132133d14" . + "72fe88126d2a147b3cfb4f9d0a8ed9c3b8c82758f071a2e73bfc51f191b1bdef" . + "39dc3bb74aea0b37ab091ceca778e4c89fb85a0aea819336c80148c5f68ca8b1" . + "8471b90554b2ba4335583c209dfc266976bf265411e179c608234f08a3937b24" . + "56ce49e4ae3fe37640f5323a611f7e2e175c1b7817b14b8eda0c1dac2833a64f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "cfd7c575f7043e4087499c9a1a0c1168ff85969c3c5291fc89f24b010b097b39" . + "5fb24e096bbb2021f9bcd975c6112bad8fdabd307ce87afb021d90465c310325" . + "7607ca48c4fbe487b302d10b263fa3ae392cd65ef866343ffba1b749a3d3629b" . + "d0df33858aee3157ed0521b5bd0c6d3a46e2ea3195e8a06f5ad4b07c7704aa41" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "91a56efa92359a183ccc110f478ca92f5f27a42a2451e0086d920ee1c6f95ee8" . + "e01b6ea84f66cc4b7a299df20c170dd45a143361d4c03b8983b2f51bd56d9117" . + "4d71a227a27bbee34c174fb418356edb690b58f2a5f1a801379a258701cfc4fa" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "31763cff70c576d3a51c83f3a991e4e290dfe08aafee52d545c8062024f6a5aa" . + "08eeb2e899c8fdcacf6423dbbd5bcd2710bcd8c53843a70f36e434b2c12dee73" . + "6b2118ba2a5ce720c94448d788c3ffde6f3b52f52f4e7cd47aef8740a0a55c4a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2343a030d8b0e23666e7cc9a61068974101744b5c9257ab50f7c2105ebe4d57a" . + "2343a030d8b0e23666e7cc9a61068974101744b5c9257ab50f7c2105ebe4d57a" . + "fb1870184a75234be64103f20230702b34050413a0a3d44408966ddb31ad9e98" . + "2dd4501f65db214c3c92894e28cb12de9e216655a3827a1799ae80e7d626e092" . + "bb81db904a8c050eb524d5a6afe39d44c820aceb850d00f4a8b10cb1da407028" . + "459852642bf762101b47dc041d6309eaf34c7735f5d8b2304bb93eff51ed6aa6" . + "25547d4dd91319c13b2771bdb811b5dcd9813165df3e84102358b3cfc974fe93" . + "c74303f27116dc0c42c372364e5799c6f9fc9de65bfe941907b53a174358d684" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "b0ba8998c6fbafef1cb7db30f4a787b5753d8afdd21e1e879fed223ab2dbc561" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "6af1161c120bb83964c13dcd3b3a0f577aa860094c170aea5b99f4811c04c702" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "ecc1b9fc45182814194ac7af4de73d63a1d8a73fe058b8ea2f7e7e5d2f59c06b" . + "1e85de555e2c5fa7007d0ac8ab957aeadd661ca08702a73bfa1d2ca9b2f1ab8d" . + "ac41f1d6870896e39c4c9c2580defc92c8a259ba598fe077a1e0971924cc5df3" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "aaeef613a21909091f5c0ad5988d3f006c7ad835ed0d9f438a8fd1667da63731" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4a25e1e6450335471176e1008625793636df051401626e7bd7d358f99f3edd6e" . + "1bf8353bd06cae5a51577d6ad33000e75b95b2eb37d02b0458cc893dcdb07a28" . + "aa17a237a8f5171a78569d8deb130258cf74a778b128e279aebf14c319da2f84" . + "fdb95a9d5a6da10b80f346836e7c132a0f01549ab4f982147a34cb7590657b0e" . + "01aaf4732d6b82ad926fbe3c1b96862d69eaf0729e2c7606be5f708dbfba991c" . + . + "8ad4b42f4f306e8e099ea62011e3079d2b0da69504111a27f873e671a0504364" . + "d3284e24bef8ddac6f54dbea5ca19d462266c552e16c00994cbefa085d669222" . + "403f2100b5bdcc375d641e10c6375babcff4a6df6d556f6558a1dc3bad5f5973" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + . + "8c64d775a32d3f6ac8ac0078fa5a9f232f9eaa4bdd95c5dfb6da4e7d90ec3d59" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6cd2c15fe55a52b6ba15c7f97cc011e428dec678e8296a727db0b680daf34d19" . + "4a376dc7aca56139306382a8a1753d4e34af970f790da83b8833c2b77962115a" . + "fd4cc8799e987c7de57c2d885586631a8b3eee50aca1f57f4dbdcad7adf1cd34" . + "219240f0d03d75e7b101658652763a785c0211eda6f79762f411d0159b4cb2ce" . + "35e68976b029f4fc740b97dcb2204c48ea83f7665e97c6782cbc905d0348307b" . + "5eebf71dcacae81c70318f6224fa28ad4398b9a801af17a67a44583d2f90f91c" . + "2c4b0ebde33f6c906855efd62e803c3caf58429faf1853e104f56918e8dc79ba" . + "7ef8bc9d4a76897ca8f525ff006180132e963198a6dd86cf6aeb83d31b29ad4c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a6e230ab6fc30ec8bcdd0769c21b8b0811867d95876198dc49911fa01021bfb9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "3f7dd8328e370ed0915f76a4ee72f3209d0a5ef809451c51e6ec33f7884d33a2" . + "9185d7a57055a69fc90fbff86c0c937ac27dc4d821ada0f3423b17d5be8f90f5" . + "881043800dede38e3b0a881de317a86909f2e74f1264597477d7488740e0261c" . + "361c9ef96f95a473d5bcc00d0bfbd4ddcfa11f8dda4f5183d0137433a2da83b1" . + "739e1ace66805e10898dfa6535409b1189c759a0338fee8c7fbaa66db2b155b1" . + "eed352c3d1c94a01823506af6863497bc2cc76000d4c5958bff8f73c3ac33eb7" . + "f1c0d739ee4b35e46789cb5f280b3d2b43abc56f867a61c828628b4fda47e7b2" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "72c3330a3dd6382af08f0170f4bc7fb5ce96c9bdb83d263723b75fba021216b8" . + "72c3330a3dd6382af08f0170f4bc7fb5ce96c9bdb83d263723b75fba021216b8" . + "7344f26bbfe64996b78476191e6a3bbd5ceeda5c4dc8f7092d84edc6b052ecf7" . + "4eaefe3b7858e1278c172f48a2b90bba1dc82020dce74172c77f1d7c64a06d71" . + "cfb7affe4c793cd48322c262f4d6c702ad64a310b09dfbd5a50ad5c1ed23e102" . + "24cbe8562e7d316586731a0bb6883bc6a37bdf3025e701ccd18704abd57ad948" . + "0560d97feb3c51d67cf0dd3fdb566d4210abd97d1bb4019a8bc78865723d7ee6" . + "51dc87e95adcf20a395ae89816e613aacda6a2be2cb67bf27a4ec4f4a90efeab" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "67bf0a4e11fd87af1c7e545c69bec79aa45953b1b9f24a1ab9642c58c38c7596" . + "81dfd5c8dc88dcaa3060c018e787a56cdf773b9932d3bf9d1a496c3f8fcbe380" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "28a1a9511ffd71219672688ae7cd2850f0ca0e47abd0ceead31c00070d8460a3" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "d53eaf4ce0a215855f4f4d9e48ff7f3ec376e0af2f82cf5f9db5d812870973d9" . + "b5e887eab8046485bb6ebb726acd6bf5c4058d2edefa453643a0c426649c4c38" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "f3a9c9deb156b209eb7c7e137ee96d75e322cc69090dd2a36e40459235444b1b" . + "325786d1e02543e128759095c9ebb531f990526b01b367a3a4bb14f00d14cd48" . + "f498f9bc8179f37cb6858078602e08ac457ec36e6856445531b158924ad8d59d" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e8171a448c002376e4ad261f34ed1af6124d6ec430e823764fdaa397befe0684" . + "e8171a448c002376e4ad261f34ed1af6124d6ec430e823764fdaa397befe0684" . + "00880386ae7718a31e23e4b7a22672cf1346414416b2819892157d65a75ee3e9" . + "ac1e5f50bda879e164b8f7d11559cff9be4d4007c0c03c9daa8652104520f198" . + "6cf46618745d7de0bfa60eb7ee5a62a75da804f5b8f0ea73b632ae4de4b672e2" . + "2f960005c53462cd27ddc5acde222444079187bc255fac299f9c18b45972485d" . + "075cc53d10aa6318604a81acb066a746c97bfaa9f6adb514578d8e8562657c0f" . + "664e23f733d53ebaf9fe69dedb146fdf1bed71eaa80b9c2445f58169faa55607" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "7b1d4f23046c1ee8e181da53a80eb8890e1403a25b262abbe069fa683583260a" . + "81c1ff72565c7ba955cf8b2ce85fec76c27057dfa4aa67d1462d30a1551510db" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "be27c76ba22591b576908bfadd028ec2a2866e6eaa30e04b3d84827554433c0b" . + "218df5515a9d889d7ffb96ca7b5f832582dd750630e84cca5537c946d7013d92" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "a33b42a342b6a43d32d59c90da0a49cdc68a27ede6f5d473572357bfccd602fe" . + "3d289a33c5793bcc342472c8b77f0e99e4622d396f8da9a99a645244f3832ed7" . + "1a8d65ef688cda533fff0ba8a3b09907b468c2a603703e8b416e30522efdbb1e" . + "4362f7842bbf8c1eaa50ccded0df1202ca39e2f254121ea95f6b8e5551829895" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "01fc74616a9e7fb30e80932053647d4acd41174d154e3bb9692e74e494ccaf54" . + "01fc74616a9e7fb30e80932053647d4acd41174d154e3bb9692e74e494ccaf54" . + "1c0467817d839239286a9500898e62c6700e2c424d3b936210f3c08b941e3864" . + "9640bc8009531a8164dcde168af43b397ac35bf53a3b166e7e75331e2a00d773" . + "f95c276294ff4101f37fbbbc152021132b3bb2f1f62f6493d13a0bda3fac6503" . + . + "b438dda51e8fbe080605290e62094614c68b9e84b2a0a9fe0b90b695eaddb3cd" . + "de6fe8a6ad1b31e433f0f7033c8c7176ffe379f791784cc5680afc3bc275e541" . + "33a606a6de394124e24fd1df21b58c90ca84921295edd24895c8520e37537741" . + "b953c7ba4621566d05e7559aea5b01e37bf4fba7051c04f4ed9c99fea832f831" . + "fa3da9368d586669152c25af33f4bb3897f807dacf470a8c18c4b0d4daa35d48" . + "6e357ee1802e83182fe6764fa76ef6b6a0d3c7acaf19138625cd51904a7a76c8" . + "01d31839d34a22ea04cc49e6a0a16d4e1dd990ec68e76abad19cd812e63070f4" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "88b1d7ec6fa048b78c428cf1f96a68dbb9dd791f9f1dec601ccb21a66432a02d" . + "c9c726090ad08a8f4be3ef0746362285d12341351ed9793e885f28a3a45d188a" . + "da5f2e18239ddb2cf90915a84088091932041dbfbb593467d8cae85fbe0ce655" . + "8e0a13c79dd5c2733de6afb492ff99e2b5134aa61c40c31de4933816ba4bcd16" . + "c70273db8ae778e8b75d523ece3e244b2c232d7bddcfd82dded6356f9ccd43fd" . + "130a02df166c26ed1bd7e2ed307ff7d398c087127a883b9bf0d8c8ad153788be" . + "53cca3e095e16242ea939dccff32ee2dbf9f3c60bbacb663390ffcb793c493cd" . + "870ac5212e9067442c1a7a273e5e22ed7ff17dcba3f8ee5a07ee9fc8cbafb36a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "8f0d9537f73e8d7dcf7ca4776c8b179f8596cddf78a9b1fde53821a73e57a725" . + "fcc13b3887ae3a37d9545edfe748c36df8f1ea2011ef8b235f85fd7021ef9ec0" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "b70b3435d59d7f721152e80d89ddaf0c26d120565461018481aec0f3fce1d833" . + "97b0bcaf209118e98fa498add554fcb29390d3f821f3d1ec9264beed09a3b6b8" . + "c6824509e14c1cd5f42e0c3c3211e424961509b1d239aa71980755ea6bd48143" . + "510de2643ed4c29dffa850e8da158a9f347e4a9dbf0d1c7127796a82b510edd5" . + "c45ab4f9b5b1797a4fd4a74b720aff73a96c259aeb4a66a77394849f2b15564a" . + "36fe9343c7237952f75c8360d817683593a2b247648c8e6f37c9c2651b7c07c5" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4f1a8b0f5e59b95bc8b8391e652e2a687f02db298cec3fa015c7e8cf4a4ea6cc" . + "9520dae0dc9e9ec6deadecbe251cbbf5c8ff88ee53f4f4c2e678e0b000b16476" . + "bb10ac23deedee64d71db2eb12c9d0abec7008392ad35ffff806ab948fffcdc2" . + "3512b8c3ba7ae51d5401c85913a0ee16baa745f8502f7fa72d599a2409afd7c8" . + "e13670cd56b133ff8846d4bb06c1b27ba2848acbd7aaefda1f40c9bbedf61d22" . + "40e03f9d3b2095587d1543de272383808549d002f702198b930e4ef332d638cf" . + "1930c7ddd9cc6959bb594bf834e6a87c127135cb078bce02f70746f79fc2d3a3" . + "0227b7c969e84d1a116ec79592dd3ea4e47acc2ac043c81288ba929e5175b1a2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "118792913fffc45a6a4ef1175abb260631338f4d303e579d2c5f4e40243a1640" . + "217b53d849f6164a8a6145d615377dbf32d4a3b10ad0a6c79b52df0de13c7621" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "2f09a16713a02f1dd35988711088827dffbe11fb9493e2041b5eb74d4215aeec" . + "f206f4ff45911130b59e670a8f74cc0c75eaa7833de6669ef04ea8264c82d070" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + "30f95b068683552aa6f81cf9f7b4bcd6dbbb9d4d5af982421db5e775b1f27455" . + "21ef321adb3953bf318404a6ece99c23a7ab23a5b88d0169e0cbe9f51a3690cb" . + "81cedde620b645470163a85f6fcdac4979742f43b4846b69b6e3ab46d5970854" . + "79071115d5984bfa0ed72c32a7ddad2d45a7b883eb7ea4c9c65443dc9a61c922" . + "79071115d5984bfa0ed72c32a7ddad2d45a7b883eb7ea4c9c65443dc9a61c922" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "67645cfb1644408ce97ee639fe3d064c6c8af69a335876d3e7e50e452c8eb012" . + "30071f8ee7a38c55512878c502b2a0cf5abe0ebf9cf7bcf53e28af22278998cd" . + "28662a47cad1fccc86bddfcc92128112084738e91b82d0a276ab0c9a8cdb530c" . + "d798e7e015a86f202abe2bc44c9aa8ac3aa0305d1959eab79058e7451bbcb4d6" . + "f6a05df414e8fc1d1fd0eab66856710f151ad19c99d65af4928ff4e00b50dca2" . + "65e79971bbd4ab0a913e8d02e329fe2fd196d51248539a1a89428adcad6402ff" . + "831790cc83e548b7c010f9db98f9934a38e1911dcb3010cb20a40948bfbc669d" . + "e929b19c3e4bac169851f3ca37abbd4b26a01d43d672a3ec9bbb16e56f289da5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "58557c4b8bb7f8200495adfe2ded85ac9e062f5a12efe2b7886105686f2793a7" . + "5e3b76c568fa29d6f97aee5d1126ef7cb7581fe6441d4797448cc2a9fdd6a77a" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "4c3fdbc846bac8119d32adff96173742608db36e05fbb376d11a80b954b1d3b0" . + "2a9c4d258afcd59594c74dd24c62414d758099e87cb7ae046fda4653d54ca022" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "3c2c3138ebe4ed7f02a347d8fcc8afcbc14720ca45925b49fcff6616b5f84b83" . + "f948bb2d7ba2e9cf100e21b50185717d71b631f3bd9613d374bae954392eea67" . + "66f40f94e0d32bb583473cc47529b29fcba6a9b69383df0780fa5da69913bf72" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "04ac8b06927a0c9881cdac8f0feea0fc94b0644b55b065471d53446609fbb1ef" . + "c7a89938e4fe109793e5d537963e4dad6d1db5a559962ca8640b1d8c83f2700c" . + "d0d5c414acec77c52edc55fd62f0d5413e664d39513b774e54cc1c610b6a6d22" . + "0fbd390a40330c37088a85d658a29e00be0543fa8f705532e0bac72b1f9f28e1" . + "b36fb69b0d023884bc9cb39a8b2ba9a54a0477e1217c7d09d0f80dc11e5f50ed" . + "848eebea5815bff108607f506ac1a9c1b4a3af4e572cdfde345a7c2d614a62bb" . + "d9d1ac065f769fb9a2c1c2752e570b8e547321a1b72566ecce0932c6f02383de" . + "17ef617ebff815e994a3fa63baf61a52592e2898a3826d8eb20cd388e0bf3d86" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "37fb403797835d5d956886b9b7bf40ba2e90bb34ffd07a5b19d7588552e22ebf" . + "d334cb0fa79d3d24196bcdc384c2a1b6358e1eaa516f7a75b15247abff6cb9ac" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "e59eac856f14f3fbb7a1ad13748904c7eeaff090dd01a874881565a22416b2eb" . + "a6cbd61f4bf39776d1b2656cfed9363393e8a6180c8e2d8c39c9ab58e55d3e2d" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + "6607d2affc34101bf25fdde70860d7f1e9dd5f7bc4f3ffd6b50d3734dbb87507" . + "3373f3921692baeacd3b9fd71974797c6f95e37d0ad4f378518bf07954903306" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "69e9083892c5e4a215305d0fac73c4f19a29ae2bc38527e3cf33057366e9650a" . + "69e9083892c5e4a215305d0fac73c4f19a29ae2bc38527e3cf33057366e9650a" . + "0273cb401b03db8a5d0fd55e51ecbc862a374163ceceba93c624a9e222bb903e" . + "14be3991c7e464c001acb58edb307980e695f1efd6675ab0ee072cab4df4970d" . + "610f0012483d865141c44597bf858f2da0415819fd13d248238beb43b57a0c2c" . + . + "19b25827e4e84cfe562021fffbfb141e5b703a5a9e9aafba393bc5427885e26a" . + "acc95185972870f16b03a4c7da18360d58f8245d963456f7402378b91ad60a2e" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "65f515cc210ddded79bbf98630848382b7c6503d82bdf280bdf75991c6af497e" . + "4e303b19c834c4259707967c43e8cd83b3807f9e5380a5cb524678d828cf2d78" . + "ada9a487b01e2df231dbc0477d640e8ead95399ec82aada781fc3c1288ce86de" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c05e6519fc913a98db9230d2632226b61ac8f5cf6e635506d72d2d5aa6423c7a" . + "ed30e7d815dcdfd8a5552aa9fc4680e2c6dde722ebf04c565392174a31a1156c" . + "47a9b8b16df6573b9edfd8d0a9fc1d464f3f41f2a1169683e983ad20fa88cf04" . + "7de549aecaf73e9691950eb9b886b4a42e931731ef06d614cad0a584b357e430" . + "bec5f78bc57b5d496890cc0cedea96c98c72002729e8bdae1b0f1ed96ed1df30" . + "b653cfff6eb5f71c4e1e23083c74051fd78d7d08a2aa55cb115f0a6749002764" . + "03b1e12b50c38ccce258e9ddb97624426dc947917ea3db84a8b5919ad85112dd" . + "c8eef1dd64fa9da5040eac5fdd7d4b8ca743cbdba11bfafead500e8b35cd9f19" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "14d1056b08b413088c461dd40879e540757e2e5272a2347de443f387d43692a2" . + "14cc6c00b6ce7a4873d00b65cc5f111ad9a157c8f8db160724beee9c1bdfdd69" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "1ce730056601cdeb7f8dd5978248518d49467757017e678f55b2ec763e756f1b" . + "948f6cfdaa865fb36dcc0ec1a515aa1a8b0e82bc41dab2d1e51bd6bda2a8038f" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "e15adfd24ba5aaa1ded8f3d006de6094fd23e6f0364918a97c2fdb4d80ead691" . + "ca71d3dd281bc532294637a4ef084189ef96fd49aeb3a514ac259a0a3d077efc" . + "e802a26c576149e2cf97a877c7a696381071385998e64603a43bd6535265e742" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ac0395f0ed64059c50633fbf5cdc2d18da1e3b3c249fcf40e20837d5d91e89ed" . + "b5a7128dc803c7678fe18f4094a7f8694f078e7966633f10e565b185a0d9e003" . + "ddb858f15fa4c25be6c56fba18aeb7f0c3db7fd048eebc60949127d6a0fb1a51" . + "ee55a748a57a3a2643969c0ccb0b13e865ee3d3ce9532c02537218da6014efe5" . + "1aee809917bd9a3878f884109b79bcbf6de0e3929a8e9e801070912ffae5fd11" . + "2f9a359439d326beb9dece7e75c41c62bc86d5a4bf0f11838a8f7950d565f5f7" . + "5df983452fd9be3f66b8f9f69b4f0af496756676832c3029caaedbfa0cc40fcf" . + "0417a85f877ef71b2846257e3f6ba0055b41a949926f0a6eb82377b8a1bfc792" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "9895602219748947777666742f04cf874eaf312edc8b64f6c8ea7b86294e398e" . + "f320c18a4f0c0c19c3cad97ad52ae75fcc7cf3adcc96a46b5cfb848ef2a43727" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "af5945b66dd5412fe2a5c7f0f8df6186e905b2e4999906ee4d2769128e85ea4f" . + "cbd1e77592da12f2149dd424ff54a0f3a362904bc05a7cbb0be3c68ed4242332" . + "28f0712e0467e7de5435c0cd3a479655bd07319fb9e997ad45b00cacbd1fcc40" . + "50cdaf0a0edeb1e0bb089fdf151c7e70085aaf18dc1c29de4096b19c56c300c5" . + "fad74dd8b88fd5d4a05784d4774d1a79ff3b8b8ad5509ca077e842d176a79365" . + "b84a2763cb4fcfc0c4fd2f591bd78d3987a3f43410d0d58183ba452f9231e49b" . + "ce942f8b97d64919cf3cf0377db44386ecf6ef7d840498d215a1d3da0ecdf997" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c337feb5cbce426ae1ee5f3862a62cad0ec3b6ca5f4c534cd9d75ba185c28203" . + "ea6e4e43c7b0aa60198ee8b832cc6809f8c35e6f6292697985a11fe519c57265" . + "b7c5d54c10ae496a85ccf212dc1706a55dfcc7ad01c5358ba28fb2357cb99ad9" . + "521ff313d87c678469793989a0cdd9ef6ea2769168b2fc619c4a2384e8aa869c" . + "506d7a3072b0d451083fbf4056f9881c56611365ae87136bb0cf6652a301f36f" . + "2a386009bc9cd972d41969e41c37b93623c8f90ca6b65b02180f09d9d427f2ec" . + "651e7d7f42b5a024b3e12c4e8f69cedaa03295cbb1c8f97cbdc8f64ef794bef8" . + "a9f66d08ac783ebc5752f3cc72fb39a80144a20d9e5b21bd3b036c29d2690e69" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c032d909721116fdf1b4e288a665bc2a48892c30db3c400d5f8d2c8bc94029cd" . + "75e8af2c66e80d6ba4a637f0de8abc478c3371377684b0aab99d662dbd09a5c5" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "90ae86d80738fbf32124f037f1296a23f52a14e567b762fae2c741a9a945e069" . + "98661ad6c0956f7705291ae26df390cc2f4d3a2162bdd68acf7e21ab9f527e82" . + "c21bf0e0ce8d945dcd785424ad87b322d9b9aef8c0181bc95983b008efe27766" . + "59b172f7ef3312bbc17c89a19107bd69a7df3df162a605e0d4fdadd99b2cd8b6" . + "730e1c2c9ae5134cdccf1d28e4d2771b99f8f70d1449783ee7d506dc10c7cb8e" . + "054e94e4689a9a2684c290233e314e21d7ba67bf4c601c128d9626a3bb557913" . + "b754fa140a453993a6f2fee03d6e42dce08546396aac2650c36f6831d3c61918" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee1c0abc535027cf815b5b5fd876f42d78f43aee99259f7b989c6f1fb1407186" . + "ee1c0abc535027cf815b5b5fd876f42d78f43aee99259f7b989c6f1fb1407186" . + "1196d780355c7f9a05c251e0d9149c4d572862c46a7a7ffadeb13d18e70c1d32" . + "ca76db044111bb54870da39e82db52f6fe177bed357008b772aacef8f9d91a8b" . + "3f8128b594d67c68937727f23e6798b011781419c53d2865288b079f4296056f" . + "217b53d849f6164a8a6145d615377dbf32d4a3b10ad0a6c79b52df0de13c7621" . + "9f05721757711d104daafc70aa707a96547380f3b28ea122c4c20b29109a5412" . + "28e0a2792d99f698913bd4b5cbd2cd5d9288982759fa37c5a98e29ffddd6b16e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "18d6c634dbb8fd80a71e1d621c03dac47db6c1cc79d1ef0997db366151b8b8a7" . + "4babc552d25c600363b7b6205c04bb6118a4771d617235d717e6bf61f17fb9ca" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c4678204dabe8584d81c0f15334f6a7edb4f4fab84b1697e8116030cf634fdb0" . + "671106af6f567013dc8286784e0ccb80d3224cc9254090ed1c2ce768427c46d0" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "0d54bc3818d44994b97d7fc8040d3036f48ff6b036712dd200afd4d474a2cea4" . + . + "30ce1d5a6c33d4ecbf4ac7ce87f505b9a88f054533be77e53991127f680b773e" . + "c3afa16890c4a6a3291a6cd066089e0f292137281cf66caa339f2237c8096f41" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f16f7550b820cd82646194a23c3ae14ed0ad9a6a849ef473038a7519f52018f1" . + "9daf94cdb2558b60da692dc1a8a914d13ebb94400c2fc902a3dee36e09b45622" . + "948a020ebae922cb61e65c157bf9b0a35b3c206858da653913970190f8f12edc" . + "1f8d017487b665c1694d79689431231b9eb7de371fec68790ad8b2c72f7ed3bc" . + "49a4c09ce3b208424fdd9f4733f869df42d28e356d92e5fc5a0beaeb19491e61" . + "147f5c68fffaed44ab3191269b496c281a4ffe599b70cd8b794cd002fae497e2" . + "fecdd3c5ad934be4377651266953b44775c5121b9e79cd2b7779a90749976152" . + "4dd348d9793702a80b60afddbca899a658aab9f41b95f8a88213219c7ae11243" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "923f549e3fe56c21e765fad13da8d4f18a843d504856ad0980b266cbd717b797" . + "d5de33b9709e48bd4a47eac699bb844a3c758c158ab6e3c03d703f676e93b455" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "def472bd567b7f64f3a54f997676a80c12d11566c2ce0dcede95acae64c6f090" . + "065a8e2d72c5efe0b78c70d61bb3b31e71018bf0a4b342b1b445ab448763356f" . + "e8c4f586ac28e93f3b4f7edcd2c98b41859bad919bc6ab1be36b0a439d00703f" . + "32a8b94c3334801141e96149aabe9345c035b285da8852822e227bc083813493" . + "9b4378b62fdf2f3594737c72b600f10edd4f1826ae1254ab4120c1923e39e62b" . + "43181b3ba3bd5823acdf36ed96948339a6e4d5d967912e9f3444a0009a6a33bd" . + "d4728a4bf28e17156a05243359236bfc916eeb545fbc26581238ac9a05ff0eb5" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9a9720f8024aa5d8e73a0d13b54f92d6b80351e3cebc150278ecdd51b67ec165" . + "224ece7835c9b03c0c140da3858c320afbbe1f3517a5f2123fb21b93551c96fa" . + "9bfeecac058950ee62dc39430eada7a5c10c0390c9adea6e86b5fcd199601e5a" . + "c0f17682bfa793ea643e30e15582d99473badd6b5338ec6193460470341363a8" . + "8f43683d3c666a8273ef633e3bcd30e016f01d0d9ac4f35a9c327cf7e09e0669" . + "b1959b76aa420d91c871e4241e02c7e35687930201039d55fdd08d9e46d4864a" . + "523b053ee54dfaef9b0a3a3959f92e003a653c20134ba0dad09c1975903ecedc" . + "2c735a079aa2311ec9c438d3718d40fb031d85535f845061ede6aac52050f76e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "a271944e368257088fe5fabac860d7e43d7762d145b986b46cd8aa944c116214" . + "e8a2c6d0cd29bc004f2f315be9793dc8e6784673c2da5d6191a41634082073f3" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "da31b7f95a5e67087f2c419564e5e2a3811419acc58389e46a68d8db7038e110" . + "08f547d85ffe30ac3caf9ed073ea7f2d6bbbf69ed781b09d4850ef37326ed729" . + "9d4ee0961be2da7d6b3f7b3040a477d50ac73378711932257d80da2a6b0c98da" . + "6a2fa202cb0675843912cd7a41a8d8451d2cd22c94e2b6c902a580004d70c4c8" . + "59727db61252fd88aa6b35afeb857fb420541a600270065f044c0ded17b272f7" . + "c91331041e0128c91d39e926768f5e2a4aa00319e63e9c603c2f89515f7e8713" . + "0826fb9bd33ce43c400f51cb87c4936764392b50b03fb659f5fb4d8117dc34a5" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5106e51ea6111e8a9ce5c9b91ce56c6df6145e0b7535193c97cfa0af6a9af4bd" . + "5106e51ea6111e8a9ce5c9b91ce56c6df6145e0b7535193c97cfa0af6a9af4bd" . + "51128a38de65c5a3181a2dff4dc8649201767ae1bffac2f1c52b842bebf9ffab" . + "802d219dded923d459f9f128b54da0ab4d379d7c0a9c0c14f8de16e802cf980f" . + "46634ed58ddc9534f1d0e37908e6f96fcc97255a7cdf96140d153a15e1bdbdc8" . + "d19686372f7496ae6fa31640b07419938676814fd0d92e4205c4fafec2b41e8e" . + "b25e70e2ce11cdea25503b4dce87e3835beb196f117f040b599486dc980f41db" . + "b6ee943a9bf229a9a0fd2a1a22e4eb1a782d6e03181bcf335e31cb371e96208d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "4bca05ba1ed1364940704cde659a908fecdd9378ea0337454e536691dc12d627" . + "2cc0036b8c261fc224f1bc9d3016583cbc4d3170fb213fcd72c8699b287f899e" . + "cd99cea8b7d7ccaeb7f60872418fa42972f0459314adebf2645b22a1d306b087" . + "feb405f2e071491302ed6082622d36b65024259b61686f66d27cb0f6d8ebfb30" . + "e9e00a26441b4090070f5303a8e3f50bea1203da105ce7d85f5a5eb912190041" . + "92007d4246fb73153f9af00c272f2aa5841b382745d514836dbdff013d44565f" . + "0826fb9bd33ce43c400f51cb87c4936764392b50b03fb659f5fb4d8117dc34a5" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c610942934e45f207942c47d534990173a7cdeaea173aa2b565da35687751a49" . + "c610942934e45f207942c47d534990173a7cdeaea173aa2b565da35687751a49" . + "62df394a095ba5cfbc0689b1134b11008f96d0f754429724e1c50a3a76b266e9" . + "dc3c44894f41ecd2c7a0d138bc152df3a76418701dc28762a78ed37a626a06cb" . + "b66b9a5820a4c72ebf8ff5c89cfad91468c2b729895d439494c18c4c869647e6" . + "dc73b4bdde5b2df27bf18f68b6752fbaa9fe4988981efe68d24613a0144c78c3" . + "e265ac36ef815689e05916980107dc29cd61fccc3fa34c690898e343dd23759c" . + "e6665c7a74e9d6edca75b6b6c051a968a0538e9f4574ece70a9f57e3eaf76f60" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "408f6040377b24c54e18be9aea75334b8465f89d76115fbc9c4a7daa9cd416d4" . + "ab4657748f2f4b9334f0ec93b6b1c9fa809a5cdc37aaa9c505f1ad53bdb86e6a" . + "051a7a6db85621a1d5011d536595c39b8c9d54ba249b8423fe846020326db11e" . + "caca1c14c72cf039936f51758b0fdd6c03fdc0d3da4ad5827e8efe445272b10e" . + "179147ad9c1b387d2cdff5b3921a559a7f1c75ca20258aa73e9499b2aaf07083" . + "d5cbd8676135663acff5ba24e4708a8645fad913e091aff46ea09edbdc69bc6d" . + "9a638d930e8e64ec91311c812361c4a2a313a44a81bbeace36606af776a2a8da" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee39c8a338f4f0963d4e23ff5996d514b511761a5d56481a16bd117ab7fc58dc" . + "ee39c8a338f4f0963d4e23ff5996d514b511761a5d56481a16bd117ab7fc58dc" . + "84df77b3dbdff684b5488be2aecb6900c81ac3ee2b4065fefce389a47645ea13" . + "5cb194a43c95413f3e7bda08d8b87ff72e5e59f91541f57c289d6bfbbf479fa4" . + "68ae41a8c56610562f0686c939b8bcbda81f15a338845e13425ad16c7f465b8a" . + "6c5b74dc32400a3c528127a14ae79ec0e045cf7380b3283ce8c6638e56ed46e1" . + "031df93a2afc7d6f0a498ebf08cdc22deb3452aa737c1bd48bfc24c1a1a88005" . + "2a80be8a59b0465c939b48807dea6a1cabca184bf2e501293b8f2c3177bf4aa2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "61cf2d8a2a18a6400ec0ebc467d0d783938a6c5711122f98aaba0e46bbdae380" . + "05fa5653de948ce71224e2e9fca9837e12bc2ff8543ac144c44b3ef0c29c3c44" . + "beff4063c0a01abb240de64bc58b7f2af7a3f63c467f4a5d5a866d2511c59b23" . + "4380e54b573c56d5ddc9237cdfcefaaebfd21262e625d6d5762e047d9a7d7a7f" . + "736e170470469eb98f69983f0022a7f5f5208f9f97e03fbd89b600a783030f51" . + "89b02d5a1b7347020a91fac088abba1fc237c6ca7280159f72f551ca2db8d380" . + "93dda85a343159be34736fdb83e7c97ee95187a87015fc557ed9876fdac13f3b" . + "02113f4a5aad3f8869dfb47c582d985ccba2c7b548d8c8e51a12df05a0db6036" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d71282534cc2f28e3a1a4df231b9208838121c94aa09ef4798d24e9fc36b9fe6" . + "3b98dd929421fe2769fa578aef95c832d583370191631fb7d2ce4346a86383e2" . + "d99b1c097281b63bc687678fc0830e32cab32fd131bc88a0e165680097e29376" . + "5456bbf5855f9a2ae0d1cbee2a947f754de55b75af3bd2ff742bcf56cb91f675" . + "3dc727ee21c7c495962608927ce23e173e695b97871663ea11e7df7cc7680e17" . + "9105711b24a297386e71113b857016e8f4ad1ebe8af31bcf6b132f9632b442ca" . + "e875d2ef38a051b90d05cfab6bf511343cdf65bb16ec990ee98ac7dad868d374" . + "503c9ac9492bc35d997fefc7a723988d8a6cf3bcbb2b2128a620d04bc587850d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "b63fcfd4f577306e113647a36d4ae3b42783e8e2cfdbf822a771d4ce1a77451e" . + "b56c063087da94d245a5ccc567e054bbbd428c49b296985978ea8fb8dfdff693" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8d6f359ad552d92b7e7f671e5264b78712a7a380c52f25fd94b0b33b07c61fb0" . + "37c38dbd020e6b70e015e511c27a2c61eb368f01689cd43a22433565918ca539" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + "f640b3a7da52de9f89778eb6162b478b8ead5794b33dc10fbd208b25648c47de" . + "d2b40d23a98f3a7228e19694fcf88573f069f4549d022f33b642c8d0e086293c" . + "c6bc852e0360a492763526fc247d40433ddae4b29b591555c82dc60351293a9c" . + "14840cefb7441cb5f249a1b35a1cf85ddd1c1d95b90b7892ccc0af59090c8c44" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95e8c9ff2dece930acffbe609a37618624c024130239f425ec414fbe37e77d8c" . + "54ff40567fc5217f3b4cf4ab055e00b76c6a27a1462310200fe9f27c39b9e7f2" . + "29de6d3b75eb95842a693e8b7decc817d52e93553fb24dda2273458ff023aa57" . + "e36667223c0234ae0069e1e98d1a04f5c7780e3416f8c82184468c4ec051ccfc" . + "fe0fb61f8d8ecfe8014d483804a589a755619148292e82be59b4dcc724e1a15a" . + "9bef333cea4d92f67cac787850925d7334bbd37adc8a6296c9363182dd60f9b6" . + "98e32aa20a08567a6e5cbf24230b7548975a150c90acac42b1964b9b2c32f861" . + "3dcd95ad1d93bb3d367468edaef9a6ff753e9cefcd6a279cad6b91500182a34c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "f4afd48d4ef7dc85e913e0b52c1e04b2896e54ff653d068c59db53a0ef26cbf3" . + "d5b728b6cf8a5f6e6ca10532c1abc8a0e03be83b637c44ab54473bf4fe48a3cb" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "45bfa4b9b651af2f513a47be25a5c13d7cad8bfb5ea3d8a925c8324fed874628" . + "9289b1f9bf7da99cea76c4050124a4aae36e329c9a779c8f5b61a3650622f409" . + "bcf11acfe54b36dcef20b8e497be7b6a582ad3cefb1f9ed2e54161f6e1264801" . + "6db8b00f3a88f0c1cbe094c569914f5bde07ec1366e68d4f3388cee1055b7f6c" . + "f5790984d4079699f2d7de8e48fd5d62b88d5c5f8e3f09ab8e1cf81ca7b73631" . + "284dc5c24d90bad6e34346b2a7cd8d75bc3f30119ab0c21299c6c3d29c21bedb" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dbc5236a35a5bf4079f984ed982352ddaa384535258a90e384bb4db6e51b4514" . + "dbc5236a35a5bf4079f984ed982352ddaa384535258a90e384bb4db6e51b4514" . + "b83cd10ea04171819fef4bf2b87243e74c0d769e967310f2dab1b6aa88b8a8f5" . + "e30c5a991d22e79ddab6df3b0fb534008c731b40499ac06a0472ca4c52840d8b" . + "ad0faa670f0bd172b63f6216c3acd62d3bc8400758b4f817f9f3586a846dcad4" . + . + "d22fa04a98d6e4bbf86a60adc21b50ed7eb29c01ae5e08408ad70b4c94a9b6a4" . + "07de5859864fe556ec1726c901e2a6f32a0456c5e9128cb5e178e6db1912a0c4" . + "9a8b5fac2c52e43b83390210c1fc4ff65f95314b749d28efb5c4f2be02739fcd" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "c83d9097336551876731e72ba3bf42d6d69e0852e008f70898076dbd460e8361" . + "eba7499a830688f44378be02916dfa2f1e242e69967cacbc208ef574503098f5" . + "d92733cc48ea47164b9c53d864e50c19ffbfb00ea4e69a284b3e7750544a5562" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "02f4894c551c6f5ffed3f4af8dceaad5d30d233d125d8fe4f4e0e36d0aa1357e" . + "02f4894c551c6f5ffed3f4af8dceaad5d30d233d125d8fe4f4e0e36d0aa1357e" . + "bb1e6a7e2aed004a12a264bff6a8bf852a5922136e4b11d90bad4cd7da812ab9" . + "4e52ecb3e5aea8a60837c7480980a67441a050d43598d51c721286ed27407279" . + "3224e2cac6f52835db0dac3598fd3df0f9972e8803da9ecf44e47626d2c44529" . + "b25e70e2ce11cdea25503b4dce87e3835beb196f117f040b599486dc980f41db" . + "b6e9e4760717839a1bce44b12332d7d54a9bb2b680ddca6d634b864302f33185" . + "7a1562d6c7a9e7f4216c04878a078ed46ea1203d293078750b57de63ffd98113" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "f3c7c8f95829514ca00d2e0410deed55f6b203c309c5113c4c473e82dc650e34" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "99818be6d1383d1b8aff8f4fb191a5bae96dcbf4cec155e24ee5ad8ebff2d8fe" . + "53081c12f7a758a061365d272c5dd0c1de82a15a367a769313a2860fb5dba4a2" . + "b298d59647c9a8d8e7df3d76bf4d2c010040de4e6e02d92758f552e5c158a6a3" . + "c766ee2906c4715bf3e3e2f3f789c11c319a93a9d85b0fe0bebae87b51f59bfc" . + "99818be6d1383d1b8aff8f4fb191a5bae96dcbf4cec155e24ee5ad8ebff2d8fe" . + "deb618444d17f489ff0fdef883d51b35a3833ba2fc00aad4161b6caa92555dd9" . + "022b77f62738c7b92f4244c9669e6b917f6fce48da4ca7fa53c1751d499de6cb" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "8c7fcffb0e6fd645085e554e68f21e6021a55e5723bea9f098d8a6badade2410" . + "671f165c81533c4742c74f4158ded79d16f2a881dedf2395a7134a46e0fe11f1" . + "8c0699cd042d1cb487b307b8790847762500e9e3312db51ab960fe5a8f67537d" . + "92448dee9aee5b58a556859ebf35e022959bed325337c33561cc4aa3c1569623" . + "15ef7b07973f8938c18c1786812afb6f936dc01b4554f740960713cc5f253d02" . + "213c4cd7fd0f5bd3eeedff989631b9f275ec79e581dddbee23c69fd6aca6e2b5" . + "0f75ea53ec36f08191c3712b0d6ae0f659fbcb8793fea0d12dbc495d00a0e906" . + "7e30ded62e6715623fbbe7e90f1ad44b36680da6067960492346b9686d10de09" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "097329e82d7fef7eca5cbebe63add482b032492102058801d06283dbe87a5a46" . + "a6c419294d20bc942a992b3460221ad3c149ec40401029a2a8607c13e259e3fa" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "40f718b49bb7ab9a826c331184b94b2298a8aee007b802d37e864c40107d82a2" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "2676b0d5602382f5803c21e5d21b35408e94d67cbbcdc92c46abc6ae9ee4927b" . + "0e4b5d8353a4710b8380e41bc3fe042cd7714dc7ad97a6f70d6ed2ab78e7ec96" . + "351a1c6bf2c233790ec343e63aca9d37d5425abb86d41b7dfe7075ebf5d91652" . + "c21bf0e0ce8d945dcd785424ad87b322d9b9aef8c0181bc95983b008efe27766" . + . + "825a138d7a4be6622f42e078a5156d192e2c521275cbad93a626723c6f4f3df9" . + "59081a86ae44ed984e989ac7b4e586acb5d87e2af6f023d8ac876ead33746b62" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95b49c4547e6bca0342fa73a97dafdc9f410a0020869d9a28aee472d1275873c" . + "53849a29ce293d361114ce8f8e5cab1cf917b85e816e7dd2079986d5d55f73e0" . + "e2c03221a1c0e6f79b1b936244f33468e05fb9a99468d47258b3c34995d71c99" . + "37ca5cd4a4b2a3f1b172757f8b2b484c7ae793dac73ca93bd088d3d26bb57021" . + "2d249b8d63d99595d9550ad4260ea53627391b3adb61ba788f71bff524397a5b" . + "f8a01d79b4270b26cf725daf0888fd5ece58abf64eee9ad6ec7aa2ad5592b5ed" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "ce055b1b0123e9a4dfd94636d20139754ff3ecb55fe44949f9960674e15dd9c2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "367a3e6e083f7168659765f92b36bc03778f3d4a1d4d6198177ab0e3186613fd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "6a3d4a96c717aff7b388bc719637373002b8676fb52112df15bc1a529ca3e77e" . + "212c6c4946bc743a9f44c096f8e97b550e1d437076966974c1a2c238c54c4932" . + "c821dc4f278ff7de133ced545633fd9da4f261fa57268a49b6fe5ac828ecd69b" . + "566d1bd5cfdcd9a4826277abc752c39917e1fc20a1d3ea0b254cec48b99f1f64" . + "a08180dd438ca1a2f0638712113c42c3d6b1af4d15e6d5d5d6a91a8ca8809ea2" . + "5f79ee31d29e45b98cbb517a4d5ed73f58960002841787b5d84757a07a95952b" . + "ae97e11ea80f96919867601b01f2546bcda7a6a080c636eab36b3f9f0c89f404" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "04fa731b2fd2cd75e34cefefaac73f546c9bef7b8604c0fdc21e8ef9a6bff7e7" . + "d4de55112b01afd12a178ef0fe3981f70f914999edcefe8728ae98c18e913879" . + "4fa2a5c96bd07ab5e38ec2673617cee045be19b49c23afe76ed8e300eb1357eb" . + . + "b7df6f7a4cb4707c5399a6893c12686d9a953fd3bc53010f392564b0b742c701" . + "276460682ba9d67633901eb347679ad4da481774b92b3b56fc39b13eaa20fbf5" . + "26e1f24a7fe3459ca09cd6547a0d6dba43a4807482d03b00f92ed16494bee5b1" . + "66f1c9ed6856bc51158da27509ece6bceab2880792e3db6123f864d40ff0caf8" . + . + . + . + "4f7ad65f6e4351cd7efea13df6dd471bbfa1260bd388165e74c531d8b82c3d52" . + "b510a0a1b7f73f410de9ee65f19d5d2c99736eef479ce4b694dc7ed072a94513" . + "039cb24b58664e50358416111cda491bc7c34715d5c98938c4f4137812ba1010" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "04fa731b2fd2cd75e34cefefaac73f546c9bef7b8604c0fdc21e8ef9a6bff7e7" . + "b6e4acce906c8db474640ecece7cc32f52a8ddd19454b8c6f2a2ea920c5149d4" . + "046791cd06818e74f08d93d7396b4be5f5d9c6350d549bd9ace67667ac35a893" . + "5831b793ed1ce56c664df0e76f479df1395b023dcf2c32122de26da5148c6ab9" . + "adcde5cd00a276c5b3da27969ba2010f6d37efeb7c93e82e52a0253954a5f86b" . + "5ed550180204cf32365a771f870e22f169984bc068b894f27a52ffea18b1e768" . + "b8c7651904755a5b6f4b6096fc6bf653e3de0d8c891c5e88fd1f80b933c799aa" . + "6a2d6845052f51f9efe2f29cb62e2bb00ba0453152fb0bf96c75cdcb9df41b73" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "e471e956e7408dce5cf15705778f72b02236d555a4039ae8c4ed2b5aee924132" . + "18bd9925593939920036bcb1267827b51a1a29ad64bae7cc7fa797f3b96b6d9e" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "820ed775022c917cc90e406f73202baee00319f4eb879f132ea5c31d77c3d12e" . + "9b3c3fa73419f276ae0e26404dcac79a4f34cb267323bad3814d4ee7328a1ac7" . + "6926d5c67b71f639b54b490e79efe22e6a6c926bdf21e09e6c0f6d74803bb532" . + "efc794d1ba523b275e3362159dae129cec8a6cd32bd01a4514e27f7f6136ba71" . + "399d392de8127dad5e6b01cfea96c97b171c4fcef5cfb4839f60676f86682a84" . + "9d74076b56753b6cdfd6373d94807d66c2da70d66442ab838a9dc73089c274db" . + "08359b28c0b14d5d09a46bdeb5295cad51128e6e7fba686f8790c63fb136aa5c" . + "9b9c6467cbef28e35893ba0692a6e966f19c2b014c14bbbeea8b34152fff4d10" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a21352115550a8859fd01d94c193eba6933e8626b8463dcde49d554a153486e7" . + "705e04c018d3eda83206ef415557b24e12b577a30838a0c7bf9b79a15b95b523" . + "854aab4a65c2b7987c75f9f5ba6d9786712d8a9e37851ee9617bc0399d04ddf9" . + "50b42767992635ff638dda549c5bacc4c6f224a177c0498c840e5b86698c83ec" . + "e82889753b54884b3c0d593fbdf50275e0b3ccd2fc632a01a999e1c5992d6301" . + "67a9ec4ad964d187f0e976817f4108939cb613e1cfc565739424e527744ece97" . + "80feff8045c2ef72f878243e08ec172a2da3d66e1656ea3e3067b15b40e0d00d" . + "55d4eb5279e30b09e819e759b9fdb561ce306f3778248844d43d3307e1ab69ea" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "3c1ff4f6276c2d75727d54eb722e371b1c92e4d72c53979de9a1298711d80e79" . + "8bf2a0f655377324908471b8f80c7877499ec1be5d7a9decae2b4dfef37ad83a" . + "ddf08399bc178f19002360fc13f35c66457f468b9b9b84e9482ec369bc9b2244" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "8a8f73a2b3a9bece75bf2e92d2e0a08bc7114678e118526740cba8b4158b085c" . + "1f132bb7a159f3a207f51b453947859ff077d0bf20fc07da8aef04e7a205f267" . + "d8f4b0dcf80a481cd502af93001819357f52f23b800c245807bc4866596a0f00" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + "69ca7a57daf6f4fbc16f928c78d6e29fb4661dbce52125e18364789c029f4514" . + "995ce7f43781814a2a74cdf40b3e0d8d3b3fa362114f21ed996d1eb27e1afc4e" . + "17a93fad52cbf85c469fb70dac071a7bc62d873309b97bf3f24b3fdfe7e891ca" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1ee116a5168c09735c86c235e0ca6ef6e9d72a4538110ddb0f76e36d0baf8cb0" . + "1ee116a5168c09735c86c235e0ca6ef6e9d72a4538110ddb0f76e36d0baf8cb0" . + "a53d6bec93184c69261e2363c64e37f18a3f111e2bc73d081694854769615a77" . + "8b44e78e35b6822c631c297240a51076af12106952edd9d758ed28346294a7e2" . + "c57f35803334e1e16017a77ff964aced40f430b8042d6a53d1d76e8c20eb643e" . + "e7e13277836decc4bef132178c583471a61cfee71fe556702c4b32df8d10acf5" . + "e15c489c90449582e238f8ebc620bb0f32bbad30dc3105283fa739b5d12c1ede" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "1b8ff04f8e825dbe657dcbeb4dbcd09e02b5b604eed667a5e72f02e2abf34778" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "566750cff3a56fa234cd1994216467d7477de36c6511772f81cd6832dd643575" . + "8b8bc6dfde4c5beb92786834956e4b99606c5ce1a8a799117365baecc3839eb1" . + "4a2b505e1cb3a9b76837cd66cbc27cd6c0a13e1d69389ffcabf87ba599572a50" . + "b33df5621ae85d5b91a576179f655c2fcc0ea32b58202135ed9bb621f6d327b3" . + "ef6d6783325332c85a951718535b664249df6820cd121cd57d1275395622900b" . + "70938613d4faa75cf97113a9d14aa9c54a33158efd66f0ad3db4e5b205fcafd7" . + "17a93fad52cbf85c469fb70dac071a7bc62d873309b97bf3f24b3fdfe7e891ca" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bd39c29876d1b9adf84747b36a78453c17e64de226c9775927ef2b1245d3fa51" . + "bd39c29876d1b9adf84747b36a78453c17e64de226c9775927ef2b1245d3fa51" . + "19f7f3dd777bbcaf0cc491f6f8adf119a8710a210e81f08fc548bd0567060da4" . + "00722731965dad60a48ffd7346c932b3d8bf7bf115657d7d5e662969390f1124" . + "d304e52c5f5590e2e90802dff66248224282dc04975a51dfc474cbfb8c8e6562" . + "81c67af22e1b1b51ede4dc642300bc2bfbf4b7916b11a9449824152c8086a880" . + "bf0c74a525f3b24fb3029afd8c7f54ec5f710fff63344e7cc8e9a3e43a366bc6" . + "424473535e5761bbbe44fb023aabc572cde5bd1984f3685a7f4c6fb7a5d7f873" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "d0cd7aae303ba918367c27fcb69082dda0a7c10dff4c758ff09c2b743a35c265" . + "3a6af7d370ee2fee5fdc2efec9285424b57671a39b9d15c88212c47ccf27082a" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "1deadbfbacec1c94f6f442aefeb5a4755fbf7a087e90ec682ca0ca8b5e796486" . + "fe153886310063327e39cd311269d7b9560089b93324e62e5576c7b8444c183b" . + "106158aa38428c0f34d0c8bc979f356f99d1c3453600d9abd4e9a7903d40b324" . + "94af0475c2afbf29bf1a72509487bc64502efb7f8ec5ec9756622fcc8ce39ebe" . + . + "b3e42873e320692fda8d6d44f38734c0f75be3c03e0e219a7c5925d064204039" . + "8d70006c8ad3a265cf37b5889e933021cb0afa4d265b095c2eb67fe5c6576e04" . + "1210d6b910dc06c803cfa64c652b32eacd7e139daffab49f43d558a54039c6b8" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "f8f1371582bc6c17b007709ddf647d8d495eab523b69d3a5e96bc3fe1c634eab" . + "b8c8bcc14bbb296c9f96adb085f5c2cf47d366aa657e6801e0f2be2ed8244850" . + "4e08f4c244ec5ca669caacceeb1f2ca29b2f1b2bc7371d0a739917aa8e8e6075" . + "a4475a395a6f146c7603a1c00aebfdc61ebf31cee245b1f6282e1d55fa33feb0" . + "2b76eddc2ce22a20f6c31d95210c1c72f1d76b46530ed12cf9a724894db34310" . + "a17e52e177ef7923adc42e5ef116ea9a30b29f5b251882dc739c5d0475a9e73a" . + "c4f13658f0f56a19bdee87915139953243092b7e2c8a716f7d3936c4a210cd59" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "00d3df5105484cf78dbfdc5d5a730accd976de53e2e7a3e236bac2117e301de6" . + "742059262f6126714dbbdf5589008204993da0351135817bae7662eaa37f633b" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "63d11dfa275f8444a032ac11a3714b7f489c886cbe6c0aa8edc87e58038bf5fd" . + "d034ba54cac592b14e3fc4fc6f9dc7a3622bafbb1e133efe8501d2443550f914" . + "cafde1829e95eb5e12ffd9c40c3bf43f9e4db6c09b2e593118784ee88727a331" . + "74ec08292cd42001748fa46a719abdbe7c26c0fbe55787d02181086af96128a1" . + "0df85b6e91223302330960541102432beee167c7aa6066451c86eea7fc4d5e67" . + "3f2f69269af55f254cfd1b8a8c8fd8dc337650cc0a257dc592af4f54bb83eab3" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f8f23b6367cb6a0a62bbefc26602ed0e2b8bb93a4faa0838c3c735808ea796be" . + "f8f23b6367cb6a0a62bbefc26602ed0e2b8bb93a4faa0838c3c735808ea796be" . + "b8cdddcdaa4bc1dd03e857debf67bd67077ff01ae8e705b91fd0da21e21c3bc3" . + "cd568cf591bc65bd787d80e23bb6314cb0d56d848eed197744efd9807d7a3e3f" . + "f072fc7fccd2af19ace841102d8254d62c2e5fd769a143d7f6f6dbb2a5038068" . + "c1df978790e706e1aa9c9cfb02c2cc762cd3c2ac220b4931bbd0d6655f92e52a" . + "dc73b4bdde5b2df27bf18f68b6752fbaa9fe4988981efe68d24613a0144c78c3" . + "238d1528d3b6d979ca8169f37634d650d7fdde4c75cb4bbcf3b6291605ad399a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "19ace03cb9f7d1fa188694869dfe013ade11313d7c6afb9f490515110c5378fd" . + "17d4cd05af397089caf27126a8fa83c7ae34ec1f546752e9152211f78bd897fc" . + "4d13a152b99f54ac8893a41a8b73ea17b832f8bf4111715972db805ff293d13f" . + "7515cc0946a6789f71762fc9bb30f59d44fddd19ee3f582162cd850b2e3f422c" . + . + . + . + . + "85a34c24f71526ba25fd4f49bb9acd42452629d2f2931d4e5acd7a1dab3e3235" . + "80288c29136c8b22b766c4c989c9cdda4bb7e2f8752e6e60d21f59aac8347ecc" . + "ca31488685137a0cd291bb565df85003a9fe0ea345b1bcb1e218c13881a4f515" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "38a8256fa7d93b0c7f082e61e8d0450a787eb958ea01c22f73914d38148170ca" . + "c11ebb80aa5e811a0bfac3d222beb94bb9a8b816456b73117bedb06456d4bf3e" . + "84ef5f73b3eeacab75c543ad7e7e231b207450e7c6a061935b124e2370f5540a" . + "f7a76c902d3f56654c707e2e65bf79851db37092b5ad2b52642b355d035c324a" . + "2d62962950bc6570b8007c75b2b518390dbee7f404c7f676867b76b4c0c7c4a5" . + "4dd348d9793702a80b60afddbca899a658aab9f41b95f8a88213219c7ae11243" . + "0ac59829ec7a423b77a5f0705fa9a58d5e8a46ce9bdd2b5bcb8a02c8c1e3a340" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "ff32338d452848d6f1f3e29950f83b1e49d5b13ae2fc26c16f40b9d9f4b1c31e" . + "8256a803566bba4d7c117dfe9b671b468b10f56cc35328df49fc6e3a2123ccce" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "cfac6b49a0837bc8b8920b48e197693faab987262aa3c661a05db4b789092e28" . + "af7a6e71a02d8df30a2847039746a136c6656ef37789dc89fb3d7068fd3e27dd" . + "67e7fe14dc03a9d02131e8331244e72e9e12362a2df10679b7f28a7aacd9b030" . + "607279ddbfd65c99452c29e6ebf72bfcdc83ca2c2a50dd593cc81344e40b41b3" . + "31fa11ae0ab0ff4cdf02b13f18103b9956ac1552dd81e3c890fb37e5a185d9b5" . + "8051d18f57ddefba2cd89620c4b0c71fef2321a13706e061225e204685ba05c3" . + "cfd9d12367c9f6d0f98c2bc785119a0c5190fe9e59b16ecfcf57b388e2f9a48a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b5c49eb7d3d35c0dbf6f7ccbeba5a94b597b4d876f201357ec73f32530e9a491" . + "054e2448ebeb55db930517776c38ddb2547a8bec596dec44f336641b47b2704d" . + "a320420896b6d4d1595880561f2430abde048816c325aff57df41b75e55d9704" . + "2f425f5928d6813a2835fba2301b95190de069c9d0325b4fd1b81e68f224d986" . + "d030f1bd1caa046506fe1612e84b78d4d0ebd88321ea9e9c8c6ef292d8b4b60e" . + "1cdb92bc9a590b1c98e2bb8b0afa06f313d85f771d26126340308c4e43dc9ce8" . + "d03c469845d61ef52329ebe5bbc12d17c685fe7d2680f8aa2d0501cc1c896de6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "37ca5cd4a4b2a3f1b172757f8b2b484c7ae793dac73ca93bd088d3d26bb57021" . + "0b2db5c40afacac5444c577df7573c0e240dfea39a57c43a5ada98714260e7a6" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "bfc01f0aa47f57a5cc7e88dee7e54aa136197dfe75fb2494737d5dd3ec3aad44" . + "b259247bc3295cecb058a4c8878e0db960a2416661dad0719399b7cf933409cb" . + "23c2a356eb7a9a1e7983bfa9c85697dea983fffdf34f03ff605be4676365d0e7" . + "f75701893ce1722083bf062f127a524dbb86e3abde5c917831a2f484cdcbd343" . + "bfc01f0aa47f57a5cc7e88dee7e54aa136197dfe75fb2494737d5dd3ec3aad44" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21d46d5da4ded59258f11769967774aa5730b24666fc544fecbfe1997eef0e9f" . + "168a21f71e950bff80b50ff9ce27e0c9763dc78046cb26b512a12394c58dbe9b" . + "4390dbe2ec6d1a72a384c4e57ddb7d444efd3d4ab0fedad916416cfd3cf0d93c" . + "1220215f6dfb227cc25a7a832c1979c32bd26e44cc41799243cd3077e334d080" . + "d2867d6e71de091e3a1bc392364ab786f297e464e1a66d0d3aa7f924105741e3" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "ec42c141c4f87797977a7c21f923186eee5f038cb9ed60f6a0ffd378d92a746c" . + "862ccde589f2f680d6f392bc08ad67e1081fae48573446748b2ec8f29a13f52a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "8d83af47468813e862001faf8f92360705666baafa9de0af6f231008eee091f6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "063162a96ce356ccf5f09e98264c6cb089227c372967b234d46fe20389a58a49" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "68383a52d83c02156e9f3d3be87e6ff1c314a29b18502818054b5c4f56bdacfb" . + "780bcd395e09dd245e5234e8aeaeeb21e3c875e807460790f7b87f7494c91ba8" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "952ce3c29ab7c1037266f4dee0387165d8492bd1ffda9f3f8a69332e1129a7a1" . + "3ce801afe9422332d0f6f2863afef131a2b7014be1550f2fdd7bf8693e8a510d" . + "410073537f01dc33359a1e5b8bc6d4345e1e1edf60b5442f855d5026a796ee3b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "38ea00f8fc484460712bcf03340104e79eaed14e28a192015768b4b24090eacd" . + "38ea00f8fc484460712bcf03340104e79eaed14e28a192015768b4b24090eacd" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "17a79de2ebd66764c9a115e1c9eb5fb34a05fcbb050ca6cd26012a5d5caae97d" . + "f82a8c200c3cec19b0241a357c14053d49f26852086cf321eb6c66eff5f35264" . + "2a5f5de3fe08662e8cab9f6abb69ad6ccaf42eceef57551d3861ede489c015a3" . + "713c880ba4eed65767a71d74beccb758bed760a608bf74653dbffa6b3e60d41f" . + "c32da49b5e59f9f806d964cb25f9332e6ee1c1d81f5091700980f43a5c83945b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "96584474d12b09737e42c0764d08ecd61b1283df24e15799cf602f8f30465ad1" . + "4250eb2783f7b973325fdbfc5caf2c5fe2918f3de69cd2bfe5606b4186c79a95" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "45640839700d5e7a9ef3bad6b15cab0266ac34eaffff5a1950bc43d9658b7678" . + "e9e957650fd9e5f1906bbe2be68951d900b3309587e43614a0c0fb79fa93794f" . + "40543bdd118487507a037b05349cfe86e0d9b26dfc8b99b503199a42bfa27df3" . + "7aad667d631c87ab992a528e67c85be9493d15f02c279163caa843d792166a92" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cf6192b5ee87a7c92c4676c6c6fc47111fc8d9cd6f815312250feb7d2f41f363" . + "0eb2889ee97d10d4ae7b384f2e74ac437639ddbfc33d07eabcf51f18ce03e387" . + "0ad65c5f771df0db5814c54a30533a58f7a40df84879a3abbff5debbbd56c1f0" . + "d9e24e32dbacf0e4a5f589bdd3ce239837764cfdd0aaeda09f290fc08e38f627" . + "19e21f0d80c24fb69f42b5857997eb53a196baf71a430c0adf35742503e265b2" . + "968f356b8b2c69d6f2ec6a718f653c1493e9f61f7ad32c46cbfb86d66e8659a2" . + "12ca52d86b914eddd6536dbf4045e832f408d56470ef734ede75ee870ed3c881" . + "c83630e09481abf88a0805603516f3b2296087368578a402fe76d4e22ae02d59" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "1203cba6e3a93f8f1d6b30396f68479481eefee8500fd9789165067ff9fcf18f" . + "0fb06c731a63072f6fb8bfd45bd7d0908155012b14a806f9973b572666511998" . + "2208d13c58ab3569eab25166029048640690ac7f2acf51aec53042b336be6330" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "40f718b49bb7ab9a826c331184b94b2298a8aee007b802d37e864c40107d82a2" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "266c1c4b5fbb5c249c73370c17a97d01ea579679a56192084db4342c500e2ad7" . + "17ed3d4d7a6af368918b8a2cb3754b64344c7f925ca73709f61d35a91edf3b6e" . + "c21070837b6bcd5502fda098fc63a6552b264136f3646987485a8195aa5fe5ed" . + "d32d871f4c641767ba094e83ed9d2754cf6cc640946d1abbca6105b2e2feee98" . + "5f8519029fcd4cea013bd4edf72ffa090596c009d0a0391cf9d795d2c4b71022" . + "4afae97475bc55cc377595483e98f64d5d705e31a7f1a47a99d185032c77c2ea" . + "054b99533d4c0175cae7bd7c7ae1ddfdd8e521ec641f0783c284f2e12e653027" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c5b7c03121fc27c8e50f4977c1cf0c553ac5b6b9779d49ba2ae335c79ddf852b" . + "abc39df7281064037a2199c52d8a708fe2da5775f8596dc5eca791edc50f991f" . + "a6ca0c99e6b1821a3205ca8221d9a146a8f90c9c977a9d878c64f30395e2658f" . + "f12fe205ed0e4cbd79c625372df07f361c4c6dbea6b13fce42cb538e561e5812" . + "218f2c5cefbc3b3560c25621164edcc394b09bc72b53665d4514c2da6783d959" . + "4cfe0a83ca39aa5ee5c44a1fd41cc471b4f877e3eae05e198c4f7bb90d3a3285" . + "c269bf25a205af6157c553c520e71d74f8721f2a06598b936f76057ba0a2da6c" . + "84a793880195f645892e730ca2e0c2ef1eb085515c6dfc4c6af36d04c06f52e7" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "3cb649ff0affddd28f8712afac09b7f02ff8186baffcc598c259ab066d164462" . + "3cc3b9e131c23469a2c96bca688465bc2a85a0a2334b31e0c09fb08c5701f7ed" . + "bd62a65adfb087bccaac48a41c804f6487d8ca5879403cf35f55f3f0eaa912ce" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "3aecde3db8dd1c69e3117f63b55ea5ae847e27057f5232c09840617308890617" . + "57f69d7484d50bf97d31948db079aef45621b49579e224ddc878bedffa98f6a8" . + "2517797299122631d59877b40026bdfc22310034087ceff53efe6ae0770b397c" . + "007d5cc49a6a1eb7cc3cc46012a91896607dcb8633d5f360201ba7bb24a7c0a5" . + "de8f90fa8d2a913d03506316452cc05f3fbcec641e0427016fe5b862c612451c" . + "4e0e4fb8d458de640f4e55051ad0159833cd068f1ef18f3e243ea4fa25181b55" . + "0252d8707837cafd6467612a0ec41d469f41e91e0b7111577a0d45e2d47c6205" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f7a79772c3b1d705d84f085178437d076493f1a7e6ff76f0c53805046e152329" . + "9aab50478c609f99e8721c3f2cfdd12ba14d044814fbd85e5daf917423f812df" . + "479a3b752df55d080c3e4dab3639c35c436858b143dd7073456bb824d36d401a" . + "2bbe57adffc461f6a756f883eb39980acdd391a552ac085b88cb7ceb993c6001" . + "30b142bf824c75f96e746143c47c78db482665b0966c65856dd931a4d14dae81" . + "d5cd19a787e581a0ec017aae8f217992d40c78549a67bc70ffe997e5eb26617f" . + "6761cc6146a2047329f2f08426300aabc185cd14797f035d4012a4ec35b8a247" . + "956cb5b41132c1db3a29ae421803fde57811e57a7957220baf699c0e40c4a233" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "f5e560f7ab5200e975f6d9d96e108c78a9e822129b02bf3af24e25eefad31485" . + "aa833949394238b289734a95defc41d49c46d2f79ca78d667357795fba4cfa6e" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "e3a775b4147bc8634351e2de624b4d3b39ca0e6ece25a1f05b0f41cc7214f414" . + "b79f728050fbe1e344b2a8bd7e19ea75b95d7b2cf0ed439c01b5ad489ff3da45" . + "19f5acddfb274fdaa5e2b00364054349b1e0d96a308924f5e53101b7e8c5b78e" . + "a624d68eccc80d9584303db9b3534b9e86a54f471db8061c11bf8f7b6727ccc3" . + "7926ff76c575e1ff88417e22c04ae7f3065eca59694ca99cb1f1e86140eaf5ec" . + "c34c30888ea5f2f730429ca586e10891bbf99edf832239d6b15b9ffddeb6d20d" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "639b23083bb4a1cdea53b1fb6b7ed19ade1eb4fc94ded3f479625c2850099332" . + "691f85ad1f519ca2fff41a79030e55535813cad778daa6a48903281702b52a4d" . + "d9eb6e7da4c63f48191a61b91a948edfc289f64cf2ed62f950184c77983e44ab" . + "ba4e4b1957fc1184904412e65a715ba9ec74da08a431743b9abe1846780f66aa" . + "444ebac77f371885e8575e35cc0c3d843bc2f6d66550cdbe251e795bdc051689" . + "3fd7c1be322b9f04c77fa0c8ebdf694ba56f29303b97069a0ecbbd547bf879e6" . + "2183e458937f0a4fceb275d097239b4f30028cbf2ad4bf328f8205c20efb6ebe" . + "49126168fdfe9e5786b09158cf0778d4ce3e3b866cf201db7243819b6c2112e5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "57e019c7b5b64d8759433d6c89d26ce199a1ec9fd60c4d7e9b3cf9547aa4a386" . + "a523e6cd61d1aeb8a47a17247f87d746986624573e0460bad14a4b9f3afb849b" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "898b47623585ac4ee4dd8181e4f3934a112badf6f226a052ed36b8f18621659b" . + "713c2b6fd43079103815f5b3f75cb191afab2272154a066526b98f65f8e62e08" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + "cbedad8f3842434427362a437d7111efd38a79edcb766e8eed53097692442928" . + "c11cf35100fed6765467873f6e65bf2a15c820a87597bb36ed562d1c419fd26d" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7ac0f9c18a563e0f17394492e5e467b8e22073504d40bfae852a4ebf9b4215ee" . + "7de3c48b24e54d5d9d50a2ea1a467713b385e60215c397441cbaad4acd7a2a92" . + "249a6fefbc12b1dcfbd2a0c59c1b3ec7af796556bf7459233b5ab737581fff31" . + "70a45f6e3dcf66642882f89eaf3bf72a9f52a696add54daeaf7f82086e836a05" . + "492185e2cb639e56a24cff4037c870bf24fbd5826c4821b1385a6a245a114c8a" . + "5790b65928dcaa6365bfaba7fd259bbd6a08b47076396c2c85e1649f78fd314a" . + "645648df23575507ec8ccbfedd3fd67b86d2e63b750dd2fb530ddd50b89c368a" . + "2d263ac9354ce4f91d8f8bcd8ecff5afa1be567412a4987c2e02ec07268a3e32" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "e317aa2b109a8c1fb477fbea799f1f6bfdddafc270ee32068a33dd670f735675" . + "86435d3e2fd5f0ae96bce07240d43269b99f02756d46b3d3b1452d89db8db76d" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "668581dbfe7b3f03c721992d0dd2583b6a3c8448ad86da65853e648d9c431aca" . + "e9679c4f33bd7a5c92a128b5c2052bfb5433e780f547e46bd9760d272595381a" . + "c6e8528ddd26a59346be31bf5add911d6785fa35f5c434029cc7edbb0be4b0c3" . + "d76d043013dede77f1bfd16714c039de5205fdfed7983e0c0e8badd02ae9e3c7" . + . + "8cd664875125745f4a4ded998de2d62f852b34323d621bb7964231ec6fdddc54" . + "3cbd837ce8ada12d6124013106159afc920114a5ed41e52912b640cdbda4d041" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a8bcdfee8d0db784a0fc99a55e831d284cf85b23c4ea75151465822e83927fb" . + "9e3618531de76026bf9a1dc96dc85c6124b010315dfdecdc141cb0c8d0a49534" . + "e7462eb051fd7badcea625894913679ddfa66071a4b1a669f07a0fff4aa10ea8" . + "d2295b8f1370e9d5f7b7633ff72e268fe57ed0fcbd791ba177db241e9e074f36" . + "45cbe7925b3194390a86257317563c260186470fa7b75f58f27c83d8863845c6" . + "098c62f521b1e32048f70be4c04bfb0ab7467cd9d3819d0bf182be215193c770" . + "cd3f5740c3b435437978418a40518de24f63bdf3d18e7b4b8720007a31546d86" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "21f47be103aeec551fde540bcf63180165519c11983dc6d72897d9c5243524a7" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "69a95ea7a5896720a1647190b630305502dee55837fe55c9bf0b804f7c018dfc" . + "b779d3dbfd008632ac1fa097170593d27e2ebf6b06f0e0a70273ca797c7992bd" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "2159067d1d232ec908f89fcfb3d49ce8f93bf78c937d41d96c916168e426241c" . + "78bf415b073f6f4f5f84ec8bf84c5cbdd81f5384aaed10a814b26fedaf54af5a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d81b80c6483f32d5c28005c30a1af9a59be8591c34e036997443dd919cf4bdca" . + "d81b80c6483f32d5c28005c30a1af9a59be8591c34e036997443dd919cf4bdca" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "54491c641ebf841e626efb64d94616fc07b3965219832f6941b207708a2e211e" . + "9da25b993837efb04a251ed16f9782519325fbe9cca0da2e4dcae5da742d618c" . + "6be077f84be4f0417628ddfdf3e016626c8128cd948f0a8abb673c1d3b012f44" . + "b9dba451749176c340ecd33c9b9bd3f8f66f24f8bdad9ced5c8690ee5ccfe4da" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "3cfe58b8a950c363d382165e1c978dc8f5ba2e6c4b5e41db5054caca2447c2e6" . + "a07f1064de8ec756387d5bd0144660367e196a38d330862e713f468bcfb5c5bd" . + "5e6daee77afe38e403312690f95be61e774b2da1913bc056ec95d10347b15eea" . + "4bb586473904a7bf5974e4f5df8434203ac5439e990298b334a3a1d4481c7190" . + "99c83f472f0ea45c5f455904e9766725b1a0af84fc1c1a9f2fd4f267f7b2209b" . + "516bd17152317f54fd2ebd18903f75b230052270192cc4e1ad83f842df575864" . + "97e53464fdc63cede53ae12551cb9e25bc4149088ea70827213a37d22fd4cba8" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "0e6a13111d796aa030d4f8b906440e471fdfdcce176024c0b0c1805a31ab259d" . + "ac97361dd4c8cece46c57e3c9822aa72a1c561dbc73a36140ff45afb0ca7a502" . + "4ccb5572ce5ea010f009eca6ae2154b18827d38e8ffde89b753f885bb7c201f1" . + "6fdff91ea10ca5c684c2b967640aebdd852120add3b1f3bcfeb156c2c5d74411" . + "c93acced359d7068dc7117769ae84123c8926375adccf2335a1794ccc4b676ba" . + "8c3cd580f83cd030b2cfc654e0e42234cece32ef7d645d5fb43dc8d16803e09a" . + "212cd8730f6e9186f01e96148b884b356b1056dc0a1a1062ebf2eac573f543b1" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9bfad6868db78f0e2b0096b04e31b38507b90f87146a70fff4e0f76060e916cf" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f459a747061eed86647f4c982416d3d567d0f31f5322828450bedb784e2f0c4c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "978135cd6cd355b837f597e61bb1b8963cfb37d161241a4284cd32f351a34804" . + . + . + . + . + . + "d98672bae649bb1912b12fba2f300a7817abbecdc40daffb247b4d6f3faa839e" . + "1b4fb1d1f4ca73da0ffad1952adf91e99a09fccaff1229f7071e26ed3dcb902e" . + "ec1b228b965637f3c057967fffc5791f813769a79d31bb2987d1f87c675a94c1" . + "f18d53298caaaea54f51bc6765b4c16c1b081566b7337107438f61b77578567c" . + "dbfc4910089053d36eb9ac0e282cc71f52c9844b27a5f97a39dd951c3a2564d9" . + "780dd6e6e20d3af15c58014d5fc6566e738ad19f853ae9f50682b3b771e528cf" . + "9fefb73253a6582d36444001ac4b9fcf6d11d07de64513c0a002ea8e4d8c47ea" . + "d895ce32741983789cfb872118348cbbc79eea3dda182d142ea1656244831b13" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "607b1b1717c13e13b015d098be68a88962674e9503786c9d32ef375c3a2f1640" . + "607b1b1717c13e13b015d098be68a88962674e9503786c9d32ef375c3a2f1640" . + "ab238257bddc9f1d448e02a2dadc2496b3a553f3a29d158f301828173e6a2ad6" . + "9ea856c8d8e1fb289a367559638a5db68d0302e58121e9ebfc6f9827f4718a43" . + "e60145259c81710df7800e1315ea5fc6f36ee7c432f5e30cfe649cf6c99275d3" . + "7a227820cbe6ce20c41a37c88003d347cc0bb8c95f9686fbe9631766fe3b468b" . + "f60ea0f8dc4d53f7a7ba3e05d6704cf39d44b3ca9b9389ece8fc65ba88e551b8" . + . + "dda16405198772a45f9b675c37d07a58f1e8364bccff1efecd7789cf2c7d8687" . + . + "5fa38d079ce21bb9d97558c34fdb455858f64118afb984411aa2418c6f5db492" . + "f79e65aaa688f551863e3d84710ddd08321b5fd942e6aa564494d7c5d49e2456" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "fa52502c4cdc5d98780bdad41c59e1f92afc9454d5794932b61eb102014c7b70" . + "ec8d9bfbfc6ae8c53c6659143b6f11796e7a8097599778cad3c57ddb0e2d5d25" . + "661da6221dcf8dff034914ea428f99d3c685c777091314d4ae146b286062e971" . + "241b74a4bca66d44f6aacade2a724113da25101fd60a2018851d45c0c5d80a86" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "54359598dc5bae5e8d050a3a5248951bb73aa49d3d0a31cbc2c2caa11d718e2c" . + "54359598dc5bae5e8d050a3a5248951bb73aa49d3d0a31cbc2c2caa11d718e2c" . + "d56aa67d32d23a25bba64ea35e5578f77131e275d88502fb09b33573ab156995" . + "607b1b1717c13e13b015d098be68a88962674e9503786c9d32ef375c3a2f1640" . + "607b1b1717c13e13b015d098be68a88962674e9503786c9d32ef375c3a2f1640" . + "96c389d5912c36a65f67336b227a7720fc492a32147d3ae4cb2d30a49a8f692e" . + "6f29b5a2b4f1eefe57ab4354adb66ffa2d7229308915bfebac8850023b8095ac" . + "cb7ae2cb52de75055a00b87204b45e4ace1e813618863c12f5658d1fcf08ce97" . + "21870d5ad6b918e2fadefff7e4870cd74ad0d22a5b03dafa7b71a270312d0010" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "513c7946352757aed6be631df9583d14a1bf761dd7fec09450de55896b36b988" . + "0dd13e5f36efd7b968930f234601c5b6206f4804d2535b0ea78f23fa2e189670" . + . + "0e3b08f715bd7aae29d49719fc07de716593fca8ff38387cb8ed668ccfc0b7c6" . + . + "84bd9a988e309da0b3aad2de60a05575642b6be300479cc669fdacfd45683487" . + "e23b288477807d499ea62378a7234f35d7b1bd4dc86d62af76c15b73d8bac4c2" . + . + "ea9836746ddbe82b61db702a33dc46797aa183554c4ae7af9869beacc6f207d2" . + "ff7bf5ebe0a6f986c714d9bea2633a60805c5be07058473f944b4d4117a0dc0d" . + . + "e5dabc9038389f3b420a48b384dcdc6938ad9215e915662e18a0956447c66bb4" . + "032c54aa06b97936a0e3859871ade9889e786d6899ba7ad56259d9a097ae9e92" . + . + "75a289c100caf457969dbbb0844a30d6aff821c5d730b11fe722b23230305c9b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9cc95b302267b656c61e836b65ac2bcd3edbce24b3ef10e6269c1f22a739efda" . + "cad9e1bcc89d0640e1379437b9c9a8b021e7411c515b53a15d89f8439dafedf0" . + "ae366cf05fe952b0566c6444e32cb95ed0a0bd43ac58d39ce853339024a817b3" . + "2bc658a45c65f3a5ff9938045a08f9786274b19f72b72d6a6c9e7be51510efc5" . + "3a72fc7d9afaa301865f59956a0bf7508a579078106514a2929fe0ef96ce255b" . + "4ec9109d74a18fa313d481f629cf7af5a991a6488da11ce78d6d53305cb00625" . + "4c798ca7d081f97a8d05038d98f22512fe11f8ba12542e09a79ae842b9a59800" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "9f3f8e317508fe1ac49b5a5cce6075a73b6faee2a604d15f0a36a74aaf812637" . + "dcc66fe051c96d3120592b22f0e425e646fe02b12b6206a9915486fa0c8e1c52" . + "e7f144d674b2f93aa804c9ec5235615553435efd2afdba4dfc4db99dc794cf10" . + "fb83f170246da642b6a05335854034991c2c5a21d07b47e6f3a66e68d45dfe4a" . + . + "ea3ebd805336c3796ab774eeb5f4ec0375c7c24e1ceb2349d91cf9d9762f4b80" . + "ffddb86730333e05ed6b54996d453bbe8fa3eb28591d15cac8288a894bc7f400" . + . + "8424e7080c185a520eb31441492602844ca24f5db9d78b06e0749b1c793d2219" . + "64be75167889edccc0cb6ea3cdef8002cb9cbf8a1ae2c8f5aa6eb6f749abe1ca" . + . + "824111bdebf3fb6e38cf2f035378478ac690c5d9385bb91d67d99c38aa70937c" . + "5343243339f5a20dadf0a405a750e78bd93879b38b561053fad87c2883142bb6" . + . + "c4e23e7fa10b6943ecc499fa4e9fbaad8633b74964053dc557c1c534bbc75aca" . + "e2f9286edd02a18db92a9cf7acd6c24817df35a6c38ab15ccb5222fe37f8e956" . + . + "54368a398f80893caa911865fa5d94e5907dca6027be70b23e6de745dce3d338" . + "026887875505742c58e952824196bab4bf87bb00598f5c182fb8442ff6e135d1" . + . + "a158455327f126738ac7a317c4ab9433e0fba3e91e9d5874c28f77044d97e893" . + "e3a62a812f07dc7a2bfaa0a12220fa9f245a7a37f9901c0c72c390863fe5452a" . + . + "8e63be45263da0da68bba6db0728310fdfc5208ab12576442331f0a2f0c9ba1f" . + "1384fdba75b78d72345da05c0d5cdb7574ae7a369e5023e11cc5538790f76ec4" . + . + "9b84b42ab566291958e6f0d0616468c8ceb0b5e7623bbc1a91ed2b44fdca7741" . + "a5b303388b5fd44105cf7b74d38b703b0efb1839f2d3dcf2232f74c9fe45e697" . + . + "5cf1bb9c8e87656de50440845d90e544c1ef8b542d49a6b7d5dee805d8922218" . + "afaff4ac8c3d3c3c312fb3a218d7d19f8c1af0239ea94350ad886cd517d60d87" . + . + "60a8cfc0d9b45950720d6f202ccb24f838932d2f04ca2ab2e274c39284eeda9c" . + "789f7856645f81fb44d16bd9c0ceaef3f1fab83f2f8d210a5103aef6b9e0dfdc" . + . + "6dbe2076a3ecd540f63ccd971683d3b0942e1481832f4f496c59f18d00ef931a" . + "e90eced7060818ff58a29c8e3d9762920ee10a2a150c3ac1835655630cfa9afc" . + . + "3dc8bfcbcd5a865ee355e759664f6383be81ba03cb7fc69732fb5dfb991877fe" . + "9159abfd3fb167f4abf5d350a331ec41595710c71a88a3987c29395810a4aac5" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1b4dc19b13b984c74b859af2b078f3a2074db2195c406100f724555d8ddc0ab9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "c420a78583a0b3d15fb43824ada518e5cdb7c0cce9528d7189d3c10be43a8d10" . + "e4de84cd30b5ef3081bf5d7f3fe71c225184ddfb6436bb7320eea6cb4ff30933" . + . + "75c07e9c23eaa60a0ca476211501876e028c128c75da963294fc6ca518cc9526" . + "7ab82f4d166f360ceeb702079782a7a3de303e50e1418923c1061a67e37ab29b" . + . + "14d667cf9a0d0445480bfbde0dd5051aaf870c4159ec796dff9419f0c7e5e7bd" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c08303259982c09e3f04e89c4a73a1bb633056da70c257a7477fbac7dd99c91f" . + "69220f7477a544771b5a3ff320de28334db1406d3e0427387b81b42fb96a26a0" . + "0508fd1380175f4f716d19e88b92c2f1f739ba5f7f72bfaa72768de40f82f9ec" . + "ffd389f28b110117c935472c40078e85d7e748c7f638d68fab1c5afd7d9dc277" . + "efe03e9bfb2fed588c9529ea849d2b1c500616fc7ed4505718d478dd733efb6f" . + "bf6ead397d2182ccf69b1dd689ccd15e7b164b29bc05e166d8c0e25f51ba06bf" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b1d4ba1cc1270ab760b8461e521e87e25f60b2fb075bb77be3ba4bacd96bdc86" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a37bf1e64b44026f001768b66d4897fcfea3db5115adf4794101e9e8f4663e68" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d08e0cc7449c202cea85f5b09fe4c4c11dc0c6e2167d3634b606cee1b1f42656" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "84d639fe28c62b89b57263f3997e534742479798a91c290dbea08ad822b688e8" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "886264c37cee382f7aa91a3bb4f661446bd996a18319b1cb8c0573e54e0d5a0a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e2fc5bf9868eb57013bea6def73b94fa7c673a5d471e17ecfd2622cdc54bbf1e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "20934894af20acd7f18fd292b1b757c0cbf84bd62aa8f52b532e8fb664a1e7e9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6332a1a84dbf69594123f8f4ad0dfb495265827c8048ddab15aa3de856192fa5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "51d7fdd1a86602a561c6c4707dcba34197892f0da389cff50235267ac5deb29f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "17f7b6703a8ba13bbbd97c0c22ecc4e3721d5fb29a8b3235eb8d09f9c0bdd816" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3b8da1ba73cee18c78e72afe8de6fd51ab80ebdaa1eea4b0633b5abe0cfb413b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + "53c43d122ba9c5ad38cb309ce2f3ffdc85df62b8b6f482d936d0c0c7fca29493" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9cc917c5104b83a1b6a45993acbf79e4a856d366c9a55e51b09fda2adeedda1c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4d21e2df363832b3b96234fc555afa38617aee7c3acda036b9d59e6010ca2d5a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c28e38d11410d357114b8b7de8c129d93a663f950f661e543327fe2f41341504" . + "12b8c0944c94778c6c9884cafe1f8a143f12c6daf2f4e4a19a9dc1e97df882c3" . + "c1355d566fe7f2ed750921c7f593369719a253161a60cd590a9aa0575d6dec74" . + "e4056da24f95e79bc06d8ca7370d5398477a54afa481071aea2d85d2776d96db" . + "da58e72c5b56aa7c204ef4061c35fa16ee4c305c276884851ee1447b75d52488" . + "be8f90c4262abb23d9e575c28d0b58fdd1c1ae998f66264ed6facdf13bee59f2" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "c6b2610fdc03b4a461de6de5b7523a958dbf96d005c2b117e8b0945cf1a5b252" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "9c7f5d3858f8b5efbd6b354eac828c76aa36abb372c21c098596a69fdc8d260f" . + "d5f78a4210ead75b9f50e470f982af59af3cdfe86d3c39af97bc53983cc09e21" . + "d671729e4498a57aeb3b11375a247a6144022f7d5aa4090214b9cee99e856e9b" . + "7b65466290dfaa492cec40bc32b25eb24e595ad2a23ab542be32d08c0bb6b6d0" . + "fcb49217f8a5c8dc6abde147e86e3fb1be3befe8faf99161dd21933ca4f5876d" . + "97163fb2c788bcd2610a793b43873d6a9b8a1b554eab536b10c37a713bbb94f1" . + "db9fc3d9a38544dc2a55063f1047c88a8bae9b4322abe6e72bd5838d059e4c83" . + . + "dba3500c36e3827ee3b65119f6270e8c798ce436b539336069988c6aeb73a462" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e9659a8a0908d415c8704f908aedcb8fabd372d70f079c507e7c74b4b87cac26" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "4bbe1d1440cac31d3e924825fe340e8cac363bc4338d49e2cb487f82efde0f50" . + "6ce1ced1ac1f56f8cd7ee5c55d117fe99c805b89a603e36c41852fea49853068" . + "22c16e38d9805b24f7223135c2f8f5dd4b77433df7c2ee6de1028cf59b193021" . + "0b1e92bfa165ce38cdcd11fde36e6b4a3ebc87cff269bb009bb6862094f4f083" . + "2f4981d6c634920dbc634dcbaaf3624d6b617e54bb5aedec97e4d9f9739c4a77" . + "b298a2a1c9513614b0e54dface5461b8e0594894a3501cb89441b3c9a7d0bc9d" . + "091da9667877a3a56a0f857f0ebec93114f10fcb901bc73945b57f67b6d9501e" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "7a49a5460da7f993f53391f086f4fc058dab5ed38a72a5dd2077d7dde3fd23e7" . + "f6c92906a3af0623e0ee086daf460e354c04cdf11bae1bd177dce860ef2d9329" . + "4a3a7b407d9922555016dbba1cc1b2b1db8eb343ce713be9c10c59977ad9a65a" . + "20335711fade6db897889dd141e7adeaf1390d4c6ee7541bfee9f111004b156c" . + "571d9d74a7626bd00dc9071bdea9b94631d8597df1036bffdf989133562ca90c" . + . + "47835092cff54353a8a98379ca3ed69ff976ab3595720213dfc08941450220cc" . + . + "8c9dfb163b2447a45940833a9daf6d27a7fb05f4a087f0fc9ec40a88a94e7bc4" . + . + "f3aa69630663ceaa288cfaa9034a11b9338d0fd5291b2db9aa55963afdc2508f" . + . + "6bf5fa317b7631baced39d5dac9bb6d8b5bce3b030b9d4f2fb6f17596ee17fe6" . + . + "47eb54600a9eabe411009391e301753a276b36deacee294089ce13ffa3fd59f1" . + . + "a8a40e55ede2fd07f7ab6469ee2c52bc9a518f7dbf34950deabd799960d9f76d" . + . + "45bc1a35b9c80d7f9ff64311d681fb2331b302aaf402ac6c19d395dd31b495cf" . + . + "36f3ded66f36539a5074e2fe38980bba68c7a4194ff3bde893d2bc66d1fc2056" . + . + "51a6dd17703fd806e19f8edb374adc7e4cc4f8d7797939bacea2fbd2887287ec" . + . + "c114a296fa6fbe02a2151ee98cdde92a1c9ecf469326bff78feb1af956e0f9dd" . + . + "d7ce570a5128d23557e4bbe8c76f6fc773b9e37773ed63eef63a6929d12bef2a" . + . + "0150a1b8b7a861d3eeaa9f4db9d5882e4daf68c6c6899bb5850acf9489dad4ef" . + . + "93ce1ca0f589f1cb7df86a6b399c02150fa46a60a9b5174a18696b668957bf42" . + . + "ddb34a4092b5558cbe55d72a42351df7a327c08e441b2050677dc04038ca1157" . + . + "d12488409cfae9608d817f70df2afd0881ec9e08f5573e1116810452b34a6ce2" . + . + "308a37301fd1238f2d6904f5c2a5d7b4e51b4b50fc359456b39997651f6047ee" . + . + "93f638ad31815871a3cdc0cf1c8d4ddcda00c34941afffc42c6c4ecbcba0698d" . + . + "ea5bb9f146ca7c85e75842a4e4dde8f081b4e5b00ee52da8d2b5ce69c722022a" . + . + "23bdc269cce24fa28ad71a96523427a958e1565029fbbcb8cfe81f7aedb469b9" . + . + "b940ecf85eccf07d97b97ea1ef7f74674029037e0a2d262385c6f35645226833" . + . + "016f902c5a03fb57a436ec263cc438f684acbd808b4fe351ee08917f8d00811a" . + . + "a96248069a891e7501cb3d0cd5bacb48854a5ff2902e1a220b0edc454031c2a9" . + . + "be285926b7b0e09c0fa5972ee0edf76ce28fab5cffd3720f1e75973b6276b66d" . + . + "c93435f5b408d597ddb02ceb526f8d9bfaa8bad4375b3e56c32517ffeef1f989" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "643ea40f2defadbacd5eb2edaeb8b91e3bbf21600d80a976afe28fb88508d49d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "cc2aab07d16f1d4ce85c7099d30fd89abc84cccbd36de4de6b4d2a8912a5bdd8" . + . + "881f969ce59fc39a5eb21bf01d56dc2ce1e46f993d0013f3f089b1afc07cddd8" . + . + "37c5da50fbc78d14805aec837080cbdb61c026c28dc7fe01782e274669e854ef" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2f8c8caf843d53e5d1a9fd85c889b8e83e2ffc1cf6262fed2c6088346b7528c2" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "adcbabc18ba767c3136584d2f1c2844895246a04eeeb86507703b4e885c0e8dd" . + "eb5bde148532cd9b6953f00432393667657311f8b82d20b35e83947af3be09cd" . + "c9e99fcaf999e862179b2775e0267d87b846e5d3f89f1599626997951180366a" . + "e6a28ca5fcf7f69df7b0e085e8ca0a85fbc27a644787af2c7991ece3cd8d92b2" . + "dee8e4462df92ab45b734df4926f6fe380ace171f1aa183d2e5b9117c5310a02" . + . + "dbed62330e6c4433b7dfb394544a667842447283c68cb4c5574aa20f5dc34aa3" . + "c769c01d9f6a131f110b705331975d757cf13f3cdad9cbebbb7c6ff9b1bfee5b" . + "1680a18bc237b6f8052ed958d55835b5df81a4ac851cb160ab564864161b4d75" . + "01d9a058147b6f31134ac5baef6710dd6d511ad0904600c10046753419207428" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "93a988ecafa7b5c887adfc4fead576e160db9d9b810ab041493d1998887e0a1d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "dd47858fd7ad0762e77a28d7a5541475bce423a4213ebb872e5f199f0b106e22" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3a8e5d60c836da9d32e2ff34aee863ebbf781763859a23ea95d854953efd46f3" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "af1e06ec223861e827f803310655ee4dba8e735de8b6336209895e8d2c6d590d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "716b9845e1e65a2d6b352cc3640ad577ce3061933b7aebe30757329e841b6f98" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7a601b3ca27292b3d3f386658ee1b60782a2341756db86476353e7777bc05329" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "22b7394122952af6420c4b248f4213c790ede56886b1b81802b867840bcb4c09" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "0b8cd1365411912e24a3d2486dd4dd034239e6a78275c6f8d4e6ed01f6c2a875" . + "28801147acbf8633f64a0d699ada5d80cbfab92dc2d90e2ec0bef2c188066d3a" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "318cc380b3d63bf435247298572db005e9520125b666c55f969db3defbc40e36" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "68c950c31f93ea2199350b781116a90458b7f9fd4572461c009eab3a9096c999" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "77a77b9b3140099625390c855f9c8c39c66e7d831ea7b35a96639c08f643185a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "0b2e88882c1fb9ccfe05ed0f6e040174aba9c6a78cb178c8c17730e5b620185e" . + "120177089a41a2591222c3163b3f1f84c126bbc1228ee33f675af9b257231fc1" . + . + "c1f2a37a034321d180a4cf16dc0ca33f7a3c06e0718ba4296541ffaa2d379457" . + "0c8c71b9fa37ad5e6ad53834f04d5d213385f1593c04c37b9291239b5492d655" . + . + "0f3ccd5234ecb0cdf6b04f698e64ba1eb0fbec2b5d21181ca985af8ad3aad319" . + "5dde4aef60a23f940cea299d95c0ff03ad416f4f8a289f5457a9d473cf687263" . + . + "ea0ab10d91ed3f4c905a81a93d5f3e118756bc7d9bc2da852ce5431ceb005390" . + "8e289cce0de68cb377894a48ac074597937a0dec514c1faf7c2aaa140f7fc4fd" . + . + "e868b0dfe85440c5589e71ac7947c088b80786d95c15fd46217507d531db9365" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "aa2434e926a1a8a3dd0450dc1eff02b1c461cf6a5516ad09d2e0501a331bd3cb" . + "d06074cc1e1fef695019c1bfe724f98a79bc8d7965845f3a5573d4b53ff3c8a7" . + "4bf54adde7bf40b209c9a9059b178e30c4cd4ad84b83e573d20c5da7aebd8ed4" . + "566d36367c7149eea8d2bd3d032f2c90a1b1786b916b7df489efe19559a17ece" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "e762773273f0f140c48234e2c958ff5560ad9b3958f28cc21fe111ae4cba264e" . + "cf6864518548e91be272983c8eadfa37a62587e036c00623cc1ee58e147ea3b5" . + "f67ba147e5bf42d05544b744ad733f11136f308c36ba55a9c517cbd8fa273735" . + "da50a531f9692e55adfdbe692903af08415ac4c157bddb5ecb8e4eeb2523d658" . + . + "8b84a5b776a7c8db7adbbb827a90d2918c91bf69e362046ddc2abb6514d0464f" . + . + "b79627cb92bf823ae874788daaa26b36dc4c0c0d0b53fbf590f7a34c0f132a46" . + "64be7e2bae237feb9a15e79b8c4b5fcc8962d1cea68d0a915ed53620583b49a7" . + . + "515f5f4cdf2216186507d9ce88a200826d7bcc13db259a3c206264c6997e3d1d" . + . + "a74b289144cedf7cef8097dfb9a6ae9013c24ecdf4f5979e2c10edf3efc88a5a" . + . + "c2b46c0a77ddde5d20357c05616cbac92836bdeb0ddf2739966d9646211ef5df" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "fa52502c4cdc5d98780bdad41c59e1f92afc9454d5794932b61eb102014c7b70" . + "ad7176635fcc98a81dd81c9ddd06d2c9f9838a946379999df7dd08f857796d74" . + "8ac47b1a33ad824c91e11b48a2c7a01c49376f799ef49fa37ab6cb482076f2d4" . + "01de0f6dd598c65ba8cde1765d6648779c035be50ba2fd3462cac6cb879de1ec" . + "d287b68b72ca170c7c6931d25ff985bbd0b2456b88b015dfb47ec65db8c39544" . + "d711491fe123de1b97166fe7aa9ba645b479806e782026ec22abc368419cb6cd" . + "8a71401dc91feae2c0090bfe428df6fc6a1a7e19bd42772e2e882a85240c4683" . + "daf5560cd5565056b527005ddf858003d9fb7c6ebf6938e20aa82a441c7bcada" . + "01de0f6dd598c65ba8cde1765d6648779c035be50ba2fd3462cac6cb879de1ec" . + "ddc6c2ad235a2ecce4adc9ccbde40301e8de147aa7b7b18363c01768428be831" . + "5f983af44ffc8030e11b7da60a9c35ade7a89aeabfe3b043171cc999a04e2076" . + "57ff1afa1e6b243d7da82e8370dbb29f95d5bcb2b0f06bbdf235d8bd64f548bf" . + "fbc77c9f9c85208297035df6605e5315d1cf435793693da0b0ea6dba04da9aa2" . + "35a14620b4529c89480257f01e46a0ba426c824e6578b48424d2993684772c45" . + "b6e519e58a7de1d03aac247ba3992132d6688423fd2f4166810567fcb64488cd" . + "659f316a6fd019702780d36e0195b78630f2f7427d8245870cd6fd79ff0c3ae6" . + "4823ff61a9192aade7f185db985816fb7388c79231ded3cc46683f3f7be80790" . + "99fa4ca381efb3aefe78a94be464b91563038d67307facadd23ec520213348a6" . + "e66b78042494f72928cde7acd9e9d9e7d61b40b31aa0f278ebec8b755c18b76d" . + "a2ae3d1763ca3081442acf099da5fe2e1a76c300faf9ee65aa3a98cb7306f821" . + "717f71218a64db1b066793710cb23430e392813d59c65982ee046d43105f6df8" . + "afc6023812e2b252423672e360b6071fcbb2e003137496a4609227c0dcc980a7" . + "607b1b1717c13e13b015d098be68a88962674e9503786c9d32ef375c3a2f1640" . + "ce729f745178250275b42ca0ce473a0a6b8eb9a38cbcb6cb59ea50716c412340" . + "05ed5437c835a3d401b53efeace6f004bc559841d43eb74a3249d31d6d5bef98" . + "2a0891b85d47fe694fd4bf7f2d235216349e3aa45e351a3a964dae18fbc9229d" . + "3e306ebfef811581800d51f6b420ccd0cfbf79625c6a7f6306701e54b588dcad" . + "607b1b1717c13e13b015d098be68a88962674e9503786c9d32ef375c3a2f1640" . + "ab238257bddc9f1d448e02a2dadc2496b3a553f3a29d158f301828173e6a2ad6" . + "b1a1a9bb973aa245ef01a122f0390b9be93bcb5705e2f21cfbf32e6bf31d9919" . + "2a0891b85d47fe694fd4bf7f2d235216349e3aa45e351a3a964dae18fbc9229d" . + "968016c9b8c8288fa833cc2a375c672f0ada06d07c35c9187f85afed2c4a7831" . + "e7493fd89741191a9c2e9ed909c639613885679bb24f72a684968620a0089a67" . + "7e9800d7b0e20cfe239a4cf39315bbf639d94a807ad7dce242aa0adcbe7af108" . + "d525b316bf6783a13a7e500b2a27d38fa8ee42b8194f5941878ddb916d987ace" . + "d73752af4dfb5c0845c36ae23ebfb9b335cbde06a69e1f0e00b4549c06544aea" . + "9859aa3cf436d4fce4e8fbfb83602f738f065291c531f97082ec6d858408cd50" . + "94bfd567b142b0193c96559e5f7a54b255d7d3595cc211e2bbc3cd247a87ea04" . + "595ea56ecbe3bdf2041f1cdec16e0fda2fc7419ba4d95ecff420148bd9771a38" . + "1a111e5b6918636fe2d0ab3222c500170656a994b41780876c6284939f66d358" . + "44d2b6dcaab261d9ac2c33df919bba0037bb1a17b2e90ebade60f409fbc92835" . + "b90995c9bb05896d31c065616ff8ad4ef49482ac68dff1653ddae075ab12df68" . + . + "7775abb577a768334693c2c3fbf467ed3bb83f7e3676ddff00d07657a5ce6c31" . + . + "93879c24a81c883b7b594716179ed598e73cfddde1d8954cfb204021f0b04378" . + "36fbc40bd1316aa40a9f4bc5b871c8cc4107e4fd877d0339627cafce4a4053c2" . + . + "d6420784bd9882f6e75a894561b80916103de64fe796061bec504597a06d4d7b" . + "dff239fbbb550f21d9d746f2db56f382bb0826301d2b04f3a760842d6a772875" . + . + "85c891198749181efed35dbd978063b1896dc2b0d264a5269dc00fef03006c4d" . + "4bb7f474fb98fee559a2fc8b5dc1ff7261ad949e4ea3c3f65ab01a89d0d7508e" . + . + "b248629c749d6aec4c3798c2abc89c173e6125c66bf76428c744f867be908c4d" . + "98783615269dcba600628e7b923f84809cb2a4c0e70e15e8b284354fbcef81f3" . + . + "4228bf5f52901565994a5c3dbe6edae44631d80c2b71e28dc76e458e783c1312" . + "adac4df67995c5f7fbe850afd067f8d899984e1fbd1f60b6c3bb8a4b1c70e377" . + . + "eab8061eb07c15ea581d821235c5456c13e10dc4b0a0d5d3ffa44c69630ba42d" . + "416df3d62f64e1257e8356d7c24fa52bf920f5861e9357f5b8b4e180a7d72651" . + . + "28a4c504fbf50175cdf0d70907a62deaac382c4c71d46cbd76ce201e2144c2c3" . + "90d6ee12ec2638fe1aa9236350c49e66cbf390634fcd74f0b14202b5c4c59fbf" . + . + "45d7a20884cbdb14ccc0fb5a75bb022aa4689262145f542b87d77d1aa972dc11" . + "b7d582628a63fc2f9143dd6f5a8c31e04f89e1bb79545f614a8a087dab228b50" . + . + "938ce73d8588e5d5bb9e8d8abcc5462d45ebe0d44f25a3c892e4a1f9f49edd13" . + "047270174cab95eaa10ca007d47ed800054c8cfc317e985f70d553aea8b243eb" . + . + "3ef4c60178df1bbf241282c7d65419092cb6182debc42e8a9e90d1150b3d9f41" . + "8c4754ab0f1f3ef96bffebee1874db544c8905d4baa242d9540ecb183ea93dcd" . + . + "ce044bae05215f3c15412e6e527a51b3e2b18bc9ae1fcd2fb5d8f77b90179ba3" . + "b04b45bbdf3f5489f3d8abc10f2535d2ad3af3c5118c0733eb9fff5ce6580893" . + . + "721792b3d2c9a00d647dcaaf3545e7fb4140bd3f8277fbc74575fcb17c61e53f" . + "481b7f8e82b65921abaa1acaa5ca852a44e01ea5509008ef7315521823ef2bc5" . + . + "51d9065462bf9e5c016b777de5114f64daa50b734becc5f4285911dc96868c14" . + "81bf7ce644e8ae6d5f605b8b9bdc3f6f42abda7250143581707cf6b02d7e45ff" . + . + "52135f58417f10001abab2c4d6fa4b465c47d75c4b729356cf3ed8579f5bea79" . + "8dc6dd81f1d5293ff88654f79b6e6a6bf52d1b1f0b7610d930d581981f960d63" . + . + "cfa7735367b989fcb358cd536be0607cbe389730bac56313377f759487d4e040" . + "a753250cd9ca634860869c22b9cd2a9faa00e5ae7efc80ab106d063567b16b72" . + . + "9ad41fdc4a1098da5380675ac8bedb59deb06205406ad9ddf6a12d75643cbeb7" . + "9529cc82391ab404da01c43d36bb7be5a3b4bb737a3e51a5539aa2a83d286fb7" . + . + "206b17d3c8c37233ddbc7a2e8a078960d307d3addcfe1f29e36a09b8b10e0532" . + "37faf8d2240dc803a1be638c3d828d3843fce0b1b2fc4a43566d5acf221d19bf" . + . + "c464e361a7f19689861f2208c409266204161935e1240bb55e980fbcdc492bc0" . + "b195d921b813a62cbf82cda128a87732d726c6c2f69de1bac9c06ca53b1b08af" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7a48eddd11882e57fdf138fb0ed5373a7116fe0d169d809baae6999c34245b2b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "2c3f6cddedb13f2cc91b0e49aff8387729aff61da5f59b414a42f63f40eeaa67" . + "fcf8e6bc704383223dab54abedf124a0044c8bb008afeae49cb3d54cf636d2fb" . + . + "268a3e6c7b92a4aa83605dec2cab0a767f147c9f6e7e6663260edc326eef5b2b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "cf7b5d2caf8adbb57b46b2f46f848b281b21c32577e009b15a01aa076aa65c07" . + "167e06993da5a765a555f7e4881863eea7d672f71bca25b95314b58429b31fda" . + "c0a57345e47d472fd080e7781cb0ec705f2b4e65477813cbc92259921f3041c1" . + "c984a9052144d676e2d3bffb78202a8b30dd5d1bc08989e76460b89319da22a0" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c1cdfa341cc52af5b494648416e3240f806810e1394daffd16c3d7adb6251054" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "73523cb252949cf655f9e2f29a19bcdb3ff264635b811405f71e524779f176b7" . + "db8db09afc8f5712850a35a531cf8e4ef9b0105781eed9606a75767c2c923027" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d027eeac96144ba96a0e3180ad0eb83ca2b38b45df15ba002d3120af9d5fee3d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "277adf3556a93e31d0765025a76553f160054adc9830a1a1839e0b68228b63ed" . + "7fa3d2d4e571766039f66ce1cf0980d9ecba31cd907614181a2ccde338495281" . + . + "32ae6644a3aab7b10dd4f8a9cf633d38f009552e41bb792ab8458bf2b40d1de1" . + "116f83c2ec9b498e7bf637c0e789a2f893780b811e44d52d5967074e4eb800a2" . + . + "ff06206198e3ee49d848ddef342dcf0097f1feb7777d2debf6e9aea8f4a24348" . + "9858dbb003a5b81c30b623ce928ddeb9a15a06ef9cb781b9dc511ccf58c9e624" . + . + "c1c830b970e1eb6aa338276b62028fe79f617f5e36244f8770d297edf1aef077" . + "d95a2890946983d0e2668f24e3cee32cd09cb619e76f4a368dcb965657373304" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "68b48798d892b90c8d40524d35a122080f4eae3439491df7a4d9ec34b57bba8d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b0bdc7f198f91fa8533e08da5332b40a95bbdd09039f39e4ad2d09f0b80c83d4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a3d314be3c0e80f252d168b5da8696d7a4f137af15bd91cdd44b051327773069" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b615111fc9a746a85feff07da1e6e53513506468e71486bff5bfed66e71080f9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4efd380020f9ae116228416af6cf198b785abb79013fa05086924c68d45ef7f9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "90cb5abd3d44fa26e2b1cdb5e42c6a74f693405cec7c365bbfaeac1a506347fe" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + "48abf401dcfdaa16e5de6c6bdce9a8fb81ea2be71a4ac965fdd66b4e8d5eefb8" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "93648455d978129726a4969f9ee42a792e9b0a309c0b5d5b2c9344515e42a04c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "a640f3bf283f879141310f6b35b68bc1875b141a52c5e17e56cc1d3ac94ab4b4" . + . + "eb2b0e91e965c3ade5d7437f2ea6582f8c99ccce5e809f7ebade9fc644b0d52b" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1da7986d47b280a9a2e359379e0003bda795c252949db2d3c686784cb26f6024" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "ea498ce6f74b1cf98a7fa0eeba5de2cf06ca262fedabce8228b53e9d6e3a884a" . + . + "89b0a771ed151c908c4cb08ad491d9c93a322ee9906d373e6ce0e85344678ac1" . + . + "00c9c49ee5fd8ddc675bbc6ab0eac4bbb0780e1abf18031c98b813a692771e96" . + . + "33240c8a4c1c4dba2468b2d14c26c4639bdaeede56aa4eea52529bf571eeedc6" . + . + "41fbe26a7bdfad7a40a3261847627465a336855543af4ee3c1b2184d55a0e985" . + . + "1d24400a28e6cf1eb3e7bfa35ab8def01ddec4257a9efa8b565856a9abaf9ad3" . + . + "9c90ac66790cb81899f85eabebb26d498b22833c37b34e765d15fe28c37666a1" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8a787e82e7238281cc109fb3a3023f9dab4f339b01807d01507de2a33cc05d71" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "4e9597b0a30759988723256fec12edcaa84b1d4d0fbe11f77d0d9b14b032d345" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "06096daeeed0886df9429620b57cd8b29c87a164b824d812096665c1ffe27dc9" . + "00d8b1352dd7313072523b787f4211ea405242b19550d0d52e7014a4f61dcd5b" . + "29ddd7c117ba88ab47bed94c3123ce890c80bd58f249d87c6265cb84474602e4" . + "953a5072e31d0456d0f1b6e6cc617d1b6d0aa2380e16492b5f74069cbd7da57c" . + "822e7cd78d9b99a7074548de719f7569a75b7a9a2ea524e44b37dffe288f14f5" . + . + "4da11f6bf237c878cdde15c67d8f832e7c32eb084894ca821dd899f07664c206" . + "560d9681f33fcc1003c0d80c63df3609a50ae51b4a46056fe6ef98344cc62009" . + "62107c322b191b9cfc12e2d840922602d320b13228f640d3118db3ff1ecac68a" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "88cf478fb1898c0f951aff9c298799398b9035e7c13ca084aff900e3a849cc06" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e22d2eaf63dd411a7c8a6db130ea759b3500dc0cf5b8e0a82110e7d60d5eba51" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9a3efa7f0dc5b070662e487c7a54070d4f5df0b3ade84e3ac732ae83e590944f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6f64b483e0f1e1b35119eafff01acd05e9bf02582ff5887905445b1e3394ff84" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d7cca836a06d02bbb847f565bcbfd65807af938d8c54707340d7cd6e0fb3d9d7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6d87e1adf8424e7ab2084512639bcfaff3990808b64eab1ba49fb0b3f93550fb" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3f403833a3077e722bcf38e7d9f3891cc1ed323bda0715d7c878a8fa52023aab" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + . + "6c8b70a3f93ac0068a195f4ca72c3bfb44d37067b5591da0508119117278328a" . + "3a98e62ce6b93da48053e1668ccef5cceaeb66ee3a5853ac6b1724bd165dd3df" . + "a5e2afa24937ccd37b112a07d37d39a3ba6bc0c0fed5df17c66d47264b0ee250" . + "d76d5939dc07ef151ea44c8121171c92b27b7cd155852150d7dafdd7871fc1d4" . + "a2c2a241c952e9448fd16c5aaeb878eb5f01fb06b3b3c4de0aa2503c69a14a7a" . + "f1f80ae32e573e738aad22f425c50588448771abd945a365a5be87e6cbcb3ca1" . + "4ae05af2a302db55de775accdb965d21ba0457905f17672aaed532614e2297a0" . + "6e1a608ccaca97425ff566bcb9ea0fb09c7da8981362bfccef476583e45fcdad" . + "658c98f1baaf59b1a7bde70e92d2a1eebff17868a1024fdf15b16870e85c9aaa" . + "d67a93c903660b0cd79fd8190f11ff27155097760c21a6fb5239503dec342279" . + . + "e8fd515d8074a8dedce4651358b360b06ea7d07eb538439de8964e0263ef4baf" . + "f47cf497cd039a929e78d3d5961c6e0952fac9a511372dd3f3f3dc3b928f5c7c" . + . + "ea8b0428697c4a6add568485acb1c87f553c24ed660feef2873c71caf91acf8b" . + . + "525a2abfee78edbffc6589269ab51dafb7ad2193225480223601d46e06d2aa90" . + "f68e451f0511f550e0a79738f7652b16352d362b6a751e11a60eaee1d7620a67" . + . + "c0817e5c5008df56503750eea36ce5d06efdd8a90b8eea9d9c5d328474eb9346" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "ccf9461c7ee2170682f0b8e6469863efc993f2b8a3c090b04afc791783cafada" . + "bfd9000426e4fb66c28c97b9eb7d57fd5c344e0f3f552e7f3d8b124b23035e1b" . + "120675ab74defb3b1f6963122793f5c6c61b9066c0a4c0d8be774d1df110b6dc" . + "d457b1e3ea9e74ff11c545ceb4487d5676f7affa2729b246d621453b93f0e614" . + "1ea5c3aad1dc06e86617677c6bd39ab39c4d05b24ce819d40c0be8ab3c6cb069" . + . + "b0f61f76b89745d0eb9db2dda2e81309ff6c34a667ba8a15784a751dd2af5383" . + "5ed4d5076063fa99c909b005ac420ea1b85c5699b6fc5918f32fa5582ed75041" . + "e6696baf72afa52f9f362adced5ff14b09bcf2b23836603206f2626be5f8e5c9" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "43cb6d72d67fb54b1296e9fad3ba714619c34ebf40a9da152599342bd0184c77" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "34fa5265281cddb1fec0d69592d6bd0bc7a35095eec1af7b70ec2b2c67631910" . + "dad07be5761fd2ce769da79eb4f36fa0cbbd6a44007434c979d291476461d1d5" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7a0d121d5f59dd810fb0199aa43efd9a49acf409aa6119833f68f0ea8ec453c2" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "665528a59c42f29d352b5d77e54cb3b8afb2f3cffb514a7ea71f0906fe9fd48b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d7d16f80812350dd8bdd1c94549aa58afa5ac31c34a5050f8cb6fcee7be3eb1e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c420fc548be50eeb02f1cdf2122bd53667209458e531a59be005dc4c96e73832" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e25cce4095805960c6a40bd13a83c3780c0fe9b0a37d33c37bbafe224ed25261" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "43c9e2b3dc541501db0cfa7fe640ba06abf13c1c3fc2f511ffcbb5cbb4f78285" . + "883f3c35be5d12b9945fb63290f00084497026bd0b4b40729ede9fd94dd88ca3" . + "f75d8dab0e402f646b8d9775701a5852485bec39c523f0297ff4a5e9394a8251" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "780e7f31c73096af0531a75196f3c760b8e2f021083d37d5ad877db4f80f3ba0" . + "b74213e3a638d910155cd46aa280a2460b30401b05ec33fbf9d83d130dbd5141" . + "6edec87496165d04fc7d79cd7cdab701bdc63a2b20303e7a160e280170d29db3" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "03296ec5184d34adbdfc52e9dc8b26a1f922a7da4e46a61c195c4ada08281241" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "defcccdc78acc4fa8555125d7925338712565fa825f4acd960a7536bc6c24842" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "90d1c2462705397ff2271cf7b15af5831c0dcd8d6e32c23b1add42e61368b4e8" . + "0c4549597a02077313e564ebd853fe76bf7450b907e69b9328ecff63885de441" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f627a4674a9badd23e997a5785b23f19953ed72f0a2cd3da7bcc0b53d1420fd2" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "52c070b85cfcd7e73e0c156255af8f755aefa7773780c21b8994a8838acab7e6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5152d7ab3ac3bc51cf6f17770e1393b419e36a8987bbab1a344393f53d50c30c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "44470b7edfb77520da8d24de521e6e0e4b60ada2744e4ff917eb40e148863b8c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "718287735a15c1d0cf45e4e93feb856e4f0232688ff9332439155614d0d21e73" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "820457d719b6fdd6f832ba7e8e2ae7ca11966e7bf3300a2b94228946bc68422d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "5dfce92484b627d87e7d930808cfdfeaae1464b3cab81595c417aaaf00920cd5" . + "6a348a6da94ea2c1d8f20ca04a98c088b392d4ae61fd0f55133b4fa6b8ed9103" . + "9fa7431c44c1c4a7106ad89d83d6c778ad9cbb31a5e47ef10cd86dcc07191b56" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "678f24dea424c01ceb667fe5e0280bb615b68b22553e2824c5d85ec0805e890e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "0f20167b6346a9aac6b6cfe1d75f84174ff87fed7a3159d06698c5a620aa88dc" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "730311b95278ca4545d19b6be8c2093a8e1b31d8b3685db97218345760dba50b" . + "37bda8ba4693d914989fe4c1da8074abae0131e059cc6f45fbe89d9893d0e17a" . + "fdecb73c87a600b74135ea494f2002bda3b3dad012638067cde8b2c252f70547" . + "dbfbc53e0307a48bd5d4b7ab83faf690c6b9ed0c1f3957cfcd564bd56750ac9a" . + "470638ebd1a7c1dbd227ecc25f49dc536b859f786bbe94616505d07a3d701da9" . + "be246f706f1ca351f7f20d443984e2d510a85dd2ff7739e12ceba4f22c6e6e73" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bcbbbb7c8652c26a39f5e25b9c4fcc1b03b8bed4e8069ce9d4b56677aa62d733" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "505c11569b064b7c0d12c79419e741d9e516f4a0a6e6a4bf09cfae9c02ff1762" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ab2f773cf1f2f054a9a6bf50bbe5cd289ace89f2a2bb985d7a3219615e4e3680" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c39aa4f540d4fd0782b952144d97515eee4b8d0482fc1173406a09f6e4436851" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8c3e5c3050db08090d956513b145ac28655568acbc847c2af95c16cc4c62289a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a7f5016a7f21902eeb999e0875f3aa18831640338dbc5eca237b26c101a3d7b7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c356bfef84bbf6b635da365bea3af44361a1f4b92955a28ab49d13d751a05cf0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "493f259d3d4c64ee3aa06fba3a59240070c1b1eb3a91310f48ccb4c677d9edbe" . + "56ec3d367357bf74801e5910b85eb0850edf8c18fe87532eeaa6df4c7851c378" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b6e47ce11d35702e17fae1953d6bb559958306995c578d12aae35d329a87777b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "2887e0c6b98cf1205b21b15cfa600ca3e64c63f522345660bb21297273c0a119" . + "e355ec99cdc7a4c6840a87e712403976b421ce50995bd15afa6d86f65c03ac4b" . + . + "e2efb29f0760bda88183b56720bfc505f18facd2d46e3427de195af4203d07aa" . + "b30a7914eb76eea1feccbed1c154450e0ca4d634939343919384ccd06e98f34f" . + . + "594dec1315b71c01bd638802f90837e4f82bb511e71bc57433c68934f58770b1" . + "e8184bd1cb8b50ddbcd960c36ad0dceaa0fa81d860145cffc1eacc47ea98046f" . + . + "d7d6e54d37fc474b17f3446ab4075f197c1c386760fbfb95c3590b03dd992dad" . + "0378ffdf6184475e21116ef09eba9f4c55dc7ee72e940fa7c8c262bd59be6a74" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bce79e765aedbf459b503cd8361be657d893fbbf3742b09b41ff9fd8dfe6c6c0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "54f6d958c80e4d7fb015a559906e1d384f98919b5d40555ecdc00586f6d8bee6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "78c8abc87bdbe8651016f0f343441d65e66c624213642cb100e77461c0a19ae1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "c6c9d83e2e59bfb04131daa64277d17da7f88d3c8bebda3041be3c6ea3d2820d" . + "774c8c0e03412da3dcdf8ef13fab99ffc856c2181a6bf3d7790a6a6cd210ab9d" . + . + . + . + . + . + "70bdb6ca4df57e275a59de3c6567d79ced553f844357d968b7212bfe1a5c5ec9" . + . + . + . + "17882916d2594c6ec6c3fb2f8a8c2188c27d26266442ae56f269c39ae57b6359" . + "b140d9a9e7a7bc9835ec23ad6c5c4859807a9b863b2b514721f1ec7aa4db7866" . + . + . + . + . + . + "e80276d18875bfa7645e718dd28261146cedb36951e90788eac781ece4a3c555" . + "5845f0bd146a3ea41d34c1359cb9c3cb3af7c2a22a9efa61857ce02a89dd0f9c" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "781ff0ce2bd9c8af67a20febd62de72b2cf5c69b9b193452da8ad059c1c2bdfe" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "15dae9ee64a4da1066519bcf774904a221546b42794d81a83b92a365da46ed0f" . + "535b7f14d0f6a2298c49d0096df0085a852e8e2463967ca59d99c1dd607e4cea" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3e735b12d8b690841ef39a63a450187f331e006f27491f8f176203dbc5061298" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "0b6353695e60744838092716261559370eb6841d2f897b50e80033146b30a80f" . + "79d07e8394a54a9c3185a93291158c85d5ad89add78716259bfe0c911d2986c2" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b620acee8819eae428e429f447dfd04f58b5d451c5553f9ec55564c2039c768b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "d0f387cff2a09961dba1aee95aeece5636212b2045f5deb5be60eee3f1a934f0" . + "7311a3ec30c9e25777cf1ed5f7b643228007a59e814b2dbd03f17830a6ffdebf" . + . + . + "ce28485cbd09cb03d2b2f282f6bc9f7dcbb94eaff815d998e3bf3e1decacf367" . + "4a0fc4fae7d3d72548304486c533623924fb235897efc65e7b5aa1d9660b7104" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "455efc376353e9b63d28276bf564c885a21502e76731abd618a374f985384ce0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f0815db3cff462622a8b1c82661029fb774ffa9bfea37e406f82ad0a2cf91225" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ef5990b51020e2a5818d21759dfca49efd7b908091a2735bf6074b22edb0c8c1" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bb61cee387cb8b3735e46ee6ff6bf457fe8678782823d16bc8a7e26ace6a548a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "90b9f7fa22f00651c2eb7fd41a579da0fba1359e50649fb58038837826eb34fe" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "93fae899faa0366dd321ffe272e5888a04b441d9ca13ee088a785047b557ec7b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "370c4ad049b88d6dbba5ec54fbb943668461ac908546add35d72c1cc3c7718e5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0aeb207dd38049588de6e8cbd24ad2c2872fe42deb274f946ffff14d7095589a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8cadf45f6b725a6688c0ed4d0df29dc98cc64679f414dd746495b5d11260306b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f7546509be1ca13da6e5917087788032299b88d59d70f1574ddccc5d99de3162" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "1662ecd295ab490e54107cd46fbaeeb4b9b8c826fd461089a820ffa3b7e90364" . + . + "cabe1d189118f6a656d2aaefeef95cea7ac9ef9abbcc608c1a523d799a231f13" . + "74475cefcb922148f7147e65969716860b01ec1a21c869bc14e16f041bd9789e" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8abcca61a00bd9f6b4ed7a4d337af98f7df6e3980748768e1c748ddb52b67be3" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "b669609a2f831b24982080fa43db706320395d24856812d56dd93c061b551939" . + "5d9035e98ad079bd12f231964ac013864b179b66c30156c703020d51fa8ef424" . + . + "ae79e723abedeb0060ed81f6625a18edbef8a7aab47c3490835b63638f1bf327" . + "4141f50b230ee43c1ef6e1b8ea94da96bcaf525fd0952aea6b38e93c86bf671b" . + . + "489fa9691aed49061f26a5872d65420178e3971e9f9692d5d8eb6457689ce48a" . + "589282c8503bd9e563389b7d87aca200e75dbd2295b1cf41d9848c30b073270b" . + . + "6d1b28743675de2bfecc413695d15e13b5026b95f5ad60eb8b85e5dc4d1be2ef" . + "d3ab2a4435ed2fb69d73c0d79db1bd3c434f57a5a1df425e8e590c0c8b05bb41" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d99a453c17b21d4d71de804bc8e55f18f3c2b68d1d66589feb40e9986ba71899" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "b7deadd4b5e6f7a672b4dcb643cf6538de71a5f84ca11b6b6e85c3ef3b577ef2" . + "5c0abd58b172be962d6d8eeee12a283e4881a8852b04508e3aa5d071c3884815" . + . + "32de52e0950a9d6c494285ecc3c0b0b024e956e35392f82482c0f1fa1b8e2222" . + "96991613f681f1f98c425abf44e87d28bc5a33284186064d851b5b23471083df" . + . + "348e60f01dad476ba49eecb4d5c8fc0639df0bcf7669cae76bfe320d8f05e595" . + "0d6288f7d5a731a3e025d98f6b0a9109a0bf1bab5f03d4132bc5046838fd42bd" . + . + "45037ed9d6a3eb8877b1a142c3ff1f63c23bdb3fb1b515ac8065051a969b2bcd" . + "171dc23341f6a82de0d89e4a2270effa642cea3ca4c3b7b5ca4af8629439d94e" . + . + "5cff7fe3c72d9f7778eeb1859bebab377dd0deb40930f2611cc5dde5dd783ff1" . + "2ecf8d81740f5f2713b45f5334114ad1161915b5090947883eb780e41669ed25" . + . + "abd8378bceda57333dd7802c139e2ac042c33f31a5028d190a42f552a28ea0fc" . + "0a34be2babd933dbd8832a403bee35628ef04da3eb52c4134bb7e853726d483c" . + . + "20ae87d46b86e47a76cac09d9907bb72fc3ff654c894a1231a68d8456e8f3778" . + "aa266b1189cee534318a67b082e81f621e35c6cbd419defe5f367b5b3a6de681" . + . + "e5cce9ec3ca4197a71a02de65e6d3bd65715dec983172a943f495cd273cd5b9e" . + "5358c947a3656f73dd8a6248a6d0000b747594d5f0598c22a8479f23755b8aab" . + . + "efe0258dbd43a099712f791759d953b8db60b5e93f867ef05135c9bb9be2e443" . + "9f2f0216a5067fab4d265f1a2de5abf5eb481f027e8b8c8ce42baa90e72c446b" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1db7926daac338a9394c3816e19554affd82c120d59abe450abbcace02df3a32" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "e9f3631cd3c05cd28b7163c008c8e95eb50bd852df3690b00d20a1e97a86527a" . + "d35201e985b1ec06efb15f438bc37b562ed9a76438e1c291352d05126c1973f8" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c1c343cc328d9ead790712274ef85bb13e5d4e2b32c8ac10eb2137d48fa86d42" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "36038187cba70e09146edaff75c0187988c56227433bb28f557b48f436b8cea1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "d8847dd45ebde76de80462417b89f276a664a7a242cf4ceb6eaa8e8d14c77566" . + "2856abb430a4ff03af479fd2076657e628aa32cdeb56f9c00a2f9fc6867c1ca6" . + . + "37dd65ca6c00f83ff825ca9884d504d139c7cbd0833eb741a078ef3f00b5a1e3" . + "5f1151e8607b9b41b6ab3991105832714cf1583b8244f35616a17c753af07c04" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a30b42e305478e3ec7d7afb19cd045e6f8a580c675cccfcab77acd1595ccf39b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a9de31179ce33053be78196374e231fed99ab90727f43b58591062294fd2319e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "9826480f33b4cf941991cba2556051b328dfd7f199e3a28957ff8941f63d099a" . + "0bf7802eb6079d56185388d8b0e54df423e424b3a21b1fd302743234f9ad0654" . + "0739d46cba60c1bcb6b3cff3916b4529475ebd9f695da3bbecd9784027e38497" . + "68867e5fcd8dc622fe1b395c89bc862dfe3f45605ba506029bedef59596b673b" . + . + . + . + . + . + . + "cc10f7dea1d627138b80306d76ac114b8d2ec6030fc097b0dc3dd37b1ac9b9b0" . + "0295c0ff58824ae2335ec854652870de2f8ffc22ef40f75e9ccb6686a8c47b92" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26e939d59eb68dabdc7b19f275b5a2e52716dabfd70cfcaad64286a469415b2a" . + "2b415d6c84c67f565f59fa81bf218e70550cc0189e911aa4e593de3a101fd43a" . + "fef0bc3b246a4541ec62416c5eced110011e5af87723850fbf225fd70b3572e5" . + "f17c8155c0cf221cc533b64a38beef250ee4af212856068dd51bd09fb2f6b3d9" . + "796dcdaadbafe4a44f2a45342434e066069c4292aa3165ab2cee024a2c99be51" . + "14e7fae8506b4b01f03ea9ae3f121d8b2cab9bf8d0abe7a6300266ce717168ab" . + "8b6f8fb0b7f106307cd64eb3175aa91ced94903da10fce6365d5314588e0282e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b02a1a2cb35ed1d65f3e80083b7e3f651ea96ef870778871fd612d39a8a3c848" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b918994e0dd366a4fb4e6ddb857776f78315bb7ca8f0b3986423ea5edf7a91ec" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "7b2c68e7a03a354235a7ce412ef9d5246d0f11fb288394dc43adc197e48a7609" . + "7cdf7c58354da9da14623d3a0904c71db07bfa0d24a4c41c2e7038f2a2bfc9ed" . + "48a7ebd8d4832542e67d5796357ac70fa52b937cb2c102bc8dadeef465ab31c1" . + "fcbed72acfd853d8df61064a2e72bc4a5364058a7e56b0529baa455e78c86ded" . + . + "07c7a6d3a13eea5fd808008c7d9fc1ce141094ac3cd6ed918558e2856114a40b" . + "cba52a94068a833dafa21308898471817fee596891511e7a5fce84ad85e6966b" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "52573f2fd88743fc076d24483fda145280a10d3f24c875e6d8f91718b3b9b567" . + "4e3fc37bb6d1f7982caf692a87b95d0cb011d1cebd66468c858a0a9d53398f59" . + "5f737d75bd88b8c40b0ce6204dcee752314cb9bad7385d651c40f66f5361c0a4" . + "ce6cd91e2dd4092f6a547be942ed33a01647d377903bf1ee44893a3eb6768ee1" . + "6a0ae1bd8dcb3af6c86e9cc578c3445afe9c277539a180fc0016bc196529761a" . + "bd313236cd680c17155a8634149b356103c6e0eca1eae7aefa9abd9e6ee8d675" . + "9b6f5d59a24fbccb866eefc71cd2dc2a3312dbd23e66517f071b1577bc9d26e5" . + "85db53262e09052d4dd1e6669415806ca48af7b0a9a34e9014fb541126ba262d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "e6d5b7e7f0363a288ea3bbcd53b544490a2228b52fb36ca9c80bdeacd3a1dd9f" . + "c7ac238e5bde8cc390eb6ea5d7ba82ade02b60894e1899b31af549753d8e0364" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "edfc5ef75b65aa8310dec101592a3dba63f25d094afbe4978224a942175d23a2" . + "2efde55c58ef6897bcf0970fd6a0d93dd4aef25b6dd31a9e1ac6b6c46ec41074" . + "9626002ec0701b6f8607ad9015384322c1aac1edc455dd38b42fe909a1e106ac" . + "4a5bc19dcea6699de0179abf19ac038cd828b471640f717201a267a12c25cb72" . + "27632732ab96b899ac77657e6830b9e5712e051bf4fe5b498b349bf1ad9a8c7c" . + "be7e4ab446e270232d241140fa3ee7e9f6c5f8247dee0a345481c7bc35818c9f" . + "621556ad3d2aae50433795b8f8d0d0f1c389028d5f78c75a650c2dd3a836db47" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9440e5c57ff2b36f8eb723345240fc29b02d830dce5c34d01e73c36459e98ed6" . + "7377bba23242c4682e7445da21c4e19a15810f54a82cdb39b3d8a861ba917281" . + "5b47cfb35008a267ba3817ec448af1104bc05ac9de7092c4f4c3da98d25d6e45" . + "6e9e71e06f7e9305fcb367cd910d32f44e96b7ae5fa63b67f510cf5bc7147a21" . + "f2974894d274b385ce84dfa549aa1dc2521ad45b8d1037dca29ddc6d1805e86a" . + "a5a33e237669a16e7de269d8fc7711fc5a7be89019de31587f830835af00d589" . + "2190c751ab73497b76c78f21ffddd3a1e3be0ee7d86ad1f46e2abfeb02ebdd08" . + "7bc9553a037e198cba37fd966bbb2264a07d49ac010b3ed52de295cc767babe2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "7b3859e85add3cb948501ade9fd4c58b4f08cddf251e33e0163fd0b7595df6e0" . + "bd62a65adfb087bccaac48a41c804f6487d8ca5879403cf35f55f3f0eaa912ce" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "4b59f223187e8a315ec50dc95fba0786b206d570cc1bd9dcf99e760f2a24f960" . + "7affce056137b6b2c58a3a1c6f9c696d967b6ca14c3d20de8dbe76781333d3d9" . + "9d21270ddb54f1e7f3d16f18c72890d61af66151c8320a76fd662fa5a1ce5ab8" . + "9198cc339f2875ad9e08fde7c60b7f122b47c5021130cf530be3041daeb7e24d" . + "df647611aa2838b0ac497ef9b066d30a72bcd8bbb101758c27dc732ce4a11b38" . + "50fe7aecd996bbca3ced76335e331ba1fa57b55239491365d232cb8a04dae2e2" . + "6e08a6dc143e510daaad63b0aeb0eaaf083beb8abc690814015d1b40a3164d6b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4af147cff50c6e25663eb22c54249cd94f185f65b6248e2a9c5889aa1b0120d9" . + "4af147cff50c6e25663eb22c54249cd94f185f65b6248e2a9c5889aa1b0120d9" . + "e863decb7403e6109b704567d6571c9c9bfd426f7136de612a71569ceed0eb96" . + "e7eba29bcaeff8bcc787f0a8aa323b8748ad0d57d7f222437832b4c6dcbc9318" . + "d97f1fc935b00e5b25d8407434a7bfaaeb5035734433a280d8fc567a087b2fd0" . + "024415650097e3621cf5968e8f4cd8d8e08b00ce18188abf5baa31e4eb95a520" . + "6ccc72020f3fd682263d7ecb5d79f45f6bab9c2c534c445694e7c480983799ca" . + "d706d77a8762972d6b54a9e3bf2b84c7a6637ce92a8081497856f40bfb31083e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "ed6829a9f765912a9e51384e78533d38c82e95097a8dfdf6e4558ed28c02c633" . + "076c22b9a24090b189b9b704c359159876243a0b00d02c79c0db45b0b66a7677" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "9fcd8e1b0387cde2d1783a98ebd850903bf3960647a51cf5229c3fa186284b3e" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "05c89ba7a425a64f1d5ece7fd08434a761f1318bc6be1f9e36e991fa49ada5b9" . + "4ea3a73420cbd0fd150ac4d450ff63d2c1e46e3d37a2fa62b60b3965e4c17bc4" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7e3e517334333b5c66a1b3309b0d488b5d392476c116f3f37ef975befbeb3323" . + "7e3e517334333b5c66a1b3309b0d488b5d392476c116f3f37ef975befbeb3323" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + "be221a5023a9cab6e81acb71345142d9d7658980c87746ba01ba0a7f979a1741" . + "1d4e3108119b52397e6d626bf7bb9b7d4c61e728369e96b1081334bbda3d2fc9" . + "5eebf71dcacae81c70318f6224fa28ad4398b9a801af17a67a44583d2f90f91c" . + "9bd625b1ab016df8826b4515fc4bdb1deac33cbcc3bcc926111b3e34b575b829" . + "8b43a923610ce3967910f97411f74b9c19f6ae779b58a8a6762b1e47134e2072" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "f66a7234a4f2f74a9ca0b0d5dec64178bf63a7b9e420434822b6ada1188450b2" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "dfa2f2097976278c9365abee620b2416f0f05f32fa21a12ac7eeba5a9725ea66" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "3b656e8fcccc94a7182dc9e78743c041062f9206edee0985e257ff00b6ed2b5c" . + "c3ef173626a1df133e80f2262be70c178048008e7e4e724783e411f885ae136f" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "9c4fa637b9243e6b29b2a635014df0fbdc2e5cce4abe00c971d6787211ae6874" . + . + "ba0b887f122abe515b83cc59538e0250550050c652b4decd170ad6b0c91b9c74" . + "0b7a1516bee19c6cba1a83bde260c1f98bac32ab4657f1ea632d8e1bc8f32364" . + "61bf64ccba3329eca4752808ccb9a3146e42c74d483f646354b9e10ad001987b" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "32498acea030770004e2e7348a0f77b07edafc0d9e2b5d2a8ffd25a1b7e4836f" . + "32498acea030770004e2e7348a0f77b07edafc0d9e2b5d2a8ffd25a1b7e4836f" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "d708c525cdc62fd7fd2e5129bba943ff94bedf50b51110579e2c7276e8b492a0" . + "ca90f6ccf4ad6a81b1eb4a338a9f96f27e5cc9594036ec7a18cd93087ba2970f" . + "5270414cdc905ffe2fc15dc04130419f8d901f139740754acdf130334ac06531" . + "e8506c3ef47f75bdd1c67fa966a7290aeeebea6358e68cbe863d060d2b45a8ad" . + "e92bb42df06e4275221371945144b454d1a99d1a30863b2aba67cf469f1bf8ee" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d01e02df63c154e7ce71bc3f3a54a11a76cc3ba205e92e7306426ef7cac0df87" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "fd801d39d4c84641b5376044343315cd3eac7be852f4e24d3b75862905c376f7" . + "dd140c04f728bac5c55f78d47b3f5397f77bc39c7d43dc85e17750ac8bc55123" . + "75f81925a9193cf74ae991ea13d0a06b9bfd1e9a55ba536a88d4d469885dcb49" . + "01ab6808881ec3d5eeba596472f088c102b68ecb651b9eec3171f811f26707de" . + . + . + "be00262606482387890fe26f84a371ab0dffe5c9fb5010977fb3bda839634c88" . + "ad34ff2734d3f5c8eb798f6e709b6f6a6980d61253940b3407474f3f621bfd7c" . + "3964f9c1b4e0f5547494a42e6481c565bcdab9b7a5313815ef273e95b3c7a2ab" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d1a7745c1a451e26b260ec942008953b2565f1444f9938e6e4f487fdf73e93f3" . + "150ef3a628ac2f74aada0d14953cea01076aead969919691fa4751d581d9a362" . + "e94764191cc9d0e00a438aa52565eecbca9877092584e2e2b5510df1189d4a07" . + "54e5ff5980e548b9a7e059623aa596e28888b9fd589b35a64ee05974fdfec947" . + "e86fa140ad58f937aa0db8657498a80dbb2b8b1cb1fcffeb49cd3df637883614" . + "56ce49e4ae3fe37640f5323a611f7e2e175c1b7817b14b8eda0c1dac2833a64f" . + "956cb5b41132c1db3a29ae421803fde57811e57a7957220baf699c0e40c4a233" . + "fc3082e45f301eabd31798edcd5dcfd404f8204de46c6f8b22c4a6b4d7ecf2c3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "3583744951e0441d41217382fc255ecf9a3695648ac00338dc05ebf68a4ac4b1" . + "1359b653ecaaada21f498ccb15cd412876e49736ec89a7b3839c9d86092226b7" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "842b34e5e86c99116239c96b1839ca76fedd25ca8048ff2e34e8d2fd8633f6c5" . + "163e8f7765d5d0cf69568ad50446e3300e19de9aca8f28fe7098f5c8450d9466" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "a7bfe5559f092e309af2b2d283bfb73b5d81e9c8eba2db1c2735d72b7871a4f2" . + "0d04ac025adc6b7a30aab757d10d5b896084f86765def101b9cf5c026051d85a" . + "b7a43449d7e3c69976eefef12f7f4275bbc82e72df22fbbd6f67a9a3416345e8" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e59d37e6d9d5e3ca91f836fab51cf49643af481421339decef04223754f3b30e" . + "b1bc0ce9e684b93dc3190871be9b08be5196ae5b1a293779e6f57477b42a1efd" . + "ea088b9765a0bae104902994b80efabb58e5c73a1bac39270ac2f6fdd8ff4f1f" . + "337b58d5239d2aa0f6610f22bf67a50ff3a897f7688067b631bd92e02a04551f" . + "33a838564831dbfa98078398233ef832699329e21c1e239de15b405cb9155a0c" . + "5564b1db36e840ea358bfb58266c3079503a141c68bafb761ee3e1987676fb72" . + "218768851c2cfeb623b532aa6e976095d6de75858a5891085d20e58db05d9974" . + "e641fb9beb0f2d3eda1be14e4804465909ee0d3bd67e5e94367335a9bab6de79" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "b93702a9a564dad3d7aac841bf73cac61b87053fe7b82973d7371f8baae71b35" . + "637fbfcc1941df4849597985bb23b8a8e08a57cbf9c9038d739de94f7da64dbe" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "c37c318270ef932927daf50e0097e97f796cb872c5a5491112ca411211475818" . + "77b703b24a925821df4d8af985f2aaa026944df2648b86262ddb700300ea17e6" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "f6fc96bebbb50364de93187753a85da100c771de2783ea450bd696f3fa6f547b" . + "4ca7369ffbf4d9dd215cf453bf2fc4c6cdc7d811672f6b251b99fea03b1cab63" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "defb191e8811c77ac13bc0199b95437c96d70aa69d4c717ba2c8200f23a4f0ea" . + "6d6bfa8de8ee20f40bf4918cd80ddf4f763ce5bcc71a9959b0d799f994332281" . + "7d090b1d7ca951538dcbe500404e1ea9f0acd11475cf709f85198aed1169d39d" . + "dcae4425d8e37ca62e5045098828b56a28191a8c36f0a702dde080299fd073cb" . + "935dbde76e25c93cf37cc459bfeba248b00bb478be8477bb39d7bd79c83fca5d" . + "a824e4c3166aa15883147195dd63b34c8bf8bebf59f5d571facaacbf458fc079" . + "50dfe8d7a39a4319efd9231cf5479d5e9867548154ff23bfc54b4e5852f710b5" . + "d2c7e5f97afb17976ffdc359601a3f6abe19c41b3a853f58f92a7cb7bdebe524" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "7f96af764897d7e83b5545d9632b5fa7ef0663106fa5f0fffbcb432f8d0e8604" . + "19fe9a644788b32fd6cab272f232a6b28e5ff7aa46225bb014c915042e7a0f69" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "2dc4011c96ac338b3b064dec577c5585b348bd1727f5282a378d8350e8c7c33f" . + "5625c0fc47a9197cdb22cb9407cdf472ce923187f8ad623083528e69356a850c" . + "a7fcc8f86e85140aa0b39685346c58b87c22b4f6b1485a80e9378ba9237704b8" . + "00880386ae7718a31e23e4b7a22672cf1346414416b2819892157d65a75ee3e9" . + . + "6f8959cef9ce6ee7594ab80feaf5799397f4a8dc1de8a85c3c99a9423ebc3230" . + "42e9a0639848a9b254b09832f2f7c2738b4d07b81254e76072278c1372650cce" . + "395146c2443739e02447e9a675ed445b2a9e5dba9a3cb65f30b82b3631f53f64" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c0c669983b8b1efd62a545d1b799cae72c466b7ae7cb90645fa77c038d8bfe34" . + "fd1b5c186585031d5cf8b680cd74a3745ef5bd10b23e6ee4a1275598d3a6f1b0" . + "9c9b9f6c7c5d29e9a21c9a932434058cd19fa618e4e5c83bd125cfa97998cb03" . + "a7d510156a4f3245219b8096451439f3028280ade256707ec942040263dc4f17" . + "c337350ae69ff470d786a10cfd29fb7ed4375d3b7f83bf268f026e9844fef070" . + "6953326559682246e49fabf403ed6e6eb2c8622e7b9c446162129204cb13f4c4" . + "2b8c88e41d378a32b8b6de4c56726bb645ec3058c2dfc0a728dcec7e26cb8dd9" . + "75fcd8993622980ad3b235dc9db1866882ca026795f47276a4a811b05046ac88" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "e2b77c4111baf43ac39bbcc66070f2f7e81e101f9c8e99d42673b1d71cc3090c" . + "bb40fa492bc400fb525e5379df51c72e2cd2f675fcdf98eebf5db44f79bf74c7" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "3a46ef890fd5c550d2544ad70670378bc8b5d84bf9e8c8262cee723900257bfe" . + "f150897d415758e7cf6d79c0f497fa3c69f1220fef79fdddccc04bd61ca69594" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "3a46ef890fd5c550d2544ad70670378bc8b5d84bf9e8c8262cee723900257bfe" . + "ba897b17d3e9d417a8363acc6ef6b25f9d0f11c4f6b3316916c2baf235bd69e5" . + "33676e33a4a9ccdae573a3918aad0f91cc43b6f8da9f856c8ceb9698b9fcaf65" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4894482690e5bcb38617a7d4f514bf66acd74e0460775e7a2ff57bc9589b8f6b" . + "4894482690e5bcb38617a7d4f514bf66acd74e0460775e7a2ff57bc9589b8f6b" . + "82f4287c2478ccc072fc759950ce7c3ffde510bf5959aad00a2146166a935d9f" . + "367a005bbf64a0c1562d4605f27719298588a21433d789ca30ebb41d1795bc46" . + "948123ddc4aadad625044f118865544b356d49a7e5e93f8fd83c725435d09f48" . + "2dd1d14dfaf182f257e86f7cb2dc6d9af9dc4b34887b7973e4dbce1bc56eef77" . + "6c69406eb260ed13388cb6c9d60cbcc7f35e0e74df9bd9024075b24e75a78f47" . + "2599b239596b9ec0af7ba78bb703f657937ed2ac50854813c7529abe125b69db" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "3cb649ff0affddd28f8712afac09b7f02ff8186baffcc598c259ab066d164462" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "128990a9c1de106108eb5b46552b1ee5f89f602078b12a901abb03d579f41173" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "e0304932d0e93a81034fc7bd29e5a005178e186b7191d5ceb5d4df24c337de9f" . + "7401ea00102a95c0685dc9c5735f8b22cb2e04b20ac76837aa6dee77721d6e30" . + "6b9b78e4e5c87912fdd70cb9a41b9108f3e461318c5ecf8976fdfdf928893cc2" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + "8b1131066b6863a534d0fddff2688ab645398f07b3058311f0f54739678af1bd" . + "a6331482bc35fd4e7ef4ad091b1132b2e5cef227b0b9e2c3cb8ec3cd29c20d43" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "91f57bbb007c926de92a50964c838cc251c8b09377fd91640935af8384a42839" . + "91f57bbb007c926de92a50964c838cc251c8b09377fd91640935af8384a42839" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + "b333567ed517b1b35f1a5380052ee8c0879f200fb811efbce0ece1083dccb5d6" . + "bc907747189468bfc6fba592a9a9c364cb6caa23f1cbce2ac832c04a807709de" . + "16ab8751169f03e24f8a7c8ce04824e366a697ad05008e759614e907b48e3dc4" . + "284c6822f0e279171593521e1afdbf38bdfe7cc8592afae05d61c0e7ec3ff9d4" . + "0d7365c6c04e385cc4577ec57761c6efbd90fe15c80fdc385817155164910b10" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "cac7d14c417364a6004fadb2ec30e1cdfbeb052f18712830fe2048b754208060" . + "4182f5065a3a6834c48d909c9aaaf80ecb23364f232b20c7b9d883f0102be8b1" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "2fc43ce65a3081e77126cc27494543f4d4dce71ee7da97d86d23203f7a79e43f" . + "199931eb224ca6fe99b7a74f04f68c13f675d5b15353ffb3753790f300b31954" . + "6a146f2cc14baca6b8600b7c20fed689342c7e2e4f3cb82e0bbb3d59d87e3d82" . + "e2db02bbab2fb07af33462db21b34eeb874ac050287231ce151ef82040154412" . + "568b503bddad9b2f3b85f433cd9db1d5083e69384c0e87e888426f257782f72b" . + "67c8f6d083aae97887798190d67556b2d8ec4f718cc12f32670edd18846d73ec" . + "8514101ff6d04c27888ddb2c90e72033c3256e0332303783ffc386331138fecc" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dea9154aa2a973d20527cef9db53b1f75dc74f3dfafd50b1dc344b1b36e985a4" . + "6d310cce9cb1a4c4f0d9eb7d3b8883c44592d71ec20595e9d4ecf3571ee53798" . + "914f658ded2243a6c830da92f0e387c660f9981cb59eed00e7a3c7e0f3fefc15" . + "50e60b8259f8a18aea3a3e69adffbb3221d8f8530f481729034d1c429ec650a4" . + "20a04311d8ab4311a0147858fd9d59c960d63620e18a44b2728bc74a40afe6d3" . + "882d1bf3a834aa03b522a0b3e35d59680dc4421322541ba8112d8bc4b6e07109" . + "7652f385679875a6a6d587df790bd2c371b8c80a27d44c8601f825ef63d27f6a" . + "5cec45ac979fdcbf5854f4193f579096fed69bb6cc8f29a7fa29029451a41b0c" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "85432d6299d9995130dca41c152f13d742c474349999cf5df3b21c1f66080b72" . + "8d26434cc99ac91ab0520e73f02f4af8f527039e5584914a255ebe925c9e5b6e" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "109d998943bc81cca8bce9d3934dc431874f1e6aba28c947ec00801d645fb404" . + "39b2f251a9a8132af7b0130639fc36d8f1230564d75571c5645c939f54632da7" . + "b953c7ba4621566d05e7559aea5b01e37bf4fba7051c04f4ed9c99fea832f831" . + "a7644808cd884d37e1a716cdfb5b43172829bedf081b3e873f3e041129dfa83a" . + "7b8e569ad8b81198fefdd901c9292a3b109244e75220a2c19bcd79ffa26c29e0" . + "9cb6d708752b5ab0120ee643f08bf71ffabd26e581b86353e5fd901fd830c237" . + "680547e26cf55727a1c08780a6c608526876aed05f2eeb9397a597c54614aaf7" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a7ffd6e337b479413ba24295282d0a1b18de9ba2a2d261805664ea0e7555d8b0" . + "0f8f32f3f40e8a8ea420ffdc10fefd03d2090470cfe37325f8035cd5f7620d95" . + "5a2c4d3d21a459784f7d8dab5433523ef0efd168d84ea171ba767569e751c92c" . + "41144ea1338084351dda3725462cca352b1a4b3eba4ef55cc2b8c40f52ea3707" . + "5184ae9584977bd8b5dfbc083d3ca0459ee7e91c1fefbbf72eda328b8a7c34e2" . + "7ff9e85494920350a43069e2f7d919e43cb8694aa60405bca1d762124350ee34" . + "9a128764c266ac6c43e31d39fa7b2e0156860969db713d878573fe2d7291b5bb" . + "ffa2dfc376fa93ce30c78e6640f65411a4bea16eaff1c66a62afd065d2facc91" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "9a5d218f3261fbaff6214ec710efb02eeac2c58319c2eb30257dd330538532c8" . + "77dc471a47edb90c78763f5be65d91708d24373cd027b1ae36eaa1c6be7f1612" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "71c0e1557c1374ba59070d3b590b10452014dc479d248337195ec6da0a96f633" . + "d1416e7cb81cdb32d3c7ebd9c726e19bb10c4b4374ca967d75f309e873291d22" . + "49c26ed06c543b71573914fadc4a80dbbc3bda1913b7b64b97a7c2f902080dac" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + . + "846d552179fdf68f1b4a52bdee3ac0d6a93e72fa9899f6e9356db8c2d6ef478a" . + "f9ebd09bb91c98e1bfea570976c79694030b047f0a5fdd01cde937ad21605284" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53316c94c2dfec5d4ab7ef1c3552993dda98e5bdb9647ef88fb253061a1ced2c" . + "d5fd8e52cb2ca1cb47235ee94c494af8a18ee77cde9b23d3b199c9a1c9ed0831" . + "eca4b5576693681476d2742e8cc3c2a3ddc574f807bd01e197e5bdd6c86bff09" . + "96c6624bb831d05d2f9c05bcf9e129d9b36cbbae20fd96bbaf34ed4b5e5b1ad6" . + "2d58ed9e458583b0b1c46370c33ea9c833fc371db8e464fe9c21a49dd521b0c4" . + "ccfcc87746df68eefca30ae2d1a2f9cc9fb800c8ccabe49ef46817771107554e" . + "0c3a1daf396feeb7ac0fc9133c8e8c227884d3ee1be25048f16ad8d56998b41c" . + "a5722e9c7432d9154ebe8f96c0b904c243c785b70517d21defcc5b85363ffc8a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "90f195407df67511e6752629529aae62559965059e972cc8dc5f26a260dd1369" . + "192a14999835ff9a9918a21f9694269fd4bf16097a12f2a99085772afd9b4049" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "2695829989e82e557abe9e0ddfe2641a0ca4fd8304435f54cdf65f18e0dc1631" . + "95075f969e8a28a1e011ec03d0f9b85a273d422f482d1658cc4fa305f7f05e47" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "faa441b0793344ba2b8272477283344fee48ac6d00dbc6876b487a956f4f200c" . + "5042001ca613b9b12ed319966e4eafb6223059ed43b6940bd02e5a7b07a7e7fb" . + "343185e4ffe2e4ad39f3d76e61a31c301f745a17b4f6b7dbf51db6fddd5cee01" . + "9e89586a202b11abf4852eafa257f84efe658bf3c4b30ff94439e6f3856e3f1b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2a5aa4770d92e133a3c2ba9de06404adcd79da8089f6b25387d4409c4372ea2d" . + "872d01af385e1a5dfa47cd721adfd75a3cca4c56469533c7994e2f8bbae51a27" . + "7515cc0946a6789f71762fc9bb30f59d44fddd19ee3f582162cd850b2e3f422c" . + "50c01b3c8c033a5048b1a837e040bf3754a117f3eef8ba853299f012348411b9" . + "5ac8231a78ac870f4452df435bd2f6f1559ac04cd17feb717ef8185aeb2bd7ae" . + "c67bd53cac498aa46602ea4885062f1449f6810c6d211fbfdbfbe48bce2b64b9" . + "a2950a6798e1b92ecdd15e679d9d8f33fb1ccc4db44f911666502e3bd6fbd3c3" . + "afeb41aee23b7a3f74a78cf7f87f147db1c9eb5ef3d6c84454690f94a434a98b" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "472656345618dcd71d2c5bbf4f72a3415b61e8bc879e0992461bfefa4632f52f" . + "76cc6e30b2580bc3be18182762cbfe0d9bd495f35cabc1fd73962adf15928608" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "619959ca793fa46342a648189be1b8b03bd51ed95923218b291bcb54848fe821" . + "08ec74db39eef60c30b0918810e35c5c75b159241eb7c1ba51edff6bc88973df" . + "9e16690d06dc729b371bc0a1cd8212c013f2fc8aab73369349f96207987daf48" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "39cafdde3df21c062d8c3e5c47934cc4f8df305541fff35c6515213d38968090" . + "5d44c99ad3fb03bf0dff56362c3866c499347695f5d4affe17f8649e3268a747" . + "2ad336399c482ab9a7cc5b80eb80b48e2851b5d7ae7472d2a7cf3ac185f8ec81" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4e50a8ed9b3613d76de6e0eaf8a2fbb1190d453db4440d019dcea3f01d06ed14" . + "4e50a8ed9b3613d76de6e0eaf8a2fbb1190d453db4440d019dcea3f01d06ed14" . + "bfa9d0dae50eb4f97cbc9996254fe7d1d91810dc1470dbedde798a3f982aac2c" . + "50081e6fd71ea831958a6ea7b518f0c66dae38ec22f82568488159444236f1eb" . + "454478f0154d2ff39e39d2390c739a6eb4bfdbd664a51f6306c47d38f678bd39" . + "298eb15cfbf5f6c121c44b76a73ab1e6538bae7815dfca2bbfb50fae0f673f64" . + "066a6de427e42a98d785da1261acdb2965d22aba413fa97d8f0a67b4b1e9ac6d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "b5dd8a9dbd3397f357a6690da71e9bc6f3f07cadce17e8f73a93e987965970ed" . + "9299aff6446e238ef9534b5ca13235447efe6211a2e318398cdf7accf53b44f5" . + "027765b8eb7ea94fd71dce0984204350c4e96bb9a58f6a5ebde1b3dfeaa44a79" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "0305a40af0c08a7db13053db1b232baf817d617182462c72a852de6f2f58b750" . + "61bf64ccba3329eca4752808ccb9a3146e42c74d483f646354b9e10ad001987b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b37c15cc08aa01c54b7cde3dde16098be79b53d74a105fe01ca6fec8bd1fb230" . + "b37c15cc08aa01c54b7cde3dde16098be79b53d74a105fe01ca6fec8bd1fb230" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "c57216dce5bf5e04edc13272d875d4f243e997e8a40bef336461d7ac36023231" . + "f96e04d842bac0f3cdeb71ce81a4258af0dd950f46a0566a92c1a1dfb485ef4b" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "b2bc29800fd6aee4f84545a5ded09cd1b5cea080b5b646c850d86a0a4107fcfb" . + "5108ed1b78a534ec36438a215fc09fdca42a1ba823fddc8fac181771ed9af4b7" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "f66a7234a4f2f74a9ca0b0d5dec64178bf63a7b9e420434822b6ada1188450b2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "474d4fe643dd74ce8d1fcc5648687faf27d87d169130012652b4ae2279aaa095" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8cfd914ab11b9b73ce3f7575f29382eb72ec41a01a57b84525f690494f502468" . + "c23b4f8e390ac1af1db8f1feb382dee73f963dbafa025f1830da24811b082bea" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "e3c43683d8ffb5e2817327ffae2549bea0aea0f2474f2c2865d35f50a2e2504c" . + "620b439bda283be2774201542a4415800e1a7ae3de47bc04aa31772bc17b6de8" . + "bdc5b87bcf8d7ea81a0a37c391dba5019f4a69c0d4933cf2d591ddbcb487db5a" . + "72982b6860179dccfb92d781d471c8cd0e2a96c3c5920ab855fcfb9b4517c42f" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dec439ec71864e2a6cbf5d194ca126c364e650caa8d8beb27213a1daec21f096" . + "dec439ec71864e2a6cbf5d194ca126c364e650caa8d8beb27213a1daec21f096" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "ef6aff4d4522a0c876664043d2f0242e4da574f1f720652fdfed9241798264c2" . + "32f6c745c006e6add645e147e724760e5e7d08d7b99ecf8000f9e9b00032c60d" . + "dc73b4bdde5b2df27bf18f68b6752fbaa9fe4988981efe68d24613a0144c78c3" . + "5d6f4dd53d63f8884fb09a0f98013e2aed9667b03ddd5bc9bdba7bbec128b3c0" . + "f19b53a02f2f5fb362a12e4d51dfa9ef48eb5c5356e2771aab24bc112ad41b00" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "129873ee7ff3d1db5108271f71504179512a607fb55298b807ccffde4c8072c8" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "57d6f9387780ff4a4bb80f06520885ac7b22185ac49bf0d87eb1c15072b5dfa2" . + "969a289969c3b626791114237708ece9bf2724015d1bdcc1e6abae39555d5522" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "3e16209c772050179ae65e499891066eb10a90a2b26ba8a4b55b825afe028d37" . + "8bb6be0a222b49082d048bce7850f4124aff34c285563292fba0d749be8724dd" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "030c24384fa62b1a86a750eaaefeacb3529e826a5e63f38d9087fe1af9da7364" . + "030c24384fa62b1a86a750eaaefeacb3529e826a5e63f38d9087fe1af9da7364" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "7af6d9ca128a17a20346e05603638453e3cca2df2b8171e856665cc940b0c60f" . + "04f8834850aa15e506eb91a35729166ace546eab227d4099a96c4d61ed9bc3c2" . + "99da390ef4a3b5f6b4de8d7e56710b7a2ddcaa85f6d53e300bf5702540ee7038" . + "a5119fbf4af592458c71edaf8cac18a588fe9feefde408b0887d2547d5b1ce56" . + "969d717a911b996664675ecbdca527b75eef3a15fecce964f50c7ac2911af734" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b6527d50c9563d09daa91f43db11f84a2e2829c45e88dff231b8159935c4d0c4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8e8cb6f716bf5f601ea7df7d0b7a704f52955ca993871076379b250e7b06efe0" . + "d7c6ba2045d944a35c11544c07afb3a667f879b71737051c8458a60dd951fe62" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "aba1a53edc45a9a4ed9a7301f581474f7d030c61c6e1666c618042d79150fff0" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f9b4288f03db68480e0d4127d7d5658666cb14e6aae77b0d3bfdafafe7b241e6" . + "99223a632ed8b8346074cf9c734e2196fe9dbfca597e69959fea7565d542b6d3" . + . + "263526b87b77b1b6d41a4a8beb62ac7c16ac81b67e5125bec4d9af22a69f7e1f" . + "4bb715388f5368b6df9eba668c1673ddd51dc53974186374644a410749af4655" . + "c21bf0e0ce8d945dcd785424ad87b322d9b9aef8c0181bc95983b008efe27766" . + "77b9c4da073ea5a969ec15addfb7fe131553c5823e44de973cd9da331a0be31d" . + "962a1277b7cd7adefbeaf0d43b83f85cb7cc175dde7ca0eb92bd07f6f0297634" . + "24a2e5a39d816660934126fba09c5bcc2d0b17c28490302aeef4218a4d626116" . + "f2f1995cccd823a31e86df238da06fe25a21f6ed048c39605501d430edad85a2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5bac1946abcf6c5fb65bfb057f1dcf2f67a496c7f1c1f6be993e87a6fd35370f" . + "30abd0668413c546f21f0b478408602bef4f1f8644585f957af8df3ca17a5838" . + "af782eb665fed82de7adb9f96653eef5c556d51c49476cbe810f4367137607a5" . + "6f9464919f79d723b31220a4e41a9f2bff09022fc9c93308db44c9401bf4bc5d" . + "5053e8b0cb6458a7e9d4fd7b1eb5767a43cdc9861e91238316a23596fb95393c" . + "66679b39f8672076e56ff235929b91d8a6d5f14fd2b8350dd7b64f386401d1db" . + "d27860a4731b39e39368b4f22f8db7ada9f3f6357778b7738f23c8611b553942" . + "b9e25c972ee756536b9ce9f07c99bddfd97669100d8b7d2c6abf91bc9b68c6e7" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "1a4a8842d5103046caf02f8661fe57a759d8fcf9fc564b547f0a5f0186be5e39" . + "262ff465966e3e36f49402c0131536ddbe97e1057526eef63d178bcf694bfbee" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "da971e522095332bf632e279d72b02e8aea9bda3b00c8a3c24d5c9798e9587b6" . + "bf8e3b4bf0af1e10883386ca8169cc1a71358749dce8ceebdd863b7ccffc8b30" . + "840680d6a49263690ebe09642372c48a10b046a99856b1253ccb3d5f7e145dc8" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + . + "7c538cf8c4accf27797a7c0ab28af1e776c7a3651081904bd7a2c3bf608e8d20" . + "7fa1972b11d31d1b4970d24137f95e9db8646d3438924306a3e5026aedfdb066" . + "930ad076dd2e0d3a2d44dc1ce85cf3cfb21a65a68e4137df975897ae594efa54" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "50e528414efd5050e018e9ab2d5aa887e488a8ec33b83ad8442a5bd306c51113" . + "92b36fcd31d7d88e3e89e946b9d5f823afbd124b24c116784aa22e80ce39c1ac" . + "18edf29a277c1fd577055b7b226b38c839c6b06ddff6e843088f85f81c691f21" . + "233d557fc1635e4ee216d606ae3481adca871c60077143d47cb2f531eea6b8f2" . + "a348dcc33dc60f36ad8836ab97b56b6434f8bf32ede32972c67f6bb57b25af82" . + "d7f425c00bdfb9e1171a6fbc7312bb4a60fd230b5808f6bff417c4944723663b" . + "a735db01bd0c327146f044998dcad5d2ae3435b0f615cad209fa4a5ceb195ac0" . + "0417a85f877ef71b2846257e3f6ba0055b41a949926f0a6eb82377b8a1bfc792" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4659aa164619da32648a0b1268de6082e9d5ba7a1582449ec8c955b08757b595" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "1b4f0a3727ea357cdb8d88138ad3929b7aaf57f51e8331bc34d974209c418c98" . + "4a73c30f45a74d2882838f45ff3e664f1153bfd201214376ba9dbeeb0adaf971" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "8c9dad716197b73e65fee814d51ac06c0d6f7557d9a44211f4173fe18673986f" . + "145398921b060994a31d4b5ccaf6f574cb8158fd923b544a2c93ecef172dbda8" . + "f83a28e6c07b05ff54c5d87150a186632e17376032f27d813076efb2474684fa" . + "51c9e20956d60c78f52d860201fa7610c44a77ec5f8de8853a04a3659559250d" . + . + "22a2e8fb69d917681d451f7adf0cce0e604346825890846073c02948de58cb80" . + "4afccf06f466c68e5ef81d0ca5eed397abf03df9ee5bf0a1c9d739c13e872c39" . + "dd6d0e3a59b09fb791139723305deeb9c0a0ca348ac989c91f69d12ac9b7c1cb" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7f31a13791f8de7a62bd5117faa58aba2c826c541f6b264cf8623b704ec7481" . + "5e01faf8290288b8cd4bbc94b0649b7f0cf8c3d507fd4e544c08226c2a799a56" . + "2a499328477aa11aae0133085a7265be07967637b5b6d8277b508a4cd95704c1" . + "62a404cb6ac15284a1708f9c7ec63123c75cc93214772fc0c11948ae7303646b" . + "9626352e1d30e18959ad6d3824b7ef0747512d94005139134b7f187182c23b44" . + "39a95585a028ed35bda46786eb143019762937f41abf9bec4d9d67def426014e" . + "cee6c6f3552a592de7cee2154b0e38cc1dc087e7e9d631ec9f48a2460831bf96" . + "9228f87b805d9d31ebe1da9a98ae2eb5dfe52b61835b7b54f55f9bce43907484" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "47f5a2930c860dcf43965bd76864b6d728d7cecd1d782a20ccb2de4c143774ac" . + "617e841476fa459bf278419e6f0e2e535d233d30f6ed0d97328dc9f1781f6328" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "a8f0c01a090e189e4eb58a49f0767efe412d6ef063c71952f91a1a3793d4e377" . + "036a74a5185be5e13d4f767e93735b29a885e04ccfb1e7e931cede414acbc4b5" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "ee354bc06499dea85bd80b0b0061507fdef54d561ec380089c21294edcfaeea2" . + "c7c75ae3313c6caeaffeaf748d4812107daa483d2bd72bce7ffe0f284a91ee6d" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "486dcb1ebade1349a71c73a4f584442909c690d26251f72d0c4089316768d8e5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5bdc60f4c08d1785acf1d31fc568a80e535a13ffda39b253c76885fd8f6f4cae" . + "5bdc60f4c08d1785acf1d31fc568a80e535a13ffda39b253c76885fd8f6f4cae" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "fbfaa97850c976e9a5dbdcde4d2cf6e10b3727884adc4c8c4d37e4ddd5f26d33" . + "20ef774c2c322c3312b1b95d3e3fee9af0fe37ebc0a6e55eaa911e826fa0e603" . + "2b4d953599560200152d2781811ce5398e9e47562da45abb297cbf7aa7b22868" . + "83ac0ee613a9750f47ede123480e8046b3ee2f938f308c6a5a5e6347726cbf72" . + "8bb819987cd6bb7a86ade108ae84673bb5f01a22d1c45b9f831cd39ab04f42b6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4659aa164619da32648a0b1268de6082e9d5ba7a1582449ec8c955b08757b595" . + "e7c80892af9c077174ac2117a19573408264ded4f355471b63a740834c281494" . + "e2b77c4111baf43ac39bbcc66070f2f7e81e101f9c8e99d42673b1d71cc3090c" . + "7faa52790cca09dd044e77c0c25516db4a5afae1497a8cd3bf8cd7adfd4b186b" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "391e662c9ac2d26e26b4bb4607d0748b787d45d5170082ebdfffed5fa20eb65e" . + "02bbbf1ec9aed6927bc16c1746c6549804777528965aa382b9a21a725b6478a5" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "2432c889bd86c141553758ac492c27d97ce9b73852b677b6a66ac8a772ab1b70" . + "964e88827ec759d88d215cc108171d09dea18d25e6d3ab6c54ccced045bc9319" . + "82d46754599c80424ec8ff5d412f8a619de2d64350fbddd612123b4a02c54c9c" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "895b385afa587c51ce726fea9bc6ae628570dfce342d3af48afac41347919929" . + "895b385afa587c51ce726fea9bc6ae628570dfce342d3af48afac41347919929" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "c1b6c25e8a00db80183618fc88b087d254ce5a3cf70cf041011aef64885208f3" . + "aaf4273c67e932aa1907d2691284aced93ad55a1e598cc6f240ec9cf465a565d" . + "07bdaed037f6671c913c8f6169a1d4dd4b44c63105238d9bb9945e31fc53483d" . + "6c1e70ffb23d4defa2300e8e69279d33a3c09d0cc82d3c5def1c7f5bf5af5502" . + "81021088075e1d7fc887339eb52a06f8f85ac84593d66494ec7fc00a5ac63941" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "d5c31364c44646daafc2c9b870e48dcc48c22ad87ebc1a9ea38f932b19f6cb45" . + "7bb06ada799412e99c1ea65224cd37cb80ef9535ceba9c25c92c39befddc593e" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "fe8f5571c40edd6acba429af06b31bdec408f1f195d85a7dbe4ae4f386c2fa99" . + "577397488307dd5df0110bbab95fd79f54cab24ed17ead3fe1f1cfb73e9b8d9f" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "05468049d3a715efcac214ddabd805a8a4da8d67b35326f9d27464bc7b4dbb31" . + "e7f0d2c2f7eb94c9eef80d1d880ad997f9af7b1ac3b4814e71169d26479a46d4" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc52ef2e72eb2f32e3640bf7e5d8e7b8a2f924e1b27ae192554fe8f1d44267d6" . + "cc52ef2e72eb2f32e3640bf7e5d8e7b8a2f924e1b27ae192554fe8f1d44267d6" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "1661bd160df7780e807b21b4b44e6554c4a29ded904b67232fac6db44bd106c6" . + "4cba4e3760a3d4adf102fa96325803722097124b71899448d7c6745373073826" . + "63847233a3f71c4cbcb73df66d5dddceffe751bad56ccd4418132a7fc297290d" . + "9ed7c4f971ceaf78b1e9c5e83464e37612dab1a45b42a2c7787760f4904318ab" . + "a0cd71b74696ee3d601f1898c4c61d34e6da7637c75488a1c0063461e59a0617" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "32151b449ec60c1e909d093893f7d2fd6402e33158b3cd562d78581ad9373e0c" . + "280476a16b1c3899444ce4eac8637eb91e514ddd2ca52bf53b5f4c2f79d3d90a" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "bb82883f92046db294684778f37e97e0080fa48ce097be015f3530644d4081a8" . + "e4922aaca4cedbcd5c28f5a9fd42ed935c62529bb2c95f2512d1ad7e7db5a4f4" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + "b42cbc4e8b7ace409dcf948c2aed12db73bef7db8e691495624ea31cb975609a" . + "3f86b13927781bfdcb40352235bb5a69727cfd868cb5d7b8572784980213f908" . + "c5986b352d8ae7a3f569202bf62e544910244ce406a7010b2465c6a1b916055d" . + "7bf0d6aef51489464b4b84dd1a4bb91677e73ef59f6057d77adb2a64076f8826" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5033a06eb3d6ac65bb36931f7770c01e4eb988f1d2d76ec1636ee571719a2382" . + "e15d67517bee368cfc1f7bf20096b9f48e9f335507681459aaa763e327ce7c6f" . + "f7e8f1cdd2a79988be03602f8a8e08c96a7405ab6ea712ae4c4854809531ed3f" . + "f4c22cfdc7b1ed6ec018846d2d277b9394e89de1ee5e12a9d95ca94125166402" . + "6bf9aaf55a114cdb8aa222688f454049a9a42c465336c2aa1c727f3bd59b33f6" . + "c736fb914e8030e19d63089664f16b3ac1c2336dd8e7024244e1abbbc5c04cf8" . + "4b121913f7d2756b31584dd4c458ced6effadb91321d4bee12a0ac365af57229" . + "cc59d2552f87347296909bd44b7f802de4df7354e41a57ddea084453026fed57" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "348a7f1791374dd948da0b9f1d9bf14b8a8d59bb289a709b5cce0ffa6e02951f" . + "df14b134d6f1569c1a871545e941132e0845386fa4cac3680c51e5244c20e44a" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "2eabf73eae60640e10114bc454f18aeaf84508960a45156c1d88ebf5a516ff4a" . + "6c6448f80a1178f7ce56f878fade6df5f02b76431dbb78070ad94f6c85764538" . + "89cfcde24f7bf11b37070a03edd8a4b79282ee645551f6c2767bfd342f9bc37f" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "48fb390424fcf6f710cc2264f826ff571faa80d929210b2382e69eceba0b2955" . + "856f259d8304c0852d3a76f1914594bb2d1e68f7aa98bede468cccc340b849de" . + "779fa350db16a25b473ffbfdaaaedafdf45810c5e9d1410fe1a69ec8edad979e" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4c2220f8e53ffb961bca175b18ca52918d763574f5bc7982a63fb4d1c0d1eb33" . + "4c2220f8e53ffb961bca175b18ca52918d763574f5bc7982a63fb4d1c0d1eb33" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "c6f635a4c5bb9debe0f510a54feff967039aa08c68b758bc2789c03a299da32e" . + "3b32323f01fc47401201bbeeb541af5aeb92f9b74b4d26fbf9fa5f696bf88002" . + "4ad394f4cadae5c8196452aa5030119f1deaa3ac0434b465d0e30c8a76053c1f" . + "6cd501cc37507ad6c6d8b0ffaacfac81dc84f11087cfd58abdb316be2ab55796" . + "e78ba0cf0fb67f46bbe70571e923f3cd51e8bb02ee84b10cb652fa56ee9ed748" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "2fc0b5893c709ee341704b539cf93b292ff5752cc00f81e92cf2dcbf6afdc109" . + "4f6a5fb040c9a58628134dcfb46a3e303359faae9c97c480a2490c4cbacc3a27" . + "b21d071c31afa87a1e40f5e9fa19719a7f4251805ac1403b5b74d89105fbce8e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "4bfdc93e7f6ed8ab47f25349e3122a974af3f43678d09e4274be61c3bb61e6ec" . + "49927ee84a74c242296bc46b415bc38a94904574f819da8951298e4e8e5e248b" . + "c04ecb39182dc99ae04ec864636738e2a6d9e99f01ab4eda3271fd3cc329a7e8" . + "fd4cc8799e987c7de57c2d885586631a8b3eee50aca1f57f4dbdcad7adf1cd34" . + "c317c3c6533535fa37c78c526449cc11d83c65d4b90130c9ee8d8302058ea428" . + "564c98f2c5864720b0a4406329d9ded6309d6107a3f1831fe000ab83a639f12f" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd8afa604ed91c809428bdfce47c0c882799066d29f32af8985567745585a64f" . + "d23b998182fe421c4938d11b1c2b0ccf483c838f53afed2dc43e215f6666508f" . + "1f72250527fa8372f6b9f2196f5689c5dab61ab335488e521469e95327c0e2de" . + "485ad40ebf635c33858158ae0950cf41423f25ef1b7e4caf31731eaa3322023e" . + "c302d5c2d2dea1f6aec55425da3bc91525dff8f3b44132cfeecf0639afd2c1fe" . + "0227b7c969e84d1a116ec79592dd3ea4e47acc2ac043c81288ba929e5175b1a2" . + "63847233a3f71c4cbcb73df66d5dddceffe751bad56ccd4418132a7fc297290d" . + "0f9d1565859d8782d287a405f78c806a3a58915bb89201725361564c7a2e6a92" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "168acc723c849cc1209b9a168f080ddb877910268c173dbe213fd368a0837992" . + "000d792d88f97713646c9315a62289d7422efd13c27e37377827e5f0b8b47c98" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "b1891798196f5f83ee2c65af36d8d6ecdec03ff3317dd7c1e6e3ac57414c590c" . + "5ca641d0ada8aa368565dca7be973f22e0d6972b545f41039040cff8a77bfb98" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + "79d88833058183da924c88a3ec614cf739d2caa08db09e6e482e62bdfd3efb26" . + "251af49c6f5de7d725b6fa2de979d49786be83e02f719ac93a4f7e397e3a075f" . + "65580228049a9bd0315c93bdeb0c398dd09626b9b5ff08aabbd2e95851728998" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "48b60524cebf6a2e001531d10778bed55439d99a72c618879f5bb60da911ff3e" . + "48b60524cebf6a2e001531d10778bed55439d99a72c618879f5bb60da911ff3e" . + "86f304ab84c71f7222dbaa2b079d0092a11ea4632a9577cdfa9d40f971d89e3f" . + "989fbbdc1f813ffe668ae27e585748e15fc6c63ef0d080c8cf9b323f7f765bf6" . + "83e730733534070b22c551d82068395856a6274ec8ee277acc00ea6b285636b7" . + "fa8d9f2ad69b70b760496a1ad37867ecf284176335cbdf64313aa500b97b8abb" . + "5a3944c4570851a2bcb73a5e191b2215fabbb24ecd657d9685a84e9bf5f199ae" . + "d681a8e0c5ffdb30e81e231c11c7a98f25c544ea85649864184929134d076c97" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "59716cb57fba9fbe48ae4dc791c2115b9db617f57257008d71558cf37517c6b9" . + "939a58f9d416ea209fb0906f4855f76fd74f9e24d5d95e2b4b35b41f689faf05" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "921d4750d8092333a60cd9d05c34f30cf90cc4f411f571d304cb3d5de49026af" . + "2a29f9963be29fdd1dfdcb9a5ba4a1c2a87a617653ac8b4b26087ac2b34aa930" . + "893bd24a1ecef0b8b7efb225a18c97e0c20788802cccbeabbf9338ddc990e2fe" . + "ca9bcdd6448d53ad56bdd570ab3ca5fd99b05c0e5bca4b67a893c6ed28019078" . + . + . + "29ce4002fc11fa6ff7edbbd464c91e8c79d01d37f9d1a44c3c2b9458dcc0aa3a" . + "eb78fd7c53b6b8b1413306ab32048672c7d62f9fdbb7c7b6965ebcd202b73acd" . + "e9952b6ed2105d12b3595c6c5d69b8ddaf3f5d6be7e834f13394a929abbf75d6" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be944dc74bb485e344b7c09493ca07b690944a9b52f8e6d4d4e2f6f5c1d0239a" . + "5694b41b18a3e3ecb8f046da5890a4790898f9cdd61d777901bd421ffe6c6588" . + "6686176fc79391db007a48e3bc66a648fa724bd31ced77a29cc8388507ef2836" . + "2ff64189fdf3909635fea8b77271dcc486938f1310949f42fa9c064dc1991325" . + "024415650097e3621cf5968e8f4cd8d8e08b00ce18188abf5baa31e4eb95a520" . + "951c32140a34a41f9531f642b395d4f9431b62f0984108a662d9a460198bcd3c" . + "b11b041ceea791963bab1edf6a810c1d11be034be4223426bd291d6bddaca22c" . + "f0c23e8d959b814a64273aa2096b89931fd184ffa6ca27abe1c982d1f5428c6d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "21f47be103aeec551fde540bcf63180165519c11983dc6d72897d9c5243524a7" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "7949d4f9339ca8dda2315d548689790ef196bf29ab94684e5a0848f8365d3e0d" . + "31a785a63b00537285966acc7ce0d9b317e7efff9ff1595de6dc50aa81b9d893" . + "18d6c634dbb8fd80a71e1d621c03dac47db6c1cc79d1ef0997db366151b8b8a7" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8766e4a9543603c346f6a9b11ee62a1e24fd61a0e1fe91ed2cb0a85b66f71b0d" . + "0225f715134f53f09783817bdde8cfdd740f0595456cc84e4d4ed909e75f2295" . + "5665231b8b74bd03b3c90ffda29f2cd4305a15b79d3cf8f44002ed39ed9c0c5a" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + . + "9001233b3c43c3881f05339d7e2ef2c3cf8efc2d2dc50cbc7e9317d2832ae8b2" . + "3549d08828ed3c4de94da50d128bc95d06dbf6170eae2801bbb43596f06e1201" . + "68554a20a13938c7f1fb09f90b52c8ef500e489f82f99995c7a4e114c991de58" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2464c8cd2cd811981320eae5cf056d9a799a7b6e86b71521a86ba11334543e26" . + "1988c5a5ee99b6f4c00f37715150f432668522209f65b7a5142203279301274b" . + "efa6988b498aaabcb1a4fda6431a15f5c4dc2de10925ec8c89fcaafd2f78b57e" . + "9117b08dc3f7dd9248c556cc16bcb2b5259769ed00bf30ebd2b2b3f77f71bd74" . + "92d5b37d5785dd530eeeb8e38ed9ed98dfc305771aac13955dfd84b64ceddf5c" . + "6072cd171cf30dd64a874792d0b722d806470cf51455e0322ec956eb84f1b709" . + "e79c3df84a1447fe054fbc6b1be4141eaa400ca01c33a8f312aea3464af34d60" . + "737048848ed4bf123d96c0ca53bc83d0c54b68070513b9bc4f0a3284608ab4c2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d01e02df63c154e7ce71bc3f3a54a11a76cc3ba205e92e7306426ef7cac0df87" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "ebe139a9fa21ca2953b687c2f5ab15ceba984c28f8b0fca7a28b08462d4f3495" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "987a4205f61734712121ef34658b49f883e13ea346e6c2ebc731a9827924c36b" . + "059890d81748cb2644dbeb1817fdb6dfdd847c5435198b479136b18c1194ae74" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + . + "987a4205f61734712121ef34658b49f883e13ea346e6c2ebc731a9827924c36b" . + "49580c7f4577e43cbca4897bae4ddc8a3ea7119c8d30ff0ee4df08f588d3dd4f" . + "7bf0d6aef51489464b4b84dd1a4bb91677e73ef59f6057d77adb2a64076f8826" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "660c6345956a5c156fa5065dc4c0de1322e853da06a1ebc870a909a54794dbd1" . + "a186f841a791e817ed30b6fd9aa1ae5c7717cf7de04732248d77f9578d7bd280" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "b3f9059ff0637dc82e53074993b80427fdadaaebb2986adff83b9ce035d8ab94" . + "cdcbea022b965934d80a5eaf144851d6518bf3846f30cd9f9dc298eb44d611ed" . + "d475177e782af1286376c26165d7ea65688ec1e3d0b680a1d3df4af77edccb77" . + "a8647ff1b304610470a52c16d2421ab1df38d19284c6d5b1966493ee14d36ff4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "474d4fe643dd74ce8d1fcc5648687faf27d87d169130012652b4ae2279aaa095" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "ec099fc2aecb565cb669f9e8cd8b085f5d34de40fae9bd4c2c89c4eeeef62952" . + "c7c2da3458f2f1f5516764146febd29a2ba1d6f46ae395fdc3bc6208f4b8944b" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "46e88afe5b6f1c3c1e13e3c1d11ee2646707ceed8ecbc2c4aac68fa17f8fd6ba" . + . + "5950ea3893d00bf178fe8b0baaf5500c5e0b7872317090d028de60200195df0c" . + "2cc16b23182682a7598d0934e045663f444b843ed2305f2efa1afb254e245323" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8b31cd06600925a393443477cd50b1186e1d2675376f50a1deca402e7adce217" . + "8b31cd06600925a393443477cd50b1186e1d2675376f50a1deca402e7adce217" . + "01cb26c0564d11913707d67613b09774c75c133c0dd865c2bc6484c3b9542e12" . + "67b91146e0b1f2a2738191823eb964bba670c2d109773f6b3f4aa96ffbfe2e38" . + "aa799eb60d591a127519c0db93d34c89dbefd838f6d0860937a7d0c7759d5d23" . + "644ab875263f893551e186a665f1b8144aa997cb364db772f07b5ca9b684a3b1" . + "c3598e2e1cbd9840578d2479ce9f6e393b884ee03d28f30984f0db82369ed2a5" . + "888f4009c2a35724fdf471b00546c47d5a718ad94e4638eb6739e1d2ebbe0e31" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "45ab10cbc0c7a6710260ae2a10f2eda403ae286b9437fed034b7de75bc52b0a9" . + "56535aa17cb1a79275a35a5610787353a6d4c5d133cc2c23f8ae61e4699ff52e" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "5eed27d4df75ab537938c6f94fb5e4bae591a9bd7154a24adfec9f8832d88f0e" . + "7b1135818e3656861eda318c82cf799e8a02014cb941129c4abc2a6260be09a0" . + "46e88afe5b6f1c3c1e13e3c1d11ee2646707ceed8ecbc2c4aac68fa17f8fd6ba" . + "a9630fb437046faf1d2c807693fc8cedf68dc65f8bf14936451b4e6007df7c9c" . + . + . + "5eed27d4df75ab537938c6f94fb5e4bae591a9bd7154a24adfec9f8832d88f0e" . + "2b14d779412648265ebc52e206a871390ad426697928081d8ece07bb8150ac53" . + "5a1e3afe88b544aa91caf6f260efd3b542b4a7c062caebd5b6ec3df3f13fe37b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b54dfbff5c21fa3cd3b752c77614f15202ad662fcc81609e6d6780c82d727b3a" . + "0b215b66447d5014114e80b0c64fa52d7305306a75799e4241368e1176884cca" . + "5d6644e22189528a7f67896523e7f71ccedcb08d35d863010767a6a515c56d83" . + "f66ffb5b8d571dfbd4cdb459818d875023ecbea512b515a4608f967437a0c3fa" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "8b43a923610ce3967910f97411f74b9c19f6ae779b58a8a6762b1e47134e2072" . + "990da96ac8ab00621c95946b14296cef20caaf466259a5361753ba2495044f33" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "70f97819665326d391ce6f78088df980d361e0ca2daa58cb494fa751ac87aae3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "559626d3c368eb28636b37b580cc89535485245611f96dea32b0b0747012653c" . + "d66edf8c478e102724fc760eca2baf9c25ed88d76f74bc2fa95e5ffe01a2962e" . + "cde2bd069b5e9772dd4b75e943c2d4429d85eaa7c4987f8862a16ca3ed5d033e" . + "b050691eb2cef384dc00660ffd5f33d51251d1f815b4f83565b60e4cbbe37860" . + "160399dbc9787afe6f6e18e635dddb76ad82e13a81acdb9ec719e1df3db44201" . + "0774b30bd258f146bc2a3392ffdf9e86ed7eb0843c709948255f76e0c36058b1" . + "6bdefe9cf42f1efa0821aaddc06acb84037a14918a51c17224430a9483471897" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "022795e7aebab40d239bc013ea767fffad1be37c00a0618b560049871c1c0947" . + "00cdfdb2a1f8fcf28cd4f59ded3993e366961cc1d7610f5aab36c880c85641bb" . + "6d359d96387a281d940046308746a4d7b82569ba922849c83a9871813592ff3c" . + "e6f0a9eac9f7a56e1533e0528ee0f5722f169b5b8dfc95463153657fcb8aaf44" . + "14979bfb656ccfe819686650c73420de29e2fc2d234da8d503644440218a2ddd" . + "d43534b43ce8a5f56490f27ce21a98188503183104360c0335a4e0eaa91ed93b" . + "1f47cd734636cb5a967ab0f6421872796465eb42cd8a2caf586f8c3af2047c84" . + "1013dcf1cd784d7dfdbb1059b36602b99ad4d2c3aa843faff84638d0e08cb8fc" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "2a85f71af02a076e7a2e46c2218e4b0b12b28271df370698f2b4186c32cafa0f" . + "464b94d65a3485b27cb98bfc4d0fdfd613bfd542b523bb37beea6eb646e97816" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "46ab3c9bf05fdb1b772f8c5c3b06fa97bbeb3af4957a69c07413efe5500c6017" . + "65bbbb147383c7e7e396a44ece68947fd7fc2e4d55fd545d563872053a8dec30" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + "ad6d85223d2fecf2a728e710cd0c84ec6eb54f14c04657b98372b550a5be6b58" . + . + "2a520b1fe523bfaa8db18723a4a142c6ec9e5ba7b9b82c957a1b4f51c04fdcaf" . + "48cf9d7ad94e4f3cba77fe0744fd2f7345abd714dfe547246afdb1dd8e3f4a52" . + "b442025d5132ec40747c29aebdc12916cf009a47fc13942e6d35948355626cc7" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "80e4af096340c5811a751299c2a346ef94b97ab4e6d0e2b992d0e08a7556f15c" . + "65c70c5e9e4381646a0355d8103a13d16cfd9139fe429d827a9322ce639f64ec" . + "461aedc1c8cb6eb3844a3d95dec1ac9b7e172564076e1f3f533403fdfaaaa49d" . + "b79141b78047a8bc2de9f5ed1758a4f09b3afd53e24d8d215bf74ad8e4e9fe02" . + "5e828fe09b20f79479a16a14fcc8a0a8983992e6c788ac48bd63cbf90943a66d" . + "fe08510adb3328708f9fb7512b24264cfdb97c8d1c7d73b2899a67a5b96a37cb" . + "cb44352da8077fd3dd65e413930181d6a85c1a315f433520b66cd40b14630ecf" . + "1f580fb76828b50d9b08a5515abae9769bef27f2e293e04a96594ccb694ab1bf" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "756e1a9bfa1ddd05a495474d65e5f6e46a918223f14b7ea8e35f3eff51ae40ef" . + "369acce75bb17efdddfa124307f2bf90fb8118b97bdab642b0895b2572faac53" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "bfa15bf40de2365b21a2642fdbf24b059211486a5fac9151ccb6e1fb05c66d80" . + "27246f8192b47a549efb4e4f1516f6c3a13c8ea0fe49c1c3bf56c6efb670d419" . + "9e4c2bbbdff78dc4d3c58e9787975bb36aa609e108a03bbde8fc89b78a4cfdc4" . + "91593aabf9063476f9e2c210a00679b4c2efd1e92b12306ab9e67e2183f5cc49" . + . + . + "3cbe1cec2a6bf1f80a377882423c1cc920c361f97b74197a448e37f45a437cb7" . + "f4507f4415d6d79031a4a8ecd0e6e0b41d93d7547086e7d71a8a36c414659574" . + "2586c19a354d09959bf49c81d8679e3ee48278b2ec81c70f335bde4398b19ef2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ab5ccd8ccf0c4e4adf79590f77c571d08a93c41c907c14dd15167f38a8dd5713" . + "f7137e64cfed3de3ff21b4fa5ace961510ac3e62511aa3afd9ac4a87fa35ea53" . + "40b20e422ccc01a57ce88f8d23258ac836745c0f008373f6513f642e58a880b9" . + "f8f635af8713cb3978398f00fc4e668ff744bf5829a785e6d67b325a4404d53b" . + "0ece0e42ec0d002cb5f4aa53f9835b1f3f69118ad9fd6069e9e6d27c45e6f9ff" . + "e4bf8bb8fa02ff6d0bc46d9eb5b97d6763830dcd2f771f7a7ceb71e0ea1f1831" . + "b70ada43b2982ed43c85bbd7ad90b34c77ef76a1f01781404cc866046cb035b5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "86b4ba121837aefbd8408e894f825c363c2797c2840537e4580566b3f1890350" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "962da9bd653cc0631acdf2634333b2388022fca535c9c8322d32936d4fb0a9b5" . + "420bb0733b2b2e91d79bec54f05e92377ae6157acbb21b552a21dc4d9a7b9875" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "c9144c2edb951273e0d90ae7299e476c8fb5065dbd55b2f02d4aedbc641998d6" . + "962da9bd653cc0631acdf2634333b2388022fca535c9c8322d32936d4fb0a9b5" . + "11e1fb03ed97f5faffafa6aca3e22826c84a9ca1043ba11ce9050387fb750110" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d3cfd5d08036fe1a935bafbefd6c166e9974cf9d6446ce4aa65419f5c4f81f09" . + "3f5a823e6135506a7a2e2517fc28015623f93652f78a7fbee60edfec3a2dfd0a" . + "c32258116fc5820123fed50bff6cc339d905df30fb9474f7cd5b5abf5f7c604c" . + "bef5a6bcb22c37c0f4183da20d5ac40b2008366731fda34eb22d24d33227e952" . + "fdf8197675b5801f03059a3280bbe4c006393a3fa6da6dfd005098598c3b6e51" . + "d0c704f6a600dbe687b1b53361c28e3d761e2a263f1b34b1da6834993a354ff1" . + "689f71320c4fbabcd1ff1fb5e580482a5181117ec7e4d14020e6d63fdfc1c6d9" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "6daf2975770b0ccfe7fa1da75642def6b08b6b9ff11d3c9e7ad866f0b6b47f3a" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "9a24f114e1cdb8eb8b6d6813c11dbed1aa4e82182252f0535d92a41e8718df36" . + "4fc62612e99d84c68df27d095eaca4c8e16a8820aae588f5471c3815abb8f2ea" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "8eeabf6dca13412bab051f2bdc465197809e9917f0a85fe3da039c15e9536ff3" . + "e9f9d3477bd4a1da46c03305c961126bab73b6896c2ae22d948862a8b8f8e8cf" . + "632c867ada0a6977ce4d71b06ac05516715c7ac1164a2b44c2a17b569a8181b0" . + "b5e86cefc9cfb8c972b2ede02131e8a270e7fbc4216e7be80bf800aea5de029b" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6f0f5a6c18d31137b5481cef7102601e66043edeb980727700647f1fb7479ced" . + "ec0e679f9a4539091dec7d7c60583b4aaa997794a17529eb197d23bd06dc8413" . + "652683217b6a7f2e3d8cd12a1506b3fbff1d1f12eeddefba689bc9f01183073a" . + "bf0e6fe940e6c4d90c4adc68c0b806084fab74be63519a34396c630c0f60f0f2" . + "8b088adcb51a1920dfd6c64867b5e765175981537cd40b7a6e3bc1014220441b" . + "8337ceccab11b81a4a0b0a8f86efebf25e48191c3fccf74d4ae07362a2cd8eba" . + "a883ceb3ed68de3aa379c1507ae1a54f4e18c86b5cddcd4b56af3221e709e1f1" . + "aba10709d4fab2fe074ddee0a8ad9a62b92e96485b9ce1b5edd5e2b71d2518db" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "1740073349a9a0449642d1355b9fa75b0e871bdbd616209ff5a8c351d8b35814" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "f94b65664723fc0ef798f1746475ccb451e3f1cdeb91fe97f8d9929f6e6a8bac" . + "c26687c79cf4ff309478e285b9faf66b581be1ec1873396287178a87828efec2" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "d895bebb04cd012d596c7f3571078a6369833d4624c048c61f30a7967033f730" . + "0f86e74f23791a8369ed58196c456b42ac931dd85762cb9838dd6f9ea1c49553" . + "eb64c169523878e7790612a4cfd2bfafb12bb302bded6a28687b039e26bea05e" . + "ffd5fe7962e3de478152de11be4aeaa86c20c6c8be80f1cf1da3e126e407820f" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "389476059d1e9ce4c97aff4c730bfc708c84e2dd37486dfeacef001beccf6223" . + "389476059d1e9ce4c97aff4c730bfc708c84e2dd37486dfeacef001beccf6223" . + "d6e3df261a3b71c66659387489e7887f7738bdedfc29ba5bc1e32a73cde18c9a" . + "27c36122a32a317aa79ede8615ce81555a574527f69a9e037c81fd4213e0ca92" . + "8a0e37f513ac5c25b3f6ac6290cb5f1aff303e2e554b5a0e20b4d4ddae0858b2" . + "cd63719daa9aee228769614a76e37538e5184f171748ad96f2ad563c408cfc61" . + "4636a52fa2d046e3117f44f2c05964524db47e918c151d96f718b8a454e8ba11" . + "0e074afabd62114ba736b8ba8c4bd6159c0fe0fe1b25dd26a96cdd7365e82458" . + "8d83af47468813e862001faf8f92360705666baafa9de0af6f231008eee091f6" . + "2aa8ec7d6e5ffca04b7a089dfdbe7eec5f6ba3106dcfd05bfe32be46b9e96b59" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "14c2c31588f412ed4d5c03e7ede5e690b71222cc944853bc219869de83d20557" . + "13e35753455445062108cb08d7be5fe0befba2f011aeaea2ec13d9bdab17cc95" . + "03b7d8c94fd575508ffcfa9b3950a1bdccf65b507bcceb001ced5b6f1dbb6063" . + "bbacfcf65b801fcebd2d0db2c09f64027641457fbe7e89a7100f4bc543c4205f" . + "14c2c31588f412ed4d5c03e7ede5e690b71222cc944853bc219869de83d20557" . + "8c5802a6a4f4e04c48a60bf4e2c047c5952a8ffb2257cfbe3791c4bbc8e86b5e" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5685dea208688cca9594495a834dac832bbbab61e14c0d7c7daed969b08918e1" . + "2a36f5a606ec6048aac43b1e128925797699a3c38df5cff02306345fc04c9676" . + "ce7f098af34cd3678ed8511ed3392c594f54a1cc92c37c656028edc0b42b6f92" . + "572b99abd37b99999918b6ce098289ec2b69e1ed6df8c8338fbef14b8d5c963f" . + "d755f41f5cdce3dec45aafd3c243a03c35cf849f620019a6100e710fac44e90c" . + "ccb2336b9c608bf97a1fdddb7ab006aa3863d5d950e1b32991710bfe19b856e0" . + "ad91c0d2a87bb68da62cae6eaa08cff0b16fc967915cf9074bc5c14f3a00552b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "ad95d0db5ae5d030a54139c6156419454bc626f273daf9db31a8aeb49fe26142" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "80a8f13cfad76cab45a15d6f0b6124b2bb66f6e0c186fa71ca51d0328cadd02e" . + "134e22782f930cc608bbfb42822c7925bbb4d57f3ba28180b00dbfdcd4c1e3fd" . + "5665231b8b74bd03b3c90ffda29f2cd4305a15b79d3cf8f44002ed39ed9c0c5a" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + . + "b27b93bdee96779cadb05b3e2a5893c751a3916e74f2f5e69800a519a9f03d3f" . + "68e68248a6c423387d8a1c651c5f142c700bb1353eee6c8302a671938db463cb" . + "54814cca62046c4a31d5b9763dadbc69657cb9e39ca16d76ff4beecfdbb79fab" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3da39e2fee60521488a4d2203f1ba20d09023f5a95921f081a75ea45db35c6d4" . + "3da39e2fee60521488a4d2203f1ba20d09023f5a95921f081a75ea45db35c6d4" . + "78fe9b33cafe58c172914578844edb2fd35543ea84f346b4fc6969012eb915e3" . + "61764fe6e274bb861e181c7b6973dfce79a145742f2a042cc0053b6d5d4f3aee" . + "fd1d9bef559201d1f51a39e7cd3ee616db5e2f69198f822780802404798c4738" . + "c525daf01acaecb9487c3dc5549af4659df2b02c79be6357c6f08d5792363687" . + "3e021c9c9bdc522b3515a29ac2fa7e5ef8773f47fcf87a855fe9e86b65bf55a4" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "81055db35157a6d14343142d3bcad03c78f8bffada5d6d798d3bb27b401b5d5b" . + "d18a18f6f31602c64217f5ed00e187b6b7172abcd27e6d3d3b46d04de2ed6a92" . + "bfbdf5f1bdfe8257ef02b90ca0807c9f0c8e1c5b588a58a84288930223d5016c" . + "a1ecbf1a0e419b1aa9f6b6125ae0477257bb294a58a6698a3f59de3555a854f5" . + "9dbaa145fdc05d951e42a4a34df6aad15e961486173588263428889c929a8991" . + "f79f22281bedfc12ea756bb17d67d6cd2581c9c6596a16ddf76dd398509b8e85" . + "556fc6437866aa8ce4533c0986508f49cceb772632580e7e2ac8e2323ac79eed" . + "b61f72611f85d5d16e75d10240d79bcc3bace79daba87e0e40b52bce6e2632dd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "442ced0ba52be99f5c5ca19d07fe887ee964895a06974aaf9e6074c45e11e55e" . + "1fdc5e3dc8a7ffba05b148bea383ae9de8b618335185c80db705a186ebd74b63" . + "0f913faaa97e842fa3618da544601fad2a8db4c5028473b4fbca28bd474cd481" . + "0e278af4fe12e0f8216937aa4b5cddb60f126dc3861308d1fe485d055948bfce" . + "20011061425d24838b66422beb2f5836a53d8aa98a96274bdb633a7272cc89e1" . + "a504e3b9ffad59d419a50aae81119891866a0d731787baf5bb0fd87813fb12f4" . + "15ea7bdf1f57f4fc341d8bbc08e01d6d251feff0ce8b56e29078b28147aaf0f4" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "9f921424db9e5f76d50ea5e350b9d78f45ebb175e8c8186ab0155c4f012d34b2" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "a16847369123ca7f4d8003cdb02e2f99c34fcb12498f20877cbf4b6e57235f82" . + "89d5732262800eeaf03c2e9c44b42381f205b8f13b4e44e9ebd54945b24fbadb" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "0c322a8fe3aa0904f3ab49f65317d8d020dda46e9a482ebae51b8df972e11e65" . + "a16847369123ca7f4d8003cdb02e2f99c34fcb12498f20877cbf4b6e57235f82" . + "2a09e26fb2e20c65b6043cfdca132ab26a263f482604c9a4567908fb2398af50" . + "89f16f2511f5e8cc212f27859328b20a5fe7a14ed1af6f93dab1c56c3d6d0fc6" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1708f1ba2f6e5f2adc2e47ea651ab234dd14ff6f914c18fa6697715f21bc64e6" . + "948eeac4ee5319d2915d6d1cc46e8e268b79214e71490082cf02912aa02bbd16" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + "83ba88b6d2addb1f3110d285d05479610cfdbccbbbc1d75f50f1534006aa271d" . + "7f021d70db4dd080eca5928b9521ec37ac29750527d30a70a636039220b6c4f5" . + "e4475911e416997b67dcde098f51e1287622eba8bd767eef9dfeb51be2190986" . + "dd79f0ec1af87e40e488691a5fe1c37505c4469adeefde8cebda9dabf5314ab8" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "284cc6fbbe95497ef167f35536bb15d2b69c9073cbadace4e9285a898ee1c5ca" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "f033a81754a668f8e6d4105c37f4a6f6d30f64a481b4424fd36dc4aa982e40f8" . + "42ef6efda44cb6274335a270d88d0066e97f7bf52378782672778e0fc880fd64" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + "49c26ed06c543b71573914fadc4a80dbbc3bda1913b7b64b97a7c2f902080dac" . + "d3c92ed7cf8bae1337dbe2207c19614c2e5aa7f0a25f162a1250126ab6d4fc1d" . + "a7fb4646a2969269de424a7f34171e25a58c37d5d524590598411d7de61294c1" . + "f91d80a2b96de4e67651ae845528ce5c39c004c5ee6fa409c35d258dbd21224a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "950f22f7c956a5cb85ac338915fd512d63c2a8c1d63226611e1828fd2e184e75" . + "0b0e1f40e81d51494debaede44f8f5353549fead117f0716e68179d75ef02fb7" . + "f6beb321ce589bddd74c40eff5855fdc38cb276a70c057d06bef507fcdb5bcdc" . + "8d50e5e65644c2b94e9434d116545b629d0d31a80d0dc3f85947565894410a4d" . + "2a5c9f08757a50a4c314b0002cd9a9a98f7743d2b8baa3afc85ddd1b20deb095" . + "d3b3606d31e47250dd37f956ddbc58d4f8e6829045d88975b1f38c063bfa445d" . + "14217fb25f473f95202cff603f7cbc105fbd983cf3da88ecf8eb27cf251c0720" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "61ce786b28fd737869996824f6f60a1b58d27bf39f99dcd3afa37208574eaa6b" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "84bfdfaf503bc460671d40b6fe350a7ad06b836a617f81619c3bdbdd4f6cb9e6" . + "6e9a1db949ed5e7ebb6dc7cb38e6228fc19b826910f0021f2e97dc8711108ca0" . + "ff045805136a1d471483cd5245306990d4b3e466be9e082dc383abd350ec8698" . + "64c0695567812997cdcb35797557b5490b86eae30fd2a773faa27feb04a2a491" . + "eb652f043457a21ffd25dd939bcc0ddd9919361b88cf88b909ee8b5ea9119eb3" . + "c26c67c874a9271be8718936009df32eaf05d5e10056edc276cba9d6fc59ec44" . + "dd6f0d4eff993f50f83d6f8291ce45e5db9b7f9720ea9e38598d8643832831d0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "35730f82243472087d3990589ea7170e5b901cb7f4fb99c42de0bb172db6cedd" . + "04fb12488d706cb9317592b20ed37b94ac0e208d51b4d5b9e11b201cafa3f982" . + "d2c31da6fd18ff3448c2fc47d3097376265f1e2e215eac0e0bd45b674ef54602" . + "533fb939f03204caeef635f2e32cbc2f8a4a50a800b36488fadec9ef30d4f00a" . + "c9269b5b54dc4a7206459c95cb0c8ff27a3ab268bf5d67fb782de979be939537" . + "970d4bc0cef7330203f3e8369f4a6b4f1458c191e2eeda8e6e6770d52e9c4c67" . + "ec2af23c9841cc8ba8340995c9b296b70b4dde3119164753645a15d5df44067b" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "539100c4b35884f67ad171e5c6d70fbafe99370299f056b2f80afa92755565be" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "2df199a58bd3f6cc751ac002fdc3bd9a05749ad38069a4c8edce969e4f277bd7" . + "e51079ec610bc256f6353d4bd95496abd752bdf08b6c6d9266bd6aa8b2787390" . + "5859536b6dfd0b3b2c334e2b7f9bc7a247aed7a06144d3769ea60e0ba1b076c0" . + "300e710438b7b1e25ba243d92a07f63a3e4f9ae8320868d9076271750e855f71" . + . + . + "bbf9becd063fa6f6bafbd114611d40b97433fff3fe5f7ab2600c2b98ea0d3b6a" . + "3a2c7fec281c8c9b69bef3390ffa7bc49fde463cd7f3364e19bbd4437814bd0c" . + "61bf64ccba3329eca4752808ccb9a3146e42c74d483f646354b9e10ad001987b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6e7bcdeb3d23444040a758b9c855d7ccae9ce635cb094f16fe9c392f7a0bc20d" . + "c64a72b2f1a52ceb1a57c4deeb85ae45a58e37c28a0fa243dc9fd8fadadb5ef5" . + "a5d4a240cdfd40b74673729ebaa241e558e9883b8e7375ef58b84729ad6e54e1" . + "85d4afa072151af8e184a575d80ce1f4a267d76d5f381294e368e6295d04a8dd" . + "380b0bae5b0c45dd66d70654520bbe2178d9e83f294314a441d428c8b46cf342" . + "a5def2c1e0bb66430c9767fe5d02c7fb7de04bcf412af3e9ebd8378834925175" . + "b12416bfd9d19eb4fc2bdf218479e8da3376d182f516461dc1cfc212c579bc99" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "100aa01f39aaddd94e75dee658c41d5bda3787f043b7fe624425a6e51b1e8789" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "b99939c5cb01e0544667f4d740bafb745737978f7f0ddbf654bbc0cd7f091d8b" . + "0e09e0a7180dc2b19fd64abc826fb126411656a805eabbb339d502c354920d9d" . + "8779724321f9659a702760a7391691d00aee38cc4c581a695d7a5a96e0b3ba71" . + "cca5b40a332e7ddbaa0a16f94b9e37bcd5ac77c5a414083da239e03d4908c35d" . + . + . + . + "264023dec8368c9619882239872f90676cef4adcb3c5d43f5f3a2c6e0ff689ad" . + "230c1ee65bf7b51e3098884fdcbc6829a3429830d00ccb7adc2e51d25ecc09bc" . + "61bf64ccba3329eca4752808ccb9a3146e42c74d483f646354b9e10ad001987b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "42b816b9e9f49bae724d2188330de327768ec0032442c4d5f5e80ead23032e5f" . + "a47a6e747738c7617f88b800182e56aded71a6575c0f8b8ae6ecec82557472a7" . + "2fe520f221775872ad04b1cb28427c4f6feae6cfe55a03f899d0606c6d9666fa" . + "ef4a387ac6de622dac327bbd93cec9d2ca923a189a40e10cfa40d95628d3a750" . + "5ed550180204cf32365a771f870e22f169984bc068b894f27a52ffea18b1e768" . + "30c048cfe37a0a21b8d22a0f74cfe9a694e8dd39f40080eece350efd50e47bf6" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "1fd3d04ccc14b27bce1d12bb413f9945f5446be08d3e41082d2670eab179da87" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "4b1613fe3aa4e69508b0ad76d9f17016bbd7bb4c304ebcd9b6a5a1298b950ed3" . + "8be0fea29160563d70029bd82791b1cc483a49fb6511a76ee1c87d9565868088" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "a168aea6cba76a59d54ef38b1a9b45340a7900e7edc350c1c46e01bb06a3c542" . + "e69c28dd1a620bfcac8f3f6071b80882c15fb1bc775000966ee3259323e1dffd" . + "c14a90fd7562c216b9ba5eb4ae51a2ea2eefbaf53d242b708fedd86482cfb73e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "b88f77a3fe5716f0898e0c7302dbb5155597e0989023d66485d28edd906beec7" . + "03184ce7a0eb0a5eef6845f50f54bb3d857b31dcf7c5f651e871b7745b2c2981" . + "ca9bcdd6448d53ad56bdd570ab3ca5fd99b05c0e5bca4b67a893c6ed28019078" . + "f053d1e5baf36fcfccf642caf5f96b05d890db518cdec2bd7f166cab449ea8af" . + "212448d0520c0c4490aa5bed68d0a8d8f8f4385fd8a98662551a08598414bf55" . + "fc49f600e96e64c84ef0d29a35d69f442e84a36a5c0f3e82357a622dd6f5104f" . + "1ad4721d84110cd1f18f34a4dc713c589c828051583a56f8928e9d00996fca27" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "a338543a2d0a07a111f90db0f763dd00295cf0266f12f023e75d5a19c925e694" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "351f8b7692f3c3194150c286bde22dd2136c22c5f25f7fe62f68de0214a956b0" . + "9b5ab2023d70f4bd56be1761a66a5f98a58297926dd33525dca091c8084ddc46" . + "7d090b1d7ca951538dcbe500404e1ea9f0acd11475cf709f85198aed1169d39d" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "01c818467e64ff96073a56b4de076e28347a714aec35676fcafbc18549ba7fac" . + "4af942902bc399760215de049cc558c6bd117ebd017fe40eade332beb4403292" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "20ac84e4fa9e395719b34dec9c2e4e805ed29ce957005b1be080ab50bb1e16e5" . + "c6d015356cba013db54ec2efc36fd8184134a8de586f9382e1bff45abfe5a609" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "ae3019d17637c0ae2cfd2a1967661a45f02d9f31f8a682cb8e64713aada98d42" . + "597d708fb087750e784fb62654100d3f65062241b16ce96cee4c9fa7441b9c05" . + "7f0a8be0adaf2f9396f0e3c3188dbe24093e1f1344bdd6a54134b888a44bb5c6" . + "b7b5330cda081721d4e58ae6091ee64e4df61fd7e3a4d3d665c940b62c980ecd" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c0681e5b24c95df66de046022fd069dbc4b036e53c8d2df5e12493e3ea49fe17" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "d3ea6e2373259fb05dc5d138dabbbe8af2f6b9acfcccadad508c6f5900f2e2ea" . + "62b90d3c5db52ce1b6d681283d0c64417fbe1c37e246b92ec355924908597736" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "3d2801338181b8bf15fa8c62780a597f10f3531e697aafba9fe31cf38c2ba76f" . + "690a9946e755b3516efe67df0ed1fa326fddf166ab72f56bd8e49f49bf801714" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0e48ad993b26db8d3f397d7c755f695b9ea2df066ccce30abb1c10277836cd0" . + "f0e48ad993b26db8d3f397d7c755f695b9ea2df066ccce30abb1c10277836cd0" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "11290d35bc0cf2ce65a4d017685ec569affcb54e45c70e146edc4d5931b31ac0" . + "c0e416fe232b2d29605cf1642a6e0e5089c059243347164fed4505b67b2bca86" . + "6436857a1cf8c7168d50f29bef0d5f86400b3140419388fcf3526fd563875ade" . + "fd060cfc8a0d8f6c7e2382d2e54ca539a320bf0d98ca79aa7724d7c45c5e1042" . + "aba10709d4fab2fe074ddee0a8ad9a62b92e96485b9ce1b5edd5e2b71d2518db" . + "27c0804676616e3489406cc820c8e88d1141f7daf1f5d520aec1bc8831d53ced" . + "485c33a198da5a75a75fac0c8f5ea3bf09f07451538ad4aeb2f902eb27c6277d" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "3babc37a46fc5fc438256d2f686d961d00281957eb923909753116eb59f930e7" . + "2da2c573c3b4e1c666f8aa4955ba1d46f9ff01e8ba7fb6a12861b9153c446263" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + "320e950a64c810d55934b949a586050e6dd065220d351c64d973e5076c295538" . + "106345f9568a3f80d0040dcaf73bac238fae30a85dfcc630c25235b6cdee78c1" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee2e5e974398322cfcced09c871f1330df0bc1c0a1334ff82b37d94d7729721a" . + "31228ab04027720fde36af392fee6eedb2806eda587857ecf0ac3126256358f9" . + "f388ade5c80205d90d1109cc8d897fd16a13b74b0cd992ed47313c4091620035" . + "8b0b317fd6e28195a3b1532caef1afb1503265d5eb213b9002ae1aff512421c9" . + "feba4543120e2403ccc6f1e29549878d0e1deca1996717d4e1cfc0a2ab73e841" . + "c676f045fab32bbc17134e9a9be4108cc9d577348c3a470f06ca5065fc673f8e" . + "e710b36738bae2b51b5f7361a12e50a42d0a8b33e017f73083093904f3e06563" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "09ae6eb5f13d86ac393834422a9e0c150054418a4946ab246eea1c31d6253d2a" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "b8d93bb35f09864c67b09637aceec479b03adc8ad152b17b578f6681a9e523e0" . + "7ebb0607c4179b1422d897be12e9d9d2fa6807c761d7f46533db063e469d0d8d" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "3f5c7c229d3fac179b4899c9041c2adfa7f9291ebcd566706517971e40bfa3a3" . + "1cb3b4e81a663444d4860f07796885cf52f891b55c255c19b605a4b0801140e0" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eab146a8c17330708de1ebf45b78fa60aec3bfcde163cc2a913b270debd005af" . + "b8ea923542675a42ff8dbd567405b5c4720137c0e0366adb447e8b4fac73ca8d" . + . + "3b6a39602d19f6d1f73924cb70b609a1837d8cac5687b86ade1cfdb334b15c03" . + "973f6e78f7073f2ffa5dac05f7a00a9bb1e5f16b27dab1f4f8a45fcc6f6db97b" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "d5ccbdbd283225eb58cb3ab86b99682659c2aac198232da415dda26370ac4b8a" . + "0deac5d0628ff30ea72156b70661cc7de41833b75fa3dab459df1f05292f6ae7" . + "2ad336399c482ab9a7cc5b80eb80b48e2851b5d7ae7472d2a7cf3ac185f8ec81" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a5d889779dca42d42de65d2ac116ed6c405a041a35abd0865d574f08d9581d9e" . + "a5d889779dca42d42de65d2ac116ed6c405a041a35abd0865d574f08d9581d9e" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "d4b0f748cfe5e73a50dd326e53db8026302a67232b08b14b98f13b0e7c47f9b5" . + "436b6572448623d24b07d5b40963b071270df45ea9f33b4059cdd0c344996520" . + "761cef156a6660144d8baecf93fded2afffee49b1fb026e6b3f889fd49976765" . + "46e964806f8cf4c905ba6131756407a26f7783d8a18c6caf80a2af4541bdc431" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "242726d906eeac20f586d4595e6bfac264412acfea5128004c79df678ce560f8" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "3a0b546e2801a5a9774f9d9f8e829a846be8ce1742d770e48b955964c3630125" . + "7038a3ed96b31a16a33a82443059f4578e893c0c3ceba8647c90520643f82533" . + "20166b30dd3d68b688197184fc40c9523f10f7d66c23faa013c5f8cc62fc7ba1" . + "7ddbb387a295d71e921ee59c66e7e2892031fb42bf9a89abfa03f4fd2a1ba90e" . + "ec18c4f867a67057974dea73cb6971d27f6b1dbdfe4258c00a28af144e2bea4a" . + "4a8bac6243f7e0f640aa9fb121c5db60f633ac38dcf9595181b7531478f0ac76" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7ee129d4c311375d60d49bbc3c3cc6d4df2502c67e88561ff5a1d0e1f2fbe3e" . + "f7ee129d4c311375d60d49bbc3c3cc6d4df2502c67e88561ff5a1d0e1f2fbe3e" . + "fce5ea48e2ae7b6808e76aa5d4d770e65ebe96103aec5603727cc84f0bb372c7" . + "7876ae8b168828aef712e8828d268a81a2001d2ed986fc8b35026735070c6004" . + "a7ea0210d6f86dd285dfb8bbb9de20764e8889ddc6cc12748321d767ba64260b" . + "8be38f5e6f5806b7e5c189a035e7f3a9ae8abb867c3cc8b3cc21f4de500e5d1d" . + "c140214da52749d6e758baf9b90fe5305872b97c0a130e05c7ef3156201fff5e" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "dd5b6d595627396af9d5e0b7f689f047a9aa88d07b581b9cd9078c01b335cde7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "c5f91f2977f3bea1114b917d44c27a43af87dffe4aaa5e3fae5765f82841559a" . + "042f55eba02fbdaabbd9a6887cb6435be4112c079fdeb7bc09ae4c3b3adaf04b" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + . + . + "caabe3f6abb0b8d4f91f9817ab528d7265048526d7976e91ade56149689f9f3e" . + "9061bcffe6ced2e6a1af0460dc7f88927ad9d99c5c827c340e703bbc8c8e55be" . + "3dbfd1fd173f16965f2998bfb1265d2bcfd5b32ffdb18bf7fe606827261b3bed" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e9fb1451031a7c78e891e58d9e167f5b61dca53a185ca5a8b33d22d02cc5f6d8" . + "0b4c15717f91f8b390d8e45e766e1646e03d562d7bfe2c397db3596e210ad9c9" . + "66764329ae8331bfbc1666fae4f69b1dd72f0377e1e5bdd20df0c8c16e7aca31" . + "a614766670bb629c7b7e2ba133cabcb1f76f13861e6bd783520ba979bdcd31bd" . + "ffa105b5f7af275e4cc49c6975cb697a077455556a43626bc3b19dd573f7afd2" . + "08def699554d31e801e674e1f8ffaa83f53444da59be69bfb991d33ad7cdb92f" . + "0368903f8527634cee71e567b1f4b293e9faf3bafc605c9872aa58fe2ee50f6a" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "21b2c1dad0c7c574b83c87178abf34bb85f82659a6ac75b9015d524201af8ad6" . + "28a1a9511ffd71219672688ae7cd2850f0ca0e47abd0ceead31c00070d8460a3" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "720be008680f4439f97d23c7b5e94a184eed825b5b3586590768c119846d8e4e" . + "4af985757efc46f5436788c8fb6472f8df7bb67999a572b0057f5e48f8d84712" . + "c2ce16ceca0f446a416175bc7a27fd315bb794bcb57d4a574ff8f9bd92660a61" . + "768bc869f2cfc3e24ce1a106febf2e85737f6bab18417f13b0fd59db0f284f4a" . + "69b821b81c53a8cf2f975c876dd0a4c899fde65206f0ef71acf9dac712e71418" . + "966eaac117ee20343b05b6b77cd238d69033b08c23642f595e261088c63d81ca" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a4c79b2d4ecd9788d5bd8c1469f9283bda140f42ea6ba9a53cf162e1a705a38" . + "62e3e6aec751c7f4b3e1309c34a1ded59c56f0d067f4c3c50fe8a9eadb268f6b" . + "bf07bef018b7f81360bbf15e5b7acaf3616c0e5febc00d81b9c3928a98288346" . + "94b3cc398ff6631694c966c57e77ff621684ea4dc6e2800f146d6b91f3ffa6c2" . + "0972b02738071f3dc5f4d920ea380f3d7ec329efea9bd0655357ab31161388a9" . + "7e5e29b650361dc86ca877b45e524b30e5ecc019ad1161ae3ac64f7b61d39b10" . + "15125b4ed815d437f52a3876af013ee2f2ccb56b800d51ab65e9c8598f9805d7" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "31470534c096ae89634cfbac2dd465010f0793670ee623a61c9633fdb2436e6d" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "0541a6d4fb03350180d63ee62947dcd88b91f31d17f57997ff1a11abf6f831f3" . + "3cefc38600c9e189a663f9d0d94ed2a7f03e4aef57e868ae87c385bf091ead6a" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "e0060bf4a1ede4f5bd2afcb56d33ccebd7e4a3e49297383bb70a8ddb714c761e" . + "d4c6ce94768133cb460571695909e9c53c7ebf25d8a44b9d4b3535e4720aa94e" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4fbd8fb7b76e463173a75d2cbed8a10ce22fe7b45f8be0ddded03741ce04d49b" . + "4fbd8fb7b76e463173a75d2cbed8a10ce22fe7b45f8be0ddded03741ce04d49b" . + "0bc1a3b4b9a82fd7acd3aea657bfa5ead39a69121d02e756801a62e850b2d93f" . + "9496a033cccfdc4321dba7afd663133ce604bfc7e5d635b3a6f2b03801db061a" . + "9c5f1e3d15f35eaf92600ea2306daa239b0a85e8924b902926bda1a8e2899a3e" . + "3151c6fbc0b56e800e9ceefdb5b3ecec74d06772799c5b4cb6ddc3578503071a" . + "43e8ea97bc70c00826ddb27fcbce682eb74682844c0097aaec0bbc912c2e6fac" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "1a4a8842d5103046caf02f8661fe57a759d8fcf9fc564b547f0a5f0186be5e39" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "c82dee26be978a1032adfa30399b4d48a13cfd60ae5f061ec26edb545224aa91" . + "93a24cdaa68d990765168cd5c011b530dc80f41d8356173133b8c88ebdd13b7d" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "2f3d62e273e4121d5d921e12d76569b9c84f9fafb470bcf690c4a30a731d9f61" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5024d74ddd657fbbddf935434b1140666cf3044572cf30013b58ab531026b81e" . + "413ee27c59888ed7d62b7e050154789ee78161800db211a8c9bd43c66f824ed2" . + . + "993508046191308f32e30c010401231dcda208077944a42009689f00f870cf6c" . + "e1ead5814a1f9ef2e2256ea4ad06270d20153a50401fd74649f2dd8f583ca8f1" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + "9010c0b824a082fc5874134ec485c2b5be971c5ba6ba4d2f2833ce9e8ef092ab" . + "e3abc53e948b73c8a2da24c43903878f42720618a3d2051f7c071a1a126d3e00" . + "95a430422e70cc25e658d5507b15bc67fda4b3e2417fe505193156db4c63cbe6" . + "d3357bd610c6f3a7dabfe0950fb7213e75b61f82f46e32c3339d224538a2dc5f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e92d09c7167b37aa8babae398e4489b6a6900c8a885c9d4a7309e9df890d2f0" . + "5e92d09c7167b37aa8babae398e4489b6a6900c8a885c9d4a7309e9df890d2f0" . + "96dca0e070b809d4d8c2a8b3d48fe92796055f9674416ab81e34ac20acc411f0" . + "b016788ad30ddfa1c9db918f722bcf72ebbf9941745d6e746933b0e7b5b0ee5d" . + "d9380adf8c315ec1ce6d56cad872d1bf183bd9542d195139c350e5478e5c43e4" . + "c9653a695fd40832682de0705e2fd1735df16c5f922214f9e68b097e481332d7" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "0600a2fa20942e6bad9268d0f17249e2dc856a5808f2b6dea07c1444b2916875" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "907125f4a66f159fc815bfa0a83a129c34fa07506cb1e7973cb4e30205dbbc8f" . + "1fc38f0548bec159a70ce4dd24d6448d4251517d701f8ba0815373dfb0f6b357" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + "278659b6bba5ad7c9d3c7ceb213768f89eeac09ac44565329593f7bc37d857a3" . + "9d164d80e4d36ae76a3aeac2233aa2b5286dd17f5d28f25aef9568a021810574" . + "18843e6b88751a6f83592d9d3de1c9980ce091c75695343f006c50a2ed84f4c3" . + "ed58d78b367e67b40d14fa834a0b5c5b97bbc3243c73636e9cfa0534f12880a8" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "af6ee2c97dc055d88474e732e99cfd3c2db32419276961aa33973329a69f8e6c" . + "af6ee2c97dc055d88474e732e99cfd3c2db32419276961aa33973329a69f8e6c" . + "26d77660454226e5684b428df12fb6ea98ea60874dc1c94fef5bb1315a9fcb29" . + "233ca24ebb02a2690b4c7a0b324b8707ced29b5278206c1d5c0c3b6cbde1aae7" . + "ebe36cdbc1de767b73876a320991de7ffcad5b30539c79801c3416381da4b4a9" . + "2169fe8ccd74ee0c1782d37fc782ed2c186c83449f919c7034261a6534d93cd3" . + "665e00e2c9a55193b60966af95ee3f68bea484747179e2e209092cf806c2dddb" . + "a2c3a163611975ba8c20b7056ed681bd8ab28e65668bf9237650dbdb2761ee64" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "5e792dcd38343bfe1d8b6e865c74d24b5af043d1f250dc64c90824d50c0ec042" . + "bd04cd52266888214e3114a0dd3d561fbba5b0a1c2df09ab2232299ad4e3d3fe" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "69a2077960df86512555e22aef48d93174665e73d9e49f7cc077347ab7a9407d" . + "b14d231f235a098ddb38eff3f55a3d781ad45bac46984bdde4820520323c4df3" . + "f0c9b40f4e4e9bb86fceb04fc51838d9f241de6723f2c6b00ebb9c1a0f8a2846" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8367465bc0bf1b79b41575e2411c492cdee58d05c384d8a399f4c1e2fe213452" . + "8ca2adba45493ca8eb3368e57b8818a3876dba2633600667596404c83f951dde" . + "c97d45cba483cc05f3ad2e0aa71ff76d7a994af39347bbdb73e0149e7718c407" . + "f76c544473677e731a552e82ff5935c8e6d8ba9272fb516ab19966388f9e7319" . + "223f2c6806413a6deda725d2c557337da2534b1d79858f8718d4c4ee66d4eed8" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "cb928486e634f1e029e6c4df92bb533b2dfc3362536f852f9b64376f622c9898" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5f701ce6b53f47210afccf9cc84d9b3e0184a4154cccff4828951157d27a9fe2" . + "16b09b450405d1ef6657da405e414bbd733d8f2f07e79a93a50cf693b303e5ad" . + "ae17be26003d0c4eec4d541173096a87ccc642e38e2d344649bb7686382335f4" . + "eda50bea4712a4c052c451510bbfac7e00383dce33209c0ceda5ec9571d9a6aa" . + . + . + . + "0c2b711e77b2ec1b8102891d14fa520553fabcec701d9d4db83576e138241d76" . + "28217b48f6f0b6d4c3988f439c356a621c77ae591207c778873090dfa93831cb" . + "f8f225ffb1ee898c7755e509023eb2ccff5b4beed048a1bea1bf0103e8af415c" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "295acf944cdd4d727a6369455ccea80479a82c3ae0405bd676891a4a8a0bd622" . + "de029adce00c6d757948a85ca7de959e554958ba89981806c67bafdb55c61530" . + "81a86fe2eb07cd9254cefdba514ce2fb8d4997d2abfb7b056c817e4fabd752e9" . + "daf30b525451f08f9d9d64e8a9c2cc74d7a403b1479e065d3e053d459f9e3f43" . + "ddd744bd2985e6dcdaf5a5c9e9d3097b33ad20c5fb3d0e9eb25fd6b17584318c" . + "d1fb8750d9402a0f78ce57c510a046e775dcfba81e923c949bcada846b5b41bb" . + "213c4cd7fd0f5bd3eeedff989631b9f275ec79e581dddbee23c69fd6aca6e2b5" . + "c583d702a429e36eed17734403af7679847c1e83ff2081257faf2c7f3e266eef" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "396f0c984385ab26f95fac3c52dabb2c4c44cfd67128238b7cb9af70d5e1b199" . + "0a9c1049a9361166713f01ab90c5698e290f3d01807446dd8a70e27beea68cf5" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "70156da15152d10a0072c4c039b9eeb4908d703d683b3359c436aa9002f5e2af" . + "7d53861b44bd1b00962a4e94a223790bd74802140464b9fe91b98c4f4f66703c" . + "51277d09fe5231598ed4fe1563de730d67f98676d2797a8986a1cf3f077f5ca9" . + "2fda7de22578be2f56054d8a7c733ed0f532c09258936be973e2849c49b0aea9" . + . + "8969ee6182b2ef6b2bb43f7ba284b697782476df2031b2bdfb133b45a1fad355" . + "8ebc4dee3ddc523b748dfe2208ffb7adaf7713c3cc620c16a151514fb0bd8093" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "557791e4da5917f13e1f7aadce4000144033387b708024bb141904364d48a45d" . + "7f98debf55e3ed222454fd6fa0b5f2d49cb76dca4f4466f8b78c970595d13b24" . + "df0fe71bae54920c7451ddc7534350e834ebb0b724784d42ef6357f5292fb1a6" . + "f9388fad4b85227f60502773e790e39ddd5cc9aa8ac488571bb5e99dceaec705" . + "457b8148dba144190b290586473bb31fc2621ec1d4c9026854515bed34435c9f" . + "2190c751ab73497b76c78f21ffddd3a1e3be0ee7d86ad1f46e2abfeb02ebdd08" . + "363f6cce7227f7d28b74a0c80e6ffed9845def15f6b39aa69496445521b1c4bb" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "5f60efae042640f8193dabea055a2cd7dd47ad00cfb1ce8e4fe24fc7b8290bff" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "7bc753e271071aff9619cba2a0378e28faefba3aff90e815861c43bc40416def" . + "74dfe051d6567e786fce8ee6b58095ce6341dc1db37a73bb66f4fd7d216763ec" . + "8d4077e7a697866d311c0c1c6766720cb6b6e91d1a53a53d818fb23f7dcff194" . + "4ae69c8a9d4ffabd16c72020c9a09f3d7c51167903c399eaf3be7b3e1f72bd1d" . + . + "11b7b11d1a70c8c6c09929d4abc1166dd25e0f96f5dfe6b09380ff88a351f397" . + "73bede4d08a946eaca8c56123c898bee908b954b5545e8f6ee5c706269fbb2ad" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "17f30dfc8d089248ae0cafe3273962b70131b7fa462ed6846be8a452e5657dd0" . + "19f5acddfb274fdaa5e2b00364054349b1e0d96a308924f5e53101b7e8c5b78e" . + "51e0395f696e2390d4aea2911d4d0dae1b19061495e96a1b0f921fecd8a987a5" . + "896e9ab400741781cdea86c266baf07211b46678c09d561fc074f5d899c1381b" . + "9682a7612687a6df78da1efdf4f9eff78d85b4e4ee480d3c4d1eb6a4827c163c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e258d01e6a556407c415232ec93d946164729a81028367afa40001e693073993" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "70121e2dab5738d027714b5768196962b140e35c78340adeca0206ed8b10b35c" . + "e3ae66c50e69949428b7bafe901aa296837322cae1d3ad9a2f06466e537bc629" . + "881043800dede38e3b0a881de317a86909f2e74f1264597477d7488740e0261c" . + "e16581407cf0b5e90823f583ab87ea02b5907ffd894726277e01e2ef240b45f2" . + "70121e2dab5738d027714b5768196962b140e35c78340adeca0206ed8b10b35c" . + "297abddd75441554aa6c8fa3df119b356dcf46e4f822982908946d8a63d11cec" . + "d95cd2ab7a0c3d7442d769addc8278adf1a1b196dfa55c5e30acd0d417d1b7d1" . + "fbf4e657294924acca4862173ee31b86b300ec94f8c3e0cbf291c1c1921f35a8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "278b210c9d6a2f225b35c458c7df9572afd309f697136746f478d4d7e0a5c888" . + "229997062dba8cdb6fecef69283e975c72038413434d4014afe259d18832870e" . + "e80e85c742e140563cd190a68b120f9e96d6c115e8a6159446c2b5703a978b81" . + "56d01c8b2bce0bb86b0f75f28faf378ff62711f4c720ce43eae0876a5bd73e4f" . + "3abbef813b68e579ece64f9e22fd605a3edb2b1ed216697cc2cc363a08214772" . + "9d087c942d39dabd5ba21d940aedf878ff6f7fe6dfe385dd8039b605887844c5" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "bb29d8ccf514ec01bd6cbcfcee32d546156063530bea13e9716e8247202472c8" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "ec4d17bdf0601baf870d9f642c7bf02d8add497e1bb5bf31b13d82e3e2e682c8" . + "e494f54249737915b7aec0d00b4461e8bb751ec65024e9ea58620ee13b67b880" . + "932bf52cf333815b5eab68b7d94f5498473feccd96c06283fd2329eb5ecec592" . + "788fd86474783db4805ed5b021d28c51b0a68550074b74812f593d623852842c" . + "abc871d90c7ac252e00551b58fe711b3b49ea745e7d3544a711ad1cf7494a487" . + "f3f0d37754865303593ca042aa374a0367e9a3650c052387ab6058103941056f" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3900970195fe4368b06da46136cb852251f866d335b7601778fd00c55ea22bae" . + "ab3a4189c842d93bd937719385e466cfa870e0dbab5fadf3ef4c828917f9ff70" . + "f69694a440d081890aed1b01a47f95625cb146c159c0e45154cb4b0350b5ef39" . + "d97e1fd659f72cc3ad9a556141adffa236fc3439a86d727d56dade366a024dd3" . + "a74012d20ed2b59037dfdf3987d0bd8f39dfbc2d384536990c02ca19302cdff1" . + "17db6bdd94e900b77dbc84752a3d06b0c5de3587bb2402e235317f9be92be129" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "2208d13c58ab3569eab25166029048640690ac7f2acf51aec53042b336be6330" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "6fdc11ef2bf933563930c949ad7855f1d399f503b262d70c51cffd147ed034ed" . + "abeead2fd77a1640df2f48126627ae603d8eff65b9236031a0782215ac794e78" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "818316e981dae6bda63609085cd46b766e6ddb0ec8b2ce398f5a8ffbc017e371" . + "8b50df34afdde074298e752466dced06358faa72572921ef175d3531da135d9b" . + "4b349abcd23cf570152b1c75b656dc79a1a6e9afb700f20b2f2edcd9b54d5a9f" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "ad1ee1387fe8b93614bdacd09b18de0522aae8f7bf607a2a2d097891cc55b33e" . + "816255c78a6fda4752a4e158e016f1e5ed0c27529e4528669cef5b4949434e04" . + "16ea7535427424e2465245ef7079398a0f3f4df1485d0d6f9a4a38f77814299e" . + "d19563cc56290d50f2932290a7c3b4172315fb67ba20deefb59d4c42ea7508c0" . + "9a8a09c245ed5690e2feef6c626b8fb97b03b3f2b729592c7ece38bcc9ae32b1" . + "a6d7806e54edf2dbf6bd384c6c4a12947527c3a5c6a90af50df1ba68aa15bae8" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "6160a04882b1763c932d0a12973759a307480444ca00284af7081e9ff99c1c71" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "8319576f4f61c4be298f83910c78de972c7d4d80ce592dab9e01a4043b11db21" . + "0b1aaa359cb534edfc90fd21d9189aaf1888671438ceff19f6aefc1799641065" . + "6d857d6a840b50221c15320740792e03a12280fdf69c40312b4f49ff39b5a0d8" . + "36404f433c116c18553eb71d136a9255a13aa73319a2f218e3f97c4828de7739" . + "5f10b035bc3a34795535eb2606a8b95ad9b636de20c4916717bc316fba9db3f4" . + "421301a909a8f7855116dbafc3d8c1fe07d6da052d75269fb09a32e2737ad174" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bccdcfc42a932f7ecfe9dcd2b1182f7cdfd2b20cef936d5783b4c3e4ac933db1" . + "a4a91619b0c853c9d5ac7ee1126dabc06bee28648b127d54963b142e05c53ca8" . + "20a4cd5f456d7207ab73a3d382d8b2aa49dd48c21b0de4976a96667e048946f9" . + "8dd176d27313acc36d987e4e35b7a4748b72777a6b4edb1d9acb7845db2d3cdb" . + "e3bcbfbdc93bc03b209985097d9c07598321f8fe3989b5c17cf1ad495e0fcf2b" . + "e71f97b5dc1055632e75edb3b58ebcea0184431ec44c370fdbd6fec2c02906ca" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "3dfce98de54a71b4407c597bee0bdda8babc0531152890d1631a196cb66c8d81" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "60884ed5ce3aa21a3270ad2fd60214371f396cd4c5b1e80250194a6505f1cac1" . + "253dc29c4848ce90dc6071ac8091c4fb481feef42a8e332a53c9a411f70ae6f8" . + "5413c0f0bcc929a892fe97191dd88ee09c72ab083edb6904bcdc4f041b20cbb7" . + "206e310ecaa6349aea372e7988d0efbb0bbd9e259381a1e9aa1588e91d77fd5b" . + . + "9d05d9e7acb38bf566594a148f99cbba3f57748cd2449bb5da2d1401081cb88b" . + "1a023d8e0bba4c164bd2a181611814cf07a80746c7a67d2f14cd2243d6bc414e" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c94118d45f9d65339537e9ff8ea1e70820d95e07d61e28fc7d002c8878efe5f6" . + "3583b5ac100f80da0012b8e9cafcb60d31745e1f9356153089d7c3a318f06662" . + "640f9144dca2e1afeae0eb1b84361f27543c0251d136c489f65fbe2f3a0a4efc" . + "366fcd34ea16d44dcfd262cb9267e74afccbfd1efac2ddfcd750757247353f5f" . + "1a29fac2afe7504db63e5f4f8274dfbc5236a5d568b52363a097d8a58d1e8c9b" . + "47c757751c9a4a100d67788ec2723730b3dfc4f4916c7e29fa3785f489281ebe" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "5d6f4dd53d63f8884fb09a0f98013e2aed9667b03ddd5bc9bdba7bbec128b3c0" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "b455bc396ffcc9f768a83972923ad5a1f7454fec3ac162d623933e34d8ff733c" . + "39ab4ac2a70a4ac0fe0e1f53bd6bc5b783cd842c613d940d1f624b1cb302caa9" . + "dc2f00df510feaa9b7867e0d533eba7b554cdbae91d599e99140c25d8e7fd76a" . + "c048b987e50b9725ca34a347ebfd17b7aca07f1a8b78f1bb92af86c4dd5efb16" . + . + . + . + "f6763473e9d40fa6db493150eb81b6c138f94f93ff787918321ec57512911e42" . + "274241fb8da022b31a0cd73d0bb271229c6f839cf8400a756443f6e5abdb1090" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bcc3b327c8044999d45879d47b6e59d85fb0a7529882def400556ca892b16934" . + "4684942258a8518a4e6a3d29792499af47d111a447f62296c8efe954f4b11b46" . + "7f103e61c754d1ac0fb54470b2780067ae176054866ef19912a6d1fc5d523615" . + "494f792d3643e9c3c3c17d733267e7440cda5676e6e9bd0b0f96b3cbd3728599" . + "95868c53d51a0b248390a4dfa38e372c5c1405ff3a7733165c23534e2fde2d18" . + "d9bc6447e6eb92266d9783333bf4d318d666f3f4e66393cbb305f5d15048ce0f" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "8a17454333c466cb65bdf81a07cd56ea4e60b94b5086290f7f86ef527cfac0d8" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "6af4a40b9486d8c98eeb5b97652032eb300628e6fae605fb1eef238ee9c9dad1" . + "840e87e16a9d1557242859d211fdfeeb0bbf01f94ab9ec42645ff3845c7983b8" . + "52a4c1f97f8526fb03ffef19775c5eaefe352e1ea1482c23561d31a07b25505c" . + "84df77b3dbdff684b5488be2aecb6900c81ac3ee2b4065fefce389a47645ea13" . + . + . + "b2e1feb1af6d1cdd89fbba3a955ed84f6d8ab57d038861ff85f830a6d8cf1b33" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b2c33e8adf9dd8771ffe38f98d13a3d707e3e285dbe3c6816accc400a63cf4cb" . + "4e854bf475d057945a92e6b1669a0fae6193403f410bc9adff075d958f04b398" . + "f6269c03037f2f500442afabb2b9c91c67d53efcfd708d743a4f8ba21cee4c1d" . + "c1def984a85a8e22afd6fab3456b7c06d178b5a0881aaf441f999569cd0628ac" . + "8071bf59e67bc5de5b6fac1f7f6900a968b33127ce444335e6cb524381344307" . + "7de473debca44c11c87e5bcf99398ca3162d47dc82dd821f02687fbc96a6e89f" . + "de913e2b042f1e283d7464d678c5562361dd49285cebc21edb83dae000326011" . + "150e8375a52724aced5759c2aff14d1265789b95b6ffd150510d30662e4c4945" . + "ab687ab047665c758bf6bcf6e6381eccea3dc51a2c4faa320f08744178c0f074" . + "753dd235a4314f885f4e2d84bcf554799ee4724a6f58345c003449a876a56a81" . + "1b850e416760b128c59bb66711b09c426b07de370f2563f160af606565be3727" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "b1f9392fddf4d43b0453839041a246e9a9fae53bdebe5a180852aa48557c558f" . + "455511da39b4b39006c104da70b42133a129491bb7bf51a63bca57b40ea188c0" . + "8ad46b8225281d66799ef6efad65cf367f7799b08c73d057dfa70d950a0ba9c4" . + "d0ea0140193f6eb0da8093fe4004da5b81b2f31d5fd99efe844d3975e7da808b" . + "6cdfe21607d155110a80ab2575ee517e75f931ed6542915e079123f9a4556f18" . + "6dfcb0af61106ce016d7a5456417c9aaf47e671fcc0b45486c732c4d44e82981" . + "daba3d548b1376410bbf712c16bb369774249412f4b014a90964557f988e7ab2" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "d337feb0d5e56b533fb097489a1bd6786e2a459936aba5d8592a36ff02274a4c" . + "b6b2f54844a2217fce0a4cb2a674f0766fe1fe307375dc5443a46917b7349b61" . + "6a66e914ce09cec5c9469797f268097fac75957d4030b48fe99e6e7050fbfa53" . + "0e2ff46cb585b98b67d1f2589b91493983eaef1c59a7bd0a067111cbc78edb75" . + . + "87927e600faa1b52acb8a58e7d66ca25e8e2315c84ba18b77c502cf74126f2ef" . + "b0caf1c46c73810e59d3a4d3b08deb6f6e7d18f49242b398930c32b47151bbdd" . + "c0f82515531553900432b3b4126d335c6d02681f0d36ef84fdb9869ffbe568a3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "32655590deaf83cb8c1c8880f8e3d5b6c0a67aaf8db6bd9b0a05fa840d040410" . + "ff8c3620fd16a437d65720cb14f8aa643606cd4fa7b49b45843a599b3287132c" . + "0131644822e6efea206bbe2ff302398b6d17d1664f9d7d1a04b04f4ab2caa303" . + "84297225cb706a5e2d4c7ed015ee5c5ca03fbabf6c22f1ee524e7e41347ab762" . + "a1004c6e33b5a7bcd1fdef81cfa7e91634174352c5d48947e428ddbb562ee2a1" . + "b224bffa8de336af92701340458370b6209b6a6b3dfeaaa3c78da128f0635ce3" . + "6705efe7eaeccb2efb1d31bc0d6a27dcc9311f7d36e72ec7693598372d6151e8" . + "eb5dd926ca2b2d301be54bad4e6b96f799917e45d20d4cc1f99178c3e60e2a47" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "29a1b4e7da6aa4fc7d3bc60924f606b15d09ddde5fa848cd8cfd16bd57aead94" . + "b2bc29800fd6aee4f84545a5ded09cd1b5cea080b5b646c850d86a0a4107fcfb" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "d6b49c4f9b6f667ae96069938f0fa0242ac3896067d75d302238bff7b67e3cf2" . + "e9ada566adf41759bdf038b5b0b0bfa2227e7745cefed3c6d82d38ab27210829" . + "97e7441cf5cabaf41a86f814ee4a2d022bd9558b449e34217f055c0d5bb33c00" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + . + . + "baa7eb415649a4fa995586afc7237e99005a4db04c1a25b54ca21d8e2f8e8b73" . + "52fec181fde65de0fd0ef9526a009e2192877cc6ab87a06aeee39601c80c7be9" . + "3dfe93d26b51920b5ed15b2baf2ffc5b61609665d0674d8c927dd57db6b288c3" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a733424a63985540a1ce70241ef3049386c6c3c0534a9c3905850421204e2fff" . + "a733424a63985540a1ce70241ef3049386c6c3c0534a9c3905850421204e2fff" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "4edd25cfda0877496c99c46cdac0d683297632c8b9c6c7c3fab1851b8a2d61e8" . + "cafa6bec17551333b98575562ec88d2003de1aba4a38c8e3eb376130b409b76d" . + . + "a1629d9ec5c5f68c2937644ac4f0ff4e484da2000f34887a3b525c70590455ea" . + "9f3c36f1425cf7295776f8992520cb278300ce6e54f74188432bc84163261488" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + . + "d59c2ee504a59edfbab0d9f1e33ad3ea1f1d7cdaa2a8eafc93bb6aeeb346f3a1" . + "6f9907f851455c12ed0f3d0dbd081ad9f6c5dcda7036002db4d4bed774f424d1" . + "6bd0926dfd15946bc9aba8eb759e15dbd64f8ae50f04e0720e6f956e50a32cc4" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e8590f0670de3d39339ef6586ac811edab57eb320a3ac416bd825ae1c16a1957" . + "f783738bb765314ff82a75cd4fd7604b01e23d2559e29942b40c43b8f4139cdd" . + "cd0e48ba309f49cf8fce4bb93d11c7044f65959863b85ba7c46dbd7556b1f59f" . + "237bd1b1be46fbfe584bb37886259dddcec2bac442b3046fd668fc1a106eb4ce" . + "3e1623b59e6172b4d832df5cb9f79eab1e629cdb67237bfe76d5c66aaf494fb7" . + "d3b3606d31e47250dd37f956ddbc58d4f8e6829045d88975b1f38c063bfa445d" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "2a38e0fb2e3f7b559e1a6a863a80b99fb42c14ed1e7e1d1b09ffed807c8b1274" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "4c225911cb5521eea7b4ba00bc52f07468bf6634a8d58cc34313c981f69b35b5" . + "0a2619c951569e7c424ee79df848b05f6b10882cfe561d408c810191da7536d5" . + "d3006fcdb4654832d72ae96ba33e61cb97dfca6d7fcfcbb90ab9fec552bb966e" . + "7bae3ab544b5113a4b0839e3abf6d4347d4b21dda782d78944160f913577e461" . + "cd421a372ae1037cdc7cef40b5c053160910b29ffd477e310953ea67974436ef" . + "1a43279ae2fc6dc01948c91fb19d78fba66b344e2b2a8e098952795966700b93" . + "62a053567aa960969b94765a6f024aad8e3f9199e465997e0cb41a5abf94b0c0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ca35eb04263b2544b4ab7e4f8f409050fc0f5cccb24bff9a702b19be3a008ef7" . + "189815f5936c9bae830776a035b9ca19806f2d0a31a5bf8f722372139a5e7069" . + "bf46be7f003ba8566249e040b197a1fb069ac9c10739645d9dbdd18a3368c805" . + "ecb21a90f60e2a5dfd677dbc216b064b00899df6696e83965b523819359bda66" . + "25a30e9c3899dbcd359bd580b78e408c10867bc37aec12935892a040408556d1" . + "84ca0fe28516044e8a2aa832ffe6ce22f97d4fdcddbb34643d2c58f077c2d6b2" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "7f0a8be0adaf2f9396f0e3c3188dbe24093e1f1344bdd6a54134b888a44bb5c6" . + "5ed550180204cf32365a771f870e22f169984bc068b894f27a52ffea18b1e768" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "45ff962645cfce746ca9d6422b52ffb62b3749b613fcee8c133b674e4ece35d8" . + "6959be871748f3f1c78cc560cfb4e7c229cd24060bd3475ae1a9a1aac5d5b1b9" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "ef8c5f90e2a529b3516a1f57dc5ad8e2c384898aee82714e90f03b9a23fd71d4" . + "89dea563e48341738e2f68ef08382a2c963a0e978d415a52eabe6c5593c0fef6" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a296157db8c33b1e54cf241efae53a59986f7dac4488c9766c40fb3cfcf9c6f4" . + "a296157db8c33b1e54cf241efae53a59986f7dac4488c9766c40fb3cfcf9c6f4" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + "df5daca3ace3ef14589fc05f222f86ac0cb2b2e8fbc0aa5f8e98b48c0f0a4797" . + "7feeb648bbac0fc6d1af5903110e50af8fe519497b2f125ffdf32f60b33c8773" . + "be622b0b83c684a6b0232e9462a168fb192fe766e2834f23d330cfb1aa82f6ff" . + "07a9b8a69302b48c0215f813c7c0347f518b87922cd6b458cd14ca12325ef403" . + "9b9411f439d7634734a2f1bf472fe180ae84b3b2322d366157fdb5e8eb7656a0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "66a2c266083d3c7e117eeb83a7b4a6389b5b6ae2f370762cd94b28fed6d18bfd" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "e5c2e788d6aa1289b8f2f9cf38b912c486054161c779f4ae187d84b90f8315be" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "9c55b18879d31eca0693e696f36a41c4504c8c2a98ef1501caddf8b5cf78d611" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "04c7a38b3d4332555f17a480a345f8f1bd9cd5c1e0b5f29dc59f21aa911d9aa3" . + "04c7a38b3d4332555f17a480a345f8f1bd9cd5c1e0b5f29dc59f21aa911d9aa3" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "a1ed3ccc6390b79364012055994b3950ff602876335f7916de735f3806a06d52" . + "1e7a626ce333dc1b54fff2f598903ba814efefc914879f6f172852038cd89b43" . + "512bfd10bab01f7d1551e22b4240dd327bded3ffe218b18722376d6ee68ccbb4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7775aa742e8cd8af946f38c33067c9f638b8b46801003004cadf00d585901e63" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "b7abdd5865da96e6a04303f24143b58dc792aabd5e0427c787780cf0900545c5" . + "1a0feb4c34881199d6e67145b7f55c594141e509cf8e6675db2a390f89c757cd" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + . + "73e422f03eeb0b70c3b08c097398afdd12b4da7a3125ace6e8ca46e63d208f2c" . + "c1080b60c2646a838362a0f984f7f12d35691603f7a5641bbd5be3ec8610fe4f" . + "f3cf99964b3cba8004cfbeec187a06f02867d3340c2d43d0b17dda1763bc4485" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c46e6f9d78546be7f5c0200bb32a1b4fc646fbccfb3c3c4e800640b5f5f876ca" . + "c46e6f9d78546be7f5c0200bb32a1b4fc646fbccfb3c3c4e800640b5f5f876ca" . + "97e7441cf5cabaf41a86f814ee4a2d022bd9558b449e34217f055c0d5bb33c00" . + "7fe442e61c4b0bf612855bcb389223523721a1dea50a95d50e80a0813697b8a0" . + "3a66415d073ef9abd85953e5e2d063d964f5e2094dee823c6a34d6637986ba35" . + "46e117e5346ddf390281da65570d37147f2088ad816cd890d9e9b56ccca87a5f" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "d5a640f608941ad2897824d9bffa5eebda7f40f1ddaff2c5ce8e2839cbf11e98" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "1b8b48f3ce529af6e94118b7a50adc14d404eb86a909204681e9576ee9b9760a" . + "c9fff76401c3799a97e93bf848b31b6e6ccaf2ff155ee1aec84e5651cf7670d1" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "c9ec0e458c93e8ecb8463fbd4377f166b81a997ed7bedc3c83c2a860810af45e" . + "9a41a87184bc3f22fe06041b0dc62b2c007580f88db0e5c75381ffc7b68ebe33" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a5d43e12d011deae3278420e3ab7f8afb475b052c0956b6e41d7df497cfa8e63" . + "2745924f29d6abd7581a65f6dc692eed0f2e2604b8c76d1c2e88b1a9469d7d01" . + "d01424664c998d5e5356b8569fe667c4ff4cc882f336016970589f6105144561" . + "6181d32177a6a00ba606fbfdb63b54589a6e4172ccbd84971c68126ad14d6e6d" . + "56dea180ce0128b6623ccec6f3bdbbe53661c233022ed3f987a87073b2d805b2" . + "cb8a856389033ec5997ce334572b2cb2b5df8fc1c7c0c8bc888115fe4dc82f30" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "5be8899671dcf38c581982d56595e576a9a9bb5bdf0ae657de409becae8f7e2f" . + "c9e6e78d27a19c5456fd1e74c1006a84ac547e18b28de0b3583ea580b3bcf569" . + "d7bc7203123b56bbeb1c0b082e7ba0941d9ef46adec4163416e52b27f9c83672" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "c72ac3034c7b8244e481579a72cdda62f446c6fda088fb6f6cea63b9d4298e72" . + "491937bf97bc4d7332090409828635dc1a9a576c6e54865ae8ebf1ecf5ab7199" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "4b798cd3465cd40eb662a4d48c2ce8e3aa78017a0183a80a14da1f4974cf7547" . + "eb5f3df3014f377b73e1a2a1c670addafe929f91b440cccbd6a6588db68e4586" . + "5c7be7d6db781ec0a9c7c70f9810ae492080f21deb51b36486d8ee3db80fb7ab" . + "e177ad71c45df818d583457ab12c5df88788aa3e0509e0c5be36a7febe89c15e" . + "4334ccb310b2616fc62dc96a8ae4c4d3a2bc0b6f70bd140eaaa0ac378dd50ace" . + "30e990a961da0756e2115348fc769a9aa32e825fc9cdb9bbfc22f0503270800f" . + "1e1220bf475e684468fceca48a12ed539727d5a7606eadf1766970a21d929c38" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "866eead21b39773018eb7f981bee50340f8fe0b14959b83ab6a37b93adc800f8" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "75113d7f99443807e2a1f29c876d7d85e5a9b8bbecdc0c7960715e40e507b4a3" . + "c93cac2ae2f4414f8f4ba64fa2e9542a5370413f18c6d12e1475c683417b533d" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "528e092cdd2be43496846b5f378fcb146d125d81a1c777f6b4138dc0ef787187" . + "104565b50c1621e44982c8248b986fef97f4cf13d4273546d9059652aa5a55b0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6c66ac08c47e48f8ea3427fafb9f90c3c2b0fb33d2bead39e2f0e8dcdd6fd019" . + "6c66ac08c47e48f8ea3427fafb9f90c3c2b0fb33d2bead39e2f0e8dcdd6fd019" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "54d4521e6195cbd4d59a0e47f461fe345091b8d7c1f0ff6ca8b218554a28c423" . + "43c50e7a6eedd4507ec70462da1dc39c032fc8084f147e01ddd7e846eacc43d8" . + "e93a80f80c4a9d975b683d39ac7a55d612716aabb3922769de8ebcdde6b0e993" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "dddf8658e0680a8d82f008fec6931249906022bef168f26e1b712d197c2a1ec7" . + "1d03f96b7fe468fa507dd4d82dc7db69bdd872b4414634c528bcae6d45960cb0" . + "75f81925a9193cf74ae991ea13d0a06b9bfd1e9a55ba536a88d4d469885dcb49" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "9ede853c08709660b532faaf37dfda4612f6ed7d00ad72882fd5c488ec9ebf94" . + "2e361e392658eecb31243430ae64e8a3ee41600afea9925897bef7565ac93634" . + "8035eb9d479a21b3bfdbde9f64273599d5b5e53d63de6699e810d9dc59287d4b" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cffebf9fbe5736b0626d1727cd89c10b704828d29e4994ea5b260520b77a0245" . + "b75a60b0d7b20caba59a485668c68b9c5c72038307606409012a81317842205f" . + "4189fa2d076a3b871bc9444f0dda81ee5f705b27d1a50aaaedb0964890788a0f" . + "93f096d07f62926b3f801af9e5b0b29c6049475becdc40ce16500dc4246e9080" . + "12fac50c942070da0cc80009755d2ef8cf1e5d80fdef74121c091bd4d722b9c1" . + "b83b498bd2889d53eea6361af37128d55dbb4e442b7e8373227390e5438b7171" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "91c746fd8dd077fda86661912259b1252a2fed99df85e115b90e82fb799ea21e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "6983285b5affe9ec3081cdd84c4ead39ddfb4d6ed0e55aac0a9d049f4cc598f2" . + "dcae5d791bd0e2091a1de29f2fb8101079fa413d007e4372c22a5aaf0ed5821e" . + "f640b3a7da52de9f89778eb6162b478b8ead5794b33dc10fbd208b25648c47de" . + "e3b4b2a6181580c56a9cefc31144aa67c86e94834b0bff372ac44294f147db7f" . + "ea4eba0a50b1c4a08bca299cc88638b171f0500ee72d7cea147904e7f4c22692" . + "64ec052eb264844f8ec97de466fcccae7449c836fe66b7696d8701ca16c27a09" . + "a97c1d2514d37ba573c2fe30a80cda429316fbeaa2023ef5e04403c9a66c0c83" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1b53a8fdf15f73eb0d7342065f172eaa20cc1d3c2ca05f644176b013f26ef986" . + "2f3f09697fc543f6c7f92b358faa53ca71ffd7fde06c9ad374236c63790c47fe" . + "57076e351b4e463e6b838f5631defbbda24514cd0b34f84e329583821d1968e6" . + "5516a3e6ed1f3107e601325aba06a06ff8e72c15c60f4c5546698d86fd6f0745" . + "222ddf9898caa85b0e4d15bfd87763fd5d5addd4b8f03ede5a910caaf44f33a1" . + "a94aa359a53014aeef7045e92e370ebf5f02a64e507ba3e1794717ac4deaeebd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0417a85f877ef71b2846257e3f6ba0055b41a949926f0a6eb82377b8a1bfc792" . + "ddbcf52271034453b49d85c3ecc66332e89dd2373f4dee22a48954df37480066" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "2ac0c4a6ef88b5dde93acd5697f9122e3ce9aa10d1d9b093b889da714a00734c" . + "3d8fcfcfb6bd762b99d1e355a57664481c663aba6d2f3dfdec14b1f73d82802c" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + . + "18f0213c2df610ab1a26535698df57d1345316191b6f9e2bcccbd782bb8cb945" . + "47a740bb308c927c6e69f639d86f3ef686949c825cec158eb4e62c6e733a9359" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "478b4fafbac9908750b08a0ab8799bf537c81334fd0aa04bc3cb5eed6ed975dd" . + "478b4fafbac9908750b08a0ab8799bf537c81334fd0aa04bc3cb5eed6ed975dd" . + "bfa9d0dae50eb4f97cbc9996254fe7d1d91810dc1470dbedde798a3f982aac2c" . + "9b6eae59cd0263373e3cf2c6cef50f1768869b92d697a1b1fdeed6ad616ac144" . + "6108789a9022a7443d8998429f9c2ef5de9502d755e5b0800048e328071acefe" . + . + "f316b92d973a38075bfa7b1fdd66398e12a42888c29410a9e5a5c0e5e59adad9" . + "b68b6dde97fe3e9cb0349e28cf80c48970198c2e1d0503c4960e9f4f1dbeddfc" . + "79a9d6efdb85c7f86e4a7007f9a082cf07adbe9820c0163e8893b4290a00a5f7" . + "bf07bef018b7f81360bbf15e5b7acaf3616c0e5febc00d81b9c3928a98288346" . + "d098f6446bb48ec9d864a290d02a09e29811d4eef8641566af9296f02d993281" . + "bc7c7bc0a4bfc020d28778c8d1b059cef831d8bd3acf6da12c500ffdefc12c35" . + "b883a02b502512b0bb27f06cba332db618ee92c410af940f7eea24027a236661" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee498452fa2f915eb1e91a696b107fc5802bdedf398c8b3195cf941946dd5db0" . + "0f73802c4b18df314f4c0a362a6ec63750e8369d2799ccf4bcefbea4049bb378" . + "0a30948304c74a5e61ec20afb1e29bd6d59f3be2f42999f543c86e98e2f017c3" . + "06b327947327bfcf9eb206379b23bde0757811dad9c13544ba57c2b5a462a622" . + "207066916177336dae26c7652c962d5743066c2b2cbbebead95d91357e17312a" . + . + "ecbabf68e07fa40ca3e72c3436bfb512f430e0d0c81130a785755bf34ee73025" . + "d2a1fae05ca42be984f6ad124b59415ab1f48c9b87f7732a2729da3309b714ba" . + "20de977e6912d60f321142413c1d440cdcddc0d4c1500fd724785fc5bf6010a1" . + "96ececbc347d7b3c2657533b305c8165104dcf1bfffa38c76c9ab9ff4b403ced" . + . + "e15837aed2da6cf712e437006462d5b97b3d380134d530ad577b087f25176b8b" . + "3ac6281e623b637ba4133e920dbc1a573e43ad3f12e96142b3da3294e1284f42" . + "f7028dc9054d1227b4ca2f9a1956c722c106d985a72b68698c67c3a5964a9435" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "83c029f2b16ab37f12dfee20f52fbdd97d03a86635602c8d0efb9c196cf1ce30" . + "e156ea134f05fff6b33f4c5eae8818f6a181edf6fc55a227d9409a75b1348c00" . + "78d342df4b813a59b68fbdb7f2b565ce690fdea47ad307459d3193da85833423" . + "eb0c5f613af52d78b26ce937df45db3dd3dd5942b68f0a50dd2f74dd177c8851" . + "27af9f0075706fafcdf94815f36e6153c36dd88b20aa0d5d17bbc0785932ea67" . + . + "094b3e8596c0a7094936c3d2e34db8a28c52566edd3bc2d4e07ebe4ec30880a6" . + "cacb49156f059688f865854208052003886d230cf24f4a32307274624941a3df" . + "f83a28e6c07b05ff54c5d87150a186632e17376032f27d813076efb2474684fa" . + "da7c60928ed0f5ae3751e05a98bfc9f2373630953ab24755715707e2df7b2dbb" . + "59f98da9012e6c1da364fe0c1010bed39e3f361794931252bf1ba9ac4b4c9c36" . + "dd0317962251f945c737bc71a1e3a4011c8f7b390250fb23035951b371b532f8" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d637d6c5b7e7d983ab2ef623766288aba5b36e1bde95fc04f9f7d01b9664445" . + "2d2f080b63ba1751cbcda117cfcc3f54f0ff9f50e4a04aca09277f5262a81c65" . + "d88408decad29a4b1d3c2d68ed95c11e9f3c6b12b1c3532f14bbbff69db7784d" . + "4710ef33aa653e7be4d5b0672b8221696e04f4b8c17f29403897f11f12d553ed" . + "af02f6e0b65f1d97c48205c6e56230dd9c7f796c760be5fd16f7a407d1bb8855" . + . + "a33770450a17b658f690fb4ce72817e08c1f61b3192bf45cf385d8951ae4a59a" . + "49b61c46508e7b4b3d4f70f37dba04bb604aa7ac4dd68a8679af2a58e137834d" . + "6db8b00f3a88f0c1cbe094c569914f5bde07ec1366e68d4f3388cee1055b7f6c" . + "49c26ed06c543b71573914fadc4a80dbbc3bda1913b7b64b97a7c2f902080dac" . + . + . + "2f6093ad40e0d49128964f14a8e26f5160c8fc6f815f58ba83df34fac01d4867" . + "d5abf219f6f1924b939aa1d6f3aff0c7626a22f0697240c34e280cbdc4fe05df" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8cea3ca2be06d468117dfb5f8cde485bb403706fc311271feb41afc6c66edc75" . + "0f87e66ab6e33260ef7a50f47a71f504d540b38a600f59b272b368a7fe3f8d84" . + "5ed2c7ace8a785bdfd9e5a1b459f7fa40cff3e5182a62f74b7337b73f393fdab" . + "12a6c8934168ed9a16ae8eb8189a2c5351216a1387c0791e62b296d276fb4c98" . + "56d6dfa6673084ed8eaf55973c008bacdc86bcdd273b9c8d4e5fbdd25ba51005" . + . + "081ece6ce2c3ac244272f93b4a69bcc487642d66a019fbfe7a5f24550a7f3c55" . + "9f79fcb856e49bf22068afe76786d4ed5651fc7e4fbe29894fb8d00ba7b8344d" . + "78086e86ee14abb36d43f0e5a5eb00babdefdba1ba624bca97e776e4f23dcc84" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + "620c40f28eb53fe99aa005205e0b081872cff37d77f6aa2f1b9f2c9d755ff03d" . + "f84f50187d1944bb7d1f576454387c326891b62103c9850399345c6e52e7e8fc" . + "66383c65fab158306412889c6bba374583ccaa9fdeeb86107b44f5071add3c41" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d109a9441b2c44abeb09cc3475f8e4225b50826dcf085730484539d2959e7210" . + "d109a9441b2c44abeb09cc3475f8e4225b50826dcf085730484539d2959e7210" . + "a7fa4fc556aac955fd89a46f2f355d01316912cee1d7c31d0f6bd9e349886b79" . + "34f875aab802876cc99663e6298b78b974457e7cd81193b457baf8aa46344a2d" . + "bd020f767df72fa80926667212b74b5caca5e071c936e82b095d87c5770cc46d" . + . + "708608a177b7c868a1f2531bf77607d9b37fe5fee836ee4813b262e01cc55e53" . + "4a7b9c2b47fc1fcbf7f844f2ccc94f58fff43e0a9e9a90bb5e3a95a4a81ce4dc" . + "e7540ed45f18ebab30c81c892bda228ff9363c3f0c6c1d61e70c0915ef55d5b2" . + "3c064fddb27bedd42b9bf1dff562e74a155158437d3749a8b2a3cdc9f307b5d8" . + "d74c7358f4d18f73f83c9828e699bf667a379cc096d2c9d975d3ec5d8bc1015f" . + "586e9c04d9f53139d80792a1fc95d8d8746488b614601c0b67c15eee2bcc3e73" . + "27c554184daf3097679dd0a9ec6994450ce5048b23b2c4659fb1ad86e525bcf3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e73d91c26593eacac33df685bd8a193267b65bac1d3d89037c38f2ebfd029041" . + "e73d91c26593eacac33df685bd8a193267b65bac1d3d89037c38f2ebfd029041" . + "9377b0cd1ccb7f12204ec96970eb88c5b4b212d2e231ae41c556fd591c4cda08" . + "ec9524786ffab08feed379c7e96d002d15dc769aa1633a7fb235eabf36a04291" . + "3b69b3ff7b84141b1f7d55bdde7996644e2631daaad6d1c3058428cc917b5ee5" . + . + "41216bf5c3065444e4bbc6535da0ac1da7096b9d8210ef9ba3669e6d67cf19cd" . + "92bd0b44e26c25f89ea1824381f9972cec1c69df7f91b86f3cabf2175f2abd07" . + "477804b8c631a79663d643dd29be09bfd0b574a292fa461aa2908fe3cd40538c" . + "272d48f07b1a465f707d0c2e61f193b7f5c44d9f3266c55b8050727417967d8d" . + "8ad35e717dbe1ef4de1692bfdea0438fcee6b4dbfc507df8cc8e23186fc29c35" . + "f4af1526cab1e6e60acf4fd7e0248e1ce07093e02d58ddb705db81837cc3ab8b" . + "423f6e66ba6188dc3dea317d012beac0374938ebd3490c9fa8f38a87dbf252b9" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d19d8eb62eed04f992fe5e93a62f2b464e1b78c18bc519f42f30cb2f449d0069" . + "12e9f2cb08bb0c12d1a27f09e819838b6beaf6acc1df7b9ac27f32a5ddccb863" . + "3128d54f27d000b6d8e00894342704529972e959f6b97514b3fa8b3977d81195" . + "12739c3ed2843db739a7bbe5ea704a3cabffd964da662ceb84332b197fe537e3" . + "ce7e93adababf18672be1b148f5e858c9460f45b74661fe6cbe7f184043ee97d" . + . + "8c3c360c829aaec23ba5e1717d83a31e519b00f226a21b500b124e829df0e040" . + "9b618e101cd0bea9f3f2bdb53305f79a710ffd14c72c2d245dbdd02924e4324e" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + . + "9b95039841e8c20b7daebc38e3e60d9fa3760aaa957c9ced88e11771c02984cb" . + "d7581eb39c0184ed3a5bc5c951da5e53248ee949316f608d4f97c9e0d2f673d1" . + "953818e063ef48610d46b5ada880b056d7420b0f246e0d502a55afdf76a8620e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d3c1cde42ad89f738680e996dfc3986f5b7c1ad9240b225f859b714f4153a6ab" . + "d3c1cde42ad89f738680e996dfc3986f5b7c1ad9240b225f859b714f4153a6ab" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + "905f7e654624dfcd7b6dc21f349135c2b968cb90c40d36269c9be0740989b987" . + "29b3e3626265901d3cac4e6dd62c056b8640e6eb5c23b03300ad83acdce1dc17" . + . + "9cd25f507f87dd9aed39d1e06b9632b2faf47ed509583a36b36f800a3c685ab3" . + "e60b8e7556dc776e6bce19360a1bf6609283e5d26ce4057b4f942681c4626e40" . + "4cf6b5480f3a772a9d68682d10a367f1d5aa797ecbf0d3cc1df210585c1907c8" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + "4ad7d02e89e0148778d9ca1518790e155bf0d42892b177434c810eb49d9d98e2" . + "f48c596fd1c83ffb4a12520ad65fba443a16c6943c7cf5682b0e8252796fce69" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "db0e832a5d1d03732137a42407327326225a71adb491147cfd96f3fc7ba087f8" . + "28555bb14a31a0b6c76e5f59dffd917bf71ff4c7ee1cc4be6a5a45abae085fd4" . + "f71fd5b761cc410a2d2e410d8a7445603ec124745c365799a8f39525f5337c66" . + "28dd15c94d73549d37361ef54670bd7f866d8aad1691c3fe384b84554d4757b0" . + "d1b56637e52ca83890d2da495e92031c583ed9e551465f23ae35678c0d99cb5b" . + . + "c9f2f30bdcfe3356d0124f6620d100376d98dd9ca5b0628c092b97a7f4870bee" . + "902dcfc37607225debaacece9be6d057b582ca1c91149e53f58cf43172635220" . + "dbdfd7f10cebaae71d266219d1eba2a3a049bb40a2ba27d798249cf53dee5fa7" . + "0cc6a5ccb75e8192ae8413783e66dd7c7e5c0f521e2ccad1704a055cad1c51e3" . + "21d1a1a5d1c7019086807891ae54cdec6cfb152cb9a448eef1767847c9c53a10" . + "d822433f054c47befbfe0f959c8b8fc63ab2ae3165d64b67396763349e12bf59" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "492fdf706b477e51a4a44c6f0e7168a3843f32667a787aed387e300f24c9bcea" . + "492fdf706b477e51a4a44c6f0e7168a3843f32667a787aed387e300f24c9bcea" . + "5e1c82a355b7ca98b7892ad57fda051f519cf5386b2c9c6ec321b8d466bf7bae" . + "dd66c15fb95d1d46d4c754f11b5d2562f6b972cd1f254dcef593704eee63fab1" . + "22ff976e694385ac3618518b12e41448b5b24f96c72572b2f70ee79459a2ee49" . + . + "8780bf9185eb32b2b8b8721278832cbb54276a92354d60d7e6b54309173ce004" . + "796f2c7b5e522db97ded89fc39b1af57a82cf34c6d954f7ffaa3a5335879ce6c" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + "73db25f8182b6928d00f0b1fac882c8d4bb3c81e35afb4c751bdd10d264e3043" . + "ef4eee070fda2a2162e712d7e65ae4821c768de1ec0bd6e29cf915684cadd6b4" . + "74ef0cab2291654633afa93a71faa738325038721056611717fce8044855da75" . + "54814cca62046c4a31d5b9763dadbc69657cb9e39ca16d76ff4beecfdbb79fab" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "458a7cc11cfac1b75340883be66f3ecf9cdd8435fa8a6d1c35babcee61cbd14e" . + "458a7cc11cfac1b75340883be66f3ecf9cdd8435fa8a6d1c35babcee61cbd14e" . + "f4b953e614087bc04251bfaa0125b710d2cdb7f698836a5a8dc3fdb58c73789a" . + "1a1c3b1e87d192c1cb466469b9f16906a04e935a696735f80719d48beae31702" . + "fc350ab6ac569da526a0948ba99fe34d6471cbaf6d6417f080f1270f01aa0f5c" . + . + "5e0aa72fc5fcd41a0b5b500d5b6fa1db11ee165fb2431b04eafa4363ee7137f5" . + "0deecd23c2f46be625510af4b3a6fb00c4fed771977441ef6f31c3f0fe616243" . + "482e99b44affdcfcd08d2ed4912e44c53931d051bb6fe9207a586aed4f3f16d8" . + "b8e2824d705c7830ffee6b2c4f3df53cfa1810122afa1080d344bf2a9e82fb24" . + "4da1e007a945dff0af39ce772e311f8c068e2d777df56886ba6192f5b9d2e828" . + "e5ae68732ff4fccb5aeaf7d6b9860fe57dc8187b0b56565082e0e8a54df58ce0" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d19a905631de9cc5bc907bd826087a51300b7d5f585c039ce214f67fd4f44ee1" . + "458d4c83c19ad27c3a61f4a3059ba5929dafcfd807d6759c44f3d5c071dff624" . + "c7c9e2b3749c95a8df26a7c879a65d61ce193f5f69e72f32d6cf43ae43a15d04" . + "60b8a2a73d673d9ff1ba9b7a90e602ef2146eee4e8e97f3f8f971c1b996ae925" . + "63d02bc774b845eb6a3fe4e8c128bedaf8d8f46340d3da12f67aee39a54e8eae" . + "8a7650d7fbd06da2a53fd520131c5c92b058dd438bb3d6ab229de1951bec41ba" . + "1b1edfc733d50f81a4fb227137223b64c360aaa6a271833575592a02be0d66c8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "8e7b3559c7bed445b01b9e26543eb8a8c467e58544935d171744c06071cbc784" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "efedc7bb1dfa7a947e81e29194595820c18e8047ba8393ac06a2f74b610b964d" . + "a6b508d2490341121e9f3d94b5a3c49ee9ebf78c6c3fd3218680f973fe1dfdb3" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "04f768abcc5cca8b9f9cbd0876fb29a7a875fab7566a0136e82a4d25336a00a1" . + "f84d78fa194e6c74e6b57fa6ea8a940798fa09ad72b522b99bde1a9c9be7e41e" . + "d83b7512aa69a81fe0e9113e26db2d0a1b17df08d4b91e29d9b291e6fe6c6263" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7bcdf3c3d13d776cf0ba74b49c474b0f88c61b38b2ef0d370b72008b7fe7b18e" . + "7bcdf3c3d13d776cf0ba74b49c474b0f88c61b38b2ef0d370b72008b7fe7b18e" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "5543eb5d5c33aeaf9ed3f497f133bc809a960bfb16ce89b75aca31546f74b146" . + "601cd89f0bfbe02be0612a4f16167f9af3b9fdad673cdbc7cd45d8eb5cecaa00" . + . + "3531c5d6ef24bd03bdb0e694476cad335f0cbf5f643ee488963f60eb73c0725b" . + "04e93d489aa74edf627a5cdf3defaa4df63d311786030c22f32102d263232eea" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "fe18d19b23496f9ad76bd24316a2a88e33a19dc6b00d7caab79934e5cf7787f3" . + "75faa28e6c5e45b71756a7571c7d52d8da76849bba708b89c04ded240289323a" . + "c19d207311aaf3fd13e086f9bf3b8dd621f16bbce41df6b42474ac1d7c887be2" . + "1f76a3b7a380d1599da419c64004d9a98197a568f68a9f5d093b9645f26ea9b3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "613a3fe1f24b6b59bce384893ccd92dbdc163ee653e9d602a346fea774c53e2e" . + "2d251dea49a6c40008157393900170eb62e979fb9cd0f91c12c3b26bcf9de3d4" . + "f318f6a995a2f82213f4e64615fb3618be458db5ed8dfff26b9c13bb099cfec8" . + "2bf29332c5972d63ded066a4e5a15c62240f56654191b5400f2109ff8493b19e" . + "5d0338f14437909ee9c519c8342e3c8e2c62adf3f55b67c13f60f51df44cd5cc" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "2a7d2597d29f99e4c8cb04092a4b38d34d065775a288b3f271abc3828d163928" . + "85d87a9e90477699bfa9a1101e62c9d58bca73fb06f818b2de573413ea00e1ee" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "5bd06795b7b72b65fac32952c0ad7da16281665d661f926de11947eff5e9b337" . + "ee0fd6cd179a38a249640033297d9611314bf8b50dbd88015fe1592f9da186a7" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "be7f6dc27352cee8bf0460de0c86183f236e116b7000b67559bff8e5ccb2da9c" . + "dd60075103f47856a72914b218b43001e8d91087537bbfa1cdbcb90317ffe3d3" . + "b81ffe126d03176ac229913498bb6dda32f185a9f1d9eec6e70ddae753c9bc11" . + "410073537f01dc33359a1e5b8bc6d4345e1e1edf60b5442f855d5026a796ee3b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f832b0ecc7200635888bd92f506febda363d9eefb84d0d6eba6164f70d6d5a4a" . + "a8ef8cee615d6f841d2b42a7b6da88aab2fe91e8fea9e894277712c5eb9a5b04" . + "804392f87becfaec4838c6d4a550a92bc5b09b0866a1391c38cc7b31057c05bd" . + "3c41b08d68884709e14e45e8db4626907ba8c8558f109902ffcdb3d1b45bba76" . + "fecd2c4b9b718c9171dcfe527ccc99fff7a6b2a406bc67094e4a41ae0f8e43fd" . + "9890f2a20208f934bc8136b9931404581779a03f577dddcf064fb3a32bd9f37d" . + "24a8fb43c99ed4682b0018dd32f65b5564bbc975c12503634871447f93eb975a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "1cdc8110f87154dcc5d28ce9f98f67a1f0406774b01a0d3acb736fa8480a3119" . + "0e78452b48420175bda59944d3367e2c359bfab7f925e069f994453fdf2e9595" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "ba620dc93cbb14ca85c80b929d0d2ed87568d6f16610f7498ba7d5840624b0b5" . + "6ac0117b3aa69623adf5038d3f45e1e4609b5db42dbd3208836b292250b2f66b" . + "744b79f180687a976be4f98c6a65f0f10056d3494091dc506734e86e4e891661" . + "2dfb4967d65d7182f5ec48d9046ddd8437f3ec988330c02068de74b64c084bb8" . + "72226057870a47b24b19a3bc1416bea7ab9914c705e2b0c713c74806c71223f0" . + "e7285dd113ff1e322789928911cea741d911976271700c4193cae5a3f34030cd" . + "410073537f01dc33359a1e5b8bc6d4345e1e1edf60b5442f855d5026a796ee3b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f91a53182eaa73fb6ddbc07f6aa2e40fedc744b3bf0baeadd249e2397e3b2693" . + "f91a53182eaa73fb6ddbc07f6aa2e40fedc744b3bf0baeadd249e2397e3b2693" . + "95e82c7860ebdc32d3961385c843749c1688a7dc403a8d554cc14d34b375423b" . + "9dea5db42f8ba903bf9ca6f78ec77da7f8919b9e37b4a9c6eef2a03810805ba2" . + "fa3e3a00fd06e5b06e7df3fbad3c18c05723c12c7c876f6d691a5f6950cde943" . + "8c3cd580f83cd030b2cfc654e0e42234cece32ef7d645d5fb43dc8d16803e09a" . + "b313933ccb0f36dc4a9af5667484969d662235032d5e1e5db88aab254ca1953d" . + "d118597330e0c1b444aa158d109599ddb7799404bc77ac5e2564b335a8170382" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "40da2d32732bb49f71c13d5e3bb8f516c4e36840e097ce405d221f99550d574d" . + "6b4b97317c57e3352e254123f021b74bd34725641b8ab92281f91700892d8ab0" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "bbfe2d7bce7132ac8dd5ffe537a7452e4ba312fd224f7a860ec497c733961fcb" . + "5d060e783a67d26295d67ed9daec84ab50e000e7e707f4a90472c49100ae8d6d" . + "0573769400c68eb6f1b816e8dc76e3173b58e7549f26a5511b4b5fa10f95b65b" . + "f96b364db91aa1e659efd835d8e48e991fb43e8bfdf4158acf23c9b8b7d997e0" . + "72a0c89354c663b9d0a0da05a68745c641b99e6d813fcb05c73e07e9635bc1ff" . + "0243e8308a2c73bc79994f3ac61178b53a2e8620ce2096aa92d1bf60da91ef48" . + "b883a02b502512b0bb27f06cba332db618ee92c410af940f7eea24027a236661" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc7c104000d615663ac3d6883ee30f192fe35d641c4281dda23da8deb81ab233" . + "fc7c104000d615663ac3d6883ee30f192fe35d641c4281dda23da8deb81ab233" . + "1aa60c3507d6f591856c12131f5eb3b28eed039d94b5e7d20160e06a5d355ca0" . + "e1dd613f825633038b9007faa37586411ea4af7d67fe4e4944e8f67fdbbc05d5" . + "08049d7e73b18a769fe051c6045225d6f2782271506971a4f933e770035a3b7a" . + "e93a80f80c4a9d975b683d39ac7a55d612716aabb3922769de8ebcdde6b0e993" . + "c583d702a429e36eed17734403af7679847c1e83ff2081257faf2c7f3e266eef" . + "41b13e3e877d2b84e9bd30b4703fb0db7e495d76a8d0ef9d73c5e5e3a9d67545" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "f6c8d7cd4d2553704cf0a771da9d42358cf174af928d9e43e58b292f7c36c638" . + "7fcf9f557d56c06751e63f384229fb271787bb813bf3c6564e4f2b4a2e2ab91d" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "5b6b333b21b8422a1ae69afa520ec2d9faa79fef4621fba083e2f77a0f206534" . + "2000676f16c3a9b06922b608de48c1343538c504f0ff48186a1db4a325998301" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "2517797299122631d59877b40026bdfc22310034087ceff53efe6ae0770b397c" . + "7bae97e56326a70be01d85e7065cfa4239c6c62a193f4989b51d419256cb6d5b" . + "5d3b1840084a289bd7fea1c397a95f3a0a47b95c3e33549673efd404828dfdcd" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fd1244222923fcab03e696f5be1c383591fcc21a6acac154fbfe3ea23bab8612" . + "fd1244222923fcab03e696f5be1c383591fcc21a6acac154fbfe3ea23bab8612" . + "d05d01a081fb8faa4c94816dd64a11f6bd4928a5bf2ff55b4c25f8d707eb76ef" . + "226c2095af58fcdba3b855ee433d745361cfaaa9c0e0de9c3867eaf4613fedba" . + "679b8687c96bc228ad733c0525cba3b5547d46060f722e6cced4cc6d8b951913" . + "d5cd19a787e581a0ec017aae8f217992d40c78549a67bc70ffe997e5eb26617f" . + "e71f97b5dc1055632e75edb3b58ebcea0184431ec44c370fdbd6fec2c02906ca" . + "f765461ecdc9015beff60e9ea79f0997492b7a09240f787bd855d9aa687f7b36" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "8ee080a68f7327152de69e7aba16e5359f775e3b5163340bc1f5cee006e1a626" . + "321f784feabea0eca8926cb2e3af6e1365c285fc273060c15b366df48d522993" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "9e560816a907d2924471c863372e89253e17be39dce4cd9acfe7e2ed73bb4c79" . + "766f1c6d6d3d73635f5aa6bfad02f03e7749fd6540dbb2c42ee3e8ff98e20cb2" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + "94abf6bf8e45935c5cac4953f43a1167c4f588a9a2b23baeca5e8a0c9cbbcfc8" . + "5d16c17d81639f452a186db790a6f54dd3b135acbae8258906387dca22a30266" . + "a1acddb38542317e25116c8d91484134822814dad59d83f0062e6a954de9df43" . + "d848134fe21cb9db0eceeee7c85707b6a28d170cd288c78326d9045b4d562c96" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1bada8bca8f4342529a3e3068a348d93915f1cc2164caf4baf4f0caae0ef0873" . + "1bada8bca8f4342529a3e3068a348d93915f1cc2164caf4baf4f0caae0ef0873" . + "a31a1e3ab2eb2674fdaddb6bdd25e6819007790eeefd85f245b89b99c3ffdbfc" . + "6a9156e4c013062aab9354f81b3b5e147e5e824b6df4de780a4f3824d2ee464e" . + "bcc26765c1aaed79782671a6cdcddc3adee1abcf6fdea394423b2f64b5b51242" . + "47b46d713bf2465bd961f63ab0999364354d5a033e5b4277a7432384cb6b4a52" . + "0f9d1565859d8782d287a405f78c806a3a58915bb89201725361564c7a2e6a92" . + "7f0a8be0adaf2f9396f0e3c3188dbe24093e1f1344bdd6a54134b888a44bb5c6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "dab6fa2c3d396bf723c832ac2cf197dbfc007f0f403e8a5ce50efd248cc5e51b" . + "164f4e4f4c9ac2a75731eb3333f94184cc2496aa66f0021d582f53808770464d" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "652258ae608c5d0abf8a7d57700c639ad83dad0af04836bdcfd34cd0ffe389fa" . + "0802f9d7bcf473f7e6aadaa8bd29087518ba9184ac94fbd851b4d6c988595ad5" . + "74229443c97fe127264672487c9ab3aec437e8bbc1cd46771d5882a8c68b7d13" . + "16216d2fc4d093ef4690316e84eae65f792263f8e41eee049e39440cc596c60d" . + . + . + . + . + "559db6a13ba19fbe19278850a5bdfff046ce83ea5ff880ca3068cbd0a5f60a25" . + "0d377a8e78b5e6765ddc77c816796d6686557314de8d80e107a27657c8541857" . + "d848134fe21cb9db0eceeee7c85707b6a28d170cd288c78326d9045b4d562c96" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "823de5fdca17a62b412ccf2091374506a4de77d5d95775065e113f1936714333" . + "4de22d79ccd10ef686492121bcb07904e49ae9b47dac2516c9beefd5309ed24f" . + "02711e58ba9357cdb66bfabd05154187b5f8982c8df9fa6a32e1d5b22a73f14c" . + "55b5b904618c518c89e5e7b33c8066a9a32672d4da6c2b3a1cc3d1efd9b5d0ae" . + "bbeb8d89b2a83454f217b1f148d00408b979676470754f499c0a306c5bf0a889" . + "2f57ec08c8cdc1bd4d93090bfad573e9a7092509a6bd2f1510f1c7a5677f2a16" . + "21ccdc998ab9304c2fabe3bce22095e86709f1c241be11e31197b03ec97b9ebc" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "5108ed1b78a534ec36438a215fc09fdca42a1ba823fddc8fac181771ed9af4b7" . + "e77377031775932c5906c4aeae9aee2bfee2056bfa9e94f35e885ece754aabf7" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "fe7ead98c8168d5601544c251561dcf4436c25774f4d864f3dc6bde8a60fee97" . + "e64c48905e6459cc55056642c946af0d6151b5e27a10912e0bc4c7a5a59b8b7c" . + "ac59370b9ea079b24b8dace3e340c68754245e8490fcfd7af8d9456115cf81b7" . + "8ab84d3c57fe1f368915feb70685f5a52ca002801c5468951d11fc3cd0facb03" . + "fe7ead98c8168d5601544c251561dcf4436c25774f4d864f3dc6bde8a60fee97" . + "00239eb5112469ff6187686058e4a1718d0dd9d4e4faf6e01914cd368b658c96" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "692a36d49e4ab23e663fec9d7214f71c523c28a4f79fb6c65f0d48b7b6cfe78a" . + "0d93315423df2560f2eb08567d234940de9440caff65622c7f677791042696d6" . + "c1b29cddbc670b61c78e275ab89c81b70e8641f9428e534fa433c18148a91af2" . + "2f30447fb8fed15d72237ac0ff1022728dd7a71d3e99e156824734b6b6f3a19b" . + "07605fc051273fee81743171e6f575dfd21e66992e2c27f6027195c6af67f309" . + "ce44d3e62068e27cfc26929e37c6c7c74b12b0783f827b75586a00fbb437a022" . + "b28cb45d86357d18465cc49f27b28550347ddc92695f7bdc388a2c3a70e53829" . + "8a8e8a3a1d256e6e1129b4372880f6d5c8e5813eda8a2de8f4f81719d3395f81" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "34f90b1a3607e7c2f2184fdcc209a72c2432e34236fe2415b4049d342367b81e" . + "c1bb23ac45094e033a151d8197b9130e96e9f857650805f9a91cc218a1a45d42" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "b321f5b5c610f57160de074659fc03a828255eb76305a4aa8e77d65399e82b63" . + "a67c56afc6d4f8d73c6d54fb03e8f670f16642057b46c37119439884a9d5b054" . + "3a939550f45494d0cdf88dcd8618787dd67b523bb0eb705ca6b52a3a8b6aa2f4" . + "cd99cea8b7d7ccaeb7f60872418fa42972f0459314adebf2645b22a1d306b087" . + "3257500b31d728a2a1ec1343db2034dd1d870c860abf9bed6be119df9a76b2f1" . + "be2311e639cfbd8c9f56caf184522599af09fb54fd59c6f8f6918ecf1021d005" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f1b43129b48dc2ef247311395c0b59988dcb28fd7f5970a5de0999a8ec6c5ce9" . + "f41debf2d692e0d469426e4daa26d11d03e4a9eb9cf21c6dfc41457405e0c0bd" . + "e35afae152901ee987695b3c2d1912e1e600c940632d158a31677a5a6dd76a9f" . + "45ab1c76367618a41690efcf606e7f3f2e3d0b5f2c3f41753f68164b23b4c334" . + "d8bad3616e0bdb7c16a561b0c676ad061a3676a47f773d4f89fca0db939c506b" . + "aecebf437140fa60a7260f4b490bf548c81612ebfe2b55488be600ffe69b2592" . + "ef57ea699eb07375ddf67184f1418acf772d06d49c0a9417e093bb8e55002143" . + "72394ba6ad82e0ef111ca8dfa769914d22bf3e9f0a406f8fcc079a6f7ffbf903" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "503c9ac9492bc35d997fefc7a723988d8a6cf3bcbb2b2128a620d04bc587850d" . + "ae3a9319b2c63dc065925a9babbda063b18862d3c6c0e1f3a08aa749edc26ac5" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "30e4ca170cdf69d415c5abf29447d61287997daf2fc23119078dbfa72cef7485" . + "d626333806802874eafea89e161c4b0073d7a1da9a4392d568ac1267d3ebfccc" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "e461c9793b26a4e76905fb8e18f7f1dcbac6bb6781e32d18baf01ea68b10ad3c" . + "a50c1cf936c3d46ff555d64cee51ecea9e040287c63d8da49005dc8f9929dc9b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d92c1a7591b1ef7bc1c54f7f08537d5116d8a186b218725d5f3e14f3952e493c" . + "d92c1a7591b1ef7bc1c54f7f08537d5116d8a186b218725d5f3e14f3952e493c" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + "60c3b0e0d60229633360145330c6930f980ada06dd08c167174fc280bb34c8f8" . + "e5703495891f8fa20d7dd59ccb9d03e9e513902e7f219b4853b1d8993bf32b03" . + "5ab7c727cdd79afa1fc112e1340e26b88ef61e3a45ef851791e4aa0bb1054c39" . + "15ea7bdf1f57f4fc341d8bbc08e01d6d251feff0ce8b56e29078b28147aaf0f4" . + "ccc33ad194d81ca2799fb11806b3c474001e231c1b31c69cf025cd86c7d71d2c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "348a7f1791374dd948da0b9f1d9bf14b8a8d59bb289a709b5cce0ffa6e02951f" . + "baf1cf430b22da819464bec221972994bfa70c1c07f11a28a75169606bc4861d" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "6b9dbfe08ac14a25dad6181c4989f8b34fccb5af3f3bcaf746b4620804e45324" . + "8061c636e63727d3a28c79131dfcf8d11c6122441d7a82eaccaf31fd18218c76" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + "ec5013a5c492be36a284182cbf346672fe7dabeb591e5d98829a162f4dea5927" . + "f689d3950c03f4fea86b9291e4e594718c569f8ed095fffba9e0aae12cf65ff2" . + "38f2ec814540100f9904970375f68ebf8e3af7a0504a3f4e6d69603c37ca1fc1" . + "13dba608d47d7c3bff8b82631741d1cc0ce7e361ee7ecadaf35754dba87d17ee" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "105c6e5057f8379c5054c6ba25cf4ec9981a622b96a425c3183ef5adaa262cbe" . + "7d2d33e1944e503497d8524c9ea87d9fb12634a3c1a95c7008a2ff98300595aa" . + "c404d5a0a0b824e6ecbf4a47cba7dd9308d0e4b258d597e31c2f8c3ff2b8b80c" . + "8d48db4c6ce9cb7903f59435f1649e1ea35f52fa769db878cd20b0b4e601480e" . + "35df8b7c99c2be74565f007f52ee06c6bdfa90244de0e93dd82fad63010824c9" . + "4517250599d087b0d109dcf732abd36ef65e161839ea367845574e12f863bf0f" . + "68f98ab294b72dc5cc0771a2eda9c92a367e8b526abff02ca96cf5bb4c27fd8a" . + "2c735a079aa2311ec9c438d3718d40fb031d85535f845061ede6aac52050f76e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "028f178014ebe88b15d89e795a7e87ae139ea1c81ed7495dba50ed9cee74bc2e" . + "52c34bbb535e7584d4a4d865c8e2c4cfef203ab9c0d05dd8cf72ed107f40859d" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "a730afd22963d661862c41d4f8d6edf6689feafcacad9acb3c4527c796e96e94" . + "5a8a8e2b9009fdcbdd543082df050865d72555fee5d729f73ccfb16b6c7170bc" . + "36cbf80f9e47041ab3e20cbce0468f91bed91b9373270305e35ba66c8d0426b1" . + "3267d7dfcd1da0629873c0754c5a465a47ccdbac41e951263a2c8dd4721945f3" . + "de7d114fe10a543d49c0eea8e4ebde2588ac7aa31a3ca656028dd346253d140e" . + "e77645d6c389a67e72a0186f8c7c9feba7a69765a80fd957d782474c2e384f0f" . + "4f88bf35f2db14066cff60874aba912196bd3d5ab2e369a8f757d2170d3c35a4" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "84629c9ce122706c998ad3834c529fc65b86604417bc9a30bf0686b5acdf9270" . + "84629c9ce122706c998ad3834c529fc65b86604417bc9a30bf0686b5acdf9270" . + "cca5b40a332e7ddbaa0a16f94b9e37bcd5ac77c5a414083da239e03d4908c35d" . + "c1a43666f7457970f48b55de076aa4d2d28655fddb77f919641e9381224c0830" . + "bbd12d7c17be22e6ce748bd99556a3a9e79aeb40d3f618764e76f20321174cbe" . + "7f9b3261122f7af4aeccde0183ad6de06c489836159ef883c2163a0266bd0d83" . + "d475177e782af1286376c26165d7ea65688ec1e3d0b680a1d3df4af77edccb77" . + "b8e528b4e4bccba9cf7fef56d460cd95f1f15b373c9a90324fa49e4ef87b3a3e" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "fac6d080b741b2d0cbff43caece643f6d519fc33fd3b611b64c21fd38c1b0950" . + "83fb223e7e000c9adbf2326c470e50a23d622c2eedaa22826cbef64543ae4ecf" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "a95880c5e3fe2553454d60f264d4c7ea86f1db01b17a4c17d0508390bd35faca" . + "7e525db938a2d18a5928a569ae68d8d76b6f39b185a5384ecd0d85b95d4a470b" . + "7ad8932f0435d075a99e3a42f7a5901286d7707ff8ee6ad581034f47c6925880" . + "fd7f1b6a8c62c55f6b31155a870ea8b7ce0afa89772eca2cdc6eeb3a58a625b2" . + "457c6a4f2c7fcd8abd39f0ade3de97c37029de942b2b9cc92e3214ce47e84a63" . + "64d0e21f86c1edd5ae71d0e63279ead85a948c6b86ee216045d1243ca2960a74" . + "6947506ab38653bba0d2df152478bd6ef9e8bbfed4fb22e0dbd35ee252f5b5ad" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "af69cd85a294bf76f394bd37ee6583c7457d58a3bcba63fa65682b09009de3a3" . + "9e5a93ede81fa138f10cf0df9948919fb5735e2f98456d0de34c2c5905abd1ac" . + "9ac87486c892e78569e7082ccee0560d05adda16e90031bfa46df3b320dfdd30" . + "b119259f5b18db93dbe9b6eb551c66ea210801960a28c6d15764f32b82e72820" . + "b3669e80252ec8daefd8af1beffd5e528fa2d50e9fae021dc7dbc34767bc6b72" . + "03e6485d2154c7f97d4c20e2e362055c85b90988ac141c1093dfde2bee6552b1" . + "2205d4536083ce035c273f727757aff43671480f1b5c63b8de884eca2853584c" . + "a576624f39888c645455ad95431f28f2f8d9c5ed1485d2f045caa639475e5cb2" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "7fcf9f557d56c06751e63f384229fb271787bb813bf3c6564e4f2b4a2e2ab91d" . + "fa9111d5998efc5bab553170d74129147679e52f2c4b850394a58efe25d7c9d4" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "70386116bc5f799c863428e91fdd8abae17336a585f6436c7d2cc6c25b706818" . + "f60da0ca1fb2513fed33275486064034a929b8db9ca6eddd090bb4ba6d3f02cf" . + "fc64d33397e8d4890700b6d8aadb9f58d4ebeae0f17be8f500c6bd35ee6714bb" . + "02802c63fecf8a8123352d5b6aaff2942d77cc43a0b8ccae7e20c0fc4ea292ec" . + "9dad3a1a223bfa9575a9f1de0b4713b8e6e394797d61a4522d66e07c515c1204" . + "b15a69f1615327f35f8b8f8f98ad7bd65a02fbd774721943a620b742c84ca477" . + "79071115d5984bfa0ed72c32a7ddad2d45a7b883eb7ea4c9c65443dc9a61c922" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d60792c77e6581d734e9a81b1d6dac6b69c60af5172f415bed21c77320a14c4d" . + "2ebb04222de15890d288e188d3c63f341f70605a01bdb4595d7740c57f0e8528" . + "a83b32e7886b9474881d5616e0b2e038bf98920eac5110c4c6cf2c645d278519" . + "1fa4b99b0cdbf79c828f66e99cd1c183c7fff9abc99635a212c9a4991ccecb26" . + "1d815f666e8a745e5dfbfe82a4ce85f37842900cd5e8bfcf95311402768f469e" . + "58c8fe29d300a5020151738e89b4f5b801d853d174813eb9aa7425ad539ad64a" . + "e80b3307f6cbbfbbd70510d87e331aa87a0596fa0d714ff00ad97977446df373" . + "ccc551b02970003625fba56769fe7378ed12200600f238525b913d7446f3ceb1" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "66dc74764ad97a1d4d4eb7accea48803116a259598e8aaed725c9bfd48b9ef06" . + "ec1111c48d43ddb4075a3be510c6c5b2395c28820ee85fa54eaf23d172492100" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "dba778158ee830cf8d1119a1cb2cabe9dcbe4b54275f32c06001563501099c44" . + "675150e0611c28f40878c4322fe86efe8d7807d67672210916133e2d79095b2c" . + "7b46c496f852fc899df1a72813ea6842ffbf43966ed814850e86b6f0af182daa" . + "448f67f82a82c8a8c53aa41d6835b1652c5109c84a5588822beec6ad2ae65cba" . + "310ce2aa36f2c4e8d73f5890d1a5dc862bfa03f3f7d5e301dd723418d7ff85f6" . + "d5d201a283dd8617e80a3e07a57147101f0262164b9d6617309987ca9e03a78f" . + "b3ccaeaa4b4a8400b896ae614f8385dd7c757889cd31ea0aad910037b97b1b4b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b792d66a57b98ab4be378bc70599a85f00c58940d30072e689c6b5c4bf5fa274" . + "c8ca28574dae16182cac178ba6575b5685f74c8e2ce96f560d6b63fddf51e3ea" . + "9822cfafd387cd2c9dd630e19a6d634d21c79b6d7b4e0b2a877880a868c25a92" . + "ff1ff05bd18ba70d454a93508e731ddc41c73c7b2ac9b81be143f858e07db4af" . + "eed46649ab4af7108e2b5a32a24e9bd7ca9a293f69fd26ae226ee0dd2ff9ca9a" . + "25cbbda7522c30d3b6861587eaeae9566b0a12bee009226c4884245121fc01c2" . + "b3a0c0fda42f3d2b6a764c2435b6a7875121db2680f567847b0162de62130a7c" . + "df64f7b5c277a186ce58e346c8d049189d58411a829a638da7a1c447d0ade4b8" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "7dfdeac3b1299fd497b1c1cc8a8ed50c0d28e6a7961c2ed6c5dbce4544820619" . + "46668d0ace4bca0dd1c50c5a5f0ce4a06b0707ff4ad7ba2c225209bf8893cac9" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "7fdc74af2a5201cd415e6b339bb815a850be3832fbee7c9ffb6fffff64d9432e" . + "66785e4899a3ffe86409b03d672b68a4a72a86d972c775d4c93dc0b281a4682b" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "ce5cdc507e34e47a86110f11b9e2bedc4c178f5cc2c7bd47a9723c4ef5ac002e" . + "6e6548448c950b60930f2639242bd2a85ee14e152d6a5e16ea31ab77b290fe64" . + "b48c90802939d07b132f140a5367052f8cb8c2647cb172a890238a5557b42914" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "253c2e978e50a4daffedc8e0db771e08f36cb86bb951508bc40ae78431850a4f" . + "253c2e978e50a4daffedc8e0db771e08f36cb86bb951508bc40ae78431850a4f" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "68e49542f3f185b5206949f76be5887fd911c29d8d72646fce0db836112d34f4" . + "d4eeff63038863af49287ca9e0b3d956d602e721085dc8a5afdf6e1e42e433d1" . + . + "49a921fc336fb0ed90fa56a2257ad4e258772aa65196dff76e26f0173009447d" . + "921745f409c954a3826f1397273c2f85629637c2cde7f6d4e2ea1c47082f06c7" . + "3af7dfd521fbc1455346dc00c7f0c604399697e173b1cc12069b076ac29b32e0" . + "9d29ccdec4cc5a66f1daadc146548d930d1a6fa5aeae036ec6fc24efb3b06343" . + "016e9eb7d9f1a267678338eca425b4ae54e8df517ddae955f6fbf0ea2cc4476d" . + "9c6cb1115e576081a448303e532b4e3293214d7f22a2a600c17e75a933dd6978" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e4d21a444af30294db2a470fed5c4769dbaf2d0f681cb6400a8ac5268719cccb" . + "c8cb47bf11d500f117e60ac06674338ebbbe9efce170e806a914fc1991019686" . + "385f00efe7ff680279132437a6a5fa91a2070d11edf8782ab26db6e99c6f18e5" . + "78ca875d7630267544f447722d4a721ac735d737e1fc5580543cc87466f5ef1c" . + "b1cd7c3f8cb06bb09876a0249d66a03d40811955bc457e36d9fffb2eaf152387" . + "89328e72ae03df565d9d29bf323d302da3127f2bb1cdb07328e3e1fc1013b1f9" . + "f3b20e4a09900a09ed808ccf0f28011aff3416099f406009d5c5f8a0df1319e3" . + "9b21153355e1df42cf74558bc75b6c0ed3aac227180a7299bf161f07ab652667" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "453f5ab1fa31dedc8a89926c2002b772080ed8f407464448b13df228f3092cab" . + "badffe1199739d6aa76d8ec03b392134557d168e376ddcb58b18761d120b2f5a" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "26e4c08600bc9625564ef5a6477ec2f35f45ae3a9ac85dd9da1d2b10b402cd2d" . + "901a40b34c164a0f12fed59b641f7103c23ea3e92a5e6af054c6df884f2dcc29" . + "f75701893ce1722083bf062f127a524dbb86e3abde5c917831a2f484cdcbd343" . + "2aaf1314820c233e7afb806b71d54886cb14bc38a5eb45eafb925ec714e67bb7" . + "ffc76bd83d2cd77adc302ff7d7edc297a4d66bff4f27433fde903f5d02c5bc50" . + "f9961f296523f65231d79693ab20f6e0d87126604b43534a16cc29113448100d" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da6d0227bf032c25b86561c2f53bcf222c417b03d7ef6c11a03deaa7ee2a4b55" . + "da6d0227bf032c25b86561c2f53bcf222c417b03d7ef6c11a03deaa7ee2a4b55" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "462422bd62b905c43b537215bb4f48f32651a01d18400e1abbf8ce397ce19222" . + "5a6fa8b72fb7213af6bcc68c939f5de7badb1d67dd56e2a0fc5198fa56299cb2" . + . + "1acf233d4d7a3faa09775c569f51f5840c0809ad1a1e30c1a9f25b1a8788e495" . + "d0e616ed1a0a83a316a99669b52448ddbd675ec59ee8f55b4532418084eee997" . + "75caf5e8056a2125ba9febc225d36e11c7bdf557476f28d25a68bb623784ece5" . + "1257d1137ff075035df93e3b9954c7b5fd08567eb1e348a1a8d7f58db5848127" . + . + "b5b671b6e080d72e8d6963fbb4f8143831ca597210f01d2e673cc682b459e43d" . + "0a14aec62d02523a9a8e09326e05b328b2397264297f63e0b41429b82ea56015" . + "13b99e627bd5ee0cdd8b66281bc85c92a648898a0e450978bc6f996f50748f92" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e1da8d74f6986b0150bffb9337ca916cf02c008a8c2b2818e459ff0bb0f56306" . + "abbb1693ee2e37a522e39207672802736c824a8fda1bf501f664193d12ab2b8e" . + "04097e6c7c76bb45dfd7eddf70ed59af0e740d7d44b70e67d1d1fd20d2e58591" . + "af447ed2effdd248fcb62cb0817a798d63438f1f5cbccc7e2ff660fedf3fe28b" . + "6dda760938245b4b6b93972d04b76fd676e625dda3752725d69c141f403d7560" . + "cbb88a9d1061e99d0bacf2e86f51d2a7086ccf60ffb56c08f72379c858d58695" . + "8b02c6ec863caf027f7f5dd18e5cd0f305062cabde0c261101528cd77f081751" . + "d7dd09ecc389ed132ea09ff54065299f4d1106ddd49846c95ee3def3ac5e023c" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "3e785959deea23b165c9f226e5a08fc4839b0f4c3d4fcf629dc85823c75a5d37" . + "41a882f7c5f34e967f01ead56d379db8393345138af41d1c8f2c7cb4319188a9" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "350a9d28ae547c80f4a080698ed4cb9e1943a9641b6b60cb51bec0e0a9a50757" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "7ed60399eeb4444b3a1fe83209d78facb5d6cf6405d3d185da4148904db28764" . + "2cf5fc73dc2d6245c4ada35d15c88d0caba29f85d9085578b549f25b9889ae9f" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "741e0e95c63297feb6fe970cae4197b668cb13ad764f79ed2a7d146e32ed97cf" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "c143b90f051c40ecb5452ad77d848440b38354b2cd6524047ad1c66a1462f154" . + "911f438e311725696c92a6066d6fc07991e38c6472bae0b1f7f410d4ac8d6735" . + . + "63a8bfbbe18d4060906bed2407e59bec9769475545226c0e62a0c724380211e4" . + "7efbef4c9456ccf25467ab4ff48f702b0d1b09687cabf342f1d15108bb90c65b" . + . + "f7b68c1e41e3aba7c9372679ee262e0344d0e20330986cf85f757a6d47033fa9" . + "379a2649149611acea9da242fef8b50eca29271841bf980d9e27a3b54886041f" . + . + "aceafc47b63e48e91ff893500861e649550dbf04b843613bdf2b41aa5a59274f" . + "5954192ddf34e55fd6362be80708ad89b8cefdd7a490aebad72e2f8722049eb1" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c609e229bc294c301a710740fa3e22e86b691564d630798d07f4c1054be14dda" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "dbc78d93b9f7f742348dc6d756ee31ce7bea9f3ec4c1b08aebdbe1a1156d4a14" . + "abe5e45621205496f39239d548410b2abeb6441da21366296934820613558090" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "80b7c786b565267bf860ceda432b28c94bbff8c56a66ec5a953fca66d01c365c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "e45269f988e57153b5b3e5a4aa685dc0c06bf03ae8c93d656faa2929e8bcd451" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5a2e7329ac29136e7fc69a081e0eaaac1ced43d1eaa82d316cd9bf80ee214a40" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "de13344252339a04ebc3f76a87c453811e4d428b9b6aa223c6e4c2785e28461d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1269834b7cf4f83ae0eebddf1bd282dad6c9c0bbe4c463e9d40a325ad8c64a81" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "46bbd9c366e409fde73775d086a6eb5afb9e19ac9d915c8450dcbe3cdcd5babe" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "484b9df9a5a5780415b8f7a86e59da943f460ab9153d62bb56bb27b9f466b49d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "a704e3d9acbdfafbc3b628bb6a29c2245f042e651fe0a27afe48067aeba4ccfb" . + "88e1c124247dee6d575d54d41ffc93f35bfc58ee3c8a84f9c515216b4e73000e" . + . + "1cca3df04c30f45da4f05f5631eecd949620140bd08686db238d2f2a21cfb2e1" . + . + "b4e91506bfd54467bb5e7d4d9d6e32d8752c0f622e882772cc221d922562447f" . + . + "e4a61d485e6d4f90bfd7dfae9a61de6ae824f606e60a8615a6a5911cf87451f4" . + . + "a238e08f1835557ada76a47db952ab8a4d1a1cf80040e76a3604c8a88684dc9f" . + "0fae2c86f1a294256b7573f88e030c6be9bc4dc5c92ef3d63840ff486a4c5832" . + . + "31394a8a8be22e49be69225bf01f8cd09899bbeb8bafedc06e546a9dfadd8282" . + "faf3f4239e7eb0721f056082f26c3d7185fb519c16d0fb6c08b803ee873013c3" . + . + "0ca16e79b3a35b890e960faa46304d56242b8ba76cadde7e6011a8a1ea10e307" . + "7969de74f5c28640c9b8cf1256b642b770d38910f7d7e34855ccfc02e14b4246" . + . + "c40e60451d596b66f47a121f31331059b7cc384a6d15790934bf0c18e6248f53" . + "16374c4cd63a5885b15c0dec8d4ecf8defb2dfede6c6b3f5bd36f56ecc1d312f" . + . + "60ab68f6d0f2bc5e5fd70201a01493fdf94f68b6b53c11ebdd30ca2e6f1dbb92" . + "86f6188ba4589e0a6a4037a3885f39ebdf7d5166b146c90e4a2db12252f98e8d" . + . + "4affd7428998063a4d0d3a018b1eb59057825eed6882d977958a044b145ddf9a" . + "dd555b10b184faf25da390f94a7fafb2064d4b5893ccff1f594d53003f2a0c3f" . + . + "35134b08a39eb8c93eaed0634246b820a82715ca289ef9befa341991ca8454fe" . + "dd30d63c3b7ddc1c206eeed498b969c3563483d53993c7d9b5f7c620af96d455" . + . + "fb279a85b0a3e26e4f56d063893cee8a0c7f46c0d01249447bfbb026c8c001fc" . + "a1093c8ab80841dacff1b9cbcd972f1a028dbaafc711a46b86166aa91d2109f0" . + . + "944883b612a211f7609a8872506dda6d9b1fa5a6c9b10b7a194ec0aeed0e7c9f" . + "c96ef2fbf8fd3207604b2f1afe97987f672c0b124b317e4a1061d362f6af8be1" . + . + "670e26f2f8cc4de3387b5f14dae5dd549ae021cfce29c72e6c1df24fef2a7c6f" . + "e9a9c531ab0479f98f45e1432f092ba3660eb664b32f32767025f5c8a7bbbe28" . + . + "34f9c5c774a5c73f35286ae210013eaa35f32e469d0a2194e760d4c656da987c" . + "1a384d688dabebd62613dd0cb4b91344024fdf5053be1fdc77ab2e04cf5c9585" . + . + "a3216f37d32307f28a9e2e6d03f6253ed61d6b9c2133c5c4344cd7e4d21efde8" . + "93681ec141f080f2159f36a33952d0cc9f73d42110762ac37257de34fd348619" . + . + "0ae80eb430648ce3478a3927bb7b8934d2b1ccbe64964a378b681a5a67ad818a" . + "91b4e4001b1a415b1075759594cd67e7ac72d936551cd05a3ee78eae504c2e41" . + . + "8027c693e4cf0501d6ad72a6eab1dc29b53d1220f681b2719e91d18b5b6238cb" . + "0d9a7b850e294cb7893acaeb1b3f40ff9b1a552b4a2a39c3ef2c9c301e236567" . + . + "264de583194a12df4d474d2cba2a919a0484cf1795043e8e4ec39ded30636a27" . + "962d075c6493e7c6721474759cc02b8d2fc5a0c0f42a29be51d3bc091ae1acc7" . + . + "2553ade31ac808e903bdd63e6b5b0f360d11b697f16fb33028cf29903921531d" . + "c7c8f5b413a4065394dac2480091085a912f54751d0dcb2a3e7126c490478048" . + . + "295b6b1cde350d7e782700fc00dfce57e2fe1e8ab13b426d8882fddd1bc7685d" . + "b7d2261969d93a51c73e042df2d0cee55eb6bd81cb5949452026fcf5eb4cafae" . + . + "f2fbcb522eb7368137639ed31f6d06b1234d5eef4e9734d7d4d4acf898a16c3b" . + "177b4732de5e85ee892a35ba80d57bbb34a945e4033114c10b8ccaf2082d9f5a" . + . + "acd77f0f9f2b42f68ffa946bdb87144521b574a248f332007b9eab9533e22ad4" . + "67972f5b5cad7836341dc43e62b489a598f39809398f1f4f761b6c59ea563d39" . + . + "47fbec18c3f9c9a05c8d8df38d3abedead5962243dddb9f5f1e0bcd98bd575b2" . + "5f06260892aad3606048c6583e77bba5006b72b228a96fe20f198acb19abc6f1" . + . + "54ad114f56e61fc72635ad20446120721032cd3b2f6d60b8354a4f00125f3d26" . + "399bfe8980d27ffd048af14b9fb665e33e93aaf20a63614c402c7c9e606da330" . + . + "c29dfacd5584d41ef86c84eb7f270a425dff48cc9944abdb1623c84efaf17e39" . + "6ffa092909a0e7fc3f954bdeb0bac25924795ac8f0e93f8b1a6bcdb5c10308b1" . + . + "5f95709d8af1e1bb90a5ba7001bf42d3865e6e9000d949607a70ff00705f44f3" . + "59ab208227402c7bc3d3559609753f2d7bc5535545445817d771d92e8bfef39b" . + . + "2a819f7096def388796a8d4d4a32af389f291cb38755f8ffd0e6b3c2766e0e03" . + "bd916a041e051be7abc6333aa439ad52690344cee8541e625469e7aea51e3c2f" . + . + "1adabbe0942c2528d5f37fe02136a8546a1f61a9cbeb13064773e0facdb02033" . + "5e95eb9f7189c93e0519e47aae7ecce08c61186b347941cc90d7948c629b7282" . + . + "9e677d0e037c645b53f0f84757c0808f10e87fae4f627ae1fd746d4a637cf267" . + "a35aa8c100a87beca5499ffe3df68a7104ebca1744044d79f5cd7ec27e5cdb7d" . + . + "5856a48b7548dbd30b2e64baed0c76c1d0122e84d206f16bc623bd29cd5b5d26" . + "a6bec9c28bba3738e3d46e87ac8213398faebff5a311c960daa7938281039d54" . + . + "37288ffdca4c5811e291e2c8b1ee34f55c5d47fee706b5cd17fed630b8f96324" . + "85c237c776046b69ce9da0c2b4c0a2d386981d092ea76705a86d20d7342b9629" . + . + "138eb2f1f517d6994b4712d5001ed840579d249502ca001ee2e836063bf9b086" . + "40123c7d22acbce11ff9c24234819c9828fec9a9b7dca273b953b11810a9ec40" . + . + "08bcf15829aed3603d65833e87c7f1428f194cda3788e8e8fcf9b85cdb41146c" . + "21fdbdd66d39d349055b4bcf25fcacaedd411356b055f15aaf59eaaff75c5798" . + . + "a540a7598128349c60001a340ff5d025f6892bfc2c96f005e5138ed6aa9808d3" . + "1af37885c6982730c84f120a02508ba3a8d495ac7f8a9da38ca4aca3f109bce4" . + . + "6f870cb4cbfc0b0632dc672e1f5ab8703e03d054a6edc01c8cbca0f421d10afc" . + "01831e598e93ce79ecdb2ecd6c6f3efe076e4250745563f3936a060dc8495c33" . + . + "6df8a3e24f6c9504531a4900670100f9513b0c6c74dfb6a86c3d036a412dc01b" . + "45892cbd863403bb387cdd331bd126917729f060a0fb9b2329e4667f10f3b68e" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "153a8d398d14159d5493ceb262489b693fe558682f7d23d82b54994ea5976f18" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "a55586557dd724ea6176f910f5c2bc5e5e5f11183ad73e26045642f581576a79" . + "a72ace8df05c426d1e96c599c7c43fd2e9d9d61f61007e70f6d0507999d711c7" . + . + . + "2c8af36c0977f21f2138ff52f7fc66f5fd55553c6cf073a0e573b0e65e8354e3" . + "3920e3b1e311fcd36e8e4c4c332ba4c1a4cf1da9f326338c350cc16b53ab4456" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "667745f48f6c7db53644caea11d4d75e7214e2f7f5aa1e5dff191602c4bd9c8b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "971c0299c4c921e032b6b853d88e7e29916657df0011485d7cd010991c99186b" . + "2bbf6ea736dcb1bb4417dfc350232bda7b3efb918202fcd032b0c5a1b8a5f88f" . + . + "516fe0772b923de2721624e32d7563593ee6b22147d8290263bd2ed8678a1a0a" . + "eeed5a767be3502168fd91d49365d44cb9e160e67f546c3905091e47634b9d9a" . + . + "1c69bff37efc1b6283df2c10805dc564b1c0ec1d99543e9e188e017cbd0ace8c" . + "504bb54f13feed51d6d4a18107cadecab93050b95f719d192ea5fd77ae376dde" . + . + "38a8ee8832f5844041b227c28adfe129c1ddc826126213bd0a1d4d207dbb883a" . + "f535748a7c05a0df1d5090d8a9e9cfd686c7f20a933aeda034d03dd2855689b8" . + . + "5ded2cc2a0065fba57429e1629fa2243388f2e4f8ac377b572790121127b5db6" . + "abd4aeecaf184bf3b096b0fd878ec5072ea024b6a98721fdd6d1aafb7f3149b5" . + . + "020d5e2ee074af02880a0304c342712940efcc6bb6cafbdc629c7ee0cad719be" . + "a718310cd448a9366d28c0e16aa838fa29e3d252ea374ae195d6611228e57675" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d6f65513a928a5659ccf1b5f3a84832da7877b275c5b080df22b760b39210638" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f18d7286750f3bb0b4eb2926fc2ff4162218b76166df69ec7ade0619e6cac2ea" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4c30e691843ff5b360326a94926bf309e80c8e927ab1d803d0d04161861fb371" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "d4e80ba3689add33c0d6ba69d272ada893793a06c9ed7dbcf3d9f302dfb3e3f3" . + "903809f7649479a50cb3ccc68512abd27ad6b32a2b9fa38e84652e6c1d35443b" . + . + . + "e8aad040a2f9099944379c8f6ebbb2aa77cad963c45ab15c2f99dc30dbbeb094" . + "d67979f5642156b3391affeac578d088d1982b3e4a99b025f342421b2f8ae5db" . + . + . + . + . + . + . + "f2f2cc90d900ddb6c57c6c6af36cd9810856286617b5891b8db3e0085ab29ee4" . + "cdad610bdc56c96304021d0d745ae37791a0147202f9099aa43d81698c9b11cb" . + . + . + . + . + "f6462dfcda17f6a56fb9d5715076e07cae7ceda9bca8f2ae203ba1b4d9528dac" . + "34b22dd7ce2bc72e987159d8bc6045119f715ca5a505a7a5f6b8f4fbfc1f90b0" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "da3adc7821d15513f97cbaa19bddb2cec780b4b982f982c7f925ba9b70387db4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8975db44d2027381d50a98e7f32ec60e5bfec1a158d2dc5eeeec530330bffbba" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "580d8f3af3a9184b7980b881be72f119ef0ec04615a3d8d9e1128d2d50d1108e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "22f8857c8281a0f7108ec1eaf80f07d39b2841ab4c5ee8d1f226226559f41573" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "abd5cf1c021275007e4fbc886dd57061d7b9564a17e498b33b0cfed4acc8f9f5" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5898fd3d77373f17cbdc245551bb634036d3419fe4231d5535f6476eaceeb4f1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7dc87f369dc8968dc23942c3c3fdb9fa83c61d05d400e181c154a65286c6a330" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f7f3aa3dcc85a93d457f3b490560f69efa602bc755c23b98d148de7ae335dd27" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "fa52502c4cdc5d98780bdad41c59e1f92afc9454d5794932b61eb102014c7b70" . + "b9a9f15714a2a7af00637c2030926ce17919df2d9dc3b3531d582e7bbad7315c" . + "69446d5e9ffeadf97531e68d06eb34f06cae6056a10cf4f6536e7e0525615610" . + "8aea3a08f600998695295678b9a2fc2ce62ee8e14aae15853a6cab9bde86488e" . + "b96513c42f1f418df740ffdc04b65f09389d48b2bc3fdf1fea42604d7641a73e" . + "f3ba7c6d260d7c0074d0b7cf2e8953e49b200afa15740bc640fa0be1e7e71bd9" . + "0ef171023429321855a276c5df69d538fca4802484f25ad4ebc3d2e3e875834b" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "65122e90bafcff9b339f18d3d200f2de2a511568b29514a49b2b8a7f224ef916" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "b2472579c76790f01fe6a4c0a4082b00cd5160f3e5bcfd1bb850ff6fcf4dfc1a" . + "fe1f4acc9beb842be0a81dfefa11e651db54484b387f7eef65ad5a52913a3954" . + "cd2e6c3c19a1da3d064bfc91445d663386ce842305461d0218a81ba5ebfa176c" . + "c9e7bcb921a86661098061bb8d31bc3527821b290bc914a315401ef4d2b9c772" . + "47cf1909f6fa3f58175386ab19434647b3a38e870fcc1231c84d85ca0cd29ea7" . + "4f4895af40a3ba87aa7b271f4ef6abc8f4195c0b5e572153cb21071289ba7cb6" . + "76f6d698301d77c0fc68491671825ec349bd1b3e7a7a20cefd1f73ef1883a788" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "fd69e60b1fc1719546c9d7ac189d4d5d9a22db5f2e900778937ab77548a1c6f1" . + "eeab477efef9bffe559912c3ef70398856c1826aded69ccba1af53cb66a23d45" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "fd69e60b1fc1719546c9d7ac189d4d5d9a22db5f2e900778937ab77548a1c6f1" . + "72633eb322205983417bb7611cb0ee61233678fdb5b1ace898759d75961ce724" . + "255be0db0035432ea7dcdaa17de7c6c90648dda2695a8ca7dad83f499e898a20" . + "fe3cf19e1d749e2122e9640fec26c6dc364898759a502ce96e900c54a629b18e" . + "b1f1fc2ee574a783a1063f1fbe6ce6a4d4bb90ea2b7d6a238481a55b7812485a" . + "e75fbdd5f2b3779d20f29b15aa6a4fa7825eb602665bfd3f4a52762a45efc30c" . + "9a2db9f65089a5f8523a14c9ac762b8a94f13511c16d0400c64cebd50f59c2ca" . + "dcd92e01af1d36af6cd661aac14322ff5d48a5809c9b460a88ece96847dad3c9" . + "e39bc938074a9a8559a71780b6b874bc7fa595a788c39906ed22c9ba5637b668" . + . + "37ef810407cf2ba60c5bcc98267b2e674ae8df74369d2a44d5076cd41858570a" . + . + "950458d35112616e97f8a059661ae68ed7f760caf442c6923d4388038e76f854" . + "dc5ecd4acf1704d9f552f0d4b5f59589e27006ef1e46720325e6cd53c922b4ec" . + . + "ce856642de1da376fbe1e524ebe512e203efbdb82622ff7ace6ce389ed860a54" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "0640c8990cc539c8e5ab7b6f25199871d4981e63a1fa8b02e07dc721530ceabb" . + "0f27308c83486bab414f60486928fccd935404d8b8e56971e60977b51d3fcc98" . + "b1d470b0ea1ed6aa10b78a5fc68e53035d8643dcc0602b48c62c1761aa12079e" . + "e6a28ca5fcf7f69df7b0e085e8ca0a85fbc27a644787af2c7991ece3cd8d92b2" . + "71ff8b443e06b4db952f9d7d728ad308245acbb81e0d927ef6fe9b4cc84399ff" . + . + "b0f61f76b89745d0eb9db2dda2e81309ff6c34a667ba8a15784a751dd2af5383" . + "ad471b5a56f9d49bfb6168bfc6578cea237c4d4cd433f49f5ba980491910d1d4" . + "1ece421b4f91bfad28e165c4233020f30126b5a3dc70b2a86dfc2d317b74ccb2" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2e66f292c43f463e665686c54e17eaf60eb704cd94f28d3b01f2943de6b1d361" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c27c296110b064cc3062691e80220a9cdef904d3f5554ee576761cf7d0232543" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f83da995e2f71a584d57d25b75ed1c983a5c50e0c508cf4819dc6a5da07a9e76" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7f0f56bad2d14ae3b882d4e1bad18216858e2f766fea50745e660b9aea487a8c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4e822ded4a914d739bb522253fbd61d3e728e68b344d3d4d7bca002cfab402db" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "1a741ebc600fab23987f979b6bda3b23212ccf84d5f438f7c004c55032af5642" . + "6be0bb92dab980628f1f3e840b1de03fbf8b1ef95a8a7bf9dff0e40463bfa645" . + "9c8edccba4b832503608faac29f3b80daa9aa4500012fbfaa95c4145009cc9fd" . + "a0e2f9419e4b9c98d1fb63ae62db8ed0317bbea157056d51ba89309d1c817b51" . + "0fb2d96149e2c6ac2f5423bfc262d2635a357c7a356059576e3768e9e9d1f231" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "6be0bb92dab980628f1f3e840b1de03fbf8b1ef95a8a7bf9dff0e40463bfa645" . + "83015fa5755d76f8f01af41de36432e831d47b302c5c2d8412ab303e158d5049" . + "4e75dfadeecc294ffbbd950cdb8fe1780c261df4112eccdfc943822c40baa122" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6ead84460489482ee1c598f4ecefcfdff190637a8b86c63594df9c03f6f3c22d" . + "ebdaccc2b77a2013dcb3734415fae2bca36916d457baf4da552a3be6e4380368" . + "90a7c4202c3a25eda3f1e6f746fe7368496b302a6a389be86894e4d4f29970ee" . + "870e1a2fc369a0a7e15792a8000e56172c65d963f6689f909b74382593ded85e" . + "8b5531c25eb63ab5651b7426773c4197beb7dade2dbe4b2709eecd995adfd1fc" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0fe517da4d6c741094b7525e8e26d575064db2c5bfe970b48f06bbd7e9dc7b4e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d9b88b1b310c66b1794af5705713e1326b6d0a572d07ab93b9c7b5912a77a158" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f1564b9285b96e2701c12ad847aae654a50908d08a3419072cde068ae2deeda6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "fd769d05f867baa470fcf3de4d2cc2152fa4df387754a2157908a6740615ca1b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "792e93cf0ae0a58afac6644587aac38c011d6f5619d34c8c0e76465f0bf96605" . + "f8215e8ed96ccdbb8fd31b1b9f6cfa97e45d3277448cd26918a83d24a7307cb1" . + "461aa16493cd0bc39705d9b0b6b3dcc18654696b8fbe8f1ad2d4c7fbd0c25b00" . + "7099b15ffb212cf640fd6795da745ee115858e498553a29241f3b2e3d56d6a01" . + . + . + . + . + . + "0dbbf3d87217dc72118c3a28e8b7ccef89411802c53abe1d9459d251e256f612" . + "fcb909ef88e3282920151dbf436433ccc06699e95bfb6cb156b20d8891d9e135" . + "96d0b1d5ae610f274b85c0579674a9db8bc57e8c7c2d060b0bf9b73f85fc8665" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6b6605c8e79a774a669ec432b7497161c53d31530e1721fe0cfb4d5c991a123d" . + "0b215b66447d5014114e80b0c64fa52d7305306a75799e4241368e1176884cca" . + "feebc315edeb278315e5b5f52316ac91cdc8eb69b86836747bf0708663cda4f4" . + "d6a7e9cd0d3110185b14bd6d12cdb90a24818ca71cee4ef8a4d91faf5d3cb1da" . + . + "fdd2e47c5fdb5012435ef54fda29283ccc8ce5583abcfee7266c399532b73b64" . + "f48f4dc73ef60420ad92d5202dd3df877d6ef2eb06b0151f625bf2952bf108eb" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + . + "b34ce6523817d2a36353ed3c699b707fdab82e46432e17d145e1fd076fae339e" . + "24823258a7bb6e41de9a9ce8df8156b472bc13614548486bd36c746ea62b4cbf" . + "f2cf54a48e63021ca1d325a7885c5f2909c3067240741e6e8008dd3195419e11" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "4fcf2952ba9cbb9a84bb1b3fbd99cee3445eb8c9fd9cb83d1a807d03a97b08c9" . + "e274ddbe4e12754df50a5ff31949034473d072d7f07c9ecf2e41c25c94472a59" . + "f6c13ee84efa13b60a8011e739bec212460782dfd62c3c8b062b9642d329ee57" . + . + "8a14d322c11125fa3233acf7a1ed6f067db7673d88b76c197f793173df637014" . + "c4a2f6aa1f35e5d5d4d52cd3ae1d454f1e20bfcd257841ca44155328abb90718" . + "26687a68e88ac833ad52ec624a5b490d6a27f0e53fa5a22f92d7c55bc80d007f" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + . + "0d009cee7b77c9c67d9338449921efafacd5fe37419fcd3e64df7fd66d364fba" . + "611b7c8579adf7f9e464bf76532ed02255449a0fa581d1f796f9e57ba43e85f9" . + "4a8833e0e81ca7a59680e6f52fd7bd6325be05c671c6ec71711355193bf08846" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be8c494b3e94aa2a1fb46c9b01fd45d48884f106543db901d9a48cfc3b0c221d" . + "2068e957c5f9fdd4fd06759a3033fe2a849acaaa05fb6d3949df4ffe0be881db" . + . + "79a8ec1fd04c905fd092d6e2f335a7958850aaeded1df2d9b41fad6a4bd5d0ad" . + "6290fd599652d46423b4fb2bd95b7d3f50ea4bd89670dac88cf0edaed128182a" . + "1a332936d4f459ed4fb1bad993a6d62196a0cd270ca2942a1fdb99dea521ffac" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + . + . + . + . + "67ff780f3498d1bbccd427000b5e1704b8a1b7989164a04623b78827d9f1e59b" . + "81c3385157ac5ac3182ef9c9dfa1f6f2540779d07afdd7dfaeed47e5414b75fe" . + "05101fa0c4ad5971fa3d95108450163846ab332f5d6a87e13e8f5cbc14998461" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a321aefb67a327df70a5898a90eb1ed562e3efaa37f2f653e85962a8a111f0e3" . + "cab1655d0d8d41a2f1fbd8a409e087de4d2bfc57e42cd513f733daed73d3b4aa" . + . + "b94e33368fe50393c2828e105f34d4b5291ed3693d4304f57334e776ff995e71" . + "f1af9ba1773a18008b7319355064920f62847042d783fc696264ddd79160d206" . + "55b8f22ceaa0fc69d4c80c88c8d256f80eab1433ab55f231bcff6c5f9d79e9e3" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + . + "ec57227934b488cb7a0be050a2365f40c5d96cc848f99fcef1e0c62eb0bd52c3" . + "b4c301253756170f14924a6aa9d47d7b26a76ac909b156ec5caac62cb3454da4" . + "3a198a4272d97d95a4cedc59541dc17198af91367b3054252c92ee8bd41c8c85" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "63a96e94bbb616f134c7e2c28b53cb05ca60e4a289a84f1fdabbe2c3e96fb280" . + "4adedc60d45e4ab636612706ce057287bf91e040d282ffc6820acb623467cec4" . + . + "893649add2ebd45891a132d81783c0dda8035f1edad0f9dbaab3ba5157e526a0" . + "31fcf37b7d3815c95cac14b6f8031288dd07544bf1b0c100da054138a6f9d3ec" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + . + "56850f37ec21b38d378d39c27722d68e83930727f1f1fb2c61ed3439280bbe23" . + "adc7e19487b50aca9290adf06dfafe770578de0e7879c6cdbc749669f8c6ce40" . + "48ef8acc63774913b48f321854693f5bc6d9f67fd044e58ab9bd1873ae56b5d7" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b2d4abc12976d0c14bfba143559c92c1b7e7b7892863817deed229367dff8951" . + "0c67e4759626867502f913d7b4f92df1984bc1aa7f3902d0e8514a9b3e6e3c57" . + . + "ea9c9c2a299e2a1b38468f0ad91baa181d8a9f46b6ba0afedb5961cb8434bb82" . + "128981386b379ed4ef9e80dac82be8fb8c05e436885ab3bb028fc4bc7e0b0221" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + . + "e5e964bae1209eb990b658c44965d96362c0ec33ad1b75d36c60d8c4b2359dea" . + "3a2cb0494f6aab539bb54c1aedc216d83cae955754f5dd5cd2bd4be689f24c73" . + "c2d3f1025f9da7ec085684c1cd72a5df399c07397305d4079868b44f728a118f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a88a02a252f2631c7b4e13a302d317dc2083fa01651063b46d448fb9083675a" . + "8a88a02a252f2631c7b4e13a302d317dc2083fa01651063b46d448fb9083675a" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "54a34aef567fc5e22c376c0ecb083815fb9049d9dd27dabcbb7bb8a07881f90c" . + "bbf5f872ac5c3a1b746da18f1b91fac4eeb0d42ad2df731e309bab108ee64775" . + . + "1d3738431efdfb907ec2a851dea94ae67be7522953fe1b0e47edb24451587def" . + "8a83240991cfbcedc65e33e14434f018809b429efc1d4307c39a576502f354e2" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + . + "f46cde752aeaaba6b95902783bf5f59e723998e6deabdff1227203938e1bcbd5" . + "313294b2a9836c86b61549b211a1343d02c25577c92f52e226acb2bcc28a3638" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7602c64ffba9465b8d6000d064394d28c0bdc5558643f010fa43328501c3f8ca" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + "8c37f434c4e94e9f9aeae4058b783640b4286792643ed34a0c5b01671ea4ca88" . + "5eacd0dd857176dcdef522d678016e3b79d22037d9eeb1755870f995b64b7259" . + . + "c9345c7754911e431410011a401be2d1785e7940163c319f07886ad75ec9ea34" . + "14d321c01cf16ab5a080326033e57a8686f0892715dd78061ac11fa7c48cea28" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "1230865e29fe4f201da450437646cde58834f90c69380fd4227b927cf285e758" . + "85abfe66c7ccc559bb5442dd2b967aaf57afa3269432b263b0e7a996e44c438a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "06872e644c331d3c9cd86d8c4fc259e38d63d4ea6cf65aea9e01182d353a2833" . + "69c6a571e543eee17c2f5c59c509b44a920459412a1c69e235544e2ee8c50e74" . + . + "a5a240a4e5fabbaf522f34f6f0809a4ad38e26ce8713ef1fe40695197d49dd09" . + "a838e93e38493f722735b9600e3a24ddaa43764f12456f188cabfe53ea6dce70" . + "3108ea50e351957bf4fb5eb0a66011a824403be783bc16002cfe151ebd011b77" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "89e5b0df6e43974e98ded53b113d7b4d5383f2138a662495326fe87d7e469e3d" . + "8374be73c8c087878f08f53eab5c0226cb41b5408617e665f81b2607476cc0c5" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "75e11844fae6444ba6c7814ac789c61a9fd828d0c98a2c6e7b509861f3841135" . + "25668e3af47d2754488c16641504c9887f40549355308350c4a4335dae1c89c8" . + . + "5108e0e77c6dc64eceaf06d28a311e14561f686855bde6d1874ba337f0309f4f" . + "c4e8ee0166dc9faad50747f58a0aeefabc9e827673743ff6ef610fde12140499" . + "75f81925a9193cf74ae991ea13d0a06b9bfd1e9a55ba536a88d4d469885dcb49" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "c59156bb27a60be18819acd786dfdf5418309449e42a6b33124576084fcce3be" . + "2c56e88bb50c77369e7d6054e6d6fe69050079b8c2e62f6f7fc608317cc63849" . + "f9be1a54227a055bf4d8ca6e7a7a0795d961127cd5aec179566900fe9db9478a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c54cb29b88034c2dadb48d1952ad0275f7b8b66c554964ad716391d1c3e0964f" . + "ba45773077ea2d3f1c749bbaf5d7bfc69e5accc873ef44a27808c3d7c703e923" . + . + "de43b8be1176f9124571f2087d2f4ed45e90269334c772017e33c2237f89bb7c" . + "9d0a0e65f9da2537cbc58305a04f712835f0bb72a10842018e37111a6d87aa07" . + "f54bceb459d7ac7693dbab729d3e303f06c082a77ff74aa54d28451577887c69" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + "43f7692c3efb2917db25e9a36d350a84af711a6959c6f715ba21a88b8bc1e766" . + "a570d322e6e6e63bbd2f292858cb43f810801d7e3ee873aff8221f26cb8e7b8f" . + "60754d8071992edd9350a94f47edd309469ae31126df5845b38478e6f477b572" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9ae4d07785550bda57e854116847dc3b58aab96686f30bf8505b293b241ba905" . + "e131eeec978de9e0c4932dc7957639a27be66072e0bc48c1e1766cbc61fb17f8" . + . + "71dd31891fd426757953a981f2c136a1708255ed6012ee16fad2a428d57f42c0" . + "c868ece28525e32d493cacc1e606fd4712f4163e28ee8f101ed27ec90589c2e9" . + "01d60597b28656850786641377d5b98eac00f67c725452c3d2d130be1fbd7215" . + "4d5c9d932bc8c4a6850b7c38b78b1f395420ad314fb37b75488aee1975bf2dea" . + "6540a1caa32bb56ca11a766130c059ca7fa343552d0e282d0fae204a61df7bbb" . + "c3ce6ba459becd7dfbee5cbee74b3e10287f28326c1813c307469dd990bd20b3" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7a3079779debdba38d364f2df11df3b7afa39c66fe2e1b124c34820ee2e2e8ae" . + "dfe72821d7d8e74ef2fb9d488aebef3a437302d03a81cf0047f2edc712cf50ac" . + "66764329ae8331bfbc1666fae4f69b1dd72f0377e1e5bdd20df0c8c16e7aca31" . + "2fe7d6f87b5ecbae56e5ee28f5db619476984af8e7d8be6d4be026c8b6fc6018" . + "6cb627bf936873132d1efba0b68b140e200db309eb48f295f54fcfa1a4507236" . + . + "eac7b2428464b65445a91e5e5df2b358b412020ec85a97136330921034579bf3" . + "d79a7cbbdd7cc8dd7e2deee8739fe659727b0367148cc25beb2364335b7a50f6" . + "ac41f1d6870896e39c4c9c2580defc92c8a259ba598fe077a1e0971924cc5df3" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "a090269b7350aa758a40a27c0dbfb79b4022409d8eb731ad665fa05fbdab7cf5" . + "18211786d3b8faa1f77ac58bcd26a664f2de6e3c5a5c150bbed2395fccfbfb5a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f482f7c4ceec5cc188febffc130d80cbc21a29174be7121baa8430707005256b" . + "b904676230c68fcafa8e118ba7a21437e5060f19ad0ee938fe5a9d45e5495c31" . + . + "8991cfd5dad5cfeadc698d93f2adce9ca7d1eb901dcb638414c2d3b72bb3df75" . + "e868fd80f23642b912e3668be1ba116fb175f90c566b8b3e8671968c11c25eef" . + "caef7f8939854b5f95e2c6519f7b5d857fd853c051ee8e839e115005ca2ec226" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "7502c1c2bdc344e34076c218c60650c01cb552bd186ccf6bc3a90cc9378ffcf4" . + "f76e1872b7590a4fd39f04a3cf59c0f26ea60e367fea544e937676973c5d871e" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9225fd2f34ee8404b6366be933ba30d9f48feb8cae0452a8db5ea58125bb7deb" . + "3396f0b5b8df2aa1ec54f4681233231105bbc1c0e41231e5e949a50466ee5234" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "8fa33ddda00e37857f3b071e919d98138df1fe35ddd5f4479ad3e5de03cf2a7e" . + "9e18078884df6dc7af9882bd72800a7c939423d003f08378b8fd99818fda3a00" . + . + "429425d16109bee1801f5d71c379271e967740676f0a61d4a4a4e93d747f06cb" . + "55e1eb2fb59c8ba63e619af5022f27727a99eeb078bdd7a398278b4b1e3d56c4" . + "cde2bd069b5e9772dd4b75e943c2d4429d85eaa7c4987f8862a16ca3ed5d033e" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "ce5be8ed3fe51a50a78362426d06ab5e5e23ede614b4d2f538f87b1513ead614" . + "026ffce88ec573cf515eb228cf0307e7e5e62ba6376d6d8f53f7d753cdac097a" . + "001ef6f849d833ab5965fe0e3e10d559f2740e0184d008870e4436ded77bb7a5" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7ce057ec19a0fadc602e87eaa7e368476eab88a0e337c1092d6ed7a617634021" . + "7ce057ec19a0fadc602e87eaa7e368476eab88a0e337c1092d6ed7a617634021" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "2781cc63b4709a68aff8620cb7cb38a0c2d7cfdfa5b343e8f2d4f9f22a95d5ab" . + "845924dabdc8066570928d1dad96cf1ddefb6a1dc79fbba76d4558b4b48e05f0" . + . + "746ec6752dfe07297e75831b1494025b87e61f143afff82efef4b8b05d658cc6" . + "d113b99472668f230dc2cecb829a5dd40a17874a3dcb81dcfcd4b53b6b2c9abd" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "b613cbf8dada20eff4308a5be63118c29db4878d2a08e1d7a6cc935dfd9c5e20" . + "3a19b8f97a03f5d68a500661750eb5e921ae22e15936c19dac8bbfcdff611bda" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4fc993443dcb1d14c0a48188a89c6b021c55b70cf73193c69ff73982894321aa" . + "4fc993443dcb1d14c0a48188a89c6b021c55b70cf73193c69ff73982894321aa" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + "ff259cc6c63df3246aee3d289337cd0a7605088b98d3e81dfd103aced1b328ff" . + "da185e5e203bf9bcdd5dc7bebb9ce5c0f75ae176956793f22bf4032e5b90f79f" . + . + "283d1853ebbdb34764dc7fe4c1b15b985929d044f1a682f71a3e5e9e4d46d0ad" . + "af8cc5dac5ae41db437f14dd0fcf0af0acc71eab24ad8479d7c0cd05273666ab" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "0f525d3e1ac6e07ff58a848d04cf8ce35c00ccb4c27fbfbb9a2e55a04279ca98" . + "887f14fca524291c8298e5aed3be93567c3ddb745d6baf0abc17922b2a417a39" . + "a6dc0b613c2c75a060533ba718050468ff2ad90cdb0f888b31f34e37de773491" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1398a928981336c16c28c38a5a93d38a859aa92a0178166b818dd3349acc7359" . + "1398a928981336c16c28c38a5a93d38a859aa92a0178166b818dd3349acc7359" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "5f11dab3554379b4135dbdbb9ff572d3c27a672567774da34f848ab41667bcd1" . + "796d5115879b00f5af6d1846b1da3a1b63f277e83161af45ababa32fe7b94b70" . + . + "f4c946dccd50e904241a73b48077b5b58b63a83c74a45554faa145d867d7f713" . + "e395cf829d5bd3783e0c3b1828d791aa249451cfe7ea2bdc5392ae3eb551c570" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "a58773a303f5945f32c1dc84f828f9e0760c524dc94d4c3dbe6ec4697ef48971" . + "ccef176d4ee2821ef1fbc49ee7ed7f15d9ca2f4cb96e7b20b55d456d364248d6" . + "8b3aea45b9e8e7ccd7221fdaf40465271ad50d3702fa81c78a732acf6147d24f" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40d39f5210be56574e58743918437c01832ece6c2dd5584f583a4ee9b6d3e621" . + "40d39f5210be56574e58743918437c01832ece6c2dd5584f583a4ee9b6d3e621" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + "9ca87c0393cca2ecc974790e886ecf561b371e0e5db37c4784b8dac2bb7bf30f" . + "4d51997d112aefaaa568407f5d4427051460c6f8c4e8fcbb8ee0fd4ca606d480" . + . + "bae0083722e5fcf570a9435874254d3b067c7cea006767819f2b45d7b46be391" . + "595898f09865cd879e3caa3f658e166275bd827cfb9395f71acd0988238dc45e" . + "415adb6e34ed7227b5af245dc53d1162416bb0b8a0f7392197bbfb520a58142b" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "dcc877455e7de6765b1873c57f0660506dc5940ca89bdf84e6036cc8a7a15d9e" . + "101ffba40b0f929f8f91552595903c4650b503210bc6d8866439fdb4e92f89ed" . + "7887ee7521836bd4ff6a2ec2470a79fca0805312d85717651e720e35e5c20308" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dd768c02c1a2a5c45ab447d06c08cd12af31c072435189b5350b16e9463e2c08" . + "dd768c02c1a2a5c45ab447d06c08cd12af31c072435189b5350b16e9463e2c08" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "9c26cae03156c12e7bd9a617da2c12a472716f19094a38faed83a653133179d5" . + "ca4ef568ea92d0e40b239e29b9932bc71cbafb493a11700b10db7fa41604fa95" . + . + "1e83880bb1b7f18479d2ba5e46587d67bbe50b9ccad6b70147fda3aa3a99609e" . + "4282f24540f3b16a946036253b634ee3b75221f178b65d1d6c9ebc2b9e93f59d" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "c6d16da6ae4f59277754ef34ad9a39f78babd7fba3b29e8e46e65f5737139c56" . + "0cd69756d75847165237ba4ae58b675cf898ab4af94387fa956a283a0bb1f651" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aef0f44a476495705965d203d1dd19d4caee1b415e4a148678e281f709b74c4b" . + "aba1b4f3ec02577d5d59dcf1ee7fd1980b18676e389be2a494095d20ed31faa7" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "3b78fb67f752025cb8022345429ee4b6617e181efc04c827dd90474dd52e6e78" . + "fdaafeed585ff010c9293c2054dee7e979f4dee16c0ade6efbdc1c4f31a90806" . + . + "90009b1ed202df98f290e0f94d720c3715c41282ef44ba9059a01bdb28b216da" . + "6c0f6f20c91a9a5f330554f9139139bbfc39c13bef27d13476bad94e5ce3daaf" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "165a453eefdb593f5d1261eec3e2570b1e30303bf667eba93aa35122f8c463cd" . + "f2a138d3002237a1810a1b38c5e4e1f63bc00da467eb645f64d0f77146107ce8" . + "0ebf7fc609fd6c42e756c3fe316eeac26822c054e2add6e70af16ca3df7945cb" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8dae7e99b50fcefae2f749447988f762bcd2cd4a9e80d290c7a3b7ea25835845" . + "8dae7e99b50fcefae2f749447988f762bcd2cd4a9e80d290c7a3b7ea25835845" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "6ce8a16059c751815faeb77b974ca9fd8e9fa0efb3e9222bd925375df4b69985" . + "aaf2ea186ccb017de753c45ad3e7b70c8364cd019aeae31b0df267ecd83b31b2" . + . + "367b47c2a681ae98ab5ce7e57515c7be90406e3bebb88b3e161b215df768a75a" . + "d7c502266d2ef3db301cb4cd507b00b61c6e8908b405408dc71585c5ec827596" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "45def638188b73dc0dd111fd6a6334bd80bc0e422bdd649f629e5133fb46d5d7" . + "eaf73771fdc47b66799c9dd628637da65f2631e3c9f24f0c8624d5d0313b5045" . + "276f2f3dc70f3cf1fcae31ff31376836f80cdae382dbf8f7e26d8289deb3146f" . + "3779c371001342e62821aa072ffd7fee5f3f86d44b11dc462a97f9ebf2212c1e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "00ed86b17b1a18b61ac9e536572577bdd26a9482ee6adf585af1769a33da59f0" . + "79c1cd873b25302d56727728b442f950f0c524b6a0757a61681f053d8ce30309" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "2019ae60b3296830335b1e21a8f7759f95263ced1cb0abe6c2e289886707e54b" . + "d61d4c23b96bb1a2f83e7dc7c16f9f3edaf4e77406db4ffc553d4ecf1d8c1163" . + . + "03b0590f57d9e6db07d6f3745469d95f037703a63c34d10d2ea8a51c05212771" . + "4e2aa3c399a035ae7ac02f99e86dc476e41049738617d7d3a0e30f214ef32d93" . + "92faf599e07ac16fe2c0ad064117f72a7e8046fae1be4a46d876f16023d9b0f0" . + "56b341278d8602a6c4173f59160bed66e923d04c68abf2ca41347d52e5618fe9" . + "9253aaa01abe7427bf1f13b378eedcca0fb5dd28ef21931951689c6e18ca1f1e" . + "1644b784ec3cb6cb2e219ebdb7f0b029ee48b0428ae0be5bb5d9827799d42efb" . + "92b7885cd41af5298c4641f7d8c5fbc59110fe9919386e26f1f0bb8a9e8df17e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "767ad72593bce0210dfa6be14d8c8e276e15d9bc48ff11c4413fdb282cd850bb" . + "aaddc6982a7057dfd777e3374574f918e68f2c20c3283d51ac6e54de46418ed6" . + "394d34fec049c58793a3cfddc2459649598c594c7fe8ecdb9be349e27dd29577" . + "85ddd0f50d685ee40cb81a7664ec9a758b2d29cbf810baa8e0ebc9884bb7e649" . + "c7b1f1c3f0aebe00d708fbe3b8cf9a6f6164c2366759325ff5a1d4e8d8a496a7" . + . + "cb1412e495792345ad3556de289316846007f4b86668947bb1395c467cead133" . + "cfbf53183bc6868b938d44ae967bbf2aa40df496ffd1e8909ce6d5c05e6358a4" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "9b326c336a8ca7a5856abcdab1755379835266f7a578872fc9ad71ae11a4232d" . + "45760d7d0a8319f33a5fcbbf33c322909c4da869b3bb8e42564bb81c1c8db8db" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "665580d2624739d73e58a3cd144bf9df63cd9592f2469622cd7bdc1442da458e" . + "d6ea69b3a72c1138262047b2fa872cd24e314a970c7a1643995958b7a5ba4f5d" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "b455878568bae6312fd65e7d9b13627974feafdb1a1171fc9dea424185b72cf9" . + "be0a82262e24de528b222435b32374f50df6398a226b8df370b204d784f64300" . + . + "20273a2b0c667ca44c25733d28e4702c3c81b6674a361e8c2be6dd8dd44a06ee" . + "b121c07b06d00a711d1d7a9727ae4fb52884f711cf67cfce0c534f1a8a357c52" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "c09af799e6ec52ec4cd5408da7a110753223b7120ffbc81b7ee99bbade7508aa" . + "840a5b60ca5e1eae7190ec610eb37307840f080208b0b01807433231d3234254" . + "35b925d7fdbe4570de21f3762daf002d885f213b0f0c2f67e34f205715659df6" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7c3608b867c190aebfa03d9ae9f404fdfeea745523ec95c3d681f29566136b63" . + "7c3608b867c190aebfa03d9ae9f404fdfeea745523ec95c3d681f29566136b63" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "3e1182aa5e328bc2a2c68dbeb06a20c3ede2044349960f4b8bfafcada3b5cf1b" . + "2063d65769dc2316653551736d22083fecebeceafaa792d1a834f8c4a294ac94" . + . + "802cacf89d2397caffbccb65acd4c6276612f85d29adaa52eee0135db01348f5" . + "a55294e94ff17e3b5d3da7da6616b46c9afac536dec3aac2a7d859ada91fb060" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + . + "1a160935c1168fde492f189710db8a85ca8afcfb92806a3dabf220236eaa46a6" . + "226bed8924524ed1c5bb37330078783f94f4baa47a1ef669a18002ef835547e2" . + "c43efcb5640e4aec86f5470e327e20fb56f4f389199ca750c8e8872909ebfac0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "318f245bae11d84accd0e96cf3b2b6e30cd02635165f820fa7cd39e7361edfbe" . + "186ab62640ee5de5ac62673211f20998963f5aaafff77e9908a1020daec5d5d0" . + "eafc7d0e135b3c4f00fc819db03cf62e5b182ad4a2abb17defa3e79f1e0c440b" . + "77f673e1491f16e25e9f2b5ec5c8e760ffac64b93326cde4a839c070401a6ac0" . + . + "e5bf049c25d01a8397fe3d95947022b368613a7121fbfaf2c6d76772c27d9e72" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "59230627f3d5027f11baef30d1f765d02a684742b8d0087ea1324078480e156d" . + "7c287ba87c420f7d6d2fd1dac3bbbcec64ebc1b56d24a13178c06bae994cfc49" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f428757a0f1d3f12d20cb4b2a164652ccab77aa7eeb124fac0590321b19bc439" . + "4a2dd3ab5fb50dbbd91ba9a8a206a81ba1328e3e0ed92e27cfb5ea7e8799f777" . + . + "2a9fafce4b374196e0d36908cdcb1195d6ead47bf2427fa84082819f2642b21b" . + "1e2b7fd49dec79876a5292b852e5b6af4d78a05f40f511f743219059c6c675c6" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "21a044dd51d6300b5b8b0fb8f74b20df78e660e5b210f87d6d6dc338b0dfc945" . + "baa40dcbe2137827432504bd79c533dde1c245a8f689160c4ef800368c5f856e" . + "7543e93becf67b62fe63d48af904460c16b49022285823d6e1c12d7690603641" . + "820920acd8743ed8805bd6de98cd7b9d5a252371add5e19e9ff405ae9b008ca1" . + "05f5efdab0e58f35eaec09f949f67fa970dbf1e9b355d78cae386c9f3cec314b" . + "e9d2fd99e76c9417515259d5ea4ad5eed8000633d8c0e51d0fda8d7d4c2ddefc" . + . + "07e188cec03d94cb6aa0b1518a665c77b48e72b7375b037955ed60c75f0a2650" . + "e6bad387fa99716b3c00c3e25c6c2720e53ac986f37d58a7a9d25c945384622f" . + "415adb6e34ed7227b5af245dc53d1162416bb0b8a0f7392197bbfb520a58142b" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "e8204bc9d8194f20002a4f99e5e6ac8353b8ed68aa62c1a0b0fbae5ef27fae40" . + "c67d6ba5725f60a2fa2942fcb1aa2abe6e580d1a6e666c3ae287ae46be124fbc" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d8ea339ac6ae1c7f728dcdd96fb13fc1bc12c3b5acd90fcd536cfb15f1c9a4bf" . + "4c4dfc239733140b95b40ddece2837e86f4607fe771996a658fba576faa617df" . + "8b2c6bf4866c27cf068ccc8f52107c06b79d66cb53801b7c51b6e282ac439426" . + "1fc6a356ca48a5decde65b6e2f5c828d0a451948ead9b35cce026786c1a7eb9c" . + "baf8b075aeb9b1cafe80d9cba8784dde5cd9306cbb88989eb8947b0a82f249fa" . + . + "c0eb782d024d061272cce13e729c6b00d9079c51a8f0ac93142908dfff684ece" . + "7b88acfa66f5898e7a9b8b942dea49453a938210e88fac8d993931373f7b9a42" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "893b487f3ebf16558d797bb2db95b78b77a80afb840b4f9c1d2df5e9783bc239" . + "d2fa888d09c5e71c61744aed7a84c9713abf4f504a28e601081fbdcf5eef833e" . + "b19b83fb6bb0db06cd7a524830e1d2dbc0887d6660c0c260e5cdf827331ab175" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a3af3af12cd2ffc6adcf10cb9a9326583b059fbb6aac5fb4eb37b1d5e1db22ec" . + "a3af3af12cd2ffc6adcf10cb9a9326583b059fbb6aac5fb4eb37b1d5e1db22ec" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "911c2be5a0247b45afc23bd521f5188f2a12be29c14bbd0711ebb7935c075aa1" . + "b213c04e189e1e41b1eb1a0dce9a2c9d001fabf93d6011444c5d351607798911" . + . + "5d3a073f128bc2519a204274452730abf227e7010057b3a0f17c6ef00348b78b" . + "f53f4902acd623be242ea24bb93839e7784ce2b2bf46bc44b3817b81555bee0e" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "ff52512a71ca524d294dc5491bb30da39fe43c4d91727996903c0491157345b4" . + "e25c3fb2320e60615675c0c26dd191dd61346ee6a19d84ac8a2cef150e9de026" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "fbeee3f757cda62812c8e2c0fff2240f4ff7dd4fced1a33030b2e1e257379679" . + "fbeee3f757cda62812c8e2c0fff2240f4ff7dd4fced1a33030b2e1e257379679" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "fa757051e85a31688a049037d22547665d82bfe693b133714177ad1d5ae2638b" . + "aa8f064b2b185173f80bfb5956e312bc685525eb900d51f40692e66be4ef93f4" . + . + "75bf121b8f4505a862c1d32559e4b44c2448c99403e7bf510080ef7ed51b46cd" . + "7f46c461148b3f95c722ecf8d5574528649177763931a6ee666c49e67069cb9d" . + "fe18d19b23496f9ad76bd24316a2a88e33a19dc6b00d7caab79934e5cf7787f3" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "d3db3c5dc7a090c0260f214a6b9449d0f6e289647b94304378d90ecce5c0497e" . + "c83bf14c4f417dfa06c2f917e629ae34276e29b025a36abfa86ff820415d4df7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "72fbafb75fd03ade45384871753cc02c9b8967deae04c9c114e44385890d28bd" . + "72fbafb75fd03ade45384871753cc02c9b8967deae04c9c114e44385890d28bd" . + "36404f433c116c18553eb71d136a9255a13aa73319a2f218e3f97c4828de7739" . + "a7e12d2788dcc206da2fdf55652e670322f7dd0b34e45c82e503a4943552b966" . + "3e9b80159dbca8fd6aa093da7c293c40da9de813d98fceb26ec8f2e581ae1890" . + . + "77dd261d3e5d11968eea7b36b205a78f9b581c6f5234b8ef7fec1e13ed09c351" . + "52739e45dc4b408821c3f18b0fa3528cc3c05c041ded9ebeb066e9452df3da43" . + "fd3f17bb6d9874278412b0ab2c9adc38eb636f32177e9f0302641fba6354b9e8" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + "7fa7e49b681f9de500a19725629e61d5d254213a477fe98a57ea67da6a41d8a1" . + "0a0f1fbd2eec835d92b9388293c03ad23bff41c52386aad4a0b50cf99aecc824" . + "988970e3ddaeaf82803247d27ba5cad92f764231f227eaf48deec0499a19a70b" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7008389303b5b2bd623c3955d45f575eec8299693d0421e64d0e22dd9da2cf29" . + "9b35387553feff822b28f460d888bdd4afd5ef07f52834799476b52c79d0e81c" . + "e19aea21530e4569d0e60a1ba81246031102ebef6e6ef8876ff24c171e6e27ee" . + "21b8eb2b99ff11168252733a978ce96c0ab303e1dd27a7d4c3b28c267ff30e2e" . + . + "354f6906344cca8533f655a127f984dc791e67662a4cbaacc8a128397bb37377" . + "5f93e927dfadf47331565446d0a4e4dcf242bdcbf63491865326a0a721726f24" . + "46def03d77c1c3d49c50f4b929f803e7b19e0642996479217d4e6ac357efd2b9" . + "78086e86ee14abb36d43f0e5a5eb00babdefdba1ba624bca97e776e4f23dcc84" . + "9a2c590b449cbcecec7a59829fdda49ed34e2525e2d1b464bfbf0abe77641e6f" . + "e0e96ab673265aee02cdac3c790f4d66d2378506c28e6d99a2e879d1034b25a9" . + "f422e01ca1f9d12e1511c3b414272728f2e072e3358e0ea05f7487ac5af84bf9" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "94759b6b387932130a80ee3d4cc0beab9f3c39f38b560c882b0dc45172573317" . + "0cfd5611438d9cfd5c719cc5915571dd11102228e79852098a3e42a3fe81d2da" . + "e53b630957f5d48c3f2255a1e664cd017e4bc3539817b91650d6ffc3a3388c66" . + "8f765849f9384b6a59539d637596880844c2767701b6ad0d0954de51db0437b1" . + "cdfacea8b6a56dcc213823febcd33b2fd760c13ffc01e66bf1e9557f76e990a5" . + . + "8e8742a351cae276b39e012b7b8f8630730bd26351634dc9b1c04a1707fead29" . + "3ae378f3702f30ded93e25c1ba7f96f28a11ffcaf4627fb63a081959acf183a0" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "267de746c679b735b9d838de50ed52bd14eb4edd7b1568a56428f9947a177fd8" . + "0adfdd37dda0f56029c17a6c0e2e0cee3061598fd8a2223b50a560f3b1650564" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b825dcfd3993c2fda0e67a8d8c3cbbe9e3aa22480b25ca0e7051b76e3888dafb" . + "c1501de754361ff15338bea4028197ac0a25398eda36134483f56aa7eabbca4e" . + "051a7a6db85621a1d5011d536595c39b8c9d54ba249b8423fe846020326db11e" . + "bd92b3fe278d01bbb150ae59ab49e6a02d895440565e4c9a74fdd439e35c543f" . + "c3c316a34d149b02a578330ca42f4bcc904b70aa755fe6d99d5d70e450f50f8f" . + . + "dc7b89ebaae27f01e0af65183a17912c9f608384635171c69b7b936a74e18e59" . + "fbc3ab546648bab6653aea7c8808aa7d501a200587f66729489adca565c5756c" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "c95d8f2bd318fbd5a64c580ef03b404b08327d9882c62e797481849462f820c7" . + "85a5db16679d9300049dd8a3fef1e06f096ff400e516b17ef498b1eb2b7c24e2" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ace52763a16fa96dbfade8f3f4a22b279df108f9a1c9422da285b27ad02cdaa9" . + "ace52763a16fa96dbfade8f3f4a22b279df108f9a1c9422da285b27ad02cdaa9" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "66607dcc1a5d973450c21cb3fcdd516fb476a7a7384ff682007cd8555b9700dc" . + "fa04b500a6e3747c195dafe88d0f0c5c818336bebc24b19b0bf219c41ac3682a" . + . + "8e11af97e8ef82c4741251b506503c9acad5656f6cda87fcd84590d64cc65dcb" . + "3d5ed0173ee065b0d2ae0b901cae841ab2885800b93fa64ad88b1d3667e0166b" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "a7aa0859702eb2aad335884183b9fbaafdea9f0456ccbd3f2da74ad9447d296e" . + "cf46420127e70ae9d648417b088a24f3c6de13b958099cef020a876f8bf279cf" . + "85c657df186763fc008a044ae972c0bbbd131bb802171d4945d9b48819ce1bc3" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f773f97557656ba1f9728134c61f306a39568a849174d89a691f810c7c7a70de" . + "f773f97557656ba1f9728134c61f306a39568a849174d89a691f810c7c7a70de" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "077ba515fe573d9fc65942170c744415c20aa7c3be528e7195258eea6b877ae9" . + "13c4c48c9e857c84b3b639401e4aa08a67d99b6a7a07334bed4e13b9360014f4" . + . + "546205b3f38d3990545006c7fd210801c0239fc1ea3aba77b72eb5fb89c69153" . + "6e14b8ff98a19c55afdb7344bfca310420a7507903acedc279ad7cedc35a454b" . + "d8ff900de629f800e9a69e4e25612449c8bc93edcaee5847ad97fd539a90c083" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "26d2256c4c89df210cb0c0709944d65db8378a5b7efcb310683b2fbb84a9ecda" . + "679b47986e1f318b6348138e4fed067c1225209a2c3596018e9baa35e2ba4497" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aae02f45978fd14482dd1dd24557dc0df51b2294dce1436ff0f01ffb2948bdbf" . + "aae02f45978fd14482dd1dd24557dc0df51b2294dce1436ff0f01ffb2948bdbf" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "7bdad8adb48793779f0827c7cfe1e04e907bd0a6182ca10bcad8a20cb404ecae" . + "98a8616c8b9a11f94594fe71222191316248f6c9eac45b188ece584602ac3427" . + . + "dad7bfad233f974c583360271a1639dd04a8631e9b49502e1aa6ed9025dea028" . + "b9db8f3a8c6fa811afe3e0f3dad5e1e0295f1471bedcbff80db1ca31d295c071" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "75284c90d9ff382c5e8054140f194c7e8305df3192c1972926ccc63140e4da31" . + "3122dc308a5665728c53c6243b22aebc43072f76707dcc8ad336fa21124d29bd" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "764f1cbaa4912c49a9f8e466713530fef66d14dd4fc19265e8ff6772cd88d0ae" . + "23d74c5a6dab65d4061eb796bf30ae6b75c1002a64aefd4d95f3e251c716328c" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "3dde5e62393b74f9262046d7b029bffcb2d9c5e8915178e872c13d0ca8c44732" . + "71147e1cabd92744f76699fcf9b0069d48ee420d21a0245b8457377570983f5b" . + . + "8966b1e98df1d1063f36ba410d180333d9abed75a5f78da113418fc73a82c34f" . + "20e8f6774cae5522b7c38ede57678fff9f46ceb735184d5ee462c4196d7c2d30" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "1d70b2a23123bc5e0acb9602e08c7c7e61f60c2adb5185c5b7b78866a0c9a688" . + "14dbed6df7e4e5f47e522fd771528583a83cb22abf445a5b180cde0d9a7998aa" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "814b6f04578a4db4a1ae1e2c54f3d4aa07204ab457e4a196af7a69e87de531f7" . + "814b6f04578a4db4a1ae1e2c54f3d4aa07204ab457e4a196af7a69e87de531f7" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "110f55d2934f55a44914f52220121c7d8f699488b0c2b8bf1bdb669356a39f3f" . + "3c2b4e26b525d4d6ce4ab5933f813366fe356425d7b301689f9563e4c736f1a9" . + . + "3b2d17fffb94f53f0ef3ea11c550ccef1d883d895bc8b6526ddfbe2de50eb7dc" . + "85f649c03b493bf9b58ea93fc33bb6bb567f899078b37dac81317d13f06fb0b4" . + "7f3355eb89be6c7bc83eed17328c00ea77dbbfb824a4d84b6644185ef53a6e4b" . + "d76d043013dede77f1bfd16714c039de5205fdfed7983e0c0e8badd02ae9e3c7" . + "d31a6d95bb2e2a5fabf227feef6a05a607b99eacd540fe6ddd85812e8b8d6752" . + "5b0c4c7cf34e42235d6db14f8fa9038df9c7bd5153bfe1a79b4726658ae53028" . + "b18f123907b589817454a13adefd2ca757766afaddf3414175f988e99ddced9d" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a3cce44c942bfdff14f01e55fc48a665607424cea2b517ec43b1c786f9be8e1f" . + "239329a762a49368b47d8b01df3ec8df05767020b47ec4f22891037e1dd210be" . + "113a3acc5f487d6b2ee424a99cce36b246a6d1a802022f8010c4af9f9aab1eb5" . + "36c9b775edc3bc4cde74560e983c04a4678a3e474e5f82bb67cc0162fda0e155" . + "87b6500aa9f316f0af9ffa49e9c6d696da8cb9a8bded512efdf6129c2d70b601" . + . + "fef97924a036913e3c7fffcdaa467f14ffdb373dbc043c3b1c73d5fe0ad20555" . + "a84a39d8fe5380c4d88150198b563de3cc94b32f90ec16513c1881470d7052af" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "a5834d8585b82ab028a7044de375353d52245424a4b86e23495cfdffcb088fc0" . + "80628a0462a63d4f0de3812a8f09f4da5b425920483f37fcee515e3f05a688b9" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6dbdc39f44f3defdb8b4e84b69ab532f94860939535ba941afeaadd936099aa0" . + "4e77a2daa6a4a43ae562acaf90f3174a3da8895c67349c9b1e3651c3051275f4" . + "b4df167fa748b65bdc451f614f08b9c60368eba4aa0c124e246ae11c0b7a45f7" . + "b023a97c8c0fb52822559b5666122f802c43103219dd6a3ae5fb41740243c29b" . + "541a3565f748feb01e09455659d19388783136135881b183f835a2551e400d39" . + . + "084d10996e97f0c225150157934a05067c6d19b5d3c52a9c2871356c7da8ca65" . + "7b44a89301e5cc90c0248ac6ab0a3443dcec78a8e5e6cab5cd869070fa0c5483" . + "dbdfd7f10cebaae71d266219d1eba2a3a049bb40a2ba27d798249cf53dee5fa7" . + "f8ebf613745f56e3bd0a6f34ee3acb3968c30e70ca33b26db442689a239d14f1" . + "0b812a64789b6e88342d73544f7327752e925f62f02db29304dc658468cabe00" . + "3e747a3e286c3f6d45337e06eb7a3e610880deeba6405548c183b9ed95b1e470" . + "70fd5a17883dc0b1aaf4e4b9202d6aa417b3b55506cc1aa876ca62391e21b0ff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7b1764d301859b6a89bf5f8b3f864028ca1c48afe26dfd81386ff15204eecac6" . + "e3e84e8a5d60b754d19032647d6b42bd601e2155b6cf98b6f3795aafea18747b" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "662a4eeb836bd8a9281e2ffd0d0e614a461957db465b7637796280ce07712b6e" . + "c794fa61cb75938162660aa732ab49135049984bd5aff15299f1b25339b44ef4" . + . + "da457c19768710bdc5341e08c39b6f9a43487f897be04e949e28be82f03b6c88" . + "c3d14dbc83a5ff211640f7d3572517b57bea4a441391899e4a0c5487bff57323" . + "eae713d060c4a0b29e368bda568314da5624d76e12542c3aff4ef3495b664327" . + "2d6ba55314375d0a6cd5c62953f16d704baf3d58d6f17da2172d0a7b7b9eca49" . + "aae1fe069204b40798a8f47e71ac9da99ada904c52443a32feaa07dcf97ae9eb" . + "b14d44f74238c27a283aa11f857b1a2b08a5be1160a072beaaa1890b269d3f27" . + "251461164a647bf78b3a252b3606cf56e305360bef52d729bf10e763f1874d7f" . + "04fa731b2fd2cd75e34cefefaac73f546c9bef7b8604c0fdc21e8ef9a6bff7e7" . + "309435e8f8ccb31a8bd37e75bf371ea78c077ac2a860d580f0e10cfbf8746aad" . + "309435e8f8ccb31a8bd37e75bf371ea78c077ac2a860d580f0e10cfbf8746aad" . + "6171d8906cdd17be8d1b413eb510fe4bfef6e08ac99b92dbd66bfb556364d008" . + "48628ccf79fff86cde8fb89bad2baa0a9e42083562e6efe30506c9656e809d6f" . + "b738a12a316f43756e7fd5fa77283a36098406366b503c1343a419cc7a4087ea" . + . + "69b7df40144f2af5ad698eb336a82ac4e812b1c0e4caf6fe6b20e58862f56f2c" . + "9dd28ed86dde0132d7b54ad1d3d1011c39624018092b56586ff34b15ef88c907" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "0354ae9f68657951ce85c6b4955e1e3a6d7f0f275dc69c33598c8316b5a00513" . + "cec2fec1f2d80718c290a36e6175c1f2e113420a56012e8a392b5ab3e8cc6512" . + "02b35ae708c6a098e6d3eb8bc6b0587fc60405f29b26b17c42cb3f30b94668d0" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "fc3748b98dcf72cd657d40bdd65ca6121d1d93a900807f556246cab0f5dcd112" . + "fc3748b98dcf72cd657d40bdd65ca6121d1d93a900807f556246cab0f5dcd112" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "4eefda5e768c574737088f4cc03435e412039a11ba951b9c3318cda7d80a9043" . + "6db3e2df89c059dd9ece416e279d52e53a9014a01df4eb08473d65f0dd453cec" . + . + "d335f60c526aafd09578feb5cce8f526890baa970a357a910f6d1e4f997a2908" . + "187f8dbbced6f83a65311d2ae3d930c51c19defe72069e597e8354d177814240" . + "38611443bd7b744094296e0caedb44eb3875f06f8612db9e731ec2b416051c05" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "fbcc7da90211e4d303f11581c8a0034ebc3a702c63054ab3f3f3f7d2a2437926" . + "e7d81b678e2440568c27cec5bdb5598d61e0c7e1d5a55f31340758fd059de34c" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6bbe977dfab6261f0737966139548f46852294d48ba430cd406bb890c12eb74e" . + "6bbe977dfab6261f0737966139548f46852294d48ba430cd406bb890c12eb74e" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "f5c9c24f59f55f332d1856c4887ba48c7fccc61753568739aa05688324694c42" . + "406862ccd0e1dc19dbf73f074b68239cca4fa08510d3007d795ef9fd25616ee1" . + . + "00339fb68c88c23881bac6bcac52b51877db7ad27057f29df5dd173219eb30b2" . + "60d2db69f62f48bf2a9db526e8140608b2bbf995584290a5483b410e6c28a44b" . + "5e2aeadb587dc88db24a593c90de8f30590e972f42f0d52f86f4d5b120038cc4" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "f9161caab49f55eec880a0774a453071fe6b1f674d3840dc84700bb887893663" . + "ec7a1ad0622a7ea0128475443ad27057668781c6c27069676f1bbe3f5b289ba0" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7ab23f1c9d33921c4aba63e3f7b8e05177e0b05da63efd48ca3c6f258b1bd46f" . + "1bbe4bf9654fb66ee5908f245b8a7f96058b9bbf57a6f25ea71286fe2bab9b80" . + "3c0a095e8a2a2d4779c65d18678b266d3c20264ef5f915f400386abb49942066" . + . + "f338c3a2281d1c764a1cd5c51f2ba083656a00cd8f3aad89a39ed62c6ae5ea3c" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "9c684b4f3c2689ec51c16d613b610658c0299cf593c046330d07b5de23732b3e" . + "62a9efc573cb1e5324f277efa0c6fe3842d16984178893ba8052d28de18ed85d" . + "ca7fe3e3f4fc27a03766f8cf4e8bca6dbf47e19482583680e8f565a7c8cd7ba3" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "de4fc58eeebc625d93f3f16c79445adca3232e1c57b1f458484eb740c6e1a034" . + "f7dd322fefef6707432049bb80357e78aafa3bceb07a9f51416de285e0c1d490" . + "373c7acd496a2ed0f76c93f66c084c05608a672eb3ec13b29ec616ea4e9bc8fa" . + "e096f22fc42b6c53034fbae6648b2dc84bb70579f5a4fa1e0b42990cf52e1f43" . + "ba4a533b3947264bb423aaf185ef13589d380bd446791d8ad86b3730017bddb5" . + . + "d5a22637ed4db67e4ffb0d6e0672065e206e560bb7f58f5a59c5382244b38312" . + "8eb5972d158965e3865d23e3d989485402e0ff3aae3557f145daea92c9cf4ca2" . + "9e16690d06dc729b371bc0a1cd8212c013f2fc8aab73369349f96207987daf48" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "a4b145589ca9bdf69202dfe3bf4448780a4277b82a9da1573b3b922464d762c0" . + "b88a17db5d68009b57d04df0769e53b6895b1c05231e3ca29f62b13c18529c7a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b3e784792941f98136f41622e8f9145ddc9d752763438e42dfd28c474d05ec98" . + "aefea0a1036649614326c5e6c34adb319ad906ee4e69a27553fbe14a4b38de2d" . + . + "7f8a0ab60a7474ee6b4acfadfc715aa936f1830d9f6104321761cef906e2853f" . + "71305389dadea7f8e479aea779f4c8e71a76fbdcaa265bdef44b29cc514e9a7d" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "c035249a3af00519961984844ce6b1e3528772053cf5c093b656968249de7258" . + "d4de7a14f5279481514c08935e429c3bef52403434c25ec15ee86ee072476edc" . + "d3dd7ae7244a2021c8d566deb15256359c508a6330d5eb0b6f7e54af1fb65c75" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cfc2040c2e949a83c418c2e06a95e10449a41aa2bafb92d1d406d810a7dadf3f" . + "64d2437262bb5039442c95b81aa89fee6afa0945779d32a68242487931d3d61b" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "9a7848f193f481ea4f28ce281156d7999a63d35aa8cedef899ce4e13f73477b4" . + "0342d76e366cd5da5fe421321a436b16e355de691aabba9904e185947047b6d8" . + . + "850a9c33bea22677e813403c1da200e1b7ee005a0ed611d482b34cbf6e8c1a20" . + "211e5fb4ec08dcc7ca9f8174cb4e1142ced0ee3d6855d16f827fa47fe5f969c7" . + "b45eb4a3b9f0b58cf4fc4dab558798ff0623ff04a605004c422bf53a88659f47" . + "796af0413542d792cdb3c5602b3a6848b184a39d8e378561f41a202fd17eb5de" . + "7cab0a867bbf96cf1c34d68f6c1101dccc29a883518343074fcc556a1fceb50c" . + "4fde67cf6ce38822a6feeffe83d2af11f77ab91c314fe1706726cdfb37a6709a" . + "1f8048d41ceaffa6dd7f855cac3370e2165777c71925da611f67de00726c687c" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6efddcf4be09cdc2916c0b9be0400fa178ec1224eb46026291b59681df09a6dd" . + "417c872a5b1fdb579a29c3732fc54d788e70409f34b3a8d4d2902c33d366ca31" . + "48234a7fa3e122ca3acf3fac7c511ea050025b3ff802b4e49dccb8d2a628819f" . + "af8880e2ea3d318ddfbf25429de8f97d933a7bbe376a715341e38f19ce547f0d" . + "6bf746a113376c96a31df72ffb17b2a9df4f3ebcee98f5b684771eaf10f47f07" . + . + "23e4f88f8f1e6bc00041a1b800530ccf9f0912b2d7096752dbbd22705de4f2ec" . + "1098d158285e5630eb583ba80602170075b7a1740fb52530d22c6a4920c945cf" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "b31370f502b834e2107d574a8b40cf8419b79068f3c20b2c92d3ae1a2c25c52e" . + "de4e62231762977cb33dae5b35b046d689b090a6c792c1cf0a99d9d1c51b32c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2b16e51a4b219c6cf8451ff8376839fe8699e22e70e7818cb80314b4c3526fd6" . + "2b16e51a4b219c6cf8451ff8376839fe8699e22e70e7818cb80314b4c3526fd6" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "0efbd0538fec233ed2cfe92644af8984563dfa072f2997d58a14d17ecfe1f509" . + "a86d72e3ee948365f62a830ce8408085bd07f76211a9cf4064d2fc498bff68d0" . + . + "8f8b5a0b438a6790341a5a398b4db97487b9afa71a55e443eb5c45c23aee94e8" . + "ff5c3c4178a9d16bea60f0670f11ebee250d7c15cdd5677e00cd3b8f194c3d2a" . + "1726867f21bb706caab2e441dd7e3941a60d53d8e5523c2f2b2742c2e4aec1b5" . + "1ee9b4e05622a736ab56a0a6c5d6e8a7b2d241d9cc5a8409f66ecf0b44f0fa8c" . + "044b4b930de6e081f0910894a0965bbd12886a872cc0d62ebf94549731cd0103" . + "89a93229422a2b454bd590222acecadf2a8443ddca3184fd68bf5cf6e8da2c1b" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "ece73bb115e8a1393af59ba9327899fe5746070b9c7dbca98511ee738932a53d" . + "fd360a4dfbfa557134c4222e92aab03e509dd28afae90216dc9fdcc6aa6e50e2" . + "8a5c3ad4e8f42aa19317f571f3c3f88a734c5b66c4f0c3c39abb88759474aa68" . + "c07669f293f7537536791be61df74f1aba6e544099e97605bd0f25abff1abc3c" . + "7702ae9655502ab3126b4240f0ca53a337bc17617a59f6a9dedb7a28ffe6d672" . + . + "b17da9a55dae07c635b31da47703e84aa2a10f0b3792434c536f56db660cbd82" . + "dbb3274246bf17bf87e17497c039aac3fe3d8740ec3eac8492e1455a31a544bb" . + "311a534775194997b48ba112e08e97cc057d990bdcd29c9a06b1e852fca2fe50" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + . + . + "8d4a59fc51f9c84f9061988f72bba2947d81d0e76496c93e21388d46e79e2f8a" . + "0a0f79db49dc1615f5bc68de65de221f23e623a572ea0b9062f5c00e614c166d" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "ea40ddce8fd305df65dede5c9b1e8d44713026604e672cee4c0f334c851c1a59" . + "ddec34111dbafd5f0f3b30aeeb8bf961fc822c94ad4906efaaf0942bc2529525" . + "5a9e1f95c5023c2c2a0d7d28ec67a0a3e1df6d3edba4f1b37ad290c26a74f525" . + "635d2cb6d42fa53e04d2bf931707ea5da0407e61a540f07d06bdbd5017c2f793" . + . + "51c4130a60e6e88295801e7f85b23662cf3574599e650fba2115908e201aee1f" . + "ed5e9741ea9efe16563b08539d1c8847a21720be9f369c922db825c9bb6c1ced" . + "f5b3ed7f83cace6c939f9e464943707a52f8b17fe85ceb8bdfbedc1817e2c406" . + "c95ef4586c50539df2494b9aa0684a634dfc1c44f6ac1b28f9da5817ee9d5269" . + "e07b8e75e1e331d2615e9a7612b098b525bc1217677663a3724d2c33bdb9e8f0" . + "6c967a6eae06713dc973704a3f43ca716bf60a5a89722b3f725b347eb84efaef" . + "c1d47a6a92970a8c3a04a4fc42a979fc47c9db13f2e188419393481e2bf7c46b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d6b065fda5c21d82bb2bdce180157362c7fd476649861f685195599023592b88" . + "85c4706ab121491bb980d5b1a7fd1eb8a0026649828fdf1dc0e4c34496d1c097" . + "b96714f107fa82d8ae1906ce55b9f054f69c4373c147d98986cb303b2e27f6aa" . + "254e9b30c6173755635a3d00d5cfd45aa262baac851dca6e986f8af5b550f513" . + "ffdc9734b619974b423555c34056fdd3726e2002f26e986e5499623d7f7d7f19" . + . + "05583723f6be15b4bbd9d9468700852bd6b6f3e5fe09cbb027d2cd2bc65391f6" . + "6b8895ff8dac968cf5bb9c785e11cddb55b5c23095994e082060564dd3f73f6d" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "3a1c3f99d7d9ac09b163a95cf4eb18629c80b9346c6a07c8e37c0c30632d2cb0" . + "8c76caf12be41a0a04a6ba0127ec62f05194197a81ae719f3871b6a7afd755be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5444c42577bddfece438bd412ef4b8fab76f5b5ad1dbf4ffce701a8cc7fd7873" . + "5444c42577bddfece438bd412ef4b8fab76f5b5ad1dbf4ffce701a8cc7fd7873" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + "496f9ab8edd642775ea688e6307b401835a2c1f36daf805a78ae35f727331969" . + "25f5cd4d60f7c6f1408a3ee0a641f592e25306f32b7ab6a9b00a04c7fb646d1a" . + . + "98b74dd01c27b3c84877a1727e1350072dd03c91d13e56a523a73bdef323a981" . + "d35f449f4031d5621980936665d55f10e453552a6018c89606444845e8b1f861" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "1286b89eac1e7715253ae839117ebb05288ad7f34d5674c33f56868476a9a249" . + "f7a51b936f9b00350b9ee7a38ad6211ad67b53ed1e660d945d6cdee9decd6be2" . + "98c1bf168d90c09426af7d4346a14719ed36522dc2f96c17f0eb23da75864683" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5d37821c813c878f7150d0489c4956540cba1ad28576e98e7b53accadbbd664b" . + "fd2e135a5cdc47865c9ca24e6ca1430a27588e9f61a1618a8dfdc2e7afa4338c" . + . + "ba3b1413a1e96cb5a105017ed01b4675ab660517a5d5f6f359d683a946b017ed" . + "48d1d5c41ab606f11bd159281c17d9d0f61d079321412b97e0179d350c6cde4a" . + "6a522c214efd2b43a26a63f8bd0b6f58ce8e117ffa55c0ba0764ce9e02c18c7d" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "a266ee17ebc8fb1a17458fc04fa2f000ca7ce1a392032482e61ce172590e2868" . + "70210ed59bd7b56f3f44eab031812c163fe16c8040274636b44df4e3854f5bb4" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2426ee7bce418259913b26f6af17f9787e6db1139bb382d13399295c0fb04131" . + "dd5de631b66cb93653d4a5ad3adf930617dff04b31e84399b76474cf3da73de5" . + . + "da7d7c8e670fad37ed2c36ab5afe38fb8d57473faf15891fe5320e2bb7aa07e6" . + "943da48a0af5b3dea5cf327ebcda67f8ff92731c6c846946f7a7d5fbe05956a7" . + "51d1df17f7212802fe788ddbb16477e613f839dd9c502a6f9fc5cbc2aa1732fd" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "fd8f76bd4ddc09aca5591a4f023b3f800604c9c0168dc389bef7f27841c7d232" . + "42d079486aef36a0a2f05df525792f334a56836b168a7a18a9334d40ec2da30e" . + "29337472987317942412376ad3a148b299242a887306a7cb1d499c394964e5cf" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "57b5f2d75b4fe8743c484810e2e6e9d7e2a55db00d75547ec56911491f321be2" . + "c8ae6be20721410777597088a34856aaf887facde501ae527814d1b8d4465d0a" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "97d7fc84416d10f4ee13f1219b34aa7e023cb2587e87d1ceda6a940fb989bcce" . + "f3a70d2dce7af6df4db156dc20b7d0eb93d3fb5ce78dd346e8856fb12311f490" . + . + "e018f181beb1f01b6332d6eeb2306642da04d189006c6ef37907342d80e745e1" . + "81e8617d9e11c6a1bf90226dab8448ea301f4b1c9378467742dd53403b619f67" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + . + . + "68b32577d972d5ee7d26b58a522606bd8cc6403f7283843816d50a133e93b967" . + "3c61ab1f1648faaa50f549ae985c98dad0bdd24e0976a40f2e821eb064546f7d" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "51876336cef5103f9663001397ca87ba9713a83f05e5d580f1040547dc16b22a" . + "51876336cef5103f9663001397ca87ba9713a83f05e5d580f1040547dc16b22a" . + "97e7441cf5cabaf41a86f814ee4a2d022bd9558b449e34217f055c0d5bb33c00" . + "4b10ab18f06c4eefd143e2bef13335f19296441f9a4550e09791f2d5d57e5fff" . + "4c11779ce225f8e0c022b252b1554fcbbea2f972db8073f7b5c5688f58699ec6" . + "dde8676da5adfe0b420ab84d099cdfcfdfd5921ef1caa70bf5670e2ae415612c" . + "84df40d002400a9e8a6f7a4b385b1c7bb8fa3dfe79897b5bd6f1a7140851b38b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "b00fe678ec87b268a2a36e6c324db95bbf704b0228cae475dbd80d671e09e787" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "e4939f4b31feaa303635644109a46dc06afd66b176ebad59b0d5b8c75d8c345d" . + "18901659d334f97d2d64c68d335c0c32abd16ba31fb577f5a70dbbfa146ee45d" . + "cc080cbdddac41c08456c42841304c6bbb7b677975b4f750f14fe8eb4e455d53" . + "cbb3412af9c688ef84a2c87796ebe7ed87d197fc2ce59fd76abdaa8f34328f6c" . + . + "7113f4cfe17ad3b202f46eacb66326c47bd1f2112112f2fcb74ebb81786744fe" . + "e3db4c7e5ea0bc612d4cd1ad103d10bf0bdbe1d15c6d3d4f12ab908f647132be" . + "5186e0e3bbb439a5e33141f670031b3bbfac732001d7b6da56a3c4c4871610a7" . + "02113f4a5aad3f8869dfb47c582d985ccba2c7b548d8c8e51a12df05a0db6036" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44acf1c5c166cd7253979d4aae22fe980173e9a52fcdbe3504a674d5b470b90d" . + "dd8b46db7149aa00614453de85887c425a86078a076d265a8892c9434e0f153b" . + "7f7f399030998c3bbe95a1d10c57cf517922081bc09d3b991e34ccbc6b867dae" . + . + "875c76a93cf5493e3b04b1730bd8f6f2648a3b1accae613aa633fee06d260b44" . + "77cc62e6115abbf2f46ebc9c26969111076f064b8b3e66efaca37b62c284bed8" . + "3bfa84890796d106e5e5493037b002c3d43b5664a4506413f72668637e6b2e12" . + "0216d1ee943adcbe8b3837bfa49b02a325bf8d7c056d986a6e3b8c02ef374a44" . + . + . + . + . + . + . + "3457567374c46090e2409412275456c9653a0fa4c39c2198a1fd7504e060574c" . + "25491e148bf50e1aeedf44fa3c41eaec162a5f2fe07911ad3f2391340e6589aa" . + "d7c569e11b9b496b2003e0710b14c44d41f16b975fe327d721cd51b39ab14432" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a4ee21e75d3aa983f0a8cca0f9b3c42974f401a44fe57de57139b8ce3a18073" . + "55b04b6eeb150638c6bd47c262906df873409831c98649e7baa19515cfd84a41" . + "8ab5d3a0b86ec11144c1fd2b26160ed9f56b6c284b7cd1225cbf0964c54c2e7f" . + "1ff6f145aacd042cdfc90dc6e246150ff85c9d289b5182e66e1733bb12991813" . + . + "eb563f3b729c9d49bb7662acbeff8e200708d5f2da7543d49a1d16756fd94d4a" . + "c97b20621e276d5aa5b205580d176a821c4e66f0589595f5773bf3fc8da6e7ec" . + "4d71a227a27bbee34c174fb418356edb690b58f2a5f1a801379a258701cfc4fa" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + . + "649a954890a99f7633a54e92fa5e2863dc623dfa14240b16fa80168946626489" . + "5a63dc160ec5f22cabdc474eea1c7ee39e4995207400c8e421d91b94829de104" . + "0f03691e4586af67c3298375ac121e5e445ddfdf456f190a493bd1b41d725587" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "37ec9833825563edc234a3dd1a471cd67ed197d63dfbdd31bd66e0ced03e2d57" . + "09c463a66035ee9c0b6384b9c5f4a1fff228bcebcdac01b2e4b6e0513cd52695" . + "9d433cbeef056c19bde7a5cb1cc7c645abbcb795592ce1e4a5e3aa345c808ad0" . + "45a25dc6fb9d0bc4e59a64b3e48af2edc1dcec356d1c963fcc7dd9666713060a" . + "51f479e75df90565c072e4be1fe5b43304ac7d89a5b0533f037ea6c3a54f8a2f" . + . + "969ed8e528a5f06f8bfe810cac78d2b28cb7990ee435ae170ed04f4cfd19a657" . + "3439a709bac7c6aba5a8c73bff3ecf896f259697221c2ad17f1638743161e772" . + "9c90d4e14ca21ac587337db2aea788824a1b50a7a462e6227ac0dfd7ab6146d7" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "d797dc3de3fc5de6fb6e71b1bb38643e1078fa1b471c5dd39ac4cfc7e6a340d5" . + "80316b31f01e242a4bfbc2f711d90f7c1aaff087c4f6a9c2bb75660642a64e58" . + "a9e73101a009821d6b6c384d87b4ccc05ea77a11a41a7fc359a9f7955e89a741" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2674d2203f015675e0f90b9c4ef5ddd9e51a048b87b6d95113ec21eee8f8f613" . + "9039a4f4e026e18c18a7734d333c7be075437b76bd0fcd68cf016c0caf229aea" . + . + "386d6f0ab0dd978f12c78e2948dde24d45bdb26de173060825389f8186ed2672" . + "ba7984c249603f940439278ad2ab8d9f7ad133a235ba89d12275f88f43aeb51a" . + "3f8981a7f31723392e6b3cc796e6f8fb58e8e93a72f1a23de9b35aa74771c2f1" . + "1de8f31e9ce88c3e17e42b1d43d2044e9136c0a39422434fc6db2f6f8d5e31fc" . + "2c184655c263f179fec86bb871f3bf29b14953b9bd7afd29741be037f88d071b" . + "53eaa31e421fbfcdfe543f13002b27e7df61310e5fab8f921377bd9ad2f0e5c0" . + "1b7fcd7d77e3541e6af4265a17b87ca6eb2223548d618f9364833d54369bf38e" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6ae2372f454655f43e7f5f664c18a6f0e8a787a9dbb27bb90a56182e7b087b91" . + "37d8f2bea398d8b93874d8a8b185374515f56d6b945bc63f63d391741b298623" . + "d3f82918937c659641c46f241ffd98e6f5eb50b6745f2c4cd6922436af8fb969" . + "e15ad65646b65b3aeb42f09b2d72f4ef1287f1e4b254c4c9a1539ff6565eb171" . + "5306866a9b9e08f11437baf3e895b956d68b783b49a534a8a853bfbfc566894d" . + . + "7c0d9f5effcdce046701e7bde4931e362f5abd5708d65349220c0d0dd252c594" . + "2baaf415d16c6d5585f19f1cbf1e5628d298de546b369032df6dd10d13a73c8b" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "998509d98297be80c82f153f0446c1d4bdafde25fafa5ba545d4c11aefa32513" . + "b94cfa56c5101c65143601300b3dd75434e56606da129ecafb54710805f77266" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f3baaf570a343ce869d6f96784f3c36849ee7cb5d796d8c467299b676c941cec" . + "f3baaf570a343ce869d6f96784f3c36849ee7cb5d796d8c467299b676c941cec" . + "6926d5c67b71f639b54b490e79efe22e6a6c926bdf21e09e6c0f6d74803bb532" . + "148ec294ccb79ad6a3e9f0895627af16469ca9a0ac58bc28c0d805392d5ee280" . + "fe423c4d69fa936aa36a557a61e97dea3660c221ef75118d229d33c967f2331f" . + . + "dd85569349af191b92e4e49e6b54dd7c2877f8c8b20043253ec0f14ffdc52e0b" . + "0f1129eb7ebd8e8609b0872907a998887d4d251b44aaa050c6cb42e0360f88ad" . + "5f5559693456faff03d519ebbd26143adedf617b055631514c17a757e05d8aa2" . + "6171d8906cdd17be8d1b413eb510fe4bfef6e08ac99b92dbd66bfb556364d008" . + "65b5a22abe6fa091fb851c459c696524a9a64f50f4857d37eb5bf2d457ab2626" . + "9832236858ab7b232768f1cfe1a312bb8dae930372e114db98e0619e4e68bd8a" . + "c06d44da788edc93996757e660188b135ced14a18cce9b34a0b2cc15b6dc2242" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c8f9ddcd796cc074c760cf971d45b0dd9083ee57461ea366a0c20b9b558bca89" . + "f116ced8ed5345de78ddb33242ca413239f3d2ada835ecb042c0a3224a71bb0d" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "18cbac06af4252cc2036b828f9b85b2f7076c94c5d42ad80635c2e6b529107c0" . + "7752258bf2cb3c5c1232b4ee42edc2568c24a24d34a58f8badd01c5d9802b6e2" . + . + "0f8c3b56adbeeb1e06aa74cfd434369d17e69f39ffb769024eb6ab55ee1f61d2" . + "ed80401c3fedac74917a7fb06e6d70fd1c0944b63d40311290c694e13aafa40f" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "8aff6e8a9189dc78312f9d1f485e86a3b5edde1a49c637ee0329e8c062d6d5d3" . + "0bf5824918e63f0c3bc214bcadd60064ff10a1938b9bab2098446f89d083fb36" . + "2978e09f52408b62f72afcd999577d97dab87d929e087e69228014a98f28149d" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b1100a22be4fd692e44e5be91b8b9a2fc7fa771c7167215b9ef5716393a5bada" . + "d1e2908ac5d9c5566b51643f0005275c4d2b5f5af407d9574297781a843e5245" . + "8f213043b3f048ee7b88bd8d1da3fb6e299ecc890da3349ebb8e7a96d67fad3d" . + "f4a8e4633a7dc9e7304114b7e52e2655f79f8655ded7e0d5a699d61c8992f4f8" . + . + "ca8bca5761d1c1b4af7aebbf8fe5a5a819986ee30b7232290d2c5a1a57b1c29f" . + "63daa04d21ca12e1743285121d8521ea9e469a1d13fe29ae590c5e38d641264f" . + "4d5c9d932bc8c4a6850b7c38b78b1f395420ad314fb37b75488aee1975bf2dea" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "7ec396d0d9bd374d9f6f5293578acb6eb7be03cde7decd9a3b98925d2b52d2e0" . + "e3c62de1f8f7148f987429622c747661a740b774f8efe707afa53cc172e51162" . + "a71df1d32018bf842176093cfed4457f10a01f11260402d9c7ca1ef27e343788" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c03a7eaefc2420b6756e79521b38bb11d5b0e9bf7fc7b86e8c4e9c60d4d92049" . + "05e58974fd78f79ed4ee0b0702d6ad60686c19a4eccb3449d3b2cf00a9ae3304" . + "0cf7c98a2a8f246057f8e6439dc96840cfd266839cb15eca436826f4355cf0d6" . + "73522b83bea148ed5ec8f74af5fa12209a3639c8dad9176a35413e4a5b31e156" . + "49a1826be52c90c89d671806539c93250b500043b52673ad91c680f6a9ed27fe" . + . + "3f28a34879498f7d0fa59bd975e78dec62ab8b306de94c9209f958c048b62308" . + "633341177b5cd9799308155c997b324b5f21cca9e8adf872652dfbe12515495b" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + "9c90d4e14ca21ac587337db2aea788824a1b50a7a462e6227ac0dfd7ab6146d7" . + "5249abfd34fcc8fe13aa51247df08e85231a09936e8f3e2626af230cafc9398e" . + "43bafdfc57e271fcfb0ae4e64ad40ed362aac73a7e03f2fd81ac77825de26f45" . + "d65c415a257447f4948b3c31cc3c26ea883f1ceb61b115b2981ca8dc15a59c0b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6f4be5a1620b1946e8ab0635a0b0b1e1ae8168470cd76a88a2b46c20acdb1475" . + "78ff4fb7154afdfcfe8d6e39db31d82627b6398ee04ddcee48853b2e8abf8fb6" . + "19eb09a5200554fcbd9dc7c09eec1aaa3eb3ff8876dd8010d310fd07f3b70c1c" . + "0389e8b8d48ab4ed0ccc806c0e6f8bc0c202bc2460319d6d6f156f1a58e1647b" . + "bce078fb8c87d39850bc4b89ecd7bdb9963199e69beab30ba2e9f40c77fcc968" . + . + "23ce7838e8df724229bdb95ec5e2f3de80539271c604fd649ec000f247ddbabb" . + "496a01309bb3c8159fcdef9cbc33a95a97839f25b9e6a3f9007eefc7c90ed471" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "b48a44a07810033264b186ebac33ea305307e38725f800dece29d4e60147c974" . + "0843b17b768556c9ba875ee4909448d80b3af33e30837ae614994360d9a5f42c" . + "09245df6129712de2a683e9bd31433e14793be84a46fff11f55f2242cc3c74ff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0085e9789afb666fea5c49a39127be51a0cf464c7dbd4acf9d66fcf77351df8c" . + "0085e9789afb666fea5c49a39127be51a0cf464c7dbd4acf9d66fcf77351df8c" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "0d37dd679fd9be0cd74f962c8b5014a794c5b078d59b43ed33271c22737dfa2b" . + "cb1844b55da272d7648212567f2b2831ee9ec60eac7315f00a5c0283d5b9380f" . + . + "2ba61cb9ca1218b91c8bd9d8bcdbb0660722f15e76fe587f0f3f8670d60abe36" . + "51ae6dcb6bd8fb2cf155d26039350f0e7023fe83a55e86a6d8732939005fc00c" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "772fbf014b7fd6c7a3516970892e9fddced26578ff845ec29343d2165df653ac" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0952651639c49d351e476da2f2b5cae1a2f2466b8addb9fc7dd0ccd96d1917a0" . + "0952651639c49d351e476da2f2b5cae1a2f2466b8addb9fc7dd0ccd96d1917a0" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "8d557cba9764887ac0c67f52853bf26b91d9455a76071e98f25e05338808a539" . + "82917ab8681da2dbed8d781310b1d5e3dc2f3bda8756a362e9647d5372af2580" . + . + "cdca03aacb276cf78292aef7bfb9afd463d1f8e6c66004b181968de0989ea822" . + "a1a677485f03a0a4573924421b6372bdf5d51f1389f7d20efc9205cbf4407841" . + "b5b3b5142e1deb34bbe41bb6ba1fe96f90ca77f5cb76de16ad7c424543c548c5" . + "70fa41883a3634c6af50afec8da62693f6ab5c92c2356ffb6d4ed2c2d4597b01" . + "fb317c51acd0c7460086d9073f7d3b53096b42472ad14f2abf251f04b28e16f5" . + "36fc9ad280c911102e76db9c211374a0224507f12164cfaeea9661cde0aaecfe" . + "54e54645a09e76f805d76b362bec8c83c3d2cffc870f94c082532482a3cf2e08" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a8736dc438c3b0c1c4b56d034dc88658c3b6e9d86ea293d20d8c5ac92b0280e" . + "1e906c15417460602c5efc717590d82fca42607b77e77cfa67059c43e7770684" . + "818f3d9f399b02cabcf2b894ba543eccc355c34f6ed0a0924b396dcebeca61b8" . + "8a24e0019d72169f35b88d552341afa3bb5511ae31021971e9db40617189c0c8" . + "4fe46c309af27bec671cfe595b882563d1daa92657ddebb9b8cf959c4185814f" . + . + "803c8b1ba3db7ac5feaadf9740b45bf29389a999503b0a00dc13524f9a93cc44" . + "3154ed897731d9f61a026bcdfe411a69438cc3556c32727b0a24bcc64dccbda1" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "0e43c2bce8da65d804c3628780b7531047aa61f825e4bef657175cf72dc1d2ec" . + "efbafae86ffbf4bf8996fa9ed89e4ef21f2650e2f7891412222b1d2c1c646059" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "5513ae0b62dbbe315d6daf47a4312474ad1630092e340ba46f98c2e6e8a55889" . + "c64519ee4b06cdc96d25385284876521297204398b53f1a256547afdc47ff3bd" . + "a37ff197b7eae203d41ba8a5220dc50d374b106b57aff2f952bc113e83000e94" . + "8b0b7884786973d43370e1b022ae98ac2c945f680b9d73bee5545b08df8d1d4f" . + "98f4c63f32ac0553e5c16e21a617d65ae104ea44c526bc8535d54a0cc33dd67a" . + . + "eb0c774dd586c5dc04a9d3e4c5038c942d2f92ba92c416bf2fb9c1c5265dddf7" . + "d201fb1a5f5287e679e4ff3fba4f9b0637ba4fb544aa4ce7c8ded61a23dfad7b" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "57b000671c5b0a349f19d18ef83f0382211aedaa616de7941b9dcc2f2fdaee2f" . + "1b128f3cf330e770c0ff41ebcf0591c3ac945c94be8fd724450d7d02a10391eb" . + "542fae80622159f5d5acb66cb2977a5fdc53ceb3a1a9c239e2a85a11d6dff6b9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "30ae8fe9b2f3627c4cc77cee3082ec1aefe7b46f3ff262f3a11a945ba0545627" . + "f0552526e40901889f6fdda16bea72324b4c20190b6c6990b2e58719724bd6ad" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "04dbbd947ca065866838e7055f12a75418d72cc5db82c6265cf96cfe198459b7" . + "635a02dd954092b0d9302de766e357a799e86fc07bcd3e064b7dd2c343d66e38" . + . + "46ed131bce64ae80fc11be29ddbe2523535aa09e50411be51b00e5304818a35c" . + "4f484033a027120098c94af7082440771e3171a612289d9973a9900406fed22c" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "c8eb14a9f5eebc05f0c302c85765cb1960b90d1d5888150ffdc802959660ba47" . + "05b74207ef742bc6a44a1950658239e137e9624e6a5981864fed202908afadce" . + "ad05f3a62a9bb7fcee365c936b494cc09a9c19cc1ba66aa0df429496d9e66887" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "967ea7143807169c3f4fd9761839b460e041328c126c5c5437f66d9e1996b2e6" . + "967ea7143807169c3f4fd9761839b460e041328c126c5c5437f66d9e1996b2e6" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "887055042d90bc39ae0fadb1317e141e16eed8aa3b81e5e162447a9e0d15fd7e" . + "52b17d1006e4c5f5f87483f840f621524d0b4e9a1227db8092500f5805506295" . + . + "3e2f9378fe08a97a2c6bb0b16e59e75ecb9cc5209dc4d2509e6d6457772581d4" . + "5acfbe4fee80b98bbb1722ebfbc080136fd02827f8169767c96c5b06c990fa0a" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "4c1a229f607d19ed3827fc30a6c6c5bd6869235c1058348b909793f5d98bd954" . + "145362cb106c1bb4a722db408d80cb968aa7375e90c8170b2fc14ddc9dc57e9b" . + "5fca961bf0bdf651935fa1ecb4fb2b56d2b04c18397ccf4ad691ac4620bc0667" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "3953b393914fed9176754c082d9432e1807d38af58c9603829147b72daeb7029" . + "3953b393914fed9176754c082d9432e1807d38af58c9603829147b72daeb7029" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "dbca9530563a511ec11fc019ed8edc044fb5954ca13e7bb6d4c3f0d952cfdb8f" . + "6d0834eee16fe671e7a1b78a7aa5257fb7874a6992c9342b61eee7b3470cff14" . + . + "9aa1df03d60204fe5dddaf4c15c10799f3210c899281e7e9c6a743a54482879d" . + "89244545b53a889a23756a21bed89f12bce74ef67921fe33f4b84943636c935c" . + "59090a163b3011e09d8fde8a441fc293ab6ff43c44815bb5519f45311eb4cade" . + "b63d2399ab4453c5b67e85e6b384a4be638a2ce892bfe27b1fe88db2eec6571f" . + "aa2f16ed913d84fcb4261c894db07edc07051bb3db2f24bf48d2d71af6b7bf85" . + "693c8b513be940a0c7e17b7c38414d85d29ddb49fdcb67faf5c9824dd157314f" . + "3916a86cfda08b3db1a1407eb4a1726e2e1f37c77d3e5e470d3ff86d6dc78a3e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f5b0222825e9381046a0263e5ee86a285c52104e6ea2f0040d1e5f36af5e0871" . + "2d426509a74008281a4b7717091206c7b091204520086ad2b20a8e0b6d9be462" . + "2a75fc21c406fd838cd5f61b232c0664257273e1dc39b31e74572b5e12085d9e" . + "660161d38847a76016ee70e25eb37f086bc6c8d2c5d703abd75a3832a36d60bb" . + "451b702001e869c063ea9145c98ac749e147f0cf0d01b401df9d588373c46af2" . + . + "e713280c650fb9211fbdbe305fe724382454f2e3c8e588139911ac9ede4c24c2" . + "d0a81a7d44572c397ce4c44058606973dad0837a94b207fc3856cf14dc440e08" . + "0be97a098dc366547fe21157df14d10a308e3e75f5dba26074f4951c98cd1faa" . + "671ec131b833a744b6ff517d7724cadb844bfe2c714a099353bf9b0078f48337" . + "9d7273927d1201c9680417ef2cda00b505daf054f5f5d3ee5293d3c04d1b7fd5" . + "fe682732f96a4a1c2c2924b2992fcc67b48515528bf26d30042fc4caa01fb09f" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40cf6379d1faa7db12e72702897ede767df90199b756883cc63ad9d0aed7e0b2" . + "40cf6379d1faa7db12e72702897ede767df90199b756883cc63ad9d0aed7e0b2" . + "7238d5eb1cef03b158f29bfe96380b73a941b331cbb93fa20279d3df0776e274" . + "e15971b14751c5d016921eaa03e4fc2e0e400909c935459927d7c39188084e6b" . + "d6e175d0026e2b2eec8deaa0fca61d57162d098d5cb2bf25fd0652791ab58e9f" . + . + "8749b318fb00fcb0b2aaba2b1a91056939260b1e1d078159c44eb22b17dac90f" . + "feee813896166a4da9a2f6ed660baad9f35d16fae7d3a92ae29ade6a465c97bf" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "f37226e0a3f11f61083c6c4bb1c5436f7bf9cdf6a2beadf70731f4994e5773b4" . + "dfb8f5491999e765af08e0644069853ea0fe0b505a12afeda46767326ecdd052" . + "68d891c05649f2d836ca9c05b67fefc249cd97dea535e7f9ff86fa43214cf4f7" . + "264579c4cf7c569eab06020d61e057e943e1590514fcf024ded522f676f4baea" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "678ff8ec1561579f4de24d8782a4a4b3c3e79cfd14e73c19e4cadbeb1bb41a9a" . + "678ff8ec1561579f4de24d8782a4a4b3c3e79cfd14e73c19e4cadbeb1bb41a9a" . + "652683217b6a7f2e3d8cd12a1506b3fbff1d1f12eeddefba689bc9f01183073a" . + "4b9d0dfa537e5d79d3c0415c95652fdfaedcedea06b8dc2995dcafaa08864288" . + "2c68c6890a9fbc0de84fd847745731ebff7aa8eefacc271437974158bbb70aab" . + . + "226c2aa895f47e22d69c967856719515be31420053956af1bbed1c4b41f623cc" . + "bb7e9bf3929e29600c80ebe51ddc025d3f100cc71d5bd89e47ef858f84477c9b" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "01cf5e91f33be6ec76abf6a8cd79ad81d98dbd6246cb956c81057b3cdf32c883" . + "a959f347603b9a8fa1b0dfe301855ed178d75fe559c09573af9e2334a22e68bb" . + "6a62af4b2150af3de9c3a1b7ad8d5dbbfa03430dfaef0269ad95b5196259c9de" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "3adf2a4ebe731ce3dec15fa08b12fdb87b9e091c90dade4483fb80cefd673ec7" . + "65dc16e19618313fa1ffbac310b5779e5025f8c810762ddcca79e095bb1fb917" . + . + "1fd10d9aac08b43bf3b42916c5fbf45327d66b2c516edb711ef07f10104847b5" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "7d927d20f6eb8d7acd833fa526de76cc45599ad941e0b5dcd9431919b9bb671d" . + "b2e46d9036ba2ebbf88f090c9006d3946a59ec16a2f8b4d70d2d3856ce8096d9" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cedd03dc7a07abd8a5c344b690e8bb02265b5491ba01ecb6981affcb02dbf04a" . + "5babf380a5992c1976e2342b2fa7f717427911323404c5cd1d1189c281a9647c" . + . + "c8756d3cfd2c0985fe13aea16c5bfb138de8bf2fee50dfc0ee376c6a4421ddf2" . + "e29d37abe8d989842ea50c5332a4c651fed14f84386ee7cec5926c9e52c53d1f" . + "3d49754e05968a9c543a23cb4892f368709c2206328cac7f7fd988f6af8e31d4" . + "fe18d19b23496f9ad76bd24316a2a88e33a19dc6b00d7caab79934e5cf7787f3" . + . + "4c6b67748419816deb4af168f610190190080d0e18bf2a2a33412da2c5fae4b9" . + "ef83952d6b6bf40e09be46820b75dfffa15492eec2d3c0516925ee9a73589fb2" . + "c9f229867f229d238a856e8938d0c47e026453fc1850c53e66fc055a5b876c80" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a913c3ece2faea97f5c7359656e1f9ae77938ae2709bc07eddde0cfbf5b852af" . + "cae5d553c39ad162f4c54a739542e90f821eaa36ec36559155f2453e087125b3" . + "6a0db4931c34a3c0b8c6c33c29c10c1c312da7e62041d974442ab851f372bd21" . + "ad2845d181a2a52f0049f04003974936f892024787aeaf24fa9c2b20205468f9" . + "337fe163474362cb080263f219e4951c0985e11cafc28e803f214dada676c78c" . + . + "8b632eef724333c614e86176d1f3307ef046f6b36a288ae789c6c2d694229722" . + "7b43dc39b3a8584ef9eea4126aade71f9cd9c9f9dbd02d4d52fdcc3f6fd2f9f4" . + "53b47f85d7ed28499892a90049cdacec2913b4f35cc248deb88dcaea774a76e5" . + "153d9cbfda37228e79442b1b8a8799d562868ef6d58f93f6ce94514ede25fb14" . + "94310dc73e55aab9ce806f4053aaed7e96c35c562a0e7900c1cf62b96d0844b4" . + "a70363d8f81f5163826213e6668ce68ad822f8b02e547b91881a65534dbdc831" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "d3b79e9b9638433afdbdf43969e5dd58f33e9ab59e82be70f0154d4f28ef0c09" . + "d3b79e9b9638433afdbdf43969e5dd58f33e9ab59e82be70f0154d4f28ef0c09" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "a824c912f3fbc142876bdbb542d8b90761d8edc05edaff2a9a4411b3a2cd929b" . + "14bebd614d3e8a10fcf6135ee777299050fd03a0aa8ab4863b3b2ec60815938a" . + . + "47c9173a6be4a893802bc53dec4ad6a884c7dc1c16f4204640e5d51298ad7c02" . + "22d3a3c0e3d26af6e2e5b7e31db0ac67ce0dee955726948f9b3a9daa3a6b489f" . + "45640839700d5e7a9ef3bad6b15cab0266ac34eaffff5a1950bc43d9658b7678" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "1eb1aa950f671bde69e544be1fa5ee0278ebd95b3e6738d1a6519413f50085ed" . + "b7570cc6ede9565ab26fc64bf8dd08b44ac9858d86e26ee0a7f59aa28cb3699b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bbc99ed4ca88cbb6d559034878262e1dec0e3a07967a7fd452a68d94a66a7b7e" . + "df5bbdd88b8ebdf8c87666f67112f3804f646e48d70ec9a435006a72f8bd504c" . + "5ff0c21ba6723a875cc99d2f267d0c1e7ee56e660659082339b6cab39d71e749" . + "6943449eff34c49efbe413eb8d76859f3f3e30c48a7a99a0deafd01636030f84" . + "aa9e74e8faf47be7fd5d0900eaaf72b9b39232540a6d77fb51532eb8ca7f2828" . + . + "b9cad575c078caea402de546e77ba32fef7a87c8d54b53cbee14285f9a83fa22" . + "791479b223c8474291c212a4f3e4a6ddedbe5db29489fc86f9da8408d0ae60d7" . + "50e55454eac27cb31f8e72a52bccaaf9cf855468e6a32722306621b8d953f059" . + "82ef415545d171a15f6a891c49cc070b3270a1971e814488515947af29556b8f" . + "8487ef7e93ea00f41e21803732a1d130264f90d060af020be36bb8721a77c678" . + "2f4500b4adf073194e1aaba23b58e233964ee62ddffd937712930c1c55fc6b09" . + "057db10d56864e2cc1bbe64c7a04d24ec2e70cd40cc0ea21bda29f6f120026f6" . + "0294769e916ba664d57ad1e4184c18ba754f3cc1609c892bcebe8ca6bb0fe582" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c4da025d6fd5077504b045cdb858301d9e4177f008a886ef05eb39cd79cb85ef" . + "b284fa4f00ebabbbf03fb106230bfd0ee7fb9a890b0819cc339b9a3499d32d15" . + "32206ba08cac75a61bf8824efcda76adf62193f506185262e3db754788a35133" . + "d0494f8ba6b250c82056c071acbe95081c3fa2c747e1aa02679cc762ffb6994e" . + "664e11107da82d366ac53e0e0a747c8dc9d97e4cd527216eb71bbfff5ab8d061" . + . + "497777469d2a7390adeef71aebfa49ae8697bec84d9dd89ece14cdc125d35dfc" . + "36b24e15d4f350bc366c0394289e366cf6f82447f5d479079fc71c1fa676e2dd" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "22937d1f6365843b736b3f233daff8c71855b5286edc227cef823dc46e53cdf7" . + "66f1da2258c7e16fe7278b81b2f2863ad23e15647ea6b9558ac03d12e2b5c7cd" . + "0ad6bcc566d393f2108a99277f3b345bb76bee66430cf17ae40a336243f335d2" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8484deb52f53f634a512577f89ecfc1510fdfbe75bbea20a5d7898ec5c09ec10" . + "f7718c9a2f98fbdde08ac8d356f38307c828bd24c72140198780f1d0666fa541" . + "f464cd14fc43c86fde02e2120e225c8a4397b766c48dc18a94033791466f0255" . + "59e85cfaf75bdb5c4d83805345c1f6167c3405debb76c8bffb0177fcc7430762" . + "c84e6b2b4340764efa389b15a7d449b0858959c5a2e7ae6190692ef0a6ef92dd" . + . + "0a1f0fb2ecfc374186833544856d9df146522437e4a348cf06b16f2675c2de32" . + "eb7082903ca47329df8a139112d8ed841992dfb1e3f35d25a22c6895b0713399" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "38c4666ded0ffb2a91dbe4184ef159b027adfd021a30c384a80419c89dad2ad0" . + "e0f989570c4dd38905c7b77026e14652eb894f1d6ddd990ea774624894c81f19" . + "e8c4d449523d3f0cb5384c756528171d18b5df0a5560a73ad9f85e65e88fbb80" . + "e8c4d449523d3f0cb5384c756528171d18b5df0a5560a73ad9f85e65e88fbb80" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4bb9b8b23b4eca399d3c76a0967c02c3482abfd2a5a94ef759c28fa1e192724c" . + "575943f7e3360c2c6b98276533a55e5dcf983d653719d44bb5c222211207ffb9" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "5788b8243da16e59c2e5be23b61fbcafd14bd71d9e362f4a23289a2a97df2bc9" . + "cbd1fbe5bddacf00552ea824301e381fc410794c67083c7fbb9fef8c78962581" . + . + "35e5f71ab5b8bdb6c48c4da170209cc4c19afd4b01e83cbc5cd020b52b44fc51" . + "d262cd001db7fd77cf0b5f501701ccfc88c7e35748b1b8929da3d105a5d2c54a" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "df0cb7ccb4428f83ec7d66a57ca8b38ef197bcb375be7eaea9f600d99872ad93" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2b7503a562592e051c3e8acfc547e2d7067bd5ab143b626366ece0cdace2784e" . + "a8dce8a002bccfd09352ef690a0b5550184da2310ede9f32bad0dae9ba73f123" . + "e6392c3860839d6334e57a5b735fbc16e34c0ff96e7880c62e08625989b80306" . + "d206fcc07d7574dd11e9ac4471ec7dc65ec431046efa09a8f213693b421a794e" . + "25ab0dff84d12e27b62f04356ffd5ddfe651d64f4b5fd20a4614a2f59eea2055" . + . + "a6ed3554feaaa793faba60f863ec64eec450de7cf93d8ed2970e4b716c6ab37c" . + "db0f0b8f8379576e0b5069acf1de8ced8bbf72874790dcf7aed0b2990243dee1" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "a6ed3554feaaa793faba60f863ec64eec450de7cf93d8ed2970e4b716c6ab37c" . + "965e753a8d47f7b02e63b95a0cf80a0a98f0adf9846e9f004a0220ff700baaee" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8d797297346534ba45bf2e3cd010da11914dd28cce5b913dba750a7b95e516c9" . + "e42b30e4036d9c752bb16d7398c14e3f8fc3acae83a94bb4e6cf3f0ceddb5be9" . + "957dfab90d1ea6b17bbee096c4caaaac122d837e2b2968137ef38637ca48db79" . + . + "602a0843d3af2b6424939c5f24386c76be57a3d7834eb1117b5d88c81f053860" . + "67cb7e9c87253f06e7cda723e3fcbee9944be9cd821138c2213a6d5258b790a7" . + "0eab66ef0b564dbc00812a4c8c02d07848174811eb431c7f0dd4c16df7eb7c1e" . + "f96b364db91aa1e659efd835d8e48e991fb43e8bfdf4158acf23c9b8b7d997e0" . + . + "241858ebc3c5539c7f1e8eda16be4551c4708f8bad37b14f12fbd6427dcd8ee2" . + "5ffced72aa8369928db26b90b307f96684cc30597bcbdd553d321df4fca4111a" . + "d4ef2a031d73151f8783b7177600969fda2171991bd2eddc3e879b3365812676" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "7f6a74de1bf05a0cf8d8bab0903f7025dcbc62532c04ca20ce55023efd1ba56c" . + "6b655bf88e2daafee3ba1d504c4e7fba2d9cc250909c531e4c2edc4e27e54d1f" . + "76c503887238b94e0cd27716c100b45179667a94406989c66afa95793d35becc" . + "b98c3dd242d53ccce4e3d437430a7217df586d26f2d838536a82390fb414e072" . + "5f7d283ade1991dc8c75b40f374d072cbd13679c3f587bd838411372f7d348ab" . + . + "cabb7d0bd14356323b816d970823d8bba664172821090d13c52a8798d30391a3" . + "21366fa6b15e4da3c8f039c9f993d42ac88235eb5b69198e2b1351b1a1e79f71" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + . + . + . + "20c7261c8bab10f69fed370b809eb7908153c694ecba8c0e9ccf66af24f2018f" . + "26eab11218b948169e2f90fd81908458d897b76e853136216bb4b6c28e884499" . + "16d6410e6491c1b87f56b25c4837869725600f2b047d8ff7ee68ec4ca7d918c6" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3c9d51bb5d5742f899b14c90c16d455198c7df69068349f878117f23de372374" . + "981faa9d9324693a54b839d2b683d4f6e5bd44a7a1489eadf805382234836be9" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + "9c5547779d9725fa9beeedea45a9be29e0498d3f106595cb100e376b190a27b8" . + "aee2aaed7006b3b0d9c5aa50597a52b966d38bb32708f025e2771043a4d50967" . + . + "9284bfae9a8457abb67db2f137d0fd09947509575989ad3b6a2249be9f6cc8b2" . + "de78d3d8ccc5e7799ad61bdac1dbb108b7ab94a4e65ca9aa4906b11ef603c293" . + "840680d6a49263690ebe09642372c48a10b046a99856b1253ccb3d5f7e145dc8" . + "5a5a9658f4301fad791b3e1fc3e5dd73f37a2019c72adbea75e5838d0cf7e1c2" . + "841c45fbbdafa12b4323d3a1d1f0d9c64776af2380909d2e8ad8199dc46202c5" . + "8ccae2f710cc031d001153c125a7f2b54ba0a22d7e6ee0d85578d602506f71a9" . + "9bcdf1f0ec386da35b8132012a8fa064e561a9ab55f59e241fc19e5df7ea6cf1" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65ec90b55bc20f15d5838e117601d4825891c4b431d5ee3110a0dac4b621f65e" . + "0f092576e526c4ea4cee12052adfd68d99853cabfddd36e67f0b81541597ac51" . + "571fef046b5221c66852243f622178305996c1d6469550997cd5ccc97047a389" . + "2d740dd37f7496a70612cf9f064649449c76936ebe4c4e77cac4a7f9e6904f0e" . + "f3a6c39875eb888b5387af9946834e675bdc6e028b412e5fd9a6a2ff89962c87" . + . + "0f240d20fa0e1cd7f22ead20a6d63378b57bef391ee0536c40a0406ac1ac84ee" . + "d9fa0a8b1f5930367b02a2deb3583302a8a12a09b26676c74d9ee13e675ad8a7" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "8d67722762867340a081a3122089ab6a4d78e99f9d2d1b3e282f5465454a00e4" . + "935359adeac3477b48a71aa95b4ad2cfa3f06f39fddd717df2d1ef91b2542c9b" . + "29990bc4a24c6315450eeaf9410fde4e9c030c6ba4c040a84ec0bffbe8f13cf7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c9298abb11bef51d2e22cdb2114a7c4bed00e398c5b9ee3a81d87609fbdf1abc" . + "254ebf3c35b64a4a39123ba92c98798d8b26b1397c359f3813041369a8cb1868" . + "1380a6d484999aa8151c80d5a9b8a1e61404ce66e505c7a2d609e5b47b0165c7" . + "b675e199a7041a58192e08477c0b1e8bafc6f08f8fab3ca1f1c2268b6fff0336" . + "cb8fbe6662cc8ec12ac8ac125f9c9e63d62e491d91bf550b780718a0954c6dde" . + . + "4d87e7c77365e9a75668eaf4ef9f793eaac73bddb494dda965a78a8293d444e6" . + "b35a68390002b76d2ed3c8ef47686d10a1cd5f848f1e7804c2b4dfb590275a70" . + "78c7f1c12db904ad372996b1357df7ccd137e82ccfd00a6288da16c1a9f12b70" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "ca05ff836824f9a868d717f75f9964cb5b70f9b35fb4d376a1ae9ea026f22d87" . + "03936f68329e2fc1ea55a617747c0370076694ad82d43110128a713eb4d04f3b" . + "06f6784ac1e3cb4d6f1a0a2e5fbaa99aba50a7c349b1e1d7fc71a299490aad24" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "952be740e62f1a57b853ffef21e951b11fd1f9212fe088f5fca0ecb3875c4dfe" . + "952be740e62f1a57b853ffef21e951b11fd1f9212fe088f5fca0ecb3875c4dfe" . + "a4228e6449a3ed551300981706c5b4d155409519e20b2aa4cf8be00b5be67361" . + "f92b0d2af1cadb1776495cb48def85a048b95c89896389b36ef2efcf1cbc861e" . + "7db98a68cf17779b47a656e7e3e9d3d19c3ad0b5dc21480ce8966fe489bd5aaf" . + . + "c2047a49fcc2c021b4bfd04067ad054b49cc75504649b18e529a8c1e0aa0704d" . + "f45dc2f125e9e634358deea09042fb1a3d59779914990ffa8a9e1740f4c0434d" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "b7af33004a63c98c72f7daec5b25383fff386b9057f9bab9119bbe7db27a653e" . + "ecfc87b53eb5ca3a51e328a999b446b44616208e87ec378df8ec7d158d86be47" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a7952f70327286f1eac0cbcbf782e1c3ad4e7c712db2b1cc7d0aff0b847356e2" . + "60af84c2984f27545dc00a6600b2670490705fbb07f581c2d750072cbe7445e2" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "2144ffc907705299d95c6098c3a5e32fca11462c8986aa006241f0df5134c116" . + "7bd3f2c0fdf4d08450b9d81477269653eb4b3160c167b2a7e136d8f9168d6c66" . + . + "2de6e1d6c9f4029e4b3f67dedc79c126af34cba73f85f1d32480e11e8de01f93" . + "f12352991779c9873ce6625651d8a2b5bced1a73e94c81d5041cc47d3c02704c" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "a061735dc96b59aba79ff3769b4f1a8110421a372c3e1e96d244166fe561541f" . + "2db3744ebbd9c298fde062a6c75a503f99bb868ee61cb1cfb6b0d28577c8987a" . + "bf23a61224d5d182aa673dab200cf88281a31f4399a993cb53b7862280398780" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f15e10d6d0e0995be3a75c2cb14f7bae4a94d2e7352415cbf407d0e0601f37b6" . + "ad9f4371f03317be6b22abd2449c615194685b257a0532bfe2d62e74eb7e5f29" . + . + "130725c17c0141ce92c7063f91056cc6ad6851c84afeaaa99b9ea57be4f27155" . + "26509ab4684927ae3208686973ffe37950ba7053c94ecf32efe75fb9d977a805" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "f2632e4d130d5c621e715880faa0f6e5ae9ac64f9ea8e2eca1555ea59f93aef5" . + "94b99918bc5146772106571ed681cbb9ca0c930daabe793fade89a2f5846799c" . + "86582c5db9388974b2cd2efcae136920e274e9b91582221fadbe53796b93d68d" . + "264579c4cf7c569eab06020d61e057e943e1590514fcf024ded522f676f4baea" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c1c10b6c6e332fd67c4af7df897f004576e45fe53bb5a34a0c0c0bbc4138c567" . + "8ba4e720e980566a6a971be2f4aa27995964eaa275c8ba4ed88d28451d736067" . + . + "5234caf065581f7bafa505867e8973270e660ad51a64c5dd5ef6cfc917cc89ef" . + "a678c6e12ce394a267af5a5f91c585c1ae39d5549a5f16511092a4c880e401d7" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + "45b7ae5d56d7aab3cc4d1e4321c9687d41551b832c125633f63e09eaadcc45ae" . + "feac77ba3d1b99ab7825d371971c6dc69016b28cf1218782c1c9b3431008cff0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "625445fdb5bd62319536bb428d5126c33b3de171ce2ab8f69712f7f6c150dca8" . + "822b10afdc13752a4b2ef5352e2985d4d916df0dce0490c344e6360de9f19f83" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "185822a0ad194f2ac5a3b85cc1d06edbe9e922031f8fdb6f6729d02e083f38c0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ad8bf8b3260a65da542cd981feb31ac99fccc79988ebd21e3dc5f9c8086470dc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7e2c04b04eb63fb9f21d3fd1afa32956d1757eaaf0502cc819f5bab3ea3a4d8e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "349980c0a7a938254d3f99e07c9307eb36ba6c874e1a0b35066be85368ec7108" . + . + "b863a4f4d1a5425456d8349d5d4849de6e848eb0219883eba1eace1a3095f64e" . + "ce48d976f93f2d54a6c5e337a9a61be8dbacab1b68fa43d5a3099c3e0de80c18" . + . + "4919905584c11af2cd48864cd8552499616ebca3f74b74c85f1bf31cb8b51291" . + "c807e0941d53f9d739b22d345b9e3f522fbd2fdf8a4c223b31d0c0fdca1ed19d" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0046c9dabf9a326c313fd045bfc9bbfbef238734341ba13f065413a5346637cd" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "cfc3345b9fcda58b83a8961c65a9cee2fb491b54e14070d8afb5ef89eabbdf50" . + "5e49c1ec6428a495f1a3a84af77850ba258b910ec91656e21d9fc816285eb0c3" . + . + "6f0918e93ee31fe99091e0b5a9ee4ef0db950c5317bc5f912fbe3085c0adb4dd" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "d41befcd6d3c18a0e05fd5f7be5d631d9394b9813432870a98a94c7d865dfcbc" . + "ab284cc24d579b95472a66c4781cdea8a227838d6663cac8463abc4866ae0d4e" . + "bc40a6c687a764e785616ebbc37f147906e1c075137eee7194b380c53e38ffad" . + "e6a28ca5fcf7f69df7b0e085e8ca0a85fbc27a644787af2c7991ece3cd8d92b2" . + "be9f1f3155e7c70934f3df325357933bfdd5272b1341354221b3324949fabb4b" . + "a8844b4c7106ec30d1ec1cf08ec741ba44758af6c753f1f5c62b0f96a469b7a4" . + "85f28a8dceaddda83b7ebb8102466c25f692911812fa3fab149220f60f25da74" . + "7518a56d385b16d99cacc619425143fe5da42780151a387fcb1d76e5035203d5" . + "58c5cd5b118c22552c03a44414de24d678a68d33140e2d484ce08d107c3f962f" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2b54d6617859d4b5f3af912e9d592bc55c692dc56510f0b5eecf71242cc99c90" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "699de780da801fad6324325aea9c7173b8eb86705cc3d0e4e26c4db10f87a4fa" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "6ce74e7ef0d42380b1c87a49d795a9eae5edff54b6df3701518a02495be1994d" . + "315a97f1d505484ca77ff7ddfd6e705820d83de04f4503243031f79980d6ecab" . + "9f8c2d4beade49c7fc7931822aadc3293542ea5db7d310ca46ff0dca465b9256" . + "e61bc58032973451841e30ec50934aa6d6ed0190cb00e9dbc9d6218fca80f4ad" . + "4c3354dc17ef098c1cab1b872479ea091ca8923cb32378af842bb31485751e19" . + "5832dd9a1fa96f8b803e25b819b7b2b475b1c2ad721f51af77d1d2caf2e08e44" . + "142247f61ee0c38f53d068d69352115f301e29221778e3f46c0f260388aa9e13" . + "5e203dfbb7428f357db8827e91d3aac54c4d3f7d2792937f8b6218b76fac0bdf" . + "0d90720745a3a7c39ec04f616ed000361c5edc83e09eb11c253713336be15ed8" . + "82fd20e8ba04dee55ee5f02eb2e33874d9f85903b0132b99ea20b65719639a8b" . + "366fceee162df4399a91edd754523e0fa51d0795a4ca2f74e8952fcb2ec802f1" . + "ea03deeaf558855937004d05b865b9aa89196117d1b0ce916343334bcc99f767" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "426bbbb35c5c31f3ade5f53040c674c8fae68a1efc1df813f14ce3f34c29247e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4b8ad8f16a0bd973c183f668370675d38f79f829a610056a807acebc8e6318ea" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "84c7fe44199eb32136df116402c3e85dca9b59b74054394bd114d3127c77c3cb" . + . + "918810c52633ff7afac28a39337e56dab1eace80e7bbb063d1e061b536573670" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "484a42864879289de52d1242e85f00b007f391e17a155f869363aeffe8ac7342" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f230c9e04f635ad8caa7af03c7ba22e629bf3d56458bfe88632dd7ec3d224821" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b6baeb72f4143744929b2bb7be612083bf4fa446b72474c2dbb7bf8a36e36497" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4f12b165d2f2621c27abd05684d70c78825810a0eaa146549d3ed908a9874a17" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7d38a2be23ad5a22af4e7c64205fec7697cb788334a1f0f258a2c86f81d3ce11" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7f2618b4d6caaf672bc3a75b63baad1a95eb63b296009b67d9f4d2345a5e6378" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "85fc2515d369942b707d8f30ba189f79eb8a19767a335f2aef9bcc2259539b84" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1a6fe893eb2713c239b0c81ed50dae73ee9dd3f4c7c126947b4f16fc58dd3b5d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c75a3e42a6377a7da556ad83feed8e7fd187448e47bb85a180e93f3cc9f2370e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d36e57a7930c6d2de60d1d16c08df9da9eff61b53d71caa1d1287c9c238085c0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "e7bcc17483ab7a92a3b895ab0b37206972ca02cea6df7c3b0481fb46a15053d4" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7377c1d0136b32e22e8830db167f75afff8b99e7a650d78901b839b7ea4477a6" . + "5bb9c8489ac35d30a692b96b4f3c70bc55c5d3f047afc717b39d091a472178b3" . + "5c7373252bc7a725f65b22a1cc1e86c8d2b1e2d26dc2c8a7392d249b06ec238d" . + "6d54f5d84441a398c109846e1ddf9c5b6299616f608ef6287b7facf42243632a" . + "52e168cb806fd4fc16ae709c7879a08661634b6ad964e4515c0e3bdb99fc86fd" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b086a69c423c0675cf68bdc46035a6530cb1b5196ad07b54ccc33ca5998977ae" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + "1d8252ea5c388771f6a116d2711516851d01e0ae432ae77166c0479446dfe8a4" . + "8126600632ea2073ae45a7f65da3cd372b2db0b71f244a662e59fab567aca62d" . + "a61daf5457aca3ef7192e1c09bd7d796f2ce0af32bb0b2b4884efd587da38216" . + "44eff86707f5cd5ba543972844502608551660abd2cd9902f217354c1c78e6de" . + "f88dec970e162be5871226adf49a785837309175e26a126e7e3ff8a39bc9c9c1" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e50160bf078f6d6a7d7a45f31fd2162d9016db494bb04138c07c8cb223b3cdef" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + "008401a1a01098a8da4fbf204d9b1faebd4c6fc8f1dafdb1cc8d8a9a69ad986c" . + "0fc7c75b6fc53eca79d7db733c245d729774684b7be08a40ca1ac1abffb67aa5" . + "22bd965703a4a566c7b9573fc682d8a68a202b11e46b9b1450a3d66a8a998a9e" . + "21f595938b2e54d097fec286b75bb3cb1fc6fc9d269a8b3f4dd0584f9084757b" . + "f9d5de4bafdaf4626e4f16c0871b702799e0dfe8c9237dbab76c4e248ca8d756" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ade3f2d63c8a53a5540be977c4c9dc01554a87bd416196338d86a9c1747163cc" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + "fa94865f6465d815fa113f381013a332708ade53713db5a42e1014664f0c604a" . + "a5819ab5a41b2128e1eaa6f9773979a91c177fa3ec57c0aa7f2f177ed867bded" . + "be9f8658db88395697be9c56d98ebe3bff119093ddc05e861abc06137661095f" . + "5155f594c7d4177819bafcd8c7ad94b08716dbf69e17ba8ce4d08e1f68836bd8" . + "a34ce9098ed26ffbe5543e9de5d0102885050118c810bcc61914478b7d891e10" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "29e6adc6828ba2a1adb02b146848549b1735fb961150ad0155292d2074e4d3ca" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + "3741afa02713e0462d9576ef49c870cd6aef6106cdb29b160b1b23b1dd2ecc57" . + "36c39b2e4b2c942244698ec4b35a0cf0856e676dffaa8b0bb80ba63253866459" . + "9e2fc6820766ef972440e4c6580ed44ed7b0f0ef82ee7ccd178c4aa5af5c5486" . + "20dc9b108205cfac55ec259b36e9e24252404e7fab24550811aac9ccfe743223" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "be3f76d48c8c0b918b8c1d7c0cbd4b53668a74b29f3d8d265fc6ec07c7d75986" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "bbcebf9b6e5761512a356bfda8cba430585835b7fa463bc409236c37c50ec3ac" . + . + . + . + . + . + "0cc8b9dc62503dc382bc72001acc09418445bf8a89fa81176df361683f7abda4" . + "e2fce1b347b57f50e1ffe99003441ee29de90603bbab84dbc98e0464e2eb1a7f" . + "49240935bfb5ca2c4c1d3ee281c68c1ea073c1670a288b7d67f8bd6f960702cd" . + "4ac5c213f93674a9bcde8d7622b851a38a517783184b533d71bd2a07b17baa8f" . + "de153ecbdca61b9871df0c4f24859f19622620883d9047b76b4b638dbc9c6909" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "db5d5b477fc79476b0b0e208665fcd01cf0fd11476381ca14ee31919d01acbde" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a65efb4107962be529edae65bf4423c03b449e3cdd2c4e69bbd567a15e606c4b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "72d07373befb64ea439a68aecfc3521525f445485acb642c3744eda2263157e0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "e5fc3e9c31a518e66f17ba4868e83c62b2d52132354273b7fef5c6c79a2aca39" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "47ffacc078981100583d616e5c7c1303a8a18b9e7c3a193bb813a6f502460989" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ee1a0d9a7d6b7f9ac2cbd9d62e4dc6288604edf588ed026f90be5936f959ea5a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "eebdf1ce3d2b01eb316e62c6e90d23587317ab8cb6303e353786826828b1ab61" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a87622217484e96d002dfe04d30c981a311ebb6135dffa9b2b69ea92d11ab663" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2cf06fdb206a65abb10e070d86708f4b6d74880a5d3c290941812b3615208a24" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7570c0ddca6e4268548064cc99b1fe1be8bb48812b9f51bcfc165f3cb1eaf7eb" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "bf8ae3036cad3b4b7dd73d9231c172a1b1a42c873e78199e0fbc3e550afe948d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6ae1d5775c72d13f9223b77e528eb787f9122d0978f504a3e0deb204ba0767a0" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + "8623d6b2d427788472a6b68ad4c1d33abe446a6ff40f58a2cd3f29f9e9210fb3" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "841048e6dd6435c7673de039d3e275a79a7c14c29b9a96ca5c8cca8a13bf53f1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2a123f0085d9a4029deb03791d5443dc8cde07dfe829ae05e951f9f0d4840ec2" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "41ad7efc69880e14d6a47a2644cbe9d40e056449ac8a9f130c25d8e41824161a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "9b0868ca5f6275e073f8167964fda11f1c326dc87107200333d12164c14f9cda" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "fd90dc570315a37056882f70a8827ed4cfb049dc60f30a19d42b2d395333ae33" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "b227abd16e548fe553ffe7da6ae86b33875b66afcc535c0a05b7df48b5cb4170" . + . + "d9e35c80d96b92792f03b566d75e9bde1f35b14761ce0467a84e2c897868f832" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "70e8eb04e86afe602a8222bce2414197e993082ba83bc6d7c5f0218c073327a1" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f3c6d483da4e5af13c9beec9c718cd6a2e6942ea1ffb9d6a80d1de2b2b072246" . + . + . + . + . + . + . + . + . + . + . + . + "4c0905fddf3dbf9dec0fcf93a9c6291dbfc69d82f692cddc3347a938ba1ea326" . + "10e18ba4c5e834202c9406a1759a85603d84b2a202fd8a9658f378ad7c08e2aa" . + "bfb9bcab5ff3efafb5f899c0729295fe979a5a526cd43d541a71a0bcd7bc83ca" . + "060a836f0298e558e0cca455eff005daba0fa5d58d47f2ca900cc3d4c9d46d56" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6fe6c129da686627887e871d8f99b4f3ab2160d6893ebc573190b122e2a59ad7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + "6fbf6ea8cfd6ee78eeef3a99f9d23d88ba0fc6b01abefed23b5bcae78e95ad71" . + "a094ea861c2dbe365727523ca2a190d556f7a756ad9c8838fee0e999433686b2" . + "135cce555a2427a141399c8027449ddbf8dc8f9eb0111081bee286b01ef1f6e4" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "d2590acf52a08b5fd332d4499f5e57391dfd874b6e49e79a402f4cb5bbeed1bd" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + "340cb53587be9896f09be10376df8642d51639719701aa040d0faea186995b52" . + "dca5483097900ab25d7230c5ec522a84d17055060a516d8a1ce6f6cd8f5d35e5" . + "ea93014e45d62288c38dff289f88766277093e6818cdff3077f5c66c67dc2d2e" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "87fcb6a6b28e832751880baaf3fef0bc5c6783cd8885518a3aa7a91fce9f7c7b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + "01eb44aca9b8a346c48507b765d6c1756b2e496b09cba741c9fad02377147bc7" . + "ab8c0f98f5500612ad89990e72f37cebeea50703d0527a1c6511f99a02684299" . + "6171942a52806056f17c3e23fbdc3c3667846b612f78fdf7243fde2520ac77aa" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9dd5efa5977e2deb3126e1eb2cd83373fc016b7a9c63f7df2736a13b14a3841c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "1fe74f7e5eca1a6e107b997bb77518478898f2fab59f0ca022db767ee963664f" . + "78525ebcb8567a3634fec4b98a834dc81a14e6f8cc18a77af70f950ad7b49720" . + "d4543fb6d8ba35731b0ffe1fcc76550b10f811932f1430e63fa70bbf16190dd5" . + "27814065d91d67284a731b72d3e0574c3818996ef79be240634dcfdfe7fe0583" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "216aa23fb7dda10551848287aa01a60c00b806123f389b7e9b1d0fe8015ba037" . + "0b355ae70a8e486cf436e0c4d02f12b2dda57923b674b7aa4bb773472b26702a" . + "c4ce52413636bf939a375ac65c0e5e7131398efd345e9331d91f7dcc1f6e65cc" . + "c670e45b1fcd6e245694cefa14a2340179eb1339f8dfe147a5d71b15116b26ef" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f6f02d92fa8dab8f429931994fe54c6cac87d96cc05ff1535513ad7a389f4353" . + "f278ec230a125a3bcfbdc81c238ae7e55bd9a2e24acf225bf214783cb20dc0ca" . + "02c5060374a2cc5c4e62e6579744a8677743edacc0700d803a46f425654e23e2" . + "f1b64bad6b9992ae36ac34f2f26247d08d10c26a72898b2a71c2c58797a4f403" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a1f6648b9358ff32c5dba3fd3cb34e419b39704ed310b791592409d3d42e28b7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "b968895a447e16266f2ce9e9e15d0c324f762e4b7569e10b9ff9e9b7cd68f0b8" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9f39831e90eac98bd6ba457be7e93a666c83fb70e2178e598b5de4c316d904d0" . + "b7bb2de489b40fe3c14908358702fb8f1d3a72a7315647ba87251778712a4132" . + "eb2e702961e49255af4e657cdb2b7a52d63a05169044577a390de11b44373f29" . + "4b5b3ac0f836ae03c2003dc8de5f945ec50aa1b763a42e380d52f669b9347446" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "1cd5fc50794ea664c41b0ef88568a5857057f254d8e019076f492e429a71b731" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "55442b2dde7565836ef9e87d96a2567708ae5d606020635369477012f2add4a3" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3c11b18c62c263c0af7be59b8198fc7b02e811fe18fb475f3ad5a67f7f7be16c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c3a40fa721dae01ea86f6c7a5f55922e1f703a5ac9dd0ae025e74988d11b482e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "99a303289a12064ccb7d90f473ec62590cb42fcadfc9964db50e3aabbab8f715" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "0a321cd7b877138c346991f28054bcfdb182e94f7af93c991611a255bc1660ca" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ed664f63546e1567dbccd18c89b8110e11cf1f9a5619222dc15dee2c4745dcf9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "65b24b635513a69918dff6de9b5294fc8f9edd6de0fb447705fc6eada4bf873f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c55e2ecf16d0385fd1fd992df35ca46df2db4188e603737dfdbc81bdd069caaf" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "05ea640f41e3a5b185cb3815c8fac24c7d0f5e4b3f391521814cfa20bfc671d1" . + "003e1336dab63b609945a6e736fb5c4de90c262ed77cd9e2fbb57a554d5662b1" . + "40d827af472981a717999685b0b754ca0fe2199c2acf876be91f897742e69b4b" . + "e6a28ca5fcf7f69df7b0e085e8ca0a85fbc27a644787af2c7991ece3cd8d92b2" . + . + "5b2da6a3d2423cffd407de6e440d5488200c1db417f9134cb4c2fd875c23ab1c" . + "30731bc77d45035d646cd0472df29bb4a6084c8b6a208eb61da31eba6a8f9449" . + "36006b568acb241bc6077a2755c539b95b3947b3ab7aa00e390844610a33a34a" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "55aa7352b8115b73d422c686e83ecf4514cb8b35c7c116ae4e48fcee21028e29" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "488a98f069f701cc7db9648b3e0eb1a208791c763ecc00d32f26dc7aaf849e4a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "71e0e1b974fa65d088292deadd4458e8815201efd37ab40504b63a293cb9e74b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "8f9729aabfd51cd3a02f5add4ee25860bc594d2475b4b2605cf158b48b806aba" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "94aa5a6a4741b3f272db7262a3cd26193b7aeca504f83f3595a40e52b8c47957" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "22df213d0f4ab7d4f81c4a8cd487ed31017972df6ea1c20b63c2aca9f546865d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "45c1c601bae04a1524c547a8df929cdfefbdd3b3c7262803d0ee64b64b2254f4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "415cb4ec925c4896507e767a74d4e356d2112ea63cb7721ac4449f74162ff9e4" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "062763c258020dcb70736e79668f8da4baf36699b133935d1af8fada7d8ddea3" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "acb11933df38a539204b31fe67e1ffcb5f14a37d62399f90e86c0665f807bfff" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2bbc4bd488830f9945398b5495c35c5e23ef479ba039dc9d2f757d64ba7af7ad" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ff4686c9d92983a9ed04628b9ae3f236de2615683676c07f2052aa0a2f8e4a86" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "ceca742ea317137c7e63735c7c5c54e4f7ee375fd4780a2d14d9d22f9b00da8a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "547421fab1bc7007799ab471014383356e5d0ab4201016c904e169396e115e5a" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "76bd57e9b9ace65d881e4fe68f9c46a119b9cd7b56d968f779affb59172c686d" . + "60ede4e825664cc0c97bb081ad43f41da9b2a04c79c47f4ef3cef35525258922" . + "d449b897f216b5320951aabd67796c0eefcff450c9e31fcb5d3e254044d1e377" . + "6996fae59714f0a0365e23409e9a5056a141c5954bed3a961bfbe8bbdbd0c611" . + "299d81d1622d5b4ee6f3bf70a539e4a844eba4633eb48d22921177bde78af59f" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "60ede4e825664cc0c97bb081ad43f41da9b2a04c79c47f4ef3cef35525258922" . + "e9ee379024484f13b7f0698b6560b1deb290079e367ee9f5e410a0924c8bea9d" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f36ee3b34470dc31a2c2e29b561a0dbb2a8871e313c418a2a00284d5b8404333" . + "f36ee3b34470dc31a2c2e29b561a0dbb2a8871e313c418a2a00284d5b8404333" . + "90ccbb12e756969bac7c3f8200ba5e87d96024cd3d97a917dca19ebbf1d87fb7" . + "030213c18980d636e4f3b21c913312bdd8bef0a6c015b6b99ef1495bdd06b0e2" . + "2f9f8dd60dd6ef24be5b35dd4fcde20e2101bd5eebc4a85fbd0eedad0f3a469e" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a5ee87879055509751438a3b28e6c10ffdf3305412497ca77357f02ba0f5042e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4ef7bf3e78dd553586a0236d52503ef55434b5ebedc63419c442cdc3ef298bb9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "44f19d15eed9d0cfce9c444ddf36e0110d002f3c0ca7f652ef3bb7d57c51a3e9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "85e1a4d68a7e1b73e4113446621f75c212150759acf584d785e3b9c49934e9ee" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6bdd663a5554f7e51c028c5da078d6886cd26a2927d55d93b1ba630f4c0324d9" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "656af149fda387fc37b67d5476215c5467d5547b522a60dce6f525f535e18e85" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "5d3d9fa18fd242ff665d4696c027be902c24b560db6162acc4c6e20bbc3b9b32" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a98bcf8d49b6e1836cb9f9c17fa277393c825b24bd45b56b7a32693e40b49e52" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4368c5403efb6a95d20910908153f51c36033c976d0ec6043f67535e6698735b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "262d31488e9bb30fa293ef2bb921b95d963e0681442274cc87b6bb461d3c7e30" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "c703c780f129d31533b8a081968774e54b3177788589e9e18163b4a32854980d" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ef5990b51020e2a5818d21759dfca49efd7b908091a2735bf6074b22edb0c8c1" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3e9c6e0450a0cf7f135629e7696cd54dcc974d7bbb56d3f202b87f6113c38d7f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "901d811c14228b2034f56df5b3bef25307582ddcbd029692c60204dce9e8eb62" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "cf905b76ded0749d0b93d8db9236624102835130bf635d15e5221872f814c65b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "789f02657c14a8a25f39f71644e7faf895b56cf74544191d481f03bda9dde47b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "fa83d744f2651d55655c34e8dd8fdc6acba8d8b61c23e9c0290a3dcedc2ee623" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + . + "5eae37a3dac48f3d5e98b0eb777923cc2ba0c9519a5e99f2ab4555ecaaf6362c" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "f4e321e043ca8c7956da23a7ca45df0433c31b85ae7b7d3ea4d87bc448533836" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "b18f32e73f25b6b6de7e0aaebc33d3b25b04a261cb19d6b450d73b151377fa03" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "167e3f8a3b8f72bdae7b5396e79c8cff8342144068ceb14eb605e8871a8b8053" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "ac8aab60f5dfba83dad779c7f3cd7f4c4f235504d9e5dc9674d58e7001c068d3" . + "d14426f13bd24609eef98ee7eddae0f82139844e146e6f4c759f5c206c4be8df" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "a6f1fa4eb05118900b31f61f42785abb9451b11beaa4d304d9ce8256dbc9b68f" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "7f0641ab3bc73530bc7f87d783c5ecb63606b1f52da4c3496176ca5e89c9a252" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "6f61adc1ef0d6912c3a3f5dd951dfe10d1d5008e87ba3025900cd7f6cb53fc9b" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + . + "164c2a6b82b18f9f39781422cc610e2f63de86efafbc9a1de53108903fd95897" . + "cd400a0277af672b391f6eca7a0c68b05058b292b5bd1e9c733532360f43762f" . + . + . + "501bb0161d5cd24eb70c98f89b293dddb6e2e62b60c69665c684338de2380295" . + . + . + . + "fda62e518647c7dab0db4570066bff4df76178276f44019045bfe82378151fe4" . + . + . + . + "357897611c3f8f76fce967c0f4fa4243020ed13c4fe067d0fbbdfdd21a0792ed" . + "b5f1483dc14b0544a6dbb22158befeda943d80ff4ab85c2d933d76bbc97dff9a" . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "93e9968beca9e31a534e8dcd5240954c7e83100b1b7e54c65c6d85542ca977d6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "9018318c69e2b304dd6a54d29a831111c3cfc544aa1415514ee27851c3e265a6" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3856bd095098377ac0cfe6f577a912f4a611a07f8bf2284dde84e615066fd1c3" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "d36971d2c299dc80c38e99be5dd0705b62fdd4f7bb53725355319973dca372bb" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "4b60fafe123759689087090df705a2093400722840689138a87b780d54a3c1b7" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "5450f64db8245d65775eb1bb31fc42f05a298eee916bd25ffd43f43efab1da29" . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "be57d70788f271b5b80a714d8c40247e5a8c79e2cf5a83df49c100e2c3af757c" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "2d006f17ec553e91da6a6d07a9079afa735c0ae8389423cd0b5b9e06d7394c84" . + . + "acd70dc90f89e2d1cd6ee8e7f3d0ef82b02b20542c4dfbf29bc8c88d81cb508d" . + "5e9055a7ffabd3cc77e4b07e87ff9e5dcdd180c56ee4ae62b7986f68ca4f998f" . + "c36affd4b410d778d2e78b3f1801f7bd486fd33b29030c4aefb8f8ec25fd1f6d" . + "c462d8d2941fd08c4c60f087c75b92d030a147ab1a62aac1e793127b2591659d" . + . + "32a2122cc2adea2408dfb7f341615f22689a190fbfbe485fddbbd35ffd879960" . + "19179554ec974993ab733ed5cdcab81961fdd4bef36bb149cebd31b7d00abdbd" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9ea210e62c58a61ca378e2df7859812447164c7a22136e00a829dd197f7a1621" . + "9ea210e62c58a61ca378e2df7859812447164c7a22136e00a829dd197f7a1621" . + "4be68e428eff93e79f70db04957c07de2a9acc94d67815634eb315ebff138b30" . + "6844476a608b4736e359b69707be8e64a43237235d75027a49e8490c80f38b20" . + "bc1b57ec2e3ce2f8c387dea0a944d80e1ebff48ba73ad6866a873df9c890f8a6" . + . + "b976a5135674daa9e179243d0120ee9122d57ea6366ca5fc14ca8a8aa519e923" . + "b995c4eccf4918e0d210191e904d4edbc2b396423e50028fc9899a9669315305" . + "0af92101b0612f0eaf762deec25411afe69eb22dc632db42c5fb5232c4fc741c" . + "d8e4859dae22183853bf5c2ad2fd5d9ef858f59dcf4bec346fe9102396d13eca" . + "b976a5135674daa9e179243d0120ee9122d57ea6366ca5fc14ca8a8aa519e923" . + "ac77c28ed785be78541f52365b438eaf017d920b65c24dfcd320f9970c48eb2f" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0ea927cf068e2f63a9bb2344f6eaa01dc5ccb72c390ccdd17e337663a9b75148" . + "0ea927cf068e2f63a9bb2344f6eaa01dc5ccb72c390ccdd17e337663a9b75148" . + "b62fda4e76148c80f70802adbcba28a653d1551f7f4c43c3a2da012ddd243cee" . + "de935572c3429b905a2fd5f2b0730d5c927187a2279d39eee0ad595c6cce7d23" . + "82e2a64197639789c2e4e42f53a18085b67cce99078558b08c681b0fe7037638" . + . + "0d85959b8f7f625310ad87ec4cf5889e67736a350a9e199031bd4c2b5febe19a" . + "e6279397894cddb7993fc68d6c7986efdfb8d4fdf248f4105d67ecad81d1694f" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "b41adcace24346d40e3cbc0ce6248e9bac73a8922b359d97fa1367b5384f0e81" . + "1bc5b0a34b09fbe1f1f9f357f41e1a8252401c90dc514db3e988a36d881695c9" . + "b076b4f163cd9801d0c024d132a6f639c70163c2d96413639caf4dae9c944510" . + "db0727489431e7b54f401fa0229d571c24fec20bc0ba65ad7b93bdbe672dfeaf" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "37d2f648d3acbedcddc99f3760f953a9624f9f0e862548d57929651a9a873f6f" . + "37d2f648d3acbedcddc99f3760f953a9624f9f0e862548d57929651a9a873f6f" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "c2a67ea20fa599834127bb7ad747a50da858105c24ac7d56221bee39fdb9d813" . + "5056fc1a750dc901179ba908ead42def225d4212dbc0709adeec9f4072355745" . + . + "c8838ef709cafc872425f600d57f63833e4d56bfc2b6fa19d0c9db970203eedb" . + "1a00fac92de89b3b06e4dcfb650e3c4224cdcb18f92a10a3467600cb30803213" . + "2c225a5b5a7467d869d60e697f677c5a20d068b2e3fae593b3e141a11236e7cb" . + "372292fbc697fdc94d1fbc74a2e0c123ab63d018991e265229938fd96735422b" . + "8d966302e5da0cd25af217479bd3b2e245fb7162e3f5ed3c9f6554fa96f85cfd" . + "76109c291e4137fed9c20205f3d5aecae1481813dbf43e7663168839f657df2a" . + "647fff338c39f4397dbcc701af00118e2fde12c38ee32da9f9b947cac08d19a3" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "99ca2ff5a10189a322cfa328fbfcb9311b1d60db674f1e58cb72ae4ae4ee779d" . + "99ca2ff5a10189a322cfa328fbfcb9311b1d60db674f1e58cb72ae4ae4ee779d" . + "c32258116fc5820123fed50bff6cc339d905df30fb9474f7cd5b5abf5f7c604c" . + "99f6a6ca488822555321e91652be3ffc64200ec01cdca10c31adf6a43bd2f522" . + "da54e87832b27f41259dd5eb9d072133ecfc46d013c60e04bbe0e5144f197ac7" . + . + "86d869fbccaefa5411b184a3dd55ef776c760966697fb20b5d29a20c93e37304" . + "5064367da3be1535f4db9adf3e04eca9628f40ab4a900cecdc290b3de6436e03" . + "e0673971b79a9c221a04a56f1716bbc5773a8b0e0e4a96809de782571b715690" . + "961c112e9572fac19dc6c211ca25beeb58461c83908402ddae7fa031faa32179" . + "eebae5063ad697af8c5ba720c8950f74040bb0cf204d5c15d119c9f46d9abbd4" . + "105903f0ca93fd15a9ac072cc3fbc0a06c41385d9b322ac1d75a677c9bb5ed14" . + "240f85d03d65734eddfadb1221ca575f58a45e2308ec061b94a290d5b8337465" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "076d8c0bff3faa528eb514f553ed3bf526b5af94cfd483fd6f759c5275497b2f" . + "076d8c0bff3faa528eb514f553ed3bf526b5af94cfd483fd6f759c5275497b2f" . + "9c281de8ed0d8c2b2471f86ff01ee1f9681b635f94137b3b1cbc89a074259432" . + "218edf21e07fe5a31adbd81af30368dd52e12c6d6d0b1c0e91a0f6a2a3de446c" . + "979bccff9560a56271f3429b3a8d5f8958b58e3561ac9b9eccd531a516a73151" . + . + "5bea2d4b42ded2aefe85872ca27bf0959528855f5126c6235b24f9fc747c7096" . + "1c8a68d976bd69839c39304805fb83b05402ef2e0d2f7ec29d67339d8275df36" . + "efe22a33b5b1169085e64ad6f92918bfce28f8ec0d56b5af64c124ef18e2f2d7" . + "6e566fb673f401e094a3772df49eec5d85824efb3763e5d3e09548ab55a7fb88" . + "50d981a7cb9d2a62ea4ec479539ba9a1289d3286168d26d4b0ae239a75529146" . + "2cb8322922ce15dc86cd918999814f8f8f321e7c5c36cc45af010aabeeeed03a" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "eb0f25fc55526a7458d4ccaefa2a7d00da3d5f565264bb5bdf27c630318b1a49" . + "eb0f25fc55526a7458d4ccaefa2a7d00da3d5f565264bb5bdf27c630318b1a49" . + "44dd0f0602d1eff0503d1b56ec00dee5f3875d35c13bae50a1f4ed6758f506b2" . + "13a6abbc563324715569603627e0644cd78ac05f17e02f3386abaa3901fa8d52" . + "cdd0cd68c26901bb647a6996cf4d1d643dd35e3c359079e8ac12133876720c00" . + . + "a0795236730981e8244d66e1a7188f2990fdf275a972d65607101f2deae1649a" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "c3cac3d8cc81850d167f3882b70c12cceef166bc16500c286823bae9bb03f33d" . + "a970c117b5086b15000086785464695fa6fe6680efc69621d0ab5c5ae8be8be2" . + "a0795236730981e8244d66e1a7188f2990fdf275a972d65607101f2deae1649a" . + "bcd3168182e335775f78787fd88129519d6a7e282c4583f88d730f21de25a45b" . + "5d257421883b7f655c212c93ca0eb629551beb8db4bc0aa4f24bef6d7bc8261e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "343c708345ae97958932da69e6b77ad34482f209c14c84c4158478870fb9837d" . + "343c708345ae97958932da69e6b77ad34482f209c14c84c4158478870fb9837d" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "8ea4aa63c2d074b359b26bd8ba7ce3c5baafb4ad98f6c14490bed880e2ca6e59" . + "7a02a794babfcd1a2c9394e021e9e07e98dc203a632239448046213e6c4cff26" . + . + "b04efef9db83f956532d56e7f99722fdda6b068e8ec226d963355a8270a268de" . + "cdb5698a5f1c6efce0208038111239616a20240ebadd19ea0801b1f81b09e854" . + "5b5a97bc08ea49c7fb59a6cbff98cf1df5adf4cbe4f04b11094f8b7036199bd0" . + "3fbe30f5e97a1bd554a5fbf42300af1ee40961a08351401d5329b20da0923e59" . + "b04efef9db83f956532d56e7f99722fdda6b068e8ec226d963355a8270a268de" . + "d90ca40c874fef5f1bd45eb0edd26f23e1d30a67e9c2fd49abdee71ee878524a" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "0d77e4c9e47871f3da16931f521d60262b65b00240f9c40256f8e6a323bc2805" . + "0d77e4c9e47871f3da16931f521d60262b65b00240f9c40256f8e6a323bc2805" . + "b6ef7ef8fe336737bef2bddf25d3f8b895eb8766d02817c79ae9c8eda2f911a8" . + "d189b4ef9702a02d5e19fbe72ae783e6d2d671f00ec867ed26395a7aae8fc9d2" . + "bd6f891b34179449ce5343cc83a4dea38e3f935a2006aed8f035e2d518d5489c" . + . + "2491ca9b4d8b7a42d09388400cb858e6eaccfab6eee74cd356d935895f34814f" . + "e46e2b945db29f6b736ed286a8405e219d55bce8e898d40155db91fc44afe8f8" . + "d0fbbe4361d89474d7861c1ee0c1d898f46980711e054b4bab36eb4bbb069acd" . + "15fc7dba8cdb48931c2bc5be5277cc54d84548f143d67cb17ea22c8d40103d50" . + "2491ca9b4d8b7a42d09388400cb858e6eaccfab6eee74cd356d935895f34814f" . + "de8a37a748713fe1c0afa22911c13fc2653384e9bafff3fc560dfbc8cd7b4e23" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e2d0d91520cbb524017b17d6692a1ff8cb556ccf418ac63d91c8fa65561c0f27" . + "e2d0d91520cbb524017b17d6692a1ff8cb556ccf418ac63d91c8fa65561c0f27" . + "310eaa488a0197760ee587443ec8064bbbc2e62d16d6970ed6dd6438a38deaf9" . + "0df54ae531611f496ad6891f3b5d5b7428b44bfdd049037706bbc0a7077cbd6b" . + "622cac0638a580883391c4e663af7c80a0a17c9e70125c7c9913652f3055df9b" . + . + "8b708c2576352fea4472f87ab9758acbfb6a18a6b51de03a7cb2d0146f43ba14" . + "a7c4abd8137247e91ed78691183760ae31a298ee67ba192d1075603e01d73960" . + "06b0f31fc4913ccbf61717d91bd368b0aa0cef1f9a909c134ea1f0113f60d548" . + "03dde32747441418f8bbb7b6cbc148de8ed3e0c20f2b2d294ae6f38ba28f607a" . + "6e02d9a273626a9b18542df47df92f3439df1ddc57932fdac7ee71e9191998a7" . + "1c423264a3002dae42c5475370cdb917f6d463c2676aae7787c6ae05c06d7222" . + "5d257421883b7f655c212c93ca0eb629551beb8db4bc0aa4f24bef6d7bc8261e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f1479a89f591404c1effd942e56ff1ff649866923a60b706ef4c3850875a871e" . + "f1479a89f591404c1effd942e56ff1ff649866923a60b706ef4c3850875a871e" . + "bdf448efd15e55ffc5b66c8ab743637ebead0f9e273f7cf60ea30ef50dbd6401" . + "13b7e54f6299646e7d67d804275637f687c9ea9a045abe355884af57827a1cc8" . + "7ca385f523821d15a4ea7fa9d38e5d33dc4f6fe8f9d0895bac937b5f175b7f1f" . + . + "f987eede86b84e0747a1a8f68fe9b69cda682fdf57aa25174f0ab54e8ac9f0f7" . + "4651ffca88a3a12aa81cecbb362651b498e6754b0f2dff81fe263447ba3121b8" . + "4bd943933ca57c87db85cc28070a745d95125b364012db5925d6b432bd3e3e39" . + "e70305867276a7890c919ff3fdda4ce8c85c656deae2ace3988340d440c256f7" . + "104f569c8056d961d8ca5590a918203c5d61d3ea234b3e9608331b1185478a97" . + "5ea05ed2b22bd0f1f112039c6e339e62b953c078b53209d859eaac0e6ba3a3e2" . + "f8047476cfb6537ff369ea2eab3f3fda13c9906a8e37d2e1c21f245827919d90" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9c019b45ceee64eaaf304cc00dd183d92a25de0a4154a8e7581d54b5fb613e80" . + "9c019b45ceee64eaaf304cc00dd183d92a25de0a4154a8e7581d54b5fb613e80" . + "c2ed0724724a299d82403fca852732774d82fc098b6aaad08009a0c41c9db94c" . + "d98e6f44a0a7a752120c5df2871212e521e59e3a5315b3446db1a5524d9174cc" . + "d3bea580995b60d85d4e6cd98d86d6522f6d13bea0f08d64e99bc3952755bde8" . + . + "b3c16f79ed506afe1f02791d060570bd802dcddc98a2a6a3c4a0a585ee8d204a" . + "3eb797dab7a2f7687294b1b5e9df54fa3e692b4aabd0d14d011dc634c83e280b" . + "57dfc90cb639b283df540cb36515c7994fcefdc36fc6d82c689eb6db4251fa55" . + "a216a4c935b9b55a080be54c384156f7fff1b2690328be5a532b346820e2104f" . + "25f3e21601a1f48c4d758fa064a55be277eaf83dcc522c02c1da461ad0f2a860" . + "5d792f4c29c18f43350282350575b739d476ce47dd23466cf7181d850392cf5c" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9446c7152122ccb4f61fabfbb4330598959bdfc600ab7478a176537e9ec76d55" . + "9446c7152122ccb4f61fabfbb4330598959bdfc600ab7478a176537e9ec76d55" . + "c38321172a808399e5ce2baaf2d61bb774bb19735c8b0251733b503258ca25c3" . + "b535b578e5a7f334523cbdc86971d8fbd03750a585f4738f371f3300a1d2b70a" . + "9408e4756f35a300de60569534ca6bff143e8250a03244e63edf1aea1a998a2e" . + . + "4d67b4be40fc22e5786a6af14855abe28a4939dc6161c2da257519dd5e8ccde0" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "9c6db3986fe4d429d9c29aad4fad55dc4941f38f96a1aabaef59e633f148f7c1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f07366f476b87cf7a68e775b44221dc679f3e350105a5f3f4cb54f29297603b7" . + "3ea7ffed0bf06f7d388020b5f985607f121244b8ea7e10a41ea0cf55526f4220" . + . + "b6af3b9cff5be24a3ee4333f375062bc1cbb3ae8a10d427998d365f7cbc0b877" . + "d04b2dde477fb270efc87fd0d5d88fc1cf40f084b06ad972b846eb62023c4646" . + "802dbbd0ee0d5920cc79b65e89fb4383f952893119c5b2030e9bc76fe93f4b09" . + "b1fe06d40bf6667372aa6836a985e3e6b3840d74560e266fdbdd5ff53f9d36e7" . + "58134349701f656575f3c247706dbe60dbdbe8662201ce826b63c0118f8f14d6" . + "687a9c46ea6724bd7f27621e77453ccec60571cfea4e969356fb4c4beb7b4186" . + "15b5c2c2179f247d0f7579284d1286178462fd0aa1105f00dcca1f9a7d45ca3d" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4dc1262fbd89d021f740c816d8e99ed1a84774d0007e782ee64138b0ca97f0dd" . + "4dc1262fbd89d021f740c816d8e99ed1a84774d0007e782ee64138b0ca97f0dd" . + "caef7f8939854b5f95e2c6519f7b5d857fd853c051ee8e839e115005ca2ec226" . + "bf12209252fc0da42d41aff4356349f309e038155e3328d2319f4defee86cd61" . + "50bc900f80ee321929467f88b136fd067c0e8bb0ced143afcc454533919ace37" . + . + "00f0964fcea786335ed51362c2e570c16b2a32968fd561c6a3150653c46e83bb" . + "072b8ca37870f73bdd0e076906adc599428987c701928079ed75a9642870a152" . + "f15a65515f8fad981b4e7965f4be849d53b8d27d8b9e6f9d9cdec85d87ad4fe5" . + "d0ba6820c2fc60a4d32557902d0ce2508c5a84725dddbe245bf263d37aa31c03" . + "46c2cd8c4083e4085cdbfef9535ad10f0bc953eaddcef0383669cfe4336178b9" . + "fcd89d51dc37eeb03418cc1203092a3f62ab3fd60e4067cd5533862ec5420961" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd223a3fe423eb7115d5bda9a3a070f70faae457d3953b92c8967221552e06c3" . + "cd223a3fe423eb7115d5bda9a3a070f70faae457d3953b92c8967221552e06c3" . + "779a159c1bad5b2daded91e4832fe5d5302f86894b1951d90ac9878a3231f76f" . + "a5e8c9ef3636e9164f805a3fd470baf253efef5cbe7930d02fce03dc8b5d78e9" . + "a6a41c35b58eeadf461d94c4ba2b7d6d9c676fb32ca1e87866df447afe556875" . + . + "8f9df335082dcc48c6914a6999333922f37d0eb3f8d499fede73f24dfe67859b" . + "07fbc97aeafb80a4497cadbb986f64127d5e918a0e4eab3c093fdec5805788ec" . + "817512e524ec25ed2ea278f9bfe72e9ea3ed19b347ff4ca70a4ff99277c9f3b6" . + "afb23120eee569074b4b16b94781ab03ad311011c6892ce0881bd1044a12ba26" . + "a9d68c156945a4fe8eea10056c13b6f286bd4943e077fd5aa2b3df0c4020e08f" . + "fe51e5086d44b15b703dbbe422251d7c56727da6dbc538be7961763b5938395d" . + "6864d9e2ff4528be2f2b6b60d8e9719db7ddec879f711a9556a77a83efbb22ea" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eb9ebda9756d6c84edf566af2bd81a62452965eb393faddd76e40ea70d015863" . + "eb9ebda9756d6c84edf566af2bd81a62452965eb393faddd76e40ea70d015863" . + "601590e85405649a300ef2fab3974c94cae80060e6aa72ff48718ea7e0a8c203" . + "9f0251eb27a86ecbad922695a7d80b2adcce2a1c3d61e737fe83e898253fc4b3" . + "3a13a94af4dcef6c99804a88342d094fda30e8499db022eab0ea44df19ae5748" . + . + "a21e628d80b8e91f71309ad2c8ade5ce9748938cc1c840c8ff5dec2fb9c4c5b0" . + "b15e8761b2b689419d3b3daa933bb34c99ac081d38bc564c529eb57cfd30c7c1" . + "b3f226147c4b9272043a35fc04e84b7bd3cf869815de1ec52041652474531ab9" . + "f3980393e81693f01cb804ae1c37df97d18b23d45ba9ef8d63f9415d46258487" . + "5937d5bd41a68df10371759cbfef617de1e8ed31c0f914dea79fe749e3617819" . + "25e5f751c1f5656857f3bd534a614cf1d810c29745a1bcb9ef9b6db030fc13c8" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e2b8a2fc85c820989e1360c35ac8739eb6d9e94196539aed884a564c4b105779" . + "e2b8a2fc85c820989e1360c35ac8739eb6d9e94196539aed884a564c4b105779" . + "566d1bd5cfdcd9a4826277abc752c39917e1fc20a1d3ea0b254cec48b99f1f64" . + "5101c1181300e3b2737ea6c50f3badce3130bf342b32a0c81e01091451519cc4" . + "ccdedcc703e7fa571d3d87cea685ee3de0df2c4ebf0ef30c502a7c1c32717a1e" . + . + "331ec39a40e2a2fde33b778dc1ef7d56fce87848ecc105407b00f7c969d87d10" . + "98dadff672642e00e6c9aa8a255e52a939c94cdbfe7f70b51f022711a932a38d" . + "03f307d37cf2d7e3057ebcc9e31ad0d462d86a5da967007730f9f0b16eed982c" . + "ff35fcb63774b492431d8b8127673478b666b27f1a7f260097ca9ba6e832b879" . + "2c2de79b06826ec9659434dc1574931c516ea7b7c0c400d03d996638a805e6a0" . + "5bd8b160f7f94ef42ffd2a7dfc90915aaac0d5b03fba1ea899554e1f9997652a" . + "9e89586a202b11abf4852eafa257f84efe658bf3c4b30ff94439e6f3856e3f1b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7e6b244e873f03aedc0a3365f38cababf0b3c483622ef15a5b01c95ef83afd52" . + "7e6b244e873f03aedc0a3365f38cababf0b3c483622ef15a5b01c95ef83afd52" . + "a5a7df96563d3bc3c6d00471b28597840f326a0a0a9d0e35e4f1caed2142127f" . + "c8a860fe928d73630cfa681d1d4ed55eb07c69a3dcf6891563b5ced4e1d959b2" . + "3c38d8b8d35dea92dc585e84ca31957f6827d59200430a1d869b6df3a0fa42af" . + . + "3a258d894a2f6c355a9913d6e5d3564ab721c3a3da6c67d40208d630934153b7" . + "52741bba3cab4a76d6cb96924a791b100492404e57f05c2e6505b8ecc483e46d" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "aa0e03ac1c33000bb4a060b675588e3fd02e66ff55ccb77dd758272d93e80a5f" . + "ae48adb45b7fc26a601477ec783334a38959f62bf03a60712741f8fc735b6dd5" . + "566ea48c3eed8bb0e93257c4572c72f3670d7e09a14c55ca03dcb5e55e40e4e5" . + "c5e8e6251818930fc1c883fd9295662f965a979b664ae59df3299865a3cac35b" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c9faa0cb9879706e566d3a343ae4351ad4e4838e63a7f33499ca6699a0261566" . + "c9faa0cb9879706e566d3a343ae4351ad4e4838e63a7f33499ca6699a0261566" . + "d3c46a217446de3305dbd8c79fb4cb61d5a605a214d71ad6abf12ff97d8cdc10" . + "bdcf396bf8109eb64fd0b3f5a7c8052d0218edef030649478ca0c35333f0e396" . + "75a32ceef083d8c607211aae44920d9e5ed9d203d51fd772f199881e77ca7c39" . + . + "9379fae2bc714686b8ec6797afd4f9ab37389e05b791bed545dd21703f212bc1" . + "599c39bba08a29bc84ce08771686c043366004dda0dfb6a1bbce2661210b8bfd" . + "4c7ead98b4d7a86cfb92302cdd5ce694a3343d1f1f304149889d3203791f1646" . + "da9a37dc8aff9f2048c737cc65184006a8f8b13d2f7b1b756bffc66bffd20d82" . + "2d9e3fe4b8505c20563956aa7c751984b49b7b1bc50943cc92cfb6732c793832" . + "91a28ab7030b87a697821eb910f6b3f69cb536b57dec3c8ef75f8035b3703e2b" . + "91d7558f8dc8c43386d82b17a63f3ed6796806f523fb46e096ec1e1bbea19ced" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c51e1496d0b6aa3019157d936aba21710a2bee5de4eff73d0d8599540ac99030" . + "c51e1496d0b6aa3019157d936aba21710a2bee5de4eff73d0d8599540ac99030" . + "60632feda92f6f3d2143d9c6be7eb0bd1d4b9ce7fd9fff2d333b3204dc925440" . + "59306dffab125217c5be20c6ee2114a5942417814a9af834264b6961021e3321" . + "83e6c927e320a345608161fc449cd36c248b7f9d8df4e6cf7aadd2e8790872d0" . + . + "1d8ee25c327a05900c22d232d91b08f06f2ce47c2415f66e95b91d554c9ace88" . + "27b2224533505d5f951e064df8fc6f9d2318154bd4004065437d58cc2cddd5f5" . + "fa4d9c80ca5c6732b0b8d8dcb3c35f470b550beba2dabd65668bed29dba3f07a" . + "95d03459560b3d1583c1d0fe75a205065ed7ca28cc324085e59bb34f25c548e9" . + "bdb472fd5a2948b9e002f14b93fca32b5e014cf0657cb35cebc4e15347086d53" . + "630034da67e293904af7be02c4149cacd9eed300c3fd3cbd80f52cc11b7d01d1" . + "891d64170fbc75bd89924f875df71bdc5df9739091b9c9154d0b4c20cf4860f6" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "24b0830589284ff3915c03d6012f9f65367c82e1a58058f084b2d75bcc272e22" . + "24b0830589284ff3915c03d6012f9f65367c82e1a58058f084b2d75bcc272e22" . + "067228384bbe28af84f3ca5b8e8bd8241af5d4178ea00f46f5d06a9f0682af5d" . + "bf7c0dc69325611b59a24dc1b3e4919e319d361e814469872165807eea4d1bce" . + "6042ddf98a6f7db2b114bb005c2e83f27878f73f833ccf8daa111cfc475f60ec" . + . + "3c218d6f10239246785118dec5d4586e958ca1393c4a596b9e9f9b9e0bdd42c7" . + "27e01d08ba6dd0ed5f67dabdfa6a30be9434d04a53922097f1141a7ba3843416" . + "6ca8f66a407c72db7359cee7833c72ca9709cbf9397ee1593d8f3e1e21b3940e" . + "590c4029a63d3533371e92f735998be9faa2aad62f2146c0aee590cce9242853" . + "6694e4e5db51156985e1b209eeaf02a83643546a63232bfaad8379d4b80461cd" . + "7435515e345e5f6cc45f841043889e0fac30f6f6be8dadcc6012bcb0ac8db407" . + "6321a3aeca976acc381617ca3f4f7528b06f8e13cc8a8fe41c6d3a611b0b0381" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "852da716713edf80efff58973da1f946b9683e14bd8f884a24ed8e6ceeb0b476" . + "852da716713edf80efff58973da1f946b9683e14bd8f884a24ed8e6ceeb0b476" . + "ed54859b869e19d57dcf6774659903978c1fbcdc0e9f8438ce53f4dd1d23143f" . + "687ef2d46dbf343932c7106c32694317e68b8a6b78fb9054a6d5c2c7c5187645" . + "ef2756aeb79987e8fc78896f63db2491a59b11bd60f44e2857c0b1afa0cf17f6" . + . + "06fbdfea4e96090e28b7240863bc07a617446ce09bc9a150b35b7b06904771f1" . + "99c0ecd2108c77e06550fa00cab8bd39d454334fa5bbf59f6475fb2df92bd716" . + "e88020e3aab3ca808ffd44b3f592241b4adb280eb93e0959d74d56f2f15b4bb1" . + "1244e471798ab1c1c1765ad755c2227fe52536fe7512db6f25ed8e5cfd9fa305" . + "770da4c5283f9ef77f5094634d82e496c1f46cd6fb26e31abdd5f6ea102f681d" . + "be15c0d8e98be2ae80c73e452d587f674dbd67d9f28bfe0720640916437812ed" . + "d896bd3f194bb428377c4ce9d02b928e691e3ae08d7fba87151d1e6ae9be76ef" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f6b300aabe605e6ae8993cc34b1990c32ec754a0e51880e36697de44858cc09b" . + "f6b300aabe605e6ae8993cc34b1990c32ec754a0e51880e36697de44858cc09b" . + "5f79d0a20ceb3a45d3b75de5d61b5ff1b5c656231b87f158a4b7c5bc9e76a445" . + "2a155ab7ee9f2edec2beb6e18b8655b8632b073cd836797a608bdafee7960bcb" . + "59d371610532c29d3ba1fbc1ea3ee787c1a93e6ee5753910294c102442e040fe" . + . + "4d4db55a5e2d059544cd547410169323ddaa4c1c738677353f20da24234d1e5a" . + "50fad8fa745b74134e83bd045cbb29810a5d9e9807139a0c84c715fc25b304ea" . + "19279e2cbca001e01ecce306ecec6e699d6ad32bdfb1ccfd103377eac603dfc6" . + "2de5a1932d7be6044dc9e81b0b750bb47fe05f3ad90af93205ab0326d48ad436" . + "6f6bf9429f501e5ee5f04ada7fdf99fb45e770d7401fbb1d789432d4150133e2" . + "ce4a4da6218e3ff3d9b160eda8b73705ee22cda93dbff98aee5622560666fd0d" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "19a4c974fb04b7bfddf445369050ced568b15afdf91650fd387aee095fe87548" . + "19a4c974fb04b7bfddf445369050ced568b15afdf91650fd387aee095fe87548" . + "dab0f6450b23792699760a7702fa9b353ab2171f27bf865b727512977c2b8566" . + "2f487599defda5d00290545f32bd17631bef25cad1415f542b307018d8e5cbdb" . + "18503addc9a158603202bcd9010de3c1284c4438e657cf6144df13f9b58839af" . + . + "c70a0cc267f798fdedb9c0219afcfa5196a50da4c18e9de39b49686981104f93" . + "83b42a32c4bae656e00ec1b6c4d7de269096a5ea85b1bba73409c0a0ea3133ae" . + "dd4a2e6b3d5388bad4a6a1964751e40bc954f826773ad7ab0bf82bfe93f36f53" . + "1054520cf06a2f28cd8b8f76081da66cb074dd175258af23d1a30594c315d238" . + "c70a0cc267f798fdedb9c0219afcfa5196a50da4c18e9de39b49686981104f93" . + "ef1ead8a9ad8897e4f5eb4fca4007a4c8824befd8ab08427ed5d0ded5cf316bd" . + "37be69267092a8a68d7592883ad4a039a18058634d523bcc56ad64981a508c40" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "5cfaada95325307a38f70aa405408c13fdc018a5ad14f4227fc3a8396460c1a2" . + "5cfaada95325307a38f70aa405408c13fdc018a5ad14f4227fc3a8396460c1a2" . + "49c33c744b6f97de00a3c01f12563e405bbb0cde2367ee0288a4dc96cd3e705a" . + "b56cedd6a197f3b2fdc1af8b351ef174b9b51581a848ba0ea4c9141a2b0e5f76" . + "2392a6089012a119d0c54f2ddef5b87c24cbd6eb824918b0cbf51a3d46477cfd" . + . + "a346c911ee274b3c46ba2239d3aacdc0394d7109f34f2fa5ca105e3a1ce23ec3" . + "7f941f0fc9f26f9233f8be9c1c907c60c61d96dae0d7892e8202bc804370dda4" . + "70fa41883a3634c6af50afec8da62693f6ab5c92c2356ffb6d4ed2c2d4597b01" . + "df3e8bdb8c701466c16198ffb5c0d9f3033123089befdad2bcc3820e64370bf9" . + "521ba292f976c8e15aff577f562260a1a07c37200260c7caae1fa37f13821e7a" . + "678fb42c61a1833c0b1cecb0d5a2107140568cae8ee43e90698390dae6ee7760" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "408d4850a08bddbd4a4ca2b3bddece8e79b8b63e1a5dfa8307c59335ac9e0212" . + "408d4850a08bddbd4a4ca2b3bddece8e79b8b63e1a5dfa8307c59335ac9e0212" . + "e640e3b94c36bb6ab3a9c2a5a77ee2bf4e389619f559ce5e6b8e53790546cddc" . + "ee3be2e62cb1f8b65e016cf2a2e5d68a4daa5f827525a350af92ad0ad919c096" . + "f29a9aebd97cbd6fe592ce56d6d6e50fe71011a211f29fd59be4b17a5d52f36b" . + . + "6d9f908f65fb23b0aca7a179837efe5dd42e3735010cbe95fab4a3cc35933920" . + "6cb903bb0e85459642fb716c6216de3d310bd210d9fafdd5f0533c76ec7da02e" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "ec7a2999a0f26572e8c92a0364438b12a105014d6f541c4ff3d09f4d9de5be60" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "6c4c89ca1fb6510cd093e645ea5f0c777c5a4b41e62b1b97b3a8a4ca366c48ba" . + "6c4c89ca1fb6510cd093e645ea5f0c777c5a4b41e62b1b97b3a8a4ca366c48ba" . + "72ca580519d446c2fac7f21cfd34ef1d83bb4d6ed0a98ff4d22455a5946e9672" . + "7a713336539385d8cf34c1e6b3db20dcf4bdcc04d9fa4e5e2488d605deb45008" . + "dec88c206ac3b77e12a6bc0c827040ff015da9dfc87dfe6c1d871c0411033269" . + . + "f89e8365e21d1145edcf82c36ec9a772d7334cc705ce9f5789235e459ba6bab6" . + "e94ea84dd94641069fa650091738e8c76339cbfd6ff2163bb141f7ce3db53e74" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + "73546fec7fb87e1e7e341651d8885ca8ede0806aa40a242d9b385543f6040d6f" . + "ccf4a58ab132ee0553e4ab9c2a9ff63c4360540312e91f8534d1bd4f8b4e6634" . + "da519a9b2959a344deb71f1aa1e74a73e09fe366f5370f21c6430d8543581468" . + "47ea5efa31cdbd9a3d7b10f1bce1c6c6e579c469f9a98b745bdef57833e918dd" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "68500aa80984feb3af507b896381266fbce95875cd4a4e84cefd320b885d2119" . + "68500aa80984feb3af507b896381266fbce95875cd4a4e84cefd320b885d2119" . + "b72a635a81041d9d7aa36037d995db8ab1e6a5ae77ec5a408bc86613c7dc4181" . + "bb02b83d5fe08e22fa6590fa4f4ddcfcd009b7f33f6e842cad3bc1fc7d732836" . + "252ef9ca7bd596064c9ff148be7d5d155fc79b16d35801a27f3629ed0db42ce0" . + . + "a0d9900eb9720ae552cb9737c72b7ca9e30219d401d94c9793356018eaca849b" . + "02dbbaebc11ce4c95b188789f913a83ffd0028bd6b81827f27652b844446fc15" . + "f661441324c09d177f5b71fee249a691d9a319687337f64b3f1d3e35c2626875" . + "b5df9f0b844dbc338923c6bc306fc6a5af31e1837dc80e3681e1be79f7cc212f" . + "c96b8a773b241c6480d1095538e7a1f7dcab8c612f1a176b91b2023b2af35d8d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b05c7a9a170727414de2b16381325db52d96fd02e349cc4f0b719c6f3c2d8b2d" . + "b05c7a9a170727414de2b16381325db52d96fd02e349cc4f0b719c6f3c2d8b2d" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "bccd9bad7cb3365d19321c42acb5753f9d9717c7ecca7f42cc87ec72b8b665c4" . + "a894e77e27e5bbd7eeeb37926cc80e29ebb76c3b2d11032c367e98808b5df1d1" . + . + "10753e6dd376ad93f92299074fd25b587912a97a6e3d95b332c501b295f13170" . + "28f65239cf8ce8d2285d52a74a0cce9c2bfbe259914b770cf5de2bf46e554f4c" . + "4a93893eba7743f9a294ac076d15b8c0177f4db23e8cd930e3812e6928632c7d" . + "cf38d717b48f45d9b37c69ee7a72cc67848c8cd0fefeac1f2ccdfad615b340d2" . + "541487c3698140c65a873a876cae83c9384f5a765c5fd5e8cbfdf06cf6cd0d95" . + "80f5a8d31d8f39d999b52816aff870432065a51c05f75862ead4058dbb592fe0" . + "57849eb500e505f3f1cec6ea4e7a297b0ae245b92270a61bb1b32aea5f8a4a61" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1563a065bf2cda0ae31952fd75e037cc3347dab9bf97a51120716b36dc91a1c6" . + "1563a065bf2cda0ae31952fd75e037cc3347dab9bf97a51120716b36dc91a1c6" . + "6f2206c9c0455da64e480d2a551f35770f5455b0286bfdc6d5ec9b78df69f8bc" . + "74f2eec3f6501a4bb6811dd5a993f2275d97a64581ca0baa083752b518daba31" . + "a146deb767a262db0e8974d5dd095fd9e5357d4bf4cf34374133196741d04cf4" . + . + "706ec4f0182b438ea2a3bfe3372beb51a747e60c18cace0ab6e119feebf666b5" . + "25d6dccb98ca6f3757585d1fdecd7f8ebb5426e4f794808ddf58c194c4c9502a" . + "c7961cf65e9f8a964db1eaec78293691bf89da887a4b83fa38e6561a584f6a80" . + "850919cadf479891be14dc9b74a49fb8351112627bdc31d6cd3482cbcfcbf0dc" . + "251402948194d8f296ed0195c3f80deb5ca6dab0db0ec3b6e041a7fae6002e7d" . + "c1605097ec09361a13f6ad4dfa06880e14b659422500d8d0faf73fd7dc5f9992" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ea6773ce9bfa789a9fdd00da9efbc40867990e3d43081f18ca85c15927c1f027" . + "ea6773ce9bfa789a9fdd00da9efbc40867990e3d43081f18ca85c15927c1f027" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + "169eb5fe08e2196b4f52fe18c61c1f660a65514a96d9929f43423f02f40a0a7d" . + "e5f688948835c52fc9cc08762f95f63d31a3ac9f3f5421cdad62cbdd68e4c32e" . + . + "78cc1c87bf691a53f5df6cabc8ee126c1f57de25e32f9bbe69d0be0744cc699b" . + "74c570902a007c2e3eddb744a4c56bfc001f582732173b5086bb8748d4471938" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "7c3fdaf87e5d51a0ef8be3f59f03a8ef00d48843c0feb5f31efba2d3669fde3b" . + "e3e586328f8c8ef72fb95e780b4b80bf0d1549aaa0d4b4b74a521652f31a91d0" . + "936545d2bebaa3ac501242b6092f179a193a7e3f3b93c46c5253dbe795a94aa2" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "db6124978c93e8f52ffc6d9a59d13a429353c51b7487811ac2bd997657de413b" . + "b2e1cc7d9548b94b5bccbd9f6bd6c83ff3e92a0f271452ce70b876593f2c9259" . + . + "48cdc2376a540d51e42fa01d308a7020c22b64f5eeb0299dc3e9a5a463633e5d" . + "650f5348997a207fcff386a7baa9045e09c65abb05c42006963f62533db9b909" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + "65f02e64051d479122d4c09c1c72ddc860038e473a9d2691e0a1b09153c2d71b" . + "fd714045b6210b243c2892f3b8a81e37fd13170cce4e082faeb342ecd28a20fc" . + "8e0524866f407920e1ca2b1d9a9eb1e7084461b1d3d5d0bbd1e2f8ee8f474438" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e1aa850526418c74ecc375ac65fe9b24c582b9d52eb6f7a5c5a53c9e0ed0dec0" . + "e1aa850526418c74ecc375ac65fe9b24c582b9d52eb6f7a5c5a53c9e0ed0dec0" . + "7ea3b5fe9191e4cca6246f7b01dce874d90447e581c1e361d4e0c6c3b9a86f10" . + "a02549147e9b3da123b24d06902a804b3cf29fa4521ea904ba4ace26c221509e" . + "4b3f4b1b440b9581d550e9aa2ff44b15f8b91d63c50b35d2dd2ab838f2a82790" . + . + "5b747dff44e27e1b8150f250f39fb7584931e2e903323c51f7748e065b2a55d9" . + "5f92f0feed95851b0a42132d6512a404fa1485d738cad4dd3a137253dacf9095" . + "58a50b63a096cb71bf4f6f622906cf5beb9599ddbe00eda3456446ce8e072ba5" . + "2bf9c1c7b679ad681fc1466bd4c63cfc9f1315a791ad3bf86e080a7586c1db7e" . + "a1567dc43dfec93a4d2c1d487e6e1f4d42b90e1e3474f544303b742dc1f86a86" . + "b8e1f8795515cdf47af9ac3f5d6e857f9b7a8e1ee1e09a5bb6dce972e4f16468" . + "f266c31cc942520e6ee6c4afc4a834d3a3976ff9ab6a1b95c27fd01d812bb7e8" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "1ebcb7a793b538623e8a9db6075bd3a8ae73c044482599cac30b37ff49a68e87" . + "1ebcb7a793b538623e8a9db6075bd3a8ae73c044482599cac30b37ff49a68e87" . + "c9c24dac8d1707c2af7de1dd3fae8e678e5f3614322e2c717b6fc60d067d71ab" . + "a5e23ceb4c58f0c79dabff9cb5eb3cfc78ec1bb587ec05b5224eb697a17ff088" . + "70749d6c3a6756f4ee61ce3a22c27150244cf204194fc53ab9ad33f80e28d502" . + . + "0d425b865bcf55fd3068b18d29ad26e292a896af28f3ef33a95ee947f8da488a" . + "eb812481401a3e4136b6e3237339c1d20fa61ae9c36489e15cee2fd60f8e7766" . + "5e3c75f78221d52e3968445ede68b17beebc8aa838401586365a2ca121abca5a" . + "e9055490c68ea3b8c094dde507a9ed1fe3f21109d1e9541d526867a8a0e7adb3" . + "530dc369ea8498f987603de1934de401b2e794820ba6b8719838e2fc88a9488c" . + "7b115232966d9c59d654189a3ddec7106cb7347f7653619f67e287889f44cc0a" . + "044af855421b2e7e3e864e4aeca694eccd4a82ee648bfe486db899e3c32f0c79" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "ac953143775612e6c9dd5b9f311a4901208eb3db123c6a73b8f30b9a0cf2dd62" . + "401227171092b77ff669e7f0b50de6ac8220426607c8c14a0ffd76425fe34262" . + "401227171092b77ff669e7f0b50de6ac8220426607c8c14a0ffd76425fe34262" . + "16dc2d1956ab67afdc0d4d17c9aa550d9df2f2aeae38540df2cc990ebcc74341" . + "c253f77aafef06e70514aeb604a8250401f4ad3bf326d22441082e8b0c7d1fd4" . + "59f679e5bca5f4557dc853f2f6880cd7345b0badb8f2ae3de8770da34291d7e3" . + . + "9add10161e8845249ae3d75556dafdef76f49f8a4a7f9a99bd4ce7a39c435ffb" . + "1e2de41e0d335fd0087d1b1b8c6fa65d51c196e24d70bbb06e2e5e8f150b92cc" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "db1b581d9c34b05dbcbb59ec0f854aa9b287c77b99efbace481322012d435db2" . + "525c756039bf26850358b389d6e8cac442b5a8280147fed6cb33475a01109814" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "2a64d131c3345cc70d0892c05ab487f3f96cbdfde1a15b116abd0c3854b9da41" . + "2a64d131c3345cc70d0892c05ab487f3f96cbdfde1a15b116abd0c3854b9da41" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "aa8bf84cbdcfc55bb3cf3be97ebb9126931a9c4fc4725b9e80bd7e4559df600a" . + "b5bf883119d17bc56ebd4c28b6c5a96b4953399ed165effac3b19ed7ebf18575" . + . + "2596e384dab2c607e72f33ec523774e76962aad9b2b36db352072ae153b0d63f" . + "8b854ae57dc9252e1ff2d76b72e855527793775729d549f0cb386f4b2cd37830" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "2596e384dab2c607e72f33ec523774e76962aad9b2b36db352072ae153b0d63f" . + "4ecbae3875d107d59e15257ea16860c617f555bc24db317ba7c8932f057f0aed" . + "bcf5143374e1eaa78d276b2a2f23ad328666cb191d6befce744c9c00894c0b99" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f3d6c76049b21c5ab018f9e934d189d75f2de64dd3109233a6084dae54307611" . + "f3d6c76049b21c5ab018f9e934d189d75f2de64dd3109233a6084dae54307611" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "996cedc66cc25e0568952e37090f776df74f0c4b35d80f3411785c2eb8978572" . + "603024a4eb12050794f0f00a593c76d5dd2f15c4a34a6164217987160e093b9c" . + . + "d807cd1419213b68c0b531fbed9865b64e57573ccfbec8d477d10054fb8f7e21" . + "af756864dc9af1dd8b28ba1631e656aa31873cf5e65ec7d02974ed5d605bcde7" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "9d2934420be2600044cf9f34dfb65fe538aedde7faae5d14cc579eece6ed87e3" . + "bf0b34a8a5f9f090a4ac38275090ca66fe3328ebae595a1bb61a3608c6542c6c" . + "a11da42411960bee23dfcacc92a2029ffeddaf187ccf3860cac38ab7701b67f6" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "cad16f008bcf705e45feca48066fc644e5671bff38fb14cb7dd25afec830a7b6" . + "cad16f008bcf705e45feca48066fc644e5671bff38fb14cb7dd25afec830a7b6" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "0a15b29d0956f4bdb4edc7d81be86c7ab5d0502df465888e222c57252682c5e2" . + "37210089789abce1e3995d28f3b636ca66e27113327a4d5fde53d315b9567b33" . + . + "ce2d965139f207c47fc0027084a6d374cb11b713bbcc3c93805574799b40003e" . + "16f00dc80e3b3d687641bb4efed511d10266be29aebda0ff7c0a91b012529461" . + "d8fd11425b096a14662a314fa299fdbf2285c7e3fb2fa32cc8089fbc15c3121f" . + "9efe7d539ac4f56412e410c87bbb50f222c547d1d49834a07fa7f5e8587aff3a" . + "a1a90e03af865674616e74a7f6d3c8e5bb32315300cab9631440ca915442966c" . + "68269e36a4be45bb3e47536719fa31e74f68ce059e5a58d4082d1c0d2871def8" . + "1a50f074e990f22c2e9b507f8c11d6b932384151aa0ed19036a71296058af336" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "61faccb5bf3281b84e97c9efd8576057801ae46db31283f5a711bd2cab79d818" . + "61faccb5bf3281b84e97c9efd8576057801ae46db31283f5a711bd2cab79d818" . + "efa77cf227082f08e7eca1aec89440c4cb1b162b73b8ac44b024cee7b71205e1" . + "4549a703b211a952ad3b6fe9c526b72045932f06222d7d3f306cf9f873986d1c" . + "7599b54259628960596641519d46fc77e9975ae8bc6ac141165ff365a1645e48" . + . + "070d718c7f45cc27ccbe332eaece1014094361f6f0bb8b039e6c189201bd139a" . + "e2bf0e864c5eb746c364b313ceacf0475bd6f14b7159e9fca00e4cac4832882f" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "3ca1f91790855aaff605bd6698dec91f4d81c60b8f7dcb4c5c1cdd690333a755" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "b95ad8e1809f35e7590629ff30f53a6c9c56f5ab9ec91d224a39cf477bb0715f" . + "b95ad8e1809f35e7590629ff30f53a6c9c56f5ab9ec91d224a39cf477bb0715f" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "23e060e1286f44dd00c534b669e7365530525c871a273c1f1f02289193136eaf" . + "8158a1053c7d4ff07da539da1669d1c0421c4959774aec2307c7651ab6ab3983" . + . + "cc9582480f4f279e2597ad8d1c1d3acc12393310a90b2901c5e41ad3771c11b8" . + "6ab8c925c82fa6d96cc2231b077548392c6c5aaa54bd76f1c35f42fa0d09e938" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "afded94c012139168e5b4c019009e827b25174dff2631ac2f663eb517503851e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "37e23b3b96ff163a24c93317b43f0414296c5436110e561658b9fb9d1f2e7ff4" . + "37e23b3b96ff163a24c93317b43f0414296c5436110e561658b9fb9d1f2e7ff4" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "65a5431348514082974da789e400a5e2b66520f8406712bb161cfc3fc9cc0256" . + "6e4f9227e97d1d249e23a10c33663b30d3f8e83c5f1bcf3cef97cdb4323ca981" . + . + "8421ba1f0e1cbdad94ba2265e828891662a48fb4d292a74f84ac78d3cb57c87c" . + "576bfbcef4924cb45e040489da9cbb8c8ae4c02db18f845738e0c09fcc97e2b2" . + "2ccbaa9f1cd96fdadad41b139297d91480420ee9ae49b99f8498cd067319fea9" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "5ad4a5cd83f17078274e03eb880ac0c93c70104c014497f280b23def76c65e44" . + "1435842348aac5ebd5bab54ce5440d6a9214ba764a82a8e6782e076b7fb93a66" . + "b0fc9745eba2c7af3d37b27b5859bf2abd53f112f659e8f0ac41ee4eb3c673d2" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "7357a7d2c03175e95f9d8168e2ee590b01192ac92f8138a290f8554b542f2a2c" . + "7357a7d2c03175e95f9d8168e2ee590b01192ac92f8138a290f8554b542f2a2c" . + "b653078425ebdce59b5007168b2fcd098dd107c1a439c9665b825f2ff5ca9e18" . + "54231ffe6eb84f96da19f7ea6f8690e935ad4f180549cdd38b473664d086176f" . + "e54ac3223298465ef1c67eaa99372afb4e54de0adb0b90b9bf1e6cd8c9e20910" . + . + "22427864fc1e37ebb7a930d6f1e179d0765b21acbf409a8a43134186de564ae7" . + "3892706385d31e5b8d811a568b7a6b58f140441e1ad17753e8fb3dd9d9b57b7a" . + "efa77cf227082f08e7eca1aec89440c4cb1b162b73b8ac44b024cee7b71205e1" . + "b180913f5c437da34eaaeeac350596f36e96a532e4f2214c83b5a5829bc158dd" . + "fd48b6b43ef34ec6b976e6bf627f3bd475c0f82ff67700e0d1dc750a07102555" . + "6afb28df75b7fd04d3f65de96224fd7fb2923e8d43d251db3be00f16041dc9a6" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "99516e7bb5d0868e27d951c3f031f4ee9c848871ea44045812f07d16f49ca67f" . + "99516e7bb5d0868e27d951c3f031f4ee9c848871ea44045812f07d16f49ca67f" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "bb253804dfa97066befb65dac559d3058537dd7a9e05d83ff98a6bd4f66dbd62" . + "65a784b8be258341a39818bde986aafdc9e7b34766945392380b4d89860c4651" . + . + "f3efb4993a7d6b04f07e87a2095461783e8984fca1955da71a507c0ab198a5a4" . + "6c8d1ec97a3a7f42ef6cf592553d9bf1edfc7b8471177a22d3bd6471fa72b1f7" . + "028a084ea5cb638c3df5aaa1c0f65a5297f8cc4abbdc8879da470f1c5d98d618" . + "ad6d85223d2fecf2a728e710cd0c84ec6eb54f14c04657b98372b550a5be6b58" . + "17f947e3d96b46fe474ea85a7117a5bcac5d046c1e2bad31093f7f1d5b10be3c" . + "ca62dbf747b640c03dd2100289423c01912fd06e7ea06723d95899c81bd4febd" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c4ce2b453b9159e2b27c8a7536c8d112cdbf41430aba455265330babc721a203" . + "c4ce2b453b9159e2b27c8a7536c8d112cdbf41430aba455265330babc721a203" . + "8f9e48ff5cb39f83a7dd78010435226ddb8d6c75cd83fc0a2d4cfe69d8081fe6" . + "7e4884504b9a6e1ff06a6822283ffceb0de8452c5ddf75954f906a4af7a30b5a" . + "737854bae806e289836a1799c36227340462920622d0a259807967458f9142c0" . + . + "fbce5fa5c621b659f58b0a5865288a3e035da613081ed30836cc2d9057ab26af" . + "609562d0471ad40a4aa0693ce591d9a4e6a0ac6e208a40b2969c6e24c7c0451a" . + "0a14b674527dd969ca0cc1bd9a560028025c543d0b8c2323012c33f2fcd28400" . + "6ddb17a81e6dbf16ab235922eb6ec03fc40bc781d88243789443d19b0d31c619" . + "11b520712fd9b0220233c23b13d9f79f1b7e2c33176c06749fed602898deb387" . + "de2ba755e043d77f820b58fe7845ccd604cd5af7a13c4a62dab420ed10e98595" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d6aa194cadfb9dc8d88d64cccd641f979503ee14276599151fc186bcb69c1696" . + "d6aa194cadfb9dc8d88d64cccd641f979503ee14276599151fc186bcb69c1696" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "0e29e735931efb29b0c4234a2a526981986e26224ed65ed45f15fab0718d9562" . + "e535463a1e38d891a49c65dd7e6b1cf6b270f9e7128a18ca596c6c563d577fb0" . + . + "0ec9e246ff90ba332345033c319ad52fcaac4f1b649e2afba262e7ff87914c69" . + "2838f761ba98916f108872860ecf2edff0c3b68a301eadc323bdfe317defb197" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "d8a5d9a957d0d5157fce34034513024ac29756791fce83a08343c29219c53aa9" . + "35d98d7d7191a1abecfa051e2a69310ae781bc0d0448565d7db4016be56ae6f6" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "72f6eeb2b895e42a74f2d4f78b3662c0cc2e171a54aa31b930f579d75236725e" . + "72f6eeb2b895e42a74f2d4f78b3662c0cc2e171a54aa31b930f579d75236725e" . + "4f1852774f1625de6eb3360245cf263a66fa34b660e1245d3b4905e22ace1171" . + "e84d880e5ec490367adbb1c10000092385329a486028b66fe8f2b912f9e99bf8" . + "0dfed28e93683b7fd47329709dba7737e23c2a782f7543387183ba71b9ca3a51" . + . + "e32b40bba3b8c30faa415ff88f728aa53499bc5bb65a489125b3f2cc8f6b2c2f" . + "87550f50bbda8e2d6315b3645427cb8de7847d8d809ef49cdfa0e26475974418" . + "e6dc508a22881fa1fa3a08c6d5195590c9ae81eb51c51bb088f586b3c85d71bc" . + "6926d5c67b71f639b54b490e79efe22e6a6c926bdf21e09e6c0f6d74803bb532" . + "dc04e9a4a52ae4413c957c344883a944ece1aa2bb9c74468dbf685f7f91b1f9b" . + "4453446e0e03e6b14cae8ce2fc4a9f1ce368a9d209635b2102e16aec6db18c5f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "12c2f022dc92fede0039a19b026184e71a8d3952b8c9d9b007946b27fdb08497" . + "12c2f022dc92fede0039a19b026184e71a8d3952b8c9d9b007946b27fdb08497" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "a556dc0132ba955c229e979fa5705e63adac7d04485b606c4446df263c84c152" . + "9769fc87e3217616585fff73417cc90180f1c2df6650e7465ab45ca249285e7f" . + . + "9d71f4702abdd87a7d30844f271dad655ec9311f918276ea99e508ba2b8d171a" . + "69a223f9beb0458ff10e84b5f155032c1314177e7f0177eabcebf4dc94e038c5" . + "eae41ab5587623fc82a3d3478d0df95c49140df2f29b5eee74673a31ed2aa8e3" . + "78fe9b33cafe58c172914578844edb2fd35543ea84f346b4fc6969012eb915e3" . + "5e365f7f80a9b7faa627cf9161eca01ca9d1232b1aa39e8da1bc41cbc35a2769" . + "c49d1aee1f64e4f443e9eac532213d222fe284a6bb6a486120162ad04bba9b4e" . + "8a1d64d29cd80985a38987eaff40c895c72fecbc41662f35973929d41f54c45c" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "238f137b3fd84fcbd4b19f03b272b46aa50693b203d452ac11d6b56c75034088" . + "238f137b3fd84fcbd4b19f03b272b46aa50693b203d452ac11d6b56c75034088" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "984708a57bcf8f1c3373e01de141899ddc0cde1bed0445479eb85c863cb680d3" . + "40697d04d8114a70cd957fb06220df1149be44ac65e3515362cc56ed5e9ffa74" . + . + "2c07ea9ae350ac7b4a1a882c5eebf011be7943bfd9c2dec6c696e3aa7e54b87b" . + "f9043150c13fc3e20a43c8cadb0a25c2b876060e670da3e865ad0c2477e3996b" . + "c12d8440402ecd931a45fff2bc83b0f11b351032a8efd1a577be67a8ca262faf" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + "47f29f64c2b9676a2a86181e15403f56aa1500be2183f1f15f6467216462140a" . + "933283b68499709d1fb34fd954f39720e0d72d57c59713cdeb4d8cf94ccb8cf9" . + "75ad31b0831e1ded16ac12fa061dc1c1b7682e598ab901ece4e6c16eaeeeed84" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7320d4108b6afd777ce4390026035dac1efe73f7a9539e0fb50ebde3e4bff0ab" . + "7320d4108b6afd777ce4390026035dac1efe73f7a9539e0fb50ebde3e4bff0ab" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "02d24d188e522ded2f8433857d416ff0c3372c3e29a8ea289b497e802c95fca9" . + "1056085f4ebe353ffeb3500ccb3e46cf277d910a136ec29600eef2f836a4336b" . + . + "00f53334bf10c0769a70ea3cf31795c251ab5bf883453dc3313eb0cad795badb" . + "04ad7a7f354761c3c95f2d30efc5f5a528eaa584958b21a7b1c97865fcd28359" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + . + "984c55c8be91383707e9665cdb2c189ed53d7f6c94eb15441c98d2caf5678a47" . + "7b111b460bda3fed5848d133aa3fd1c021d2fe62589bc31efe21842985a58cd7" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "18788f6aa185b45efc46d8b8db2b8e66d7a97d2082f5c61e0aece0916e287872" . + "18788f6aa185b45efc46d8b8db2b8e66d7a97d2082f5c61e0aece0916e287872" . + "2567110cb06e83571f3462c7ca69b7df4ec5fa2671b8070754e237d3df13ca39" . + "89b79ffe652d74bd4ee7430619b0aca3fe5b61791af4d4ce95bbe0acd8a6a195" . + "1128c0dd9e39279d765cb76c7af0dd6dc7369a8c0a1e3c727acaa8aa77be297e" . + . + "3fcc27e4c7ca76457bb331fa899aa6c31fe1c23242db9312616a90bb80ae0401" . + "76b29af555456e24d5810d32b73a8a30262ee290b12081fe3f0d9929baaca904" . + "300e710438b7b1e25ba243d92a07f63a3e4f9ae8320868d9076271750e855f71" . + "153d9cbfda37228e79442b1b8a8799d562868ef6d58f93f6ce94514ede25fb14" . + "7abc933e5c88490b2ff15cc9d08889e4dc1f75b1297d83c69b881a90afcd7976" . + "8581ff1c92ca45135bd69f52481710cfb8ca35ac5bf21c912e64a4be6d26e861" . + "db50e0e67db02a239da86ce44c2cb540b499e916bc450d59bf6f99fecb0e2ec9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ce76109b89463f7b1f705be204b7af6677e02df3aa3cb701d5a4f6a85a6721eb" . + "ce76109b89463f7b1f705be204b7af6677e02df3aa3cb701d5a4f6a85a6721eb" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "35c167302a2cf939985464c9abf41ff9d8fd45ae7c1992d4eb3778cbf8cdc51b" . + "a5928a5c486fe1779e2b46b4ea73973ab3cdbcab90d641c6d7b828a892fae327" . + . + "85de9beae963c1c242aa83305f4c6858c0cee0c9a74d05f1cf436defda869a8f" . + "1c95b350db1eeffdfc07028929dfee087112a2bed62cc3b72d5e090d7f8163ed" . + "79d88833058183da924c88a3ec614cf739d2caa08db09e6e482e62bdfd3efb26" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "cccc24b50c95033816bfec6ac600aa592219ceff6646156674ddf3f61915f148" . + "ab54ce1e6b824e036d1ebd32283da10a1fb26af8d7376e2f83a795f19eb69da8" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cf2d484b339f6a2559ab1e395d9dcae5c70ce5309420bb882e087fd12db65fb2" . + "cf2d484b339f6a2559ab1e395d9dcae5c70ce5309420bb882e087fd12db65fb2" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "59c3b2c3f2e17c239cc54d8494ad9fc79fc4b2b02e408a960ddad75ac29076a2" . + "b16d4adde2d6ff2d14e62c0d2402e73b467a044b359fe4b00475a75679063116" . + . + "d2189e61745e78915fac2dbd86ee36522ad20c6d030302e6551c781a185f89a7" . + "d53aaa17722dfca1573313de7005db3d127b7c3cd28a6d7cfab036767d505cbb" . + "07b1dec88163c8c477ee87aedc3a19160271bc8c4d95afa823aee247f7071d7d" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "d2189e61745e78915fac2dbd86ee36522ad20c6d030302e6551c781a185f89a7" . + "688b4ef8cf134e761b1431f6c517d0bb34d2906ea319d7388eda02eaa17c9709" . + "18b998a3dabe12e8a63c7d09ffef11f2147f32b35d20302a3a19f2ca6851a8b7" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7afef080ce9849f2c8a089cfb3a043e6e15ad383f6ab0c0cd117d2a78458fe2" . + "f7afef080ce9849f2c8a089cfb3a043e6e15ad383f6ab0c0cd117d2a78458fe2" . + "8805c833570eb23337ac9c3c7536fd135bd4871c1eff2b9d29738bb1aa7da115" . + "d8c401712cead84e0cee5b9f82974530a7909902342e328181a4947e43269e7c" . + "e33a89d0bb8875d0b8db4f360cd68fc90d3c6afd55d510655a6c4d53eee7fc73" . + . + "4bf3791f98c4cfa0896abe37b2567242f308b5ca9660c65cb61f83b922e5fd71" . + "e72739a88db442f8667ab4f063dc032e3d1956fcae609472e27dc81c3f96a5ff" . + "6273850257cd414bc98064ee4e11ebdc49ec671b035a77103bb5e368b3d932ee" . + "99784d0d4bc911ca4487197bf17f02d792a342a1ca9f4443f8e8bf87369bc75b" . + "d7fbea1fab21e47bd15af7280cf2377dddd9f3b6bc01e412878dab7502622c32" . + "7421df1ea9dd5644fc305636d919376cdca1386a7b69fa889487dc6bde318396" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "1aa6252bae37926536ce56c83104358bc14caf33ff6b20c9bd7b97afefb62f25" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5ffecb8ba7d416915d2e9cd8df8667f45f8e8ec148a7f6afb6e280d4a5672d15" . + "5ffecb8ba7d416915d2e9cd8df8667f45f8e8ec148a7f6afb6e280d4a5672d15" . + "e451955970295ed8798c17bed8642ae82766d3d28a01abdb4bf993ea82d6c444" . + "3ee9d49861f2811a11909ddac8c552aa4c4a2dea7535032e8f2d7ca6e7236ec4" . + "56556bfd016c3b0acbd32e146e292138fbfe46004ead3dc623079db978f6b052" . + . + "088f62e8361c8043ab6e591d6359cef1175907c19619b95a031fdd416ea1686e" . + "273195acedc1d1542a7332ce7ba59161c3618dfca3892c84956070b08990bfe4" . + "e3c43683d8ffb5e2817327ffae2549bea0aea0f2474f2c2865d35f50a2e2504c" . + "b0e9caefe2d7d085b80d9bec3a79d0c0594cc25b5b3a3cdf36ea13afad34bcaf" . + "6d3a42856a6ef51e020420702984ad6669c31db677fcfa35b50ae442deab9eca" . + "68d7865e7a923f462ae047ceec33027fdae20f35aa53bae7c72b285173d8dc5e" . + "60f69e480d6ff7fbe0822ba484c66ab9a7ff1dabaaa46635c2c28601c92b46c3" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c28d9cc87cf272f550cbdccbde834753b726d1cf82b44343a1b313f5c950d6ee" . + "c28d9cc87cf272f550cbdccbde834753b726d1cf82b44343a1b313f5c950d6ee" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + "404f0414978115da01986441164798ca4066e0d3f5ce51becba5253c20545585" . + "6349e11718d5a9ad8ed18c4c4c00dd642a082f712be1956faa918ae6a9dc0cb3" . + . + "14daac14a022bc8e0d821c89be4b34f625e5ea5bd611de31494aa7c059bb5e70" . + "b2e3ea3740fb31bb1dd21eb0b2edfe18b4907129d660e6569cc24d8b3c15a567" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "f15291dbd3d134f63d1a33d03d663e6edb1cf2efc83da07bdb057a98af3d22aa" . + "a19134b16bf572118b6734b41495b262f353717f9d65c9cafcc23393a7a6e236" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "e210fc4674f8c9029c37d40ae9f67cc18760edc54f37edb52a68f96388348157" . + "f6f550c1f196ed8ebf8ad744365bfa245179e65a3cac7aaa3d014e176f3edb57" . + "a0929529a755e6bd48c16795bcf6d768a6a6081819362694f905583d8dc4899e" . + "3e4eaef603c1872b431724363824456b28171a517d39b063a6f379c7f5f5e149" . + . + "38ab84a889ca617dc8242f4bde11990fa1bd7acda3cca522bb9a7b1eaf8c20f5" . + "751ac926038d72d62471343a530ae9ee73335f5c0db4402c3a5bfdfb2329d43e" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + "1dcac61e1b04ed00da6857f49a7c4940549620f3a3264e3d9b9a4c37c6325d97" . + "64f921a0b7111e004a7892333234fe8fd7e4c7d1859a1272e5ef31ef89be3628" . + "e9966114794205e773f444235fedcf3cd3ee986cd627e493ae90722fd497a1ab" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "7cf10ea134da60dcf7a6a4ec7ed172e5570096ecd2add40998a2e0a6953816b5" . + "7cf10ea134da60dcf7a6a4ec7ed172e5570096ecd2add40998a2e0a6953816b5" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "bf56c50fe30ce21d8670965a1bba9409373a4ac9966de4ba5880b4960abc0188" . + "f561cc128c693538d085f160f09e849177bc53a5417dc2bd0adc90d5651da077" . + . + "13f6c3e10eecbac3ae43762f5c45a0e346563be85999bc45abfc450806a11e44" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "824250c30719223fc696fb4ccaa54f7a621e8d15d0b37d32b57cc0718b8118c4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5c1e8dee5f4e7f9248a71fad558bc8e06d8b3141e91b023cbd27484e616429be" . + "5c1e8dee5f4e7f9248a71fad558bc8e06d8b3141e91b023cbd27484e616429be" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "bab385376be62688faefee23d63d631c45d9e49123c3d3a4f8399153f0064708" . + "f572cc1b500c8d83854cabc09abec7c0a10b149b2062b844df53ee84c56c1ca2" . + . + "05dd911f1ea7b7af4b0eca6c7f4b6f230044708c20f537569bd2f2b99f4dbd23" . + "c4138e597efbc40a1e12658d04d0d936481abbcf58880c8641ad72b97c451944" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "05dd911f1ea7b7af4b0eca6c7f4b6f230044708c20f537569bd2f2b99f4dbd23" . + "11eb1fa88663fffd62682797563c9278ae263e723bbab3bee082f0c6f864a353" . + "240ad372367fb1fd9d5606068c5a5e5fd0cf0d1345a9bbc0687be03758b14391" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "ca182ffad5bc5ae6653dcdd0cef98bb2d4deb9d4602ec87518eaf0d5cab3215a" . + "ca182ffad5bc5ae6653dcdd0cef98bb2d4deb9d4602ec87518eaf0d5cab3215a" . + "99108d1898a19b3dbd0c97fbc79a7ae95c1c71f1c916313ebd86b735c411e021" . + "187ec437183a7c01325b4a0b4c64893334dc5f808fdcfbe47e8a6684f934330d" . + "5da5d189a75e2c157bd83975ce8f1f3818dbdae1155811aeeb786684d916ba21" . + . + "69d66822f4535a2f1994795eda343d2e64542455320bf5ebd9d16bb612caf39b" . + "0e27940e117251f4b5a0fa9f187cf0ad17b69b9b294847c94d28686e235551fa" . + "840680d6a49263690ebe09642372c48a10b046a99856b1253ccb3d5f7e145dc8" . + "9a3457fa81a5fd35da7d6feeef8270392c0a60b929f8b5e4566a444c5732404a" . + "772453072d612cfc4638f0f17e621666b7d34313e5d9e0d4779e1c3a1a69ed90" . + "f78d2161a383582ff9fa2360a6f2fa55498c6f387a5c3c3a1f3293dfa707c6d2" . + "5ee2389f2705ef4ac9fc783133958992521337894dd9c45edbb8bff470d5b527" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f64945f20dea14d95e74460e1b15783f26a9ebd3647931c8c6f5bb50bfccfbc2" . + "f64945f20dea14d95e74460e1b15783f26a9ebd3647931c8c6f5bb50bfccfbc2" . + "ffd399054320219f2d4e1a21c5ac0e2a48ebede67aad97737563dbd54fabcac6" . + "173e35c11f28cba32ea6597170b7429b5dc09211ab41bf5fa16a326a4244d62d" . + "e1df607f016de6256f4fc0c301f3f52f18832fd5237c668a9d6c42825d977fea" . + . + "8fc874f3e87f8a3b62ecebce50ce116900ea939ec144ad7c6d4bdb9e8d0f38e8" . + "dcdc9d3317ae3bc3d2d5f748f1e29951a7d83fc4869557d1539bdb79c1ba93d3" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + "4151630261f8d183f69d7c7667e13985530d9c289f1d1941c02c60d0226850b9" . + "7bf959b4699fecd513d4164068934b0c58b177a6e46462fa16dfb5e11f673d51" . + "194450add26c4fa6cf5b1125943daa2baca4f749cac26666b6f2366c781cd384" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "6f0b6daf3bcdf1219fd7d41de33a5b4f9e2bb01934e63786443c204c28d42181" . + "6f0b6daf3bcdf1219fd7d41de33a5b4f9e2bb01934e63786443c204c28d42181" . + "45cef59118fee56650673fc8e57dd2b2fae79ab69a008e811028fc0fcc0320b5" . + "f5ef932b783e5fdca56ccc2e8f42c1bb77f5667a18ed65e1d9362ce7ac18c999" . + "4c58450e285835d34a4528aaec11c0265f0df92630384262a80a6e0b45ddebda" . + . + "3bf5c2faf0b6c997097bc9824f072bf4de8a615dfe080402bce960bf61aba628" . + "25b43b85763831cf8a1b6be3ef7399e176331a63a13280037b1906569f1d0246" . + "a42344c7437c8bf3db3918d67e77163f11a1f2e0570faa26cd52031a2733c70e" . + "051a7a6db85621a1d5011d536595c39b8c9d54ba249b8423fe846020326db11e" . + "8989131475550eb3b51c1f6bc7b1b019688736a6c8d923b477fac535d0552f57" . + "ecbf4eaa2db5cd2cb5c69b93c9af4964fbae816693214520ed890c7940dbcd60" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40787622b29afbfd3b0b5e12c3c56a0e90696bce104dddf9eaf7a0c48ce379b1" . + "514781c41ce4773e376065a7085b8b60c6c83ed0ccd72063cdfd2793a909ffb9" . + . + "f8414e8e6a66d93efcd91ff8e605f4f399cff866813b79b4b25d188f07f3e35b" . + "99ba47d8d204cc14eff92fffbcaacdc60a5c4ccc3e2ed2b0e878f7c23bb26f1e" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "ef08bd72a8547f4263fa102027bd048ccb853714b9ee31eba2d126a46b905a53" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d08bebc89c659b64578ddf42f2eeb833d178cd3e6cb14be0733da71107070d4f" . + "77804e2ee9fe1ee7597e3bb78a7a0284d24a7837d0ac7f7d9a2c56abb57258d6" . + . + "efd356b6bf885dc53e9d03219b25329b42c52fffd197f3c8acc9c84b1c0f044f" . + "27c4c14612d9f15b351dd918a53f3d0e1869b769a2baabbeddfdd6c1bf27c0ec" . + "0b215f33a4782e72455c0400543392ebf159a708532ccdd5ee1861a481534eb8" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + "9662ed7dafb1d2805e1f4a774ec33c9f5a880bbef6ae70d538201f9e004c962b" . + "154961f80f905050c8355bb9ce75fd58a836c95d842f6a4b2e7c53183ab4f119" . + "ef10768af965d1ec41bdae4d5eb116511a43272806f5e44561e580dc1217e4b8" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "717b508b6fef54b46e28a098f6f6e45a3503f4a417f4768557cd33b9e21674a6" . + "717b508b6fef54b46e28a098f6f6e45a3503f4a417f4768557cd33b9e21674a6" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "ffff6926a4d3c72f3f2b0b26a228699f8fe7e65b4a8c6beeb057b1ddf6679f4f" . + "875ff86bf06963f951addce85b96d65be514b2f6d098234c2784bd84dce63a03" . + . + "30b4d63f2ecca7c3280a36f576a3ef9e8ed486c1a0f8e2aeae5fa8eee18a0c95" . + "8de39554d0b2bb160b6c00ff93b5c535a768659dc32f611d3df9e71013116a68" . + "f6eac97c000903b0b70b0891eb514bcd0880bb24f138d1a26d5a53b8001ee1c7" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "95c394271baa5ea4dc3db3879830594673c8de838dc37d9dac241c94193ba188" . + "7e9ad576af1f49ef05bfb170c70be31ea0617881b78fb2927dba36daa38af83c" . + "79357df99c07dbd894ee2a3b3fa11f8b2b94ec37e9b6a29e3cb27422d3ff1b85" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "5df375d8971a4740bb22ffaaf88dbad70093ceb839f8145f81fa59cba1f4adb8" . + "5df375d8971a4740bb22ffaaf88dbad70093ceb839f8145f81fa59cba1f4adb8" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "dc813ace9bda8cbe8731a0d87e0726d8ca2feb2017a13afb4a0f621ac518fc7c" . + "ae056d745129b75ee270e7f64735bc765e6ba3385984efcf65bb5d24766abfa6" . + . + "78dbe598636c4bb05729fa057c1f51f35e525cb13a34849e8d9a607caf9a7447" . + "b6a6a0b768ba3d4671625ed5ae6f4e73e1f64350f841b70fb5dd118f5b4b9abe" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "3352521819b266ea3f9698e56f6e328cbd528eb8c865cdc2ca95fdf97785b622" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3769f29f5679f006f4acdbc6bb5a7e2b4a37a6dcef54863a1a118acc83fa60b3" . + "3769f29f5679f006f4acdbc6bb5a7e2b4a37a6dcef54863a1a118acc83fa60b3" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "62b4c7ad1892e50dd8fdde325fc304d467652c57d730b6656d6cea196507f56e" . + "babee97e60fd19c0bdbfcbf07a6e04b76828769f72dd3116724be2472c8abead" . + . + "c3da9a7341034481de62c99d118fee095bca918a398479698aabf7e362fadece" . + "88a86738e05a4e85e99d063d76934226b86abc2b72b95682de12d5ed654edd0a" . + "c14261f606fc688af7d7eaa3a5839115d4a98487b82f2667bb685e7a5fd62cb4" . + "0f94ce473060e7c5503d6bc14495551118663605be875c111b20ae9f9a3080b9" . + "4813175056c7c9e0528a0318c279e6d9e40bc7d322dfe0f87df53229f7d6956b" . + "55cfaa98a6b0e5e63dbe5973cd7847c7782acb08f8ec3d9178f2c0b7ba20b98e" . + "168a0a0d4515e231fb8220a4c9d25876d1c56045572f7a444db736c49338f1dc" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "6ef242b661348fd6401510127c13b6c7c77470b0a7ec853b20c08585985dbd9e" . + "6ef242b661348fd6401510127c13b6c7c77470b0a7ec853b20c08585985dbd9e" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "28b816f36f3268a39b05c5cbd3a0dbc08aae7377f70cdcfbbc6efef405535b80" . + "3533c03ec1ed4c15841e647a9a3ab9be5f3f2cfc28e51e8b0a95ac22ca52e9f1" . + . + "e5d395f8f6850dd239617d73207d1f82e03f6fb69dca81fec6e1804d7a08477c" . + "2585c3207cbb7c22571442ccdcada0e907fbe0a01142e3c60c2e0b433656be94" . + "4070eb6e877128c341ae4290e9e1de89912bdec3059b7b36118f1a6dd01d8003" . + "bfdbf47a991998dd646608a14c4c12c7c078fdd8d2bed8cf227ea453ce4317ed" . + "963bce7d97fe9bed3e3f4bb9575af12344ae1a5a9eb2e9e9623b5eef6a90cbde" . + "dd63d37a4e32948c9879949dc9dd52b821cbb30329fe49e6ed795d2182e406d2" . + "ae28889a685d2b4768b6dbcc3d20954beb19b1484fa508c34e72a4e1d023f97a" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7716e8ddbb5ca58de1b96ea180830f8da1ef1bd20e9fc5ad063ecfd62786e744" . + "7716e8ddbb5ca58de1b96ea180830f8da1ef1bd20e9fc5ad063ecfd62786e744" . + "9429a124933dd7b20fd9f88474afda11067c580ddfbb38b286573859a3e17a52" . + "00672b764728a55247d9a668ea569cb21d8d9fff0f4e271315c349e384648dc1" . + "bde58df08070ed6fcd32f24ad9f0bc062939bed3d0df70c6a4e4d936cc1b42df" . + . + "0f3caad44cd7c09520f1e093f6a56009827aac1275f2bc1157140186478e8f7e" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "ac8b6e7f28c6f7d16cce71924ae1233933907381bf3ab40bfacf3a17a61b7945" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "f700d0313525c0887cfc2823c75f0fd87ae26bf52383de3b80ffa33bd1f0e8fe" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c4eb62705b98684da465d1328e2f90c77c51b9f384c68fa699aac3b1793c6616" . + "c4eb62705b98684da465d1328e2f90c77c51b9f384c68fa699aac3b1793c6616" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "73dfa4fe16facef48d8f2ff21055719a15164bb6e316cea80d2e93f5985c6cf1" . + "5b791b086fb19e900ed17ad7ac38fade164f53329c76acaa8c868bd50c3bd7c8" . + . + "59ccb48fbd13eb0713a32bb4447d7af7a9d72f8185df862d5b1b33cde5547b3e" . + "658d52b186006443df2651393c7266016307377eb7f1619100ba2f978c41f275" . + "bbd951163f93af9ac80177215337b6be57642e1ca28e4d78b73f1ed088bbd287" . + "60d0a414731c0ea7be495cc1ce8ce0a23975cfdda37a8ddac0a89f3c7e8fcc8a" . + "5ef216a5cf9ea6b93b94d5edf3399a1fce334b4cf4f75daf0f94b21d93d40424" . + "4ba1e7a32cc5358c8087913a1cc17a13b081b124630cd503644e57d29304e479" . + "66348930532252e3080e40b70b9d88ae345754d7c686502740a8d04e5beff41c" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "41eae7c0b666b2afcda96305804e3a0385c15bf1f2ca758d67cf815b3aa919b1" . + "41eae7c0b666b2afcda96305804e3a0385c15bf1f2ca758d67cf815b3aa919b1" . + "b6e348cbd841405d67f9dcee938d5d5b143675a4d5b8f39c634c103a775d6785" . + "fdb909fd438277fd4b497991b437f465185d0027fb3d350e9cba7a37301511ad" . + "a328f80ba8f9df6b00e19500c97cb98f1b6d2dd3fd075c9fc32279e48b689a53" . + . + "96d75feadf03b8027b3ff9b3d745bb5851ee3c46f24d735e49d7d1083ade7f26" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "30da0c04123ce59219af6c9bf44e41d7a078e7c6eb0fad6415952ad38b83a8e5" . + "a42344c7437c8bf3db3918d67e77163f11a1f2e0570faa26cd52031a2733c70e" . + "289046db9bea1f88fddd0e7487e45323e76ae875c1fe05046dc2974a8f0425d2" . + "d4a2656f81b3ba39e97a43e03a23fd880a328b11ef12cec0fd56d5a6a11103d9" . + "d65c415a257447f4948b3c31cc3c26ea883f1ceb61b115b2981ca8dc15a59c0b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c3135cd87e4f46e6bc49521157fe1aa5c52f99664c768b94b2523ac8084d4538" . + "c3135cd87e4f46e6bc49521157fe1aa5c52f99664c768b94b2523ac8084d4538" . + "2d6ba55314375d0a6cd5c62953f16d704baf3d58d6f17da2172d0a7b7b9eca49" . + "f915d21f726b738a7becca81a59e57ff04f80db911512164e5a6778b4467019c" . + "ae9696f63ceb1672921f8e47e2bb32c0663847b773d8cfc3e06320f500c3b704" . + . + "3acbd2f371de320a9e1ab4e4d4624e46cafbcbc1f0abcdffa9fd52f2171bd6c0" . + "b7e18268b5bdeb37eb9ab257d64f1bd8fcfd010a8b451dab5e285fee669543e8" . + "045daa014617aab6d64110a83080c52c62f2c8b025e7a6607942253819a8eae4" . + "f96b3b016a6e7cfad0d262dde34131b9948ede708e7028a4332054f2ad9c623a" . + "ac00c67b9bb521364c1fafd303b5577b91c8db486ea3c1fab550ed17e3a18a82" . + "1612f1a47f0ffca1bdab765b50ee25979ebe8a0bf5cf081bdc67aedd797412e2" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cf4f48e62430bdc499614e7167de5d8743238910387879a24bfc98e0c27b5578" . + "cf4f48e62430bdc499614e7167de5d8743238910387879a24bfc98e0c27b5578" . + "09de13f4701d85d74298e4b230e017fb4c4446ad1a89d26b8cafd7f71366b3bc" . + "73e9ac1fa2c6c2894950183a196a82736187c5fcc93856d41dc75b75be72d437" . + "1bc6f82d61c66404918d687750d944ddbceeb0c43c4ec32cb0374ba15d6fa1b0" . + . + "5df41312cd3967db941bc9f1f5dac223fcd4cfa3ee62a3ef8f1aa4c0ff480ceb" . + "8349b18f5e26b270894ac4559a8baf3164a32d23edbe771e07d5bf7a724b7d95" . + "a60480d05a514fa03ef9ecbcf01236e814d3c25a51c3ec7fc6150c6f8883df21" . + "0d7f4f862c9c1a1f8cd19f20ca2f48b01300fb1b7849702f00f34115058ec0d2" . + "5df41312cd3967db941bc9f1f5dac223fcd4cfa3ee62a3ef8f1aa4c0ff480ceb" . + "009352773b301833007c46b216a4b7eace6cdee5b9bf014ccd1fb4ee01ab7d1e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4ea9bb51623460af6b0f4fd352fbcd07d7f2d56a0d8c3ed3a315d2e240565ff6" . + "4ea9bb51623460af6b0f4fd352fbcd07d7f2d56a0d8c3ed3a315d2e240565ff6" . + "8734901f969c02c0b8eca2cc6207125322ada644a09175567d0a19e3ba4e09b9" . + "68afd8ad08fc87113613989a3f01745e8a5360c7109064b7d9dca9c07cab5521" . + "da7cebde1ccf204fd467ecc59e69e774ce8bbbeb0b25a31712fd72765b42579b" . + . + "9c0df64cc0c5ad11c0015b5efb3a30a98e0519674230c1bfc07117ba20f44b66" . + "cc60694e97e598ef9b10b1bcc39fbe92f55bc7e770132779ad50a302f748df13" . + "6ccaae62864bf2a9fc767953cd1f1501eeb59aba5458ce771cf15ac8534325f1" . + "1aa60c3507d6f591856c12131f5eb3b28eed039d94b5e7d20160e06a5d355ca0" . + "4cd145ecd28574ac94967d927dd3040f5a4e51d763a0be00176e56406757a972" . + "dafbfcb6b3c201fd0b08bf5deacbff00084f1989101065d8756cfcbda10eb701" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d04b365a269696aa7b7b7a6974f789f2803533503acb18ad5ef6f632c42afdab" . + "d04b365a269696aa7b7b7a6974f789f2803533503acb18ad5ef6f632c42afdab" . + "555a1cc0498dedfb008a6134c026feabd7408ec196dc7503068004446b7e6527" . + "e5fc9dc5f80412e5d6971ebda38f979b0e9bd40642c06b71eed512b555d55849" . + "b4981f342c443b3311e611f4d235e5c105eb4990737efdb284744232fbddd992" . + . + "f9d105f35774d9e840b8437e4fe748cd6cd088b4136c8d9a75534adefe7beb72" . + "8eaa204d03aa7dae6c94ef0b74f9d9b8dc02068d8a25e2d3f72bd85625894f8b" . + "e44ae713f3b34e612ef31438a077455f5c8ec5dfdc9f1d236e96731a02fbd24a" . + "efe73101a5eed5278706676ce8725e6e6fe83132cb95b51e72c5a9308e4be6cf" . + "26bde4939a03dffa2afa82c7cc46a9c8da065b4a7fe10bfc10259a377771175f" . + "c1ec4294d07c821ddcaa83daecf0f91feeb644d671cfa11c8c9342e33fd7121a" . + "5cf1d78a3ca4f9f4f5bde60556503ad5158370821e20196bc104c822aeb71478" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "2db87899202a4df5fadb5ec62821e5a57284068804fced3d0c20297b3857ab86" . + "2db87899202a4df5fadb5ec62821e5a57284068804fced3d0c20297b3857ab86" . + "4fb92a5c9e2c5d8f01e0332e048493e69c21ab2d46627d38b746ec24d34815ed" . + "8a93eb9da04c93b599ec0c428ce33d8ba3253fbe3c44a61b62af9a7848f5a441" . + "eb1422cad1d746b21a19cb13f230a4294e59365d45a0af4722ed02ca237da56c" . + . + "c7a377924ee9f3fe54da548694f3b76fb1159e1755f58937b13325ec1640cd98" . + "0b0bdca51606c5ef8d1f6b07be8132764863dd55f1d0bc8c0b4b67678ce39f4f" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "0c1f6ca47a82db370556558869e43a26befef4132b92052a6e7c86d1ebc14b69" . + "3e7d8090dea3e3407502e2294246089a81767ed3530851378e02f3fa1c60af74" . + "f516f085466bfbffffd4bd5cf593bd20c34db2667b0bc8d57bc1c0e9cb347b7e" . + "56d3c7c585bb41a33878682beafbed0bfc42c892012d1dfab08d255616fc3f77" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "558a1c8f7d2cb164effe944df80694b5b1a5561e4f418c16008eb9b41f7f55b3" . + "558a1c8f7d2cb164effe944df80694b5b1a5561e4f418c16008eb9b41f7f55b3" . + "1d6fd46ac5903df6c13f49d442048ff07d67c92e90f5b9be5ab3dc3b1b8a52da" . + "5dbb7eb06aa0f91be426f14dbaa48ffc747b1c7330a33456801a81919bfc3f06" . + "b657e8d5e020d53462d4b24524a33051c7c30d4a4163497a1318d89c61053e84" . + . + "be6ce9c0cee961b669cdece986011f07d0cf8fe6f6183da682d5f11072f7dd22" . + "73208edb895c892265bdc650b90eeb2369f75f921c5032985961ae06b0c9fdd6" . + "26b96ce8020f6460db2f8bae3a82045c39f913efb946e8ce4c70f4d46da4a798" . + "c91bee449065238860869ec12aa5358298caab010385253c97d285468a892db6" . + "737ac90cae8adf43cc4d0a9eb20107b403f1f1d02018ce307ee88460af4b233d" . + "7f18b47db12447bb8daf53d47270824ce55f19024d30ebf223ca76b645774d23" . + "4e6873a065b51a56958c19ce3975ac1e13f0aed5bb3a43aab51dc7c8d53d4345" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3adc2f996344622b0eab71ef664a00034e33ad1f58c5debcf86f6f4707363aff" . + "3adc2f996344622b0eab71ef664a00034e33ad1f58c5debcf86f6f4707363aff" . + "0b2d104f967258a041bb02ea358b79d8165856219cab2dca9827f6221278f558" . + "ff6386e205151f32a76b0a8b6e7a7aba22bfa61aeb18f4b147579936028ec152" . + "99ccf46f13823ffe9512097182e6077a02d81c57e36b91fa479881ddd9d389ad" . + . + "3993272ce793b5b46986de11800cb4da9496e5d03264b1c57335761e070ec2b8" . + "7096a83319ca15e40bd5662e01b0f04965aab7bfb685a37f88790af6fbe05ed6" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "9710576545339be8b6322da4fc7abead6f5b022989b17b6b1be222a0d5a297d3" . + "697379ad024de815d525df94faf170c95cba7880d9cd8ea0e7014406f1f0730b" . + "147db201c7d0133e99f9c6ef6ff7b581271920261d6f84324fbc4798bbba1f3e" . + "4e6873a065b51a56958c19ce3975ac1e13f0aed5bb3a43aab51dc7c8d53d4345" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44b43fd4f2a3ecd73366d7435dedeae8c6c6550df7d9afb46d30709eb9b02f25" . + "44b43fd4f2a3ecd73366d7435dedeae8c6c6550df7d9afb46d30709eb9b02f25" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "985474a89b7ad31f021ca2674bbf2dfaf76c0d5818c77653e16b457e37c66460" . + "295f0f410d7cf3966612c331ca7265b68e615160c92e2bb1e90f4bbd7bbaad11" . + . + "c15f7c505c2916f2557556a5cd0c44f1a7d0517b179baffce7b024a0100a3ca5" . + "0a20e3e2f81b9fe3c40326a0cc85299af157ea5dd453692d0d13d50fc0d52ce0" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "29de6d3b75eb95842a693e8b7decc817d52e93553fb24dda2273458ff023aa57" . + "fc11bc6740ac59e1832be30360d046bb81a169d5fb6ef675123e7f4f26a5e1aa" . + "8744e88f331dd7c4306ff78435f0bb36de8407a074e205bfcab809393d8619af" . + "2d4c13016f0fb15df81ca1ab4d4a2923bbf73452bc8962a9bf935bf043ad5351" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "187fa47db0a6d380025a6d9b41bfb5b23a45f76c49a074f54059bfd152bc8e4a" . + "187fa47db0a6d380025a6d9b41bfb5b23a45f76c49a074f54059bfd152bc8e4a" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + "b5b3fa89cbbbb8ffc9ff891f12f3951e270ab39331d52bc2fd069d6c67dae052" . + "351e01f096ae179122f142baebf1c6f65b95bc2c88b89ce17bcc612d523c726a" . + . + "47bbb6ac442326d1c005707f26cd71309fb4e9307f2bd74e091fbe9e2c710e35" . + "8e6cf80a8f9e7d4e57be3d0d1c84c2c58613a78902c74225b29600942e1a550c" . + "14916798d02e6c5a1baff9e4f36762cf3763fa88fd470b93c7fed5dc41f1fafe" . + "87c455b1d755f3509b166110579fe10ecc0ae872546d557bd6573615578b8ff6" . + "3d7cd1c07e887dd09edff60cf24f92b31e6b904caebcc93df1417ed43a58ba8e" . + "3b142fefb07a8b3ebbb2f96dde1f77f4d182f3e9d4a65d1f376d7967bf528d80" . + "8314ea9bb390587b9692fc0469b6db33cb04a7a0a0de0940e6b8b9a0335df305" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f77db2512df3f0445f8a293aeb9a98b61c020404269e24d7908ca2c597e39012" . + "f77db2512df3f0445f8a293aeb9a98b61c020404269e24d7908ca2c597e39012" . + "5f83076e9d31f533afcf4adfba014c3dbba0679bb0bf3168eae5d407a138cb0b" . + "f52ec1859c9e8f5660ff6fc1e7aeb441f414255f49107201f4e42f28d8316844" . + "1015ace5282d474e9089b895a52acaf1085e0fa69e5022b6b0bcf3fe758648e0" . + . + "606b30346cf66fb8e47071dc83ee1d6f8d6b645b11c346770132f2bce6dba5a6" . + "e6518c676b7ff9aa8eaeb6dde836f18fd8565f8812a25dc2b0d5dd7cf3e535f8" . + "59dccc3f2101260f313e59b9e096f2d479da00442b8f70f7dc84a312f5729fae" . + "a96f5137bbbba1e2be2ec94af691f2aa313ce8a24bae734d77d8fdfb1dc3fc0b" . + "e00e386feb56245ea358b58d35c580b165d683708e3f3d456b7126dc8513f354" . + "8728c6de34b356d16b61266ef9cc368ce108dc1179603d329c541e5c10770c40" . + "ad041ca802d884897e53c69e5816cb64b69d7e1266b3810424390f0249bb6693" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "47772df5acc978df398ed3fe5475046a544b6860a2f64cade25e78890b9086ad" . + "47772df5acc978df398ed3fe5475046a544b6860a2f64cade25e78890b9086ad" . + "a44f3d41823b1e9ea5cf26b98e9bde24b46b545fe5f67c94033f190460b8280c" . + "4a27dd1aa9f9bc34b0376538960d7969f88d11a2143141f63a7cf5ce6b8e4cee" . + "3b1e7eee2a2923cf2280e40f52cb76d8a71822a34bcc64131a01db1ee1437080" . + . + "91dc062ff3ece8b65657eb1c49c667a5c0826d612ebcfa185c51933bb7b1391c" . + "0bdc14929b297a3d3c61c9aae4e157fd478be3fdb20813e05872886b1250625d" . + "9b199b0090cd718f5fd5cf48aaaf9e4a008f28cb24de52c22e644abc7cde631b" . + "b6a3de01d8bc5c5c5add041156a25e0af051fa46bdf65e060e74dff6e7aa0296" . + "7d20cc0aaabd51555ac08ba988b311c9c855235f0bd4b9c454d9bf63ffceb526" . + "6cc6c2d5ee810ef53e56d765b0ac3ee0d72dd4fdab0cba25c8b39b50f2ec0af5" . + "2ec68c498a975bd0e86e00bf72fa9cd79b9685a5dfc6d75eba9ee0b29b523f0a" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "324b698ceb4fc12bfc28ec5b7240f9fac53564333dfce9d09bbd9b4af3f820ef" . + "324b698ceb4fc12bfc28ec5b7240f9fac53564333dfce9d09bbd9b4af3f820ef" . + "695d91c44aa499c4e2226a16a860a773c5531cac34613124f5cfabea25345cf4" . + "ba757a5a28a85061e222c9db0cdf2dc93194a40c0cba846f3877bc03fbb9b3c0" . + "417e730af76422822623ba492e3b9f21efdbb0106091cbfe151b685636fbfe6a" . + . + "612e9b1143db8e7a511dfaebdd127e9bbedd6535807b0dc2fa5964282708ca68" . + "da45d1f7930270ccd6218bf53eb282bb16e598fc6dc584e55ca97000fcd20343" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "ac68efe404bc63b19093e3da9c0d53c9bcb7a101ae13cd13a5d7114d17674296" . + "aac324c9f8690a67f4f81d8ba1d8dabe213990cd5ee1aaf90c2e0cd3f105b850" . + "0a431914debaed58197bf76997192acb971d25e0ec6ee2a6247881ba40e64aad" . + "463fa4ea12629c1d92b7336c60d7bdaca4f5430fb4c327f3e8d107b681ed76e3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b02c597453e4d76026c4bb980cf559a8d74e8c587213a02bd839842ec1f72db" . + "9b02c597453e4d76026c4bb980cf559a8d74e8c587213a02bd839842ec1f72db" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "cecd4c5b8df15fb76a4b3bb5a70c35b05abf901b1ff119f28908c265749dbf43" . + "3e99b013d224a7c146a33af6c280b2b577bd318d1dfd29ff318ddf7bd8efb15e" . + . + "2f65c0dceb7e1bc8e10009ebb6032257282247cf9ac1473bfe8465b8403c0957" . + "da2d1bf8a1faba3f9487f74c49e0a5f83f01fcd603c8be48ea5b9344df69bcd4" . + "0bdcbc705e945c5bd5de78bede1e23411360741f1a26a4d4b3dbb2aa2e1c9fa0" . + "0f46a36afa76862d22b6ba61740056b9832ba4616b0fc4043b22bc4dbf213510" . + "ad0810549705542bb20b274668b3b706e56b98fdc2bd91d531dc3518e8e83425" . + "bbf671ce4cabba15b94fc578355adb9e6f52442d7c438b16bfc2a5c7069c7243" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9024eb5af6c2b6278839c6133b3075778945cc546c0c0e6a6a55860bd076be03" . + "9024eb5af6c2b6278839c6133b3075778945cc546c0c0e6a6a55860bd076be03" . + "067228384bbe28af84f3ca5b8e8bd8241af5d4178ea00f46f5d06a9f0682af5d" . + "c49e604699688551c0443f58d69194f605309d5e7e12c5f9e498d6384740c38c" . + "18f626c0d2e27664f107514e350a7a1059b53ed9ff6aa6bad152f882c3f8fdbd" . + . + "46ca3b0a4953d95221662e9dc8e7d2fa36fe57a330d6561440085ebc5001fe0a" . + "5359621d81969a0a1a15da10371b8ed33a5b98759fb746700032db55f30d7484" . + "0dc473525fbdd0a235dfd632847a343ddd3b7a91d442d373fd582b4408359609" . + "1512b655c585bf9e844ffbe620da30e4189e9db710a745030c1daf7007c12bfa" . + "0f3288f8b86cc9d935a6b1221efaf5ff879c07596d7b6cf08e5410c146ec5b1d" . + "d0a53779541897568c2a28743b0e71719538052f75d3fc7a51f419333b060fb9" . + "9ac951e71e052ff9f32f02501168c05231bffe5db02efc30350b65d4d207ec1e" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "b13bebfd81ad415a0a0a53a5c4394b3538ff858d9bd81a8c58172bda73831b55" . + "b13bebfd81ad415a0a0a53a5c4394b3538ff858d9bd81a8c58172bda73831b55" . + "fafe3b4e55598f719e8465f54c170e1c8e9c6985a696531a779606567290adab" . + "95f4a669cc1eb03dbeac5093d156a677c9c761016c70546673fec77806eef8ad" . + "4e1baf388b1ac0b4faf3b5c0123b7939bafa14588116e99108a38ae64cc9e777" . + . + "08f688128920385c3dd66457fde6e6450d6a8f8668390c0f4d98f2a40afa5e5f" . + "1e22feac0ca043394e8adf76dbd8037c5ee97792d78e3dd823168a336b1b6432" . + "25fc343f937336cd0c969b8ad94e7a18bb29f12640895bc37b01f81ef9ac0636" . + "e75a859e75110e175055a9cacf94c55f993a437a5121518a200721c450abc6e2" . + "0ad4adc17177d73f24aa81428fd8bb754a5c9f826e8a79f9867e5870c5f268d8" . + "36b7ae114ccc52ab008d7a9e6a08817355f63f49f67483aa35cbe455880c33c1" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "33d2a0d5fec08ebcd149f8a6dfd40e4cd3369744b351315ed3948dd806f08aa8" . + "33d2a0d5fec08ebcd149f8a6dfd40e4cd3369744b351315ed3948dd806f08aa8" . + "5e61af98f8f14a58c5827f6b411e1718b1381fc3f482eb6ab5d4b7eabebee58c" . + "32ac6ddfe8791e48d7a97dd2d67b391f536ebb55123639d50fb2cbbf4a1b77ba" . + "f6e1a8a1870d29e34cf8450fdd258881eda97b0affab862d13b7327e5c2cc76e" . + . + "c255595ef617f9822e71f565eeef0fcfc87b59527318375a7a1b1d7bb459156e" . + "eb790bbc1ed0dcd59e6f10ef4d9ed5293b827c4a51d407aee588f863c248ae32" . + "edb3660f41cf9e2272e8d653df5a49fe88fa0b43fd187b3b68fb549616c4754c" . + "79efe3a38427e6917ff95b8b978a8794338591989bbc1957095bab6e4eebec5d" . + "98bd8cc7278726e350bae21491896a89e6f3beef7f58d3f678ed9759382e4d04" . + "829ba4337342c32adc99810c33a9be572943e0d2a9e3be324a05f6459cabaa1e" . + "15fcb9478369b4887f7ebc0906f0fd15a4e9283b8b7a82bc7629847ce906f004" . + "0b73ee46e72a92f897c3332b793c53adf3eada126fca4f32b787f63889050caf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "27fa64617cb426631bb4bd55d7b9aae0a62d539d5b91ff3b30a34e279d303922" . + "27fa64617cb426631bb4bd55d7b9aae0a62d539d5b91ff3b30a34e279d303922" . + "628bc2ce7663cb04d4b194e2f51192b18702dfc7c50139d30095bdc42aada5f1" . + "3f75a19ca539f64fc27637720d6ffbcf709312b451266aa267c23fc9ddd1892f" . + "577688e752a478d47f778da52870bfc92b5dd3c8653b78657cc0f5f5d1697833" . + . + "e0ee4626274373ffebdb65c69f21e27c60cc89cb367a32821459584a54d17583" . + "04df103a01b5c60072bb53cdeed8200b484c9266d0e6b5ff633496736b718066" . + "1e644f511cae1c98062c1b8528454ff1c73da61d263636e622361a8f69717a3b" . + "b239e2c90bc6fafb3f4aecb9342335f0b97286a789a645c193b9d0f9838b5c77" . + "f46d40fbc91f5a3c025648dde91c1b8413e2b20cb97dfefbfeb79a96d4db293c" . + "a88f54156d333ed731067c1d1a30c2c3b1499cd7cc9bdafa4fe5f82e7e19eecd" . + "b03303b3cbeb695b3a175ae043b8e6e3bb4686cf2883a9b0ce2767de1d6ab9c4" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "56abb01de67303eda40ca13863e81c56f5c21b19094506377e92bf183426dfca" . + "56abb01de67303eda40ca13863e81c56f5c21b19094506377e92bf183426dfca" . + "b0d918923b2d7239ab57630e5025d9343db3d05de1f69d8282ab88502f2ab24a" . + "7487ebbd6e3b5b6808bd6ccf3b2c07591366c0ae39714f1139e0a22481558d38" . + "b965d7819241e53646441d7de5df6293be85a8a02cf599d72b4cc6f3b519d0a1" . + . + "3b199406b1fd75e4729078b7fcb2ba41074a14707d5474afe15dd1d2ad34b2b7" . + "d49c9c86ccf1eaf4715f01faccecffb92caf9d2125f3a024b9ae8d7fb98e50ee" . + "efa6988b498aaabcb1a4fda6431a15f5c4dc2de10925ec8c89fcaafd2f78b57e" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "61e97c8d9d4b67f10d91f28c8d074dd32a28d2c1fdcd6d7efcc2eff740ea5d22" . + "6534906cbe70ba08fb43ef313931de5a4ba42310ef5672729a34f4968dea1690" . + "df2c9453612eb27a4bf60e136f3edd0e4c9b42bef2ebdbed6b3acf65201934da" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "4e729f98faa7506879a65c70b9df03467f8ff03d4b1d277ac0682b8c2710d1b0" . + "eff07c86080598ba632c632af4c9d538c69fa2a789c2115c4904beccb7827b6b" . + . + "203efb382bb575d652f41660affb6e05c3cba2ccbf499be7a8a8c3f770a47c0f" . + "ddd0d802ca257ef55ec7b17fb37ead78a81b85fa36e9144742fca38c94167382" . + "8dfbfb11f5b5aff81da2aaab0dff325d04f699d8f2b0618425dddd31b0022f6e" . + "ebc726403a7ebaa044a9be5cc4396be0c78551e95b4825ac6cd2bf0992561ad2" . + "224c978b4b52ce0d8459a174b0d1111aabb283cb8ce67eeb8f7677339fc6bda1" . + "52b004e75a0e488e63ab1573587cdc231a567dac12ee3b5bed34969902c5a371" . + "658fd57ad59a9abbd2ae8d3e8f7cf8d7f2fd1c5077c61e7ec3a020d41cc917a8" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d9a5344f047fd8b80d131d73b69ef37f80c8534a7b1a620f4be1a2d343c8da29" . + "d9a5344f047fd8b80d131d73b69ef37f80c8534a7b1a620f4be1a2d343c8da29" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "83f3d293feebf01c96bdaa73d0b71fcc10762ff457613579e6032f60e263e43e" . + "328f8d36dd657d35256d9c9223d5a28e1157451db94399ea3e865999215165a7" . + . + "552f5cc946a51bb6c57879ec7c9630ffddf73a0377eda3ced7fab9f53fd7f6b5" . + "77fbe164f4bb39dd2505ef24c28d29d8a288f2a91488c06179981abdf2726772" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "38b404a26a7e89befd5768a181a4c135f88bbac4246e711665802aeb8b8516b9" . + "16c98fa1a9a29559c6d6371bfa5f122eb860932baa3c071869cc424dd7f8a0a0" . + "a61fa0689306b6f8a2e5f47d8429e5bc369c9389e398e0f529500cf2bcc13bd0" . + "126d45d3bf9373d5292e584cb29437f1208019faf91fc2eeec3f29098b51cd17" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "785c2ff90103b5a667112a4cabac2d501deca33150b08fdbc222d8c293ceb9ab" . + "785c2ff90103b5a667112a4cabac2d501deca33150b08fdbc222d8c293ceb9ab" . + "4b8af33ffaef6fd60642ad32e0b38edb8384283f60d27a5f4f9c33d1adf8f154" . + "225c6a4880e79d707c99cde1dea4e3bcf0fe0789dbb1acda1ce7b9659cdad495" . + "bb2d63e29badba52169ea4982a3d5d7ef19ea66b1803fe79c72061bb56f39570" . + . + "30afeb2757307bed94bc4d4bd94f74166317f3f2d9e270b2c98c323265c462b6" . + "ea9d0e7e9ceb61d1c52093188dcc03f56e39d534335725e374ef69f46b941c03" . + "7544065126eb616e77d840abb719d83353cbf02f4ed3649190e91cdde76c0232" . + "da7e9aeec6bae49b156195b0202fb383fbe6519b025259bfda43174cd002cd9e" . + "02e1843f71191ab00187517bd63c6cd1354381def8097073f9da0a559a59f6bb" . + "41066cffaef4bd5c5956c58e7f9cc1905d6ef13426b8012722859ff5a2357b48" . + "3adec907135b472554a9537b3fea2b73bf2b5e5351873754cc5126a715ef5170" . + "8998fc934f253dd44cbc138604a5bd6474d418033a98292e5c3a5bf835026190" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d60d1a303b1d68a1ecccf655a65c1ac60f310d58b1144637e6ff10ff0aab7b37" . + "d60d1a303b1d68a1ecccf655a65c1ac60f310d58b1144637e6ff10ff0aab7b37" . + "d8f848aabbdc512f726b35f858bf4c2b8f9cf7379c76331fb2577480eb109699" . + "83dd6d9dcde82d82eac8d03faae0557d5589dce6509a9254d5ae1987f7a3edc1" . + "df8c64f481e7076e41b3e0d5dfb4953ef1839d7b463ba79da3030d085458a2a9" . + . + "0fd0678103635acf60d93e904662e440568f24efe5a99688c2fcbc1bef26beed" . + "0e639dc86250420defec20d3a46a6e1f5695b4db67cb414465ed5a66b4510a0f" . + "6b4ac9e6774cbf052c10a0b7011d6b743c0b495b78f059b8968e460defa3ba6e" . + "5706ef8457b1d7a4cc21cee35a0f687faae981546c356b4698716e58f54bdfec" . + "8d250f7130d3309456aa901210081648b322b98c7d2992cd3bbf943e0545838d" . + "c0c4c19259446b21354028f77b818fcd3c5d539025a2aab2aedd095f6e6e5df9" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7d4a4ee82db9645b90d8b9d8e169cff405e7bf33eadb7de260286f045de159b7" . + "7d4a4ee82db9645b90d8b9d8e169cff405e7bf33eadb7de260286f045de159b7" . + "6ede6c474419f0e7ae270a5951033c41d7855d47129c701187b95632bc0be221" . + "221f87a5fa619620ab626a03a1c2e93f51e735861c9fa15a069bdbf6715987b2" . + "adbf91ece59f8ddf9647e730cf1321af96f5ffcc7805551c7be3cfd1117bd157" . + . + "7f601a648af860eba423c109a21e03f7453359f886890d9f1df562d10ac40997" . + "6b191b78c7245fb61cabcc0da94e7392f26b1a3a1e035cd463290c18f2f13777" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "a1158a47e357c6ae8e50364168466c6f97de330441a53c63365de8fa9a4094bd" . + "813aa784a1decf26a9ecf010216816ae55454d82b6c02c8f380729969a7a9675" . + "b64abedc7fa4578fc707459190a105efebaa79367e808c39c1f1e0da496b5e56" . + "37712650e6ac16b5126df0db47854a658a0955da00e06c08e27987516edef680" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "04e9950d3c159ec3f4cd7b5015e0ccd474982977a4c56ce0fff1d86e7f0a43a8" . + "04e9950d3c159ec3f4cd7b5015e0ccd474982977a4c56ce0fff1d86e7f0a43a8" . + "fd4cc8799e987c7de57c2d885586631a8b3eee50aca1f57f4dbdcad7adf1cd34" . + "0917dcde71370cd9968cf0bc8a44c4d358698a2fc63f96cd76abdeb552fcb8db" . + "53fc0c7c82c534b4de6bdef76cc47191c00fcc39592ed306188ffe07c8205d61" . + . + "16500fc1a3c1bbb056ef543e240d0bad0ed992283ee05e35e662b7e17c72117b" . + "228b52b66d57941cc04f4e12028887df7f1de7258127342c8b75ed2bec2bb1eb" . + "2641a50bbfa8dca6cb753e4024896381549e62e8e3daf0a887da7ff2e26a302d" . + "9064390b846731d96274808865d7db8db162d874f32f34d268c75affe74858e4" . + "22e7da8a40c2fc8b8693378197161ce811937d7fea87c83376bc63f28c5f9964" . + "a11ce73e5100e744ff89df6f784bf575acfb6e5259e8c72f2a66da7d27cc9e5b" . + "86d70add0c10af89d67d1444d7caf5d6dd965cc3cce614c8c0129fc5937da33b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5be1071d68d89591ba1725a52bdaabccc40b4c560489a4dc9cab065ebf9fbcbc" . + "5be1071d68d89591ba1725a52bdaabccc40b4c560489a4dc9cab065ebf9fbcbc" . + "373f23c8e57bdc0ee16bf5c03953cf41c4904abba604d22134ee97fcc603d645" . + "012c0912330d677df865ae9db8b1f340606a826d202f6e595c794e72c7ed5b66" . + "a160ee8203a30e1d3aab23507b7f0ed7689b852aac6c628751566a30471d40d5" . + . + "37295a0ea39c10e3999b38de25955c2b40376defd24ae63990763043ecdc15dd" . + "9aff4552852105d69436a4b18c614ab6fe591f1b0cf9d9d41be6933e89071ecf" . + "88d90ffebbda29f629e13a66d5436a28348c132c61587f758df7d094f8f7cd62" . + "6ae0f766a3c3488fe4b9c58569078781cec28c635c7f46c294b9f652e7e08612" . + "37295a0ea39c10e3999b38de25955c2b40376defd24ae63990763043ecdc15dd" . + "aec1202354b621f6a4dd21ded9ecd5c07aab712fe53b3cb89130727c23de373c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b2dc181249c13f5de421887804585cf435027571a12badc1a9f16e5d1d5679b8" . + "b2dc181249c13f5de421887804585cf435027571a12badc1a9f16e5d1d5679b8" . + "8b8dfac1978dc3f3fef4c9bcfccc82f295f1c42ed7e6053a1dc511fed0504d6a" . + "20f561f5a6b3aaf446b8c03ffb4f185e35398e80497f3656e384bf9ed254462a" . + "18a88e1402da507b45f41afd799bdf9c3cc71c1e51f0716d299d21c47a7bd976" . + . + "052df15d1ddebef1736cd8294a742d54076b67cbe79aa796065201fdcc8249d8" . + "470ec0a6752460b44e1825d17437b40c7d526ae499e29958a7e37198d3610c64" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "0944a25094d3484acada9099c010201047e325e085fbdba6a43048b17bd4b455" . + "97863a9de6a59fed0c692b9ae301b96b9101a5c55bdbdda2f6b75234ebbcadab" . + "2c5ed0a03b53d8fcd0714e7e26c93298319229670935c1b93b350587bfabe063" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "443d52d9acbd6cda4d009528d829d4cb048083edd7794d6cae8efb7423038a0c" . + "443d52d9acbd6cda4d009528d829d4cb048083edd7794d6cae8efb7423038a0c" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "91a8e28c01989fd762175483dc9efb8766b9185cc18528026c7c2b8699d15f06" . + "6cb86e51df11357746e0e64f74383f76ff73b524295e5ada710fc0e3a558b219" . + . + "e3be3c46ab6231509970e125dc1d0627bc0f3d2fdf4070f2406e2f16aef559fa" . + "7339b1fcf2d465f8fbbdf2bbb21e3b7a7cec03909aec0551821afe53ca0ed2df" . + "37800cc034a54522c2ff27850066e0ac5440998911a026cc1f33e12eb622761a" . + "cf9d3a1c291cb5912a59ab61aeece8ae36cd7a789613cdd48fade814968dd8bd" . + "3d57cd659a2694eece43dcea1daf61e18b516bc9e3ee2b9208c48aac7c4011ed" . + "6ef399826b9b62e096f8a13381a45d152b746bf291a9814a4e4bae757680e11f" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5ae34399d4217fd1517db21c5355ce47112c08a70aa4cdaf601091842c2b88c0" . + "5ae34399d4217fd1517db21c5355ce47112c08a70aa4cdaf601091842c2b88c0" . + "e3d5b1d40ae5a3579a5561ce5f127e14c6598d303a06db516cfc64f29621bdbc" . + "71ecb6bcef2c89d11faa704d32f88b579430da78f814d6ca7c76deefb01f484f" . + "6c949d6c6465178e95e6ff02ca19d4fe7c4866c8b7ddd7f19835563ea76bf657" . + . + "f24e33058ca27d78105489fc2eb1d614b732d1a44ca0fc4f258767768a2c4586" . + "53a1b42fba3858ecb1349f035abf9dae6ec0b282c978eaf67579eeb9d2f3a6d0" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "f2739838ade2092857961d971e114d7a430cca790e8fb5d2447ce1806e92a0d1" . + "f24e33058ca27d78105489fc2eb1d614b732d1a44ca0fc4f258767768a2c4586" . + "903f778c2ddd39837e91b505784f565437d20ab755dcce6cc960136bcb5c902e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad634ef1f7807dd85c08671b541b0d705669841b648e8985780b29db2faa411d" . + "ad634ef1f7807dd85c08671b541b0d705669841b648e8985780b29db2faa411d" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "310646d1eb79704ba0dbea6cb9d358422ab2686d99173fbc7d68f9f248417384" . + "a13789dd1e0a7be30eebcab3e2e2b1b53927a7da627e0be3f283021f2225251e" . + . + "d2707446e116e80dc72d6a68e2c4866c11ac91e59768b35135448bfbcc6e4bd3" . + "bb6d213db8aa4ce385b5639fd076a2d36150572ac59782eb6dbdf7946e84b39d" . + "0f9b376ecfa50999da987789223a2c75ed28365ae539726e08c122355821138a" . + "2b7c38d3d1d5776a220f8d4757476b87e1a630f28d1abe8ac33ec6998514566d" . + "3cd82adcf0404cceeaecb38de3b9fad1961a6d0194c50e18afaeb2ea1607e64d" . + "8a4d6fea8c6e232bf07823ef7e0e0e604ddb53b5d9a6e4f4d47ce304b845f573" . + "c500373fe6942b5f63f69e8a76f719f6ce183be3706df149896b4af6b942306e" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e387f49b20b3ffdeafb6f357e7436d4310c28ccde05282cbf9a089dc6f5c7c30" . + "e387f49b20b3ffdeafb6f357e7436d4310c28ccde05282cbf9a089dc6f5c7c30" . + "3f0444ce075c4102c97597a77375e04973f0ab1c038dd059f80133a1a6718dd3" . + "dde12d3d194d4d4e8c9a413fc71c2331ac49265577f20a1cff4539e903432f5d" . + "589bc8923d4cc5443337aeb52df546d69dc18ece65214af2a04fd5a9762da20b" . + . + . + . + "f59d0ea2e8ec813b4add7a45f4e4fc4fecaa18239ba84fc70f8f2cead37130a8" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "3711df1cc82532cfb316c594ebdc2fa1d3f0b66d4e9c0531b375f71bf6f2f90e" . + "671d14da0b743f44a5e8e0a6e547c116961fea19ab87521273c35de62555909b" . + "ffa333edb9a00aca3ac584c68b5a28ef9178ea217da9d187bd0e253b12eb551f" . + "d67d2e941abf6d85a1043ec6478b6604ff907f26186d679841f90d71b0fb5e65" . + "a5108ddabb5ab4e5213d1d2c20cbe9a8d73b3cab9e1e520baa56aef430f29dec" . + "8998c4505bfb3b9e614d0eac07ea7fdcfa62a99ebe31b8e34509489a6ca7df7a" . + "06024be3089840dc57375f951f67e195b31c37b7e819c63a15dcba31e894aa50" . + "e3a4fdda00037117d53ca99317462ca31051d3dad841a747482c7cab6b9f7bcd" . + "506b63d9bd8dda24f43959945504e2269792f9f7cada9caf977fa7b99355a6fe" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "b714bfb6e3eedb4b7dda5736e798f6e77e93c105f704892dc2ed779b2447e96c" . + . + "4e4f257e03140f5704a81213927f22e5a602cf46d99863a8bbb80ad0732bfb97" . + . + . + "d182a9ef0cfd8c243efa08bbc94bd4fb77661a9ca1f2caea59e973516b90ac31" . + "0d7cb7aec00359f1408acfd7f6bf8d0866c0385929adc42fef6bb5e1a7677158" . + "0429582b039c8d17a03cfb640abe5c48f385a94a090a60987049118f7af4ef0f" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f512711aae176101f2cfcc37eb2ed1202d261191c14992242f095f98d414143e" . + "f37f422927b84efda545145c5277c547f7bb428cfc82018774f138daa8e48404" . + "8ab93b23ec36b19e2eaf3609f83069626ab82f347878569a09908d0a49b27504" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "83b1ddd2cc99b29b5ae1ee275f73e16d787041a1da3cded23e58bfd23db533ef" . + "83b1ddd2cc99b29b5ae1ee275f73e16d787041a1da3cded23e58bfd23db533ef" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "e9db329942a02eedeb0c6702c1744157e32776e5cd3aefa18e1d7569c8db01ec" . + "6b80aeafec883c0fa7d4aefb7be086026da29ec0606fd310b9baecfca377b3f9" . + . + "33f9a30399fa52a1648f4bd30220cddb2f45eda8b95b8908bdd06a5d74a1733f" . + . + "83dc152b6547d7eee055f4e8b6289e76113e0acc61859ee622db001fe500b0c7" . + "2b009ddd330aba78083a281d595bca6dd3ce6cc300930e3715cf798612c7a4f8" . + "b74213e3a638d910155cd46aa280a2460b30401b05ec33fbf9d83d130dbd5141" . + "5ea79f4893d544e5b5140c13153f34b4f218d41e6dcd81adfc8af6dae0407489" . + . + "a4f0f630aa7dc906341d638d96d2e140d1406e85bf3f681bf465b1e55eb267e4" . + "e5bb055cc9f4dd9d31603d6636add235ce5acd72419d59734727aae5d3d5933f" . + "9cf2aa62235885c1016aa11d160267ce812a1579a973d10f793141db0dc180fb" . + "09a7620ac4f73286cd18437ffcff276be74a18ec9ed283fa799986f7664591b8" . + . + . + "9a2453bcf30e525731fa13016b34ae09dd4fbc3f84c6036341588b560bbb8335" . + "093a5971ab6d66ef9e8e7ed14da1db035c3efc1c0d9240ae1627b23bb3e73dd0" . + "187d6eeb01f57002975e5e35f416b2a6c0d7719382b73c2869d6a5f61a0dfc37" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2dafa5e998cbaa4d0b50f1edd4c150b86182c98b642d35d24d298860a93b05dc" . + "e593f5662db7ff660a0a96e3fb1d22a70d8e041ab7eb22957bf2335685264322" . + "c417f1fefe5919ff33ed2252196ec8fc662a669bfd40c16b62db2ebec9d4c107" . + "6977698a0344719682bc80e2a5e42c4d005e69edbedb042862eceefafd0aceae" . + "52d3998b9afdaae0bcf2316f7a015bc731e105086e54a4e4d891214b07dd519d" . + "5d6f4dd53d63f8884fb09a0f98013e2aed9667b03ddd5bc9bdba7bbec128b3c0" . + "b9800ecce97d80ea72a7248a8812c3ee82cf7a079822bb958bcd0b1d538984eb" . + "71d876605c8c6f1f74315f1a5a015b0576f5e4a517aff90c95f63254cf423d34" . + "4c70e57c57d1e831e79085eddacf754626aa02ba24d3e60391b2669cf9bf9ac2" . + "7d3994995f66e79f770f98d860797c220235bb984e3a2b62d01e6510f86c43b2" . + "c734d6080d1d789886f12191530fbd6c38ad69f73634c99accc8beb141516265" . + "707e5d7487281d44e47fa7aa3aea08e2686d2cc5b9f8073437d0870a07cf3061" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "07048e687ebb5cbc975b742a04a1718033ea2c89c6418743ba744d961f00350c" . + "f3d88426a12767eeccd66a56e56d11ee1f3c2188521dd3e0638e77a37eef7cda" . + "a3fc34af46867c90cd068e4ce10c53eb52a2427c606c248dcab8442adc824e1b" . + "13bae16d2575215f76703c1029c5eeac17abd4a6c5a9a3574bd559c8f62736f0" . + "33e0b97afe0228c31397d94d9d89cd5ead63192a7c01274b98ff1064f044d8b7" . + "4d30afc599d22214ab09fd77df9a97bafffda964fdd9b400f062d872b9c6ef41" . + "eaa005a565dd2f0bed4bb10673884b80d8299f3e57d66c3b4e17cd90e2dca20e" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "add09dea9c58e1a3c72872ef1c72a3eddf6ea19dd911cd386612c854f44a7e84" . + "f9baf8f18a50880c479fae65f935f95782a82e8adc5a2b7f1bd50f6d20b13207" . + "6d857d6a840b50221c15320740792e03a12280fdf69c40312b4f49ff39b5a0d8" . + "99cf43c144c9485662a202059d41a1d1756b2ab61b1b38501c612a830f529947" . + "add09dea9c58e1a3c72872ef1c72a3eddf6ea19dd911cd386612c854f44a7e84" . + "c731bb4cfe9fd498405a54bfe10aa553cb66eafdec25f29bd466f4360bb84849" . + "ffbbc90b594de234e7da6edcd140706d807640c3e660827756b00d4f3dbca6cc" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be34fa2fcea23979ede9254cd08b6e7dad2f77f40f90d781b7b18c3fe9b8675d" . + "afc132a80b938eddd959c6ba7290337c6461b53d965c0a2de954ada461ca1279" . + "d49b79af0bff7530ecd52beb761205b86d5aadf10eb8b0ad154d5a4c80edd4b7" . + "7e51d279db7171f2ad1392d0b3c281bcc22a51f52e286d1d479abe66c93a4b62" . + "e87fa9098f4b1ebe506df4a88478f056a3e1e736dde6a6a2da2d02ce7d7faa40" . + "ccb52b53cc29ab14cd2636d1ce5a90531333084e7e4ada4239904af565b70a2e" . + "8c51309d27657b710582a805847a70183e64ab9f781aacc0b2160f8440aa0d5c" . + "8a17454333c466cb65bdf81a07cd56ea4e60b94b5086290f7f86ef527cfac0d8" . + "16358799d21bdf9aafb47a4749903b89e8dac132d47f3ef42a7fffec028f8b4b" . + "8135bab747e5d3b63de017215e33296d2f3514a19fe1ffb29bf469a2f116d880" . + "9d5db80f839a838276ae7c1fada386d8c43ec1421391787ea7ae03ec738b4e33" . + "5d1b1ccd2d54f61e83bd596aea0b0fb1012e1d38a5afd387335f3c4cd5ef5286" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "5f7f20083a85c05ae837527b3723fd1e9734b4747c3955458270dafbaac7bbd5" . + "47f5a2930c860dcf43965bd76864b6d728d7cecd1d782a20ccb2de4c143774ac" . + "4a3ca4fb640beb8ecbc239fd07a6e01df96b1a8dd56a98b95b2b0c13eaa2847a" . + "fe738f739dbfa2e4bc51e53c82a63ff7471d6f928b6029954b43648aa5d20d99" . + "de9ccb1ba31f7df0dfe9b0e263c158155fa60428f0d187135c72d5d3f865b9dd" . + "2d6b6fe48c4ec60c64c4ac2bc1d9499b50270e760c94cdd0fb2ba6fcf2c1d261" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "5ed550180204cf32365a771f870e22f169984bc068b894f27a52ffea18b1e768" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "563398d494502381b23cc7d267804907a8ed4e9f29322fd7c0c65d0cfc8002ca" . + "893dede7ab3f43eeb08a6bc1665f692e330f614897f7bdcc682ddcfab42b97ba" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + . + . + . + . + . + . + . + . + . + . + . + . + "563398d494502381b23cc7d267804907a8ed4e9f29322fd7c0c65d0cfc8002ca" . + "5b531d9c8093c4bbcaa3e32bc14aa23d171efb05ccea0e7d697a8cfb0c68a6a7" . + "54814cca62046c4a31d5b9763dadbc69657cb9e39ca16d76ff4beecfdbb79fab" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a22b84a0ea936349f06671c7e68185fff61f5f6feae816d62bc59cf9f347a1c9" . + "72c336017a6f2fa7a512019e06fd3827461d377cf77a76a6cbba9e0501f76027" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "916c03726dc5b7e7747c1e726b8e725dcda6e153a9e740c232a998acd6352d7f" . + "274117e64512fffc98c3ad11dc7ff4f6e325f6d82b5a4fe3fbef2125282cdaed" . + "c23d972f082aea68fbbb9a7157e4e32f39ea73adcaaa9645e3c108ec3d9e78d1" . + "6f79a2bb8c0dc42266eac285aacdf40233174e76d939636d37295327f2c9a51e" . + "25ff9cf4322e8966a090496caa52cb73d031d80f89230bc36917a4d49c06127b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "0192910bf0f465187ceb2ae6af25dc7779cd7ed354ef4ba582772d4975e14b87" . + "cd26c3b757a7a7469e7c7277159b562c70eb8539684bbf12bf4e7edd02c8fc6c" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "ebd5566441c5c7826a970bc86cb89375a1ccff8ed54f3915276d0f2a6375dd7d" . + "7973d1da2b2e90b5d5c34ad45d47c05f3b39e80f46c592583965731ff11a67ea" . + "316798040dd8b2561595b837d68830e9bd81fcb30cfe0a49ef80cf6d039aebaa" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + . + . + . + . + . + . + "ecc95c50524eb3f118ec179845abcf1c94a52a6deabc54578b85a796a5feec63" . + "767cae6d1bb334809ee0ba44538e64b31776fa5e81dfe0d7f36a28faf383576c" . + "38aced240343f4d84d19f02f694938384f4d3ced8569ae726cea1424bee976d5" . + "d918e21e6845359780b08a47926dff2cd90a8b0622178681b9886e1f6d4c342b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "83471225b004fa121d74ed83ce81402367cdf6502fd8c2ae195dc684e3f986e3" . + "83471225b004fa121d74ed83ce81402367cdf6502fd8c2ae195dc684e3f986e3" . + "5013e0453185a74d4246fcbe366b5535b190da2f9cbe5dae51e54a5bf0955f30" . + "24a4df583465f8f26360ffba8220ae2cf68a42c32a93a57db866c80e09c00586" . + "928dedd070eadb627f1183339a685fe169024d06d13b65de505f8613604b70b7" . + "31f4b508ddf6863325fc813294dc9c4ed72d920a808e7147b3d51246100445ba" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "9b9411f439d7634734a2f1bf472fe180ae84b3b2322d366157fdb5e8eb7656a0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "92c0b75a69696ba22fde8dfaf18d9a2c338dcdce8bb0560cb4191f1491f5cbf4" . + "931e1124e1f0c7c822857290fdff95d18425244f9cb74c70bb012416371f72f8" . + "7a4161493cbe1f9f9c7fab1c8a21efc0f1a6f6730382c0a253019e4b7b03a8dd" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + "8f710ae40926f405cea30f27f2bcecae07b914acfde643a37e8ef15c542a28bb" . + "25afa58c5b4409cf6f4c0bc7517770bb3e115f3c267eda68e12a0933f3af1dfc" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0dc40f4ff24ba9255bc21a0d75b297c5015a40e86b77ca1e2ccd5fd053ac19f1" . + "0dc40f4ff24ba9255bc21a0d75b297c5015a40e86b77ca1e2ccd5fd053ac19f1" . + "a9630fb437046faf1d2c807693fc8cedf68dc65f8bf14936451b4e6007df7c9c" . + "56b40da4cd27c304f50d6670ed15c5e5dcd44943e6a942ac697a8db8acd6dd7f" . + "ae30b4f61fb045d6423122d81ea3e3bb134dfbe323fdc8b561e603cac99a86eb" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "1a395e94ee1b968a53b8b98fa0a77e140b94e26721dd4a699f19a26ec17ecd13" . + "69527e38ce97813844395c09c95d82b3d32ce4c73a9e2bbdb22c71504f178152" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "0700e1ab415f4feaee32007a7f6098ba48691f1bab848e7ac9d4a78eafdd8d56" . + "dccc98a79775569f6a9fcf0564c2dc83e04b43af58bf8fb4561e10d76445333d" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "c14261f606fc688af7d7eaa3a5839115d4a98487b82f2667bb685e7a5fd62cb4" . + "98d5aa7b40affcf3b5716f6f03a4daa285ff67c0a3b74bb6dd7c9558de50fcb0" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "efef50f8f6931f1830d23cdac51a9f8f61cbddf2b121d2b3293eb138cf2016ec" . + "82f4287c2478ccc072fc759950ce7c3ffde510bf5959aad00a2146166a935d9f" . + "d67418aff020c5551f2320461ad267daba498e891f8c93598242d2b2267a5d55" . + "4357d2d2e17217330f13ae1c656b98ef6d06b913fad70a2d03e8c6d52a860d6c" . + "6761cc6146a2047329f2f08426300aabc185cd14797f035d4012a4ec35b8a247" . + "b7b5330cda081721d4e58ae6091ee64e4df61fd7e3a4d3d665c940b62c980ecd" . + "49cc67aa0ec25d6e322b146532ae9a3cfddbdf1bcea90770db125ae1985aa126" . + "cc94638a0aacb24dcf997b91172597c069ee177f8e777dafef4946f2e5c9ea65" . + "700847ab6c52cbf3848fd9ce82e99d0bf5c80c4f7d5013b32dbdc1bc970cb099" . + "eba5cb096eaa397705379dd64941b415d24ce83cc757bc5a53f9ec17bd9d8364" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "4378200a9717c0aedf2026f3c3c61af017e1fe5cf059a156cfad6af4407ce778" . + "879960b98603637f382575b17b02dbb98196a7017d44b886eb8d38681f4f26fe" . + "45d2743130718482ce5327b065cd1388d15186c46eebd0e769ac8d1998b9a510" . + "c50cbae1f7b857ecc88983f76e7b25ecaca7ed9c5d5b4950149900df94b9c28e" . + "bd196cb80f9fb67ce4a7153323f2cf19dcd2779e49a6399cf1bc01f6c0b63830" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "49bea2362d52c837c02c49dc9513af2816982cd4f20d1d78e4824e9b3b90a7ae" . + "6b0a1f240e4de71f4ec03450841a68aa296e20aa178ad9b6b7a4e30b68d468a3" . + "9a4177cbb00fc4828d83313de2f1f41fb4a164984ca6a4593605022eb9313dae" . + "9149ce811fb29cc68ffca3bc08efffb0ebeb47f010395b7abeaa90cf878d22d0" . + "c59b0b0781e68701a11b18e5435e03610762e631fd5d19ae5e6f2fa069d0e641" . + "c5846674ca07d958f3ecfeb9aaa0ec138d6e40ac102f8985121130a27c7555e8" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1a408eb3c12a218059b96f66a4daa0cc973d535099a6c60932da9199c81aa6f2" . + "5b22fcc119b98db291f87f41c3d89e15dbab82f97dd32a32fc792a47a0808fe8" . + "f9694aa0175a5e24564d7c9bb716e44c98fd8be0263c2558f44f4b8eb2132a0f" . + "c4b8693364c3f5a41cf673247703e24a3503c1359e7e5974b7466bb51a425dec" . + "9058a17380e4e712073995c2ba8c664727e00f1804561d70fc9b47d90f96dc8d" . + "017478d1ea50633c3ddf9fbf38f16a0b003dcb45223434a4be11824cb3621755" . + "7512553260de527f1977e288285a730e4fd705b818d4963e4f9b0a3310910407" . + "dcf4c5a7a56e81fbbbd2466e28edc713186cb5ec43094b92d5530bdaa008e5f0" . + "e726306e1e74e77070925c556712a31da633b18de8ba48b6a31a1e9564568ada" . + "db94eabfcdb3937cd18c70658ac110383cf890c684873808ee712264d12ac701" . + "47a7221ac0181f7d63efdff358185f0b048790427795fce505fdbc730b3b8a7d" . + "48b4376f6db975a4e32dc32e601172fc183a46b666f7dca980865d74371ffde0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "eccc59db5bdbcf9aa16816daccc8e68f750db0379e8adb32498cf14f09ac123f" . + "59393d39792d361ab6262e2b7e1ad1c42d856319af02ee9612819b49854dc2b6" . + "814cc04844a0b89986472f0aa10d9328060da918efa1854448acf1cea97c05e9" . + "464b94d65a3485b27cb98bfc4d0fdfd613bfd542b523bb37beea6eb646e97816" . + "3ebf1a90a39c5b582be8355aab9d79134a177d85b0b0a78a6eadbc7244beeeb4" . + "5c60975d5b0f40af6c9c33f73837bd98f96db8365eeb3df36ab7b2c57e71013c" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "98705aced922384642535981ea7ec1f06ce2689092525dfb8743aa74d96e5e92" . + "e4985af315eec76690f2de585da367bff06acc38925c3d90b03a51483b58f863" . + "4cf6b5480f3a772a9d68682d10a367f1d5aa797ecbf0d3cc1df210585c1907c8" . + "aafb1dfe342795d8bf33b384faad7c2043129ecfcc422cb3c269ad5fcaec13d4" . + . + . + . + . + "453b57fa0cea02ba4f3308e6d1c4d36c5abd9c98c68e68ab8844450055da45f7" . + "a521819d30373ee1f724772878a1799c4381c12deb8af4c1733f182e046a8932" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a91eea8cebf13c0c7bfbae4804890dbc73f86c92d8d7f6d9fe98a5e8b846c2d8" . + "a91eea8cebf13c0c7bfbae4804890dbc73f86c92d8d7f6d9fe98a5e8b846c2d8" . + "455b1040284c9ec79e8e7b6c794908254b7050544def091b53d7b0242ddc0b78" . + "056112b8f9d75a66c3bad2d1bcf173fa2e3927116bfde1ec4512d87b62264990" . + "7531a95bf9f20a84b939cc64efd7a4f3dc4dfe89777724d7bcdafbd52f20f259" . + "8a97fabbf3df53bbbf19a5deb6318ab188da2a7c2dc166b451859580f4e7bd6b" . + "44cf6b521f87a710cd993495258f1f0dab4d8af67b4204f5c3a9778cc8a0d46a" . + "be233e587cfc4ccaf87da8eedc08dc391ed85a64cb092f6616d17102fdca2271" . + "0fc8dbed9388caa115e894c93410865cefbbc7a11ec2afb32f4971b005a29c8d" . + "d01f9897963c4094ad97e89f0cb23825b88f8779d4762387d4d64adf47d6a378" . + "d2ed26b6c86230a7b31bb876172e8e7d136b8ab6db4dc1c0dc78aea4129806bb" . + "58864264b2299f852a029d4f9463d69237cd4b626ae8ac75ea3286bfe94b7c35" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "cd25321611ca4ef465a5f03332c84d45cf334df8bda3583aa93c6058ed8d69fc" . + "18f7b8e3a5e453cd3ce5d6f51dd51443002b1955198b2b2d9f44790dbdb610ed" . + "ebddde4b29451fe5fefd01e21c0503343afdf70583fa2b1aa7e9b3cedb680ac5" . + "e117694ddaaeb89bf8681fbfcd48fdd16cb0c9751b3f05876487b5493c69e7df" . + "b1c6bc4f38e6b0d26b843db4a0d3b7565f5d48603f64d476d8414332e356d957" . + "46f9ea0a7ef4df79ad16020d9804318b63bf284efb8e1889ef262b1f5ae67f59" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "9e10c50cec1b32b95f31a1d3f1beb1ad4047c0cd24066ab73a2952092eb3e68d" . + "a9e22588e272b34b469b18e8485bfc874b68748b26a8e44c165eb49070355e03" . + "6d8172e0886bf9c52c5347ce7447bd4c69a6f1a7ae31f8165b061fa282b945c0" . + "dd8d3e38be817bfc9386543b369045dd88b054c3bdf32ee4423ad5d80236d762" . + . + . + . + . + . + . + "4ef6dc9bec9826e01e88999445bafc3463c4e3ca8ac386837cbaf19ad7133d0a" . + "8c68ebcdab0233681a4eb17636e2bcb9c316c9cc9eff9efe806bc9913385ad89" . + "03d991442d36c8970dd4fc3e26a9eb8fa07ebcaa8909be7944c61e53694a6235" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ea28349efc64aa7044aeddc8a61818ad3ec87736b4fbf996681092f8d93d7074" . + "f105b6bcd2aa3dc25eac2fdf95dba8d54ba594a5dbf5e840c0d3d49028996bdd" . + "90e066af0d50ee82fe1820f171c984fb9c324d4f0b10b4b1180c7e8cd5ff50dd" . + "25a26cbbeade5aaece15fb29027011514aea61735531d9d4030942e7af795370" . + "a99e16a22082a4c0c98379e285b594ae598ed55ab549abccb9180d6396f573e1" . + "e2c9fb6bd777c8f4ee9765fd31885bf8bc32819da19ebf765f798ac618ebc069" . + "466c45f00007c8de96a7fa5087667d389138d354b5d8d9f97f17f30770c4beb4" . + "f1e4382cd71ec590618be1825c92810a4a3590297fc2f21f3eda37f583051346" . + "4366ae96c9b126fb3036d280db0f3e0d62f9f547c00425d463cf00e341dd6bb1" . + "a6203af4390447bcd9b846e09a3a9efbc2a8acb0aca0fab10f5a5f9687e6f57a" . + "4dc6b8700fc3007e2010d39bf06a350cb03cd4f3a6278df4d87a002d57683bc3" . + "514bfd4d51d6d099ebf52fa1dfd7f83aa80bcce8ef2e697f4cb0a28cca249fad" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "f66a7234a4f2f74a9ca0b0d5dec64178bf63a7b9e420434822b6ada1188450b2" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "1c735216a81ed17f800b313478caf9f560187a44e08fa7e238b38755cc087048" . + "6f79a2bb8c0dc42266eac285aacdf40233174e76d939636d37295327f2c9a51e" . + "670591095d59ac9438e60302e248e8a9909de631ad06be4a9f2bd122d9c11f3b" . + "0a6c0e01a42df9c13ed0e6db5ec438962264f289279ee2f9aad08fedbbd15a96" . + "6a6881d00b5102c73dc1d7e6c183b2c5beadc4396b25c2c05c4452dd9bff2137" . + "fcd7e2c1a18cc6319ebd73dd6cb1e57aa8e5040000521d9c5f6c0e6e974fcd43" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "5b90f89cef0fb4a424033255c78b3ef5b3ac4410ee423784362e0fbaf6639eaf" . + "e8621630579e9c4c5c6fa205fbd78f324a5963fe7bf0b464c7bc1a1bda6b30a0" . + "f6eac97c000903b0b70b0891eb514bcd0880bb24f138d1a26d5a53b8001ee1c7" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + . + "0c60ceb183dedd9e9018f26a0ee2e6e9b9921c7d8f76b95ef88c627b8a07e599" . + "1e220c519ea379a698f54783f5219bedd372965503457b6ca7be486c79b0811c" . + "49797b6cf956ba1fddd7fad8afc2107a8908f5b0da497134e437136abb09d1f3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4c9a4ab87ccba70eb9503f49ef121f400863f886bc2741edcb142025c467d832" . + "4c9a4ab87ccba70eb9503f49ef121f400863f886bc2741edcb142025c467d832" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "0fc3bd9e91a0fdb39d0b1e2579774a7bffa8e94c8813bf5111b659d7c5ef28f9" . + "bb6d68e8e97a6e7808d06b6d69b8af8fea780d2d1087810b428004bf6a71d715" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "3583744951e0441d41217382fc255ecf9a3695648ac00338dc05ebf68a4ac4b1" . + "bd0dafa57b6b4b946db57ee43801da042b6b68b935452c68d32cf60f730eb31c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "a09a0ca8acb2a40dc0d26a9f666cbb69ad3c2e0c781dfe2d9fa5159a3018ade5" . + "4e2e8a14c30054b7b1c53e327dacc8304ad7a3610f5671ca5ec62a4e3c789e3c" . + "4ac225a16dd52ce886a964338bbd400fa31ffa6455e9995fa3f3f16c7ddc576f" . + "d973683a7d2a3c1a0e1684ee8d30774fb88242d7a1a982b168618a1afd0e9afe" . + . + . + "887b2a4bbb9e8bcc03aeb6e97c5e9649c7da013f8bf8856be6558757ca0b6c93" . + "d0f94d23d853032fe9836aa73fd1e6deb65621da6bdfa5a4127965dc500cca94" . + "a4b9238fb4ba64c9c0fd794499f21102f8645c811cdd3cd2deefbaf5cace3b65" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "09173be8092e67ba92a8c8be1119f26a945f84667afb8b13bb2825fab6f83fae" . + "407c9bf4f5598beba090f7ea36ee57210bba3297645845728bf222783e215d8c" . + "905340599bf53cd5b99e91a0dc3e9f4463d7705b18e342967ae720152f5c66c3" . + "c746e9a58707e0cd030ca7ddaa0d0de01d45bff69f80b8f174081bbc7d2d641c" . + "bacdd54d2679d8f231eec4cd0ecbf6a96a6f3166b57abeb16805396d06f88216" . + "28130bd11b6ea78a3f79e15ea732be1ebd942f9697c21d7945e592d7ec0a2684" . + "f87bb7319e9bdaaf08f89cc8fc2385273b3f995cdf9217a9bb62c2aa47b4a28f" . + "d6c7787d91a079651a8645d34c74b3848f67b6fcb42a6a2794e9bf2d08bcbffb" . + "466c45f00007c8de96a7fa5087667d389138d354b5d8d9f97f17f30770c4beb4" . + "4dd348d9793702a80b60afddbca899a658aab9f41b95f8a88213219c7ae11243" . + "1ce5753ceb97a741a4c8abc3b8c60db2bfbf209044d26fcae4d5e3fcf13b2ac2" . + "cd01a967e5e70a46da7aa485819be4f587ef00bb4ae7e83137b4ecb5d25859ec" . + "f4daa27c255c175c53594e276bc3e9020d99e7992194729be6ec457ebd4759da" . + "3f57290135a53e8cdb616451746b31919b4fc079f9c98a540cc0191f7c2cf0e6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "5a35e423c4da0aecd9dc914f7a22e8a75a22d6ece98474f9505c57a7a926e23f" . + "0c5b81f14f0924e62f57ac0fe26a28def916a9df52ccf15982fb73e0c04d4b6f" . + "9215fe74d32971c3f89b99a35421b843c18ebfa7c34a58275856acddef78d05e" . + "6b6dfae3363f400c4a9125578d24d656984598b1e858a37553a843961b5783a6" . + "2ff93b3a82153e13715a061458eb65cf93e4807814ac8a05118a6759b61c2e05" . + "6497f4d9abf4f1cd9ae24831e3b9e78126d4fbe83eb89cdff1358f4385129ea6" . + "1c10e73ffa52764ecd978f62a78439532e5f46deb161fa2cb5e86b75dd42db06" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "8f4af206c2b26c429aa377fdafdae6a73cfb30b68c8b5d5573e1f1daad8c59b0" . + "0f05ea87b31d8912fd047644ba202f7343261b43393260a08dc922793d2e1324" . + "5d7788435fa39dfe792486744ee38a065c6a819ca87063e0a9d589e460c368be" . + "68b368a01fe62c7849d2c018346a6c37a7e3e3557d6b9f587444fe663c34f895" . + "eda9bf0b893dd3d4b161dbbabfc78831832449b3a4f9af336906e73d8b9edc91" . + "4aaeaebe2337daa2d4991a7c538fbc0c724ba83ca1c82979ba1803404728abcd" . + "6c9b82d9baff48e26044f764a59cf3a054b6528fe6dd6c1dae491903e9344f5a" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6143fbccb88126301dce183d207eeb9a1d26dfe86a381fc4c8daaaaad7d10897" . + "d4353d97f88ffb29495482aa6b184d13cf30144d8ae1ff85fd36b04d358b6dc0" . + "11d562177b0c9c82d4ab906bceee37fcf7c3d810bc94694d68f54ec6d48db856" . + "9b7b33811a6673c0c1033d215276b22c2f08912fedacca87a96c0d652680525f" . + "9ccca4dd9440dd43f918f27b0cf16da757290dfa2fcdc442f02c9b543f86cb9b" . + "96193108da12ef7c7dae13fc60bc9cdb20d1ff3b465643e98ac9d064088d0f38" . + "29c7572428e2a90f4caf0a1c1ec865423c847e0a9a7652a8412cc9948ea41cb5" . + "e8addb4e3e16d601a2639da81d1518b70dcc4205cf0bc646be718928e06158ca" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "7c80e2f9cad452325e2e865b2f919dbfcca1432a5745df343446aa4c910ce9ec" . + "e89a4ff58a09911dadaf95f19c0eaf0168ab11e330ecbb81ce851eb7b5a97bad" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "8f520d30502987f6d4e158ec43c4a455e62ea67781d9970ae0b5a51ec4d1df42" . + "cac70f062b1bc25b56541184cb89d9b5eb56dbaca7a673ab4a22161bb9757dfa" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "31e0758b814864188ac48056b5837f18bbadff542dd944a0dc3c166c9e5af46c" . + "53b01ed79b722ad6fa6b969a5320da789e70d6e43a2bd07175741544a5bdda18" . + "a6aca4d0a3a419341d7c1dc8526039b9de5affcb2ecf257a337b91e593327198" . + "093246560921316712ccf52962427f4c07c99826efc2cc228c245a9b7562584b" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "55389b7e08c5544cf51f3c44dbd24e63c2ea55faa9bbedd84d4327358240a435" . + "a0d3739c0aa6aec974579d75ff96e33b0b33bc4e4e2c546e40d438af8c5f79ec" . + "9adcf21b6664bddce15eb6e4c1d69020f0b48099f4421f24df3cd7c7e5f5da0a" . + "5d4823b2d5a105e52197dc4f5bbb15506221ef220c447acbfd108c64c7f5f1bd" . + "aa54acc74a3dc901cfe86f725965b940937272c68607a3dccd753d320d923b30" . + "f8c12b914548ea9248c157fe2c228c81870f22f90d852f06864e7c7a3691a9ee" . + "d5cc13571dc88766007050bfdd5c974d87d4ba9c1aa6b814efdb135e0cb43297" . + "90137e5b78921536e9d3fa0f84b831bd861fdd4ad1e53de3e4e93a73bf426b87" . + "4198d0672e6e67049e11ec000b9185b04005beba95b4cb1a52cb4009668470df" . + "a9dfc1b17a00310b52ebdf2c3dc0baba7f508a6bee1f1cea1bdcd1f58c224285" . + "0156d49a0c94460781e77e8f63d3be9b2ecf4c25f396f8b785c06f8925b70a0e" . + "42339e786240a735d1b2e438ad830e4262b6f9b0e9a83443a8e4664b3a3c85ca" . + "5f2b905633ddf3844d9b638e2a736883e05206c627c8d3e9aeafb9e93c86fb1a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "33cecd3d52ac4aae431e2440ba9bb8614ff814e2447fd538741ff27feef82a6e" . + "f8a01d79b4270b26cf725daf0888fd5ece58abf64eee9ad6ec7aa2ad5592b5ed" . + "34f90b1a3607e7c2f2184fdcc209a72c2432e34236fe2415b4049d342367b81e" . + "de9ccb1ba31f7df0dfe9b0e263c158155fa60428f0d187135c72d5d3f865b9dd" . + "db94eabfcdb3937cd18c70658ac110383cf890c684873808ee712264d12ac701" . + "8a9aa5f3f8611622dedf74eda0cc1afcea6aaf996d626fbc01a71393d023311e" . + "2df2eb571ea9b3d441a1b7c12dbd551c6dbd4c63085a7d550959a1df2622e444" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "461736991d114c487d06a0e52c13343d8a5ccf043261886a3f91284e3e34489c" . + "f04481ed1bea741bd5c473afdc547d3ebc78a2b16ba518a7405a44300bdb1016" . + "8eeabf6dca13412bab051f2bdc465197809e9917f0a85fe3da039c15e9536ff3" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + . + . + "e7f34889e1d8ab6d33e224044b7a5436b4346e9bb8d76fdd950326f9431c8411" . + "779920812d0d8cd10afcd83b36f32eaac52a73f4746f10498fd495273c1c6e5d" . + "e64299fdb6732a7f1267b161cd3defd6debc7b00f3a3f1965148c3649d0e92f4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc99d8678239a90628efe88ee2a1dc80873a6f2d93c488ad5d51b30c9b4029c9" . + "0c45604b0d06d352822bbe53befcfcdb020416ddff9ac46d440618cc20338dd4" . + "a875e1b88ee0aa25214994ec5f30b915221d44a5c4dd6fb9be018cf05978aaff" . + "2534e51a8342d1404a368b18ae04b7bf2518bac61954028169ce5bd8d84755e9" . + "2ed014529f6b5fd47c7a1049bc86dc9cbac8a1bda7e348a1a615c4311310819d" . + "8975c0b3aef0c8ece51d57b0ab00d9298e3032a57a13248c84a99590145105c5" . + "d79995bb6b2552587e5d200c5c837025106611a0231009cbfd431bcf80452446" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "d2c554cede98e7b8718d1b8afdb6465507594e883e493d93bf869e31afd1c2a1" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "e7791fc5e16ebc69144be73782692da468973d009bcfcb8da0d7e2f76782a7e1" . + "e715c563b4799b6cbcda12661bf1b59dca5a2bdd90e0258cb88f0024c60d1235" . + "4310c342407b96242ea3f3478ad55f0b6f071a58d2d7bc90c00c102452be9dad" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + . + . + . + . + . + . + . + . + . + "67834a9bc59fe8ae701166f7f9637390f93a2c26ea90aee191e5da2205814599" . + "20ad19c9a0e3707168458836c50f37f6a4d22e0652044888ac45a1de0c082591" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "64a32bc3bc2ba46e9d4dc4fad5ca5cd51eda75011451278430ba3e2834071a68" . + "64a32bc3bc2ba46e9d4dc4fad5ca5cd51eda75011451278430ba3e2834071a68" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "acd45c155edea752f28885b0e469325ec5ed5d7001a4a624e8bfc23963ce910a" . + "7ab4b36f32f39f4b3bbf4aaeadf9c72670b5edb63f870be43212ccc39fa2d292" . + . + "4ca70366741e72e550aabf2c579c591de99a166ec4b3be9ec824276adb7c98b0" . + "ac03145bff51426e8f90b4a6a99c2e906c451414eae04f876b3f435ab61896a8" . + "20fe5012bb3730d4fcece058bf9723efbc6c6146bbf4caaadb3273bd1b130109" . + "6f69ca8735970133a3753aa18d7e0ade36922866cceec6cce04234dce7b7b095" . + . + . + "57b0fe8a2f41c3637ff6ef8f072c5c2560c6d812af296c9fcdeabb45772a4ef3" . + "ec8f79f1932dc74652a2959a40145ef6b4ce717f3fdec203a53b40fbac21fe92" . + "7ea53ecc0cbff7f1738b140db03f3b0785d5c49efe1845a2d6c267ce73ffd7c3" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "54f10a484c60428663b39a589b28df59955012ac2a4aaac10aaa142c548b4de1" . + "66306b78c2fc20207171439da9d11a01e507a04611e8ed1842b7667ed960fddb" . + "bbaf699987824c322fe65c8d6ed4ca0c3829751beb4df4744843840df92fa76a" . + "c114f19b0c9d3a881ade21edc0022c0371c7fa0aa7a457e1f36a6971209bff7a" . + "18d604c80302dcaf0127b40d05eb570dfab5f200f84109451a45066b16e58825" . + . + "65a1db56d6b52b3091944acf1a73fafa4e47cc0b6cb1bd738defbb26314869ed" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "ca8f7d0adf9d18f592ee2cc92f8086b2a6c47ac576575d50485acc8ba183e6e5" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + . + . + "12f510497704b87882ad3e5f57850b50db30656a613bc88f21921163163ef4a7" . + "e65fcbc07fb29712bbb02d2fc7f9e39dcb2ab663a833285d6b65cf54af9b8848" . + "e270324429baa567a95d283c0555a1ffc2a269cf99976920d058f33d4d263925" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da22af09565f0fc65ba330da60969efaffdc530a450dc5c4509637afa7cdb480" . + "eb140c0998a84d527c3552c2ff3438f10187b7b2dbdbced2c31672a305f87d9e" . + "0d29e3139f834e88034bc89e7897ee73c88e3148304a1f1d3fad9a0ae83877d2" . + "0fc5d2563839b65c14e83e8c087de035c6ed8d5b33e52d74fe3151a19a5a97cd" . + "74ab0ad8a7ebfd0cca9251301a2e32b40c698ff507e7df20cd9f901c9f9a8df4" . + "eec54c306712a430ab8a9b06fa2a4c7211b5e162f8f81997d2baeb41bde963f0" . + "65741d51a3915e4e9807d27d8d025941ce2ab036fd6804d39e7dc10021b0249a" . + "28e6bfe33f60ffa6826cb93a9b35c7310e5b1e771d564c7dc3ac348f9446600d" . + "5e6ef06cd77648158f26324f4f2191e27dd16743fd5b17eee1c0051b918b524a" . + "58d5ea4dd0bf5c59d1f9aea15a7a92f58c3d47c246632e3bacb287c3aa3d2928" . + "a2c3a163611975ba8c20b7056ed681bd8ab28e65668bf9237650dbdb2761ee64" . + "817bfcc24c2e1766d060f2ee0f64cdc7b33e0e902b31491936d2d9e258636199" . + "9939433b6462b6d12451927966ebea8a947bc8049d43442c9ad06e341b06cd11" . + "d6d789b81e8958c434b169a1bfb85a50647aa14a80e58095c358d0677d6fa6c5" . + "b16f0e10e978bf172eea0696127a2796c5e296ff3674e77e8605b35850c2924f" . + "f925de182808361915a64c80c276c31e183d2af7e1499e45309277e186a5c398" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "e6107a37915c94d86aa1dfeb481c7e2192d481a021aea734e95287575f50e117" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "f9ac7385683b4f21dc21de6fb61504221c87ec6078f71179833c4fd4e2e9773d" . + "3cb649ff0affddd28f8712afac09b7f02ff8186baffcc598c259ab066d164462" . + "359a73245fd5efe8abf0778f74c88e3b30bd021ee98c79f6df1a4da1619c188a" . + "8f9851496f4049af5d6f0c90d1f4713e0ae7ccd0b1b443f56d1ef7e8c76adbd9" . + "ca31a5cb7bf143834f7313cbee8946d768fa26a3c8ec89b67a313295e4f3754b" . + "5655bec93f43f879c9387592332e9068c1d25e34e9b95af58663f730eb1d8200" . + "19d2d14c9251ab3c38a21ab7bcdd58e08e74431b6544d207954fa95be9a2fd93" . + "b1f9392fddf4d43b0453839041a246e9a9fae53bdebe5a180852aa48557c558f" . + "b424246489e14f49d466f9ecc58b707aee133d23f08eb349501c24fdc3eeacc3" . + "81c1ff72565c7ba955cf8b2ce85fec76c27057dfa4aa67d1462d30a1551510db" . + "742059262f6126714dbbdf5589008204993da0351135817bae7662eaa37f633b" . + "45d2743130718482ce5327b065cd1388d15186c46eebd0e769ac8d1998b9a510" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "a3cf142beca697883aabd5218f862e84a6df73131d5305af7707bcae487d2de8" . + "25a3f17f8f0f0efe57e1a3af65b71a782a8c042974b217d78e21ea265b30c626" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + . + "44244f1b5ba0a787bd765363420c38f6381185792a63c4703b20b6d2c62f2ce3" . + "6d0e79be1893afe6facbcd2182c262258bdd0dfb9982e3a728ce68a215579812" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "46207ada031a9e21d84986a1aeceaa118138838a6b3f720484cc6c00b069604a" . + "46207ada031a9e21d84986a1aeceaa118138838a6b3f720484cc6c00b069604a" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "6ebe30dd30c3b5615f0ef39f55b0825dab2b7f7542900f97dc8927730ac0459b" . + "3c76bc490aecf77d961eae31eb39e2793de6825a8960ca240ac745790f55cbb5" . + . + "b291395fc7868e5765763a6aa7e87b45580a6c088f011160953d332c3079cd4a" . + "ff42d3c821003e815ca43e2b01c3487735152defdcaf1fc94fb3dacdad3cb5a5" . + "ac5c36c40b4add107d5b7bba4a430072589bd381aabb3551af7088d824921d1c" . + "4fc612728b82ad3b6bf58c6c5e39accbf5df469bbe37eb699a768e6cde034a3b" . + . + . + . + . + "7c41dedd7e88285df62e0eaa44bbc1c30156554f9ab22c230b9a9d1a6218d12d" . + "9aa7b25a2d93c538dbce29773299447c6cb4d14a193bdc325c529f1198316457" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7202e4cae5113de04276f85e62307579eae1b84d67c24faf0ec46896be543603" . + "776044dacb9ccb88c699677446492c7b6c69c4a461e3e1681633d5550414582e" . + "0bd055bc730a4c9e0424bc63d1baaf35d75cdab4d01181830e38327cbdf8c28a" . + "c178fd793f27d152a04ad7bf651dd2e38d85818a47d431e9279c17590eeeb6cb" . + "cc63940a8bf0978d58ec406e8cdb43a3a213c9117a193162d3ab16e3c6eec268" . + "ddf08399bc178f19002360fc13f35c66457f468b9b9b84e9482ec369bc9b2244" . + "ccc551b02970003625fba56769fe7378ed12200600f238525b913d7446f3ceb1" . + "5353a62811356e44b86ffa50f534a55c80d341f22018de7019432b6135be2bd0" . + "40b23ec2a40733fc620dc36608b90155df241ad0f07288f8014b8b7e20f3f149" . + "babfb8aa23909a7d780446bb0e3cc54867f806abf853ba33100fa51f9a3d4074" . + "53353acb443ffc2ff7ac775d312f4bbe71bb3c9cb92af4267576ad008c646c68" . + "a25631ddde96122cdae44153a0ef85c2ce1fddd64f26c7be01d862cc4d9976ba" . + "18b3b2c54ba60c6eff74e4f3e9e36963816ee72c72da0fa84ba661e39835b29c" . + "147050619ef001f04c243e0cde738a142a0845b42a1c269af16ef27eaec8280c" . + "98a88b5b2bb0d7baf1f2e43417c9518beefd18b07e10b62f3a7b2e1c96e78d03" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "d4696784f04e118caa2796a35982ea863271d1ab89db67e0d3b06319dd6e7a20" . + "2600a5b83106791fcbe1ff60617cbed91dac741d776f5475fd4ebf4932c39660" . + "fb043101cdcffdc016d0acf042c664bddb0e998c7f770a56193213e3821bc67e" . + "b750671aa3af57fe493337d681a11b1a528ace8db4689f65635eb467e30a4e88" . + "b626dcdf1454faff1bdd2f1198a451e2269a3a8f512c7d7d96739f1df3939c87" . + "92d4a736a66420dcfb28db211084d08a5413e9a7d5132433b78bbe7a5f94dd21" . + "25eb3f1c46a1a3f1611bf925add39bf99d0bc42765bf0cbe522f85c217891066" . + "28ab6d4d2a0d98778f0355d3f85a9d68f3f449838a2dbf47f14a7f358dc072f1" . + "1687a273cbbeb471797bc283abbed630a2b2e2325a352791d60c1521c88c6b2e" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "d71f4f555d5c7dd17ecf4e50c8c4dedd664c2de5cdbf1d1b8092846ef998f147" . + "3456d7825ae16937cacd041f25d1d57c2db34a4adaaafd1d1dee173d8b7ec041" . + "531bb581eb3900fd41392ee49b475228ed57e37500e642439e05b283d05ea5a3" . + "81df5596795673f6ea157e955c01ecbf8d3d7b6d4cb0280d4d960fbfeba1efa4" . + "00b26e4e3e95cadd665465731e0e8b38221a0c7ebb18d513584366f29e685b67" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "ecfb03e470cb7c451806add565e02da8f7b3dbd14c38ee62c88984fae4604d18" . + "411be469cf9a600bf97d847f74aef3d57f15e7b341c4fa5fb5ba53cddbb6d809" . + "3651e5b49871afd5a1112023faeb31584ae983313887ab5656742c60a845c133" . + "4d5c9d932bc8c4a6850b7c38b78b1f395420ad314fb37b75488aee1975bf2dea" . + . + . + . + . + "3a16089ca5ce723592e7fc735da7afcff48446ad35b158e60101a6bcbe4b1092" . + "425546e58d44a7a60db8bb6abaa9e101b2dec2cfd2cf39d493cdb59cb96ce7e1" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "3779c371001342e62821aa072ffd7fee5f3f86d44b11dc462a97f9ebf2212c1e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3ae1ee815bf226c5f97bd9b42328b026dd387a852c76f56de208256b6b0a285f" . + "8aff6e8a9189dc78312f9d1f485e86a3b5edde1a49c637ee0329e8c062d6d5d3" . + "40c1385927d9132a476ca296f073298428363787d7e067abda0b3b985080cefa" . + "3ba3e41ac6f5e8b0316f6c1631479924b8e465a5368e3c0f96dcea302d78f629" . + "76829d4a0d4572ccb843ad9961c97826bd22d680137b14c7c1a1aa7bfec97065" . + "364446896bebad858d27ad64703f515628dffd8679e977e9faf4d9721ef580e1" . + "4d30afc599d22214ab09fd77df9a97bafffda964fdd9b400f062d872b9c6ef41" . + "33ef2714bc423f1b26d4caf6465a05fe63295cb7f55d050a388a98888b850d38" . + "4f54e10bdda5c31f9477850db4307b9b1e7a6f3b6faeada5acced56592fb20b8" . + "d701365794e2a91c8d19f5acee8706362d27caf2aa59f09cf124d79da871f739" . + "ef3b2a9c76aeaf7300ee722dc1932dc4883dae9b07ba263df94e74bc25f2bc30" . + "5027dbed46b051881e87ebce497e5eb80fcba5a69aa395febb1539dbefdd0a00" . + "5eb234286067fcfd8224f5375bbf0d36e5223fa3f79c222f99b0618dd2322971" . + "a7dce582bfbdc1458db7033ff18c9eb73640748bc7bb25327b0d7f0ac0ccb110" . + "4fa74782631c8fddca534782785ad9c811188eb66a8500ffb54c88cd1bde9dfe" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "a4710c7fb71a83c2248ebf041937dd99c030bc089ae4df643406fca8b1f36939" . + "242726d906eeac20f586d4595e6bfac264412acfea5128004c79df678ce560f8" . + "ba204c073d7e09c4323c5b9f00d0d606119f44fe604d8d15188bc9fb9f72d9e5" . + "a1279cf17b7dc3530c03e602868132fad10c6a2fe1fccb430a8be6528670a604" . + "212cd8730f6e9186f01e96148b884b356b1056dc0a1a1062ebf2eac573f543b1" . + "dd4351fec388586eb979e55e47a43df935a7fd19cf262d688f442ecad6d7c009" . + "83dd9957529b255aa6665d51e8a81522c58aacfb79b243c490a5ef8d3abac06f" . + "4c69ad9211631c2f5aba6d69734bf3f0185c8f95b354c582ab92e9b1dfaae358" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c1a69380a0a9504659b8ead0594ec375d40408a0a36732ad8c0f06024900c5cb" . + "f2b88f932fa5429b9f2d91975d5218628ec6e7b99636f4f0f32b1f8d162ba1fd" . + "d895bebb04cd012d596c7f3571078a6369833d4624c048c61f30a7967033f730" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + . + . + . + "bd637e1ac76161dd18a145b113de5485dae6c10a1b1dc90f3048b82130c00d0b" . + "3c11d9f417e12fd4eaeb0bfb47c8f3d272d882c734c1a8e1391f9baa7863c2a3" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dc22eff7ce6ca6e97d7b2ae09533f7841b881b094115a75d5e323451e1121f80" . + "b00990072d9d6011c4cae8cc2aa7e9de6c3691721c457d6d181bc46cc7402ac7" . + "c821dc4f278ff7de133ced545633fd9da4f261fa57268a49b6fe5ac828ecd69b" . + "a2e120390aeb2df3389a819101dd7d5af5f67c894a15e0125c0e4b91815a3423" . + "873776f5786b9de26c902351e06f567b72d6c33d19a3470812839e1df3c210d1" . + "862ac381f2bcac917ec239b2f3d8e0c5a599b564c3bc7846fff7b9220c516ea0" . + "ed8c5b915bae9f890b64a3980ab5a34ab30f60503ca413c02ce126646ed82c4c" . + "81af0b902cd4e163537093be57ca5292988931b6c778e07730027fc0a05a4078" . + "990da96ac8ab00621c95946b14296cef20caaf466259a5361753ba2495044f33" . + "2205d4536083ce035c273f727757aff43671480f1b5c63b8de884eca2853584c" . + "1243249a8b012d88c1de3c80a716791757074616ca3b1a087718a26d52621c70" . + "b91a5f3066bdf9a310e3523557ad6603c5f950ef77f6f2198a9d7f8289bdf31f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "84d2d9bf27cb0fb1067e765e85d18758f99374e24d5c02ba572cd7044846fcc1" . + "d8371ec58bcce6e170f6d97b60df9a0eaefd4c4f23a4e1043f8e0add58787224" . + "d92eacb420e395d7d577f75e06ea04bd2ce327d13906d3e25e61d11939e0d327" . + "c0681e5b24c95df66de046022fd069dbc4b036e53c8d2df5e12493e3ea49fe17" . + "8869b83a400eb6e795f266d1e24809a82dfbd61b0c90f8933bb4940906e7502e" . + "871be26b902ea95d7a6ec5ad66827ddbc2e51a6d1df9524a9aa0c197ff288b17" . + "e78f32feee28ed777a763f2880e9766d92c8e0ea60a87e51c0ec324bccad33e3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "f6d19e93cffe6a75086e1f7e6dc0a01e85a1c9f580354a580e4f741475eaddb0" . + "c17d5787f833d383afd4bfe91694af39e85382ec132641eca1e6809ba2cefaeb" . + "b5b7802239a5f858b1f76b6cd12e0fa0bf24f26ee9d32f2cad2b9e85308c4fbe" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + . + . + . + "882919ca18f0449b10246c277b978a3877a2a08c0f70fef10c48af8ec5d596fb" . + "a943733e1e49325f5b17ebd324710735c83a3f0017eaf37b21a8542fb117e4d4" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "4395fb7f3b202d1dbbff332429f3095096dcc7712ece5128db62f65107642107" . + "1bf2c9a9ac509db4b66b33236df0fe223b2a1484e6389ba0d096a9d389d6420d" . + "a6a6c883814b7c0abd1519ac91d9cee797a7f2ee75fef3a4bfdfcacb2b867065" . + "b4b39547d8b3239822f5b3cc09c3c6b2ec21dd7fca8d62f4c43e0457e68525ce" . + "c809bf40f79998c810d3c8137861dba7628062c2573c8fb1a9e6d83235e1798c" . + "40438d68d3388a1b7a4162ec9f9979fa3a29fa5f19d044bc0d61d8a48198d646" . + "62ca8f515fa35210522d8133b29aaf11ada8c81071301c6c5897549a656e1a79" . + "8313a47218c2555738338f9d5a888e0b54c39f3e4136c51baa28f99477332ff7" . + "41827d027fd93fc851ec823678e3bb107ef14198cbb12d5c8f0ea29c5e402cb0" . + "34d353a74b9b9c3cbe503a155d7add7cdfe438b45691edfd83d6e5d9e44cd171" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "f66a7234a4f2f74a9ca0b0d5dec64178bf63a7b9e420434822b6ada1188450b2" . + "968f356b8b2c69d6f2ec6a718f653c1493e9f61f7ad32c46cbfb86d66e8659a2" . + "7ef8bc9d4a76897ca8f525ff006180132e963198a6dd86cf6aeb83d31b29ad4c" . + "4acbd18dc04196485431766521ce2e8db4373bb8d4996ea0f6c5abc71f87790e" . + "3a254c5e6ec3a66be05b3dd4a160ce78af70aa04dfb8b0320f153d87290d5afd" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "40f718b49bb7ab9a826c331184b94b2298a8aee007b802d37e864c40107d82a2" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "d3dcb0faae85f4509730d5c0789a4e7a4ce4c5f0d6c4ec43934ed4ffb72b0a43" . + "1d90fa4b1c442c990df9e08a5cf6149cb5cbd2ddfd30dd1a20d5b21f516a3a3d" . + "7726a94abe2119131b6e4d10243f75eb047a37033ae9db2b73d2d5cd67b941b2" . + "fd4cc8799e987c7de57c2d885586631a8b3eee50aca1f57f4dbdcad7adf1cd34" . + . + "e2b14ca492ed1b65074b6e6ea5860ed8586fea0d0d20fbf265d895da7a70ef20" . + "50d59213802d472ecc65e685dfb942b486883cba6e33042651a4462fa4d13ed3" . + "91d496c0e46c0d8776c140790d83911488f4641ac7823ced6136902c9e8a84d6" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "06d6b854e88c231697db359e69f682ba4a5d5d057d348fff427b514ea40e6107" . + "a37ff197b7eae203d41ba8a5220dc50d374b106b57aff2f952bc113e83000e94" . + "e864842b88f79843b68026db413517b6076dc23528caedd92084cbaeab3c729e" . + "dfd9e85304062d4e2fc5f9e0b13595bdc94c425b6709c1401de426df8b3de742" . + "0998356151c897979579456ee4d4d9705cd1090ec56771831cdc9d9b1ca154ad" . + "c168b986a966e376a554d24d3317af40065192220c22252c5d0e0178a2f5be78" . + "2583f4e41fb5a9107e112912a2d5a747d408cfb82f7d4f8e2389333188076c39" . + "0f31da0d335ad5d97fc782088b080ee82bf9545c24722f4a2d213c4f3aadeec1" . + "94529a017f53a1a025afb0d2fc9bff5d3af067ead46a813f4b0505a33f73c919" . + "c92f921fe55fdf94fc39ecb823f22204e00ff808fad5150e540d9b0745fdb891" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "ccf9dfa4f2812708034b9a00d6428f3e9255930543ccd3852f6bb7545283debd" . + "d71c13e6ab72d6a4bcfbe3c007d0baa1e6fc859336a74a602eaa9ba8493d482e" . + "1cc20bdbd9a1044094ad8cd627cc9b9fab729b71e29f6f8b1e240a7122f69798" . + "88e8d5b7560a364150feb24cc7c63ee036a4f11110b7dc7cc017166383be80dc" . + "71eaf5735c35beb1affefe23c2036aaf9e16d3513d9f4e4e16128ab329330e39" . + "a1d670ba7754349c0d959ecdb7f8e75d9290223c3638cf68117e61e8ff33514a" . + "c5ac1edbd3cba6e3d1fd37d6e3304c4f96db6331f166a3b60f78e0cf4372ebd0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "568a4e0185be99034b1a5dc095af1aba01752ab95fc0e2cab8a6c67ed3bd290e" . + "d8dc99976d8735dd6164a1d15fbaa057136eb35addd41e8fb9c3660ce510df1a" . + "8f11d6e1b9c17cd1f0e979c0e50578cd18bddd5bcaa626694d800b0665dd0b51" . + "8eeabf6dca13412bab051f2bdc465197809e9917f0a85fe3da039c15e9536ff3" . + . + . + . + "62ce9d79240deb8ea3a9c9411c6bb08e656cff851ca34f90f2fc8b0f10d68eff" . + "22508c29a3e5835fe37d9a9f73ed5158e7b9975b5376c6a423355f91b61037d4" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e6fbb53da6e1d7e28c0f4475766fe0138931b7bc696def9edf0bd2aea16ce777" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "68442ca6d671b5dfaca0b677b8230ce07fc7bf6eedede78749ff7695169aaeab" . + "8710ffae70cb64cd8264d807042a9626aa4fe95911d23cd4d9cd4e13e3e79c89" . + "1ebaa781c8e262f590fa7d60cbf539e470cee53196e44d3ee751788ae5dd3e8f" . + "45a7b2edc68d7eaf77b2cf3a0587d7b19776c84212e1e111d98d097c047c4a37" . + "71df6f9a1005e95c3174bda37ac3876fcfa402d1cf235653ff76dd932b5d1f55" . + "ddbcf52271034453b49d85c3ecc66332e89dd2373f4dee22a48954df37480066" . + "b01337385f08d3b35e6a46e71fa0e0ab21dc331c08c42f7d9b56df739776d1d1" . + "0314b6c83094012b3a8491f9723de1e07ae5499cd0433f18df68a7cd1f7f1f53" . + "23e6d0d71d610792b0a679a7bc5ed661f1e1196a5a0d76126dead7f0a9b099ac" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "578b0a0f720a4d2ed0f8b358bce3b3d14ab8db03b6e38e7924c0b0fc6d406f87" . + "4cddbca13701729c14572f8dfebc2e7cc30b2162ccd401f0fdd4b7a0b3435f1d" . + "65e51c793b5abed6a543d71fe059d19ed53fcffa1599d4f2ac49bd6185e8bf93" . + "1f52f0cec090609c7f15e0adb3af12f2a4b302196b7bd1f68fd99c272ab1e34f" . + "4ebb92e70b88481325e8f955adbb6a483955466fe1730fefb622f2a217ded3f8" . + "1059220aba457bac19b838dd477ca8c9bbf5e015f543b2e2dc2db09b0017e24e" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "62fafa8dd5669dc712d92568a87e3acce33a656aa0ab4be7e9498e8b08d14d2d" . + "6629a6128398bb6f4aa4ae3afad37d46f3cb9d9644d04fbdfadafe0dd7f5d422" . + "66d7b668fa81a9c05cfdc5d44366ab313d64b42c553dab799865217ad6d06ffb" . + "9203d12692a9aad1439e63affcd0d64b878ccf3eed0213ebd112881152a1c719" . + . + "f7090b0e30b8095a6c2679caf5957d3d86be6f32d0c03a4dc07cd9349128a2bd" . + "c9aa38e2ba36e82ba71d81727cd3c4c901c7b3017710aa60c35e615b888399ec" . + "255be0db0035432ea7dcdaa17de7c6c90648dda2695a8ca7dad83f499e898a20" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "eb5ac3b92588033b4ae7592301a30b3248129aad9789c8e05cf4720cc5f4c9c3" . + "e451955970295ed8798c17bed8642ae82766d3d28a01abdb4bf993ea82d6c444" . + "a75e213d0bf662b9a1900b290ee08f1ab87c57f3813528707790ee8a4a3af904" . + "fa039a0e5411a7e96c337dd4c29afe897037098148167c0f320245ce8df38245" . + "c23d972f082aea68fbbb9a7157e4e32f39ea73adcaaa9645e3c108ec3d9e78d1" . + "d21fea105df84efa5d54717888bbbf5d867a5ff6c3f0ff39bf3889decf223916" . + "9dd545ee5a04e343584404c23f778d6ccf3f573b10d1798c13d521656efc2e27" . + "ab42df4d78e464e2edff149cd0e76a352feb7b51a6750d931c23aed8558827ff" . + "738621472f4809c5be8a6f720990377895283eb6e51489d6b6ccbab546b61282" . + "ab16ec171e00e21d22ea302f884bbecac5e4e797dbcc51bdfceba2666c932054" . + "e720ea759c0ce14f9ff3a80429ed5aa5225d49a02ac9afe86d69c8de6bb8f691" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "a6e230ab6fc30ec8bcdd0769c21b8b0811867d95876198dc49911fa01021bfb9" . + "669757eae8f89eef26d0bd169efec918e8a29becd3d16ae1aa3fdc0baac71053" . + "af49722ae9ec55bca64ea72bf33aa093490b6f2a2ab96237a4af8aabd648c09c" . + "f9659c6d69c8eca4bc71ee05edd9b91b464651afcc04754dcf340fab1622209d" . + "8b490f2b31ff73a55272a3ad8e50477187370b6c686d340b8f8408275d76c50b" . + "c4e01d6aa5484214a7bdf8c99320c3e91b57f717b3cde37c1e7fc3922961d704" . + "986f41e2b90121208d9f512e8e1c29b1f934015c63460710bb3202d27025a63a" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "9386d81b9cffb258572135fde17a090f3be43da682292065389183dcb47e0899" . + "2da6792932f8e68c7af99417993f8468e656cdfa8025bd1ed45689f099a1d09e" . + "f619165f1154f46a1cc9c0728bc7157505dd3a2108727eaa5979f2d49f066d94" . + "518f18cedb50f9cf5b4f5020e2d239ed6a41f919243186e3dfac4f2cf508d6cc" . + . + . + . + . + . + . + "1ffee29c79de083f0d1076df4aadd58a7dbdf23116ce456627af4752f38ad862" . + "dffba2b2c8c32129cbe9696751c29628398539c98b9dc859e79b28580e3cf31e" . + "2013e4cc20c237464c16c1d3437d41144d49d2f179058156a61398f193c2c2e5" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "734c5447b99c5e635162dafa9ae4349e5d0be2e0dfedc1739761e69ccb7f28fa" . + "9daf1c178e6cf3f7aec45506384d514a867ffef477ab1198cbf9a8ac7049ff27" . + "b1449f94e595bbca1d3069423aeca9e860d919ac74ac8d9c793529bcfc19608f" . + "40ca4ea5942403d5e9ba5895228ac37ae18ba0180b6d156776dc1c06d84bb44d" . + "cad0e097638f4e98d3d382f37c8537cd3c39f0f7717c0d3b6e88944f16276131" . + "7a5cec31f412a3b936073ff16c70e86a22d7ee65ce228f6005c82de92679be1f" . + "bb358b84ef0c3523640e5964490443ebefe86175b69ec4f3024d8ff650670c92" . + "7ac37d3e23ce73bb9c80da37d6079c643d683d342b78a33b06a8799b2cfbb430" . + "ad1e2b1ce4351f984b4e288adc7ea211cb8c3f779825fd7b2f0a69a4184869d7" . + "0521154a3a2933a56e37979ebe5b7023c39d16f3d534a04b12a6247c8e7a785c" . + "efecc6612d46deffdfe74b94869eb73432a3558a1b852aeee35c9e5ddffae8d7" . + "a0b34b21824039c8b26d879fe93b8c68008328cb95713c7013c00d4730078f97" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "5f60efae042640f8193dabea055a2cd7dd47ad00cfb1ce8e4fe24fc7b8290bff" . + "4fe3c20792a940f310b6c240ce26686ed6e681e6d9bb4ee35778e8376b6eba84" . + "01acc27701fd547a20d5cf15882529a4a094f2f3876eb0dd23fb7aeee63629b1" . + "f31f6da1a5281173aa2d2c466527b6c3878b6bf2e359ecac1ec33b3217896e3e" . + "e1483ee8c3abe3aa91a2dc7b416237c56fd1c0316e3b39b72407ae70a17457d0" . + "aa808123a43fc6280a037473001eedd62ae0bd8ed140ae4e08646bcb36c2b5d8" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "7a337db017da3b4bdf295e0a5a922cef1805899cc6f491d737e0be9975e92a6d" . + "7344a3a414130703ca24834d937d90ecb1479785159f73126c5946be15040f5f" . + "5904744d7b61bd1a662f78456e945638a5fba4dd48e4ba5e2634f2706c5b7de0" . + "a8a2727880b40a9592d8b935d082e841302cd8b4f0c67cdc8d5e545a1ccd4e87" . + . + . + "92bd4a90362cfc2e8a60a50619fb0f005de1a87d9ee062fa1f9a39bee05f96d4" . + "449dda0bcd28d38454e5a109be106cdba9a1143262f37ec95b70d9c1f96d4274" . + "7e6b4f6794ad788cca2aac4abc2c6c7b503a3bf4768d184a6e4f29a87dbc890a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5080c2fa20bb2bb25fbc934e1b36c8bf47a6af4c87b3fe168e093649ff4349c3" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "5e3cfdec79604f91d375e8d38a97892e90227e062b86303389c19057f4e7971f" . + "87e5083690505fac6b4d047ca0f53dcd3e08d636e3ebea073737dc7d27276db3" . + "a8647ff1b304610470a52c16d2421ab1df38d19284c6d5b1966493ee14d36ff4" . + "dd061557dbb8a4fd0540b3ab7d04fd9334a40207101d51d3f3c4e85d01c07432" . + "4ae338602eaad00b0eb5212d6d7979e3a113798953a90f9b0ef3297e56c0a334" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "2044afa5979e96a2f4468ac1bba079d76a4506f98f902034c28db322e57c7302" . + "2fc0b5893c709ee341704b539cf93b292ff5752cc00f81e92cf2dcbf6afdc109" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "0c0df534fdba833c2ee85381e3ecbb4fe447bc61a7bb908ca4398ae518695d02" . + "474914f92ccb5853bdb0d31d59a2531f859c3920fa092908609800bd48609be7" . + "2b415d6c84c67f565f59fa81bf218e70550cc0189e911aa4e593de3a101fd43a" . + "323df71c8909b363da3ece635c07cf203bb30f114f1daa6cfd3a8e5e8a023287" . + . + . + "95b02012e4e94b3504b2607d68a180777d8efb6bff58872ce4fd09cd170ea9f7" . + "8f937f53c406cbeb2827a42d5ca910455c71e603d60c5d5df3ce25148a644da9" . + "cb7079bfc193b9a162613f333dfc0ff16d1b3ecb3e6fc64a9e5d63220ed919c6" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e34fd8bd29cc27abcb3a7100fb8d7dc38a0c2e4883e0eb6e1f87c8e374a4904" . + "b7a893be03a817cc76e01f44f313bcf872f30389611a5a0b49cdb61ed54dd988" . + "e555e7d4a7d7af78223f214f3c3df28e0411e2e308dcd664ddca30b0a640e174" . + "0cc56590c629a0431f835bd563633aa4c74fe66e6cde66ea206cc194a930165d" . + "37a1449ebfcfbc097f7fb72a9ffea7ce82290453003f9f8c93cc7dc0bae3fe12" . + "81af0b902cd4e163537093be57ca5292988931b6c778e07730027fc0a05a4078" . + "2205d4536083ce035c273f727757aff43671480f1b5c63b8de884eca2853584c" . + "4e4d804437419f346af9acaf6fcf7fe8239d93ce6913305c4d118d87c6640d64" . + "09f959160a2bb3ee8dd9006473eb32355a7fe94e502643d8a857d4cf8d406fe4" . + "bb78d4247681f323a01399807383a8a1ad18b2fffbf3179792aee2157fbf4919" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "129873ee7ff3d1db5108271f71504179512a607fb55298b807ccffde4c8072c8" . + "d0099f37d034ed690c925bf774e9df38cb4519a2186c04b940c269d6082c4807" . + "232fd93263f260515f5d89e9fefcf134978207a85e670f87f6da4d313ee4a98b" . + "404491a1ba3350cada4412d104843581acaa6cf9bff2cccfe180186b4ed070c6" . + "72033db5b36148b254073d7c503d68cfa44aae42466301027318f5f5412c484f" . + "f925de182808361915a64c80c276c31e183d2af7e1499e45309277e186a5c398" . + "3632d26241f7571a7b496333d3bd4020b3ee26925e436078b2e908267ee37a97" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "526e4479f13e8b0235cf198e5f686846d6c97779e5ab14dfb6d82516f1cc29b6" . + "32e73e0d7a7360af25ab736361b2ceb956394349cf4b5b4969da1ec606c2b0fc" . + "35aaaaa61250fd310204b27a0d526073cc80260f7c2a58293aa24757188a7b56" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + . + . + . + . + . + "d5bb8317cadefdd24ca1ccba0a9411acb2031d99094fa737e082a7c36c65090b" . + "9bc435cc15ecb3de9b9ee44f3e69419b1c40a0e6615418bb17b336d0778231b6" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be9bfd95f2a3c2825856bb92278ee07a006e696ffacb84caf6360bd1a5b35dc4" . + "ab585355ff2e02e46f92c9e22ca1c6e5c99a7d2f9dfff20e3f4991de651cfefb" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "fe35364e42d697cf66ecfa86db57333f9adcee21ebfcd13462565fe0cb5c48fa" . + "e1767b0f8c901ae5d883752d59565a7d6066f6740c298fffe6f1ebdc99138860" . + "58d5ea4dd0bf5c59d1f9aea15a7a92f58c3d47c246632e3bacb287c3aa3d2928" . + "b11b041ceea791963bab1edf6a810c1d11be034be4223426bd291d6bddaca22c" . + "6f79a2bb8c0dc42266eac285aacdf40233174e76d939636d37295327f2c9a51e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "866eead21b39773018eb7f981bee50340f8fe0b14959b83ab6a37b93adc800f8" . + "2fc0b5893c709ee341704b539cf93b292ff5752cc00f81e92cf2dcbf6afdc109" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "a1eefb1830253b311deb61fa333bb9fe3ea06027bdc60a8de0a680a84b18be2a" . + "4ab8e6ce880310c89287b809fd526cc07ab1a971731a53e3393f3dafbac05030" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + . + "294fdc0a7795d6ea3c66627df4a8a27326c7bf94dd45b1a72671076f249c15b6" . + "f4aeaac9df2ae60e9aea0f5a458a92135980f8f7afa2159c5025adc315cf0c4c" . + "e6e13e33167dfa5b46d81c0e720151f0f0a4b961749da3d23dfe00bacad1f356" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f82acaeb0d1ac8b9a36125d428e05c4b715beb698855d91b76841597a3936c2a" . + "f82acaeb0d1ac8b9a36125d428e05c4b715beb698855d91b76841597a3936c2a" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "2d5549faf6aeda5ae03658ad4f7a2a7d556cecfd9a8bc15708aa4354d9e9bb64" . + "00f7ea981ae79893a27963f2e2d8c6742d43e3504b8537574eb384bfe7562ccd" . + . + "374553a47685d25896ac47cf0d0b948b8a586eca1c7d2770a9800257214c66f6" . + "cf2fa46c528c3b6b97c69dee7329b8a7e9e37f89cc4803c1bcfc86894b3a0a85" . + "47c7c8f2207a26c86e97bbe302bbf94aae303828d97f0ee8b4a5c7cd57b8735c" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + . + . + "f8bc39aa9b2b76bc4346961adf0bd0f82744fdb933e7d483636dd9b19048ed0d" . + "e8c2461343981506f4ffb61cdfc3d21ece0947a0f32aa199f85fa72da66b0fcf" . + "b92e106e5d26f333ba3a38c08c35dc751eee5d6454f35b8674f8554b3b476d90" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0b1318879dcee09c48042df5b38b4e5638416990f21af7fbf0e244258312e7c0" . + "d2d28d15cac4a11a13d28ee58ff561b76cb9cc6b07ca610442f9a44b9e2e9218" . + "1ddeee3902f210cc2a2aafa798e473df3134799e3e7486247f0a271fc8677c51" . + "4429c73b34e9dacc0bd626332f822788a38f71d5acaffdcf8dd4a7393a7ee633" . + "3b2f81de393291f8ac251ba777e61488bd2b417721ffb0f51e7c7e3ae6ef5e29" . + "e1ac223f66b4900375ab43e7a4f79fcf57f39f864abce03e10e1e455f912c432" . + "7fcf72bdf01c3685d2a42977f690d6dd6b1bbf1bf082029f57009b492ad95ccc" . + "3f9ad973cd2ef0e30a357b44bf066808ff5728afbc050aa02697102c2cef1fe6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "8d83af47468813e862001faf8f92360705666baafa9de0af6f231008eee091f6" . + "298ff17c0461b9b3ded506b79d083259b27870c9155948b15d5c0bb4d5254462" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c00eb5dbc2206ecfeb97d06a9dfd3dc19d07ce4efce1adcbd754c5ee4bd96da8" . + "a20debb524e4c5b96c46fb3c7c32cec31abfc8a259f891750cb258c186e74869" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + . + "ce6cd21df0b2be7e23a9a5fa374cad62583a361517d89323cac444775daae53a" . + "572565a6311f3f8bab7ca6a7212d544529dbd79b210feeef70168e5706c1a9c8" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8843f8af7d28ef198f6e332f4fde6bcbcdaaa1f18302b02882caa207c4e0bc29" . + "8843f8af7d28ef198f6e332f4fde6bcbcdaaa1f18302b02882caa207c4e0bc29" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + "6704ea483bc283d686066c6772c5d4d4eac7a6bc2f75bf0182d88179a53d1b22" . + "d96780d903ce154f19924b914a7a1be95c02491fca086909d3d4cb56d73c1b64" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "ea3cada3a86001f5a414bfe5ac67a5a71e79fdeacc79c1706659558a20fdd5df" . + "2f98b3c919c20cb15101cb319463ee9439abc52c1054c6b5361fa21a1b5f143c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "bcce8e9d89b446d1362a7d8538bc983c8dc1a30c351be2a5c3724fc37f8a0177" . + "6f05cbf646c20bff556b7611c08941800552bdb48e41533f3ccd6176db3aa73f" . + "8444184bd1c3cfbbdfc38c73b7864f334b4a873c8a537c657935e3338949dfc9" . + "41067360029e884a803a8dee164e2a2c25439e4125344b4a87cdb6484451a5a5" . + . + "9a2fe5a7c22f2148e49b560978d5aee31fc60bc82d372e9b8d743d9aca4c9908" . + "a1b3c87b195c64311f2c68b8b3d0f1d260ebc0253e78e429eb1b8199aa55d8ad" . + "a9a0f68f958e4654824091c0e7218502f067cffc2c11bcf428401d75b15f9ae4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c1722ef4153e6a9cac95aef0fd8cccde823ff8135ba821515b9c98a73244a253" . + "c1722ef4153e6a9cac95aef0fd8cccde823ff8135ba821515b9c98a73244a253" . + "f17db1a5c487c57bdc4c5436c87e2be0b92a266ec9de8310f7718f5db4840a5a" . + "5ad2f9a1b23f3c6ea03680747a38755674d45cf12e8265d1db487640bccfd284" . + "cf701e861872c3e67e066798ff82a4bdb6d0bc80a043b4234a93c37cdbc5afc5" . + "6c7c331b387ce63f2ad570dd2c4a3f9383d28390e225c02aa044728873926e7b" . + "8620da59965e2a765262486cb37d20cd762bd1699e98bb51054d916239d6b1a4" . + "1dd5c11a2c9df2f45b3b72c205b1e5e4ad1029efd8a131448701841ab79b7e0e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "8f9851496f4049af5d6f0c90d1f4713e0ae7ccd0b1b443f56d1ef7e8c76adbd9" . + "a1279cf17b7dc3530c03e602868132fad10c6a2fe1fccb430a8be6528670a604" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "540bec7bc1f134da7183c4ab0ff73e738429fdb830b41482db10862f1be3002a" . + "f418875f0ae18dcaa97df1ee4c1b441f12fcb0e44000aaeb1a6bb93d9fbe4dfd" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + . + "bb5e7a8ac1f012d1d900e7877b5ad87c6e7ee112bdc2f08cdc5a122b170a0dbc" . + "01c04b0673c067b0101300f83bab35f59a864273f8f13daabe02717a8314ed23" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "143ce856eac35f5e84ab12a9eec83b4281bab1d599abdceefa8c5aa942e1194b" . + "143ce856eac35f5e84ab12a9eec83b4281bab1d599abdceefa8c5aa942e1194b" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "6303ec815dcf7a1f41f4522e1488669b5a5e56d58724555e21c3097e836d78a4" . + "0d0161d27c01b465d3fc309f66ab436dcd156bf102f546f7a898782f453b61f4" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "79454e7d712d48953d2003bdbeccce684b48d02afc5e10e3ad7fb7af8d9ade93" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "65cc7267e9a5a09e465b6676f4a05bce8fa33f3994a653fcdac7173b4b16d7bf" . + "5c8be1916f9135666e6531a94a7f220033d2fc95eb19704a11a64ff06b6429fd" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + "3108ea50e351957bf4fb5eb0a66011a824403be783bc16002cfe151ebd011b77" . + . + "20bcfa8202c67f94c5dab76d62aa2dafa5e30a46d993395eb373c8199d3a1e8e" . + "04b711f5e15d15e3a64b015f1d3ceb6a9306cd10f0e7409ed22802f2482a1254" . + "ce0a8e2d0f3fae2e3bc3ee912acce94dfcac0037d832f0a05a169da3f85f4bc3" . + "4a904978536dc5adbc24817d9bf5cb00b9057cf5d14cbea197042eb9db3d0bba" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0a54dcee87a3faee8c83653b8441ecb83d13efeeaf636ea30e90863217f2d69c" . + "bcc9fa783563b727f783817c94e7cc50ffb984c5596cb154db297de457d6a43a" . + "9c4fa637b9243e6b29b2a635014df0fbdc2e5cce4abe00c971d6787211ae6874" . + "6df4fdc52ef23806c0bcb1674043e1ccb9fe55eacd8c435d3001179baf8f6b95" . + "c20bfbdca8c40f2efb13a65f8779b8b5e46efcf81fc82ad2d129a20f46115e4f" . + "06bb85003641595e1edc8fd617ecdcd6e57f5c0f7584cb6e43d69518af83d856" . + "502634ff3be0473799cbb60d3a3b20237d0dcba494467a7058ea375573bb3519" . + "1abbdca3601811dedee194947cfc6abcf5217f57f4223540c7b6ca2482f35770" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b28096340b05ee8f54adf208b7dc82c08ef01cc40bb8759c6c87b51a016186fe" . + "02f8e14ceaba0ab299b01111684e622109957cc263416d60020e5dccdd0eba9f" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "ec5ea5bcc353ac2c5d3f7ba006b9870748a75757006024fe1faabd3059ae5cc9" . + "e3b1a34af4ba48fa500f876bbd63e60a06a570625f42a4f01e939599bb2b1530" . + "beb479f3c195101660e285c4f90b75e296ebdc109788a13a3572a8787c2de3c5" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + . + . + . + "d55e3cc133223f635af5c532aef42e2f1fa222c87a8f9ce120b1209692695c23" . + "76db162296a61c642a1ef560fa830806338f9b9931f9effd7e47182b405f3ede" . + "bd0ac9f528ac41c8f01ad9983270b90f82abc352a48f2b80dd9a6ada83363438" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b73d1f1647f1b74ffbbc44bf761be703c1479d85468b4e4586a7fdafa1d9044e" . + "c81ef5b7ddb1de76caf8f113860614694333f51f4dd631b67f1c5ee01c3bb159" . + "774884929e3e92f339a557923ea34f6a47e490f276a90f5b4b0a9d7cbe659c42" . + "1299a890a4d35ebae794192509a794208a4db65c3bb06f841e0bd4b1de6f67df" . + "f626bd27bc08d28163eb6d01bdc0881a6495dcf73fc4d887c9f0d0437b3ea674" . + "0fc5687d0aeeb06848159d3403c8abe45d7db9d29102e63401313b63c7ab3937" . + "463366b41ac5a4194d7a34aff3caa7d84b862747ad402c5ba16749ecec4a2b30" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "6af1161c120bb83964c13dcd3b3a0f577aa860094c170aea5b99f4811c04c702" . + "d334cb0fa79d3d24196bcdc384c2a1b6358e1eaa516f7a75b15247abff6cb9ac" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "796b183a87bdf4f441310eda71a370e637a4f6426c4c9ba9942edabaa005af00" . + "89c6640ee3d66f68f70b03f9462fd5d3e35e3e215b12e1e578b521b0526d82b4" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "b19ea829d5bd01b2696f17588444233ac826d207b2da3d2f047ff87264c02221" . + "b4dee056c58da98fbc0f5f97a74a5e735624e3a23991ee1dce07c0898b591f1a" . + "60c8586b74537e2fbc357fe54920b928ffe256500ff7b76ac9cc7f431f8bbe87" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "753443444a8c201704425fe0ee48e323a0b633c88f7287c600ba4127d0071274" . + "753443444a8c201704425fe0ee48e323a0b633c88f7287c600ba4127d0071274" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "c20d7816b9f5667a8c3b80e820b2e6322e676d509dacb012964c918fcfe3ca24" . + "c0d4bd65d52fb74e2b1fb318ffb757c580742ad2c012b4432a2a369e9d4948b6" . + "6d3e3e762b4b06e6b045b208aa9fffff44a460d372369314df91fde8998abf8c" . + "d4e255a62d2ee79c5df71ff67b9e9cacd2b998420137a61e21a052066f9a7ec8" . + "20b1808e67992945f74c92ec54f0555d8c7c6cc18997424cd7727c9d19ac6cd8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "dc5f47b8d9b804d3b680e78067a8bcf9665e30d90fab2608c2e78ebe80d3077f" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "402c59d5b7e2f7de3f7679cb27021d7a58ef2527547fbe2fa11e41933ff5ffc2" . + "b6a6a0b768ba3d4671625ed5ae6f4e73e1f64350f841b70fb5dd118f5b4b9abe" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + . + "2ec7bd26b73bd5aa92e4b30a123098c89f454ae95d648cbe510063d215e658ea" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c510553356cb4559d54ee2606a9640f94b6a47969c00816ecea27316ef967ec0" . + "c510553356cb4559d54ee2606a9640f94b6a47969c00816ecea27316ef967ec0" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "377a6032143a9295658bf5f0941700dcbd77a008762757d0058c0df25b030765" . + "5e647873530343c0b327b57e4dccd0cfd8c7501f827f168b9eb8da78832e20cd" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "4de673b64d874230bbed767577f5eb4e379414368cebcd6387b852cfc9148494" . + "bf0343a1d6cbd438ab2fcdd1f9c7a94025174ad84bf21ce5e63ebe4a92dfd0df" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + . + . + "fdb932478f1239d82336fdb0aac8e96671be18cc1f2b38cf73ac8eece52778f6" . + "bc66b648b5fe0e612f9dc64baa794d56a47ca302c0831970cf3c1ccb01eb0460" . + "3a198a4272d97d95a4cedc59541dc17198af91367b3054252c92ee8bd41c8c85" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f57265f9756cdb58d6c43bd6a0f4c1ecb211d782f4853cce9ed6f29669385e61" . + "f57265f9756cdb58d6c43bd6a0f4c1ecb211d782f4853cce9ed6f29669385e61" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "fcac75163b3a3d615385b4d84692375103d598e5dd40908e9d957be3f475be71" . + "22a05e930a07e243134e82e88b5ed49a637f86a1b513b67fa839a6627b175ced" . + "280476a16b1c3899444ce4eac8637eb91e514ddd2ca52bf53b5f4c2f79d3d90a" . + "8b4a0413c17075d8931cffbf1bd632592a31ac0d4f91affd435e3ff66498c7aa" . + "17013850c883842585837403f75967df040cbb83858b8a7cc10b4fad594710f2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "ba204c073d7e09c4323c5b9f00d0d606119f44fe604d8d15188bc9fb9f72d9e5" . + "b036bbe283f3fff4ec76af541675118d41ae88d561b7b6050a12bb6aa7c812ba" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "fb53a2378fe83f723ab87b757852305e60ab90c0ffb3b89c6c1d841e741e8887" . + "adb9626afe77066d07a0c62b04695dcf63773267efd7064ec2549bafc89f37a2" . + "43cd050b5bb121619a0874daf036266fc0fc2f354a93bb0652b212d3cf194a11" . + "c6bc32ceae839935fc42d1b97a0db1719947ce71895ea4088e834a716925e68e" . + . + . + . + "fb53a2378fe83f723ab87b757852305e60ab90c0ffb3b89c6c1d841e741e8887" . + "49e8f790c39416dc2b07e95700b8b18f24f225aae809c6411221a2e3c952f7d4" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9c685b5c4ee6f0df1d4499037412277165f76c476e38a91a54522c30fe790e1b" . + "871043f36c9e4c425db28509d8ddcf051260e69fa1638476843d0efa554c0fbd" . + "54a3406cc50f47fcc4d305b06f234d79daf6b55a7dc39acb05029c66b79355b4" . + "c1745aff2db904d8a8778645f93b8678bb5668a35e9e781b9247c505fa8adfbc" . + "815426df1ba4c2b3a5a53b0267029c84925478ddc2b4f7ac108396878bcc5cd0" . + "cbf299ca890603865c3c0ed4ab47574dc64055cf552fc62f0820bd5476e0ef0c" . + "3256cc3a1cc0ce8821acaa6dcbfc45356b50cc259489850f2874aeb91906c8cc" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "1abdd0d700864b7579b0795bfcbf486284369908c3c501c0cdc2dd34350e0e4e" . + "b095317c12443fc38153eabf9bac115a26cdd15148c5bfc7c701e776f41d1f48" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "86b7cc05d2de70d8a2b6ffb6c9b6d8bf2e10ed8eed163702faf00235018e829e" . + "9bbc99c54b9a6a3ab06fbc1c58a3577270ad87d8b5d5b393b5b4e0ad30a83d6e" . + "7af5c2c7b320907831c054c77d7e725e9de600ac15322839eab0518fd551c785" . + "7a4161493cbe1f9f9c7fab1c8a21efc0f1a6f6730382c0a253019e4b7b03a8dd" . + . + "9f10641cc9c97d9d8d06c2d672001f7a92215e29c6250877786d6d8eb29fedac" . + "524d3372d3672c392227396636ae868d91c669ce6d7c32d2636480ba3d934818" . + "821cbe96291ebe9eca5c1495b08a893c69e475b72e1eb96ab4ad44b846ea4957" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d33883329c4da6dc365cb295ef0337c62a2e246321dfad68c87c4aaa641aa65e" . + "d33883329c4da6dc365cb295ef0337c62a2e246321dfad68c87c4aaa641aa65e" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "b372f7b369e0b9243b50c28910c2ab354570e4eeeeda8e9a3f4b3372e18b52e3" . + "0469a207301cf2868dbdd68ed4d5ffd38159647a9522be59ea4e4e1a09d8ca62" . + "b25e70e2ce11cdea25503b4dce87e3835beb196f117f040b599486dc980f41db" . + "3ebf1a90a39c5b582be8355aab9d79134a177d85b0b0a78a6eadbc7244beeeb4" . + "750787b81591ecb0de3743965f613d2e2b601385401cff2a98119868b608c6fa" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "e4bdba72315a8dec65e5449929f0ac233e804bac1d459ddab0f84cecbc3a67b2" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "6e23d62c5eb318e7e87894dd7b1159b6cda28375cc289ddb77ff1349735c89e8" . + "50c653f6debda329d4bf617bc549ecf60be9e87a5e37b6beebbeebad93a40898" . + "5665231b8b74bd03b3c90ffda29f2cd4305a15b79d3cf8f44002ed39ed9c0c5a" . + "f37f763959548f87b52d9ef3d98eacf18eaafcf23779e205f0e2bc982cd42617" . + . + . + . + "47c001c01e128b94d5518d6b26804e06e786ea024124f79f7127c39057747e9a" . + "d214e42f878609ac2fa0597b380b1b773ad4064d11f211c719227446de7a6707" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "42d1d23bc45ee065aed1ca424c94a32da5adab5167d29728ede2105c226dd8b8" . + "42d1d23bc45ee065aed1ca424c94a32da5adab5167d29728ede2105c226dd8b8" . + "d78c0b2eb01b747db08657e39abb94da9691e2744e16701f66e575db5058799f" . + "3d1be274591817ef8ff785f62bc83bf0f7d974e0ef3a0c731472dbf8be96f06d" . + "b02d4404339859749f0185bc0e8857f86e65a3a9fcda91afe8c9a59ff1785810" . + "e44642162d6b339382ba05291f683ed3c0fc4c270c5c49c49faeb7b762f82a23" . + "629a3fd8e5646c8c213574a4942570d468655b76d2e0a6157e22bba1989e4f63" . + "57f9af8e94a4d254b5b7b790b352d8648e39cecd0702544ee1192dd575068e81" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "fc5f85a6e880ec2e5c9aac63c37b96464447437c68f3217209520716d2f65966" . + "7acbf64fc518139e1fe5cbc5290aade6e262bfeb90193b9fb6cd938241b0a469" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "5fc7e14c89f89fa56195f7a26a7abf6d43d97d30b1282efed5bad652fa7bc436" . + "6a9808d0a43fc21ceae7bd4147ed05e2eb6a93651bf482164e4c3d7b86e7204f" . + "f83a28e6c07b05ff54c5d87150a186632e17376032f27d813076efb2474684fa" . + "173a57de87be676f0aa989b3c64baa43c495999d575c42f037726ede4d73bb7a" . + . + . + . + "9f321ae939b8b812334196d12cd4e52cbab63826261e2b10798f61f238d35606" . + "305269b720ff1844e37698999faca23026f805fcb3b6c151264994c2132763f0" . + "e210f8e39c3742759be4b6679e3c2b159302d3f3e4b8f9f434bd58c7c62020db" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd3be23ccd23f7d2430fb42fbed411b5de2713b8b86d6f5cf6a2488ff0402e7c" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "faa65138259899d25fdfa0f5e51df8eef1fe7efa44ae4cf902743318b88a2921" . + "1a5ab8498791c06fb6ca6cc93e99e940aa663eb18793bb4b106699953594dc99" . + "3e1fc7fbb39a096c506a6ebf72c26ebeaa58ce74cf0eb5167aef18c6eb0b8a50" . + "5308e274ebe1102b4681357e6aea595f7c681572a6504d660e38ccdd67d0bda1" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "94d69539e406e603b81d87e8a8714b3a6d0338d9f91771a3d91da6761fa3c5d0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "156c14e389d3a2e2d5093cde718fb2db347af194feda307b49b2f091854e17b7" . + "6a869401ae5853dd2a2a54fe9a40b5dadb3f04cc4615d9924c4d06bc3d24accc" . + "00f3c97e29c7ecfd6be21471648951a59388c9892cb4d770751db5179eb16270" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + . + . + . + . + . + . + . + "48f24577ff13535b47a013ad285f936d536dd624d0274f166a90e239d0fcdcfd" . + "e172b0b79d5f09947ae3ecdd10e634317c777c311cfdd48c8c90175a70d41318" . + "44a4101e9dc6062a09e3a25d1a50af2851ae0bb3c1421b3390e79c70330a8992" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "994784d5f4203bdeebfb580b9d391374797621289a44e3992e6cd6dc4b274cfe" . + "994784d5f4203bdeebfb580b9d391374797621289a44e3992e6cd6dc4b274cfe" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "d189ea5c38fe7d7aa076daee0b1701e4b03468c8702084c2b96ae552a37699d3" . + "4e4e677a60923639131164dc48cbe3428c5f909fe3826cb300ed0dcdc1e53b49" . + "94908fb8fd81f91538249c14c68d084c2bf1bae744158b510d6620f86ac26794" . + "92a602e587311db61e818ebc068a68c56c496a8e27fc1645e3205ffd1faf0ab2" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "025f9627d9543281a2df7457ac6aea8ebca5b7586cd3abf89d97f52eef622357" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "e24bd6ebe518bcf550a826a56cc40b4220d2c2e1ceb80e5d324ab02b6181bfe8" . + "fc86b4598aee9c4f69cf75a268a56e5b45228ca30588df076b75a7759dfe8c0d" . + "bf4ff78b10880659ef94195ab9a6972c5146a9a52c8be2158bc9ad57cce002da" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + . + . + . + . + "c261aa1d79940baf7decc10ffd6bdf3dea2e87712d0d26c731ecc66b84ae6edb" . + "14d5e6e5d8b4d3076c23a09039a8214bdb2f8c0dd93d75d3de9c0447311dbc47" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "065e48aae60528be8b86b89ca8e136b5e22573ba36ababf815361010bcb2ddc5" . + "065e48aae60528be8b86b89ca8e136b5e22573ba36ababf815361010bcb2ddc5" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + "c26759a3ebdb5d3167a69f0aadff7647e0857106799164c8f6396ddbcebcc1ef" . + "9fc0c075d2358d0844c5e80382ba1ca45539281dd2d9ea395080f6ab2a48dbb6" . + "467cef13532d9de858634957cdd4db05ed8ff8b9f3fdeac96407456689ec8fc2" . + "5de60c625561fbc811e75b7ba45fd764157fa46c6e0bdcd5e23f0651c461fc40" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "b43f5c143f6e205090ef010984db734d670965a44dcc045c9d0286f9cef59ede" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "4228112574ff91e770d6416d56124ab97b33cae0205a0bae693fc75d8b1c6147" . + "86683e0c55498f86fb62ea3f7e27e3a62562138a48a43649744798e1f6c726c8" . + "96dca0e070b809d4d8c2a8b3d48fe92796055f9674416ab81e34ac20acc411f0" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + . + . + "fbe7c5708846be123321d005e0f2002c0bd48305a494b19528adc1b4523ea4d2" . + "571598452c0c10b67bda2e0b9c438b63af1a015aefdda2bb9715c01f2152d201" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b4eb61b19954112fd7f4f5b3ae393d31af7638cd9aebed1d58ebbe20cbd6a54" . + "9b4eb61b19954112fd7f4f5b3ae393d31af7638cd9aebed1d58ebbe20cbd6a54" . + "6f69ca8735970133a3753aa18d7e0ade36922866cceec6cce04234dce7b7b095" . + "73992339b8a85048b0528ef2c5ab66174e3671f4e59c81126c1aef5e6410f2a1" . + "77ce3704b30004deee71887c74c54b12efa3c872138269baa2789b2ebcece2ba" . + "0d2329adc8665960d605065436b18b57163127725b0eaaa8495cc1c2285c486d" . + "2e9d5c3446c71cd15616e15af4196ed14f820893a29d49667db745777543255e" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "d71c13e6ab72d6a4bcfbe3c007d0baa1e6fc859336a74a602eaa9ba8493d482e" . + "ebe139a9fa21ca2953b687c2f5ab15ceba984c28f8b0fca7a28b08462d4f3495" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "174c017a591f7f9106049e2573ba3ff56790500064f3e4be2547a2aae16bdb76" . + "eb72778a52231184d6ecd001b3f6eed71e55758d2d683aa932b60e55bae29888" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + . + "7cfc04ca4eccf18e9d5c560fb79e1807a02b2945aec8a37650a55bf62ac7e954" . + "52138634840e91ec82a829dfea4c237aca5bb2ddd8945e292403a814992c4129" . + "dff497773a48470e5ea3be7c52ca8a6b1fabc7722d4cea06bdcb52aac4f2e7a0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "96c5493f3a1a8d4eed35f333f115204a26ee69eeb3d483248d314a0e36a2f0a7" . + "6a3ca6e1ad51700ba684d18f0350cbce61e6ec0315a7401fcc059854126ecc89" . + . + "74e784bcd70a2a3ec68192536325dab1710783495a1f90abb529cfb53238a765" . + "2838f761ba98916f108872860ecf2edff0c3b68a301eadc323bdfe317defb197" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "5ff6675a0140be81a817b5ae46a4bce8f2b74fab609d2f484121ec4400cb7e3f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "234b10be246eecbc3f2e21cc70c96ef63fed09bc189f74dd21bce1cab0e8b618" . + "fcb28d72de74c54f69a9b28df705a5873a966fec890739d56acf2ccf152a1ae8" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "a6c23129ab6387bf150f7a5019b06440b8b589f5e0a66c2016c25b806c5b109a" . + "1e65c5acb0d5da6cee599537264701b61d52de1021b9aa2e0ec747b07659d51f" . + . + "e8858115fb77c6d237ae8fe4637a36d1e152c7273eae783c0f28408eeb06bf50" . + "3743f5ecc9c4b9245b5b326502ec30a50631b78756572115713bdd3456642268" . + "6171d8906cdd17be8d1b413eb510fe4bfef6e08ac99b92dbd66bfb556364d008" . + "c642cbe7224447b157b496b6eed5d08cb37b77d59c0447dd0336360d281592fe" . + . + "6143b1ef8367167cc06a2253e3ff07a7e6c70c3cab1e048ffa090cdd119989fb" . + "7aa9bda015cec0219913d6d815d3d3879e26e69346e3065ceff607da8cb149b2" . + "07cc8c79eb0a117296e888223ba18ce92f909b2c4da7fa1b9795609126a35c33" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9214fd94feb65fa3e774c85d6329c3413c513370396ee67a550cd63619e6c51f" . + "b65ef709e95b2f48fd60b25877cfdcecfac45615714920af116319a0a1b3f5c0" . + "4c5cec11287709c903d50b63508e7632c95ea396f111e9556da78ba117ab9812" . + "8b338adebe486bcfdc42f4227789cbe927b5aace88cee058a097b92bc94e9c20" . + "c3402d443eb80d43856fe9ec1aac34cee172013dde920502a3acb1d40114700f" . + "1a880217de5975ecab2a4fe6a834a9950d34dcfd67cff897624c756ab9b69709" . + "6cd16cb5ddef511328eba78e6efac1b812708b594b0761e491a4d5b04daa630f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "6af1161c120bb83964c13dcd3b3a0f577aa860094c170aea5b99f4811c04c702" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "36a38224569a5bda7db4d6e2f20090d984af2456dd71a0b58dba26dc3d45e538" . + "810cf6f44fabd0b9da330e2ad82bbd39a466abb173de9b02d0ee36d3d32d0f64" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + . + "e25132e3bac72d1c1675d85e7730c56ae5e56ac807a9fb155d6db1ae1998abf4" . + "a959245ded6f34f7d6cd594905d92df6d46bbfdcd26726ef0b6db61103521b85" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d000d32a954c5a4e8ead26b8b58080aeb1ad7884856af97351a9900073de9abb" . + "e148f849f217435b3ac842150a31ac69362950a9b381fd5a69b03eea641746a2" . + . + "8dafedfb0b6ec63c62f4f6f9dbbc9f6f95ab8d9fb9abb2302d5ba3ad1e212989" . + "33f858084337aa31dd1a169d98d016f53dce2301e0d1110efac22a885fefe160" . + "da9e869aa96f41dd3aca2831397f9c2e411495515628d8e9353de64f031c49d5" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + . + . + . + "e0f96989cc2b4ec4e0de720a36c79bf0ad6057746ba46855aa98b1974b5a6aaf" . + "9bd7881fff154b13ae1eae25d7fa52d2f2ec4e24e46a9eaa1f2008eda2da5765" . + "3e345cc0509c31d74b8fd499137cb228cd3c6b4ed8731536e7058ccf58e3b767" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7fe1a8f7a4c7d9ecc73a75256378b0cd60c0046eb51fff086dde8b9f76bbe3d2" . + "7dd0ff333d429ffa25101a77a93b844a2ece671005239eed44db2a7046502fe7" . + "9aa746b085295be78c8737f0fbc9be4f9282e7ab6a60d1461a1fc52937bfdda1" . + "9ae5368233334af9c905db85847b76aa60e16749f08975da3b17e3ef38697181" . + "e52e4b0447977f917ef05a1b72bc3b31c2a78bf265cd3a88542b0e5a618f9b65" . + "148b5536888cb0ed4b91a0b2c1c7949c49133484878746f0e6fbe5a1c48f73bd" . + "81dfd5c8dc88dcaa3060c018e787a56cdf773b9932d3bf9d1a496c3f8fcbe380" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "a2ca58520f7cdd15de631fc2aa8d984d9aafb5d8a9c6483bfcfc1ed08c8aa303" . + "860b4ff18778ba9c2befcf2bda3e10aebe24b98fd161c4c28d599922828998c6" . + "243c15151b953cc7af7f9f8a0437bdd07f56e4e7bd34c6a173dab882a787de2d" . + "9acab1999d6734b940ad35b74e51b4f1e083b19d7b29dd2b143b1a1afe4d5fc3" . + . + "a2ca58520f7cdd15de631fc2aa8d984d9aafb5d8a9c6483bfcfc1ed08c8aa303" . + "48c8d5bc4041ac1483bacf853c98c57fed91571fbb75b1dbbdc96b139ef7266e" . + "b19b83fb6bb0db06cd7a524830e1d2dbc0887d6660c0c260e5cdf827331ab175" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4d429d05bb21f755c155cc978afc4a9d3419c6605dbfc167fee82ca667ec5717" . + "2dd1c1eb5f2e34f0e2aa5f92e2cc501b24f777dc9430d36f6c4420769e6f6f75" . + "56d3d3f2e3fd1999de142b054ce915e4a39a7a5ba027d0b641b6250b90ee3257" . + "d8e792e3074dead5f68f1477f5062d07a777746e95cf2491f2548281ddd4bd66" . + "def1bb97a984b96a351dde3376c94dea62c8abbbfdd4b487d8c939aba9b6aa75" . + "f4daa27c255c175c53594e276bc3e9020d99e7992194729be6ec457ebd4759da" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "3ebd5d5a4edb14bdad0b8595d73aaf2668d5cdc876941c55b64aa111480f7c36" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "27ead22c4782468777a922e843f28029109fb4a0b89a584073605f6cfb759f57" . + "111f27b9a14634de720a76aec2ceded38c49fbbf326b492188be87c3eb50f14e" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + . + "329b6d08cd3f17e56b6b58ddd1cacde77df6112ae305e271cf8a669eae120326" . + "868137b4e06721acb138ac32d8b58ff4f0d43ed8864c609f71d3d33b4dcfcdf6" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "72dbd7cd6d3ad43a084199870c48d3adb8013e2eff50a38a75976e82d14b1c63" . + "1e4dbb8cd7a29833744dcb57e75c1c0494050656fb5ce73f758de324c04c451b" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "2dfd4ce862b07ca2f962b7173d690bd462b7efa9f0bcad2cbda4525a807619fd" . + "2220722f884944b678443864709a5465b6b1dafc37eccae3eb1673412450b536" . + "39e6584f38acd5a59b2f5ac93637c6cfb445848d62af13e5ea3915d36ba54c3e" . + "4c69ad9211631c2f5aba6d69734bf3f0185c8f95b354c582ab92e9b1dfaae358" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "3d7e067861132d8af577c3e8cc6476bc24b845367716b183542a53b85535e472" . + "e006773237684a87b950b1c467813571ff621bf94f51744b12661d4f68f38a14" . + "d8fd11425b096a14662a314fa299fdbf2285c7e3fb2fa32cc8089fbc15c3121f" . + "5694b41b18a3e3ecb8f046da5890a4790898f9cdd61d777901bd421ffe6c6588" . + "c85d5bbf8360d5e2812295d231aa6fbd307a6612395a4defe3aea428b11b9049" . + "158dc89718c26ceaba13eac05ef43a7c37c7dbcdf552043972125f4bf215f6fb" . + "efbb4d27a06735aed349f587bcf85d0289f203f442e9344b90808bd14d955c1e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c71333fa63c8769b653593920f2ed773a3432b6b43c3993ad00419c10acd9054" . + "a017538a06e3f768d7ed8c8cbc8ffefaa574c5b72e195ebb76d5bedea7500d17" . + "1ddeee3902f210cc2a2aafa798e473df3134799e3e7486247f0a271fc8677c51" . + "eab10fbaf7454518b120e3e429b57a474ee10533862577b80a24a4c68d5c753f" . + "644c6b122ce8e810a0a932051ebeb5b0cf7d6b41b0df503ce71d3f0dc615d85a" . + "f7fe7145446941842a77185d85ae5634de806ae6b07751c63ef757463c4225e4" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "2b674837f4a1d4fae442fc7f43d93b3af3edab7ab065456f0a56c6b8a2c762a4" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "a9ac7978703c5fd7c8db73c246cdccf667426b8422300d1df7f42f3d9fc2d832" . + "1b66278037f58880818a73fd937c8c2b8ecb5839b24b228433814b4ac2af1919" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + . + "89dc7e5b99b51f74ba32454c36c3d1a528fdf65a45944f0e5cdc6fa232656382" . + "5c844c4293fb098870f6961b8cbf46fcccf8d248fc75d522ea280d9d13a592ad" . + "85f187a225248a5b7bce72a5670836ba36f8f3933f8c2f6824eadd07bb8701b5" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b063ce7ab89532e39258c9990b7b4d7e8cd848dd56b6c94e039a6106142c9875" . + "9bdccc76fa04f8eb685af2a9cc7d2b2116d52389b54ed3ec14aaeb8343b1da43" . + "0314b6c83094012b3a8491f9723de1e07ae5499cd0433f18df68a7cd1f7f1f53" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "b8468bed49377269f57a807384ed0c767f18ba1cbaee60863f571f00fde43f0a" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "309e1476cb0bf95b076bfc67e0ecb2bd25e6dc48173c3e002bb6d514e8a82c3e" . + "41526441439fbe2e41be9457fd3539fb4a7c324f54ad5f90d5f80a139d87d750" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + . + "17959c0d093ea0f3679817672a318bab6309f9743aa2ec313b80d808c2bda2da" . + "3417b10b25197267c078f6c5754aff9d17db958c0ae512f927d0f5ec951ec3c9" . + "46127af6ad626a122c1c31aecf543f5305aa41df0f767dda440f8f16bde60cb0" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "9899e77209f81722ffffa62add1a24a61abd397963f40e3f97f3134d08131f9b" . + "0c08d4359964c5fe11f7da59a2eebd57eaf306ca8161358878c55cd9d61ff97a" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "0927bc60f90e2fb56122e8e37b6eeade39f70a66cd94cb44d7af538caa51f170" . + "629e6cdcaa2a80ed8dfff376b66ddbe49b9e4379777e0d4ba8f49a37cbeec1ca" . + . + "3ddec76f6bc65b3eff8ddb7e402225162c08ee7d2daaf9258375827dc4554da9" . + "3e965f9c4059c9266f7c8e89c431ef18facdded1d5d674bbf5de1e9e61585e8e" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + . + . + . + "338a45b13ea11352481aba6889efddce3510fa013c08ae9795dbb29c865691ff" . + "13935f8d3bed14fff1a6cc2a6f158ec3c1ad8d30bd078ef5e1b609c0de70f654" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26cbb46e8c3d727569ddba4c7c4654501f373bb6bbd918bbe32c5b535594c8c2" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "581dbaeea7e81f1bd0a0353b31af3f7e62392f66718915332ef71b5463eed9c4" . + "bf67484fd6fde30974282c375d8db31f088f8161bca5d8568ee5d6f505d4be9a" . + . + "60b5e71293ea93cdb5187d14e443cbb535c001fd58af100da823ba0c28e60dea" . + "d968aa5215c5fc52165b0b4216bf7546ed321480c146722064f67615d1a573e9" . + "3104a48e4212d0eff2da51d6e8bb08f3b8ba43558c6461f01c3540bdb391dc3b" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + . + . + "d6ae468cc408e0d6c9a5449091b55b97245914c3aa1e43b3cab9ec0f7a4fb5a2" . + "efe2b49b48fda0a5157959d6afbb63a98fdc35c6a976e17b3c5ce986440d1a38" . + "59f01f7e26ee852d3a0713b85d0dff99612ce1949222cf33dea0db10b4e2262d" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ac9f1a7079d057ecaf39742383a9f3f730945a5f7480e6925771167c06c0cf30" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "d5b7a47bbbd35126c7b240fd715acd05f6c14ef1413304d0a148c9edc6bc7181" . + "9021b01195fb624ed1d486c615bdb2572e514b0a88c937cccf3681afe631fd8e" . + . + "fb20e4eece48e390eda417c5481c7ca1ebf0260fdfe704c8d0fc6358dbe65c8f" . + "9fe82ebcb8b7c2ee51f7886096c6a88c87a0110fd94fbaea5e951ef740e8340c" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + "cabd3216d8a6997ed20e29a5a05fbe933ed4ee2f16ea5b0cb8b65f99d887eb9c" . + "fb20e4eece48e390eda417c5481c7ca1ebf0260fdfe704c8d0fc6358dbe65c8f" . + "859dd14f6d3730affbff084cb790ec1d073f773dfe24003fb502fd133add44c5" . + "47ffe97c9e345a52abb453e524c91eeef3cea3407d85f7ae6dc6cf847e1910e8" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "200600a123efb9a44c7399ed7acfa6ea7404c67a43f92db03f0998dbc2f3fce6" . + "200600a123efb9a44c7399ed7acfa6ea7404c67a43f92db03f0998dbc2f3fce6" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + "771745983f1dfafcca2c721548507a9495fef3d91b6f1e698219274f0f08896a" . + "7e463b568523581cb6302c5ec3ee0a3d08cf7dea521e42053a4995076856221a" . + . + "2ec2ec936a6eb0081bd281c040d733d3517296e074aab347ef62b9f981ef309a" . + "36bf31278721a18214b53ff5c2859346847df30327a0d8d5ed90995790f73f7f" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "9dcbda463f50cdb34c44230d6139a468d85cf28f4b865bfccb32abe747170e0c" . + "2f74e49a8f5a55d312a910003e23a55da3394706817d7d734705b57997a154d8" . + "55d3194252aaf6aab94c4429e1af1ba9999d4dcb7c4c2d6038be9bb4de8a5dfb" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b53f4220484f37f83a458874cc6bcb5494c7c82c4a51c943831f2a37506d649f" . + "b53f4220484f37f83a458874cc6bcb5494c7c82c4a51c943831f2a37506d649f" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + "c6a13981f6e5a3cab5e37c60771b47902a2b3525ae4d270f1188a379905dfdc2" . + "11851c0dcb159b53e58bb79b9c1a104cbd55692a7b2a6e5478c4df3bd41c109a" . + . + "ff321de7c7dcba08f002065e15445df19952f5bf68b3263cbfab06374e7cb50b" . + "3a9111798821b978c0c9da72fa87d7a4f32d0de33e6b8ab8f24359919a681084" . + "03286fc5d90ff0a77c44504b74ef5ed16ee30c266161c3758d29518e7b23618c" . + "5bf67521704918c10cc557b56e057f1c9e4361a11797f60c38c64ba304463b02" . + "a2bb9036248089c95fa8ea1abcf3d626398b4261864f76d22d8ab27412f8d598" . + "4b951b04a7a0b8e2287ab909dc366357307134f769a7cb2b921d5c10a2982523" . + "68d6ff75e33c2377c4fa1c8d239a04eb782b50b0d228d0af814b1e76472324f8" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "881cc9459937b904009287b5dd4cbbd770d685c2911f871a0bc5a37a16930189" . + "cd2bb3eee9449638073db0c9d42b19a9a2f1f2f4dfd7f40f30960cb4694e5b59" . + "3128d54f27d000b6d8e00894342704529972e959f6b97514b3fa8b3977d81195" . + "4867dbcae24b28d8db3da667acf8e4149ab4808485a19455cabf1ae1eaf621f6" . + "a636c660dba4f0081d6cd494519a1d22bc929eb643e79cbffaabf0ba68cf7ea6" . + . + "05a62061d45354f2699c477252d6ed0e493a80d1139ef9bebded8773f611fc78" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "05a62061d45354f2699c477252d6ed0e493a80d1139ef9bebded8773f611fc78" . + "fb05d17d5f9327a1618c57e0e43c0c062c8d0086b564262e66af059e2dff6380" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "920a0da91a95e993a9000011d501113e0ae0f41113cb93a88efcfe79be66e4bf" . + "920a0da91a95e993a9000011d501113e0ae0f41113cb93a88efcfe79be66e4bf" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "ed66e2e55d56157596964c68c852eedb9e91b11b7c7cfec1c23704054883030c" . + "258016c5cde2893c9025a89dd616a36bdb0997a23ed66319fba5f4871bc4d607" . + . + "24d26007281fc7be14ef06ced6c2047eb9e180d362a3d422ddcec36a5a1641e6" . + "e03288485ea0f47eb5fa2bc531934b7bb86c71ebcb876ac2d7433de0b6d89d1b" . + "368febc6c5e7967dc9023618e59f8d39bcae1ae98f0e5376d7b74522cdbf54f9" . + "a44baed6849f7f188bd4039e1b5d6cd557b22c5104318f68d3c741215273bf10" . + "d9cfca4ba4b953d390959fb3a6b8d727f1e094eecf5ae711158f03851c615c93" . + "ac7e6ffe621a5539ee4768a43beedeadcdeccd7e42f18cdf4dbf01943d8fea59" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a82622b841fcee6faac1309d9861e584c73f3a40d99e8aec0daa7a16d3433e44" . + "a82622b841fcee6faac1309d9861e584c73f3a40d99e8aec0daa7a16d3433e44" . + "0642e29eeb6a797495fb20746b516a7caad96093980edce76a298a26b57695e9" . + "7d46d1998487bcc1f95689168036a9516b644887fb56868fe73715a2f2e2dd71" . + "8d39f9120f2d84bc4dae561ae4e18c45323337edb50286ac033dc69a56e3c6e5" . + . + "92b2c1ff1fa63e0a7d1059798f7d81ca5a6a12d2756d9d501deb5dd7dd764eef" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "23c2a356eb7a9a1e7983bfa9c85697dea983fffdf34f03ff605be4676365d0e7" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "0a2f306cce88587fc0f73efa68a0ab86276535347c82b10ae12f763d585938d6" . + "d853b4feb263033311a16ae7a45ad0c4389db36c49d2391ee1de02152f81850f" . + "f069dcb5dc482551cf4005f4a8076993a445ef10adde5c864f224d1184c28505" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e5ef3d18c4a63c29c4e11733dfa424c00abafaad0eebc5083c05995e51ba986f" . + "e5ef3d18c4a63c29c4e11733dfa424c00abafaad0eebc5083c05995e51ba986f" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "f415f84d3b9fd32ef7dbadf05c0ea2f8039c46d611421b4c5e56fb3c9613b1ae" . + "babf534a7c2c8a757fbbb1b97149f2fa5c90dd8889ef6ed510e1b2ec6ecb543b" . + . + "3717a5db91ed4f29101f39a8a03edfaafab39550879b46fa67af4b0e7039e188" . + "897360122fe1e70594e6cc814ed559b9d1c6416ad9033ec781e7b0528e93bccf" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "8a50d4a791132e894bcf02628341ff315e8559abfc71674ca9a224ffe983d31d" . + "592725cad8e7aa21fa7b409f9e65e2e440ecf9b563bed3b25fc49d39e4711ba8" . + "76e31d4bd4796566954942d7c6c7722be98cbe455b7b36777e473a0b88a3497f" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "76daad66bbf5aaa0d81f5ce26324379b9ac4675f8be0a7e3bf515cbe6bccc0c7" . + "ec6149d256f84aaafacd3de65a89b814078dff59ab33c9fe1071c1b312ca9f80" . + "c1893a02f3b685f1f35081ac7038601a3adab551ac627c71bf12126c547c7fc3" . + "616fe4e07f0554772a290d409b7f0e29b6a4eea2840a3d2d38bfdcaa4aa4c187" . + "8ae0e5fe350876356d62a5ea64c63243228de2b764082e9a9d6ac09e23f04818" . + . + "dd6e643abbd65f3685e1c2026ada10b772155c936b2ba40000b53e7bdaa193fd" . + "6b6c2685b07ca49641564dcee993dc1ec414dfdc8e84142df04f72f7c6caf32f" . + "f640b3a7da52de9f89778eb6162b478b8ead5794b33dc10fbd208b25648c47de" . + "68867e5fcd8dc622fe1b395c89bc862dfe3f45605ba506029bedef59596b673b" . + "4838fc22ae575f759f1c5caadfe73c385227b6c5d91873f2351f1ffc3a2cd203" . + "d703eab1a9fef679a2973c878637c953c725bf55af5ad395920a3c94350d07a2" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "576179b7c9179a2577039196bfcd5fbfeb6e58e0aaba51610386a0b10ed04815" . + "610fa4713b2198bd99b1d95d912c5d859b5d3560919cea505af3b982e8ecc75d" . + "ee680c2301526d0d37e85fecc36382dae4e99b44de858b10c38950807361b2f0" . + "0273c3614a95bbdf91f7c29083f47d6f6cda6766ed702966126023ff1a40a773" . + "1eb74134ddbd8d6847251c63b5e804a6df70be5a1cd08fe87cd7b1dc0fed5cc0" . + . + "1f2e88e560d1ce76f87bc6a3bcda26828b3d0120316e5295847110ef0556c6fa" . + "6de39b8936364db73bf137f30a3eedd6d56d8d86aa327ef63fff06a5b04e9697" . + "04d9746daeb8bdf3ed98d1d7d090936d2e3aeb68ecdc5508f59c9ab615115749" . + "368febc6c5e7967dc9023618e59f8d39bcae1ae98f0e5376d7b74522cdbf54f9" . + "94f092ed78533ebd4dc6dbb74a42d668d3ec7067a5712d71b6dc808d83b31f66" . + "db8201ad89cfac853a4eba867f91718d278e7d3e793d5c6e2bc85c567dab989c" . + "07b0c977bc118c3b6f94921e2f9954607328f2454f7d00478a4c72c360edbcb1" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc56765c3cfe69f870e050008d759b8b0324a9553682ad9a0f8f2574be1dfc59" . + "cc56765c3cfe69f870e050008d759b8b0324a9553682ad9a0f8f2574be1dfc59" . + "214965bca2c51dbe2ac9dd53f90e6dff816bd9db379795cd37e2f63a69965b11" . + "40852cfbafc03013292e0d2770f0378e22c400401dc3e8b57d607b9ecdd01274" . + "af7a6e41f479a54de5dfa7d8a14e2a94e2a4b5a2945c478355551d4e29e2f4dd" . + . + "79b28850bd6a09a443ab459a735f53f5685b7f83bdd24d4ad086e3bf3b31e79e" . + "44825479896df593957bf0409ae04f33ff9c7387ad20e4b26d6b1500c9746c36" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "ced744e495a8c6d9fdcfde436b3b83faf40e7b98ad9bc2884a1db9e8251ee707" . + "a89654e05742feb323000ed406eaffcf7790e29f96f56e46459c3d669e5ce1f8" . + "2523a739264c7d7564850ec55c6494f2902562c3abe992ca057275ec226d7185" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95822a21d6097a68844f4aa5457d01634e52eeb5bc93a7be1c851c06e4eeec23" . + "95822a21d6097a68844f4aa5457d01634e52eeb5bc93a7be1c851c06e4eeec23" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "2f9a68ebbf8689edf17744e58872981330c50fbc7b91c9c4b9e2856006b3bb1f" . + "ddd67aa4dca06eba08d77ae64c669ce19249e360f5b2c862ab7df9ae1eba6082" . + . + "a687e2c5bcce8aa73c7e2134b6711f81d4f98588659ef195cf3010924853adc7" . + "8bcd2997de89cca0ea247b78889af5b49a4fee953bff0c2082c223d534af8e6e" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "681a3323fd2b890dc280433aa18a6414686a20de1b75d7ebb026bc2c3f3854d1" . + "cec1ad850472ce0f9850de684ce8386d349ceb9878467efcfabceec12a333984" . + "394606933af29a7bc610d8eb7bf9d457d0f5dbb61764004a6f3afee29ca89b27" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bf6e74c1329751634f448cf0f8e8e80b651d61f608aa2c4798ac1edb9dd90c45" . + "bf6e74c1329751634f448cf0f8e8e80b651d61f608aa2c4798ac1edb9dd90c45" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "ded8f79c61b7bd81349de57561c11a647609a668aeab33f8d1864a82d4e26649" . + "e624f39d1bc4fe37d882b4a09e752d108bd1296a3ed48b9f2fed913290f408f0" . + . + "f1df6ef2c9630ce9c10c664f7e3517dc3bac6475efc3aa26672ea49df8f9da0a" . + "0903c9defc195715ffeb77f57c4c4f5c008c21731d283c8248554dac00029919" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "57a3af173439052d0be4401f29357a48fff177f5bbab5d288c213a9a1a7de358" . + "429de57f399b08928cfeb5edeac70663a8ae75fc2a8cb5d2f8463b0c3efa2127" . + "0c07715eb9ce5ffa04d703370994a96f127ec0210c5d7a42958ad24b9534a7be" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "47954f0cde176a35d18f7eeba8e5f5a41de26f0ff2d569fe3fd765a748524f66" . + "47954f0cde176a35d18f7eeba8e5f5a41de26f0ff2d569fe3fd765a748524f66" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "f0c45c6c5e003cbd4b377495eea0af9d6de78e3d833451b5754e38041794ec80" . + "b2dbe2a822669d30cc11ab96acd9bf1a87056e9e7bbb35166ca3d230dc673932" . + . + "280ea9b1a1e2694aea85452bced1f59f7512331e0a900c79df55c489ca5e1f76" . + "304e4b988d05ceb007977502a6b5caaf19fd939bdac6e054f0f0d3c2d15e6db2" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "0dfcd94f95db97e36788f52b7ce425421dda810fdfafa224e86c15ffed21f18c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0ca31daad013f8784d8de49824238c7c3014a2c4a830fad3f0b2b020c0133955" . + "0ca31daad013f8784d8de49824238c7c3014a2c4a830fad3f0b2b020c0133955" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "af535619eb692ba6a40d5be19e6d7dfb57a49af2083a5fb1cef069b6989ba63c" . + "bc57f5734fbacf8f1667a21dbab3435299ac61da4d849cae571aa62daba7903b" . + . + "58c1e48f3a389a7095c4dafc9fd25db590167f3464466a89420f763a2979e2b0" . + "93b7da6409d907ae6925152c4137db4db36a1cb4cd8cb12ee496988ed060fe6e" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "0de2ab800a3901567fa05477a6e668181ff8e0cf775d0bddb89c18b87fbffc90" . + "1e0ebfb9a79d300da734242880cd92bc7baffc821358113dd3b225c88f27fca8" . + "0c07715eb9ce5ffa04d703370994a96f127ec0210c5d7a42958ad24b9534a7be" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2eeb1ed3d22a3c4cd17a5e96d5cd333fb795cb3735d4af85c5dc5303243e0095" . + "2eeb1ed3d22a3c4cd17a5e96d5cd333fb795cb3735d4af85c5dc5303243e0095" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "b5040b52e2aff52ed3c0286ae43ad8217d1fcc44a586ae1c05d6b4ca7b586d64" . + "149fb105cad14c6fa6b49c59e41091fedd844f94f15e4e151a7b1979fb70701a" . + . + "0cb0945f68450eb152ca5cb4cabdb29c2862363b4580d73a67122ff2449eb8bf" . + "4a0aa9385a430dd2c4830acb63b9662b854ddd8a092d1e6dd4b75729d866f543" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "5319cadafe5a615f7e6df1baf8a4a20ae04da9dcd6602d1d13dce5bc00485687" . + "1bc77711b990707a49dbd824925e240d3036293b9782a019eec36bad3818ecc6" . + "2b9dad7e3308225778e1a430552d4a790429438c651619f3f80c818755d1a325" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1d481dc49ba2c504af3e91c77850059c6cefa64f46e82eab41e858c074c13c63" . + "1d481dc49ba2c504af3e91c77850059c6cefa64f46e82eab41e858c074c13c63" . + "fdd85c032ec741696203fe736e1cdd700d32a14b4363f94e17223af8a25e42b2" . + "6b84ef5550f53d507b1a5e224515f78669acd0521eeb08a51d1ca2556d995b80" . + "4641c1b80f3dd7290bc6cfecefd1ce1e4238f04c6c0b4801a98f6d695aa17032" . + . + "88674a31cf78e56d89e5920726d87a918365cb5e02a7b3ebd30dc3ade668ea05" . + "ad2ae8a1b7f5105fb4aca9a4ba62f797c9b19015f31be3b79a577d1429dce2eb" . + "aaec19d0985e172d92de1bdd4e108cb5692aded3b3f598c18c824d142c27e3ed" . + "7660a1f55d599281eae759be71c2324775a4119e0dc8c9892cde23d13e152f47" . + . + "6fe4992506ab43ad387686293f106e8698b2bb9dbd93c637b3fe965f442f5fc3" . + "e2220daa869abe6bc3ed39b51584eb026671836ab5d0d533e32d50cddc8fb9d5" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4a03455a91c997d9b0c5efc35daed8047ebc849a3cb224ac17dc37c9a0e9abda" . + "c566f7401ec7540d5f7aed1a7feb60b53aeb5bfc63ea82613388dd5a1fff6025" . + "475dbcd873196880c90f192b2fbc2656bf0eeacf2964fc9c265d9ae7fe747fdb" . + "ba1d27756c8aa03e8e767c239f6e12efe951988b40c98e2f543c349284ddeba6" . + "cad90201c304044ae2eb3106c2826faad4e85258bb70f0378b8895a594b1982a" . + "36cafe36b06516b16332d0f01fcb53f2f1051ef437b4eb31c5a91aa24e7a74e8" . + "8a17454333c466cb65bdf81a07cd56ea4e60b94b5086290f7f86ef527cfac0d8" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "74b64cad6e923dffd1df723ac0e7d2883616a12c526a45d854ab850db443f395" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "2391e0eee3c9522bccf1cd72ae60845ead783c2eb86dbd3670a90f7ef977eddb" . + "6732c400f9f926b5fe3d33c7d9a7529ef170cba02f8c2a34d56af3fc1599a4be" . + "5751825747d4a4b56511836cb22022d918548b22c4e07470693b8902f08e26d6" . + "f779583233d015bf73ffd266da4b112dc8d9d2aa7a0033c5311f10b7f4a08aa1" . + "c18c34f247ce13d176fa10cb39e4d15d62d532270546492f0e4836166d441bb7" . + "c4999bd6fbecec826d86b632f5e95bace79028382ec881302f524e1c83006eae" . + "792a3c280f9c87be9ff598d30ff763fb932be72c0a45301623c7cfe49b0181e9" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "57f5680e46ed662e32d2dbaa40eab943df445299bc9011d7e54e8be2f652260f" . + "6e06efdc41171bb5a85b79c48d13d9acb5c9e67d37549c783caa6e6d84d32c6d" . + "41ea29b748651f152d61634f9bda104fea3812a9ef7b488db82f3ce947f00ebc" . + "2f080b8471ab77d4afff421544dcaf15a399cc2cc49192df8f8f2f4f6b0e921d" . + "98f59368c12e6b488053892f12b4b4f6050a9369ede35da90d87a43cd14be216" . + "bb8c51212cd8178652a6eb6901e3093db72cee91ce01ba238b96a6c2acbfc61f" . + "c72084e771626cfd77866558f34cbb33cf2093122db2a5334916e79755ce73be" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "2c6ab52a74fc9d17c16a5704116e4032a360ce8ef948df2304e8de77d2fccdcf" . + "66f08732194484e29af1dd2ff21a0c8a8c34a4b3b13d0557261458177623d948" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "93d74d5b40c6baa8c3fa81cd8093d4cedd0ebaad1ca603016c13fa6f272abc09" . + "2ca921985106140252544b6a2028c8e14458376cb005b32ecb7d77494f321b6d" . + "2f5bb29e64391c175c1f627b7f7f17a04f20f151e8f9ab2438dce2b5a2c4dfb1" . + "9dcbda463f50cdb34c44230d6139a468d85cf28f4b865bfccb32abe747170e0c" . + . + . + "7fa7280528615a38348154624cfa756538377bcc6609558a7da4654d82f97b2a" . + "5f336c25731f866b4fb9df2f9529e6ac7888cfc80e07ac1d942eec25a70e541e" . + "ba49813d0a281c869c4575ad88efd865bb20378bda00d01f9ff2785accf0deea" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "94ba9b3c86587de99ed0f45e0f6e35c85e8934e63af2fb7310b813070f7b1baa" . + "917ee9f0ee9fea4cd329b8d1a4d194b5ca10e1e693fab7ae13ea0c383b78eea0" . + "9dd66514c88b38c45b3f2edc9fafe44d39b23ce3554e5ac38795cc9bebeba61d" . + "2d6eed978added0979b521d62c92000534845a03657cdd16699e9c02f353a777" . + "764bd0fced229396c882809c7029cec286786ef2a8a72a1543df680fa1c0edc9" . + "49d6fcc0ccd21c12ac9cc801558eaf4099c6ba2049538f0daaf27d012498dc5e" . + "da51e7f1b2e5b4e106fd4044055559c90ebb7310477a82f15af07e9b5582d448" . + "4636a52fa2d046e3117f44f2c05964524db47e918c151d96f718b8a454e8ba11" . + "3e5305abf25b3c3492703b367c0b0872923646b6b2ad77f1c3662177ccbf9042" . + "a58e2bec1ac48fd842154664271db82215749540e3068f1b4f8b040966e78a11" . + "1e3d92a8b36aedf6d1271b26826f9c55056c54619eed7441060e5bb1084e6ef2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aba10709d4fab2fe074ddee0a8ad9a62b92e96485b9ce1b5edd5e2b71d2518db" . + "d71c13e6ab72d6a4bcfbe3c007d0baa1e6fc859336a74a602eaa9ba8493d482e" . + "be0a64522c4ef0b2ce7fd00353f52b90c71c2803aaae72b3eb2a0f1c0b002585" . + "d43b1b3a07a16f47003d87324e4985272fcdde1baece334dfb41e8dba09afb03" . + "1b4405144d4953cbb96c999a713bf79a096dc3ab146bc2099481858b3655b171" . + "54bb0f97161fb56035c8864d6d84d599755905fa59757cf6f3d85f520043106d" . + "7929a999692f6317be01302ea8737bae0f5ccf6e3e05b4890f415b382942706e" . + "6c89cd71bfe1c1c5b6b0cebaf57d64cfe17f32aaab91933df1a747c9d53fc1bb" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "51829a2c1454b8ba25036df21c8140d726361c8073f9176e34b3e773a38d7c7b" . + "1db19d220bb131856f21d6b4871cf14e72aa03a36da065c787583844a4df4531" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "9c3bc73fef601577dfdcc0debab06d9a701c7bd85b42ea94ade2bad376df56f7" . + "a84d39894749c7da16684b187d039a925497203e9506c91cc5158d30b0d6c636" . + "246268c9c7b739be3849a5c9ca99023713854acb2d942461dd01d218ee745989" . + "90bb4f1e97d22feacb7a146e098f2b086115db43f95e138245a7aa0df71d7ec5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "34751aa6962ccd9f11e3306a26203526a768c7298669097acbc849c48c5a7ab2" . + "34751aa6962ccd9f11e3306a26203526a768c7298669097acbc849c48c5a7ab2" . + "10ee811512879413e2cc432da46aed8bc0967f0c8eec00a0dfd50193e2947434" . + "490cfd1903627d5f62fddaf189d02bfe52eb2d3fa99a52e04c8fe0cf4951a5e6" . + "028024b50d2026d8160b2176435ea95df71081776167ff0169cae1d64cca44a1" . + "4c97d995a8ca9227724cb2d7aae0beeb90a5a6805c2934992b9d9667562ee650" . + "7de473debca44c11c87e5bcf99398ca3162d47dc82dd821f02687fbc96a6e89f" . + "8c1ade1d55cb83d451ef8aa12b3caf3ed3be84bb88b1b64f13b9b7662bd569bf" . + "ae4e8271efbfb864588988d6b6a515500e152728cdec6ca185e69bba4ade275f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "542486420aab57f893c9c03817cec874b836ea8cef5f88b56a1d3f7d632c0e57" . + "2a6629163c1fc054c4011d97406b0b7b848d5da78f70dfabac443e398bce22eb" . + "7d73496cc02b6f1026e459e1fb3f4a421861ee42e9fbad5268fbbd203777cdc5" . + "fd9db5f3c0a46a1e244f78208e1b178e726bfe6ef5a36b0ed4f7ab5dafbedfa4" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "d9cf6f67ddfce7165d374304b78922b70eee88dfdd11acdf9848668fb4429f20" . + "da25f24eb1a1bb394bb47777916e4291dddf2675c804048aff347edb3a6653f8" . + "84ccc81cde19eee60f2fb6697c96f582cbcfa262cb4c921c27a05fe16c159050" . + "eaa180e59a35f6420d617db1958de65afa491c8f040d4d17faf2767921fa4c57" . + . + . + . + . + "0ac3a27e7356bbef782597de9dd2aee2766b393a634b8e8be13a79119e7c5c2c" . + "066474f56f8039573432cc7a087e2557e5614efc573b76321d970b22fa03d65b" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1e5b11dd13d56482ce5c1cf4050e6dd30c0a387d17acc0f67062456a13403d10" . + "d5727fce17845583ad71f572330fc7a543ca4034450f67aca230099ddf4c70d4" . + "31c5b2f1408e6cd6a452f0a971c2c245842ca5c345f44705fe844cdf574c4320" . + "742215fb356433face2414cc35ed0ab7b0b460ca8ba42aba0ee9131361270b24" . + "75c81a3b0f7c8ef662a77b0e42e19650503f49f5eb96de25702607e91ea1c709" . + "aa8f3a0476ce762b6863fd49bd6544e0be28e8f571116b22d5d158ed62931ae6" . + "f172eea2050757e4158e3df6c775faadb5b3b77659a252f1e7fa663021cf0482" . + "c7dd20973993bc2b089ccbfa1192424e30a826309c696ebf8eb5166f0758a6c5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "88491fa0a2e891e7866fb31c49423652c57c1250f3e63cb79199ad835f48a76a" . + "a54ad70f31887c66fe2b760d20ddb1c51908560db54dd494802c8148033282ea" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "331554b34f2d12a55c08244497f93d9dbb3624c26c8c0e4423550eb9b348fa51" . + "e9364ed59ee2dd0e9fdceff32b733b4344ae58da999b18c2f2f1c74ffb7e870f" . + "b953c7ba4621566d05e7559aea5b01e37bf4fba7051c04f4ed9c99fea832f831" . + "6ae1ee70fbcc6b2d41ba6438a37547e22f387ba7d7c732c7ff66d5e5e785e398" . + "3a8e9ee2c0b15454ebc64fa21d1de340c54f3e9bb59ff18d86ed468b9d30c9e4" . + "9116aa7610d9428164f9cc07ae4b0299163c744821b1930a96fa62d134b5c26a" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5823b750e206a3809eab96d45f39ff3e93a8c661238a4ee7238673a59aec3069" . + "78c72c4248b563c9ff8ea4d4ec902cd550af0ed4f479bf1b4c6c549a1f814e44" . + "e5598ea55a4ca8a89885889103ed5cbef1ec9959610bad320474c49831735d93" . + "800bbf5a13537a3bbe4047d33e6214823358780e5e1b7713856a086c305fa2e0" . + "94f66e0cdecdb218cfab40050dee064d8dce5b1419f5c8901460ab3621641a1a" . + . + "db6d0dab236b3550a403ba2b00f534d4fde78929fd5f358af1e31c50d160d333" . + "90cfb4fac5e5b96df484d0fb41de523b8ad12a99b6de5fa29fcc394a11f803a0" . + "2567110cb06e83571f3462c7ca69b7df4ec5fa2671b8070754e237d3df13ca39" . + "1c72f8bbda201f8f7ddf1d7e6f8938e4c0f800c765478aa4c267199cb1664525" . + "60b9c924237bcd8fc1eb7301fc461939269091330308fafb5fba0abe6d581da2" . + "54be8f2705a093940ff53ff7d865d9fd91df429406ca9b55d96ada77cc4a05d5" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a05d2c6b708b1e0e1961842490beefebb4f65d3faedee9fc19175444ee26969" . + "a1274ac852bd711cb676b977600a1a8c8870084c14dbafcb74a4a6b5325cfa21" . + "7a3d8a11731c59c62d53a12acc0431a1bcc89febdf5e6e2a8412a9bde30ad7c6" . + "feff76527d78e50012a6f53741fb7606a9d6a372b35297d98e63149564dd4669" . + "3e1fb4019ffe570cad4e376b6dbd53332fe0f5109f63038791f1dbbbdc14f50c" . + . + "0b124e1051afcded7f54111e0fc0abcde8a2f772f8b61b4c5f364fc72805bd4c" . + "2d26fe25bdd7a1deef288ce5ebb0debf51e78dd9f997ca132957534423b19212" . + "9c9ff662894bfd22b3baa05deaae3fe257a0934caac586e322ae8e4a9f9b1629" . + "dd8d0c9abc63287c03b96999a14c594d5b8fb70e694ce6b81a5db56fa432384f" . + "abb0edfda9eb8417d7cd8363fb3536517ec8226e6ae58ecb0ecaeaef0ac5dce2" . + "1f067402bc01f105fad00b75152488dcf9cf545277dbeb98b771e5aed2366304" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "640f351c457b7ca92b64845b6a7f68e1d45f31e78ce9c8f57aaaf002d64c78ed" . + "ca86afafc28975ad402cf79a5012d90344639a462c8b7b6d0c7c5dd51eb3470a" . + "3ec3108d144b3c68b1a97d166abf68de7db2a02290309b7653e7c0afeff7b019" . + "cc65f901812dea92e1ee38acaa7cde04950e08cb3304897b41fe377cf71292fa" . + "aef5b17bebb5d27b309f4e530457ecff22c0dd551108bd2be3c7ef11061d1520" . + . + "5f4673076318a07f2ed5d5b0e802949d0d08445419d1b967c1469fba1d038e1d" . + "e46ba9882740282c40e91b230214a085076dbaccb5c3194e7ab01751a0554131" . + "f039000993cc05fea6752e906fd88782dbb9c1da5675686359303918a26d32a2" . + "9cf2aa62235885c1016aa11d160267ce812a1579a973d10f793141db0dc180fb" . + . + "411772f1f6beba2f0e04079cf6885f1c1d43ff0d03f7d523982b1b6cc3c2b45d" . + "35d675559cba63340ce4e95f21fec863618516be40b0e5a41b1144ed48a8efae" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "93eb74b5c6d73f963e600aeef99dc7c0a41f041c9015596370a6be65c266f3fe" . + "33a3cbd16ba2543bef91e2e949f6b9e7501b1e7349d8afaf2824653f095eaa1a" . + "a7e2e7705bb9249255f47ccf50927bdab86ad19a6d112d4c9b53451b14643926" . + . + "19f89a04f79a6e523e4d7a67859c458b3280b06dd6321dc134dc37b12afd44e7" . + "3bb81a1c15fed551db77b8930b9f47b1d3a611c7a0d408353f2a886bba218531" . + "a4228e6449a3ed551300981706c5b4d155409519e20b2aa4cf8be00b5be67361" . + "061c780ee97558d912961803f85758ccdca485d68ebf42a2aefc8275607b4ad6" . + "bdbeb35ab13343315cbdcb6d1c729a332c34a5607de54148d531515f8f318d98" . + "7178eed118fe391b1bde9f6be880480b65315e0ae285edf470220af9b5f3d0e6" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "29a25a6684327b3e7592ae96d69769e21a671c042a7ea17fdcc6ab33e14ed478" . + "f672f261af90a78e0016449201ab667cc3afd33b09d79e12979259ec6d9669bc" . + "fbb534d437bf5cdd0b384ed2f37ea71fb5dec8a39cf68f50249bfcacf05224a2" . + "4f47e6873506b7d4b64a28e874e20ee2770c1e97ceb8006a3f4dbb5f2e481c92" . + "32c3be11004d265d12654a3cff0b7675680de70ead0240672116f9a2a2148d7a" . + . + "474853047e7fd1cfc750a2fccd3a01cb3aeaa3ffdb804ac2b6480dacd7b73802" . + "2e922d379439d396a5dfe3829f4c4b6360aa4bde5af3217ebd8c3bf87ac71af7" . + "862427cbffea4e7cfbaf932361c7781c90c8e29402a483f0bae438f5949324dc" . + "d30ef6be83289795dd1f8c3cc93720f5aa03c56eb7f3bc31938d2ec632e4c7a6" . + "01c6472d385cf314d8854f4188e8357d6c0f306246ea680ce76049876008cd82" . + "1d8482eef86ad2f089e6b676f423b07d0792a7f3e6908698aeaada2e74dbc302" . + "1160f22dd432b06fd38bab0ba83467ce12b997d11e890694b9101733c1403295" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ce81b5ffe1508ff625b4cf78bdd542873b63b59b29c2b93841d0337f86c27501" . + "8c1c4e6713726ef053dc387ca39f3c0f14379cd1ea64f7c1dd7d090bf3dff4d7" . + "405373a6397bd3a4e3fc82f0629e56ab41ecfa87a9b5d65c54fd829b2bcf92bd" . + "e73822e6b14d4b80bbea6098ba98215f81548f2fd86d70e4d973e96646f9bf5a" . + "f7cb6a6d53325ab1eacefa50bbf69e05edec84725b3a5d347e5354b6ae4db656" . + . + "a8999dfc1764365f78db495d0e7355499ad08210ae0d3a969151ec4bdf96285d" . + "a6d05be9c69de00d05d4e84e3cd6602e59c50ff102533b919b073953b83ff6a2" . + "aaa2fa5035da10fe69443ec552a4bfa33fadeaff74ff35dc5a4807df3b901949" . + "b6bea5a8425755cec4ce7568c5c556d10340e54f379759fe77388b80254b46ec" . + "971c69d01f013c48eac3fbb3b3cfc836ceca1136b999ea9bd1881f97b2fd73e7" . + "382238739babb9223244ee5e8b1755a6402cda0a76b70fb0caf2e132fc0377d8" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7072c4fd52d210a201ae0d58cec59d00c3b7aaef6c93460f97d1d2d2703fbdf" . + "d1c1a932656fb49d0285088de9fdab790aebc229e617417daf872a6e52b4367a" . + "98d0e97a7592f9eeddb974153aeea14ff761873c8917f6385574de492480ec75" . + "2f3fe5e8e03834039e690ef9383fc47e1706dbd143575dab00d45b60cb6acda6" . + "3fcf8608a42b8bf932e4fad8a216b281a1cdbd3bfa8cf667b203575e400255fb" . + . + "f7801ae9e2b7e4fd8ff93f72b158d6717ee0c2361846ef527047e2d92f0782e2" . + "21e8864856ed6bfecab7dbc68db016a9d9bd9cf226884ce702e9c4a8cf300887" . + "edf21f35e4add4cb4683dd7ff4e6acb90dddcc5a9baafcb908021bd9e1216771" . + "d05a5505578b9bf48aa11e01ddaf9ca7b80313f9845841279509c69bd3e2d296" . + . + "281e61440cac2130b2dbd418eb8cef61e94fd4d6d63f0e46ad9fac8707873342" . + "5541adb304eb578cfb2251e3d096267f66f3c74a487eb06b6fb3b9fe5e5abd3f" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3a0e01d770d8964f53e74049186519ddcfa0a964b642eacdd2bfdfb9d8716b44" . + "c3fc9e657b1f0938ab2e5c5fce762017fa0c3c04f905546475857ffdde04a410" . + "c8331da732d66a87fd37dd41aafbe86c3df69ee4fc5ab42cb96ac0297f215f2d" . + "c9e8439f917faa306d4c404ef5dbaf0d96a38ed90fddcdf008d2c3736156d325" . + "e8b1a2de9a57d88de0083ccb4af26bcb36ed18be3e1bfdaa184a4408b5bb9201" . + . + "a7a85108c8f96f2f8b9dfcc67be2e0ad6cb31cf564900e5d185d686c1ace33b0" . + "3741031639cdecc23fe6ac428909fda0270627e66e071d434274520b64ea2f0a" . + "0fcc19c9f32b7d0ad5220c6637efaf430c6a792e84685925b0f62931e0341aaf" . + "cdd4faeec60ae12346b868e6fbf5e2f6e768bdaf6a068bbcb0d5f5bd4e2d5dfc" . + "83140ef76369bd9ee983e25802ecf240efdbde6f67b9d6e187d4d45c31bb8d28" . + "37e146a072bd017079a72a2ecc9953c51d997d53fb2064705926c35d192c2d13" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3dc63fea9ba56e33a3963869c50b38ff9e0088c2e4869069c033332f247bfac9" . + "5aeb81b698448b3fe0c79f2212ae39e061a509b3afbe154b284630aabd906b1a" . + "e5ed9c966618f9ebb695a21a7d19d3ba4726008b95f44793eeb135bd4332cd67" . + "57495f0770adafabccdbdea5427df7c4dd67a55dbed70f869ca9495a828cbc6f" . + "a8434dbc0034544a7858e177c6aba39bde5202df2e156eb0de310571e6d86e3a" . + . + "ca8d76c20d677f7b604a98d385bb00cab368478b1fec505701e4fecdce9c7348" . + "c723084392a4b7c51ef432ece9737e8c5804a477c8cdbfd32fe7d219e8bb2178" . + "8d874e51663853298f1d41d1169eeb25e788a5509845b87f87a5ddb6c8ca0673" . + "e26b27528a9b12d958731ef0d32360e3a6f1a9b723b5fccad495a28d7342eb31" . + . + "c3f048b100a78d49a85b35ef9dce4e659cfd167c318ef7f1d4db727292737f29" . + "659eb76fc84fe497abc1927f70f1d92c5578b8805ac090851e7862898c42eae4" . + "1484dbe7c869acf0dd80efcb3bad7a1dcd66675334a9a2c48a866c5e3778eb28" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8649e77d81dfbc4e05549c39350a5c55d5c8b74d5000796dfdc13cca6336c697" . + "1de7870a1ef1bf9f0312e1624d8ad08622e460011c1b2bcff22a471893cf833b" . + "4c5305a19e594c768721c08c3dfe8090d32a1fa11fe1715e6c38669965f8889d" . + "38551f6c9a9788ae24fd6efed1c4324875e798dd26eeb1928a8ee9eb58521aca" . + "204fe8944347e77f8c4299be7fc63e3287660415ce735191a56e3c7200f9c731" . + . + "b8eb745b41e8fd1faf17c9a89c08048a685cfd75f8205b024ac0ae6da978402e" . + "251de6cda72c17cf036a8a9ce4d9872148f0d742e84838cedb44117cf2f3f6f6" . + "18a919c3149d059d47d177039a15c13d5c74325e69964e958c20bbe26e8029d3" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + . + . + "fe0ae89b651c5a9a99275ff852eb23b09478bc85b7470184bf9090cb0156a340" . + "e80def42800db0ecd45704add5c1330c0ead8c69c0135ce28224a7484ad143fa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e4b9ead96f4100d3e9925dcdfdf1f76bbbadf85466f3249f18001c9226b3dde" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + "c7f1e9fb946ae4cd3288e9c7e95070e27a315edea35d80214a67cfb7234af10b" . + "7f4b543a9d79ded879eb14308189de0ead7b27e5b71445593cbf91e89093efa9" . + . + "77627bbc1e456f923122f8664cbf8023417709beb0d6376f71bc81aa15aafbca" . + "76db4c04714b8d468ef6017d6429e63ade50e9864a8a42ca53a7d1b08c25005f" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + . + "3f31e29e03799f8d013b6f9760095d41198e52bd1130f52026d75d78b1e727f0" . + "f41a586235404718a4974e3524e297d545b1c4d8cd9d3b5476e70d03f1b72ac9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c60473039fad2aec424a8599ff6db05aa000b65c4783907019ead0b4702508c4" . + "a362c9a1c026dfc747409b69b087e9d38364651bbb08edffb5722fbd7357d5d8" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "6a5dce69543abffa72ad7b985398a8f659280337b0ed694e51bb419011303a87" . + "e9d78131b70650d5da83b8ce066884c8dbbce8daa3c9adb87a8d2c1f8f3c1bec" . + . + "8865553b7f550ec8fdda197bcce858ba0ad11c35abfe52aa5b6d888a16fe3ee6" . + "7597c69b63063e39449e20bab6b351ab49ce1cd5b96bbe56e51259d517315aeb" . + "5cf40774b4dd5aa34c8e1f8e908e53a9d279dbf7c1ea28367604393788aaa061" . + "e88020e3aab3ca808ffd44b3f592241b4adb280eb93e0959d74d56f2f15b4bb1" . + "e34d2c937fc494fdd8562ff0f96095058a639159f04de8e7a9d133445b64b94f" . + "0cbdd9645de7614a7dc6344413a01959f753345960b3a92c47e9af8a787f0d93" . + "f8448e2f2dfc4c633402004fb0d8dbbd1e87a6f6ad3e113fa0aff6cdc06696ef" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "39ae02d7332501298ac46eb81aa7153da98e4a48e9ebc931b47e555d0f10ef16" . + "fb0d1def712794cf6ff540f684dbe8c4837507521877c50160f8772a72e59b43" . + "17745a515426841697251425c9c69b3da00eaa930034e1ed7b1ed9ba7d8bee72" . + "bb914c6fc9ba2c8632c111e951f684961409b7e690e5a491e42a99374154dbaf" . + "140a627fa3e117805b314ac245762bc39f55ba2fe951fd3e85e04754cc638a9b" . + . + "ec8b122ee2c82f5c8c2f2ab89a9b99a80e4ee5df93e8e9d512e0743270285b4a" . + "bd911dfabfc994683bf6995d8ab87100ee9fec09b6dba92b23185d0a72625d46" . + "24963959aad5c002c68dd8ed3c79ad907b2e323f39bf14a63dbfb9727d106111" . + "01bcba8e1c29a22aaf7d04e31a959b2d59cf9fc90df31cb2c15e743430b45bfa" . + "52321eff570d19523e9b6d5f4ec5a860ac6cb5d18ce8ada169fea5f1484f73d6" . + "d22e093ca88b0e4dfd8e27119273c524766e8205da74af769696cf3467fc5f8a" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "569519028dc55050bfcb992c3ef7f9794cc8f7dc6b2133b9c46f0d637124b582" . + "56e0d5cd5a31b5b463ff91d60bf96b5f9acad1e93f7d1ad888ffcaafaaf119cf" . + "eae641f1c1419f058c6687ae4681687d7c62263c7f1b3163c1b24691741965c9" . + "ecfbc78c761727ea63c6979f670eea8059fd2afed1e3623c5db21633f15dc15e" . + "adb44e488d49d4bcdd25db75a33d12f639edc8d9be8c2d527100c7cae8792ca8" . + . + "17b3542e2022cea1ccd404606758da35935a916639d0061aa40d60325d863f2e" . + "ee756ee629bee2d730702873cdf695e68fc99847dc033db94543e0d3a1cbcf39" . + "6c03987a8b35e51edcf449b7d1b7408e998f7acd9041298192850b0865090c38" . + "8907674f11336477cdae8575d49d6b0e0cd46ad9d37afd1249c649b7ac8a099a" . + "0e00a94899cf36c0b16b650e87ecc0048dcf43086585ea381750b0528cb68947" . + "edbd77bc5c876cd8bb689f7209f85609d10ba814e5281bc50c2caa903351c3f7" . + "fb3a871afc9946fbdae343353724141c4183542921ff007bd688b4789cc86ac8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a654c4c0142c238eb67ea1eef561503c784353a8e86be0f43bc98466925fc05a" . + "e9be1ea712e3c8afc53485df43877f8a1040dc69c5abc8a92e6f5e01ada647af" . + "5afd713cf1a971478fcaf058431a93e819ab348cd28416f7b13ba02e513f6280" . + "5a41542c7875fc8765f6038cdf0e5b6d6e0ee29c24a2ecea98e07d6b107be662" . + "f2a6dc2adf99ea57212e43d09047f1098306cfb42250392de869c9765dcbf045" . + . + "df4ab187b41ec14d074db30bec5f1b93f5f525492572c540b8af7b706588bfdb" . + "ca0855552cc09dd876f7d5dee758728e63c414b129880985df663ea45f1891b7" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "524d2c5e682dde20bcac56d86f0473fba1e135ab7006f9c85a547c19f204bdf1" . + "432be0a047f4088555948149028850870be822cc8f822899f873a2ad5ff639b2" . + "c312f3aa9028377ce077b7af6f2a6af3b6341f0893488939e703841bf5785015" . + "81c9217d92284ea0a9712e4adf2672bcc10daf3c8e78044e51d824f4af58e717" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7c02046c6e64801430faaf21824c7eda96ceddd75caedc769b654b4dedc5109f" . + "8e5abe1acdde068d30dea103c72d20ab9514145ec5d71590d22ab52dc11a270e" . + "73730b2bb0aead24790c4d64a461e44f584bb50cb1f818185860a15d5b32c6fd" . + "79936f386ee84ee89b9991a89faa2b1c87d43012aae10d68f88f3009303f2547" . + "56f344ae7a269ec80b3bff8ddd5389d926e3ff7f33f2d675f6ac42fd4361ca62" . + . + "546a90773e8472eb15425a26cda7e728b32a398c58954af2925b8eb5ded3467b" . + "3c8549b5846cdbfe08a8097f95f3193b1b26c771cc92262a643da77f515883b0" . + "e3d5b1d40ae5a3579a5561ce5f127e14c6598d303a06db516cfc64f29621bdbc" . + "16798b22bf7e638206abf81b48153125960be793e90e4c9023496c6ac5ac2851" . + . + "120d3ea0e9391acaae03d064a384ec48c829a8c8708a2f0a12666ba7cb3f500b" . + "c134b37359b42cbab2ba9eafd810990ec0a7f218d07041d1c03d50214cf7b134" . + "80a570e7161d3241caa1c5fb93e4bf8a5dddc015d79215b2adaa9fcceb5c1ad8" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "147b1688ee5cc58099454059b5ae61f263e3840d2355c3ef2e992a4041203e72" . + "267cf4ad12820fd7a2cef4cd4316120fb17ca1b3ac9a53a96e8953c9af8b857c" . + "88d9fb07dfc511129ec59049a13d6c65da58c6d64b3f7e9232ab3e4e03d52254" . + "4e6d9f6da2fb45455868b3649ec5460cc4c8d6f0701270faaa262c70592f54ab" . + "92bb3f165b7f9a4afa38e2e9cc3c9ffdee7456c9fb046225c849aa890a2659d4" . + . + "4202c224e5ae0bc1dd825fef1e72aefd761a45d4bd752c2cc763a63675ed216d" . + "b9ffdf11e2d4e49d9dae7b575501a7be94fac1a092b10f21efad2777d38c06cb" . + "bb10ac23deedee64d71db2eb12c9d0abec7008392ad35ffff806ab948fffcdc2" . + "670a6e0254b9f35663e3b5796762bd4e664456724ea7548a97c350576e7b3e12" . + . + "4c421a571d40cb63fe67fcabf6a5d702a92a4475883fa1a77744524af76caec2" . + "fbe5075413172354980b1c5802fb63cd416e721e399f7c5e24c5c19fb6635d67" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26d66829be6ab4a41a07d2d22465fb10381405162d0801c25939ec4c7af7f603" . + "26d66829be6ab4a41a07d2d22465fb10381405162d0801c25939ec4c7af7f603" . + "2a8c32c953202a402359e1c561bba97e3d776ab383a7fc93b0d5f2b2351dd6c8" . + "81b66277d0c84ad47ffbf50ec692247aea1182e9dca2c6298687418fba91101b" . + "42b8b68bb3b4a416b6f710e6973464ec3b56edeca77e75a38ba2449e2ffade28" . + . + "e6c1cd58de9ab33ed9ced31224387139fd6119decaa4193adab341b6d66bcb10" . + "8a54a6e3f0080d9fce0c12c7f9ada52d7b82ea287f4b04cdc3b82926c7b031d4" . + "6d7a24a6c634e35342c50266367fcd4d4c152df48d0d0f2613262c3eeb1b2e9f" . + "86b2d84338ebd5a589c512bebd329030659db84bd3ff0fa24dd810f21da88214" . + "751d3ae214a20d0fadce8050fd3137d286b445ec6795904885b464b1d0b4d338" . + "342a4b3af6605615dd84bc5bd2937e4c2e60b6c6a6163daba8396d272b2ea8c2" . + "1dfb275dc002587eadd76051646bc385760499a9c2a4f7e1cf1415975e80fe24" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "85e50060f94b2aafb504655d6e79f9c72264f8c8055cc1b13ceea92e7e990d1f" . + "69c90a787d347d1924cb151a6ef9c8624b99238b8849a1e4d2a64094dee5344f" . + "14836f6ae5c98ea3bbf13a38a77e27ea0df5f359d8986d2f29c4e9ed12cadf98" . + "50b0c22eaa8493c71c9d50d3b04b78496917f9bac2a594b7cb1626df9f2ee7d0" . + "17136e2efb32a598e887e1b9a8a84476893d108a2ca7e119eae90bf9c334963b" . + . + "1344037bc65698ed8e3e9baef0970ebf05c2105f5e450875d4a88cbc8fb608e8" . + "81de4cb0f8e1345b86ebfa596d980d350750eb37a2067e429e3c054f9f998025" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "29287da73218347a6915cdafce06cba61a82b131d4ade4174d34274183760a6c" . + "cddb70fbd7ed663f92c2ac510c118104016eb6d87fdfb24828d85a3a520b3ceb" . + "a72ea6c878a152756cdc9438832b766d40ffe9898bdee178cbb7a41f1b87c312" . + "17803ecbffcfee4c9243de762acfbb3684f2308ccdbd4a9291b37bdca74c51f7" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "493e8777ac1ab6fc24abe40d9024e26c1cbdac4a35e73d9e346bcfa605ce623b" . + "bfe23d4a94865d28d2c480243b2ba91e60d3bab643f0eb33b2c4a69e6b05fa1d" . + "e8fea482d774771ed604985f46b4926694f8d28d0e46febbdf329a3615cf5c98" . + "29b5ab1f3eef107f33c5c9a009fbe25e81c375d58796416da909f29903a65a16" . + "bd21613be8886b61cfdb437a86ff2ac8097024665e25026e7ee657f3feed151e" . + . + "d44d88dd32a254bf4b0bded0bc6673ea9304fb9b3e929ad3a9c7e7c050d93bf7" . + "786d5d2b735361f13fdf349caed7d235c2111b0f3370a8ab99d1bc97caeea9ea" . + "fb5c03d77e424d7d7bbe0e5015e06c072c87fd63c114e96c13f7850b83c1b7db" . + "5e61af98f8f14a58c5827f6b411e1718b1381fc3f482eb6ab5d4b7eabebee58c" . + . + "dd347659db6cc275c4b54bc76dd0ec2e04bebc798b451ff6f98c9d6bd6c187bd" . + "1b409b10dd687fdbb2d4b8edc8187aed48aec366531814524768ccdd224dcc82" . + "0463240ed2f8e8d822c321c19eb3d067bc056febe8e0c465c9dee5de7c220f61" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "06bdfa31831b184c916101399cdf65f5c34d20a7e521f2166163da3b6638199a" . + "e270e0a551ed585254c9b082f8bea5b7883d6376be4d32183fb7a739341c9184" . + "470a5789e1ff7f9c01854eb237cbe5920f9335a9e3a5192573a2d851ec85501a" . + "1be4c11d6c99aadddaf243322c08abc8730ff067912aa7622b910b01cd457a0f" . + "e5d20d8facdd86184e37e3a6a1e0f6dee4d62ca72f01517d7640a5261ba4ae54" . + . + "dddef5f8dcccdc4c200880cc23d43d1a9da5abd6c1f73b906786306a2e9a7faf" . + "0a2b8957e82d2e320d2cd778cbab2cf84f1f0cbc19e87ed876d7a744d8568905" . + "57e476262d6a5e92c2cdd09b246cc1d013da4fc731efb1ba18f5a9db3832c8bd" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + . + "4bc78e4bf33ea9e42954c7b3897a569439aaa4a4ebaf4742c9514bb2a56afafe" . + "401effbff07c2b2756de58561acb00a59ada93dc27bc96453f182b963e4360f0" . + "38bdeceecd4fbf1eccc4de7af03c1589b52fd7c9a3f06e14b9d03b4d81e1e171" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dad71494e0efdf12b76529e2eaf63ac9aae5451ae2e60da42224e6a72ad3fb4c" . + "66826e25ce7f8c7658126eeeb2845702468a9811186e0ba4d294ebff19697c37" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "54ed71613b069558a59d02431cb25ec34ab3a52155b3069d4faa6f5bc419b5a1" . + "8e907718e716074db2d097cbfed9c2724e2f0007935d430ee404aae40ef2ff30" . + . + "2de24cfd412d7c13b48fbb3f16faa7f278c1f89feaef99265d47c9c95a43aad8" . + "f5e540143e2e421e09e39c087e44de2653efe875dc88408c77c4480105c66659" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "aaac9df28212723f60ee0e0fc09fe7b61ac37657513a2b474138313d907aa646" . + "c9934f406b9e644deaff755ce9518329c08d3d18a3c8a0d89a9d012529957087" . + "48a9c1db0161e3e3cf9098411218eca127428ef1cfd4db089e7785519e7f8224" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0767529385d3859b4780180bd54c7abf7a685bacd577e02b2d0018a56fcfcc6" . + "f0767529385d3859b4780180bd54c7abf7a685bacd577e02b2d0018a56fcfcc6" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "4ddc6918ef8cdf86175aeeb2c7c7edb25f105a5959c038a6eba1556ca2466685" . + "569c386c88098d7ecf6fd66709b6a9f8bd59182773a47c9ff525f5dc833aecd2" . + . + "ef09205e51e0522a7e68998fbcad9035bb0e08963ccb9f9bc88963dd90295551" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "e221af795e3d619313cc0c6c8343d3ef38fac0f5bc66fd62a0bdafe0356462e2" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + . + "a5a19b25851df06aec4b3ede6c108589b8a2a0371e26fe4f8d6e8f86c60dbb04" . + "b9e4be2982bda799e9c32efb30b642ebcac78dd227bdfcf21e285cd605b49420" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c51889beeafdff11f0d2b80716a8550c9bee8f3d43300674efe3589f9814000b" . + "c51889beeafdff11f0d2b80716a8550c9bee8f3d43300674efe3589f9814000b" . + "e34bf98e97ae1f5fd3be2c39635a583ec96fbeb2c95bfdd16d126e4683e4418c" . + "e1c3e033875607a4586aa2647bc8e32cfba56ca032cb5dfeefe9d053c020d5fa" . + "afd4cc6ebf9366f76ec7c8cc3a6ffa7b7dab66dbe28d21b60fe9594c46c85f50" . + . + "02c2fe05c38ba711ec2a4374ce4572ad8477cc4478d572c6f894d5b86eb2ce4b" . + "8e8c5f5b933b5ef42575e6114ac39cfffd4efb07be305fe4723cd6afb9ba5628" . + "7ca3551ec7566658644f2bb04387edfb5c42a8d789dae3f3a3b15728d1c5b119" . + "5b767bdc607efea62b9b11d9442d5e0437817df1983a6814c6be6e2c3f5a634d" . + . + "fc9a4e21a0ddd09078f439a8ddbbc31ed00fb43120d575c6bb2aee9a361bb56f" . + "cb2c5970bb7366692820070b61f588dfa7473f27f22c049e9ae63f61c719107d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cfd1f554c168108e24af3be14fd08ac451da87454ddaad5468c0be806e3b4534" . + "34b1861dfb0ca412e98f4485c81007349e19f1211c44d7c0f10dd8e47b37c364" . + "7153e679c29755a9f5cfc1111811763a0b19ba14f3f740558a78c2ea05fc4c7e" . + "cb07b2ba06b413e88b08dd20f71f1b241e4f2efa51ca69e94037119cd78bb473" . + "3f2154668db7cf65d61e9d418b55d8e58fc6a65c8abb7536f0ef36f77355d2f9" . + . + "081293e501e422e4813ea4d8899aa9de9dd84e40122b97f9722bca8c2aed2988" . + "f62e5fce8695f8f534d6bdad2cdac14b00b0f0c62c4a3c8d50893944b97cafa6" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "72ca580519d446c2fac7f21cfd34ef1d83bb4d6ed0a98ff4d22455a5946e9672" . + "8e310c146f66c61ba2259f83a725af9a31be4cdaee3076eb77a14b4ce870a0b2" . + "e3235a470ca9cb39df059109d0c3716960ac1b947804bc44169a2a1229eefcb8" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8b74e490d1eb29e16ac3b219ebb6d9db91eb3028f71c44d812f0b0954b8b4e23" . + "8b74e490d1eb29e16ac3b219ebb6d9db91eb3028f71c44d812f0b0954b8b4e23" . + "3ec669316592a6296144c893ccadfbf56e4e9bc307f1681728481acbfd2ceb5a" . + "f95adad26dbd20502a39e20597f915b9a68bd0921a5986de60811b14461dcd16" . + "cd44336aad2595e923d3aef4ca2d64a64243146365b9881ba55480a6b5463644" . + . + "94698ff9acd3503736c9b025c3b90bd3a790a1114ae0672c529e1213d4891866" . + "11c94e758739a30ba680fe37ab738874c91524064cf861f7adba954ee421a959" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "0acbf2d73483a740cc3db137820fa72b01936b5f00deb9016e316e54fb933b67" . + "83d243dfabf85ba003018bb3dd462ecabc9d7ee066d90bdf980a7d046cb7a454" . + "0be02ecfa615869d12253b6830b68d8ee4f8dcfc2276e159f1762d53e04ac050" . + "2987d60f5affff382fac9dd72ba3d4933f5889654577f9351434d0d11d33cafc" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eac9d35e16c589dd034c4e9aa2cc069bdf9314fe89c6dea95f5a5f8a9717ef16" . + "a952ac24d75e2978d7b6305e6f9ad32cb7d2a2357cbaa409bc9cb83ec870a954" . + "1785031823e419352a6e5e2d0791c7b884ea9de133e219dc712a0597168c2f48" . + "f89623afeba84312a8ea74b66b425b6163a2dc52c8672071e888c57ea8d72b08" . + "523a0e8c954243b3eec4dc82ab683ce7dfb320051920d1d9225046275a1ef24d" . + . + "55ca63f79c7e626c9be78608ed994d605f8808eb85eda16433784c8dea70e551" . + "4dab9035d7c570126c6eb45eb5c35f23aa562649717cfdfb0204a91a6bf93d28" . + "20fe5012bb3730d4fcece058bf9723efbc6c6146bbf4caaadb3273bd1b130109" . + "d2fa325cf37ee91578b7ae8fa567b80f94332767b24cc2aad5b82c45d099cd2a" . + "56b1b62e6fdd1045996eddefdaed8e6976c6d785bbdc3f3edbc1797c73b0217a" . + "7536049d9ec7ec99db2aed5309d52deaa24ce513f79b2d6a2cde3e9062b0f02e" . + "6bdefe9cf42f1efa0821aaddc06acb84037a14918a51c17224430a9483471897" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "58a0973f7fb5c215f2d96807530e1db493a2085cdf5aaa4637929254f6f31ec5" . + "5ea5ed5dd80b4f2a08588ee51731d106bb57ea3aceb4705ace7f8b3aa61ff1b8" . + "8e5ac6ab96d18d386cd508e63e0de59feb5c77f40c78b0946de0be5432d5fb55" . + "dc136b68b084f09906b2f5fa236c1f55165aaea779aa32f28c097d1acaddfbb2" . + "fa5d4cb5efa83a7b397a122eee1f17c0ebd7845a791a21faebf08929073423bb" . + . + "49e25351c4aed6df312eff81fa865249cd9b967c1df9f399e4889077e9181be0" . + "23aad517b177a2c9ed01a4d28fb7f70347c977e13ab2f8d7e0da6c4f852675c7" . + "f9dc33a7676a7f3dc3e20e8746b727a9d85b46c8aa798e7af9736794f3f1b7f9" . + "ca617a499b0aa322c41d8bfaf66b4d928152d34828d51f7b98bd8fc98715e3a1" . + . + "07bac2563f9253616876ab6c54a4ac20e0c3f5fdcb6fbe5d2c4064e0ad794da1" . + "54b09c372ed1bad0c15c8e46079ead7b4bdabfcd48bddf32db441b989f934281" . + "1aed0a555088fc572a2ba268dcdd1332fa66296179f965bbdfae449763fc42f7" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b0992fcc6c0e1b03b39f98aa493c9f9180b5ef1c506add7a8f773f04c3b3c85a" . + "ea4e93236cabd7a70b545b7ea3f46d9506f7d528e74ea95bbf9a789f47d79a68" . + "320feb45f7c7256e8d9c81c0aee2ffd4cd01f231239b257f5849aca617490a74" . + "89d9eaa6db6df42e952ed31461bfa9d9fdc561c64f11c26ace77f0377bc36b67" . + "da0e876d8d820a50c7c8b367d8f364dc77712779560bbb8317c2b1ba568fe341" . + . + "b90610deb22c4ad052bb57bc9907345511475b32fe25967c5ec2d878875f6830" . + "82d38df02f109ffa80e21122847d512dc4850b847813d45ab5715b1d62d55727" . + "33e139c31f2a1a1b5a20ee2c560dd9e3b27c3c0fdfa2d12155fed5a3786cff4a" . + "dbe70f59a012fe295fb736ce59bc2c092063c005b3f4303ec1191528f61854f5" . + . + "0bb46d22b424c46a03ef0dc3ae84dd41dbe71cff7efbbeecf525d331374c102a" . + "dc8eba3d13ade8ef452934fcab2db8c559b796604b613c394fc0243d74d7ac5f" . + "18119c60050fa742497eaea189b242e7ab44165a9418e670710010cea20e10ba" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ef5ce1edd4d6b9fe164bca3096a0efa6e1b7e8b9f334de0507d29c8ac23e0439" . + "8c3d12db937ca931635ec74f01dd1ba1055ac0d0fb29f02708058e5ce7fd102e" . + "cf490ed93f12b09aaa46f5bb871092325b45776a02bb5f9ee74009b0d05ae99f" . + "ef0626c3cdd53c23680dc82ff506688c6a59f859ed36d1090470617e994fc4c7" . + "3a3e8849707a34b5d7d861642689b7f84da9b489ddb02d486ae7f31ba4f6c1c5" . + . + "d76f1f39bd96a1fb5e33b0a23653ca7847d2bf130d55a7b1727e76a5c9ca42d2" . + "b81d10434c6d83b8b54e2003be048208b44c974d1ecee009a7ff0ca69f3dd212" . + "b0d86e92dae4406c599754b16c8a0fa6877d50aef19c500a5d3b6039782a6358" . + "fe8697d785dd0f3cb69c3330b34648debe48b405f2e4ea43bb58f7070c9dff59" . + "433a5631d65e317995557c1a9de69294083d9ea9c4655d547228fb5cd374f396" . + "cc3a80685890800bba856ff500c180a51ac2d68873afb1a6629b816f20f85f94" . + "08fd16b6c499c837b7cb6198ac9d1cf994bc580470f51062d67ada492aff3f73" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b7b8a001ae625c37fc99a27bbe5aa4edc6cda5e30478199f08bb757c81b9175c" . + "429eec0ab81d05dbec6f30710a4d92dd48520253ca8e53f86e2c3f3dcddceb31" . + "281ba9f50de5275c695bcf14eb38d1bcc652d8beb1cde17960a420b32784711b" . + "11d7dcd6a99d5e52e3940a5f366ea9cc6a97ecd2752da7ea4c1360b5618d121d" . + "6b7f12d7ab147c4bd398eb30a47db80c853eed142ffd5aafece76ccc76e3086c" . + . + "e9abb2ae8b8537f8a05e8abedd4ad4bc4d457c04365e1c926f4b0fbdb6187b8e" . + "e9c4cf346ccce487dde0c207fb0682c405e52a5c2db256d6f92e9ec583c171ce" . + "5ea917b83529fd639d66ba53f1bb8da028bab43921880e75cc9b618507a77b4c" . + "959ae0f06de8ebb16e97280564a26a3b833b90d273f7e5c9dfe63cd476582ed9" . + "27c4647f1c9f99c993007acee2456e56c93b2c2b1ac6ff8cfc837f2de61b18c7" . + "3e6968f30239206d5347ad6b93897eee698396b77a3183db07d1169a45bcc8ed" . + "c9bcb48ebf4f026e566a0136fa7c9b7d981a4f566cdaa8e07aa374db1dd3a6c5" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "220d9fd433441d16b03b906b17c9db916bcfb325c0987c90c46b7d40ea40ebc0" . + "6e1d3b57bde2990d593fba68d256b92aa4f60f2d888c4bf581e1da7a2d2e570d" . + "c1d8d7031c4184e8dec23bc81babe9a1ac6faeb20e9a6221523852c4661acf0b" . + "2af6014a4420bed6888223d4e7ddd3c2c057c9faeb447786de87d9626023c149" . + "845fcf1b49cef20389f4142d7e324ed83f186149dedad9e81a695de5ec620c8b" . + . + "06b28b7e0d4c46dba7ce54dde19f69e45246ca9a56d5c7887f912aaf0d7978cf" . + "49c55cd09e97ca281d39ded7f32026e3441c753544dddd65fdfc8b6779c54681" . + "0bf935c5ae1706341c1d7cc462914b309de3dd341a10253c6dfa4de814ae2516" . + "dda11e667fcbd94f0ed9741574a80c7ba95dfc65855cc86c385fe651e929c718" . + "79b5d9c43382a0ae4c16ea6af967ab39e18536c5afda15ee3341e00d9b645f28" . + "778271c5e82d6cdaddd07f0afc48f035b933bed186cd4de65bdebfceb3fb7da7" . + "20c87f53723b619a2a0ca29f518795b09e4cd9d57a0d6bb5acb4bdc644b62780" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "edb2a3d612f6617ef37b6e0ca330eac4cca62d0f3076a983ca334464a8b5c086" . + "dbfd61fe661870b4dc319e167708785c1601777463872050439c047fab8a4d83" . + "cabd3216d8a6997ed20e29a5a05fbe933ed4ee2f16ea5b0cb8b65f99d887eb9c" . + "1821369b02a94b88fec728a66c6df169d3448da9fe89a91922a120b6f3b43732" . + "1b99c2fb853f72fa86d2cb3dd8d95e0a2dca5e77d87250e2cd304ea19b0660c9" . + . + "af73db8c92172590aed5166e9fdd659289d332e527e94763243713656c8fe7fd" . + "1719001710adc58aa0f0363392b58e3d9ab38cc4b16a7556d526f3e17c716ecf" . + "5a55fef917e57cf109ebe5a966bd97dbfd1f50b28c47c3b5e0c46b95efa48cc3" . + "005995449c83fd5ad0daeed00836cdc32972df0b21a51208cf5881722a36a166" . + . + "7acac0bbdd0af88168083871aa1334b6cbf0be45eb23c1494377b976bcbe63ab" . + "c5ef07f70a259119a4a639933356d301206cdb0f4034bb4a7cf918d4192e1f7e" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1334544876280a7e00cd46cf70346ee70f5a7d2c2bc1278191499e9ba1409311" . + "773393292bfbc7966413123469e385cbf357de31bcf1825afce87b22212423fe" . + "ac54b0a43b0a4ee62e3548ecf7d0022f56bc5b7865b24b7d0953cb69e03b8c67" . + "acb1165cf4657bb80af26861ea04bc528f18b20a91d74f514792e0996c427e61" . + "6c2d12e38b998d074e556cdeeb3b4b17977d8a401fe4689cf529a499c7f7cb79" . + . + "370945a269961d83c731ee868d3edc4c65f61960fdf7be196dc756dafec77c48" . + "a316becbdadd91a800ef261f1125cfe6dc1f406daf0b8701cb668eeddab4ee2a" . + "f6f550c1f196ed8ebf8ad744365bfa245179e65a3cac7aaa3d014e176f3edb57" . + "0642e29eeb6a797495fb20746b516a7caad96093980edce76a298a26b57695e9" . + "f761147f6fa42c8fdb500f8729ad3c3381b1d189326c7f895b26bbf37aace073" . + "32a3d7d4da343ccb3cfac0cfa15e5106eeeb5dab1aa5af56219f7157df85fc38" . + "80a8aaa9308052e3beb0473becc1603b9aa7afb7871a6785480cb9d5951344d0" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "436130d4cd5c3ba017ad2660910bb74b6eab5a77aca793e9b162d38ba9001d3a" . + "436130d4cd5c3ba017ad2660910bb74b6eab5a77aca793e9b162d38ba9001d3a" . + "5405bb419b1b7b154ec742af8acf48a40c7ddb4aef17141c114e8f6643efc41c" . + "b0e8d8a41bfb7a6a81a139aee66ea7cc0c855de2ad1c6d0da65c430aa73b7ebc" . + "36af71936fe39e93d383372d3af629022d36d6e3b6f5bdab71a56d89b5312ec4" . + . + "f29277ae24e18f708f675249a5f291d9421853b4ed47343cfda880c89b7b82b9" . + "40127899f18246490e67046cae628fe4d48bb37f6ccc4f3796a6f8bba0463a20" . + "559134c86aca986535242ef39e235c6be2b2117ecc1a37b35611ad168b99e6f2" . + "85946c60a7916623d85fed18816242a29f204a177d254c5afcd825b95074b01d" . + "270efffe218241151f49c384222314065bf41af2e9c9ee9de49855cceee2ffe3" . + "add0bb3f69b94f660fdb09d11636a083b40946099350dc52eff6ffeba81cba7e" . + "43202b687d07721b3a7cd4c1fb2e63d0e44f44ff4caee881b4c67d22306173a1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2607e61a9be009f10f4f8b95bb65fa1aa9a153ddaa7a1df3ad6d7d1ec23413af" . + "cbf4c0ae64f54292420569ae760e5655a68dd5c78d16b839c0d753aa2b8d0e38" . + "a2fc4fbb9b8f8d659236982c857612d071275e55cef88cb9957a9cfed089c2a6" . + "b8dfb4c9f27c22b983aaaa30d8a1ba794296d4970bcc09bfbcb04a809172dddb" . + "05689d9f3e598d1df854983184772f7d2ad2dfba1e56546ceeb04366b1265533" . + . + "61e6245531a217310e7164185de9be6267280da66d373e5573c703675e24b195" . + "8dc14b7c9b9b7362ae209e7f46bab29041c6bcb0b7ca911ec1bc7c440db18f76" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "17a411cbdbd3a325bcf1bbef872377b2ffb3db7c3da40b67412a5f31b86b33f0" . + "6c4fe0ce15431b82580b4c19449d4e2501e4286defb45c75893a3c4a41119c5f" . + "5a5b139fd6c200d1ecabb403b1a32a7f6458493483baa972d6d462b3d0218750" . + "23ab04c4cd33a3ebbf3955faee42d5193f86570aa217295df8266ddc4555038b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5a332431412a5927e65ba86e4f8dd926af3e9f3b613aa941f7469476aee88842" . + "bdb321aa757e9e6483f23153a98b4bce2e07a20a17455a40bf18b5f31c827ace" . + "b5b650035c443144f0c87ae76d2704de2e82db5ebafa1b158735862f87067a5f" . + "fb10f2929a961d9fe1f57734c9021c334a60a55221ffef03c1502fb93b03afba" . + "6e6b8acf955e43cfeb9b39dce374cbd43f6f720c6dad0a6968f85cc0e20029bd" . + . + "43beaba6ef9a179f70aac37c88b6f41c2381df857ff064912c6c15822c4aa716" . + "37fb6bd81ced049ea6dc18508bb9e44692c3424546f5f38f1f713127ffc1fc90" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "4b8af33ffaef6fd60642ad32e0b38edb8384283f60d27a5f4f9c33d1adf8f154" . + "0fcf643c9b32be6f84a3a738f348422e477c12a7895bb28cabf343c1243558be" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "323be6f7fd3a54dc5db52e29e84911658c1f3d5234c37e8ddbdbc612fd8a41f0" . + "323be6f7fd3a54dc5db52e29e84911658c1f3d5234c37e8ddbdbc612fd8a41f0" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "738d3a227c9e8b5803d1fb6c835b9bbe8fa458c40e0784b750f304a78c439e4f" . + "e1af11b929b3196a3fce7247430953e14f8ba178fdff31d867f9ecece9d779d8" . + . + "ba0817788f5b130ad9b6345a879256f3282bcb7232a352fcaea43306e1f1b405" . + "1e5a12adb092837d817473330eea222514ed4865398f26645898b9b4c0b8988d" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + "2b1c812cfebba960491dff26cc0178cf4e6ff7e482f42015ec273413d54677e9" . + "e23b2021103c0d0029bf30982dce6f8bf9148f5c1305734d0c3aabb38b69627c" . + "62800894257999a71af1633a9fec6c4e7ae5dd4410e81c19f432317cabc03e5e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6b2ed1981280b2528fad56d4d236dc8140dd8ecfbf71023411964d41a56ab9d4" . + "6b2ed1981280b2528fad56d4d236dc8140dd8ecfbf71023411964d41a56ab9d4" . + "bb1e6a7e2aed004a12a264bff6a8bf852a5922136e4b11d90bad4cd7da812ab9" . + "8dac65d930ee5ee9cf1a518866632c3d257b3a2697ce865ab644aadff0a26ab6" . + "2b8d375b70249b63a73ba6583873325e25ce4e98776e5f37e9f8a123bc2c324b" . + . + "c663051c550f4a06a84c57cab2f928544693dadbbc3629717e01bd8d0183cfcf" . + "a7751983c6ea006e960e73c345a792a10585fc09b4355efafff7591ba5c01352" . + "ebc726403a7ebaa044a9be5cc4396be0c78551e95b4825ac6cd2bf0992561ad2" . + "b2397986f0f608f9db7a3af3f4dceadd21c48e7fe1f870fe3151dd1cf22c01f6" . + . + "e97985f2601aa9a4eb9dd8c54b8b1bf1001b7f881f4d2bc9a9a69f8ddd061428" . + "74994b1accf633d906f1082e6ff9ad553d2960f9fda1031e4500a0d100ab8d96" . + "89a0040fd0629085262502935cfb75d5234e1c3b2ebdd8e53f94f2e89928452b" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "54bed5e5b8e39c30dd5944dce442945f81f4f38c14e52697c074cf7921bd94af" . + "768062cdf2a48cefc803b632af5f2cf3bb9ec9ed2752b46ea5a2aff02f7914c4" . + "89d8004498a09f055ec1b90a9a7f4fdb11eb4d70483fca8b4fc20ecebeedb16d" . + "4cefd3800b61742336c7c52dc3f0e8a0eaf87510cc2b3826d8e5df39042b1fcd" . + "6bfc9950161ca6ec0b24963cbcf4a22c9dd0ec8702c66829e0e84635b9887d56" . + . + "29ee1a3f1a7197b4c6743f549ae1f2484df814bd938f256507e4327338e3dd2e" . + "c1556f24f77254726dea79230da5b0037299b54d13819d88e1daf908ae89dca5" . + "cb9676d927dda7e9ffe88601b945b9d9723c034f549cf722a246f185ab7e8753" . + "0d54bc3818d44994b97d7fc8040d3036f48ff6b036712dd200afd4d474a2cea4" . + . + "61bacfc21ba3ea4ff062d61bae03757d9d334e1f69366446c22075bfa999e348" . + "fe85fdda0f5cd8666135719ede8e99d5044d86063bdd6c3b9cd9b9a8bf322479" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc8b4a0afb52d29f33cbe62d0cc9c53e3c2aa6cf3321a013c8fc138f10bc78ad" . + "f5ea45a7287fe9c08d747742dd453d9c6920b416bc63401d9e17733e8dfeb89d" . + "b64ad35b3aec01c98616c0fa657630f8f5ee30cae08d55fc8d70f2ca14b045a2" . + . + "bbd22fc311067880e70ce6331fcb9fc8985d2e5550de31faae923f673fc9de57" . + "077433ac10eeaefad38384c2303bf7fd4e6dda062bc66d4b251be6848ed89c8b" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "f1100932b74d63e1dd6140ddb05e7c66316341ce1cbcba0ce02e38ab4d10d795" . + . + . + . + "317960506b979e6fe36e3b588e41ccd0912ca22f39cdb7d35d371d5b57e45704" . + "49b79d974825ecec9cb0ba8a99641a683a63254c44fda68666998433d4b7442c" . + "d01814ab7cbdd9f212885bffb3a74f3b82c724dec3fa6af82cf7449d12c36d95" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3d3d5ea6b6ed0377d40a04f7c2536de691a920b5d782b89186f89382ec63fa70" . + "aeacea9f15016161cdd0de2db2c4e4a59b697fa85e21b53277270af6d5601ef5" . + "b3756a2be578f244d6004a10a41c9e87a209e367ecacba7a9e49f9e0bf4b5f68" . + "f1b150846cfc2f3d1f23dcf2cf73c5e73ea9d070341ec9e26178418fa49b3988" . + "9f67755125f106353db7ccd1abc5097b996852c0c222d5524f87efcb03b37619" . + "e4ed7a81ecaf11df8727cc613dc083ecefe296ba429e7599f0a833952975d2f9" . + "7eeb24f51fe01a99030c51338d947b9307541e7c71bccc910ce49162a339b024" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "f07c0c44006a50d771175285afd90f544172480c0f6e5eb7edf233bff06d5ae4" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "Problematic Triple" . + "d55ca36d90d01466691f9b9d11332e21b18a4dfae5a12f3950805958769624c1" . + "d5ee1d44d6d5fbdead8de3b65f8b284b1e5607a14291426b5dcfe68b1cd6b766" . + "c821dc4f278ff7de133ced545633fd9da4f261fa57268a49b6fe5ac828ecd69b" . + . + . + "c16d033f75d7e9638815e5d705d9396beb82d1141a232594cc6d641c2d1b5c23" . + "b7eed6a15be056bf4ae79ca24246d73bfe28804704beb3accc5661f277600857" . + "9b79e46692788fed66bb45a47d07014dacc260a1ab4e40eb654ec9c23ae17d3c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53e3d5a80c0920fe30cdcb30e117582dbea496079073ea5310564b9d604a7fbc" . + "259ce079d0ceac95c4994e1cb858c4859f60fb08ef27f2b699120642643774f8" . + "d5db3a376ffde64d8e857a4a5b23215dd3947b3108028bf2b6f54c9214fa61d6" . + "472d8d366be509f8d43527fdbb8a3c9b1dea14b084704f241733ada87d5a9271" . + "75884174c85725ef2459aff0871a55079a7c4f556387d96e4f14e03ac7c70bda" . + "89a6d988e03601a3cd6068d5dd42ba5d88882a9f7105481eefc9c1a9f5cf0f53" . + "46f745c660cbb8c0c0a91f430acf3b47422c58d50dff6bddaa8f201d2ca3931e" . + "eba5cb096eaa397705379dd64941b415d24ce83cc757bc5a53f9ec17bd9d8364" . + "97136294d5085fed96e8f8ed4f81b9ed6fd8d1319ff314028db448edc0407b6a" . + "96f23c4dcaad4083330fbd86ee27a08a8d2ce4776a17395f373bb1bfd6275a7b" . + "e9b05f81202620ef203fa3268b5b57c5771c787acdf711c8521401a8c5a6dae2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "296be7ba8f1f685c1125e9051bb41285be90304d65f9a522c32ec9b87fccec59" . + "4106eb1454ae5053ab7591ec9731882e9e7afeefe1a94faf9140f23161427ce5" . + "6944565667ca9ddc2c3cec657cb809645687e18fde30c49dbf8d65a48183c551" . + "75b4af840770c10eff382de53363bdc7268325aad1abceba99d7cb4abefe7225" . + "702f2a22deb8bb61931cadc6a08c8884eff13e84eaeddfab5eb797234cf19cad" . + "0c94cd8500c74d4dfd4d562b9218d4ab3179b2e34f5573997e0abd870b955e9f" . + "071174e6059bb2475d514f97e6598eb559277864f5dd82b8f5f07596e020a822" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "15978d8bdc408a5a241b58291b67b13e66745f19a1213c8cad6a8d15fc666451" . + "67493eef14f022eb26c8a335ca3b93b23588839c1e6d617c01f45e21b73434e6" . + "3c6efd43c764c68080d83be47a6a654776f5b809cfdfc574f4ebf137f59977be" . + "b8ce3c2ed9adaf4e57421bf8b32f85a41e6ec0716c1befee98cff395c2a54128" . + . + "723ddc20a42139c3d111553287b305a0d7156a65c404d8d40688487ba834a3e8" . + "2d7fb9066e2c12f0301c49ce1cf1742a7f8531da61a2050e10e0ad544dced31f" . + "8ed2a5d69609baf2a62bacfdf07b7cc0e36d292f31ba59df00b462eb3223da70" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bd9013bf8d6d52e2daf618e7312710d55624370e69459aa68536e70ab6a6458f" . + "a99843250fa5ebf5831c36d1849740ff9363a543121144cb81c798fe4179cbef" . + "6d3fb7a725b89de5d889801a69198875d2437217bfe851883af42ea3423f5efc" . + "18454e23f5611151e9ddef98f3def10253c49b37de1d5ce277f7648512a1ecfb" . + "2dfb12f770bdf03e69d02e2ee2fefe550a3dc66a0af904f86bfaa02cc9c74fc2" . + . + "2508e0a599d7794e9c0e16b6081275571744ecf8080b1c8b15b9ec3fa74dd107" . + "a2d5b4212cd52c273c0b44ca90b486d189a6cbca9c1165412e2dcd7b5ec31aaf" . + "fdf2a7ba84030f74258631dccc859548af074636b8fccd0159b6e3d37e8f6cb6" . + "ce59e5ce644ba82077ec26d854efb99d5802f9998a07cdfc1afaa9dc260fd2b0" . + . + "faf5e9c2594abdccd44895b41e828f94916a0c4d12898fff750a75e2946bc577" . + "0b2427acbda7a99cc912016b598075081354c552a0b5fb3f8d8581805168e347" . + "dd431ec08c0a889f7182ca4d68f75942b1788f81ea8b4877385b40c383f9c769" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dfdecc34a24c468d48527d697f09dfa3b7033d570b5566822d3cd1166df8f1c0" . + "1401e3c63b6e174129d63dc8f2f73992fec5314df664b151a4e23e1aa7c825f6" . + "b56359fddbb80df53b6ff64f973e3875c73b91e1c1919d9b86796f2347e2f55a" . + "8400e5a1a9a561f67110789e6ff661abcd60d56f89b707c263f75698b082d682" . + "e85a19093552d008a6ccbc0079987cd13f4f831894681e443821581b25e3de81" . + . + "8f667a4382573c32b94747044b0c78c114c5768ea68f341341284b5de871ed91" . + "ef6e47ec70293209297f4a7a3918a292acb6411b9bb49d0b3c1aec3b8043a984" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "fc854eadf8222acb22df04aee8155b15e01b339da4b027aabc27cc6f32dabed8" . + "80765037792322747383689a1e6f82695ee7b7e5426124f6e2b46226c2ffc1fb" . + "6cfecd1ffd3d591b20d170565701a2cf0c46ddc550cb73e11d4175814b2521b8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da69512f8c03b0a360e184777a5687878622a0fc84f114aa9520d94ca037e324" . + "da69512f8c03b0a360e184777a5687878622a0fc84f114aa9520d94ca037e324" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "1213c49fd579011292bc1a8975f64219892b61b36a723425b0c62e1ea1c685d6" . + "28dfac82bd65ec486db0e8de0b5d5164112566d35e526447c2861b803e3dbff2" . + . + "36865cea2b7ace1b480ae4367238e8992ee7f89e4cc9ccfeadd2f8d308a1df34" . + "2ad53bd7f5c3afd363d608ef9292d8160e2c50b52051ba2df9794ca8f9b2d38c" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "36865cea2b7ace1b480ae4367238e8992ee7f89e4cc9ccfeadd2f8d308a1df34" . + "86ffe875b88a6ab85f7d402ea30b9add5898a28408257c5b0e6c2c0aae946e18" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "71da32d485abbcd56d5cb3e709b976370b23308abc0155d1a5699907cc0f0b94" . + "71da32d485abbcd56d5cb3e709b976370b23308abc0155d1a5699907cc0f0b94" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "0f8c67b552f395be6b162f4f42a8718eb3d7a6c2f754ec910f15c587f2b08359" . + "f65077aa7723b7934bef3b69ca82128f7e7b730fb536d17d1e9c3ad46c0af223" . + . + "5382fb2098317697caab3b0a51b1fa46fa5775697e4264154b0b3a0fdbbea1b0" . + "27d13573f53fbb2755a575175581e5c1d792209e17a00d5cb6155f7ed533012d" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "067228384bbe28af84f3ca5b8e8bd8241af5d4178ea00f46f5d06a9f0682af5d" . + . + "723ef2d3ab8ad8b87654d38069aea007c486336f352fc331be26d0e98185632f" . + "51270bf98d480b7f12fe882310fd7877fa2cc08529947189cdfc8c5b7fd980fb" . + "725f5e1935868bbe0e279480132538dbc6bb227d7efc4e96d749b46c18d2bda2" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8cd9d270cb92d6f66d33f1ffd626b515fe57fc7d75e3bdc29a7bc336a9a01628" . + "8cd9d270cb92d6f66d33f1ffd626b515fe57fc7d75e3bdc29a7bc336a9a01628" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + "63c23b8e013729db51f58de09a41925d266e47b6be2da4d9ec6db79c8c01360e" . + "d8a5d1d4640c59e93480d25aef7faea60c769ddd2f836eff90d1826cab3d2ec2" . + . + "e4cf0531b297edc8566626d92332f3ef07f6acd6f6ccc4e7a57ea4459a4605f4" . + "e117c0444487d8046444f8a45161c1a0f97511f50c3f26b02f10e20152b16fd1" . + "2d985c9cee3afc126ff8fe1f1f73b643411c21411891f72d0701185a80cc67f2" . + "50886eed063be0c10552607f9cf8de338036cb27a4eaee93f2c561285473b447" . + "07e65362c8ee012fd1411eebe48382db2f4fdaae9633642bb4359b1819443bf4" . + "e7812526e0935322fbb8c4f2b8bc9306536133b488192fc10a4a7878c62916d3" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "837f9178c67e0a640c86e9928d0f6435a9ef0525b943d2a032ef682c8c3b68f2" . + "8d763cfef00782182cf5f373ba128b0d5e47965080a52c21eb1e1e908a7f77ee" . + "1db3a28a433590059bd6e95fdf9b8acd48257c67d795a00bf050330206c917d9" . + "184604af6720e0c6c21aebf5cac4964849bef7cd6e159a581c0c36a6f28bb0cc" . + "681702c951098889aca8797e5a65de198f55b91fd553c669806bb1d977c7230d" . + . + "4251e9ef3a243587e835101b64435cead70a5a9f7ecdf97534921c1d90f471b8" . + "fc0303862b7af8dc5848b088f55ff4b69611db4765247fdadbc786f6f2cf56ce" . + "786ffd7081ceae45ad732928c8f25c8136f1a0716ea608adbb0e0099ad57ed22" . + "bc90cd3a568d440fd0706f77b1399ebd848016dd5852fdcf41203eaa587de582" . + "6bd2b88a4a3e752dd1efd4f784fd31c30029c5a3c01870e7d9c2f4f201c9b224" . + "868c3f1edc1c3fee247322c46f44412c9a5d120fbfe42934926783f4e3494510" . + "8440f3ef5730102f6ed077b4f195011a0786118ec78ac02b46ab0d5c03d93bcf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c3675d4c10313ce6b50c11ebbba116d6f0f804c5a7c22c4f1ca721f01c71b802" . + "be88a678ef359169c483e19079d7b55ced98d0cb627198a5229402e2a0e05edc" . + "5860d023dab81e67245ee4da76f06870555c7b7268c9baeb997b1a2fd7a25777" . + "b287a510cce592784c83ee776fc44740938ffcb49560b4ce82f8bf7196047fd7" . + "c366e710ae4f7a5bc7c18330553014f28281cd8b6ba18070d6c73f91f2682519" . + . + "d535c59932454d13f5faed9a2a90b753700dc8aeddde1a19f35966473f65cd38" . + "0fd8944a99bcc4fc4c61852b7a4ca9134139bd038a36466c528cd5ef710da7db" . + "1f20e81fddb6de16f37902eb48ec06c418507b81978775c40fbb63ff98367261" . + "58b346753519e89af7250b3562edb0dab732783b5903e4747ba430988735c520" . + "05c149fb2b2a14437ecdd6397dd6017d5f62ffcf86d3f5d4148539209aa2967c" . + "40f7bb37680e0482b9e635556f5ac9ce137126e61cd5affe6d3f5ecbdf4aaadf" . + "65a090de28d310117fab3aea91edbe7ae0ff5d75cda87a0c3c14e777993fe150" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0dbd6285b153e689139cb83aac8652a8dcf624556a86720d2b8b358f4ea54b99" . + "2e7b5c63ea73850cc1bfe54fc385486d04f18768efce4abe0b9a7bf1231eaad4" . + "8c4c96865d034eb7359640b2d3f920bab4805f7528d2ea4cd5978d301b030eae" . + "38b7a3353036b277dd631dae0bdcba9a275f8d05b38394e8d6bd7d5a3387c62b" . + "5f680484f119714ce432eef6546e8fc381955c97606c687c471675c524eb0a27" . + . + "94efb82205834ccfc68a7d55e6b842cc4315041d53ab7a77396fb9891506dab1" . + "a444e02e6d5a4ccedac3c57ba4fb8df4e0f22ad7e85613c038f00872c4ef6b91" . + "5e2aeadb587dc88db24a593c90de8f30590e972f42f0d52f86f4d5b120038cc4" . + "9cdc0c0ac68a154f1fabb593bd636c50447606b005696815ba856c0d57316f69" . + "fc854eadf8222acb22df04aee8155b15e01b339da4b027aabc27cc6f32dabed8" . + "642e025df97e623ff3526cd60e48804b161ef0b7301346306bd24a6f5096a55d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad314a1997964b7756de049ec03a0a74eec03bef224533ab4fb87196a41b0a61" . + "ad314a1997964b7756de049ec03a0a74eec03bef224533ab4fb87196a41b0a61" . + "360922447e0d02cae72a2a9add6d0f93f402b72a3b317dc7755ff79df5710833" . + "7e8aa2ae6340b3ac147e6bf96cc391db0ab6c42570c339d00846358bae9555b6" . + "7c254c94d0adc4875934610c3aa731a0f31f1d7c903815d86cd464ce9ed03da0" . + . + "46d7bbee71ccd50143dcafa74bfa3c2f89c5335bbb3046ad41203859cfcab2ea" . + "11feaf4662cb10854e9a8093a8f6491f9c12baa0137133eb83b2044120886240" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "3108ea50e351957bf4fb5eb0a66011a824403be783bc16002cfe151ebd011b77" . + "c0f63e5a1bb79e11db951272b198366b0174cc9123aa9fbeb26b84182877ee57" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "32a040979470a428811af064a16eb71b8ec4fb484b2606366865ec3968f141e9" . + "32a040979470a428811af064a16eb71b8ec4fb484b2606366865ec3968f141e9" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "74be65b244c5e007c222c827d686b1b6600e450a6392e020863b89e9368f5b1b" . + "9419cad2ce613f16c14bc750f0d5ee5705aed4b3c5c65f95d9ff2c73dd7f008c" . + . + "7055245b333d7c5e31717a54743c458e0ecb143e70417f720a587bc9224e1640" . + "9d5a63d45ac1052c7b08b52ae1be37012fe659208c58611c58f5c0e42dd778f9" . + "138173d8289e855bff066829ea9862c3f5f28d45dbed0b4f2b0cae6c1c8494cd" . + "79d88833058183da924c88a3ec614cf739d2caa08db09e6e482e62bdfd3efb26" . + . + "b42a36eb6ba0f5fb0a50fde6d42adf372f1653652321c1dc7b190b5714241bf3" . + "d4b4509e9db4e98faed7b0ce6a6d4c757e4da14631d0169887eef7023d83d10c" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ff1cf7e68d40c86ae90eb6e74947e966a06da7a683492d6e40c41b0e657f124c" . + "364372edae70febbb5c00ed6d50d480d522d9826d36244dd7a9366f77a6988ba" . + "ce59e5ce644ba82077ec26d854efb99d5802f9998a07cdfc1afaa9dc260fd2b0" . + "cd39f0901f4a7f3d1332f2163e80f05f35cf6e83189d2ad034aa09e3d694bd60" . + "5fb1b8323f9d6a584f0eaf3ee0c3bf39f676cf44bf12c6e9b0266faee9b3a567" . + . + "b008c7f2b766cdac777d9b7321fc81e9a888987fd031373ba9577e5215a8670d" . + "ae81401a9def585847ab1bf909bb52ce4dc01729f0b6d9075500b2333dd3420a" . + "566d1bd5cfdcd9a4826277abc752c39917e1fc20a1d3ea0b254cec48b99f1f64" . + "4a673e34f4b60e20305dd081358a3b85b106e465201a44c2bd82a5dcbbdf1434" . + "b008c7f2b766cdac777d9b7321fc81e9a888987fd031373ba9577e5215a8670d" . + "abe9047edec3d381fb03a75ca711607ef870f0ac9e2308d1d35273d55e0f50c9" . + "5d410818896969abdcb61ff5bbd42d80ecd97e9d3c0943a5fd0c2252c08bcec4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "240f1c4e9325b8ae05eeac6f0368a37eb98e3b601404428225a7d54dd97fd98b" . + "c5a9c1a22de3b3e6d58b82c1e13d6a031ff5ef8d5eb42c31b9a9c1c2e3250808" . + "60030e450906e95f0f20af0a0433338472cf2f31460348b0e82bda378d156c40" . + "57ffab64d45e82d28dc55b1ae7f86bc5c193015315665c2bc72996c21cb3ad41" . + "ecfca8537934afdec9262da4f3adc22d5a162e288c1654c315c19c70dee0cac6" . + . + "6d11ace9a05f65e89b0e21211a8154b025bacce445a482a16c221400d023ccf0" . + "080c16f18801e4d6580353b7794e8e1d9794514a7f0bda902a1f70e3fc6241ca" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "f9fdd62a8c814f962fd27d76d783390ee4a48fbd0ff2bc13ee552f8a816524be" . + "6661bcf4c88cb1c85192aafe795a5e9c6274dea71ebe905d3115dad22cfd8128" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b150fd5324a1b80f365148eb63aa6f685d78d373f71c217bc1a3adfee42189b0" . + "b150fd5324a1b80f365148eb63aa6f685d78d373f71c217bc1a3adfee42189b0" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "add7d978494c00a81b156646ec1ee0b1bf8d1265b569e031285db3d964c40110" . + "39e7bc820e48766a077937697124d710502766fc600a360ed67c31a5b7627a0a" . + . + "d96b637ba54a67173212df61476e85217c62d859281972c2beb1627f3424b962" . + "a8d48b36eca5bfd269fe29197b568335cdcc275b9745746764c39824010bfa2f" . + "b9d03f3bf75e831568b312843f65e1d8de2416e74ac1a9264caeac578969557b" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + . + "4de65e214da7e56b28a32fe6a02fed0ef74d6649abad2e493017cf2cb6990bcc" . + "47d37b63e2afeee95f201542548bed97ffc474cf71f0a1ea479c6c591d4d3aa3" . + "d1faadfffb20bbbabcadd91f7a3af6b56dd16dc908e8a2a89ed85a7efe9c1453" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5f64cc7fcfe0aabaec09298d8ef8b2cd2eb3e954b8e9e83fa564ef9a4f27bcee" . + "5f64cc7fcfe0aabaec09298d8ef8b2cd2eb3e954b8e9e83fa564ef9a4f27bcee" . + "9c90d4e14ca21ac587337db2aea788824a1b50a7a462e6227ac0dfd7ab6146d7" . + "0b119446d5b5db6d713c9225dbd8ac914890ef50cdf5fd7ed8fcf5634d7e61c5" . + "0fc467e4d488b626eaf9e3df12a94640fffed781e6497e9ebd4348af26110124" . + . + "fed473d743c8331467061f622618d9c9d42a6e0427fb1f156ed7a60e1fba1959" . + "581a82a715aee0be895b0cd533106c65fe87a83fccdce6a00d36f361216369b1" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + . + "2ba581873c8ed9ad1f4122d0719aa10e23ab56be4830ecefb3141bbbe85a12f4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6fbb478fde2c16a973ef7253ebfc6766464ea988d381bdc9adffc09aa969b7c5" . + "57c5e476fefb6bff05c12c8d837829f4555eec921fa8002b311def54e304508b" . + "0573769400c68eb6f1b816e8dc76e3173b58e7549f26a5511b4b5fa10f95b65b" . + "d29e04276f820a22dbc0ed90359c232b8a380223ca2fd4538a67187b4f6b7cfb" . + "2893cd46a0d134f99b4433cb955d779b5b6e8151c52ccb92832b906e8278e2a5" . + . + "00ac46fc8b87077db8252d52a847168a6252becc17c25ccd39351a41a7817565" . + "a7e6ed7c285ed4d09f906272e77e425489209f8019572788f89ee449e178ef61" . + "368febc6c5e7967dc9023618e59f8d39bcae1ae98f0e5376d7b74522cdbf54f9" . + "d6f52605ea40f900227ae805c18f2145bd3e52b19972ec0ce0e8af69c7231adb" . + "ed30566d1dbab71d5ba5793ae7fff725258c849dd1c40a45310334e31b3c2d55" . + "442a0cbf38e2b6a9c2c77297f16de46873089fc2c2a096d762472fc3818eed3f" . + "520a668fb5ae482acdeeb86570712da7609f48652a2088c3763e88cafc459216" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c695ba53f1e5c65b11f50feb55872ecb64bf0975e0292743a4b1c5af503252fe" . + "8fab0e3d723a62425cf0c0496a4c654960b856eb554df5c2293abbd7a392e73c" . + "3ec669316592a6296144c893ccadfbf56e4e9bc307f1681728481acbfd2ceb5a" . + "d537975e82945c1a781be87f408cd5d484092cea65894f78729ff6e6ef6d144f" . + "b6da80567899c14fcbd16f2ee0cb41e28d09717f1dc84cc1ef115380a07e0977" . + . + "9f26ce11c89614a6913f08573568f1e290ac729890b861b3d28886056d4942af" . + "6fb24f3cc8d466165dd8cf2e147fd7ec1d22dd7de1e649976ace44f7b0efec90" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + "4d0f119fd6adb425760681d8fa6459e5d665690183a0ab04efc2d647ad16a9c9" . + "0743380706325230bfe4e0004ad37d4e348959b70528e87f18c1f9e5bc2dbe84" . + "42ad4debed04eff51eb0887717921a572246b04dec76542a1618179c8f26d560" . + "91b659c5b7596b69643d5acc175eab28da1fcc50633167ab069553d7e5808fa7" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0965e8acf03d31148a1329fd3b4ea405ff098da71060a4809f719e2aca00953" . + "f0965e8acf03d31148a1329fd3b4ea405ff098da71060a4809f719e2aca00953" . + "1c23dd7adbe032072d5dd5c378161e50577864c4f8e413eeb0997cf4367977d6" . + "096956ff5810dde2eb4257475b97d10296836118e25bb3ec2c7bdb4a76bfadaf" . + "e5bae071bd9980339623bdd76514b8f72cd142ef36c057e319479f6f9bc9c01c" . + . + "bb6c860ae0f2475725dd41e8b62c9ae94124c4d75e460f3a37b7357c83e0227f" . + "2eeb2607e5b212f135f07e1e0045b4447e9b5604f3946ff5bcd9c223139ba2aa" . + "e0f9f3edfb32223154a18e7fe7772dc9cc186899f00d98ea978a6d7b43e0dad9" . + "f3f9f8664f3742f1576c95822bfb0d16f86950364cc44085f65fc0c6578dabce" . + . + "bb6c860ae0f2475725dd41e8b62c9ae94124c4d75e460f3a37b7357c83e0227f" . + "7bd1317a1fb95afb12f0fa09195ac6a0cc87d0f6c97c35b8a11c1053ce09caf8" . + "bbd6071f8248f8e4c16b0a562ad6d3a0f027377b465f3e578125a78139f65cc9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aa0fba682f33b7415a13fe9ba1fafd4df680839bb45226393227f387f7e95c7d" . + "4b9722d11b803a1ee7245bd09d5f7e90ebd0d91121dd385df9ae9e5b94016ec9" . + "2d71fa56b216475dfcdbcdafb118f54f27f1f8330630c62a145677ab4b57edfe" . + "9f14c046ee2aaf68c6f1eae2cd5457e70022a450ee4fb9de31c16a319cd88f36" . + "870f17a27d3f94a54dc7b3e537b5aac3e7f1bfdb3de86eb2a894ef82ca9f540d" . + . + "1c0bc0bcdac8ef71eca71675c94b06cae7f4dca620d7265a9063cabad87e6cf3" . + "3f2e5140dcef7117f33874e37578d8498996f3cf300941341676a4ae27c4aa05" . + "e4f3d4593a7c077d31fae1f3b6f51d6515a2ae393b6c6f8c43bcc66d0a423cb7" . + "780d9e6a6b1e1dac3da7c630448fc93f11318a0e4256d34f2b3f385e0267daaa" . + "205ae09c41c7485dfae567a2e3b34d434243eb62220b6e4208326ded82c3696a" . + "10f0b6130c4fc7a724e7a34e393c5fcf566803121649fc02a30997d639121cd8" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "938b8094bb77a14e98d4c4a28fa2cc4c2a0a78351ee9796b47b4248fd39a81d5" . + "938b8094bb77a14e98d4c4a28fa2cc4c2a0a78351ee9796b47b4248fd39a81d5" . + "c21bf0e0ce8d945dcd785424ad87b322d9b9aef8c0181bc95983b008efe27766" . + "09dfd34493dcb4af7d42c88c00d040be9484789d9448d4e3dbcc9656b533110b" . + "5babcb4ae46fe5b716ef3abbfbbf3f86e2ca6e946240120d4569ba245b5d5c8a" . + . + "3102dc2ac123b1651eccbb56a897ea62362b4f62d31791ada2058eb49439edfc" . + "31599e17197f8c5bda7fc0e0de958875298bc5446e43017ad747cdfe9d5e244f" . + "3882cf701d4b0a8ed2aa4e7c62f7a367a5106e730e75f1975058b178dde472e5" . + "981aef51f6b7a954e5a9bdc7dba4c1aa6f66b9c262c315493fb9fe303ad9e6ae" . + "4be1806942a51ea834aeb7da41eb8b2ea5fb2d4148d95f400c28a527e9be83fc" . + "bd4d5f74bd5ec61703d9e4e35c19dfbe006cf97f0cbc33cf4894ce273d6dff17" . + "bfb3df5a15daebc8591e6691e11d017030f3411df49a8df57b5ca42945cfbd63" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f131a8a7e21ee1e78698c2cdcc20c32e09c22850874012e41392e53566e02898" . + "26e12ec76e4333babd13e99bfee2e20daed77f9f1871caee543587d232243df4" . + "fd7af05d788a398da80ce0f2deb74a8b31ff6a1338f44d42bc09748da782db89" . + . + "c66922e33716ef462171b28a5579d310cd6e9f517e9912926f7834bbace7dcc3" . + "51e73de9bcd4774dfdcdd5390abdc6718cca394890e73061774cee07a2b2a3c6" . + "96dca0e070b809d4d8c2a8b3d48fe92796055f9674416ab81e34ac20acc411f0" . + "995e74df8782229ad5406a98b2e205785130890b62627aaf7cbda0aa6884a398" . + "0a1383b03fcd5245c774f9b0f8ea5445889f4f585d1ff420512f7a30c54ab19d" . + "b1d47ea7f981e3fe479d685341d5e7ce05188765089425ac00139c35fbabd36f" . + "69e6b6276c32c1c3db365320ac527f77a286d2cfda1a22ca2088a91aa2dac7d0" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8cc42bb5213bd0b5e1297054695279d2f8ce03549f8630c4198b36ddffca8ff4" . + "748d7d9d346bc7da07ed356cd9a5e95154d929c807a75801fa0d66fd92e0303b" . + "e3552dd5b063e4a29dbddb95c879bee4dd3b768be63513b9ac7bcee1a99da75b" . + "9c3270af17b69b7ec0f6da7be4d3d2616a794f835ef0aa37bb8d3bcc14390d94" . + "132859de49ea056a07f3263a0c69fc065fa1e9561d734a00239fe01de9292687" . + "aa782ec521f9b9a4d563b24cf409caf08f5e70dd3a57b32afcf765978e43f6f9" . + "40f094991019865ec400f080cfcf0ebac5e9e05a562932f0b5c6013047c1e437" . + "33c5dce09efaa4a158102cff7e77517ce0693857fcfd197ab39080df53874091" . + "845bbf1ff884576a1b3bba7819cd3f08a6b2e72851a6826e28e04179c89af675" . + "387096aa7686110878fa1dfb865870b5e4bfb9e5da99eaf5420526ef20b7c36a" . + "04ee08f060767d87087ed97b3d3b4a0654f934960574f4878f15d7dfca4e9e7a" . + "f9be91ecf491addee07fb6ea9b7d72ee7751886eb90878a864daf334ff78f3ae" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "562a00a0bbeb0968eba4ce01d660409073d3017893540fc6e0060b98ab189306" . + "4b121913f7d2756b31584dd4c458ced6effadb91321d4bee12a0ac365af57229" . + "0ffb5da0499a597205495353be57a2a65e8f9017ab1fcdb80f233176aad3fc92" . + "806af57d94f4968046cb2ef23476e021fbdeabc803fca3cb322b02bf46759900" . + "97cad7c576891c7d307afb1cc07545003f63b82827ebd3da1bccb31e77ad2d7c" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "fa2cbfecedacd4ceb0c3985439fea87dc3966bf9c8a222703336e0c10b512fd0" . + "eef60ce34b648b431ba272e07b719eba6d117f1c77f479302c8e5ecdc50e5e07" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + . + . + "00640519975cc32f0cf8360f9bfbc485263ccc4b19568f1459a9e656f0c9b888" . + "15330e7fbd1b27d235a0030ecc3c8d8073dd212a138791f1f2fd4eefd5612fdb" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7df185c1f4e546963d85b5cc0f895616b504b93ac88b9c364f0591d2d348f43" . + "f7df185c1f4e546963d85b5cc0f895616b504b93ac88b9c364f0591d2d348f43" . + "c1122f24eaf74ddfbdc24eedc472598136629882d1bb5a211d702b67fea15e72" . + "5bb76b93f34071456ddb74271a1cc7e2bfbf54977113220974467c5afdada559" . + "a33aa7cb9572cca8263103c65d5b9602d2c9a15edb242dedd89061f0e4caffaf" . + "4bc62676c926ff119bf2fab9230711595c07509411dd8eb2c57730a5ae648f63" . + "de913e2b042f1e283d7464d678c5562361dd49285cebc21edb83dae000326011" . + "04a2004eb9202b7385ddc7f1379af75f40368f56760f005c246cfb546fa825bd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "e92001877ad6cb9bba11682eee586de17e27c32c0d719cf7760f8f972142b066" . + "10b17653378c6b7c6878d4dc4a47578bef0ee96a7f4482bafd7be49dc8d727cc" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "3b60a9205cd9b6d068835be80253263bd34f6498853ca1304a33c78e1c169acd" . + "493133e5b15133992e054c514aedaca13a6baa58f6b5cbf89d1f9f829dbf1fe9" . + "5b16126f8da59ab516f1dbdbd5a7a04f9355baa6bbc82d8a62d160b725089fa7" . + "1534eb419bccfe66ce5f894c1087c4871e34463f8b8da6a6e9782e44c94edd3d" . + . + "45c6ffbb86e0d59b0a514fda965cc6ecdd835ecca97ddc06ded1b2f2471d4e32" . + "cc73c9f104140bfe921d1a311c87fac159cc22e0251abcc0b4a18df6277aaf0c" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b05850761b0f8e1a3784466f3813a6ff6f9210e8896856b32c1ad47b6a886b83" . + "8b41e99ce5764c655ba16d50f527cfd82cbc4b032217bdf173f4a3092dacf8db" . + "a3ea677fa4e79398983fc0821c00a37256f15ae75bee5d80103ceaecb93cf476" . + "0cb79126281b63eb81d5150a22253fa0aeeea9765569a4aed6b60e621fa67608" . + "b9e496b560b7617782887da43caae9fae8d0ea28535115282fb7bf4009a4e4ff" . + "1363745ad1bfa77caf400da4fdc00063d9ef06a9b3e74d98dc915f60b1950cc5" . + "0f3d01d1b9627d9165dd4c12347b4ec57834e473fd17076ef7f2bb547c925c89" . + "a50ac015317ba8b256777e0314791fc6a6ecdd4c92e5b5a0c2d69960002c4978" . + "e79ff40f91ec3a3c87dbfe64526b498a8eeb56db6d25d55b6b6e5a36315ace10" . + "3132eae7395e85edbc7a074d2b0af8b439fd27e54e4bb226fccb08e09b27d6af" . + "16493b20e54d956a55c76831718a547f5a0fb74682e74712cb93fa58b08d57c8" . + "8fa8b38c550d0352748dfc18fd11e6755702bd1a2ac76811d070e4569b4d0f98" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "94518bd43de2cea4cbb9f89fb490d1e7b39a7820d7aa68a3094c15618eccd8bd" . + "d1949dd1d43c9c783c9a8989cee049432c24ccdf2bc6d632f13fb9dbf319412d" . + "e96616bef43670941a81a1c3581eb742e9e3b4d261752e46c9b25bb128c90a57" . + "b2d6f5c702dd26a3b594e25b6a0b6c9892c572056320c11678e1571a2c63b3da" . + "03d8ad0d3b803c1cf5b4b23537bf159cdd2903d85cd2aa3d1f123e6e5dcbd283" . + "4b877ce717af6037657b613bbe62bc99e319cfd67fbdcf4c9e6cda7a635be39c" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "94499d8c402b13cffadbd374aad6f0e8138c6fcc48f04ce6fe84d831b2c51387" . + "73d6ac81eac09018bec2f04e9409b17f6266a784816d72eb6f63d70b3b023511" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "8bc09abc8886ba6c3ac9619233dee6335e4e07dbaa6f40c1bc1a6d92df36ef0b" . + "1890209f0c8c3c0c9ef171f0547c9a5247ae2274e37012c161f640f560a09103" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "152f41966d7000d7e09cb85c404fa837264fb584c028bf45e48ba7935f7f78cd" . + "d00765dd519359be8766bbac8d28da9f66405bd91d0f11ce648384d6c813c236" . + "e1118781365dc60ce4689df2b989718cd99234759beef209f7cd9400da4b6a08" . + "d6666a29abbcf318f773cff6e61a352c8d22dc4320326994c8424d6b195ef5e8" . + "ed0f55ba86f6149ac0f392df7713c9dccf78edd1b745fbaa0d55112ed7d1bdbb" . + "d76b87c74e7582c52f7b68f8824190516382c78d02217f1fc0a23a9e2e15a327" . + "b4d34d1961eee4574b4ae60a0aa008cdcc68055a908fe3b425365209b93f9067" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "e71f97b5dc1055632e75edb3b58ebcea0184431ec44c370fdbd6fec2c02906ca" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "c2821776246b6723ad23af508bf9a887a1ca41f3d5a3f13260a576325432aa15" . + "4d095ca3df823d9297e5e2932b3f91342bfe44c5161338894e4c1d017146564f" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + "01d1e81abe960c49d9d56c9905bd3459c4e4fb2ae9ac50d4247db3020f39e844" . + "5db7d937ba077d9df6987b6c01ff2847d598e1aa16c665543034049425f1dfc3" . + "d31e2995c5f27812106a96fb12d57a8483bf74fc807bbb2255109baba762fe9a" . + "7c2e1efe13a502fb8dbd25ab377bd195b3ac9d7646b956c284a9ba00dc8358b9" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0afa9c07d898e0ed8775f3914df511ee51f1757376a84be2a3d16bd05ac58b10" . + "ac44c1283403eab6ac8cc8ee3a282e02c69506239ef7a1f2fa741ebd8264c6e6" . + "f6abacbd73f7f1a1fefd722b127dbc020f530d3c4d35956e3e3693b3a3946626" . + "ece7db86aa7b10a2e09e651a6c67ffcdfee52eec38126c122d149bb1a88c47f0" . + "f0b5a0d98a9b49ad8255e8404d214daae0e127d4ac5de8719da4bfa4a385eeb8" . + "c3c4ceda0df8306881a4b2e7c14117fbe9e80f12bd738f7c590779d669bdd431" . + "f92592a18f1a84ef5b0b9dfc86aa5313c82f051832a5aef6d74cd56c1c776496" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "46e964806f8cf4c905ba6131756407a26f7783d8a18c6caf80a2af4541bdc431" . + "bbabb9afc4d3b6a487c8ad8cad6dc64fe8bd80c3c3ef07b716d48b521d4ccdde" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "817d43a15fb6a0ecfd687540dc712a4ff4b9eb1b85f467bb9b7818069aa19d07" . + "f02788050f5ea432e11a3fffb61d1fec6ae9b4a4a1caee73fdd5e6c319ac7f85" . + "c32fc0353371f7ab56e973daa24a79622ec06ea1a4f35297f6187599063ccd3c" . + "a5c1892c9f4fba2e5a8aacf38dfd7a0979482eaa55e2fae7ef7a9421730125c5" . + . + . + "e8be6e14dbd490c53491bb2e42f142b3ef67a2d5e5ce4e9b04221cf48eb235df" . + "5d4f2b91b89dc8b49ab8174072b85dfd0f4cff3744494e8724b43f73b07e4e2c" . + "72633eb322205983417bb7611cb0ee61233678fdb5b1ace898759d75961ce724" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a66b3f934ef738dc6f25005586965191baa2cb25cd6bc53597cd8bf07a702431" . + "b346010c9f725a7789da4e7622b9a1402830663203bd957ce50693eb5d7ba74b" . + "72315e15292a606d7dffbe6b82771e639c3032162f9930d431433f3e1973b23b" . + "1778ba6a5f7c6c723bb9c98bdb7bffe6e5e963df63a9db1b4a6d47e556a5a798" . + "4eecca6c87e85566c37ecc6ea6f75183855a2058beb3dd229aa66944ae26916e" . + "0da3d046f0180bf2b4fa948f43dcc20702e0e8c493fa092900eb8d67625a65ac" . + "71d876605c8c6f1f74315f1a5a015b0576f5e4a517aff90c95f63254cf423d34" . + "1f30ef90ad7c346c4b4e89ab21166f18ec509dc874c21a7e95745d9725e65361" . + "98e4c3b2f45a8d291f2ae7d9507dd0633d3966e7b7b682d93c6f165361cb03da" . + "f0f46ae54438f120623e11cbca1972e85c572d47516469cbcd17ac41e628de65" . + "fac08f1b3678be9ede87a26f8242f5dea9b9db94fb73168c507f3593433af2a3" . + "4f8a1f9795419d4cfa41e9d7d778d31d4b0934c42a7f06f9ea8e3b5594ca7484" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "0261609f6d1d52070f40c7f838c253a622c6033a2722aab782923917321a8893" . + "cd6b385bdc0a4cee3ab0cd1e2aa129c1ba4e7422c0f7da447e1c34e65f103e98" . + "3440f0f8fc4d36b58bbddf67dc77d3b5b7f10178ae7fb75b07bb6bd61b44b448" . + "d847089e4181cc8046fce6ef6ef8fac50ac9cdfc35a1d3a900a458fc5acbf639" . + "2418d751e5841566067ab5b8613a606adb7634339c2ab0fe41406409d78422ea" . + "d12f209580a9cc55f162f2d69fd9c3a3e61d35075197788eccbbc761af833808" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "bf769cfb9ab181967aca661ca7e44cbcc9abdd2d8895570aaa9799ed0f1d0f3b" . + "c8944bc29d482af98681dfa216f0e7c84cf2179360b7ff54af7331368babcce9" . + "d01d2d6c47f7d1d0fc07094dd307953e1b260d0bd51b18e2c1e7fc72d465c399" . + "c404d5a0a0b824e6ecbf4a47cba7dd9308d0e4b258d597e31c2f8c3ff2b8b80c" . + . + . + . + . + "c17eb8d4193618f0f1df42bf403916b58bc6b5ce5aade375a7d7a71684677dc7" . + "ea04f84b6335180d02aad9dad9b889309ad752c8ef6b296e0d4c2270a3e25f30" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e2ab35e247cb6c2cace9f91b3e1e4f3c6a1a3ea1e560b59bbcb077b42b243989" . + "3f3acd3a7a1e7683f6ee593af3eab99d523769f53ff66d5f728dec24912bfc94" . + "733e240667c2d5f5889b4b0b456fdc72ad18a16123e8001bb4c5435444b1df32" . + "a862f6d45d7428382b2b869cefb08cbdbbf4cd8a2e792b10871ea40bfac543a1" . + "578f89c4364ca18d0507293096c5b79da22c1b541053ff16c26ea159f5e09317" . + "d2f3cd3dcbb16369995a52e8e0f60aae53841bb0d384e963c435ba408d8dd148" . + "88ffd451887eee3ad101f5a8d276a5b8bdbadb9bb8e22fdf429218870c3e19b3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7f54dc289d68f36bbfd00179358a68c996803fa2c743a99badbe4e85735a459" . + "0a3107a90114d9652225e4e6b25ece3f62833e4e1df3a0f40c12b128f2ade8f7" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "57e191af5e0ec60ca08a10f1d04e08138898be9b980260f0a8b7446859d3ec3c" . + "b00459c3f309416286fc5d337e84dcb69ce7bc6ca3e40196db9c8c6e3c43daa4" . + "11ed7dcb8ebf8916633106a8909484a1a62146df83fe5b70bd2676391cf1c9b8" . + "10ee811512879413e2cc432da46aed8bc0967f0c8eec00a0dfd50193e2947434" . + . + . + "4bcb1c5c24701a850fbcd00e7ea24286b8d9be113f4fd1e70618a71084d62ccf" . + "7045b49ab692de89c640190c71ef56f4d4e5f086dbc2db0b0550182ed8d64f7f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0f6f77ff8c2aac26966cd14b351bb09aabed07a459f89aaeedb67ef39614c7f8" . + "403024ec743c0cea2e135a2b07a789f02c0e783d7f6f1edd997dd5ea2b3a9818" . + "93b8e3843d0c498b1d0ff9c9237ac346f055870e33d202209c74d635f61f718d" . + "ae0cc4fac75614774ac533d3c8d9a25f4ec4e7c94a5f0be1186331f9c9523475" . + "d4294d809481426ff6ec44b3f3f8dddbf9606c12bf189404ce202cfa431ef44d" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "c3aba0067bc7088e67f9cfc841b48748115c48cee9e016f56599610ca70ad225" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "851d758b1d4137c21779fc498679334966de56fc8cef23303f1590edb8261334" . + "9e3a0f740ce9fb6c748c2033b443e67e8911b22029596b829bc5acd3d67aa855" . + "bb1e6a7e2aed004a12a264bff6a8bf852a5922136e4b11d90bad4cd7da812ab9" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + . + "b2105be5f46bee517b2400daee1e54778a8c19963a96340207ba5b19a766a0ee" . + "fba21e08a7a33783ac79262abdedb539751d40e3f3357a09a343747372dd457e" . + "f50dfcabf5a7d7a2ce2f9818a3f12832223171507d999a95b071c538ca50d742" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a43ce1b8588882e11c7693fe1a35f95a8f1e91257e0fe181031b48fac5f6579" . + "3c65a19bb0383cbeeb1eb7eb5709e2219022c11213c8e45d14767c0a5995d916" . + "75e8af2c66e80d6ba4a637f0de8abc478c3371377684b0aab99d662dbd09a5c5" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "a718c01ca1a4341c17ab24dfba8007366b66d77cec1603b0cfb35d2fa3ec53cd" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "13b4ad3a25abf98903c73902b28c2a75157663f49c06f0532c8799bb966de875" . + "d6ecdd18e1a118a2f3978b02a40aead80da4a03a416c13d41aa0607edc051b6f" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + . + "104df7a5a961e8f1f9bf5260a620bc97ac37d18bd6a81038badefe4aa9014de9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e2a9d5428b94d71f1945646feb9277c6ba465e935b69f5296e0cfcbe02154d29" . + "01ce5e541eb1f959f629bbebc826d20e61c7b846e910021208058411b254d44b" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "6cf1d9eed4e9c6331d279c1f548babad2d08c11ba97492b89fa9fbaf292e7312" . + "d421f9b5bc629084da4e3383de2316bde49a979971ecf5c6096aabe53776f998" . + . + "0993b370c5b34c0ccb507119e926e4c5afa05b565b12e2bf386af5fed06596d2" . + "f80249641eb943df1e62c5e5cfa732e77465b2e457260e5dfee91417518aec0b" . + "9efe7d539ac4f56412e410c87bbb50f222c547d1d49834a07fa7f5e8587aff3a" . + "f44d54ddedeebcae430a68440a853fce7010652acc0a7474abb79b04d3e78af8" . + "b76252f6dec8fbf741b75b7dfe038a23e5badf03d842a9afa60cf6a9c19ef942" . + "6f25d0b0f8818cddc2b449d4d2a4738633b3bffcf552e175a09111ff138b7476" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7f862d759174c836579b1ec8f4979de266915016c87d74fa75b93c727b43242" . + "031767ef590b80290d94bee6c82c8c8aed272b5cbd6822d7d8d32d43f78d2326" . + "57140ad4c41e0fb1ef9706185d97291b27bb4fc468f1f9a27b3f3e82e92d969a" . + "5d8ecba66a6d856cde2c8783150e9b433647d1f3346ad4c75f093281f500dfd8" . + "70510a5397f11ac1e7062146ea727770177ab50d60802695dadae529f55c7971" . + . + "2201e10b97c46ec2a944bcab44b0420da67ef9816b8eb538fe57506b1e5744b7" . + "e747179da76db46fedefa257d37ff0bba5f24e677571b1ef6bee215f10d22bd3" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "d78c0b2eb01b747db08657e39abb94da9691e2744e16701f66e575db5058799f" . + "6e15382499879d49f323fdbd8324327c7f962cedd8bfbc2f9f277b7402f7edbc" . + "a5a8d374cf723ec02d51c8873d63c4104070958fe6a84dcfcc646ef9116b31c9" . + "1a1e5e31c7786824e5d0c591b75e4a41714bf5324953d299c8e06a292ac9b47b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aeac96a50b801f4e65871744fe8a27848c097bbbc78854ca7c5984ad5d117c73" . + "486dac3392cffdda2ab8d5e4a7c3a38a0e123cefe0f61d888d51ec1b8c243378" . + "008c2b9f7027e27a4a0ed8e9a4e284b43e5c106b4e44b04cbf602816ffa72abb" . + "bc6d8718ce2bef702d302867cae0831139d4bc164d2681a401ab473194e9e83d" . + "f575d54bc4a7611d872e891ff85f0d118d5e20d4cc5915fd765f9712324203bf" . + . + "dba73a5a339831063295419753817cf4c8f80883cba59e6869d6e556e521de67" . + "32fad1f261d527526a6320415cd9cbd323e449d390c853b4d99019b59e5fb865" . + "6f69ca8735970133a3753aa18d7e0ade36922866cceec6cce04234dce7b7b095" . + "174ba1079549feb4e13e0033c2f328080b5bfaa7f401946fdf0e2f97c3ddd823" . + "23edf79a55177e7fc68e8b4f1890535370e61648eaedbfc750b4c843099e6e27" . + "28c63cf9914276d63af639667b39640b60c5f2f09026090098f5945a198dfff2" . + "0a38c0db3f85f77367e8a5094ef7272ea081cebf9f9df9788d0b2771cf9643ae" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "139a478e724d5d0863b3e363f4dfe929452adf9f9690280f792b77b80fb3bc36" . + "9d77cb54df3160addb89833c25d2009c93d3e4b3537037bd36ee7db6e6f2df31" . + "c27916a4480790a0de7c09b4eb0623d67c82538118c4af2e2db004cfae2b4dc7" . + "9c64602057cff4a3d881d820ebc0c8fc37cb567160bd9bedb5658b64b43cbe05" . + "9829efd902451a45e4d3ed2e52245605c0785e771e51738c650c29218d784acf" . + . + "8ef2947118f282d7f22e08e2e1cdabaa9aed9cc49dec441fb7a8d7ed1fde2830" . + "aa2cbf59251fd5916053285e37090e040a7a5fa9df2bf2297e3df4aa27d39a08" . + "2d960e5c1d4c01d169547374ae83d975e9212c5b23e64db0504f36c8367a7cb5" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + . + . + "16c78807a626d51b84da2d25b79dcc984dcb6605473a04ca5adb85c9912980c7" . + "db17ae4e5312de8464c009dfaba233d26f3cb2c48848e9b2111d360ece3f6667" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a8a225311522c489508311d3d1b88502b4b9a7b967777a4faab057033fa565a" . + "9a8a225311522c489508311d3d1b88502b4b9a7b967777a4faab057033fa565a" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "b1c3c5118fccd37f61c18b946d6695eba59daf89b617c70c8da76396180edf8c" . + "7726b506763b836dec40e7b665cab083aa6ed837a72875e4ea7105c5a1557a28" . + . + "8bfe7ac5ee70bfd3aae7ed144a63a38f869e92a1e1966f562117e27741f44f6c" . + "fd160cee952b4534e99bd638d62ffd340d1a6b5f6a2d39030083f78e2fa13084" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "07ff4b021c8eb746158859b1ce36922f96b48264d592c3535e84e2f68069546d" . + "8bfe7ac5ee70bfd3aae7ed144a63a38f869e92a1e1966f562117e27741f44f6c" . + "bf30d108e7367bcc2df8a932145b95ae5c4bae4e204dc41b6f5dcc1bc5d46785" . + "c0eecee4317e7b9294b72831ed747560880c0dab01594d03df3e58ee19dc4036" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "20178ae6a19bdf3507c2384fb3592bbb63dd06a38ae1c83fff005e00e7ce7dc1" . + "2ab2cb404429c843ab24b9a292821e92ece9befde9e9c229e9dd539757cb2b58" . + "dce9a9fd1dba3d646878a5d0d9b1a51354cf5012786dc48b0ee6bcd438a817e2" . + "13a2a58779a524cb5f6a9afa7459d694616e4f44ed25be7e5225704a073afa8a" . + "54a69f1f1a099354f6b0095a10350b25c553ab19846d1e72f201cb286bc72a75" . + . + "a445714c16fff76bdee218355ffe34630e93b1036bdc8fa9d10d2690e590cf22" . + "8de7fe2c39a8faf4279fc1aef68b81f1f2407c64fdb00c8bc40068cc1c8a9ce9" . + "f22c98e2e5c5ba1c0f5466b541bd506a61631b20f496fb57fb30ef366453b90e" . + "e40f97ef96be111d7c75c721b806f0d07a64f0436550adea246d4d8a1ac3d69c" . + . + "0310267380a9a553e83cd88baac94ddbda87cc0d2184785c53f386561d5ac3e9" . + "b1ab8f62655801a5f49d8ac46b596e4892a37248d3e41d6bee846b65828580b7" . + "8ad2d811b089e6deb420aa1c239d1cf584f2768a365297ffcc8d16751562390f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9fca78d026fe056bd46924fee8a3547ec93e470ea1f3c0856891787fd8a8b6cf" . + "f02c2ea830780680f71f9eaffea4b8a6bb42cb2e48dec3897ada81b9ec7f71a7" . + "0c42c149f490ac04dcf8eb1d890fa162ff8ca02d752ae2d1bbdedd38b04c6571" . + "73c24121c1b7edc9853d39cf21dfcefe703313ae95dfb535dd25360d9fc7fdd1" . + "f5345af9deedda0fb0dcd2b7b9cd463c4793cbf5ae409ebb0619e7c7e17285bd" . + . + "2534ebe7f619396d1712da171446468f44dc0d30d7cf6d14340f41827fe2c3b1" . + "2bdbe20050569aa23c656c4bb88d11c339c79460be3f88d19bf49d8e0ae530ad" . + "23c2a356eb7a9a1e7983bfa9c85697dea983fffdf34f03ff605be4676365d0e7" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "be7df7feba4083ee9e07f808d17e8580bd29c2e8167470886e74ec18ebf6c9e0" . + "d65449a9d2ee8f2babe97cd0682ffd24aea7bf5a25474132a7a6edc8873e4faa" . + "b31ffa19f0e8fdd3395eb3b2bc4e0b9e562bd70d8f3871999557fd460060e286" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3d76425345b6a56b883d28dc3ed7c7aaa459a7425e3d1a8a8d740b5eb4407e60" . + "7a131cd838b0c94f29e110405a34ea655f79c4c7fd22f00a769a913dbaab79d9" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "e3331ff2fabd1e0b1c603e853fc5b14de466d22511ceaa60253a980767fb3050" . + "46e8b2b5cd695567f83023a83b28856d3df65f1af970abef410add618d0dbc50" . + . + "d6c68cf650539b831ffe23de1caf0c36126ab60f68c4ac5abcde37409482ab6a" . + "364d8966143c9dcae562e7c6851f17a9dcd220f0dece4387cbd393c8644f54e6" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "c9144c2edb951273e0d90ae7299e476c8fb5065dbd55b2f02d4aedbc641998d6" . + "d2193fdb6cbd4ee4413cc7d4a87377d7018e1739d6dfd5e8a774202e88149dd0" . + "666a15da60d5d62ae2e263416254a26c0067d6befcce70115c430ec5df9a9bdd" . + "8a35cd39b47b2b51311bc99e80e02adcb10c3ce0448c7ffba308624ab5ea2de6" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d8c1c82a700327fa4f6054f84ce3de7cab9be3bce0b0a2cbbb04550c9f4ad1d" . + "6d8c1c82a700327fa4f6054f84ce3de7cab9be3bce0b0a2cbbb04550c9f4ad1d" . + "84df77b3dbdff684b5488be2aecb6900c81ac3ee2b4065fefce389a47645ea13" . + "10251532226e0089b6b0e6b1ff75382a57fa27b1a8d9fb1304aab4d9d0bff25b" . + "1bf8746c1657df07e6f56f61255bae4e90bd1a3389952d160494ca82b4b824f5" . + . + "2d88e79fad9ffe610739df6114cccf12966e02f15698c97b62853330ca8c9d8d" . + "1572e25a68cb1ebee5fc0d9c1815546cfb1dcecf07c1fff77c8cf403060ab40b" . + "0a237cd46bc96ae66295bfa912f9bff64b60e92a176f34b50bf384442c5873ce" . + "9c6b480c30de3d3bdffe075432c72743231bb93542415f131a3d3464c52e77e9" . + . + "e2a0763c818629b328e0a951eafb15e6022fc7309d8796c790c1bd0a3f5ff6c4" . + "2fbdd8cfee29d6fc71bb08e0b4a328b238b897de26f8baab48312211a0c75c1a" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "99f9501cf9d35dbf778cb51b216d158f9fe17247d16bb9abc6b608294d6804e6" . + "df049a67534b8c750ee0cc45766d6642b89af3945c36b11f8bbe0733bf4858db" . + "2e43189c33253ad40fd49819fa20cca23b75a89df79f08f08be1b889f3e740b7" . + "9406791ae183c784f943fe834ee740c3b03552e4fa5479d31da36c9efe2f5939" . + "45b89d046bb02b8f7c1287f5b84afdc9ac65536fc876aa7e3467c298db662037" . + . + "f8f2812272bab9f525bee55054751db5133bc7c5d52e4ed67eaa3ff2241ccfd8" . + "e5342b0dc8fc8279b872559140ba99f46bb3ccbf68c21c6e40c9f0f65cfa28d2" . + "cb9676d927dda7e9ffe88601b945b9d9723c034f549cf722a246f185ab7e8753" . + "841d5c4914ee3f75a0f8302ce7ce31ce784905bfcba29ee85e34359a81e2daac" . + "677edcea82e9cac4bf44dbe78e36167b4f3d85befc30690395ede3698ce6e020" . + "8153d1a370ebf2ca1798b76a0b64849bb8a5f9492aec9ce9f7c218cc186bc573" . + "423f6e66ba6188dc3dea317d012beac0374938ebd3490c9fa8f38a87dbf252b9" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53f26151f1518b6dc4b76c36394c8410b736497c0d993ca7b3cabf41ee2cd84e" . + "455950195b99942d64b572571149c47638cd072f6a0fbea72bf3c159b8f71725" . + "0da66655c5013cf2da857b6df6325cb5878c77bde8b3a9410933e3148abb7f97" . + "e08993976264c54c9279c8c95716d1d49ad789322779bcd199873c53e7852520" . + "25bc89db3909962383f45818bfe47cfa4e075b163b510711cf43c14e716005ea" . + . + "fe9cfb1ee520798a8c4f8f8af641ee2123820eff60e24f1629e9d86b3a1b6f83" . + "729e3955ccb05e1f47db2159a03541658c5bebcf0e19e624249f09de1e82008c" . + "f54bceb459d7ac7693dbab729d3e303f06c082a77ff74aa54d28451577887c69" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + . + "bf9559559f28fb9d140ae23d91bbcc6f5bd0d773666abc9d46712c597575b764" . + "658d1567280f1f7621b29412d0f37913e3cffbe4b6fbd72a25bb8ced15ccd3be" . + "b11a8dfd8360e52eab2554a770f7f5a42e02c6ccd0e345ad3a6b3789d58c44cd" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "18390d24ef1ac1eb3b1fd64eaf5892262431d7de7aa3ba93d0599bc04edcd64f" . + "0a0c3ad0137c425596b2fe2328e23036fb1211b891b78cf9c07ac8155b321a18" . + . + "82397a620954ce8e9436c3cf095840c2c4d0135b47023acf8d9d90693daaf8f1" . + "6a536f9c9f329cbb034167b4fead4c897098ce39903bd4fb3c234284d6399ac1" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "fa933898a44e7beecfe987d16635a07dc7899aa146c7e96067f79522ff94b4dd" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e3168967a88a29b01e282c10755c55823a2ead176fe49686f09f22eefcbeab10" . + "e3168967a88a29b01e282c10755c55823a2ead176fe49686f09f22eefcbeab10" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "9ec2cdb3def000629d6e7a02858cce745a0c4eee8c195b7fe1b8cd56a33dd68a" . + "6c1061dfc158c6c15ac3b269fcb41879ea1c1e48cbf9a4879f05ed02f4b8ef63" . + . + "589b3b2015b8bf6897bf7c48661d85c1076c4f84f2433bb47b68a9ccd5337a39" . + "82a6e46c8fcd1fe99bb3a17e031a967ec59dc414bedbd90286e847a7a0219d2e" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "e5e5f671e6e4c7e0d2d9507e29246360750936f614709b51ea15ce942b354365" . + "c958a34f52ac8e323c2219ff77a38b963e9dbf0c65f8114876e5806a227592c2" . + "3b56ff8405f329c1057ae6a3adc29a86a4b82c271adf8ef21350dcf2a45dfc3d" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7f50d17883399103beb083c94baf96f9cf4a881c2604da23baf580f14169803e" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "8d69f401eb28f1ee90603e5bacc4c39f8ee94175c0b57e6853afe46ca2d1e74d" . + "2f5787e3e39ff70bf32b0022c4ca6850b37d433ad6d09a8828612ee2045b7d33" . + . + "fe7d89cc9ce3f651a354c56600ba7637936f4030a974bf17aff982cc6bd3ce92" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "b2eaef7d880654a644f70f5c8db1a858203265c09ed7ca54e42b59e557d374a0" . + "b7ed424815f62a641b78bfbdffe2048a4244922b227adbee073bb4bad8919029" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a1ac3a2ad9d17e0be8d58d6eac6a19e86a9262e833e01767edb86c495ca520e3" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "5c4f3ae3c270feb231d0c8958530eb5e01bca2cf8c42d22dfba56cf5a5e1caa5" . + "8a209b468e92ae07fd13d21b856a664ae29a42890db051c6917c7583360ac787" . + . + "12142cfe66a98012c9c5a25688ed1dea2929ce84f08b98706dfb21e595fef25d" . + "6f96c15389ff30b231f4e8c910dff4f4877fa341105502bcbf17790b37acf214" . + "e6dc508a22881fa1fa3a08c6d5195590c9ae81eb51c51bb088f586b3c85d71bc" . + "683702d11eba8212cb973dc258fe4ae00abda698b63c832540c04fcd782a65dc" . + . + "41cbbc83d0912b8f496790da26f7c9ca15c5cf3e1ac122ef5d64d763f2497969" . + "338b940e869aeadd4afe4995607dc3d9f28a8a2e6faf41806eda5cd01fe9b9db" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ebc4205f993a04e5201f5f743a15779f60436aa6161bd456a83b688f2281f689" . + "c03e23cb62ca767bc274dae87cb6cbf99a141ecda69081027c86e4a8689b72f5" . + "04da8f89573f8167a4abb4f4b647af588c5e16fe341c077257412abdc84e3289" . + "f1b5168f1eb924b5ae0ae3b36a43a8878330f14f584c8f4ab4121d7ad7cc9d43" . + . + "79ccd0a84d10612fea5f870b3a18bd20ddee769b97b2c63d05f4bf286df4ea78" . + "054c6e8afc98a72f6e16c84d55892f82a5f66526167ad9b149639215787e2a04" . + "3ddce1e35d4f89463a15668d4d6375376209de324183b0164aaae660fe887e77" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + . + "3a0473c8ef40cea5cd044e07ce98da201301dcc1c2946aea15192869eb4c907e" . + "4f5e9bc1019e15b66edfed71719550f5910a302b811a70affab6eae432d43d24" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9589b85881f4140ce0aeaabc78dfcb34831b1c769c96187566f35534e4afccd7" . + "a8593c744bba311d58fbda67d9ca004bc6341bbe6c757a96f0a51384a3ebd6bc" . + "f54e9bec6993a514336afab52967b33caa78e914e5200d5974044d1d69afac3f" . + "0cdbbbe0039c051cf13443d0fc9573a2ce5ffcd3cb724901e9de4d5df1c4f3e4" . + . + "77ff1145edb38b1a49700aa80b4fde398ce6b8141e2927a30d1ab4a4595a5afa" . + "f923737cb1f38906f52610c8434140f607fc13e5dfee7cf5f351f33f4465e24a" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "6b9b78e4e5c87912fdd70cb9a41b9108f3e461318c5ecf8976fdfdf928893cc2" . + . + "c444376e7fd7f77e951662112b72e5b6d54901cbd8b6a839cc30119a6518720f" . + "69dec0426888681f8728713540ef86cdc6242a6ade701be4110c1b9def2149ee" . + "ac706a1c2f325bd88e24d390f6428d8e7ac0792003046f119632fa49c30e94be" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0fae9a8c9776e9edc79d5292289e3088af00cd38ef2a9697f3800434dc953b10" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "71275ac5445e99b14e7fa7dde707cd3ac53c14d33d2a0d602e03e794639d8bdf" . + "65c70b84aefa070c5e896cbce99a7ab5e842c56411bfcb8cc6f4578bfab39e83" . + . + "a3db8b3615fa2078aec42cad1095b5706ec569c3270ff550aad8fb352d8a2d34" . + "e59acb7157cc7feb83687ca0441743137fa6996ce8cb3b26211da2376808b493" . + "d3d24769a2f2f7d03c84e7685115a1f3fe4c906b23e98b68fe3f77c5754a1a20" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "afc69c42a25ebd5aaf1f912d94150b8026b88d445c807c715089667d5037224a" . + "88dfc3bf9aa6d43a56780713f146bfdb7a0f5aedd0b9320941850b0c8452bf36" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "28adc1b86d1591f73dcff8560b1fb5a357875c6d9d6ff0f4bad20465df477c82" . + "53be02edee29edc3ca019101568b0d8fd29b7a7ad6ca7227a06a01719e121518" . + "7f93894d8713fead48e7b78f2f59565be9d022a790acc2995a03fa8c3478eb22" . + "0a9faf5f6cb815c053f0c6473bf7c72f9401a4111a5416da08e65257bf19a33b" . + . + "5e0aefc0abfdbe0c2e29b058d901cec17a8d1d51155f057fa1ae77938cf03695" . + "2636ea6e54ce41729b4105111316e3862ad278a9a5b19f2ed4953b5fd008785f" . + "773e572c162646a84a22ba38d39c640df16e314bac23433e1d1a21870ba2e20d" . + "b4b064b055f48ff7bed0e5a215553750144e7e722a362d29b401f8135f6c533d" . + . + . + . + . + "740825b744f73b33f23841d5e52f79b4bae796799b7869a5326c0b10bc7c3ec9" . + "b58873bf71a693e95ceff84504a9755673d018696c41ba468f15dc0616b3da1c" . + "e4d5b5dbd841c847fc13db885df07ae08f74ca75d24036f7a813a4c8719524c1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c63f9b39ed17f3388b728d095657cd00095642eb7f7e8416c924c0160ad78fd3" . + "584bba1a452a7a55f1c59cd056d9c6acde39b90042b3a803c10cdd757bc4d19f" . + "840e81087a6251f49b3c9f2e7d5b745623114c0ab2e40060f656a1853ace4e79" . + "b9433a0c9522916d4d2744905be6bd89fc10078f63682154305c3b25bdfafaa7" . + "84d2d9bf27cb0fb1067e765e85d18758f99374e24d5c02ba572cd7044846fcc1" . + "e33784810e5a7d8ee1961595d605bc1d73f82e09d5aed8afd557f0aa382c1ef7" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "2d65e92cc2408839cf577faabcc7fe89cb696ae895795d18ae6fc1c724ad3ee6" . + "ec4c30f1b8e14c23bed059bdc21428de3afa62d1cd03692a7c6806e55f644895" . + "ada6624c34cba0bf403eb1f278c516c25b8b098a3ebb25b400b9282852d044ce" . + "e1a802544645beb87c65df7631117e1710ce398e34baee51e7c347cc560044e7" . + . + . + . + . + . + "7200514e7380a00ce01c5863aec50ebb878e8b4630ef6abff1ea4cae9971224c" . + "9b0b61bbe8106f032ad1c298e52c6be7288d883e3b151d9db0878413981a3d68" . + "7c8fd8d667c3432bb2292c69ec4dd95ec019ce15369a157ed2a9f6098a2ff7e1" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "27a49b64013594681c6e0d41d7cffad4c02e2efbedd4c041193bd314a362862b" . + "47710160a6a1cb6c62d87497c833a670b3acfdf9272aef2955d7a56cf14616ac" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "d1ddf08ff496f85f58bf177020cac678b9d9f06b642c0f949040dfebfd97305b" . + "72d460a44a43fb4e474313ea17598f84c156c39acadf2e793c9cecfc2700178f" . + . + "c25cab20030723b933ece329c15d0ace0344e449d8c7c51e991f287850f1e3c2" . + "d731a2a50ed3b1c537fc58786bd4b34f446d313262ca5f165832980afd8a0377" . + "750e866abb9ec0abfe41e157c6b4a69d3f9fd07181d480b75bb6a05f38c20968" . + "0a273fea4cc3883c9f098ad554e9dcee829cbe12b81dbca5825b0278509285eb" . + . + . + . + . + . + "5b8e8ad43a1b64644066d5486c8ac880ca200cb81f158d276dc084cecda18aeb" . + "5b42b3dc1c297a0138e9580c61c195401d5a41f136a353b5f9226ac8610a873d" . + "bb2d223e5167d517e8fb61afb7555a117d9d6c3e104cd7187a8844f8680ada49" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e238e6cc8b8ac698929df9f2ee13f9a015a70edee030bf83ce25fbca0a2cf0e6" . + "169e10387636113737178701d73872fc820b8b041b21a3eb66c25ce342babb9f" . + "f01fea60881a4e4e0c631dc6f59a79ac30421ba597e46d7549527a90d13ce8bc" . + "c580199dcf2e57ae633e9963697a916f9883a03816d4d22e826bb7ac9f9b00ce" . + "e7916fc0d7a4cc787f85cc22ec8e30446738f0b39a18deceb07da87d1c7e27d0" . + "ae4528757282ccb960af39c80030889daf5292de0b535279df4376a0c0ee4006" . + "ca72f200b026af679a74bdeef51618f594af13c3a3383451c69b76289551e391" . + "f985f3523c8fc36e07fb811e142da8750f5220bc931ce747c0e57aa7cba68a3a" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "7e9183827cc665283787129271ba85d300a5176c9c1d9bc548f8e9eb4d79e7f5" . + "a6bf0663143c3ef41689d64f528eba613c21d7d597c5be6c5d1a565b370ec50f" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "853c80859a12244c93a7fea8dd743affbe643c79cdd105034135bc8a1aba016f" . + "708752e0e31369bb6f35166eb0b32babe2262261d215170ab2910f07cb0bed43" . + "f6eac97c000903b0b70b0891eb514bcd0880bb24f138d1a26d5a53b8001ee1c7" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + . + "7602909866bf0e1a9d01e8dbf5a582c047d4d09086e4a06fdf3659c087431ef9" . + "43b29c8bbc7fe7f36efc337871537847c01d2ba90d1f7d9cb6a1072e680e8820" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9030e932311638818538136524c824c10e06998cf41f09238ebb6d2dcf8439c4" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "76c74f63ba86e1b482f267709832736b54346e5a18251674b004f5e74de447de" . + "3a4aa3ce8a6b56cad9487a5bcfc5675afc2694a3baa7fa03cd666759e4d93ff9" . + "2599b239596b9ec0af7ba78bb703f657937ed2ac50854813c7529abe125b69db" . + "a5119fbf4af592458c71edaf8cac18a588fe9feefde408b0887d2547d5b1ce56" . + "f67a04d923093591de2b9d396a581da0afce80649f4027da5785a2019392c482" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "e7c80892af9c077174ac2117a19573408264ded4f355471b63a740834c281494" . + "3dd8295bc9ceb4e669a6c1a6cb8cf8fd969eb320b3787e2b3911dd47286072b9" . + "173fffe32370ea25d3b5f4d6a415dfa92f700071427b6ffcdac196c2399b1b5e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "46b7415fdc8f4bf416ca5dc4e6fb5dce32e84248634918fdf976070a3a648137" . + "c93fc427b881ccdabe80e7a641cdbf29ab16b3d550f0d49231f6567652fa6067" . + "b5bd47b26b071a084e26cde25bebec268e60f16296de379089419fc0942723a9" . + "2379d7b0f02dd828cca0d375d404c6a15649a568dfb4c6182530d698b98eab86" . + "ac41f1d6870896e39c4c9c2580defc92c8a259ba598fe077a1e0971924cc5df3" . + "ab9b2c597092111b98fc2c5367ed8fdd73f4f205b49c0055289180fed26e7c07" . + . + . + . + . + . + . + "3124f08935187fa6baf70d1a5ce51fb614eb05eb2ed8c1ef0a671de1d8a84735" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c163b94826ac44543112dd898fe536305c3a0297d91e88f124eeca0549872307" . + "0739d46cba60c1bcb6b3cff3916b4529475ebd9f695da3bbecd9784027e38497" . + "e837adfcb269045e767b73cca5aa69816a93f1bbf4310228a42092e9f99754e4" . + "39efd150b0237682aee08a6990b6b99fb28ff1797755da952c91bf6b9113ceec" . + "ba7479a3e2784114817f1dac2ad90587656c7d2a04a681c4626659c182a8e06b" . + "e2bf5ea74ad0aaacd2929b468f69366ab955ee397a254e7b9780e227320eb102" . + "96cc0ed37c29e4c5e3035d9cf9f5ef0ee2f6d7dfda7651943262ea0207fe75d5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "0b2b835b2a384737263c5de422d337cf70f0346f58d2bbe3e38366217bf28612" . + "be42de4b8d570bc21366db979692750be5f6a5141479c4469faa3aecdef974e6" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "6d31038caaf5b199a76c2f20a7085d76e54d59b70518a2ab7154d30d71027cc5" . + "5e9a85cfe05b9e666b0c80719d379b1830657657af0817ea6c9bb37cc75745fb" . + "90e066af0d50ee82fe1820f171c984fb9c324d4f0b10b4b1180c7e8cd5ff50dd" . + "66fde7836c07bc13f568d627bc035288461e0298b4326493d313b78532661cef" . + . + . + . + . + "8689f8cfa442b4045b4edde2f79e54a7bfdd7a7c694401198c2357fa31afc3ee" . + "8532c678439891da252ac0b05bcf5888e0d019ca621419d4d2aee903f6eb4806" . + "60349bef3326e640ca730c31a320b4dabb6cc5b842d48212f4448785dde72035" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c8bf44f1f7d55c326d1c6e9511e3afee173e1d39268666469fcdc77aadc72e2b" . + "02243b1dc4f75326374470b80986726d0a5932596006cfb77965e259fcbf0727" . + "b7a893be03a817cc76e01f44f313bcf872f30389611a5a0b49cdb61ed54dd988" . + "1ae8ec9164ba761887ae41d4e80df8f531f0049df79f809d560b5f3232058763" . + "17474038c07837a2dcd5561c89bb53c6cb55a20cc4c5d87ee94a28d4cb52c6ae" . + "a2950a6798e1b92ecdd15e679d9d8f33fb1ccc4db44f911666502e3bd6fbd3c3" . + "0e074afabd62114ba736b8ba8c4bd6159c0fe0fe1b25dd26a96cdd7365e82458" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "05f36e3bd49072cd249b126e4b23b6cfdb851df6e2d404a30091d6a2f1c76516" . + "038ecbc562ce10ec157d4e1b0178b046eca8ede10a628f7bc421d15f714754c4" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + . + "e18a41874f4d605ae2b5d6927a12de1f611145ce589fc6c21a8570e5ddae8cb5" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "d887bf759aa0b1e39133d67df1cd48983d4337ed666c33eec8be59a79401b5bb" . + "6cade01bbee5080faa85e3590eff287be83ef43f76ac6f1ca5ddf345d8c3a851" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "9b0363ec842b1b3c9347e859740d3666fc8706f38cb817faa0ece58a5cafff80" . + "462ebc4fa397dbd15e1c2c0be93b54557c49f3965cb8a2bbde89fe7098741cec" . + . + "0d49ca1313209f6a03c1de889caddf079b6233c08d219e720a352ee918c3a872" . + "15df5a46dece323f8cf01f465d18180d0e8a365e0ce4159ea2386e1b27882520" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + . + . + "3ae23395b30372ba6e3bbe931835232bb50a57d216df8cc79864e8afb638f176" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e25b59a647ef63947aa728be07b1b076ed679a2e4c24771e3d65c43390830dbe" . + "e25b59a647ef63947aa728be07b1b076ed679a2e4c24771e3d65c43390830dbe" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "5a2972726db69d63d34c39de50a0a26926114f191a05be1d149d5cc903d0771c" . + "fd09446a626530c4a08781632aed9d56882f70e6c456dffe18f70b7869d79790" . + "ba1fba52197ac8a52be1e085ac92d3ae805bf959bc9e91e53466e9e057c9c680" . + "56cc2cdad0c348b7892eeafbdf159123d9732391234615a2b8f072b265018795" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "0e7b9b9dc8609c20f82251fb312976428a5bab2444d5798f0d1aad8ade67a238" . + "6285cf37f2c974c394e24f6e62752a2345ff55678927d948edfd0e97953293b6" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + . + . + "b378d470f568a5e3d8207df30e7fa9c9b60cb0a01c0cfae58de6cfe215619652" . + "cf70f550e25dfc590e34dede959e6722a2b54b8c5f6ca64686f664d334c69d31" . + "9102bb35a7c42970c650fe6881244c262aac5565fd2bc14ec9ea08a16f6d6646" . + "ac953143775612e6c9dd5b9f311a4901208eb3db123c6a73b8f30b9a0cf2dd62" . + "957ce33851d3b0ca81aec5a23f913883138a541524b3c5982925b9ae8c741b88" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "31acba0f624ca044ee5dfb0aa2ce8fd69a7de578c3685403d6805ff5bda92069" . + "c330a6f8c653d45b9ad5c49d94b2d1e2b0b0372a1450d3ba39432b26bd843cf3" . + "e93a80f80c4a9d975b683d39ac7a55d612716aabb3922769de8ebcdde6b0e993" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "e4299972f4bb8792434bfc2cad1acabe2b2455518aeddd07d33c789f8635c7a2" . + "65d2469cdf9a4c504c8c3f6b31a3165ab19446f3c736784f585beb1e29c4d81f" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "510de2643ed4c29dffa850e8da158a9f347e4a9dbf0d1c7127796a82b510edd5" . + . + . + "0abe74a1fe6e9668d8bfe1dcfb681993e0b31ce49dbbb7612ccd54d84d96eabf" . + "5e67a294cb067b2a422db4de0ea0735be53217cb6e3504d666b3e3c4d0379da6" . + "b40ce7a4937013faf55d79b8842e0792bc550ce17c77763c345fd140086ede2b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5ea6a378c218228573dc37dc1cf7452ab847a55c07bd0eb69b431691d3565dd6" . + "e6fba58868443f040a156269b82f7b2af0c767c5a6ccd7781d519d2f27d90745" . + . + "8d8ac46f9ac3bb58132fb24b1f895a1568e845777ecc0eb53a15e8cdbe6296dd" . + "f65b0c4b621bb07bfac49b838067b5fd799bedbb045bf80e1d7377f72fd02bdd" . + "2d960e5c1d4c01d169547374ae83d975e9212c5b23e64db0504f36c8367a7cb5" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + . + "52bd5f3d03badf80f7ab61b0ebd226fa4b122255c1293fd4530e227c9a66a3f4" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a625481ce39c6c98e2961e1fc89c1c8a5c6eb1457869935aee44bcbc774bf536" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "2b1647f3d66b0f5243250be0a9191863e7f5496518253c32b258883bb0d7cf9e" . + "91cbf245bf17f7f7ab03d1818d961f8762c44e98316a671658b0c65364ce381f" . + . + "9f302cd4c518a703e4b2af5b74ceef09ac124fbfcf0d48e5f2537b58d9577e40" . + "ab7668c4427f7742f30e198a8239940c7059d09b93e84f655775e4ea524a1830" . + "73db25f8182b6928d00f0b1fac882c8d4bb3c81e35afb4c751bdd10d264e3043" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + . + . + "9f302cd4c518a703e4b2af5b74ceef09ac124fbfcf0d48e5f2537b58d9577e40" . + "67935118b9a064f6df2218122f882fd53f2584e3bfa7330fa4890a1921186ce1" . + "5cf1d78a3ca4f9f4f5bde60556503ad5158370821e20196bc104c822aeb71478" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "db85ba46faf97e3c6c2a468cfa8ac522db0ad0ddb35de738e0b22f974c827b09" . + "db85ba46faf97e3c6c2a468cfa8ac522db0ad0ddb35de738e0b22f974c827b09" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + "5c7be528ff2ee179fce443f7bafe1710689d4a28c2311cb26c31a55e7fd2978a" . + "93ff3e35a5c3a13c6df7c88c6eeefee53679206f032271b42881437f4e63a1b8" . + . + "69a983ba7c0489187b239f81067d4c5a6e04c6a32be46510e414bd2b11d5ef7f" . + "e1d76764be8252dc0f6802153e10ea3ab52e8b44bec15ac528bf04bcf3f92e65" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + . + . + "69a983ba7c0489187b239f81067d4c5a6e04c6a32be46510e414bd2b11d5ef7f" . + "b2e47f524733c385d330058102ddc56f1cdda9d5133ef035440975a41c1c899b" . + "255be0db0035432ea7dcdaa17de7c6c90648dda2695a8ca7dad83f499e898a20" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "86b2362835f7820dbec5fa72eb60453763792f06ebbb08d904541c1d2bff04b4" . + "25c1b85deed1a4bfdce392e0880e92fc904192d43fdf075d94219350e04bf6f2" . + "a88725ad12044a4bdfa16058e560e61906ca28d531fcaadedb0b09bf1df28183" . + "7911b717062b55cbe6bc73719683421e07a1d04da7c168a35cd600bc048772a9" . + . + "9cd1ac85c28d32d0270bce7233b5191165403dc38a94a24c53a15bc6ebb24ea5" . + "418149ff260570b209066d4fc7109a128b2d26e232753f71f2e2b3335df9aade" . + "5048a4a81df8c2b7bd396698b05c761bdfd60ee6d164e4c092451e3e98fb32aa" . + "67e69029334883cd24c078494b921bed2c6ae422001cc04d1e5dd04b62b78bac" . + . + . + . + . + . + "048f89ed14fec1dbd9050974d2200e3433b915a49bd672232bcdea1fe32fa0a4" . + "9dc289b57d83de763ce1e93a4cfdc808bc4a537ca0c85dc883eb6ce3c214b12c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c52a6d7b701381f556368e541b316e14d359014754df7161154de6f9436ae7ed" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "3bba56f8a28132a673cf95171962206a2f53b8b14558cb2518e6cd3569c16580" . + "e06722c12a01dc283417679a3c5ffe1e71eea35734a945b134cc7130f09e3600" . + . + "9166e2ca39a1f7e3101a912c1bc8cda51cbece7a0f9ebfdeaeffef4755e4006e" . + "37f1c74a588009fe7b3b02b8f8267ab76f4cb62ae77a72a15c1e5cda0b8ace98" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + "9860cb97f1e77e88bf5d9dee92b633599c18240a249eb2c2d831427ecffb626e" . + "6c03987a8b35e51edcf449b7d1b7408e998f7acd9041298192850b0865090c38" . + "0d54bc3818d44994b97d7fc8040d3036f48ff6b036712dd200afd4d474a2cea4" . + . + . + . + . + . + . + "a7e4f760627b2dd6a4afcaf99cdc6a96ba24fdacfcd284452e97aa5852bf6924" . + "8a7574e5a08028b0745171b39d38b96a1206373111cacb2626c4e54a6a921338" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e1623d30bba740c0c699332ad2dab707a5001066bfe7829595d5e0e35d333793" . + "e1623d30bba740c0c699332ad2dab707a5001066bfe7829595d5e0e35d333793" . + "97e7441cf5cabaf41a86f814ee4a2d022bd9558b449e34217f055c0d5bb33c00" . + "3b73804f751fb15b5e506e576acfe1c97edd60a1b1f22701483ed0776c952c0a" . + "fbff4245d8a04443200c4c91587ffd373ed9cebcaf3dcc8782779a732708e7d4" . + . + "1734adde11c2e6c7f54720b5ad83943256a1c13e8a02bab8aa0d24633aaa52a3" . + "b4dda79d0072c68abe4d09ba6f403ede637f7c61af7d643c8495c51917dbb436" . + "d0741d879c5ba023272b51280583bb5a6b7d53ebf549c5750a50a63d9028e2d4" . + "7d9659310f52dffc9f934a9296be36dbe3f2e63ca6e308573bdcc0fe8eb2f15a" . + . + . + . + "2a426c9577802930acbe4d58c87691f74858fcfaec3b73d869ce7260354af452" . + "35f676da1272e5b94a89c1d879247643685ec0265cb08139b3e2f6cacfd0ef24" . + "4e75dfadeecc294ffbbd950cdb8fe1780c261df4112eccdfc943822c40baa122" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fb42e2aeecd1ee2813094d641e18dde0d0139d2ccd6e952da949f2bbbf9e35b5" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "1982734a60059b1ef8a7bd8c651ddcb9b4a1a30e261796e724061db7d70cefb2" . + "3cae74892b4e5ebf9ea93ca5d3d0b5212338c4d63d46f09f25aef2c14aabd13d" . + . + "4dda6ac3e047594736589e687d7d4803723fb06c12d4f8bb61a7ad0ccbe97047" . + "744b570cba3cd83772b7aef7753fc59c900098684067011c76e1bd022174f124" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + . + . + "4d79a116d859ed5310203cea09684ea86c49f29126b3deeab5d46e7a232f9273" . + "716061ffca4c5989052a0a9133da7a11a1f99bceb3503911ac501114269df4ae" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f60cd125168c999aebe1aaf3f711928cad9fae61d0ab55acab4ec601e607d65a" . + "89cfcde24f7bf11b37070a03edd8a4b79282ee645551f6c2767bfd342f9bc37f" . + "5ba3451898a143f85c2df9784c1a7d522073afc89d5026ebb71aa62af6a20076" . + "54fc34b29fb7ec456153d0c6df201123308d478066ebb0cafec1dd2a06ef4fe2" . + . + "5210a74d23c2f3cdd5548e9818a769d7179d0f53c8439db7052de5c3f0c41a06" . + "42644902ab09eab3313d435fa995e3370369ff492cbdcdd909399e01a76f9a69" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + . + . + "51f0426e846c67ccf3ec2640d6cc74f7d4d8b52aaec57cbb3ba17102434fe143" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "854cee6c6f809060d01c12b6e9b1790a917945ed3471ec5f126b257fe0755409" . + "854cee6c6f809060d01c12b6e9b1790a917945ed3471ec5f126b257fe0755409" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "d6aa30a909a004f51376954d60689a82b77a49491816af918ccf11e69a8419ba" . + "d0252c710d0780b731f1df9ed3d70e52a4d1d628b82ba9e7b5927f26cc8fe70b" . + . + "fd8990e6945e34f81fe4279a308546fc43756fc544e66411d7ca024d779ea032" . + "b76c9ae22b2c9c1153bf8f3b2188c297e7bc2c719a03b50f1fcc9234e228e3d3" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + "3108ea50e351957bf4fb5eb0a66011a824403be783bc16002cfe151ebd011b77" . + . + . + "8655f3dea180ed475803fe31bd37dd0252305747b37d574d412a946b3a8bb3a3" . + "6ba85d714f542303fde991e894cf3b2db1e494a9988ca811d2ed1af1d0585c78" . + "e77ab54f3e9edd1308d414240bf2ab46e0c42c5236533039624a12967b1837a1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bebd1a5d8a51eb48ef3b8c231feb8f2f2e7194a52388b4a12c8d18d75cff1821" . + "1e44d19726207014319b716ac07e431566dabdb1e6d07237d8fa1af9338d209f" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "f744f6859fb196f63dbd1cdf61daaf62ba777576bddf0b2bb10853d7bbddc36f" . + "3f44455bf5ea9d01296e2a4b70e80e20e7ef875b58febe4c80686d7e924595ee" . + . + "9ffac8441ff5e8bf0b45fe0951c566e422badde61faf762fee68501bbcc0dd1c" . + "73f21548a0979721250fc969905bf0f6e88c9ef58dddcf1d1b9e851ea8ff44cb" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + . + . + . + "ab025652771d1867c65335b8a1288de8ffca900e38ea8b90824185d975136a8a" . + "80e66530d8be9a34ee57fb803886beba94b61a01d47e276c0efb57b54a21c509" . + "609a75c24eefa808eb6ee01551c1aca914a2f69fe828f7618b7b198f29b0fe18" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f9d193d38db7d6d1d15bb3e06850f9878a8172655442e5633bfc8eb4837a8335" . + "90e392ad122cce782a13887203f200e55af4f802f991f7ae2c8fe6d5209258ce" . + "caef7f8939854b5f95e2c6519f7b5d857fd853c051ee8e839e115005ca2ec226" . + "5e477026b466651afe40cff7b164ac0b2c9c23884925758e63fdbeb5f6793379" . + "3814277da741eeb01d95643cf956edec6a30c513cf542275271457d19ed544dd" . + . + "085d1ce70a51d0f874fdd7ad2a4a9505cb259efc8903adf912a5bcc141fff372" . + "48e789d94709b3cc5c47f5b39b5f178e34f423df414dd1eb202554afde14a194" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + . + "1cd683568ff405ed355309d457636167ca249e417451e309032ee411f27e7952" . + "c21125a52b3b345e2581608f9783a1b251745255984c5a8f0a0c52c329374e30" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "1721c85ad58819a5246c4ac9f92f39722fa1f8753a4185e7802134fb3d0a4390" . + "c4baab296bcb36e7563d5d090ccd5b21d219787891dca8152d2caaed4120bc7b" . + . + "63e68bdc0aabe7588b47315ac2c436d95470cf2b0ad16b75653e54da8405d972" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + . + . + "47e5e39746171d9b10c7a17a4578c4029325a9c088786da2037d809845f9831f" . + "3b0e7e6811fab58803fca08628541b53d3487e04fc46137708b9ddc0b437f85e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "201a3ec8aee24b2ebb5a90dc19da8abd8067ae6cb117e8b5ba7221bc0fc5ae64" . + "51744fd637780ea4004e901db37f0f1ea1144dd043067f4ff8fdc589cdeba58d" . + . + "444fec5fe18063aa85e63abd5cfd72f6b4ba442b491ff084a49c7e09ab85b2d4" . + "61e81df6f81b0871800d4cf4a63bee0d0351c1856b1d70c5cd2d39773b735beb" . + "5d7788435fa39dfe792486744ee38a065c6a819ca87063e0a9d589e460c368be" . + "9cf0732ab8990ccbc27e9cef1c64ef24d211e3f915a213bbf743beca3947669f" . + . + "7c2e3387d16ad7302de94d7e4e20d4056dfdf969056b4936c829854ae3c70add" . + "fc3d90e9ffd47857d4a8a3c453aa3ed7c02af81f8b7de51d367b8e55676fd164" . + "e4c65c63b184bcd46539d74894cd72f0bd4a109a71009248d1b27d20a387a4c7" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21f58d6590adcd535501b6fe63958839d5c9b88b8f7189b22bf08fd9788b712a" . + "eab7acb160682f848a95d0d0f33552d735938ef866f4fb9b3ec77bfa6aad1751" . + "f311b7900eba71ac62b2a78d85640618ed371742c4f34fd3944d461c9550e2aa" . + "992cf9268afe1590b723d0d3ea71b0958c80980224e2634d1c2487d40e9f3e82" . + "0157d353e6b5eef64cc2b3cc1aacde0e9f3a1550662a57a867c8699d51f03216" . + . + "773881bb05d79776be9362aca2c61d670b467f90acf79d98d1e253d13bc89098" . + "0a2187fc380bc9324fbe4aa52fcf39238ab8d04a0fcd1c52be2875c9e778866f" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + . + "dbc05c8071139be5a47df64bf97e19a83ae60deb5a178e12204e96afc81e47d9" . + "60778f3835aef85d88197bfd7efacc3dd007ef77b4a6a903aee45f461b176514" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7e4393e0ac46dae081c42981e6a1ae8ecd6c990e912031ff03311b75ba33710f" . + "c9cd152c91ac56bfdc08699088c31c9325ce055cf484a7921ba96313a40f5f37" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "30a376f43deb1f208811efb62a0de4529f5068fa6ffc58c27c5c03bd41b008cc" . + "9012e41e56f320be376888a9c5ee8dcba1619868901636ad1ab514c8234924f9" . + . + "b7f05aa6e1c1d7d27fd38b3857313070a5adddc838201794eb4f0eadf1976d3f" . + "b7012cf4f11bf89c310ce93e5b64cc86920c68da3b827d353d7c16247612bf1b" . + "805b8ba16e3af02a5372d6700a69a7880e188726d4e16d875af2141875d46c4a" . + "c3a4739db6514ecc56762fdd6181fc57215547b8d3de4ed0252491023c9bf369" . + . + "b7f05aa6e1c1d7d27fd38b3857313070a5adddc838201794eb4f0eadf1976d3f" . + "82afa32c09366cbd51631fc5cc2522646846132bbabc37e0670342f9af03d251" . + "c4f93022cdda7f0aba4f1a0e5ed645616cece1f8d67c7c31662bd965cfee0315" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e589c73bf26d2305a92f5e8bf9fac56a76767f4ef880ae3a74541a4bf0bd52c5" . + "e4ab51704166445d51b502a09e1e96360737401fba4491b23c4272cc813ca2a9" . + "d90749bd1baeab383f53868270597e0b06707d6d79a8ef70feca95613b345d1f" . + "d5af5e25f7f788e5c56dfbe504dddbbdfc2ad2e75eeb5dcfdd5f7e68ea5a4829" . + "5be3db51b96e13856b7f0ceaae171fdf711a412bc900ef7b7a4fc859b74d0fd6" . + . + "61bb1d5ba79f33337bf21e67c8d096ce035e9e0cd750c98ad5af66229da86099" . + "2a75d7edc1b6e1c0716997aac99729fed590b0b871a9df9f6d26e326b9d9eb62" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + . + . + "51536a035b1ec200959bd4512c368aea73552e53d6fdc6147224651e8e593a91" . + "fa608e55c00bad020add7414b86788d5bd865f7e62baaedcda3c7e4fc0eb1a74" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4969982ba330929b410f104cb86cc8d9e598115a1751560a92cc1723f0474939" . + "d2cba348452c16b0f293fd032c921f33ebe9683a9cf1a977eeedcfeaf44c4cf0" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "d5bfa214e1655795027c409ad3f2fc0ad51182a77d9cdf36482c590ce9181352" . + "4c30bac1696305aa5b000a127dd042c379518c4d6777b438740f6c3b485fdc15" . + . + "dd47ab6d498199775698104fe86673f389e7c2d3325bd2e29474d89a6009fd94" . + "6016522143c2db31f82d1a5e9d90a7fc53c79e48b6222e81c5532f90ea156748" . + "e1c5795288e731c10d21a44c19cc98609fa4f86e1e6b3ec54b736e3ff6692a44" . + "b298d59647c9a8d8e7df3d76bf4d2c010040de4e6e02d92758f552e5c158a6a3" . + . + "b04a2e719296a2ed16221c69bbf80db45a95d5f1bca1febe2c9c581169feef85" . + "c4d0fb342bd90b98e79c875acbf995224599a340a7ab6c8ece28789e045c240b" . + "2288789e9c0e1f07c7c178552253faf7c18bece3ac0e5b8ff87114b3e181a031" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "47b1d307f1eb9fad51d0288c7cdbb84f917a678d46e84475682e6a5bf080d7fa" . + "5dd060ccda5311c1ee6681a0e8cf41e3ee8683632ed9f82af6bb2927647ab09e" . + "4bf8fe05b49a2c689515b1218e3fdbf6df58d77c5a4eea32efec00845c6a9b9f" . + "46cecb6dfb309f4ba7a51c7119317ea18435fb2ffca48891c11ba16fa2e07944" . + "95c89b3fca8387bd05cd6bb2596b1c3287a655d98ffdfa12990fcbd2e8ff24d1" . + . + "7fc127d57848e2321ec6d0d3068fecc5a9c50ca96dea9972ffc399da8e28f303" . + "1e32aaf6a8e8e8a6299e79123ba188c23098d15ed1bcddb4e5db285df5d43d3c" . + "35400d3d1d7785ac0a990e1010a632c5f776e30e4ed27cf63a06519ba6326a13" . + "5e61af98f8f14a58c5827f6b411e1718b1381fc3f482eb6ab5d4b7eabebee58c" . + "18707b8092f294026c4c762e9aa23b185a830d428cd7c0f2825e0a09cfe50366" . + "40e7fdb063c2db39174534405a5e088ab9dd82f22a67dd790340a838e39415cf" . + "1cb5c6bb8ed980c4a47a992c1c1d293b9e226ebc01451607123dbe35e4338740" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "288e2a79abcb34e3848d62349036b23aeaf5787b5f98513850cc161f047e808c" . + "0f7ecbc4d0f2bb4bb83db958b580d6cbeaf064ae0422f333120f799a972a5e1d" . + "38baebbe57ca62e27d27145f50ead473649d36321d321f1d7fc2a4b61db278b8" . + "1c6ee6acc4a4d954f08a179eea40b05c2b1a9fb487eee262312c5974de0c2b6c" . + "fb0c25b2694051131a691e01e815588ef0cb8e231f5cdcb3ef2ff83d43427b9b" . + . + "f420c21279f341658ea11b4ad926ca3e55b24e25e1898163f58f393f80dfa384" . + "78499fc30a84a2267ff68b2c5ebf525e628b7eeb1b0df35437d1b9bc6b98b02f" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + . + "ee3b43575fbf7fc8a5dbe408e0ddb2e34f2cc162c71c5ad171460fe0d3f7c76a" . + "19daf06758b8f7433ed557edb41570f0560801e87465eeddec81e4948fff9961" . + "e13826cd778fb32d5b7402740779e8f76ae3deb91c9f8c35cf1ea55a944ae160" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "621286c0dd301153f723661ce7ec2b8341895190ea520365cef56c749643d152" . + "621286c0dd301153f723661ce7ec2b8341895190ea520365cef56c749643d152" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "526588ddb36ad1942a6ca35e5bdcbba0088c7d34b82e4abdf60858789d388d1c" . + "e8e7fd1e349fc86f4284bc3167ca95f1c1314ec94f279dd4ede26250e44eb999" . + . + "0ebc003f525ca8dac00309f543ca3490806f4f0e37200070ef5f2d1649074c66" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + . + "b183561b6915fdb0dfea062dba92a0cbb683e6274fe48bf8318a96597660e17f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a4265de9b16e5795aef3cb21942f2ef4b8ffce767c1357cef1612e7bf5e0814" . + "9a4265de9b16e5795aef3cb21942f2ef4b8ffce767c1357cef1612e7bf5e0814" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "e26784ea1fc24e6d68d1dccba9af59ff9bf8a615ccc187957be67a4fee6c9078" . + "281d0751bcfd986e79c34f6abddc7146f9c2c3f5e2b62bcd03214dcaafa28449" . + . + "bd51490951deb68a51a1e4f61cdc5608e8b30bec8c24723197e5c658b6b17cfa" . + "018e1a889a8ba0ce8dd4e5334f3d979f7474a38a46b57eefa96e18f4d0476ca5" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "3639ad2d06e28252911aca470eaae1917bb3fa849c1695444cb8bcd4099a188a" . + "1a6f93440c1ca57dbde210d6568cc5090c2adadcc6f58dbf2b568b108bdbc465" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "34602bfb1b923926a899f1134ec347ddbc416f64af57f39fa84b0ed22dbd74d8" . + "80894f278f58c821fba6dcc674ae1f26d299e35924520b4aa0122ad5667c6456" . + "27d7c61819002d137fffe479a8a42a5782d535b9b3e609f44e613fdf67fe6ef8" . + "28af1ce692ddf2b349ddb9beae500b03d3a8861ed0b224eab4996feeb575123a" . + "f628b888ad16afbd8d399540e2f72e876487c91906f823158165d172690aa1d1" . + . + "aece12ff2fc345785ad976cda625f8d075f469f1326fbb138123e084cb677d3e" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + . + "5a16773e34c631a1a5f942891877758e7baca6d07b561075a25913aeb964c761" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2a36f7eb40f6c0eaf7352d2e3d3a293a251bf3bd69548e73d4c60db1cfe1e512" . + "2a36f7eb40f6c0eaf7352d2e3d3a293a251bf3bd69548e73d4c60db1cfe1e512" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "39a7da3b02d52e2047eb6c01926d600d9aa922745a30e0a23f78a8f83f1bac1a" . + "20dce86ea0d5544996f788aec10af150eef82a7f40b6c8b71a458574d8b0486a" . + . + "87daef40ebd4c3696938a27a520f30196bd58306cd2f6b52e88804085e53917d" . + "7a5753fbd79ac692a03fced14c01294b42cb96bf067d62eada026ccb1b6bd1ef" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + . + "ceaeb8379898974acceb3e22ead2b1ae1a700385f7c00b2bcd48633ea2b3424a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7fe1cdaed5094ae19443ddc22acb46faca3f720d7c7c5b5e3a7bababed75a509" . + "7fe1cdaed5094ae19443ddc22acb46faca3f720d7c7c5b5e3a7bababed75a509" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "46238d30265d238d9568b02e423e9dcc0a680bdb0a4abb28e04116def12559f0" . + "952ebadfb886da1e69f4ce5ab7a21beb7ef616e89bbc9df066771f4afd2cb98d" . + . + "c620a2da09ff86fe07e840a76caf354b763e950658fb82d563aa0edf826e4073" . + "587df7a19ba4a90b1493f4265f1de6c8fb52ee7f6c9126acf502cb580449e4c2" . + "f37f763959548f87b52d9ef3d98eacf18eaafcf23779e205f0e2bc982cd42617" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + . + "bbb4e83fa2586f033c02a699d209e65d737e8ad499ebcb2f9f12592cc429d9a0" . + "7c102c33e0255bd5fc46569ca645be00990bd890cfb061244c0f0faccd6ca772" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0285e4e5fe69f0efba83bda588625682fcb1c28ada620de2368419ca36360bb" . + "f0285e4e5fe69f0efba83bda588625682fcb1c28ada620de2368419ca36360bb" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "79f724cab62e80241ca79a0bee8735947f61b5c6f7c00551f0ecfc98d666fef9" . + "86bb186a2a5efc9c3da58c2183aef240e958a17ed43d5198c19b0070d48f6bb8" . + . + "b3c82bc5f85f451a53f591f97ed92ab0cc829537ad97c2c40bd90124bc9b16ca" . + "e71a0322c68082d4dd9ee84075361f48f3a92f1069e28e96b30331bab805ceb7" . + "49fbc68001e88e1d3fcd703a9a62d920869ebebff40093496cf31a3ad3bdca37" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + . + "302719a057623c5872dd803738b5cb0507063f168836d0a1fb6316122cb5138d" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4b78dad3098dda238fd52c8d59e1eb4ff8bc16ed9ab5b48b60e8149f551e4cda" . + "4b78dad3098dda238fd52c8d59e1eb4ff8bc16ed9ab5b48b60e8149f551e4cda" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + "a14fa32d38a3af6f98fdb8a7d2014d854960f1b2da15eace216f01a62b8e43cd" . + "a706bb0b68a55225bdf9608057872554b40c2174b3d9029fffd51bf051060d03" . + . + "75a58858393e2be0c49c4e91003c9d44c225abfbb65f9417bbb1635ccd39b248" . + "15b216d2f9c6318aaae668bc87954c4e3acce42872c62d822c336b63f0c51bcb" . + "f464cd14fc43c86fde02e2120e225c8a4397b766c48dc18a94033791466f0255" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + . + "33c402b9fa815319e8df9ed8ae3dba241ddf2036f5951a59e587c5d9b8c60965" . + "493d9319a7bbba0daab2a197a3fe90552c67153a03236a365aae015c0342df89" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "b843e87b181b3fd38b386962b2a9ba6ca13263033efb68a73974d47e094e0fa4" . + "b5523cb50989d4d28fd29fea32397f9e768d5053a77a00d989120323e2dc2882" . + . + "583323fec8445949a090713676433c0d92c94e5ec821aeea6ae9f870cd32ff17" . + "e213a38635da8690df32214ac6c0f27c72e9245f003b018be890371603b3f956" . + "20166b30dd3d68b688197184fc40c9523f10f7d66c23faa013c5f8cc62fc7ba1" . + "173a57de87be676f0aa989b3c64baa43c495999d575c42f037726ede4d73bb7a" . + . + "807195c1f3135b8bcbaef834bddebec03f3a19eab8102510a601d509e5b2d79e" . + "37ee7eb0675acf77df43ed93afc81f797cbf7eb89091e81c6c1af25f57755839" . + "3202407b3cb7b8a67ecb79a891f47fa6940588c7fa7475ff15c3e2387d760f12" . + "4b798cd3465cd40eb662a4d48c2ce8e3aa78017a0183a80a14da1f4974cf7547" . + "eba24904bb2c721c854463ee61959282c76a270fe069c0abc6d84b56f938e549" . + "d19731a1053209105921020caeeb081b79eab79b35df0409d4234172899fccdf" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "599a2792250b5bba2dc7f739bd05e4f7c182b5981853981b40239338d9e1c7ce" . + "d0d8c06d72f83c539ebaeb1a565b1316204b2866e52c43f463e2dfbfc174e2a0" . + . + "a9157e531d9b0b37f8989a156736d8a82b9a416fc376b76207f7dad14ded14e6" . + "7274d64f89ea26e7136e7bbe070e68a72fdf17c7b0c984e48374a046057c32db" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + . + "b7d86cfb65575eb175e39864682882fdff1969d655b4daeb35dc122e56c91c40" . + "8acd1f109b8be917efa4459e4a51c09fea430883ac6db6add6b6e4be05eb6723" . + "4cb3e24908e5ba6d4a627adc3924e8fafcbd3ca5b0ba5e4ccc795634f9b9de03" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9f5641352cc6a8993ce90ff0de3af1fbd44099268aeea218eabc9b5a69885107" . + "9f5641352cc6a8993ce90ff0de3af1fbd44099268aeea218eabc9b5a69885107" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "df1a352b9c3a967b93df0a6c39d191c364b779537a11fd3b7ed872f83f752cd8" . + "8c1485610839608e346fcfd7c485f07e308dc9abb1e9c6594220fe912b62f2f6" . + . + "8dd6482694ba9d4f40874d96bda9b5283136ef80b61d90be3d5d5ff46b1ad04f" . + "6e8819877b9b63a5d265cd2d6505565f2e7decc399252e482fde4a4fbd41c025" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + . + "52f57598db382f9afc7ea8c162a9f01ed1c4efc22145c823c3bd7b6a11387e0f" . + "7f9283dc219f3fccd4fb712a8774898c2f5b325f626958a39ab1befe6cfca655" . + "9061b5304e2237d8f0c9261116a37573849b0ea29193419abc0ffb1225be7af4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "986fccdd87ff1ce833a42edca0f1d970ddc336cd5223a5fdc4f482d933b26cf4" . + "770c0e38236bbdbe0555fff12e618737d9814b19733ec336b8d2059890d2a4f6" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "fa3618944791fae6790dfc37ea330b76946ef6a2b79b6bf2ddf4c679ee6db98c" . + "ea1ea507c5292ad58c1b366fa668f135bb70c16becb122781baa83d780032ee7" . + . + "3f4395ac46411e59ab0282f74ce658f0b030f587817c177d0972e14bc4695aa8" . + "1fd68f11a1ff2b2c1592da83fb0eac5bb641cc4032330b81f1a99f573a6e7cfe" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + "35daa46fde9bab362c33008368dfc3d45937f37c3d527c50d745537297034a0e" . + "9792da6b035ca637df698e238acfea0f7f6ada5136c744977accaa56ad78e3f0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e88983801d6ae63ad1a4e84bae0fee3587e77d56d6052296adfe24828f386ab7" . + "42f91c3f869af0d75556748a619f5f190ab53aa8ca3f361617e97c72cd656f59" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "8a55c576c11af5e84117033b380798d2dc5babd0534d92b7d6a476d1f005e563" . + "b4939434a79505a4646bd6f5f0258845809dabd776c029241ef25eacc65a5a2f" . + . + "534fb6167908f63b3ed405463b5358eb7831a635724708db341cab85ab84a248" . + "8f8bf9a7da78cfe2e87529e4ecda3fef88b8397e679dfd8d4049257e14b59d0f" . + "bcf11acfe54b36dcef20b8e497be7b6a582ad3cefb1f9ed2e54161f6e1264801" . + "b1b912994567a974f018f65465d248d5a907d0e0d010bbe3791aad61433a124d" . + . + "400469e8b8f5c1c42ac213eb030923c959841290cc92685ef2f43e579a62fe66" . + "9311f992e660661cce860aa756aed118b59e9970c10e83fe1245f3f68986c7c0" . + "9696caf487bc2185d692a3a464fa06adfc6e78f7d16b15128f773f2fb6450238" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e3be3ddde88cd4bc38c490ba5647592cf86cdb8db0cc44c302e626d26a08cf91" . + "39e28c34c5c15f658d90c1774fad31ecf596fa9a3abf1f69b2bda9fed5408c72" . + "20b9be7807fe9750a6e36951f2dc43eb16dc1613cfced3e62ea0b0a17c791619" . + "553e4b26abcaf80f545a7be8348a3bdb000d5f9a379e1eaabcd017653223feac" . + "129010955825c5aec2d04949d8b44f860f26a75a693be359f966be7766536aae" . + . + "7b09ceb4cc1375a132e372af5475aaeb0c26d96ab7e1ba3adb49dff328f74070" . + "adaf9295854dce772a018e552eabd1e22c7d350c754898209584d7fd177c6fd5" . + "061df6f896d4379d39dde06394a538b0416257f2c45b07023687540ff96deb69" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + . + "484a4946e1bd41c67db36ed059062f6d6349ba8adb9b5aee4e865d513f3de7bc" . + "b20dda753c41c71088abd3e276d36d5268993cbc42c6eeadf1090822fc26a20d" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e3c0eeb87e89565f31f9c708372aad154af376480be24cabd8ab2e80b8c35242" . + "e3c0eeb87e89565f31f9c708372aad154af376480be24cabd8ab2e80b8c35242" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "5557e364f8e52b2233591b9376eacaec93c7f1b144c9d55d0d11e0aa26ba2ced" . + "a00bfe7c269c23c9f18c92c1fc7b21e0a8d6edfef7fbbfcf8a52c8a125a335d8" . + . + "ea3c32aa75216cdd716fcf3ce17f3657be4131f13c4a7759f5db4effec034b11" . + "c128275b8b8f03af4a4539efd5d00dc35725e03a662bf05a7c4a88368e2f18d0" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + . + "66466204ebd1256fb94f6b22c9dcd2eb460739943eea9f94dc8657687ea9d7d3" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dbddd8464f0018fa6158a9cb156aa7cb60c6ed87d52519b78abe3f2377a25ca5" . + "23c3867c49946518d791d309109bdba13bdf6b2f03b19450813a3dae9266fec6" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "a8e10b12a99e7eaf66f7954a55a72ec8f10147ca97e67ad9701575b0e35eee76" . + "06ae63938f869fd1579a45139f3969fe420b54657086bc1624673ee35eb1be62" . + . + "bd6c5ec55595a818157d66f8797a0be6be93c964ce4d90edef150110783b7e48" . + "2e07b34cf72d74a7553a2e5c8aaddaa50388acddb5d5fe9d6ca489ca7401c0af" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + . + "9b4accfd4f26c85a9f5c483854728edacc9521634a66a459b8b57f173279b69f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "01638f9d8428bec77ca18da05273a467aa9567bf0abf80ac00368b46e4ccb5dd" . + "01638f9d8428bec77ca18da05273a467aa9567bf0abf80ac00368b46e4ccb5dd" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "74cb9a2b57c3471ae375bb90835ac970fe6d366f161805674a1739446d6886ae" . + "8b0163d9a5c797565352b3b329cd985871bb165839a291278aed692abe4e6b9d" . + . + "0e6d92c3ea01f1950add67e69d9e9d5ee3793a624995f197312715b037b354d6" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + . + "e82cef4ba0be860f271200f071e2da788b6880b74daaef81005b2c3dc52b1746" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f209eedb91db1da02c7368b6cb6cf691b123c3cc266c6dfb7d1e788d5a3f824b" . + "ab72778d72b41edbe41544aa59440411a790013db6357ae91dbae1f79d05bec3" . + . + "74072b7282a192fc60f711fffd7408e9850f2f829c826ec72bc1db8ef70b5451" . + "566f83772221a7e025f7fa0b3efc45e7130ceffa0650a125e4500c6cce84484b" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + . + "0e9919399a8bde9862f1bbf094e86b8cfd8ce687138812b5ae506b295ca27631" . + "cbca51ce875be2b242c7993ff5ddad65b8f4854e40f32aacf3e105b39990393e" . + "f0a80182885e94303a08ebcc70b2bc806c3441c4a36ecaba460fb63defd999aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "077982782381972cde3c24b0870b227038778e0272a5af847ae17893fef7d5f8" . + "83b6365e8bfdd88b9aa9a0698690b9ce47f810f80815afd256fc38b1893f67f2" . + . + "28b75d1a471bf8e621a60576cdbcdd1151179d1442e407d53d6bf852ba793126" . + "195101db651cc1f4df6760522cc60349e02417aa263102d1783579fde4973a54" . + "231f2c62c5983faec5d61896d480c84cb0dccf1cf16fbbecbf128c7af1981281" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + . + "4c8eb0dc77cbcb023bdc125bd188ed4af3a2237bfdf840b8d8b14f0cd64c04a3" . + "f04303602cdb08356406d3dedb1e823e66274f7f3314e5d1ccae417b7497a793" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ff2c9e9745ac53611db40f8e97acd137fabaca24edfd5c29156efe65c9805326" . + "f3ea03507cba78d83af02d9259ab2dd0cbaa77493c30b969498b6e7b78342670" . + . + "124de04884fb0044b7c7c5c4b25728a5e27a6979293e6290e25d50b60765c643" . + "3d8b82243cdd6b6662cf68d36a494c24689033fb938f5f7d612b1f4b71d51c53" . + "70eca76bdd748e0574d4a5ed104131f1d188147306744893f33143e59236bc17" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + . + "01254a7cbf19750ab27519efa517494d21423447cd5b5fdc331be09e0233e9de" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8770f78babba01dabdca9ed52f93b7bbf44d3016129dd213a02927bfa6063208" . + "8770f78babba01dabdca9ed52f93b7bbf44d3016129dd213a02927bfa6063208" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "5b5b6948215f7789d456fca974b3e952d396cbd137ca2085881d9fcb86ef10ef" . + "ac3f2c232a4ce53115591af400682ab8f0f2cfd00c205f66506e9dd71bd64a29" . + . + "7295a40ce90680713a0c65f0a471665196c7f788bbb338989f77d56da411571e" . + "89cfbce288db06f411dbc7e80a864f30be7207488f27dc2f038300871d7dcba7" . + "45640839700d5e7a9ef3bad6b15cab0266ac34eaffff5a1950bc43d9658b7678" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + . + "3a43d2b80caa795922268cd91ad33a7b260fb0f9a86deacd6e895b5b9ed5889d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "adffc3224d7e0e1b27be95128bd3ab7c58943f5f9af8a9500456170325f1aa6f" . + "abd40c2cfb9aac71cee47ad04049e6e44ef191766f0b28beb0bcae49407c2d04" . + "9843786715701604b4f4e34b1bb6fd6111bf535abbefd29ed9e25c89d2ecc548" . + "da5a41f212a8f16200caaaeceacbd8dd0a803331609e221ccdf5c9b4d3a903b2" . + "9a4cf36a54b7f3ac37693b1f7e569356d9f1425e71e0c27601c8644a2102cde1" . + . + "4925c105aba97f37fb950794fb98f1475ec9a0c412496ad4c6db4af1807964b6" . + "314adb2eaedb50463b05c6912c97bbb38ab50a8618ee8f5af48617c7eaa5cf7b" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + . + "b7f82995959637a7d90b257c6cb4fc00f76702c443dcd21770c1d2e86ae469a8" . + "516e422fa678a3fc7ed41ad213aa73c4280d0360190789cb0c6bb2736a0f8e1f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8bb1ca4096387e34770b25e600b13c29a6eed81090d7207ccf3f005573d6f0fc" . + "f535ea3d7b5a96a94a849acf85a7975e8edb6946afa5b0d782b342abd6f7c067" . + . + "02cd4b1e176cdfb7ad146a34845ef58434e9d0267d2331adf1e90f46e0ee238a" . + "e62269727d368ba45bde5733178b55a2f459c5b3a4d1605306b3d9f31e781cdf" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + . + . + "0bcce733a0db980390e096d0a0de1dcd94019d0485b42ab24c2660e52c0fcd21" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "160b692aac52069349b083e13694730a9bf93c2d065484cab8ac2f09339d0e74" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "e994b8d1306d44e03bf1543de70832f56ed9051969a7e956ab11a8cb4f576c9e" . + "d7f94b90328c26e9b38377e23b75d4e6d4ba40204e3d6de7f25140ab7f580591" . + . + "b0616158ee8d3e553da6a2080fc7bd24edb6216a7815de9adfd84d33e0673155" . + "64bea362e5ecef107a932b8d87196fa13ea3fd753e3446a2f0e39bc3f99e8302" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + . + . + "3d3abf7fc75e7d88503152e0cecdfeec6e795648b4f5569b65df294b41036606" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "12951ca8781b4fcc478f0f3875f239c571da3cb55579175342e61b2b7668a456" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "bd609470f3ae1c3cafbc424def9559bb106010a50d861c3f9fbdf16574da56b4" . + "8f34183a715dfc7a54f8303edc25f305024876f09dc4efa43ba8424b84cfe8cd" . + . + "af49eb7cdb639fcd3d21e1c8a92f0f0087c9f7d6c2a9991430e7f6bd422ddce6" . + "adb0649a6be7a924833d56268ee1a373c6f7fabf1f24d12c1b28fbd9e68ab70e" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "490fc7359e40ec4bdbd12930d6cde5a822188f4c5a583f20f1771bfc40251e26" . + "e9b2ba9b993a266ef1cfc1100734adf95d06cec6c3a345cfedb65adc32188a57" . + "82ca38aab5c4a0a4616d391c03dd6403137c9817da5f2582bb41bcf150e99bed" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "457f92d15d98d1c8740eee32c35936327ea94a4e670c3130bb620dc44ec7bc39" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "5c6cf4b65909e1b1305956474601479cc2bb921c4ac8ccd351658214f9ae7f7e" . + "7de777c50ca8d380479f47437e30423feda959176bbbb57d56333c2b752d6a11" . + . + "ddccca26363c9dcf63fec500f0bc29939e1433cb1d840595d3c16493e0d139e0" . + "67b8d263277a0956169a8e86141ba848e476bf1c5cfdbae853068fde849a4feb" . + "1380a6d484999aa8151c80d5a9b8a1e61404ce66e505c7a2d609e5b47b0165c7" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "e16dfdd330e490a7039a845b06ee92a6c938869c975e0e3cb697a378cd49a3fa" . + "4733f448511c11728d036c2e0c2bd2f9acdb7df35040e508d71abbdb554c2143" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6016fd4698430031f4e73414129d48d06749e870e4f75fd136fd0a960fb060ed" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "d0fba74e545b4addc39ec7337b8e4b0461b44ea3cfa7ce9640f46f1571bc348e" . + "7f1808900be9b498fc88f13295349125ad916035ab782b57b1f586d56012c741" . + . + "7e42b239824f74793472562f7ab1eb08e3371baca4ec18b734171600016d1f12" . + "b6a6a0b768ba3d4671625ed5ae6f4e73e1f64350f841b70fb5dd118f5b4b9abe" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + . + "43ea53394f0ed9b51e6b534cb22beafbe48359c496bb43767a452be8592dd529" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3f9968aac4953e8908fcfa13ea925133c84f09662d5a55144698192028b1f176" . + "b1853aeb02ef41a80fb60bbe12ecd800d79afb383024ef1242c5520c33415687" . + . + "d20b9e73f9fa5694241ca793d483c08944a39bb0db4d1aff1e06e45a99c343e5" . + "e3bb772481dd056f956cedfa24bdb6d4ecb85f2e68064f171654beccadede07d" . + "27d7c61819002d137fffe479a8a42a5782d535b9b3e609f44e613fdf67fe6ef8" . + "a60be5d0ec629f2a85f9b61b0a6851f07258b6f742c878f7ab7efcb2350dd12a" . + . + "4a92507b5c10e736b743fdb0c009e46e89875f5ae0b04c27d179256878bb4f87" . + "8bfd0bfb45f4648da6433defee8998e0792c635c927b085f81b43bd52f9ae47f" . + "ced9c1d1cf634ff99eb564b1944445ab99b4c7583d0fcd7259b42b474eb8c790" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40f127a0d27a46836906ad3f0059ff9c1fea9b5c2f27198150df048f5c589668" . + "3393f02968a65e1065c416d5908427521cb3c67743f503eb3ce9e670613a245a" . + "7415e3ca5881c7219c61e67db0bb32691e9ce7af4302de025c17ec105a048c63" . + "73d5aece7ef082ff2997711408e03d7ed47e3f73f9b85d7224327188c5507aec" . + . + "ee5585c2c846d6493772a865984e9d66eb7cf554957473d6537dce6c99813701" . + "e936f86a6c85845f2748f4a0bd430335e4abcadb249ca17d13b1d3c50c829f2e" . + "6171d8906cdd17be8d1b413eb510fe4bfef6e08ac99b92dbd66bfb556364d008" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + . + "05aa2c173b2401887e3976020b089433daba492559f67932137292d8074f7dbb" . + "e853bc1e255da723540edc270d85c3a92da80e12c92fb66d56355628e762fcfe" . + "65da0856721e4e5c2f1428b06a9c4cc09dcd9ad0c2efdd33fac6432d2e035a38" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "623cdcad9ebf571a67c421c95adbef1eec7558791325369965864869e8f7e1a8" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "bc0df118f87ebdb78722e488af9b329b1a2039dc92ee3ebf6415957ba510ffd0" . + "42475e62b7c63460c895c9490c76e49f6793b1bcb8b1c554d054dd9b4fb69e6d" . + . + "c6bdcbfdfa2d6391ee45ac11607c45d693b59dcf8249151243086983fde28a6a" . + "70181f8b7c87afdb01b2d6315a7d675f66d2dd2638b7390ce9ead56aceb14ef3" . + "45a2a031029063e2d446fcab6ddbe5c8183dd74aee5cccb81ab23e4305f5d5c0" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + . + . + . + . + "b0d3cd0bda1806c022a5550625b1404c94bd2a2ff98ac268d857137a5bcf5cf4" . + "e824154bf3cad7b8cf836fa68ce2d64df1269e796a4806457ccf008932c41a30" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "674486b3241a46a64c0c0d7496e248ceb08456da4370d0f47b3c06e844584e0d" . + "49a1615ea2b5b382d3d9b241aacb13c0259e8619689e4f72b89aaaeb1bcfc9b6" . + . + "bbd098f33f2ccd0219fcd2dc880e4c9a47a1f9fd02d638d529ecb5212499ea76" . + "8ffdada92dadcc35c188d70c57bac2d6b0de8e1140c175593e8cb4cee091bfaf" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "a1edf6de105dc5f296842a17f311cbf2322ff09887cda498083d8ff732f996a7" . + "3193283ee434c3886e5435be3f0b9c09b9801c367c35f099dc0a930e0c62fc89" . + "b2be9443021a33dd2aa4f9fc5b47b0f6f815d53bc1263afdd8455e8383f2317d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "70785da583227a140bd8fce227e7454666d76af34c7ab5fd8f011fa4e31fce20" . + "e1a802544645beb87c65df7631117e1710ce398e34baee51e7c347cc560044e7" . + "df9079fa33b2d0c82a0eb6ac987f732252ca02e57e453cce078378bb9f9124a3" . + "1019e57409986f33fe929f539af2e0d11378674fe161f4cd38747ba0e9efebf4" . + . + "b2d5a4f6c30964b78bf7d58f1f4b9a54e64b9088aaa760e1ede15ae39b668fbd" . + "1760db0474e9e92b0b949414ce75b61348937fdfbd22ebdabcf46fa5ab373ef4" . + "8f9e48ff5cb39f83a7dd78010435226ddb8d6c75cd83fc0a2d4cfe69d8081fe6" . + "3863faf4f5581ef3b28418447de6bb81e5a05926602d36d5eadf12dcd14d5c5a" . + "615f1ea111579db427f08724a43fbbde10ddb109c30db59c4fa461c929f27678" . + "846b453abdc6e059a2a954c36ce970fb34c988a45a41e6512c49be7989ae673f" . + "82adfe90623cc2e642d22df1398be9480531b9aeccd6b5a0ad11dfc3c6a886d1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b77c7ff1fdc07af34e30c51341e29039c23abe75ffc66be9dbeccb3f8866ac3c" . + "5048a4a81df8c2b7bd396698b05c761bdfd60ee6d164e4c092451e3e98fb32aa" . + "a26365d44a1728d7f809f9333e333c8d99760d181da3c4cbd7d89799ee2ede8f" . + "4a0be7bd0e269e1f904a21496d4a1e68aecf1cd5339af705f29807ba3d3dadbb" . + . + "336ecc0a5547061fab6c9e2b05b01ef638b23c020393a2bc3f6074d01c294cab" . + "853f4afb3717cf4c050d9cb8373e7e8daba536467b6a0951649ba0e2080d15f4" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + . + "7ad5e1cd48867359f293c6c416c4a0c2d9faf02adaf16b6b063a0d06ba5d66bd" . + "82adfe90623cc2e642d22df1398be9480531b9aeccd6b5a0ad11dfc3c6a886d1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aff6021418be751e743a5fb431d7926b899f624461a9ae2527fcdf774045271a" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "64fa81cf9223cad4dc0d0ac15128453670adfa9f770bcd0ba7dc2a44bc3b881a" . + "5ce4195385172e455aa89d5fd09c202cef7740d84af8894b107bdc86559d5f34" . + . + "889f78cd0d0412bbb7228409d6cfe2e140b614cdb034c395105f32099f429db8" . + "8cbbe31ea2369dad986af65dcb2c6830b6fa469af4e09acbc352e4a2c59576bf" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + . + "f50a88c4677d098f444fa8613d4b717560d4d05d406cd112f117ee02a9ed2552" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a48f4c12927071d52d62d719d32afff976f1a8d972385354fbb3dcd6fbb73c5f" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "67c4b811981cc757e015606185333941437a4d18bc3be1176b6020a30063bfe2" . + "7727daf0bee1c0697b85e21d87c7091d60e6eefc59d8d6aaf9a5d67072b1df50" . + . + "ba72fc12257fdb843c61247f47be551cb630adf645aef4e7b1b98e9b5de73d30" . + "9af1bdd55948c9aec5d758383d9f7afc584ec5b585508140598bc76a230d85d3" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + . + "8c87c41916db01394dfd5f3edaf3d7eab763fdb3121dafecb844d8850e3010c3" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f197dc07f23868f85756da690d60d924ee82c7be49239ff2efc6cb23b654a007" . + "4f1852774f1625de6eb3360245cf263a66fa34b660e1245d3b4905e22ace1171" . + "096690625e9875b9a308d65f5862d90bfd74b2a8ecf8172c30bcb6bad9a68db1" . + "defbfab14e4c7706f2bb4414602014f300864e99c378af84cecd21b6e331a9c5" . + . + "af163581316fb38327ec037b14d77d8e6595f214e1d32303c713a8c3960cb137" . + "53dc7501de6d0f011d039bff639a843493c5d6e5477106a08f5c50710cd6e83b" . + "865f407192248aaa380c16019d4519e76e5fcdd9b486b50ef8dfd25a4713c705" . + "d3006fcdb4654832d72ae96ba33e61cb97dfca6d7fcfcbb90ab9fec552bb966e" . + "5e77b2f2efd6462132dd5b7cdd0c29091ff78074bece054ec0a7a153bc66fa80" . + "1289fac88c9b76d4b10dc65dd3f028213849cc12335a04855d3735cb29edb434" . + "76f6e65ac87c8d1c36452a2ccdbd5167c94ac7c7ad66592fbe440ed11feaf675" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ffe999f4004d6cd1ebe196a1660dca4919470b5c37fb6e09803af274fe9be7e6" . + "7a1b04a93e600aedfb61a1824c7030d6b3cf1de01c76420d9a70b53e10e0efd1" . + "b579bc6415f37f277111e03133aa8db65a4b8bf4a5a6d1f90ecd20188b26db68" . + "f64174f0a8c7b4a40eb7295418bba7bcc856d60c461407b470cfa1b815f8c8e2" . + . + "f3d8ed1aa6c91012bb3dcae43dd5f564c2ad46f3dffd43cb74b457e5a5580e7f" . + "a032db9a2e0794fad9419978e96443d5134ec9eb1fa5395e32d15973a779d132" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + . + "a3fd10e37670252ad072ded2e821d18c1a60ebbf054b451e2989fc097b9a0da9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2b0e44ba569a0229c6f8a5571ee76806ab9475d3b50c6a307d7382d354a445d6" . + "a9c2d13bbe5543d884f2b9ce4dfa5f32b7ed878fe45c4dab6bad3165cd66d980" . + . + "88f034ddca0a86aca12f480b6952d4be59ed1ae681ccba95a1865c838c3bedbd" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + . + "4edfeb419e8b344d7a720fda2eb106994482c2f3c538a3bd3ded308dd8905565" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f2b9565e0d4127c8f54a7f7d4f00c427dccf3145cf4455aaf5694356466072f6" . + "e66fadf580b8e99a8597cd39750f24f372bfd1439674a39eea0cdeb670481afd" . + . + "4394d3255ad2518a6d6bb95f533440039d500db198a3c733c8400dc22325a395" . + "8c1c141ed21de6118549cb10c5fd71353a29c4b1324944d4eb4e6b67a3b5f54c" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + . + "dcc07e33f5c8fad61c952038a203c77ca6562d30382b512bec3369a286a35239" . + "0de043040f37624b6a9ec8bd5964f21b3ebd5641341ca10dda46de3ebcf6c49e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a5a3e2c90a489e930829be2809d90e29c8ac845157d7bc6c747cfa09294fc7d5" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "94ddf8e92dea7d8ef7bd027cfc1a7fbd2a3c31d827794e9dd77f97756a6abbc7" . + "1138a1a0060df8ae2456711685c28a801099f61867926ff32f242abb0598deb6" . + . + "2d97bffe81d7a394f4cbbdf160f8e5a2dba2170ddb9d1698d2a6f55e2a6c3f48" . + "eb0dce62b1a3d7165779fa40adf8198b3c5d5b3ed42010979351ffce753c1ada" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + . + "02f817db9be6cad7052b394d5e3651d68ca1bebcdbfe53a6e5f122130ca07f6c" . + "ac953143775612e6c9dd5b9f311a4901208eb3db123c6a73b8f30b9a0cf2dd62" . + "4570c23cd685720d2426cc8964f0dca2f0cbc3e50ee91c257b47e2509466c7c8" . + "bf99192a812567fdd860d66d86a15fe0d2b7409854eac3b9d1c2b0f5534b5a25" . + . + "21bc99bcb643c3e3e5a472d37ad1bcaee2b06bf96c2ad0a1016bd5326aa0fd93" . + "168e5cbc07899f648fb584f7194d165a9ab6776fd6c26e1847d8940e1be51322" . + "beb479f3c195101660e285c4f90b75e296ebdc109788a13a3572a8787c2de3c5" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + . + "bffe96801aaa9382b5f98352f65372945b7707db346045941ba4e8c07a6e1851" . + "cd6394a6e5e01b60caa2a8e167595148b5ee8333c54197a917a9494e67570d4c" . + "dbb8b64f38924d44b7a3773764ce82131b4e235c0ee109522d6f5d2a01ac4583" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "03b3146d022983b321300e9df68bbe3846c37f3a292a35771ae85e00e2ece1e4" . + "f029b47111057d9c19a8f46d6b0932725c36ac1790f2f92cce0c47082edffbed" . + "086283443b5521138dd4075b437bcd0a46b0de70e548788f26818bb6eef0d688" . + "a4e3697ebabf9492e0a5bacb6afa4b8f430b169871acd245cf62e2ba039aef80" . + . + "df69af8e817f914a1c0439104eee7764cb3b546734f0397784fb504b882659be" . + "acc19f37e454183f94dd28acdf5953ca8b75ee64531e0eaae91090778ba73d3a" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + . + "8a25da6274a16609ed42a49b7b009cb5d42958328644801a386e6d4ceefac98c" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "2186497fa78c8c5ea050c6543dc3fe33a839778b54961744ad2d369ae7957be9" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "b466dd552918272ebf32941b9d45b268a88990dcedb6bb340e3b9bebebba33ab" . + "d38b10fd4becaec28da3a4e9a41846151aba96400a759a42bd009282ba8b2525" . + . + "8a4558fc8ce86e617bd64614cfd33bb9ad3e4c9df8da69ca2e2eedbe45fa2289" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + . + "8a4558fc8ce86e617bd64614cfd33bb9ad3e4c9df8da69ca2e2eedbe45fa2289" . + "0db7d2fce511bf2046b348fb0d06e846bd93b525d3c144cfa4add5b5cafeba52" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a716825d9ed5b8ef3d9b9fd9ff4efc2059c3676f10b33c7c94358698bd2f0a3a" . + "329382e8efafaaf07d6e8fa0fad58b90a04be2d3fa49db9d48e19a52212eb102" . + . + "4f8e89938de323e685f8a35dec36eaa3ccef5ea8b094d13727a1f0021f094068" . + "3296001dd46a58f89802db9d34a508d1bf7662953f4ca1d8a925214fde023727" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "c8512fd7c18374867604d88d1e61e17b2b37e09a5428036e52b082788c0d6e29" . + . + "4f8e89938de323e685f8a35dec36eaa3ccef5ea8b094d13727a1f0021f094068" . + "14032faa4d994e0a186858f4f239a77ae050cfc9e7631ed349c8fd0dfcfe9f3d" . + "d3dd7ae7244a2021c8d566deb15256359c508a6330d5eb0b6f7e54af1fb65c75" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eaf6651339526ec0e4de2c23ee1a24ae9a3856c2b437af9af276c261c8686740" . + "dd8d3e38be817bfc9386543b369045dd88b054c3bdf32ee4423ad5d80236d762" . + "bb4f8d9f683ff39face25e27108c59bfb0205d1899413c452861c9ae34b36328" . + "434a28210986325501711bd80bb7ea362d8fc8963ce4631c2dba29dcbd46a689" . + . + "41605147ca25a8f2500460752288b5de39d3ecf87308f7742c95c36ea4925d2c" . + "60a8682a997363fe0bd5ba68361b26a891444867cee824d58e494b63cf3f04ca" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + "e3ac7152a4d58e15de8d215f780aa5d52534948b196c08600cc9140da25a3310" . + "b0b39129225021306ea6521299ec4566ab267514d7133572e0be9c2e9e502bee" . + "b018443ad6b5f2ed49f54259b2f8541cdea2716eded6f59991573e87e33588cd" . + "14552ff4948381d84f5f3e09719faa7c1db5f41d23eec3d328d9688c0e1a58a4" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b6ec33eec6370c30a325999630b6fc77d62f1ae67d8ebbb235125a9e4da01d80" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "b7ac4f65575f3cff40225d83652a9c940fd0417c3cb7d5b7b7084d82b7d3756f" . + "4752a0a594459b28304d5239ae69fdf5a79734e75a21d6218b83a2c0af51b08b" . + . + "50a87bf090ce42846b6e416c869d86c61547db1f20aa8f49db3f7cfa066408ec" . + "4964b9cf5a91c77b0896a2f838589d9d2e30259d71f6a6d0d184907f66e4e1d6" . + "9d433cbeef056c19bde7a5cb1cc7c645abbcb795592ce1e4a5e3aa345c808ad0" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + . + "c7bc94dabe59bad740994a11f9a4ee5a89a6ceeb0a01c6e627385f704de2f372" . + "d8ce80d21b4b4732118a404370c4b65046312ffa2be7354466a6145efb4e4c2b" . + "decf8d869d3c4731aecc6832efdc9b366f265fd46d686ac73729966774f896d8" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a4cd3bf4e64f8f81608006c7ed7f1c7c58b3aacae72356b674f621ca7b29956" . + "27d7c61819002d137fffe479a8a42a5782d535b9b3e609f44e613fdf67fe6ef8" . + "03a72081ca43dfa72b33f7d22832ebcfecd0d5d97d76959f85cd756e8afa3272" . + "a01ad7e3887ae9cc6d798851cf2bcf0dd6681718459c2fab3f56c3c2ce872039" . + . + "041f5b17389885463685cfc41a9d8336a193f3d4c67cb1d27a450dbc2ffc184a" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + . + "76abf2f2f2216de26ecdb9b72189508c48c2ef17e1e285e4399fb1ebbaf8dd5a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "025a206e6d24549a5cabb5240be2b31a8cad90d27e98eeb1ea3e1cecc1372561" . + "bd958175d4ff130a371fb668a4e499adf6a761431f3b8daf03c0f88923679216" . + . + "0de23e590ce439b2c865d20781128a812a9c90a8c9366d5e4efb2cceb21fcd23" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "87c911790cf6c2625449eb66eecbd7934b59491f8144bdb75e04eedc5215c048" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b7bae8c01033e1cddec2ee9fa21c966bfdce09c65542fd363470a1c660e74ed2" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "70996a5b5ea68e7ff2e3af0a4b9d8cab765f2c7fe8942be9edc500936ffe83eb" . + "a78d66c12d010dca1ab5f2f01ce391ce351598c7e9e006cdbd8b9087271c4ce4" . + . + "b54c1b5500af98411212634a64f10e3910691021b2513f0aa07f141015d28f5a" . + "f5313db9a64a3cac5e235fa7f70133c0ac4818b801a693f7864ab5521a3e1308" . + "8656cfe3f168f253655cdae74e50ec7b537a927887cf77a5c49770bfe93b244e" . + "88d90ffebbda29f629e13a66d5436a28348c132c61587f758df7d094f8f7cd62" . + "cd038e2f6e1ef8115faf94c3d573dcd15e4d8e7426144c14afdb7c7da0b7bac4" . + "af7a9b4d3defac2c675cb84cb92d817c29ce181b61641c01409e0c77889cbafe" . + "24b00eebc6add452d782314baa4cc402e7421aa3fbfc4f43bba08e3c85cd3cc5" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f24740f17f5ed9449d24c8ee07ba02a75452904ce718d612f1be91bd79cea7c7" . + "3bfa84890796d106e5e5493037b002c3d43b5664a4506413f72668637e6b2e12" . + "36f8d72d722a4c152754a2a38be29efa64273c4ec0fee13f3e895632a10dd07d" . + "eff38ff9aae7166ba7e9edfaa973a0b3a4fe1fb954cb83be23710a09df98d157" . + . + "591cff0d875a3bb3d2c24119b6d906288e327ecfa658339ae5249a21c2057991" . + "280eab7d403257040b601665be5a2acd15186a073ca6ccf8222fe48c176ca7e6" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + . + "c10cdb1350c910450248b8f34707dd795a055cb6d4ec2a456b45d092bbebe09d" . + "e32559d0df3a4603805cfd2aebd57cf2a3cc049015b2ad8538b7022425e3d0a8" . + "98393beacce8f55ab625572935359d02c51d6c4b672ed33f19a83869764a5505" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c99a8c99c9676eb86ba61956d161d0ef36ef0f860d12ae60bba76562d73e06d9" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "161aa1374fc567b00a090bd728e7bc874058492b95f3bcae10e2af57fd88bf54" . + "17eac6ab1dafbc31235e8e49ed0263b9c41d26ce0fa73c4f7bd2f0a2954481ed" . + . + "f8c0ee687bd3cc3a20b40cc067bf17ce3b2de820f74d7babe26d3338c290aaa6" . + "de23f6de9373a32915f758291fb348b0a164dc10331a983dcd7b13259ba3b091" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + . + "1d8e575c982a3e4ba5c9b8d3b085685a8fc60c0ea348e1ab45401de3e14aee48" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "3703e0cc9975180bee1b2f8444ea4ee2d98226d888232500bbff7b86cb83972c" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "03cc4109551f3d965aa787262060f0a9e0487e342dbc72b2c066f29b331a4945" . + "3e76cdfd04bebd8d8851f58c602b7a926d4456e023886c4b611ca17f898b02b4" . + . + "aac938336f0ccdffe3f84125dd65ba869f18a56661db122d43b03424a1d98068" . + "6f8f1f23d92ff674c07e96a216b7c28cbe75e8546737a17512632b4f11f5cc1d" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + . + "c727fd6ed0a8d03b96115b6bc5811df5889f5e35bf2b0f3cc53112933edf36b0" . + "afe5d8996ee82acc994c5d01da1ad45d11bb04f6079905efe358bc6b2e52cb50" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8f3eb5689b9a807f67d5b819e7927073cd00719abc82ec6fcba7e579a28dd10e" . + "78086e86ee14abb36d43f0e5a5eb00babdefdba1ba624bca97e776e4f23dcc84" . + "5c261417d7046424d04bd633bf661c1559c8dfd804f3a2e271724c9cf0ceccd6" . + "9cda647be5b446bf169cbd9bacab0af949505d072abbe3dc8c0cc8e3174e1bab" . + . + "0a3f9fd7af1e214f4c0044c2dc77a3f9fde93af0156bd374ee3bf6ec0e4855cd" . + "14f8820b19a0cc1a4be98c679eca3d2bcc089a66c513a1520eee8af779d6d6e9" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + . + "0a3f9fd7af1e214f4c0044c2dc77a3f9fde93af0156bd374ee3bf6ec0e4855cd" . + "e6e034d143cdeb74113c213e3cc611af2da4330bad83eb053a370813733c06ad" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2b4686e6a0394b1b70e9986c61fda0d618a31cad3120ebd66693fbcc75ec2f76" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + "b65a7a9b07cf704d6a1fee8ebee055627e66580688c5b17127feb3d06dd90dd4" . + "07860a3f268bc58fe4143fce1cb8dfb68d71525e43076c56902f77e569e7e526" . + . + "6c3c63e7e36efd99dd66b9b4b60e6f3dc88bbc0bf25a81fb08b86671f70bae52" . + "c2f69c4f2d3915371b17efa430a6f69989d33a928669145a6aba7d666ef9048a" . + "f029b47111057d9c19a8f46d6b0932725c36ac1790f2f92cce0c47082edffbed" . + "3841054272a701d8d1525567bef4da95baa8aaf53aee5e249aacc70e485535f3" . + "33b5b64aba98b7dbec09fb050e22f92d5fe79d9d6f80363db44f01c8cdfa41de" . + "cae474637b62d0441ede5838d6ff147b406ca009a3a0de6a7fe2a5543fa1c8c9" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e9ebcb28f686b3dc9b3666afe965651221084a1b3d8ee34ef9c2e4cb1a041f49" . + "24a72dfe1d208ed7d28eac36f96b4f6a89654bb042cdc65870c1edf4f97d5c97" . + "e97f1e7efca8eb33439c3a410fedb0c383c96792f5ab53a7afa57563a6b196a3" . + "1b1db1f0f1a841d94ce319f770dc22e5af052763557927f3021c58dc12416212" . + . + "06d58aea52830e00ae35861c69ca9d6aef10d16909625b01498631fc5be27ca2" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + . + "46ee156a6cdf07596767ff87baf98eb27420947f3b748d172e26c11048b7a2a9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c775aa426e5ebdc51a3ac369efe47d682dcb59754b876a4d100509eba1361d50" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + "528d43ad4a3051e1ee6209b94c161c334d633f3ab584f73291e7397e57c34e35" . + "5679196c1eb5ae90badca6df084f6ed709bbf9e80e85dc981d3c4f462b138b39" . + . + "593dc4895975c5d31998cbcbcf927e944a83e67098a191345488d589347f5da2" . + "19f98d5800c8aa8bc46f8ae14c57de4af63fe023ed122aae9263489b005946cc" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "5ff0c21ba6723a875cc99d2f267d0c1e7ee56e660659082339b6cab39d71e749" . + . + "7d65feee21df7748a9320cf483f2b273153cc00c7af903d533d05b75f89aa71e" . + "9de042f8328888c250e22009d3e2ed111777f4c64c9af373ac6312872f85bcef" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c0a124619727628754a83f49e905a075845324039f9ce304636f4dcf085537dd" . + "d1fda1ad1099e21d022d52f04dbcce69d0ef6175d9c9bdcb6a94eee61c55b9e3" . + "9d8e110c4bffd180cc9aba57b7649f43f7ef4a4f561dd8223008e2a6461e4c8a" . + "d897ee574d86162c38432bc89622e0bf6b77f94c6296a4306b61b290d1d93643" . + . + "cd693ff667bcae6186e4a5168cad5818e3ea95c1ab126e6b1d22a4d589f4f2d7" . + "83954d5b3ab500bf20611bcbfa73ce143936000de156a063bff64ea57cee90f2" . + "57e476262d6a5e92c2cdd09b246cc1d013da4fc731efb1ba18f5a9db3832c8bd" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "e5ccd44cc1b6c85eda483998af22becdde406a651903c53ab89bee9da0d7b4ec" . + "0642cb8b2b0c06876892780b2b50ee3591b00ec7c1a80d6b01bfdc6830c8907b" . + "e6e034d143cdeb74113c213e3cc611af2da4330bad83eb053a370813733c06ad" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c3bc3542defb1ffc02db2cbcb703a29e69d4ad8bc19b590893de98828cd60a1c" . + "f9691c036a02238f5e5ed23fd6adbbfd5433d9241c68d756ad1b3236a039dd11" . + . + "abb5a6dffb428c00f0efb1dd5305ab0500f417bd76c7f3377ec1f7835f0246cf" . + "b69320588dc383f67939c85869eb9b66e14627e524e6ff9d0ea21d50da36fac0" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "23c2a356eb7a9a1e7983bfa9c85697dea983fffdf34f03ff605be4676365d0e7" . + . + "d188c4c1ebb766fb4ec24a0f781b58b42130595342c86938d036be2e842b5599" . + "8752d33c4dd92c0395f84df1980de0e413a661293b8e5aabd0d47a97fd98ce31" . + "72633eb322205983417bb7611cb0ee61233678fdb5b1ace898759d75961ce724" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "01880e9e2e7fbc5eaa72b5965a659bbbec298c97afb37c00a23f8114332f5281" . + "f9c78823ef36f7040756c023cbfdbcd95d42dd205ab6bca6561835f4af9b4a49" . + "15ddf02176e6c5680a08307d5086a80fde769b131f0bdedd1d4ee67af2e6b0a7" . + "ccc063e1a73438b95ecef8d6919577b3470abd3bd58084b950f8f415f7f13116" . + . + "a41a09ab068ab2c12ddf99ab6d612cb6e35e546ecdcf95f42591b16a54319215" . + "2d0fbfeab59cc541d3807a63c534fee332571b43d1fbb44b8f72491a674230a4" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + . + "ee5b83ee2c05b6fcf454273a43bd1c19218ce2cc9ac00ca4b04ce6deaa649b74" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "4b798cd3465cd40eb662a4d48c2ce8e3aa78017a0183a80a14da1f4974cf7547" . + "b659637c2a99f78ac4f39e08be57715e88dcfeea6311c1f6f50d571861a06ee9" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "2962835da6943b6e8b80d6b1031e0f106623c3f5d56e7ab657ff0357cf356f06" . + "83b3075d36cc0e9cf17b74ebc516f7ddace8816a65986ec1cc0ce1a80ed3c13f" . + . + "9b3b0d6c903dec7eacb72d381ba96eb0c1688883f11c83aa6bcc3ef1ea4efe42" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + . + "a3e790726e9fb285380c091b279e7711935a95a50fdcceacf7a538ff4b9d596c" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a1349bb8075caca08d6af9c2802677ddbde832cc675f363e929ec352661ca18b" . + "ea97644cb9abf9dd0a828735cd832627703e0bb599e2ecf8efe6618b660e39e2" . + . + "5c65390af62eb3e73ae49e60c7a4a4c1906c241379f41c4e4e4dd770b9d1b252" . + "d10fdd65bb7ddb41a9658c89c3a37c015ad1c49e8b08ed8509693c2980c32ef8" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + . + "27790ecc6d28420539d289de847fbe6a7b51b45fdf95ec9a94cb95ee1458395c" . + "5b2bf0460be4825730feefa0965715750e0b1201a7feea22b07338ad74711296" . + "3a4e883c1c983bf6ef0e02dbef019e5eadbfae9aaf84c4f0d82448c30bc444f3" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a4a93648c606f99d707ad84fa7092994f0cf7f745216bf35014ce569edc3e26" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "f38dca42f82628c60408c6b4574e208034df3ed94c3a25521955f756dd3bc4a9" . + "763627038b5edb67a090810c47f20e1b2c9f1dea00f2c4cd1db75c5972693484" . + . + "7cfee9a2e0312f238f63a5d2c80cb36a5aa0ba4d8ffea95e8841b480b74a331f" . + "0b344b6b70b324f9935dda3038b9c4fc1cfc0936e5fc5fdd26f92bd65e646bd9" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + . + "c15d45aedbba4c63ee2a47bfcb044a9e233f3c0b3d9a75b601064252f732c456" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5ccf468d9b30c1c3b23dd02070d67ce774ba049c4f7f792176e083d093d56738" . + "a29a26f057e459c124795d0fdfee1ecb3794f5536cecdcf76227c849839214bb" . + . + "cdd0e67c9ac05c258b89fb7193b6b738bc5562ff0d80037d218b1eae41960f47" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + . + "19de8a53af9df2055622d403ea33675d1edd0ebe1bd58d3239e8646ed71d8c55" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8698cd0e850e21faa5bc7a20c749a749c1cc104cd2bc9f21fe4a00e53ea40802" . + "d12a5f5c0360c6aefa4fcae5e0f7d81f520a774bcddc94722b03ce1063f3c887" . + . + "b5e410a06ca44ea30bcf1c20bb793b3a6f3daa1c42edf2b1c2c26b06bb45197e" . + "abb29bf1d812e2efe3ac81795e7c9f8f16157262a473e47fc45787da8272a0e0" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "e8d45f8f59b5c14b78dffd2ccfc1f444008f9ad34805bf3e732e5534b1dd79c3" . + "207d802e6bcf2e92ba8d4b00ffb1770e92b321b2c2089d569908e038d0127958" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "635b23715be20cd438af08df03aec5e6363717b95b4ab18f5ac3bfdc75efbc93" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "fc9bf1edba23bf6e68478bef0debe069806017ac848cd8039ad3230a5f36a9ce" . + "22f6ac5cb58515a53103d507b59afef82d81056d852ffc10671f1848823ea7bf" . + . + "c9c66c57a51f7d784cdbd8ce2702974c260064b75602712acdadaaa3771becd9" . + "c9ad39e1fdc52b7587472a53569fcdc13a1fa140486809e5c7dcbdb42d8acc30" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + . + "83421edc8f908a38bfb63c87baf65258a56fb2399a6d8b474b38490339c3f74d" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "1302c1ee85134584d8d80618594cd037d8c20461e109bc19b5b4d5e5a5e16041" . + "481db82ced707d3408b12d058ccee4a3afc0d174aa3762502df8a994a8da2495" . + . + "7c939631f479e29e5b69bbafbee6a3754a17f1c76864296cfe381e90926c7119" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + . + "38a98aeca8d782e8c45bdc3e4b19112c2c9df3b58f4d6981ef28fe7029a18510" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "217028d2791497641027065c3ae94b9436f30c8ae33238c39da6dad6b43a4726" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "34200d002a138c7adad7355ddea3a68797557e508f5f74d66a20ee5fcc406f55" . + "dd0ad4300660ad0ed56b1f5b83988950d0ac8a9b45a5de1392b6816dbabd16cf" . + . + "5111153b32b584730c87d0ec62bcb25cfb1da6b7452bc7aaa95cf12b54ac4171" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + . + "212239546cb31115f32a3c83642ebec307fffb99e7aa5f4159054fbaa8100cde" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dce0d7dc1c06b440b04e467f7a548c95c735f7fefe4956c715d3011666619c11" . + "3f4126ea7e78dc1050ab2d3aa6c89394c2c65dc988bf97edbfb609f0aa56fb88" . + . + "3d593c506192b79523aad40a905a4dca17274d8dc86fbb40afc2f28979d5b581" . + "1365d577c1c6036db7362076760cffd1188f296df67587802bfc6b1cbad32b2d" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + . + "1e30b6ab87fbc2e14d4ef47d7958b446399698a13c42cd8d8b090a0e3e8f7a1a" . + "6b0dd6dfd928d61632a861ea8a4c5fec665b7f5a6d554c46fa40bd377b81758d" . + "27da8cef6a8dd5568b5c54e8243976709bc8cffb1b2f350712673fe8da13ddc2" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "45eb29e297d4fd9d337bbcb88a5b7458e68b88ff8ebcbb1750cc3b5fcd408c2f" . + "f75701893ce1722083bf062f127a524dbb86e3abde5c917831a2f484cdcbd343" . + "5dc7ab5424d0d34d52d347827db4d16cb658ad5b4a30e2da4bedc66121e45025" . + "6c11095846759ad15923287f96446f0059b3029f2dc1e807db231bc48c0247cc" . + . + "0e2fab9dfb027723d645e21bc11c256ae098b50745c8e3d566a2d47e3dc9014e" . + "e86138ef848d12225cd80ca81db4e230c92dfb8e527cb0ee38c8b071f557af8b" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + . + "d3c8f850bca961b08ff349616d7b617d0b885fa9849fad3a0cefb50898c1878f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d1ad1847195ccd2a0e715f10b07fdd691bb4aa58eef517518c34d23159453014" . + "a4b5ec89604593171a715dac501bcee08dc36d2e1b6ce834d9fb5f701fa12891" . + . + "bb0e096bb32f25b5cb1a4c4bc52daf84854aadd380bb8931c45d68e25782b8d8" . + "3876beb135584bdaaacf5e1af754c8fd089cec49ca8cfde98e4bceceed47fe65" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + . + "6ab9739a78514ccba7ab2b181f6a291309e0e7645b288e0acc138eb627f35049" . + "3b738ad7190fe17a2b7f0b158f4cea080be43f774aa623e96b1d22b6838551f0" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4859965c8b4f6da8a5fbc8eefd24b88f1fcc69b2bc753538d0ddd5253a4382bf" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "e2ab75f20ae382974f530b5628c4be3c7c5653cc4f2e114329b5ac3377c1e80b" . + "cc5e9928ecf96c99be8e201154a266a376f7113075a3ea7a1ba3dd2cc5ec4166" . + . + "f600bdf286773a6fc512b5fa322af073b25195b7c515b635ad4f6e70a2373b2c" . + "8a3fc462af6e8e9a34c7a6e27416f8fb572828a5402cd86d9cea24e59875b9b1" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "4eae00638208fa182d87689fe41ff08564af073148b2720a0cfa1db956632609" . + "529c9f7966cbe026943edcb11466c5ea19d35ce25ac53e98d435df63f7ba5be0" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b533b81863b9d1cecd9d9330b76c925228310bb753d6b16b1d30dd25d59c8f4" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "d949b315bc55fb870513ad0465512b872b26f9aff24811c5f6635edf85eaacc2" . + "805b334a0d7a9046c84421ade16ce6a9d692fc9d119a83390469fad2b0a1e134" . + . + "e54e67354bda99cbb09ee28d614ea01e2b5ab38ba2edb35de959213e1810edbc" . + "347bdd1e2665c8d3613d4a7687f93d4f527f16d267e9ed80d6870e11c31b96d1" . + "13e7ec6e4fd2f258aaaeb27f5284315c85804004ffdc988256cbe307b407bf60" . + "7515cc0946a6789f71762fc9bb30f59d44fddd19ee3f582162cd850b2e3f422c" . + . + "74d56f55cc1cb0bf68152786857977d0b53f78e32f30d771ecd4ca89387fa03c" . + "ced7fa5c887b1a0863a0b0e2955d356ff39632711100ef49bb01df2f295f6022" . + "441fd0c703035be69edae0c6e336e74cbadfc14ded5c3707fdcc82cd2d3c61f2" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "051763df73c613bfebebaf8bfaebf122922e03f3b2c2149a2b7fde85ab74f342" . + "547274757fcc4f1f6a894d0e56503d34f37d417ebbedeebf7e9527d5685f656e" . + "8546049297b6a4991facb18274baff2a6fbaaa6250c1a6a7ccf0ada43a0ad6c7" . + "7d946da2a6dc6cc6cfddff80d761f7579f7044d3f0027b310950d157c1f38d40" . + . + "198377ca20735ac0c9444f49e4fac37a2a076de6cd9f04f662cb41900fca29a3" . + "e598f4fc0a73e18503d5e1ee23e5ba153986594eaeb6bc013a39fea8f7c53bc1" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + "6a522c214efd2b43a26a63f8bd0b6f58ce8e117ffa55c0ba0764ce9e02c18c7d" . + . + "8c5768bb36b0230123d1013247e7ef4a9bf7dc8753b3d3c95c5f9afa24142c69" . + "8abf3762157b2e61c6796846118a946b94fd2f5ccf42eab18e87c70f71f3e071" . + "85f187a225248a5b7bce72a5670836ba36f8f3933f8c2f6824eadd07bb8701b5" . + "168a0a0d4515e231fb8220a4c9d25876d1c56045572f7a444db736c49338f1dc" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b6390a30303ef34af696a5108e2a2b45f4e5fd4d0119e0c136b68ebbee43a527" . + "b6390a30303ef34af696a5108e2a2b45f4e5fd4d0119e0c136b68ebbee43a527" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "f4e1390170cdc8aeab9b6e7bb5160d8aa6a52d4a10a926805c93ebc08ac4f905" . + "3c158351c0b2aefb273413ed60b339ed6b5c2b71ac5bb942a0980ca529619d0d" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "562a00a0bbeb0968eba4ce01d660409073d3017893540fc6e0060b98ab189306" . + "a6d7806e54edf2dbf6bd384c6c4a12947527c3a5c6a90af50df1ba68aa15bae8" . + "7034345d6ee536685eae719ec6e07d85984af5f78c454362e0ae2d9192e093b5" . + "f2ec94679300dc78b69ddd2351a74d26187fdc8869747b3aae68a4754f7ec4ab" . + "4f2d09b1713551a40d676af3233c5de566ae37fd215a3f925300a6887d01c3a0" . + "6f60ee31bbf0b7e188cdbcb9a7336221da0cb59ee943600b9d267b4d57367b27" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "d71c13e6ab72d6a4bcfbe3c007d0baa1e6fc859336a74a602eaa9ba8493d482e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7e6f13977b26737468f11ebeb50a350d8ebd81ed86adc04d7876b68f7df40318" . + "d246c1c895fcc3bd14918133f8c4b5f18d63122d36229417571b8f7cd0426166" . + "62dccdbbc0d7480acef14b83a432ca5a88597ca18f99544b8f666157b6f89360" . + "b63fcfd4f577306e113647a36d4ae3b42783e8e2cfdbf822a771d4ce1a77451e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "6f3a2d1fc4cf4f080284565f87357be80e0ee38dea9b250b6fd72dab37e95fcb" . + "bbd2e42766440fa0e1a399b6b8fdd061f74789fd34e760919ae617f8be36b062" . + "e03fcdbd1bb0d88259693d516389bb24a16d104f654f7cbea22ba997d3d9def8" . + "35b5799f3914a48026f7365c2beda06c0b0ac5f5b88784a64652da30b704b98c" . + "b5888068f1b061dbd311a352d408d00f601e340240c0ec368681f1d8be39dcbb" . + "02133759765cc01ca426aab7ecdd26ed9754a26cb569b86d5fd2a34ce3327d78" . + "24170f5927c8fd937fd786101c75448b1c18bb7c42bcac54017a170bef97b138" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c226d12c04c099931cd3ce279f2c3553c00ad844be64f2545d66f265a8a698e9" . + "c226d12c04c099931cd3ce279f2c3553c00ad844be64f2545d66f265a8a698e9" . + "51239bac6b67e6a73bfa09c293d52432b1c97c01dd818cfdbc45aee6aca62bfc" . + "09577be0c4fad4ed5269e30e448781597a98d9b84b9866bf2f3934798884f920" . + "d0e0c1bde165f1d2d9c1ce378d09abb687508d4ea9c56dcb0c1f3ee414a0f4d1" . + . + . + . + . + "fc10d4e798039ad3ff6d7153fd3c461a5d3f2547d9987e006166134dbe30cdac" . + "9f3d6ed57666fbd0a0a9a91f7d25a3a14ecfc34ef781590cb8452f64a803cf65" . + "ca5eddaf0fe7ba621d222be32076eb295d4d300f9f45180e73c753f8dfaf2bdd" . + "33c1a8e28cf711a41a85fb0e4ae49ffa451a5a2aa48b4f6219c2f9c3447b5750" . + "697c0972bbd84ec1bcd84e64ecd889a35a1e57c514840807a5d3148e80c4f0c3" . + "196e0308c2dedba76387d8c44fb956bdc57c781b03e0271e41ab6310098b04e4" . + "047dde4e5634b45414deb6057ed2c280252b1c348a90d6c52e55862f4ab532f8" . + "2ba1104cded90e74452b7df0937a7ea943c6d205ef7e00fee32ee313f9a48678" . + "9fb3d6f8fadf140c68f4ca62c5e33f2485f31a32ccf31de85b67d6aeaf4893d7" . + "c5574c41233451d50346a3d830c0452aa2e6a526edb7758b7f636d4a7c684b75" . + "6bb097befa35b2ef380d306270e000ef82d26aff5c13092c38e18644672ffde7" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "e2c776ec520b4b1c27780238a26d6fdbd082939c651464e4688fc91aa70f3322" . + "d6c3a68f3753b1e3ad5c9efb19b3e4a6f91513a89d50727879801fc34699bb31" . + "2de163dacc0d7926eb8b581dd954880a4f5fec617ec1aba5099dec4792186927" . + "2639f9a602168076971d3c0686373bb8fcd68c1757de40b0193c047606c7f027" . + "d1949dd1d43c9c783c9a8989cee049432c24ccdf2bc6d632f13fb9dbf319412d" . + "dc8fc739a29bdecf0f5c268fb1022ee28c5656fc8162733268434afcb5586e09" . + "0ff0804216a346d0c74332e3571efcdf24a8969b2d56f9a3e468890938c87847" . + "817e4e4ec6ae9cdb70fc5a22560bad192fc0bb9e32e8d47d9f6bf4de8cb5d4f6" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "7e5d76ba16ad8e10d87936b5baaa216ccaeab62b4937369fa16465985bc78293" . + "3c4f9fc774124ad0983105a457b27d14ae23efe6c1dde33688187ea3dbc7119b" . + "03f5b190d1bf8046341fc2741a726b28b8fabcf818f8cc532974e8b69e24ff40" . + "d8bfa1253be53ad508748605cdaf545a850155406d15968e793fedce9383ea31" . + "65b1f7063dc0a16f78001e9cb5c4fbfe34e33e58e8ce986653be39132f360e1d" . + "8889e304ecc7682a5126d92f6dadf6864e7bf027ace8a964e552bbb368efd96e" . + "cbf52eafbcda1ec42fa36f7545f32bc399aa43f5e2994e354e1ecdac7edc6049" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "28779986776aa4b339c9b0c3a3dcf8b0b4abd59036de241216d47afc4804ff52" . + "28779986776aa4b339c9b0c3a3dcf8b0b4abd59036de241216d47afc4804ff52" . + "11ae14b26c34663b8b4bd2f11efde8f91467037c32d4cfd353150268c529f348" . + "4a2cc4fbadb9c3e00c52473e10d0d35ff93094bd2231a4695f5cd5fade53c29a" . + "48da77e3b76645e86aaeb865cb8a6babb00de516e25a361c4581504e2300c154" . + "be9edca68813e377dacbe6f7eaaca1ede2a80a2ec7f5f7fd48cda41254187c47" . + "0b87c0982e2b0b69ef13ab551fe8396bbd74261146444d7b444b76b4bc0b2a7b" . + "b9434c3b4375ffaf4c205ba3bd6d0c056501207352f5926767f51ea9af329ba6" . + "d49b7251e58151247a3728999250d6b6598b64a56210a297949d6aae878a8e41" . + "d527914567e7b2e88f8d857916f071099e90226e2f6eadb41c3b64fc0c7381df" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "44cf6b521f87a710cd993495258f1f0dab4d8af67b4204f5c3a9778cc8a0d46a" . + "18992c71ef4ac95266ddf7b9a5b699a4bd9f7bf67aaea15d9200b93b51cb1789" . + "3bb273fa8f14ddff1475a6f4124548016a74fb11bd7e4901a0226493583293db" . + "e6119a80e12ee54e8cb59622459d9c2ee5065f36ed78d2207a0fecd3d68e431b" . + "ca1aaefb910149d298ff4266a43185c63ec79eb6c6f5008e956d6a7e817c76ba" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + . + "b8e6006c297641e8e9607c8c615e3d4057af7885622a21eb19d759d8db917e77" . + "aa8f3a0476ce762b6863fd49bd6544e0be28e8f571116b22d5d158ed62931ae6" . + "f7fe7145446941842a77185d85ae5634de806ae6b07751c63ef757463c4225e4" . + "cc4d23b5764d79c050497720acbc4e124c4e840a5dbcaaa2ec618b8edc19af1f" . + "a9644344e1bcc402bf56f6b863f7141ff8d20b9ada7776b3587c4ad74d1b63b1" . + "6e7216eeea0c5c124a7a87840c5779a08add6c7341a0086e5be57fb8848052ea" . + "b3cb3db2234f858697731d19faede87ba2bca46f293d6825c126b224f7b5dd55" . + "4f1f0a4c8179a7ecff1072fa49b41a49975ad79fba26f8c5ba7cc506f70aa45e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "768620abcb17746022e6754a593681488e291c3d097a039b4434e100bd65766f" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "b069e4bf0c6d2feaf04f14122a4328d11ee2638822d8ebfa24ac06e6df5357b0" . + "2d47d7fed692719224fa3481f5783b644240d4aebe072eba5cf5018f2f90a16f" . + "c15c7827f6a52afc3b8927b5122249e4d5fc5c0061d8124e8cd72fcaaf2cf1ac" . + "5f113887c746b1451d53f305b1d357fa6ec8dc3dbbb406d8bb5dcfc1f54a250d" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "0914deea440995f1a3fc368b528e8b6203363cb87a5dfe14ecf5f35f8036c135" . + "bae0ea2c60cf11b9599a47a4f687f900c356c129d8eb4b316b640d4a02680ce0" . + "2b6aeaccac7aad724bd5e3aba5e14528bec973a037aaece86a3c9de47224a7c1" . + "6607b07de2392da60bb83c1b2e6797908b5facb7be23bb59db3ee6add0439076" . + "8f147c61bd09ed93969c4d50197a3dc4e5b33382a072eaeac691be6ff0be5115" . + "ec9d7148fef6605350d21141c6f26b43d83bcbff9592cf3fc017399fce357b7e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "98f415c0a6bd18e01bc0896d23a393ca800a5b2d51fb97992e902ca73b05b52a" . + "7438c1aaaddc10abc485006bb69435450637294f7e96dea72aad81255fea1daf" . + "8b2f9068a70f4af7ad6388bb84fa906e841dca0c21867a597b1afeb38fe1ce04" . + "3938fb8b8f6a218e66534ff11bd8f20e7b4418d58a3ea5733b80b5a91c2aa7fe" . + "d33b2c90b2640fe72ecb10481c5e615f1081a6438488e3881e5fa2a27a0b5f89" . + "83740f45bfc81479b7f5a29d07fb03932b801e1b849e1d36da25c1a7ce627a18" . + "224aaa8bc962191c310a9d002610ae323552c911e7c908f97dd1936cc397d41f" . + "e929b19c3e4bac169851f3ca37abbd4b26a01d43d672a3ec9bbb16e56f289da5" . + "274d5e9f6cf370baccf246e23f1b0200e647fefe15a849abc1212fddc5523ac0" . + "ca3cdb6271c2da5f56217569e89929d6a544d82fb4a859fd31c40e074673229c" . + "cca28de1247c941c61143905450fd8e5ca5dc96fb7e652c5811297878e2e74b5" . + "f9ca035baf96f220e0ed1adc5feea302390acf26f5b6ae14bc0022b8e30ccf2f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "fadf93bd2931059dabd0691bd4c1d0eb929fc62fcbde38cd200828432ca7f57d" . + "eec54c306712a430ab8a9b06fa2a4c7211b5e162f8f81997d2baeb41bde963f0" . + "06e363f6df4c6ec4b8c897cdbaab2c84718545228976c4c003867852c45762a2" . + "aa2f2d951082fa39c07fde899dc4a812e41771db0b26a46328dd9e98041a1ec5" . + "6465e10dd2fe75efa1ae0c1e72aa5365cc311bc6a83004136f8dfa9b917973e4" . + "5ed9d3402d989efd27b1cfad08c91578d0e953603a6e6af5be080263c41bc834" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "ac9774ce8d67437edadfde8a9a2f62f0bd42b9f974e321ed4c7630bc59331936" . + "b82d8a10db89c395556b35e22673cb9762e48a3307d0f1303b39efa28f40eb89" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "ca0b5fd75142e7b05fe4480eac9deca78a2d62e434dc79008be260be4aed7429" . + "468d26539608ef320d90a632e179f242c574567f2a612728c046f832ce3512e9" . + "a3adc31e2078ae7798a0cfa4bb7d930088e60aef1e2d117fe4594d8c3bd47b92" . + "e83a3e9ab1830fe0116ba1fa7251cd4085a4a5b157261f8726f902c50e65a391" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d593c0543f6630c7a8830dce3f3fc44331307e31a8a4180aa24ca45544ae3456" . + "d593c0543f6630c7a8830dce3f3fc44331307e31a8a4180aa24ca45544ae3456" . + "b075afc9830de8d2c31465b76f8408a33bd836308ffbe2ccfe6d92505cffa349" . + "8a95f440cb09c67ad4fff044f76a8911e03358806a9ed2236b835af04cae9ef6" . + "77529b6a041320c19b9300e91e907f2ada8592ae0607f162ed3f5b03fb4b3bf0" . + "650487dd35656428c52709762bea6e693c43ded15cbf24c5dde737cf94358887" . + "b80123c7594732a88b78159b79efa3a5ae382599cd27979bd513676df5cf4a5d" . + "809b6722fc9bea74c283cf017d60842485408e2259dc2c5d5ea3d805a1792b61" . + "bff9899956ff4e896e5a976bd7fbf4142671182387e78778921ae84ca3189fb6" . + "db0aca822ad331a1937afc2570d92ce538e3731749056cd4bdb2fdbf0023108f" . + "78ae5fadb30b2e68bc16ea5847b056a7d25eea8f4c671679c76489c43da42670" . + "3e7c7f510f239e0a28901ab07cc1dcc2c1adeca652c574b01f1ecdb562512ca9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "ba8a3dc8f4c55d3d738491f6e4c7ec12133917a93c0c22ebe0032a8b6d7a16df" . + "9ce47da43466cb4c4abb1864ccfc43f978b2c44ab37a47d0d93e3c7b8903bb89" . + "81021088075e1d7fc887339eb52a06f8f85ac84593d66494ec7fc00a5ac63941" . + "6b18eae8ad1823c8348f72eb029abb0d82d9670e01730d98019fc7ba2fff819e" . + "5c26b29a8586d0b755f2886bbf1d45e7ef079a7c59c72cbc1717c081465a100d" . + "5ecda760bf13ace1ea44d3c3ef84b47aca784347aebc2900db8d62c1b719af29" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "e1d5bed35e61302dda4d5d22a67eb4cb129614bf3894a4099bf18f6989db32ea" . + "45ce59757e2e15d84689c5824ca9293209a5ca32c186cc11fa5b3bf63351bdd5" . + "deb842f334e3258bc0d20666da684869db6dfa0d4664b09826baf58c367592d1" . + "697c0972bbd84ec1bcd84e64ecd889a35a1e57c514840807a5d3148e80c4f0c3" . + "eb1a4dd3ac13c08c8b4e6855f90791cc6911366dcd8546b4f5d8aef0948c72d1" . + "42650813b2e1f5a69a831253f0cae8a526b4a7fa5cb994277f8766727736bb26" . + "243b8acf6e5aefae0a08b056fd1f43781185f69a85bd7ce69a8fdb5a7c4c1750" . + "ad646bd7afcd41f694208ad32e26c62429a9ecdd6d62d261b427def490811eb6" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "37ca5cd4a4b2a3f1b172757f8b2b484c7ae793dac73ca93bd088d3d26bb57021" . + "d2792859dfedb094b7ca6d2d274095e7c4b30e115fa06f1a2bbf58d677f2f8e7" . + "7b0242c2716d7bd96fe40a1cf7945dfc2724bf232e97dea83a3cd5383c91433f" . + "a8d43c750c64a29c2e16ca71e3fb85db434a5877473abbfe347459eee0b1725a" . + "d7ed37c9f2daf1d1065ba74b1e7545df740df325581232e3533cd69e3aa95140" . + "e48f8b481c418c6aaa0f7965da4ca0934927b269d1bdc6bddcbd7ef30ebf6780" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "e4207c29cece3dd9c9f2c3f686a162256e0d72ed9a7ebf8502a9de6ee0bf821d" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + . + "06e807a4f8cde841e176522a0907cbe8aa4d1ef39ac081e61dabe60614abb93c" . + "06e807a4f8cde841e176522a0907cbe8aa4d1ef39ac081e61dabe60614abb93c" . + "5ce280be50c74aba5ef4062c8eab3234a40a5e03fa16a4732a2c860f6fdaf372" . + "5ce280be50c74aba5ef4062c8eab3234a40a5e03fa16a4732a2c860f6fdaf372" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "24963959aad5c002c68dd8ed3c79ad907b2e323f39bf14a63dbfb9727d106111" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + . + . + . + . + . + "8d9355a46d9a064298d1f9d77994ea93902a93f45f1ad495a414739a41a85869" . + "8d9355a46d9a064298d1f9d77994ea93902a93f45f1ad495a414739a41a85869" . + "5fea9cc0029682267095b58cfceac2514dcd777dc69904339c38b48f9d16775f" . + "5fea9cc0029682267095b58cfceac2514dcd777dc69904339c38b48f9d16775f" . + "219162b34f0a93affe7500c3564736850e77368c54bc017e1220a7654cc05825" . + "219162b34f0a93affe7500c3564736850e77368c54bc017e1220a7654cc05825" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5b22fcc119b98db291f87f41c3d89e15dbab82f97dd32a32fc792a47a0808fe8" . + "b5985416addaf85cfb017cb801360b7b932819f88e3ce8334490eb3607ee3d86" . + "b5985416addaf85cfb017cb801360b7b932819f88e3ce8334490eb3607ee3d86" . + "15f0b0a60d8a12e2b80ae07b33d451b0b44a76935b4769562a31ba6fce461781" . + "28b3e7b35b0a485e82c6d2d01971e097716c17f75bdbc351120cd5ae214ec814" . + "ec3a78b362c7c0e34959dc3a71d790a99cdea2aaee288faa5bad597c85bbb2bf" . + "4097d13622f0445a5b61ca48ada3d744244e207f7d344683bb0b9f7253718698" . + "4097d13622f0445a5b61ca48ada3d744244e207f7d344683bb0b9f7253718698" . + "2cf6c39248ce193d3039396a81fff98540ae84cdba01752b3c91bf3f7e208944" . + "2cf6c39248ce193d3039396a81fff98540ae84cdba01752b3c91bf3f7e208944" . + "59393d39792d361ab6262e2b7e1ad1c42d856319af02ee9612819b49854dc2b6" . + "bd3988708b1f4008d08568cc2d6f7010d43a9f021ff55ca801b684bb81ea291b" . + "c525daf01acaecb9487c3dc5549af4659df2b02c79be6357c6f08d5792363687" . + "5d0338f14437909ee9c519c8342e3c8e2c62adf3f55b67c13f60f51df44cd5cc" . + "d5b17ef41d4a5cb8afe7a1992e38ef66b37bca6c2bbf5856810374b6ebee3008" . + "d0d79001fd9b17e1b081a1202b455ac1407a9db70b84798b446884da91852a8d" . + "b1969b06a772aec179237e5d8f1c6c1ad9d2cdcfcde88e7461dda0a4dcf2b69d" . + "9b8e8ba1e0d1407bf902a1f39177ae40c50347c2d759032c29e273a681857e1d" . + "9c1e5ea32af872ccdbd0f37bc0ef8b3d47aa9990671d87142aca20ad0fd4cf96" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "7df24300092b2929967e6776f754a6f38312bdfa84992f027c6f12318abdb3bb" . + "6af1161c120bb83964c13dcd3b3a0f577aa860094c170aea5b99f4811c04c702" . + "d909f673e7d89336222c5f016cfe91784093461ed4681f751d1536b94f99feda" . + "7faa52790cca09dd044e77c0c25516db4a5afae1497a8cd3bf8cd7adfd4b186b" . + "e90f7878ee5515be5b460261afd17e13ca12fcc0081abe4725c1462dd7ce101b" . + "02f8e14ceaba0ab299b01111684e622109957cc263416d60020e5dccdd0eba9f" . + "634c227a43f3e4d892bfbfa8a74af3d22e228b1db2f699a6ba4edb31d28b7b77" . + "e17a96d60b7a220157976c082cef745ceb1cf660d28b78e1098f9f304398929d" . + "9471bb53bcea72e666008087c375e584243698987c06d10f74379a0305bfac28" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "6a9ae52c08bea323092a609236e09967ec54ad1d2505e719e37a0dc36692332a" . + "652405b2880ee5fa81d3ff0b2572cc60d2897a6a2e57c6f0364078afc8865571" . + "cca5b40a332e7ddbaa0a16f94b9e37bcd5ac77c5a414083da239e03d4908c35d" . + "5fe6416201ad3725694a19725380c5ba1da77ddde62b65f4b6e48519ba5ea322" . + "0f6ae20201a0359225214c30eb86cb9a864a0fc1ecc016af42d520fdb6b64b99" . + "3297aff19e85912e188a7e8ceef1201f3438c6f626160d7f915016fb8bebb919" . + "66425ff80138771c2aa5a598c4e86dce73ee3c5484eb447deaa2fca8a3cc54ae" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e78b139807471c317006dec1c1048a98880a45cb0bfa38da8d73fd20e55088c" . + "8dd1b9d20f523d253878fc3f9f8e20ac3bfc4769814b257180509cd9bbb39b63" . + "2fd0dfc47f6a01627aff51ac025ce72c4b63c5a2469c2796220c4917015494c1" . + "3581541a193e635a928fa5b81a5b735fc918312e94f6139ae68a3c723148a57c" . + "e8ca58c32d67530e436534155442c5d37f85a5622afd5008e23f9c244d86eccd" . + "a30089e34df5adbf045e05ddeb686676735fef3dd10a36090c53593b8351f19d" . + "b4240d0ef5c690c4e63221297de667bfdd74f1c366fd21f7ee0c4dad29e8749e" . + "be0f6004dd32ed2864a5bbf4150a853fb89a08d0b198a559213480e63dfc5944" . + "704171a9e821e218d3f0ed4c2d22e75bd8d875de25a0e9488ca7dd38b95388b7" . + "3c3025d7057e97713886179ff9ed44b3d5aee70bb3650b1904ff6a72bd62c8dd" . + "0f8f10232858d9550b667a84bd47090977173ca2564e3602e2f3b614b013c0b1" . + "458ec6efc29d83853fd563790276ca68982d635b74ef31374b79d54099edcf8f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "8fe9fd0a14c4198c9f8bbcfbed1d1213aca72d20e6630b529ea639a5d4d743e5" . + "3ac2ec40cf44ed347f41aa4fa132a81dc1aace52e057fc514ad79694533300be" . + "950411f09236fd1a45244cc7c8b0b6b7b2ebbf3753d5b482caf60eb528b02631" . + "4ec7f3b491b28660830a1ce4001e8879f4e4e38449414da45436bd92dec47f6c" . + "883607475a2bc57b369901fd3e52dfe78fc6aa8e712179ff62f75d0b76ede412" . + "5737232b7dfa1f38ff67ea7351652cb4042c677cb681961e2cff699708ba2e53" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "a05dc7297fabf16b42ae62a686f29dcb69a3a8ceb97f06b7f6721846e2ec2370" . + "8eebbef0701eceb296bc0147a3d3b9ed73a9ff643ee55791fb4b692f2a08150a" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + "f550a65727b26d3bf46abac9fed93ee2ede3ae602340b2925855bfef533d1bb4" . + . + . + "2b3544d6390552985543dc836dd4298847e7e5c1a64e760723b123b54d6cbbbd" . + "792e8f5164e487b4c6d881f2d4776365c7380e6855176bbc0b22bd103770eb1d" . + "86c63c8671893f2f9c616194da9f566850a5fa53961005243213dd36660961c3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8974b6b4e58ed7ffa6a05eca6f9f09a0c9c6fb8a80fc105a5cfde15752b0afb7" . + "8974b6b4e58ed7ffa6a05eca6f9f09a0c9c6fb8a80fc105a5cfde15752b0afb7" . + "f2dd67bcbd6c14f7c5b4245fb6a5f6471cedadd04c7d48826ebfebe236d832ec" . + "85dbde2f2c841525c47c6742bb9c4812122ca872d7733a8720cb052a4f260901" . + "d8bd9868155396f5324f01a38661e648d1a11475ee42c18428e2a297b483a6d7" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "5308e274ebe1102b4681357e6aea595f7c681572a6504d660e38ccdd67d0bda1" . + "a5dd8d6dcf342238bfb980c777fda3e1fa05c259702f0164a760ae3095141b2d" . + "b8e170be24de2e3a224ff16bee6093b6a59d093fefa60666eaa13f1c6248e7c3" . + "c41e1008683d67056d422f4af428085f5dce6c23d6c14dfa86f969762300ccf8" . + "e499760110d4837db2b49200898fa4ca0a07d513541b34056876697504ef3b8b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "5cc9ba3f01715b3e44a0a639b3b6faf6d9d4044163da3ba30f93738390905c63" . + "c9008979fba960fc4210aedf076652a4977dc538cff77534971bd64a9249fd7e" . + "075a46d57de2c762dd629dd839698775ae246b81c0e2d5ffce95d0ca4d067e05" . + "d3a89691aee42b447e05fefc813754a4e1acd83517f7a394fdb7a2aeaade562a" . + "3f357c797d140fd3d22eb6b9ed8de371f5ccfcd1e0d2031802e449ae7f6ba4af" . + "256829840c3193628373c25aea1413fcbe2d7f1a8efd7f060621b50d8b687416" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "95d32dd3d62fa0d147bc343c3237b6de231593b0022f1d1573a063084c1957e2" . + "25ec4502ba17ef55338da81a52474e688d9f65bbca8a318d4c00d4d26abb02d1" . + "3a341bc17ff88d3216157b435af5293151f1853abce14dc0c90569145b647d0e" . + "56b341278d8602a6c4173f59160bed66e923d04c68abf2ca41347d52e5618fe9" . + "bc185dc3a83cd2ee74586d93ca481c443da74cb4b8f37e9c39d18c378c4f5374" . + "7706d990a29b8c604e54a1709dd8471eda3d856498dbe394fade5406278e3931" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4af78d377c8fe3c1f8a2d4ccc2741b695f257a3c7aa466c1b3416e0a4d2f9ba1" . + "4af78d377c8fe3c1f8a2d4ccc2741b695f257a3c7aa466c1b3416e0a4d2f9ba1" . + "b78245292cbc1006f8453aed5af2d59f5b575e01aae509dda018fe85008a95b5" . + "cae0755235cc9e9a81d582a7e4e5e4c0dda4b05b5aebc883bf66d3634bdf36b4" . + "d25f14ba1693e0ee312444a2b16bc8d4e0b3cfa2f1384020ed770968f04c1e5f" . + "df9ea4821faee381e84e3e174a68e289d7f522e458bb577fb9416437115dad1a" . + "08f7c12f8fac85af92e5bf65ce5a20851380fbbe66bcbcc73a86b3b6f8063d6c" . + "985a2dc3e8a0b7acad12a0a621229f46e0b3d4fae43e04069230ec26b15ffa77" . + "11927b15ca1e161f4e1ba5e98c6c1afa41d38ed7b0b99e600ebc37c38a73d306" . + "9ece9ca021b9a96141eebac77df62a8954dbce7646056c108e596ee9e5b2f29a" . + "9bf1d86175894b5387a53b378930e05017e6aabc29b64bd7a57503fa1d961392" . + "c6226591762d47dd8243156d159bb72c215ca10bdba49f8545c463f91ebf5aec" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "a271944e368257088fe5fabac860d7e43d7762d145b986b46cd8aa944c116214" . + "2c2b6e67532b6d20a72e61a88226756af27f1e7b409f8bec04cd7fde9c058791" . + "e6e2afd8ce9ff880d774d79767ce2647b3b05302c5ddef809c3b779185b6a316" . + "434925d90375aa4909a005e9487af9dc74270412bcaca070d7c4449e9067c80d" . + "a3c0c4deb430ddd69e61b4c7c6702fe5ac2798a1be560108aad3f53cbffd4747" . + "22396ee1a419d367b78f26860f7f7bfa69d87798de310f9a6362f6ece331ce2d" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "4d2be8bca9bda4e6aefb3495f3f2e05bd27e6d6b5e668f1466ff3fd6aa67f001" . + "b535c329c8de61a204d74c6ea4acc8738b1fdda04a90fbb59cf935bf08ed1fef" . + "78b0dce91caabd4cd44893a159458c6ab61a0bc1e18d9d2a6cdd1a4a018a0322" . + "5c2990f4328e83339133255c0c040d3e842bcf4e7cbc012883356a70693d1e26" . + "9eae6589cd3fa45f9981a5db077041b82f78d8164f1615ce603e0f305e4a0171" . + "7e1e53a44a4a859078da111921ef38362435b27e885a9bb16574e01e8ea1bc3a" . + "965e753a8d47f7b02e63b95a0cf80a0a98f0adf9846e9f004a0220ff700baaee" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e8e1e7c3bc09a5fdc5509dd0c71b84c9a58f74e267818bfc3fd0003213757ef" . + "5e8e1e7c3bc09a5fdc5509dd0c71b84c9a58f74e267818bfc3fd0003213757ef" . + "6108235e1595b988e4a44e9e04b5398ff8d561624c60728dedcb575f9c1520e1" . + "6de7af7efa73ea669f4c5c67d53d9e553ba55292c8e4a6c28c666fc129363258" . + "55b13b42a79442250b71785a0224fa85fe7189fced9af7fdf7411ee2600cded7" . + "3521e4ed146ee23d07af897d854ed2cee179b38ce1a149f4a7958e1ad327d4ed" . + "c446e6bdca48710c0c3b3068c90bb7aa1e0b4984b079009933c51161fbb62132" . + "54c5a8cae348e7cba6b50f59a6fdab40dd38a607513ef128262d81dafb99580e" . + "064d3830e9219227e86bbf7c7f66196272435077d63e5b80c66b7ac0d8ee4ae0" . + "60b7dffe7de4915e84ffd377a11552af3a3c57d07f01d7a5f517ea5d377d69d9" . + "b2d0b9dd7be0c98fa057469ae9eff6ecbd555c3654061c19c8b573d7c59c9bbe" . + "85bc04ecf7ea823dc2df4460229dcdeac98b04661544e7d1ec64c89948a7cdce" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "712e07a4d6cefd925458ffdae3a00503e68693ea86a0c41b9d2d1246709a1574" . + "d08a269a90403a056cce128a73f9736c786ca5028c823916ec7a52127ca8ab52" . + "75d0640fa28eff9479d0be1f0b5fb7a50c7b5b45d5a2bbb454b20f774e4696b2" . + "7eb80b251541978ddc13fc6a75d8997ca4996c63a67413dc304d1657211926fd" . + "36af45f047c25696e0e4704c1cc005c7305cfc19d253683107a0741f6fb855e7" . + "84a39de85048a1dddea47e5f82335c371bfcac8f74162e137af0a068c2fa8318" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "40f718b49bb7ab9a826c331184b94b2298a8aee007b802d37e864c40107d82a2" . + "730033e906d4bb0433f066d1de89136f8fffe60d5687b366f4cbe8c47b062d88" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "3f4c1dbff1798e48a297ed7e25908ccb78583c1679d5fa87b30b7d6b2f866096" . + "ad17b40ff5c3da8ae26831b3ce3e2707e0386c6a496b6bdd5d89f485a33a2796" . + "a07ef78e95c22b1c034ca3194f743d49323a9267798770d1c99b6dae572baf03" . + "9f9b63c5c032cc6cc87901314b256f2c05c86266ec4577c5b8e603ef5e07ccc9" . + . + . + . + . + "9b204719b744532f304fd8f10e773278aacbffc0f9919c9213498a0c00d67eb6" . + "565238d5dfc528552ddb9454f27a2bc661ee0cf9fb949e8132f2ef5d24439b8c" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6cc1547c541b83cd752096d86cbdc7a196c5b887cc0e6a03e04678551076e743" . + "6cc1547c541b83cd752096d86cbdc7a196c5b887cc0e6a03e04678551076e743" . + "f2d238b13fc74e650985016af67829da1b07a71d20dab8ec0a730152a658671b" . + "fb4b830cab50f9db7986a1430a354421d7b997d2c1f0aea0297477851d3ceb8a" . + "cf0e3ad2b2e6be75661f022354269068a279bdcc0e536b65660d1a975fe23cc6" . + "56e2cb4baadc2577ed832ac7b87822c9aac9aecadf9a4c2dd4689c07dc8855c0" . + "eba033b856dca416412a2a0b1fab032df43311486229bf9f0be6711e7415aa08" . + "aa4780c2e3128209de71eb653d3c947493a551d6f354e91ed5236cab77c32d46" . + "c4f43e3e94d311bba21efa6a9ec0f5537180cc352c2caa795dd28ba91c668097" . + "80b6e2686e5e38514d71bb0ee4864a382835855690e095dd4009815c864495ef" . + "5f462112703230f3265b299b879bfd864cc7242256bcb98a447e344a0089eb74" . + "f161fe10fbe4eae5f6e55e94551691ce7e119626046451331488ad47e17cfcb1" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "def3858fb4c7978a2f7b8439e6f2eaf446e94300faff47bc76273db937df71f7" . + "438ddb88b337407855313e5a01646fd764be6ea5029f3cc4105a86fd7504c88c" . + "71df6f9a1005e95c3174bda37ac3876fcfa402d1cf235653ff76dd932b5d1f55" . + "16534910a817110ee4deb05660e37775d54e86ecd7b7f99f55b867c6b42f41a4" . + "d294d593495d312ed7ce61c2c9c55b6c81d5b6f019f6a00797b9932e77d0c258" . + "a1899738ccfbf82b64798620509b647b658f4cf518f2ad28fd55e0eddd29d11b" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "8ed94593e7243f8a6ceee1c8696404621f18bddcd40be88a92d9b13ef7ca9f33" . + "37064f739811844281883f35e0979d155f48622a853e52a664a4db4793529dc0" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "c2a846f62140421923e35f449666b365aa0bdc68031dfa861bc3f9ecf2f9dec0" . + "176841da2fffa6dba3e9002db7739c3cbf56419a60c3216fe7c7728296fae9d3" . + "6229868ac9f398f4a8aa21cf296ff975c853f99bb38781507a909516c21a6d23" . + "b88ebe2087399f871d40338743dd75695375198c00c4131baa155f3131bf9c05" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "409fd97bf188fd75c3a02f52874fa4dca6d7d5be8e2d3251e62b076fa79977ff" . + "409fd97bf188fd75c3a02f52874fa4dca6d7d5be8e2d3251e62b076fa79977ff" . + "7d090b1d7ca951538dcbe500404e1ea9f0acd11475cf709f85198aed1169d39d" . + "ddd46462892d6a959c9e778cab16687aeb64d4f1336ac78d8284eb7225bd0e86" . + "f44a7df0289acceb82de22d2916d6771d0ace05a2f1657ff1759f7c94c6716da" . + "438ddb88b337407855313e5a01646fd764be6ea5029f3cc4105a86fd7504c88c" . + "9d0a188f4cad070f6207d9d189f63d46a6d929b55df4f04aa7cd7d2fe6887cf6" . + "7de473debca44c11c87e5bcf99398ca3162d47dc82dd821f02687fbc96a6e89f" . + "8c8b81cd260f7dd2c73384c887e3149750e0974612fb479c244e75f2d7c31424" . + "0bc9eb9ea6350e5aeced6f6de8a74dae750dc0e341d7537165f0ef39b818acfb" . + "9ba37933f344e13f4088cc8ee3f7e3e89b0370ea678a855aa89612b72ce182b5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "1602f00e5d2c72d80a085b7ecb4bcf7115d16e6d66db25c9ad997f94deb73833" . + "284c6822f0e279171593521e1afdbf38bdfe7cc8592afae05d61c0e7ec3ff9d4" . + "ffd0a00e9eb7a3a0463322711d0cb81a3f0bc2cd633983a822cade8762298cb8" . + "8762cc4a572d3b49cf63d2d763c2ed822d92c889dd8bb05e1876a285b3724bdd" . + "a1160085dae599178827796753038a936f19913adc07a7365e48524c12308f27" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "58c7711459c70c72c2605b439d940a0e9562ac71e73f820c1b4890657394024b" . + "b7a8f5ad7f2d4d6e1060fc089a624f5d11a7c4843af945fba8f18a53c5dfdf59" . + "e1a802544645beb87c65df7631117e1710ce398e34baee51e7c347cc560044e7" . + "dc04a38da68a9cbae96c8b5a85665087bf2b5dd96b229383c90e3cb2623ea41b" . + "58c7711459c70c72c2605b439d940a0e9562ac71e73f820c1b4890657394024b" . + "9d583ee0058969aeff46dc199e716e5532419fd4da35b8a7059775eaf890a4e9" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2f504d3e5821c3b8bf558ae81083dc298dec1005dd9e03b1988681d439807f40" . + "2f504d3e5821c3b8bf558ae81083dc298dec1005dd9e03b1988681d439807f40" . + "da4144d67c0920f8752c9fc2b26c773a0b49c0ad55bff31cfa5cbab8f53c2fd1" . + "90eba8cae198b3d3ddd8aecf471970c89b26c18b73763ea118c3169e5354b5df" . + "0dba9ec5d01d09327ba32c46d1a067c1ecbe5ff6889f47de3c86e991d5e47d42" . + "c3a21d059b871519528409cb4a3e19ad2753378cc8619f9560d1e2c46ef3ce71" . + "c6978179d98cf48b9ab8e57a5b45043a835cfe9b3b397093820f47e9b1aac145" . + "74933aeaaf599e81aaebbc7523ad5f40a49565747c4e15cccf233f57acd2dda5" . + "c6db3390515d79895966e35c35ecf9abb548546116f7e2945563fb3eae5ca445" . + "e61b724d55dbb6717387620aa3f52fb1dd92a398ab93a315ed8ca82bab2f380a" . + "4ee4370e43e07ba2578f182cf8d841fc420db4c9f21ed2f74c0cf3103641e12f" . + "45343b18f3ac33d9d9955a9762706d1bbecbac06f2d583bf4d083822d30e3c4c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "3d3946dcd592396a0eb6323c1aee841a9c51173e91ad5766738a8329ae73c770" . + "d681a8e0c5ffdb30e81e231c11c7a98f25c544ea85649864184929134d076c97" . + "0a395c5aaf678cac5ccb510df7f24b2a2bba6971625ac35063f3add8cf688d9a" . + "b1285d38abfd9566ca53dc9e5ca2d29d90396e331e0a3403246be777c101ee5b" . + "b0e75fd2133228a3a71af2d229235e8a62819d9a4c323024b6c290a4846d6897" . + "1718d701710d83370fb5c74b704047b5651e62c299c8402db0df2d55c879aa2d" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "a72a283691bc22b066e67ff05918bfb1c2b9fb74f0213ff038d108b4933ffd09" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "df120f1ecb4d220c7421266dff0d0064072d9eb4f44f0a12ba8c7e302fda06ec" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5102a4c0789c51ebd87d9d54600025e052ab4a47d436127c09e80dd6bf0e2f3b" . + "5e7838e5f3328a1c081c6531b6a363b11583e521362cc7a3ced9dca96f7a68f0" . + "e9050fdba47ffeb9dacfe7692af10ebb29bf689aac1b19acdbfbf2c5269437ea" . + "026df1488e4d09bbfb051270e707c7c53168c83f971c57f1f29dc2b395e6b1ed" . + . + "703e004d53b16deb7b93a301546c40438d7fbd5a84c4655eff09a709a3dbb590" . + "c46a0d800805b993875e4aae49828cfa1f52731adc5464a91eb124f7f6f9f3c5" . + "24170f5927c8fd937fd786101c75448b1c18bb7c42bcac54017a170bef97b138" . + "1a1e5e31c7786824e5d0c591b75e4a41714bf5324953d299c8e06a292ac9b47b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "55e9b5620ac7c5e84cd147a59cbff5696732ad5b99d8dba961bdde44ea027376" . + "55e9b5620ac7c5e84cd147a59cbff5696732ad5b99d8dba961bdde44ea027376" . + "9b2950274c6d3d1c99de32c2c2709aead31235d68c53c1fd7f532f3c19f14147" . + "9fa6b2f39ee19441d52de0107f7574a4a245485b358ad923ea186c745d52a974" . + "dd8ff390b463925799601e327d5b5abc27228e6d77e9f0561e9131ab2e1ee19e" . + "6a0e28eed83b6aee3c3995106a02ca7dead5fd387bf389240bac93af8559f779" . + "03aecb61f269cd0e12fd452106280b2b0a7dd19edda3ce6a91b110d8391f5498" . + "43f65c2f7404cee8e380392410843763ec094dc0c6deef7e9401152e730ba20b" . + "047dde4e5634b45414deb6057ed2c280252b1c348a90d6c52e55862f4ab532f8" . + "e1e092a93436c3e8b461fae980e93078f6855f800cc2042df5fc90d78d61bb8b" . + "c2ae8e22d6a6477c1f29c1a38d2a93cc04fb6b7b75ba038283bfc5e92621cb4a" . + "83426a052f6635d6ca57c0802a204bbbb8f6b7df824c514d09b9483d36a2273d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "b98a1436dd1330741446146ba3446b4a743f3b91ed08f336dee8870489f7c01c" . + "7f555df77aeb6374ad2c802d5b6c978111e75d40c83127c890698ab88a01e78c" . + "5a908f1a0b0755d62450c12579451399462779d8158de50148f1495edff021dc" . + "5d33dfb245681b0ae90ce76e8f2d228621ce2437a9f1f6f33a1a954c948ed9a0" . + "20c1629cb4e4d791a24b84e8c3b62f6b019de4deebbf1a457c8b87d9719b412e" . + "fd2eefce13b76b685e2723812720ddd4327d2b1f3384d5cdbffe98cd067ff7ee" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "a86b29af6b96de73d2e2e96e39b5aaaf4b436f9730369eebb2e1e121ef0586e9" . + "3bc71ed0b692af72a5433cf7ac156434ec96e0f9579347713c6398304cf33a65" . + "f262a4d28050d713539279cec7e2e2738e12e5ec80524c3d5871722edd71acd2" . + "a48c2e6bad5ef79ef120689a32b059b59f14358db0da3323270bced5e7b6a5fa" . + "0e6eb810d1eca91358d8cc3264e45e47abf13658d04f5cf8bc8bc8187dea864c" . + "553578f1f6329974c49f7f801e3069d2f5f043cf151a0333b552dcd2a2be853a" . + "c14a90fd7562c216b9ba5eb4ae51a2ea2eefbaf53d242b708fedd86482cfb73e" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "14e13ed70e1a8988e9619476df638efa6492205f496fe7878571e40e821ec234" . + "14e13ed70e1a8988e9619476df638efa6492205f496fe7878571e40e821ec234" . + "bd939fabb22bc28b7df608bfe14260915ce305e640d249ee3cd89c9820d033d8" . + "75312c8307a409c862078225f14c87673d39aed683eea2781f5cae5184006677" . + "2bbd262f5234a7fbd60dcbe9f76c574c7fada2782c3af78ac42a76a8d29ada03" . + "cef40aeaee5fc930b89717e475f8e8f6f2c9e8dd3a1b75bf72e7b8f5817b1392" . + "8be38f5e6f5806b7e5c189a035e7f3a9ae8abb867c3cc8b3cc21f4de500e5d1d" . + "0521154a3a2933a56e37979ebe5b7023c39d16f3d534a04b12a6247c8e7a785c" . + "2f0ac9f2c51025cefdc345cf78c0cc8cd0ba5102f7b861adee402448845836a4" . + "5742f0cf5f6e5cc164f611809d9a1e9140f9ca18ac2d33f3a8e3c5748de45899" . + "1db0d034eed66226c6cc52995d473d5db821d08d873002bc831550a18d66f152" . + "23289f95e0c76d68b8f386202404b7f499529965951fa9ffd595f1bf9a76222a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "a89c869666c4eb0dcdab6d00d33cc3d0a09752fa3257acab1e3d27b4cfd41d34" . + "17ef617ebff815e994a3fa63baf61a52592e2898a3826d8eb20cd388e0bf3d86" . + "4636a52fa2d046e3117f44f2c05964524db47e918c151d96f718b8a454e8ba11" . + "50235d76433eac1db357c6f93d910dfa82c90de3017213dfcf55dc5d138ce3c2" . + "c411df127bd1f21746ee8b88a025c9a0f93d14ad28469e904c6bb53669f02969" . + "c62106c1a6dbcd3640e268f3e1f614a0d89f23956019f5490ab5b93615720758" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "d80af29003581ca2453b97875ae6e63fec01defcf730391f5729e1a212084206" . + "98015a8f1803a85e088d255cbbfbf0aff488adfeda1096e745ad7e593d9a28de" . + "8a58720bf5fda178b7389c50380b0534d20b9dc2131b1400d264023df292ef65" . + "15eeaf0defafca7529365437c7a7dcd437cf81f450a9bd9a6267ea0c5edb75de" . + "a28db98da38fecfb76a21c4dba2fd51649a50efea9fe4a2004dd368ccec61ef8" . + "549e1af41ba45dd8bf15c15015504a902436540db81dac9ab3aa4ab19a7b3679" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9bde3debca7023ca93a4fe07bd9e060bdf23f9f71b6ea8cdbc27c6163f52ba89" . + "9bde3debca7023ca93a4fe07bd9e060bdf23f9f71b6ea8cdbc27c6163f52ba89" . + "312cc430609b9f4539b9558424f0e838340fa635d40f109de45abae3ed088ebe" . + "3e4f85f51ebcc6ebdf45fe4c252db4c4881681541a7ddb50fce149ec745266e7" . + "7d5dfa611a157a68280d2ac8be12168c4c59836e3c1e09318dccb1fb9b2a57c6" . + "1b9652863e080027ebe182d233936a183fab4203df717365a5e0737a11b8c20c" . + "a2b63b678eeb05c837681fcca68973cd5541e150ff11f2da0aba0b0449654708" . + "c909fe7cd76e4381e7916717a561654cc34e24f9279f23579c8051c8630495e4" . + "7eb80b251541978ddc13fc6a75d8997ca4996c63a67413dc304d1657211926fd" . + "ca72f200b026af679a74bdeef51618f594af13c3a3383451c69b76289551e391" . + "ad3844845f24424a8d0a1923e662269d08df926a2c61125c21adbe38161719af" . + "fcd96169747b5ff92df6e55e1eb19dc006d07abcb7077b8b43ef265d069a6151" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "205e1de43acda5aa29e04c1bfe196e50713e8c74c478721822ba7e741e8bbd85" . + "404c7f327268e65e3eec2a9698e96ff34737138eddc6cd2d2b791a4394dd61c4" . + "5ebe46251976b6e1082b457e82ea237707303abaa402297ec32228b94a778ae7" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "9105711b24a297386e71113b857016e8f4ad1ebe8af31bcf6b132f9632b442ca" . + "67329aab7acbf332b30c7d34ce0527a8e3f16b410604ec64402ccae2b9408c08" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "5ea3ee36c9dbddeec0803f364cbb07f8ef36a2c9eee8cf3c22f3378bd92f6e1b" . + "7cfae2850e12549350eef3a61adfad1ae765e9d33cbe745557db6b312717108d" . + "968259ab436feab20f9afaded8992503c43f8f4d17c6fd0006d3761bac267de5" . + "55b8f22ceaa0fc69d4c80c88c8d256f80eab1433ab55f231bcff6c5f9d79e9e3" . + "ee3d0f43becae838371b5b4359759f57b1e5dad5830ce8338cf2e7519520904c" . + "efcb52e6cfb3016553538ae439f41e1a9b212f7c991992cb124109d0073ce918" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "33b2cdb255c715986ceb65b3bab15da7d622948b4b35da1be3fdf3f4c1c575a9" . + "33b2cdb255c715986ceb65b3bab15da7d622948b4b35da1be3fdf3f4c1c575a9" . + "0e8ada6473f82c354f5654458e357a1e769a27e0f8f06eb68fe252c6947eb036" . + "2281992ea031c6b48a906cfb8f847c350d65e2550dde4f34f3233284bce6846a" . + "339e69730f7098de360c6e05bfd5d829c6a2d6523606cbfccabc935688db30a4" . + "400eee6f115f031900d8131f4c3c155a2fd75e5a6d443ef27ece57257efa1d84" . + "b583dc41511458f798fd30688aec99c59b149ca0b65c06af55c1715fccee7e66" . + "f227cb3fe983686f37d7b5ef48e475a75a4c46643adfa1cf4c8b8616d169c24c" . + "405a7fc0984985bbcdfb75dffca5a72c03623a382e1cacf9f8c402086c099be0" . + "3c29edf097ed495ca81fb561971e8c822b08c1f44db7af5da9798114925a3b8e" . + "17c6867b0c9979e890caf17fa45dc728fa2b0af47c2330415dd18f239a1b0d36" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "b4b6192aa538998b1cf64cfc109a174956b83f5d7a5ef358d13ec1882984a0ad" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "0a90e5e6477f0fb3db40d82c789f3e5f744c6cf6563f764101864be78a1fb6b1" . + "d6832397f18678381bbc63171ffa371e361f27d40ec98635c7672b57045441c4" . + "03567e9192f20c275f214c864e08717c5c2af0d11d52eaf85cf452c8540d10e1" . + "211bb643bb55fe8792fa12744e931f97f87ee7578abf04b2a53f5c23975be392" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "1db51ff46979435d328ecc86cbad40be84cf7d99ea0132ca2157dc1cf5189b9e" . + "6c21cdd3efd405bee8b0a1f05bfd2acf7c062a004732e256bfb518cef5158d74" . + "6fd9fa89e26b45970f494a8d5ab519bfeb6b16b1b13ebfb6077c5eda790e7441" . + "3c86691ad4857cc99310c064a38cf12ad9f6f3f6363fee41150879bd168aee5d" . + . + "59e322c6b6354e06ccf10717a9e39d2996fbcfd630131245b6174daf40a08d0b" . + "01e0993f61e8b09317b614776f2d8fd69b6a0dbcfd25826cb5e64431196eac15" . + "b88ebe2087399f871d40338743dd75695375198c00c4131baa155f3131bf9c05" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "edfe0e06cd95916f78654e5634cf3e9a8928294e3aa6355b8d9a41f32d7b7bdd" . + "edfe0e06cd95916f78654e5634cf3e9a8928294e3aa6355b8d9a41f32d7b7bdd" . + "e177ad71c45df818d583457ab12c5df88788aa3e0509e0c5be36a7febe89c15e" . + "e54c4b848a23d2dcd796d29aafc3875494e52c11f2f91da7665165e0c76db725" . + "c93f8acb6f47f8df84222e23413b45a90918b2f085a69b13f11378f9a95aae76" . + "31f0662068fc79fe6b1933e62c9d0aa8f010dfa0738964a2ad02b9eb463bb1c8" . + "eee6b0773d735976c9e6d6c19e8e1a418c682cf5d4fae7229b733bf4b536b17e" . + "b20f64bdef37c2d28d9380cc157123ec141c05ad9f74d1bb6c4bf11206a967cd" . + "fc49f600e96e64c84ef0d29a35d69f442e84a36a5c0f3e82357a622dd6f5104f" . + "e1cc191533f5c1f9ecb6fefde5be844e0465c632b66885b896f9ca4ecaa3c74e" . + "5df240ee62266f9fab50a1d1c37d55fe5fc44e71dfc90c1191348968a3d65f5c" . + "05292390806d1dd398c06170661bc49291c0763573bb64ca2e542ee30fc003e6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "0e074afabd62114ba736b8ba8c4bd6159c0fe0fe1b25dd26a96cdd7365e82458" . + "e6862a1afa16b962408f31f7ceaf5c99b0f797c9d13ae233af47443a714af871" . + "660e26c9f40520c272d69cd81b8c84e693ccdc33eaa11c2f843d8dea257aeea1" . + "f048927d6f991ffddc3cb0136e9d10b32eec7ff494ad3c116ebe0df54952a288" . + "2573a751c14441913942080c9d504491fe3fea8491e18e64992ce5d8c6557fa0" . + "8b54878c486a3bcf3b2cfbf9ea53197fbcf8b82bfe60b8e81fe0cef1f9a6e9a6" . + "0c1adbdab40b3bf6014abfb7aefecb5eee31c5f7f70bdc3ccd485f5139837931" . + "aec3331e1bad85c10248f79762594382142559fdea475083765898df237f084b" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "8cb8be23a263b1c483b258b11a4b0d96996d58dc13040c92f217d7f9559379e4" . + "dfcf7807f5d468aa96ac961fc8f41833c87e6496bfaf595d71079189349961f0" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "9173b8aba7935f45bac6dffe6d36880691c601fdc9233416054ca57bf3cb77b0" . + "8b3e0ec2a2d299513915bd45b8b9726feae27bbc6ce8b1a3f15cdfcc06b9b035" . + "4256699dd1476374541875eb7e59a965d85216c8891d799404f002ce191c8cbc" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "168a0a0d4515e231fb8220a4c9d25876d1c56045572f7a444db736c49338f1dc" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dbc771a65bb3d5d6d55e47b320c031647db7951fde80f6657c8e3a35ae32c8d7" . + "dbc771a65bb3d5d6d55e47b320c031647db7951fde80f6657c8e3a35ae32c8d7" . + "196ba9367d826124061fb174e19e31f0d4f03b5c7187a41279d1acd6d970777c" . + "1cb39fa519bbc2dd479a0766c9c25158eb9d00ca6184670dadf338676a6f2b75" . + "21f8969af55843fd5bbb383b36c735167093b556fa59581fb2005900e55358f5" . + "91e009cb54e72a400e65b6d3f8ede5807f7ddbec1b5fdbc41c1b15647d605541" . + "f3d88426a12767eeccd66a56e56d11ee1f3c2188521dd3e0638e77a37eef7cda" . + "a8ee37db2c8c0a99310d2bcec3b924bc379b3ec6da8eec14d5b6bb64151528fb" . + "5084e23682d6cc9c3504f1151d8ebd91e7640580ddf29021e6ba317706cf81b1" . + "100aa01f39aaddd94e75dee658c41d5bda3787f043b7fe624425a6e51b1e8789" . + "e0745ada1a29a84a0dfe328ff7ad44fc4d3752219e144f1d6c6bb467b1039629" . + "0b47757a5630e830fc792449f89152d96bce6ed003854c7fb66e594c999a63d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "2913140872fd660ef0d6a4b253abf43232fa8a106de9b14f52bb73937ee47950" . + "0b2b835b2a384737263c5de422d337cf70f0346f58d2bbe3e38366217bf28612" . + "76262416fcbbe201d50a63f51bbf202c4b54295cead83d11f5ccfe9be162c4d6" . + "d882bcc57426b3a62ee4c1412c225c84bc0afbcb45654230b6be03a94d421ad6" . + "298ff17c0461b9b3ded506b79d083259b27870c9155948b15d5c0bb4d5254462" . + "44864b7c58a6c75b0baa83b06343e39bf5f0ec8f72883ddb46a85930cbd5d266" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "6e1af9c5631166f9f0e1b18ff77b635b4a48269d0c13420b44e404ee879888f0" . + "1836d3affbc39af9b7e679ac36ef5989755c9f77b70efec08357690243025083" . + "67e7fe14dc03a9d02131e8331244e72e9e12362a2df10679b7f28a7aacd9b030" . + "e3f60b970c2cb7174d2302417369e0da6654f5e44ab89de1ac08e8db831233ac" . + "65b74bbc2b0f591fe433e25752eda8943b2affc80dd75f601d958de6b8c0ebfa" . + "aae10b5c8307a7651a675107b114d94cc47d41c7d5eb9afdddee59444e8cfbb7" . + "7540cce4c5ab3692a999b09db2929b53aa9382480f4f917f06626d8edf61cbcc" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b9e922dbecae9fd9bc521de0ddf5eb94df099299e6b381c0171eabccd24cd3ef" . + "b9e922dbecae9fd9bc521de0ddf5eb94df099299e6b381c0171eabccd24cd3ef" . + "098d661af0221f640f48c4992ed64f74c576cc8a1c6383028d4e74c00c3f4af0" . + "080f44766c08493adb2e56f8e6925f91f55d4b872edc2f97c20ad7b98ae9f2e0" . + "3a695fa2653e405b723e39904c337b314badfa5a645483a8cb56b5227034162f" . + "5532f73bf444867b67b49c2d1bef65f07ba7a126f40fbabfc5d3f4c651f1c9da" . + "2c8ae8939228bd19f5fa13882b341292141a5d147c61257db543db7c94bb8195" . + "883607475a2bc57b369901fd3e52dfe78fc6aa8e712179ff62f75d0b76ede412" . + "88a1416fb597fd63a9ee1e57c37de72308b1ac6d2752b869a7dfd67038070f9e" . + "12b797f407a74294a0761a4854f1ef753720fe5490519ebb36aa81e7de6be4d8" . + "bdaba90673bfe7f1f70fab29c7c605c85b51d7e60270630ad096034fbab29ffb" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "9a26df50df06a1edbf65694cbfcf10b0f56015e52b595f6ab6d051b9c8e78084" . + "7034345d6ee536685eae719ec6e07d85984af5f78c454362e0ae2d9192e093b5" . + "e6a10f2e91b0041a66ce830f453208a934f15c16909301376f51162065caab60" . + "1865e8898c2a90e866924e64fec7cb2c713cc44255471fab626dcbe23c371390" . + "4d183fc93fd14d5ee11a0842fe3ed2b73d0443afc5e0cb5398ea3e9d61c2a6a8" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "3307048df1fc369b3c499f7691c545806f663767ffa5faa5c894255fe9af1ab6" . + "1ca7571ec27b0fcbcc80586f6031fc8c6bf72552e6943b288182e4908002ba1f" . + "9c4fa637b9243e6b29b2a635014df0fbdc2e5cce4abe00c971d6787211ae6874" . + "54526585d156586c00b4ff0fabc216027b47bacd36f63f33e81bc701558144d8" . + "0fe07a846e40bbdb891a8b7a6b8745797b20b71bdddefd25f3564dbd292cac04" . + "dae165df852b1eb6d3223216a8fc5e6223dd5d886b9a223be433e172e2c915d5" . + "bb69a4ba9475e62b8f351438f9804342a4112b7d1696d323cfc46fa15ad6b84d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1c7d5c19b9bf48633fb5a0a438e7b3b82d9b1f3e54a0ec291446eec41ad372fe" . + "1c7d5c19b9bf48633fb5a0a438e7b3b82d9b1f3e54a0ec291446eec41ad372fe" . + "81ffe29167b1bc9fb7b2c12a5970d6b377d4e54f4ad132e1f45cc34fcacfb432" . + "b085e8c58819800a816a3f09b58b7b61609223d62e6682ad84df0b51799f08d2" . + "5df5ccbb7cd4fc6128ae4606d6f30f480230ef3fd54124236d320773382f3d57" . + "fe08510adb3328708f9fb7512b24264cfdb97c8d1c7d73b2899a67a5b96a37cb" . + "934483357a01e6b742170f1792141dbe47368bd9f423cda50148322a7bf993b5" . + "3ac2ec40cf44ed347f41aa4fa132a81dc1aace52e057fc514ad79694533300be" . + "8d939712bd04e92b6d64dc956fb48ee71901f3f6e4968b280343a9e868381e7d" . + "aa1e521e6a051acab6ea80bde42f0a5c091619cfca7a0a3db7784513ec6ce7ae" . + "8c164e4cb41890468d3873d08aceae55c61c3b8ec2476877ae46ba6b7c4e4a0a" . + "c8c28dd3fc409a6cefb56a9dcb91305f0c6e0e95838e648ba096d2b83f28f02b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "1eccd6b1572b2b8b11edbf4d0be7b1774dc7ab7333b619bdcaaef496b79b8968" . + "f527932df74c5284bfc0a6a657ebb5ba9e8a24140d8c8203f47ba4599f3772d9" . + "01acc27701fd547a20d5cf15882529a4a094f2f3876eb0dd23fb7aeee63629b1" . + "fb5a9082adf82c910c838e05567dd5327034cfff37e34e57534cd244d6c5fd9d" . + "d10c6c4d323c5cb47cb985a2c907f48c9b46fbdb8ec92d45bb58f25d92b69b49" . + "a4244c42ce3d1bd6907b17453966752fb143f3a4c262e3afcbbadc4f0634c782" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "8ea49f1455548d96643cd9f008dc83641928442db686e5b8c793d881a8ba8343" . + "2296fc3bcb33ef60c23ff2ed257e4d5eb30ac8213f538c0182b50caef567e740" . + "ed2add28acf0086c902c2053eeb7771304dc1b091687518ee43c3af6c4a1edc8" . + "b41adcace24346d40e3cbc0ce6248e9bac73a8922b359d97fa1367b5384f0e81" . + "7cd39ee7b1dc30ade557899bb66cc74fff1ca4e6c951b28496a210207e454c22" . + "4cdeb876f3bde507c33103f3a16d22beede3163126b5e3a06a2d259be0d61189" . + "63da9bd51a26bf4db59cd64ec3a0ca7b8f33347a9d6665ca40a0384dcaccb7dc" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "af19f84a7444cdd6025b9254249f7360792685750c0b784448b238af925a52ec" . + "af19f84a7444cdd6025b9254249f7360792685750c0b784448b238af925a52ec" . + "8adc0aabb4ba0548b8ebc2baac102ae3cfd90ae75f43643236a81a5b870cbd3b" . + "c3c98dbe153b43b7923b0ec028163215fe14a60ba59c5c001bf072fcb3d5d17f" . + "caf2bac2d714efcffd7a61d2d9e565fcf1369e9fd92386dd724adff8466231e1" . + "dca36595270a5ff901eaba6780c2e1963cd829f705704cbdc2225e384140a681" . + "9d0a188f4cad070f6207d9d189f63d46a6d929b55df4f04aa7cd7d2fe6887cf6" . + "2f0ac9f2c51025cefdc345cf78c0cc8cd0ba5102f7b861adee402448845836a4" . + "75620e2547080b04aba78dd4c74cd6186ae2526d3c25afd09fbc1f422bc4d314" . + "90534fe730f44320be897546dfadc48a23d1d5782a097ceea4bfe5f4baee5094" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "dbde6f69980426eed960dc5459a061c99547e5f091adfffb8c3b4be6e75c5b92" . + "b7b5330cda081721d4e58ae6091ee64e4df61fd7e3a4d3d665c940b62c980ecd" . + "58fd0f231e923245da0d0a04e1a39d8a31c876e03f240850360fd49cc5636a64" . + "86bbd173fc2915a3929b952f420cca4667bfc6d4f5f0844220c1961dcd4aab14" . + "bb32a196086eff3ad9c147fdc49a922b2e4f0dfd64831c37982655c7f9262613" . + "b6311510029797afe300688d69b5cff91b1168ae12488cf2e66137123aa40008" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5f9ad5bda54ca851ae80b2fecb14f0a518f98dafd6aa64a314cc809d0582330a" . + "e4d6a23e3923c4eeb6b8e263969aab550c579492183c5a79e0743ae85e1bd3d9" . + "bdf448efd15e55ffc5b66c8ab743637ebead0f9e273f7cf60ea30ef50dbd6401" . + "9173b8aba7935f45bac6dffe6d36880691c601fdc9233416054ca57bf3cb77b0" . + . + "1aa1117876fd0dd522d89a6aa87978ddde841afa72310c525d1cdd28c6aabd4c" . + "56931ef5adf6446afa0ac357925462d91c820489acc03e68c6589e43366d24dd" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2652f50c770b45bd9899b56aca9191be6931fa2913becb6f07328425a535015c" . + "2652f50c770b45bd9899b56aca9191be6931fa2913becb6f07328425a535015c" . + "fc8faf66ccaa0398b89c729dd772278c002ebdf8c248d8d96624c6c7f4b24885" . + "0a2a521302aa2fd0470fdf0e5f080d6f42ca74c879fc79f7736980674d4c267e" . + "acfadd8620014916f47437513ed3bac4e576224caa32eb237ebe16cf23028ef7" . + "3beba55a328b035f9d1f7fd3e695dd926f273d9b874361c814bc8b7bd20c98be" . + "312fe89abe66b4a15dafd4b70eec0878d90ab344925095cd3c283f8358d9c4ca" . + "6f79a2bb8c0dc42266eac285aacdf40233174e76d939636d37295327f2c9a51e" . + "d768cd84d3d47e2c89042d1c5bcf664a42ffaca234992be628f40f45d20f1623" . + "3d0e333d07df92fd63a3cddeef596528007cc7882a70cd3085779f9ec38ef623" . + "c872fc72f95b08891050a33d5fe41934348c890b769a008695c7e5bb16ebefc7" . + "24231ac74f7e85e27ab3a032028c72f876be15b9120afeff9119b90cda37d82c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "0e074afabd62114ba736b8ba8c4bd6159c0fe0fe1b25dd26a96cdd7365e82458" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "2fc0b5893c709ee341704b539cf93b292ff5752cc00f81e92cf2dcbf6afdc109" . + "389ed846b4889807f1630633ac25edb18148b00f3cd4ff488d8ed5e6ca75e952" . + "4d5f523f30e73fd2e20a85f8ebdcc3f6a24142e0bf35c50b81fa0475c275463f" . + "73daf939d09ee8ae0723660f62d3c60daaf401a48decf6472ed273462a45406f" . + "dc2757872a7a3f6868e56e8d6dca0a65dc93c14d4edc9cdc2d73486817f5fe9e" . + "1080cf6edd2ed8c0a1a5c1a8a05aa818dc27e58d6740c1622a67c0e4e4833821" . + "ec86ceecd6b751975b84e98c389320b243c676c413f01ce8abb36712ca493f51" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "774086ed68767264ac01260cfdc748967244c4eb4c7108858a13456c66e14e13" . + "3b56367d28cd37ab3533b2bd8e05529896ec0fb23f9a9b610d83c6eca591b22a" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "231f2c62c5983faec5d61896d480c84cb0dccf1cf16fbbecbf128c7af1981281" . + "cd99cea8b7d7ccaeb7f60872418fa42972f0459314adebf2645b22a1d306b087" . + "7a7d4697192c3c028870019f6d32dbc2490a15e958fe6a67a718b73c95717f64" . + "c5246cd059e82289c0584ec8af220dede9cec3e97e3e00288a7bcb41c59af536" . + "46ba79108487f0824f3bdab60bce7a969493fa3761f35cbae956a36996705651" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6cc7652f5d8d4a1273c1e1dd2438abf1ea8653e534ab7772a81d8b25ed358b7a" . + "6cc7652f5d8d4a1273c1e1dd2438abf1ea8653e534ab7772a81d8b25ed358b7a" . + "564a01b2898aaf3f980686eff9ab5d2befb98f153627d635ff0305ca507013b4" . + "564a01b2898aaf3f980686eff9ab5d2befb98f153627d635ff0305ca507013b4" . + "25f11e52099b8fbcf1616700ef06d38ebceb143b47e21d3b2bf0c7483194306b" . + "ee640f354b5a399f655b169f155a2a73ebd520b9fa19f32e724bfeab859f39b6" . + "d77d2b8f8cb866737755c249bb19a97632bf339ed753d990bce000e0e5f8c35a" . + "0d600e6de856ad0119a656799a4ce84ff527327a8867d993d177f02105339fab" . + . + "2188d809cc764dc06619f6c1698b18a0b66e0f857818ff3f7aef2a92541d2ec0" . + "df6858085238753e354005cdad3a0c01aa8396cf3e46d8df541dd4012e2c8c1e" . + "4f1852774f1625de6eb3360245cf263a66fa34b660e1245d3b4905e22ace1171" . + "b17a88cbf8e71a045fa89748e1544d6afb007a8cf2e65171f133f83e0bf651c1" . + "26afbc988d89f781da33c9c00dd0325f0e5aa8f22f10b3756a3dd2888b8ef8b2" . + "da073977f3e6b1d2150df6c626bdf352816d3565d5d5050b6809e2b82dcfd429" . + "6ed222262261b750f33e12b6137f4ee83bbebca4ce504de518ae251bdb359921" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1278f1cc3132c926adbb2281fec6c217fb6a64bef56f10e95ff28ebd22e4c123" . + "1278f1cc3132c926adbb2281fec6c217fb6a64bef56f10e95ff28ebd22e4c123" . + "b721b17e06417029f60d0151e9c028fbc18f47939ce8543b6a855e100cf5cf22" . + "1dd1d5c4fc6e196212af04e636f86be2277499890b78818ab475b50c17201eb9" . + "fc10c64b44b24dd5671825ad5178697eb6a27100fe340bde19c74f74238e618c" . + "b66f5d2ac90616664289e741cdc3fcc9ac6ab1012575e879baae4d5a29db0857" . + "0f25766bedaa9dd50291e39795c4e94d95012f1aceb78e9e5a7c4357a5350e92" . + "e7b729e61d2a3537c3ea5b28db550eb6fe15ae739d52f839abdedee1701c76ee" . + "b5ee8b0096e0c8f1651c66989b5291291ae3adb5c8e959a63258c61682af0bcd" . + "ef965f5881ce26384d0e183a2ab7ee584d40b1b2c89f582e543ab14733e76efc" . + "e8a358514ec77c2cb6e307e6b21c941478ec1e8e910bd01b4f3e107d410e89f4" . + "2a9c521e47ae45b451882b5a3aa316d253091c8a7c4a485f4f77b21955ef7f69" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "485a12576f69d522b364d00505a250feecee0ed99534648f2d2e89257c0222a8" . + "9ed7c4f971ceaf78b1e9c5e83464e37612dab1a45b42a2c7787760f4904318ab" . + "0a395c5aaf678cac5ccb510df7f24b2a2bba6971625ac35063f3add8cf688d9a" . + "4f36173eec59c0899b9a9da719b866102a9240b451a967664e1803e07142bbba" . + "7a7c2081ddfe4207412ec6f5829caeb9d938cd0456488278f0c12a8ebd41edf3" . + "c801ae4bcef5f5488618d914d3a470aa69c36d4cfa3dc42a830b97194c205e74" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "56415694bf3bc06c7036407efa40cac2fd10f95dff10dcc182bc43fd33d747c0" . + "973699f6c57aabae44a92d6b8bed0488cf155c079246c7c7af0b989064510cb6" . + "594a2dc9bcfc327fb74c5ff329debe77fcc2464c7d2a9bbc2f94b2656f46c4be" . + "11598226d6ab575b96e17a00b7b8f8e743c10c863e74d5635952de3baf175f80" . + "a85c2e6a3cb9c75951242e71c0fe3d727022fa63f36fe7dc1d4da6c959ee2fbe" . + "ad939c5f0517bd85835d3943890cdd4e7afc36a0f71ddcb795eae9b725fe331b" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fb321980bae0b0c427aa05ddcba4f608bbebff200c805fd6bc01babb840a3a90" . + "fb321980bae0b0c427aa05ddcba4f608bbebff200c805fd6bc01babb840a3a90" . + "917ee9f0ee9fea4cd329b8d1a4d194b5ca10e1e693fab7ae13ea0c383b78eea0" . + "d5d6ae7bc13212516475c912b0ab197c00aea79fbb3e8252ffd718b8bd1b948f" . + "abb7120ac2dfb54136a961eb78d9e122b860d025f46afee201243b3c516bef20" . + "472656345618dcd71d2c5bbf4f72a3415b61e8bc879e0992461bfefa4632f52f" . + "8a639c42ca9a3764bdb6715a2f18469d934e88ab40051984b5e20f66bf0aab1d" . + "34d353a74b9b9c3cbe503a155d7add7cdfe438b45691edfd83d6e5d9e44cd171" . + "4743c56e5ca58616e206ff06db5b9b89923a9c5f14aec719de8dbd81d7728840" . + "218176c22d5171b9df3dfd50999a31afef88a9707c18646024e06c7f53f0f82c" . + "3326653af8149e6f9eec7bc12ec9a3da0e90e33b06b2a5e8edf281f1a4091b72" . + "8fc20ec80a985abc1cbafcd46b0c87986566779f990956d47149af37e7dce101" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "76ee84679ba0e32714fc179a20c9a2a3af10f04c609730929ac50021a6bba76b" . + "e3389159d4037ce92175fd338db80800e41328e4b8e4b04c03836278bcea8dc7" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "2aa8ec7d6e5ffca04b7a089dfdbe7eec5f6ba3106dcfd05bfe32be46b9e96b59" . + "1b8ff04f8e825dbe657dcbeb4dbcd09e02b5b604eed667a5e72f02e2abf34778" . + "0c227ba5e5ca4d328935010dcae924aba32648a03508268b1f25cb5a4f7a4f2b" . + "d208c0b7fe907fc5e09b39dba516b3dd2871e5fe5c1e9827b7a6eae48ed4dc1f" . + "4abca8063309a9a714cd24fadb7187baebf5a7df6b192c065f2c080d9c1cca7a" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c50e53995eccb080f13f36c145471a5806c69c51259772be0e5bc3e7489e2964" . + "ba0e14b707aac24654a6bf44f56b9acc91d8a665bc28f59da1c156e24cb45367" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "2685479d505e1f33fa8a5849dc15d703cf012b70fdb8c2ea39968b0b354353f6" . + "b8bb51ca80f5149571cb4d806b7f60b0f44b11e4ed15070b7e95d5e730d3c668" . + "306729ac7ca2f0213b8c061f185f4d94704f12ea741769e59cd8d463ea292ac7" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "51a3c1360eba3b68be2aba6ce5c62690ff7cb1f53b304c947e027a81a1cd779d" . + "51a3c1360eba3b68be2aba6ce5c62690ff7cb1f53b304c947e027a81a1cd779d" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "7156bba39638d265a3ddfa066dfc7425e5f15a47ec2c6102d4aa48694db666f8" . + "1ceed1796dc47d41cdc1cba7fd3bac1d4497e0a346746c43214ffa69f92fd57d" . + "929039665c1517840158b13cd461df6ed33f6fb3268d19cb6906b4e7d0e72039" . + "764bd0fced229396c882809c7029cec286786ef2a8a72a1543df680fa1c0edc9" . + "1abdd0d700864b7579b0795bfcbf486284369908c3c501c0cdc2dd34350e0e4e" . + "4eb3cfe0a032f0dfa40b80a61d82ceec7b3a9bf8bfec6d74a2b31137ef658b8a" . + "0fc8dbed9388caa115e894c93410865cefbbc7a11ec2afb32f4971b005a29c8d" . + "92b831fa4455f7dcd6e0b3ed2e6823b5c49e1fd7e9291e44964ad0bfe570c3c0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "f66a7234a4f2f74a9ca0b0d5dec64178bf63a7b9e420434822b6ada1188450b2" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "d6832397f18678381bbc63171ffa371e361f27d40ec98635c7672b57045441c4" . + "8f1d9034cb6f6800c1ad5265d104ebb251d3cbed66967e355a9b6ca9c4f19554" . + "3242fa7d07b2ded4e703f09455475f4f5a89ee685f63768ac67eb4d1a4666cb8" . + "0a9fcfdb49b0e2916f62713f692082d0ced2098405c35acc2f25239706d67ddc" . + "0417ed8b439b8d575da885caf71e50e9b835a5eeb36ed604dfbc8ef1ccf31f50" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "6d2b7d1b93e6b1cee32eb692a638d4b222698d7a4ecfe2598641a792a82b17dd" . + "7a7b725c69262d9cb822de587ff9948a50e886e649d84eca3a21f8e43c696d5a" . + "aea5632459964cd09f78d8e8c659b31c930eebad686a87e00557df1981a6557c" . + "02850124f9cc3b1f9b6956b56fa6f69eeca32ef9091330ffdd8cd94d91daef78" . + "603c163ebdc29ea752cb0ec0fd411d176df2c62564ca84f3d975321ef38220ca" . + "023f9db90239a22248010b2170530745a9b8ccf11caf72b8c6cbc35bcef3e54f" . + "5552216fe107bec9ea5ea758c2553740455eb17d3151fb20cff5908f50e36890" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "205571dcc45373d285aadadedefa18100be17754af9452e1183f36ee1ec89c9e" . + "205571dcc45373d285aadadedefa18100be17754af9452e1183f36ee1ec89c9e" . + "a52662d4274ba3454ca31c2f148bfa647cee94c8dc6719c80323a90132fb27b7" . + "463a779ce5c8c2c477b3a1d43f77df41a5b33b170aae023eec6b5b5ea59aad56" . + "c6aba549f783031c7a30c15516687235f960510f39015de9aef2c1fcef9de052" . + "ba9537ad6e8bbea4e4f1a59d107a1a9df12add88dc879842bf027722c8fbf2d1" . + "2e57f292d9f53b4cd7929f4164ff3b7fe3e2ebbe74dc03774b98217154110a38" . + "1f47cd734636cb5a967ab0f6421872796465eb42cd8a2caf586f8c3af2047c84" . + "7a8f661f1f5e20df57654db825b40d70965a59de9ddf8a832ce3278670f65243" . + "651598462b116f75ea2ae6223a5f5146c47fb355acc16d909b42f6f617b66d68" . + "ddb25b19877afc817157ce57003dbe6f5971d3e60c7a35ef782bb4b35bc751e2" . + "24c8b5a2183b2d6c0f4cba574054d22bba18e7aa91c9c0e83af9cb9eed6dc94d" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "a23e1db56eb5c72d08fb9b50d636764c8ea5397939d1ad3b35d9b3c906874043" . + "4e4de6ac3b449a470b8567b3e9c7f90f4f88de4439bdcec0ebb4ea52713edb17" . + "195d180c383c2ca392cadf467df315edab84d39a645e647a336dacbf38fd4428" . + "adf323424dd6630e60a504497487f0011e80c687ddee2a02d80a39e705b1a685" . + "56d09cafd4eb50e0fe64b2594ea43756d4f2579ba68021a0970a116f9b1178da" . + "8e7dec460e6e0a354e4eb7ed154d6e23ac8b5651a8a9d2236485189ecc1fe997" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "2f23c11275ab06d70dd46fce133ae1db4db7d64c1dc1191e670b57dfd00c5c1d" . + "212d3e07c3ebf320041798282555bf4b6d40dd58b58312559999f9c72d7a449b" . + "20b9be7807fe9750a6e36951f2dc43eb16dc1613cfced3e62ea0b0a17c791619" . + "69bf9cef74ed3e7afeedc59dfe91cf0a88181f0ebabe3b78bfc6775e781aa50e" . + "9320a7af1f2d950181d196e95646aa58935539f85cdf9f06e1cd79a2b59ed164" . + "de93c72a6f572e1d33a7136a916c65d64a34af3b3fe286b7738e8f8e56e097da" . + "9fe4372b7f799b0cc686387ff442ea35813b3acbdd5332a68d35d9e047474d52" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a06c61a8b0b98cefc0fde0bd81eb484aa923483fbfdfab064aeff1bdbc4c897" . + "8a06c61a8b0b98cefc0fde0bd81eb484aa923483fbfdfab064aeff1bdbc4c897" . + "65f14e6eff43607ccf88eebf300c1ea848c20600624e0d1eb346773f3509c1a7" . + "f3505bebc2875219b96a1d6f7d66fbd529e9b4a6d3884be304c1af6e631a3a7a" . + "599396cec3f23881e6ea1677a0ff92e7c736933cf32cf7e48c9fcec923776851" . + "9524ed523ac75273b2a506958b3aea0d6b14fd385369dd2b6af78f150c43144c" . + "dcf4c5a7a56e81fbbbd2466e28edc713186cb5ec43094b92d5530bdaa008e5f0" . + "8313a47218c2555738338f9d5a888e0b54c39f3e4136c51baa28f99477332ff7" . + "46d88cfae698a4296e9c2c8f41bd13454f09ef56303c1086a86c93b0a119ffed" . + "f3c3bf4cdaa35b98d23e7593255e9c23e1895987692297a607d66019680d6b14" . + "900e36397fb8896892c94aae63b5d0580693b70424332eb7f755daebc4cfe9de" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "1e76b2ea1bfec1c1b9d731bcfa9c0f23ac7abcd5e2225560d8ae3b3432686b9d" . + "88e51f550963a9880cc8a8903cae0486d4c168103fccb66b4f694b5be851f781" . + "9dc1030b7102bf934d6a5f1233c285d785e282ebbfd3b72d2c0a2cee4a9e192b" . + "a185810bd4874d200d1b1ed696bd2a745fbb1a9ec5ca12fc3318920abf1c1bba" . + "2c22d052ff171966a24452436f9806492fd575dacd8b2c3ccd25e40da17828c0" . + "bbabb9afc4d3b6a487c8ad8cad6dc64fe8bd80c3c3ef07b716d48b521d4ccdde" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "7355e70170455f2ffabe3e44fc473cfb3d0d2abc69b24dc416189ce06b6bb621" . + "bc3ea48814a98a8932bdeafa1d9420c66e098ed236297be51dbc6e78f6d88921" . + "6a0db4931c34a3c0b8c6c33c29c10c1c312da7e62041d974442ab851f372bd21" . + "dbb93665e4336ac4a2f7bc9d219bba5934d50d2b8e8dbb5afca912684f6f6754" . + "0324e994dbdd754f11acf7c3dcba0d83fae1b0576b6e496dc104b7fe22087945" . + "9260dd8231200d70ac33f42bea83604d4bc14ac7e118587f7c85fb7badeb163f" . + "840cf632717ddc3902f52594ea71839b1aa576dd9b2ff2d306e3cfcb2e04b405" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "78f3185ae8e9b48628c2a8245cffee13b00526fe26c2945009cb508e947ca063" . + "78f3185ae8e9b48628c2a8245cffee13b00526fe26c2945009cb508e947ca063" . + "3f5ab5935fe86221e7edfa4838123052087d01d7ddaca433e9614aebd3850930" . + "70ac430bfb6d890ea2c9c7bf8b8f6c7e43c18b38b8043b82869b9bc7a3714197" . + "8fb9897f35d6f9b87fe2e8545406cbcc67063c99dadd009e2219356b9196198a" . + "cacc6bf0b5c2a800a36868416dc9924c71f74450c1edb57d9e8f161445346e32" . + "6fb073cb5b34f470e8482cd341ccc04a441893da0e0a19df8cabfbe3d08c3542" . + "df907ebf442d21c3fa597286cde96a666177a04030048978117bcb98a17e8b9e" . + "087fd6452c6ba2dc45fe50db456e27a4e03f0c44264fe47d26f154c1b905cd06" . + "ebea300fec455e79b50b913c20f4e5e8c2a6af69041398ca3e979e2f70acf86c" . + "cc63d612aac3ca3e4615669dbc28d1bc8b5025af972e44a4dcd964bc2b795bd4" . + "e312903fe143bfd9bf6a5da94f8334f1f91acc8d20a74a9c6d0e80ba1c2f42f3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "79fd2323d0728bdd9f53a1393a7de82f46d6f6141d2f7dfa4ac57d68d86d152d" . + "62e264c9ff5b37928f397b0a8bafed11e3cec9bec440371351b1026de35da4a5" . + "462cb4d6592251f8bd8b7891e75eadace9897a35d1d7aec5d7a82d0b94bac98a" . + "066a6de427e42a98d785da1261acdb2965d22aba413fa97d8f0a67b4b1e9ac6d" . + "26b6fa44d622ce79b629e3db80569ec8882166976e74be8e8d4c6c95bed02250" . + "853aa8e4849ff261f23c115882ca0924585c5a37b857424f16cdd0e640659b63" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "571ff606604b103a29ce03aa1d0aaaabb1da343cfeaac5b5b790cdee2f7c0ba2" . + "f365f4a1eb99440ad8eed8a297e9e9e99d9ebfca79ada93b2690437832c7f460" . + "8d882d417a6c8392ebcd5dd32757d4270b6ba5d25ef3eb7106690acbc55307a6" . + "3bbbae673639c70020648eb63c04f6e69003681b32f5af5c549cd8583ab15a9e" . + "44d300fb898444910657c4c03f0c5d2e0346cd7795248e25f45a7e6f138ad1c5" . + "e7d2af298f31aab58415adbbc68ba681cd046c0e87524a7a8c941e0570152bbe" . + "23f425b708dbe0e99afa6b6dd4c751d7bd32a9111534b23a2f9265174e4cc6f8" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e55fd891c733e80a5b2de9bf3b5367816815598408570f2fb8309275e28d4fd7" . + "e55fd891c733e80a5b2de9bf3b5367816815598408570f2fb8309275e28d4fd7" . + "74cf03cba887379bc5e66abd4d987d4b010074cfda5258b906b1c668119e1c69" . + "dfb787d3b7a43b19968aed34e70164109fb35eee6040012267db663002237493" . + "21aedb04a4c2ad7d7ef7c99778cc4348fb2acfd783bbf1720bb30d4e3a30b330" . + "279e51f3c4b7aaabac8f9b97e501efa9950dbcb4eb31e9dd58e88b852ba4b0af" . + "afeb41aee23b7a3f74a78cf7f87f147db1c9eb5ef3d6c84454690f94a434a98b" . + "0b3914a00b7cf46d917797359fe0c54e61087205fbb238e726b800626bc9bdad" . + "8c8b81cd260f7dd2c73384c887e3149750e0974612fb479c244e75f2d7c31424" . + "bbf4e7059b05e37393085f4aab4f06097acf34cd1aab9e9f8d066967d2680351" . + "7a4a3e1577ffcfdb8fb49820f3a4879416fe5bc24539783779c17483618cc378" . + "6a8e42764bf547ccb3057b684a90fbd707c0fbd5a8ac87a768911c2afb422839" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "dcdb9f7f6e3b45444d19365fd4dbbe046319e39781f017374465dbe6cde8fc05" . + "b057796b6f9a745e28c43c5f300dfe1b7dea1565c1816cacbe3d8271ea7aaf70" . + "a17e52e177ef7923adc42e5ef116ea9a30b29f5b251882dc739c5d0475a9e73a" . + "bc648229db2273f17a196444016c9f579f8841009cbf384fe3bef29390796f0a" . + "0ffb5da0499a597205495353be57a2a65e8f9017ab1fcdb80f233176aad3fc92" . + "a16046e3034901cae594a9401469e88b4aab9cd9a66052b65d987afb1e300860" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "0086aa747ca35f0ea01a75ab0d3c08e0234003cf2e9e978e4d953dd8a74b5779" . + "682d1ee55c2198a69734b30787cbf38a808c68a1fcb4f5e41029e44a951b8951" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "dbc7e6092e3a72de51a20823a8928c2e1db4d41c8f5b98e46ced814cbf3a10ee" . + "2cff057f5ab211f27a29991a0ec233e2937b440481adf5a1284a31af93c6732f" . + "24170f5927c8fd937fd786101c75448b1c18bb7c42bcac54017a170bef97b138" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b5c9c40dc0694650887433cf1bc221225d6f4398d938a5926fa2c153f9df2681" . + "b5c9c40dc0694650887433cf1bc221225d6f4398d938a5926fa2c153f9df2681" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "3b19d0daf9cbe527196344206678c4eb05ed4b032f71d472ed8c2acdb9191549" . + "a1882b0dc3645cc4b8f1f7c7592c1d06d1760b9cee4f7b407b73eb1250e57eae" . + "8f4059f657f08511100bf476a118e43bb17d83327da3cd4245a779ca7da6c155" . + "d6331fc1a7184ff719dfd08b3a4bcfcaa6a1a4aeeff43c32e143f21acadfad8f" . + "dc73b4bdde5b2df27bf18f68b6752fbaa9fe4988981efe68d24613a0144c78c3" . + "9ffe9530ce5b97b2c4c47ac0ecf7381b6458421d5209ad7fe42229df8115acc9" . + "7fcf72bdf01c3685d2a42977f690d6dd6b1bbf1bf082029f57009b492ad95ccc" . + "fc364b1bf8f9b40b49515c031509e3e769debddfd66cf77ae2c5712f195f6778" . + "20c75a4836faa2d0a9d69397718212b1eac1e3bba9155f133a8cd56e4141622c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "0a90e5e6477f0fb3db40d82c789f3e5f744c6cf6563f764101864be78a1fb6b1" . + "242726d906eeac20f586d4595e6bfac264412acfea5128004c79df678ce560f8" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "298ff17c0461b9b3ded506b79d083259b27870c9155948b15d5c0bb4d5254462" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "a13022903352236fdc821f5fc759a81e2cd00b79753e6fd05e235d93df0fb6e4" . + "f90f7f03e1189d7b94f05cfb721dd7c8cb6c0998a710a033d934902336bba4e6" . + "5904744d7b61bd1a662f78456e945638a5fba4dd48e4ba5e2634f2706c5b7de0" . + "ebaa5d00f4b0d2ddd51420d8975dc2131de30b1b7cfb49936cb0c1cf21868269" . + "410690dfbdd9e2e55821b3d90376c7c4b23732d07113f9017f929dd256a0a617" . + "1632767a6c030916a3b65a063a90b90c15e814d45093bf0e3c8d044eff541cc2" . + "49b8dfd09f3a2c3f6bc78e74a77c1302aa032d5acc87cedbdd91fddf7a957092" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3ac3a29c4ef844ba7ff56c51a6c1c98a03d207930b3cdabecaad088b36237128" . + "3ac3a29c4ef844ba7ff56c51a6c1c98a03d207930b3cdabecaad088b36237128" . + "48ece0f8deb5ff45944fbd4fad81b2c7c8acc5d8d3ed70570b72bacc4ff4b7f1" . + "5b5c78b72af7953e5d7622a2f6735762a6995dbb995a14d93b284bb5df729bf2" . + "bef178baa9708d6651411fa3c44995b38c765ff241d240d2eba3341026f547bb" . + "262d83d4bf0284efaa182f41bc916b8d41d10fc5f7d52338e86ab41e0411af7b" . + "f1da126aa5e95cfaab8cd9982e14523ce096c63f6a9138910d1e0412d12bd115" . + "4e8e61ca674efcae34e540f0e4721fa9eaed8864f7ee81c50b0c6902cf73f412" . + "0f3d01d1b9627d9165dd4c12347b4ec57834e473fd17076ef7f2bb547c925c89" . + "64993e9806771d7bfd015d8ea2cd50a2bd047245526e6eb2d99ee8e4fda134b6" . + "bef3855ba52c4e383bb7260294db9fe9c650d103c02259d4ea6e7a761d2e8a9c" . + "d2618763ae60bed20c411c9fde674f1857916f2f0b29a6000843b10bf0085e81" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "87d0a693783bb4e797c5868f1870a67faf3137b61fac70a6808bda365112d292" . + "d518d24ec44485b9ad7c4cc42318681dff86805de5508ee9bcdb8284cf1ffd20" . + "de1d3a71ac4529c2e6c2723a7dfa6112b95b42acb7ae9744a0f9001c07bc8e93" . + "0f31da0d335ad5d97fc782088b080ee82bf9545c24722f4a2d213c4f3aadeec1" . + "28491e3938cb43bb0b60d11498f8ad0a8a1a8f1e11db6a5324eb20f192907cfc" . + "8c02a55653ac00efb29e66fbdf1d8dec30e894c846d8fdd5c7994ced5d4c866d" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "4cf30d1fa9747077d0b034314253d33fdddd00cd2847261cc9e4c75f1507c8b5" . + "024a6a6956772e7a38ce7ecb5b215cf348a9343c6c09391ab2577e6dca49a838" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + "c2426b74722228fc03e6f7ed8cbf11a811f55176084123ec67bb9a32911ce180" . + "8872122ef8fc12341e581f2e6ef210ff500a9917734436f9a348aa42e3266ad0" . + "c6dc87c49b4d9ccbb890797c86256958a11262ab9737dba65ae76ac1908c083f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "71dfa75ab39b11a4264066b690ce43628c0314feda28bb7eade7e3042f9a147e" . + "71dfa75ab39b11a4264066b690ce43628c0314feda28bb7eade7e3042f9a147e" . + "e6392c3860839d6334e57a5b735fbc16e34c0ff96e7880c62e08625989b80306" . + "fdb1ebc476f3667f0cd5220a9858692eced3e83dcbe9a6d3a1a36598fd46ea87" . + "b43ad2dfe97e327413b33fd146709684307623490d2caefe79f49a6cf702311c" . + "c0a91cc28fe927c3d656b6c556f7b03641328aac9c08b950e94b595648784a42" . + "e11c9a4d1b045dbbf970639ebccd25d3550b4d94955c8103cd39328b95d9845d" . + "4931a6887e34d08460b1595409635ab2ad40ee211bab9676f80087dc31eac93f" . + "ff634fef99ba07fd3db27c1b4bc5aa0c928b1d7c01401da10133d7cf65a40783" . + "7ba6515881a4c080f6b1fc48012908d3196daac67b26cef2481436f68474ae98" . + "f448de7a0af4866001582aadd7bbae860734704b1b4ab0d8292bb61a3c4f6ae9" . + "10196dd6cb76de5f1b621ba5e4230f95c36ca1847c5e0ff2308477651f398522" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f9ac7385683b4f21dc21de6fb61504221c87ec6078f71179833c4fd4e2e9773d" . + "9f537e6fb799f427300e3ece16ec1d55122196793af5ded034868d30c0af73ec" . + "d43b1b3a07a16f47003d87324e4985272fcdde1baece334dfb41e8dba09afb03" . + "908c38a2913e1a3cf309468edfb97d067af73452447e84a372560416892cf7e0" . + "3f06f8371c5f37940154fe1d40c01c49f5daa7e1a6a506094a2393cf15819e2b" . + "fe744eb8cf8f1ec8c948437f9b63a569bc3a7a34585161daf667b630e498d559" . + "d9bc12f7827e5d7ed51b7430731f1e1fd88502ed30a729d9824528dd24e70ea5" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "74f94852c9e2fc323a646ef5e509c546c02e0114ddaeb4b67afb55315a205ab2" . + "def8ec9981deb21cfba9566cdc6ee9a2bcfa21c974d2df7e22d6dab87c33e77f" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + "d3fd1ca1280b66af31093e5c98eed4b8a6b18518be136e4d5871dd5aee55464d" . + "b6142b3d2075fc7b6f94bee1184ca4f7b6999315948007dc94648e7d6f09067f" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "99ce4d8f9351136e8fa40a4344e7b9cc106af552e4c14fb71bb5be9e741578ed" . + "99ce4d8f9351136e8fa40a4344e7b9cc106af552e4c14fb71bb5be9e741578ed" . + "400e754f856b17e4de1222cb9ce30db5b3cb877424c5f67dfc1874bb1bd53052" . + "020ff562750adfea4127b91528a10679838ad2e01e4d1ea188554f837fe9377e" . + "66f05502e895846296b53f18ea5c52473806859a55ac616718e1bd1132f0b8fa" . + "ca5eddaf0fe7ba621d222be32076eb295d4d300f9f45180e73c753f8dfaf2bdd" . + "fac09beb0869354fce4de572df5bbef79a9b4d343ac1b08ee47a71557a85b89f" . + "3e5305abf25b3c3492703b367c0b0872923646b6b2ad77f1c3662177ccbf9042" . + "cf366bea157df9e554bea87689c5e4e85d4b5f94114f07e0682b63945eb66839" . + "806af57d94f4968046cb2ef23476e021fbdeabc803fca3cb322b02bf46759900" . + "a6c42000294846ab04e9275c5d77364d19dd751836114f1ebab90f120a7cb622" . + "811769176f944a7793abc205d497a89e89732742bc86242c1b3ad54a84b3e096" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "0db715067419ee056c588f5952e8481d30feb6b33f5a571dbd7ad44e285697d2" . + "455511da39b4b39006c104da70b42133a129491bb7bf51a63bca57b40ea188c0" . + "cd0f5601557f90fc312fd90f5d04baa1124ed360e96b31626244cef0ded52d2a" . + "107f04bf59b18a824474ccf50377ed3ddc40532dfe7c34e4bc3509642ce21cea" . + "f05ea07f9e1705c440da31f1970eeb3060e36d64940a701f2afbe5fb2be1a0d5" . + "151ce0631aa2da84ac1c27d78dadcfd28330ebb8e093eda5bddf9915b166e7de" . + "1ad34fd810459c5665cc43945b8786e0709b5283d50d532c1993a23b93f497f6" . + "46d5646907f3b2ad1830014cdda3b0185f15bae283391b1b0831ed3270a1ced0" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "a9548d12f8e515eff2933576c6436ef4b17493d54ab8537dc4df3ee3a5394472" . + "46e57f764c2e58e7c858df2bc2d22fba03308ef2e66743545505bc8e64200ab7" . + "6a522c214efd2b43a26a63f8bd0b6f58ce8e117ffa55c0ba0764ce9e02c18c7d" . + "231f2c62c5983faec5d61896d480c84cb0dccf1cf16fbbecbf128c7af1981281" . + "f8a27991fe75ea0120c5b61535db82c43dabbd1fc78cf2fce9413901029127ad" . + "7ad0884e03d4b0a9d5ae226d7159860db3dd7a6b47b028e0d682a5146625996f" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "add2dcc787686e48bec9cbce3ef738cbfeb6be38e6d26c0491113ae722d8a02a" . + "add2dcc787686e48bec9cbce3ef738cbfeb6be38e6d26c0491113ae722d8a02a" . + "a42344c7437c8bf3db3918d67e77163f11a1f2e0570faa26cd52031a2733c70e" . + "a1aefa3227472c79cf9ed3d2dd6371881d2226dd60e39f31bbfb4fbd1725d0d3" . + "e5f87b399c483589006ed0780c514b3e453d3b163cf2b375ab70cda91d2833c5" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "db64b8cd8627b24e19ce775461e70114640fc9a138281ea29f21744c8a98866d" . + "35884b587f831e21c5e98008a7c5fc23c7968d85c0484387b3dda1c75aa6465e" . + "4cc5701ae23a28e679bb55096f45064e74b0cb40d209411c51c26e6e4192279b" . + "e2bf5ea74ad0aaacd2929b468f69366ab955ee397a254e7b9780e227320eb102" . + "5027dbed46b051881e87ebce497e5eb80fcba5a69aa395febb1539dbefdd0a00" . + "26de59d9dbc7474c5b837e53aa13777680aa2a2275b3ed1e115cd472d7e6edff" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "c58e08732372d81210a1582dd32e3d91f54178255c996c3852832307abefbeda" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "cb2d22582cd1982a46d9acf2b02b1d75efab9dadcf82771f715fe115e72106bd" . + "a718c01ca1a4341c17ab24dfba8007366b66d77cec1603b0cfb35d2fa3ec53cd" . + "e85dfe8351d7d94caca23071387051f3ddff105d5202171eb8b78647782002a3" . + "57d8a92cde065e195cb945298afdca86dc3fd3bea0d08517bd041f0995aae7ae" . + "1e13bdf63275bb3369bcc055419abdc0dbb1a17e79332977bec21c7041d93e71" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "b50d58f02a5487648d050dd8c225dd6e0e7683d89dd1ebfd6c051efa42c35498" . + "b6131389ec6fb4f37e4334c04d6e8c5da49ed0b75d836b228602c61e9dabf9aa" . + "b298d59647c9a8d8e7df3d76bf4d2c010040de4e6e02d92758f552e5c158a6a3" . + "b55bb7a3402acbc04a3c6855ba4358158b294b52347f0c863de03ebacb13f2c7" . + "56a4a736dbc319f25830a05b36a18b6385f08bcdeca302dc1bcafae7dd8fc42b" . + "5cb03e15e7c34bfe1c886ab42b5062708e8d614a08bfe59b395e696f60d11c6b" . + "fe1ab2f8aaa8e763a6240f42f9a0ae9887cfbee7caf77174fd74ea850b2839e1" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0cf60045a5454fd93cdb9c8e1a3c1c6c8f0de00b7555da5d2e944e83a96f93b2" . + "0cf60045a5454fd93cdb9c8e1a3c1c6c8f0de00b7555da5d2e944e83a96f93b2" . + "7b06acb4e96263bf4e0a1b21846da069e6ca9db827a83e24969be831be422e56" . + "4d47709b03765f6fa70dca1a311e774bff2046fbb7836d1bae74431f8070a698" . + "ea5184e8c6565e6e0720cd5490e52607044de84b9c8736456c26a20bebbe36ec" . + "832468701d84be7874b94405081ed48404e650f3e4ceb41bcf2d8e51c70f1eb0" . + "39ae1bf35f2c3f2b963b72803a4ef6b14a18600adc894c288c415e0766059e24" . + "14913eb36423331c39e66f3c43d1a449217738fd30639bb47dcf8b7858b47e9e" . + "cdfb604dc410cccef0b0f3956bb157c80f0cc59674893ca664ef8e410ef75847" . + "7d504e18f8c1c05ae7f6d849f10ce0f320de7db75021ce488c9a009f59fa3784" . + "f5afa6017012800f94f24cce8251986f9883905735f0a0402877100be95458e4" . + "e4759d55aa40aeecf597f6543aa29be999ed57983867d81e786183d29dbbf51a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "3cb649ff0affddd28f8712afac09b7f02ff8186baffcc598c259ab066d164462" . + "d9837232cb4cae019480478485d2bc52b727f343b3720db48238c3ae17892f2d" . + "ecb3dc289a6484bc80838a4e055fc9aeed6c07f2de6e211166c76afea8367a01" . + "d3fd9970cda7c207c3259ad9dd79deb8477d978fdb8d3f76bc39cf3975fd2be7" . + "7e4cbfaa36e490070f604dfe0d04c91ff0dabc2927f95014e82b72d26e864aa0" . + "8c9c6f718ed5d45802d0f16c196dfdb1136a56fd1e550047db2b44cdd6e668fe" . + "756a5d215d298ed43998bb009945589e542f729d5cc1f36c8a29797f3d5539c1" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "d0c999bc8bce95a39e0d08383dc637293847f132d32986cf8aadea43c994cf2e" . + "3c28df4a8a89380dd5ac1744cdaf55cddcebbf33f221d0afe19f8f378461af59" . + "02ea44880b5d374cd42c3272bcb1afca4ad820af6e66eb7e1f658b6a00beae70" . + "c21070837b6bcd5502fda098fc63a6552b264136f3646987485a8195aa5fe5ed" . + "c59395bc37d13a362980607485636e04ed6836724464282308b12686b992d31e" . + "24a24e8dc6ffc11801f26607285ca96b45da332962b666dff2d2809500a4cbde" . + "b2735609ccf41f8dbffb17dc67a5668f2fca9a8710995ac56be819532ca791cd" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40ff528e36e82ffa469827aee9a0e5b0e78435edb428b028f8eeb5fe3055ef4c" . + "40ff528e36e82ffa469827aee9a0e5b0e78435edb428b028f8eeb5fe3055ef4c" . + "499c8057f09c93b8df4461f5e71bbee28cb6e8fda8fabdb012ca17589eb03528" . + "5c04e6961ce7d16adaddbbf57791488d577c706dac8e9a56d4bf30703b2b8045" . + "f3c91d61137bd2a81cf2bb0a3c3c351511a7be99238844fbfe466e43286ee380" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "2b872e5929f29aa7cc6ba9ec587e168f00a50cfe5fea5e7c01a4ecff849f6398" . + "7a4a3e1577ffcfdb8fb49820f3a4879416fe5bc24539783779c17483618cc378" . + "1ce9d5e58b95ae74201947c2b673800463abf0a97674fff116c2d6e4fc5b81ae" . + "1a9583a49bbe218a3f68978e8ee0b82182d85d161b612e3332fb50daece73732" . + "75ca892b3b1d787fcf7df123953d24e9fe94e716982914bd253fdaae9b0471bd" . + "cc4f0beacedef8c75482104c1be74bc34f8f730d9eaf64334490874ecc063ba9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "fd6d35a37bfc8482dfe774441c31820666098f88095ec76c7374e3dc40eb6e3e" . + "1a4a8842d5103046caf02f8661fe57a759d8fcf9fc564b547f0a5f0186be5e39" . + "6b6dfae3363f400c4a9125578d24d656984598b1e858a37553a843961b5783a6" . + "11c3488ac28f33cfef70a51911b2e7d46523f34165eab37cc46a0831a567a6c1" . + "0a170c8804ba233d5d31d7af2f26e8abcc20639dbb057d1affcd0dca1ca0ec73" . + "686c46ffb7cdddeb8b70838062cb9a4fae514ae1bd7da7c040f0abcd87f124bd" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5ca28a6fd0ea7ad1b8c58c65547141ec779397cd3e5df21892dd8652376aebd1" . + "03acfaf1ba0722f944e866c31d243cde23fdd4389498f24ab5e3f1ebbe954a2a" . + "e358391d50d6fe499c4ae3aac8faa6866733af57025cf4ed4c9210e0718ef6fc" . + "2deb576446f2f6fb9e4b4b2217b1cffbc103b76027c50cb66d14dec1c3098efe" . + "385e9020c80e7ecb4a4022b0987e39f4a0ff4f8ce53d52de917a9cd3516ad5e0" . + "7f0329bbfa3609daca2112d871af7cda7005daf2c42219e9e3413ef6bc378292" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a05e4232cc32974b9c36cfca9a91cc1589a2841c84e9180138a99a74d9787e3d" . + "a05e4232cc32974b9c36cfca9a91cc1589a2841c84e9180138a99a74d9787e3d" . + "f52f11e362c58f12034995350834eee24070c22fce7b17998718b2211799b7ba" . + "84188ad90dc5a4f9bc07e5ea2d942a4a56a8814535079726ac7653ab96d03ae5" . + "d9c2c0b0cfbbac3d803ea7173ddee50e5d569972bf1c293a6259de49a1da63e4" . + "f8c12b914548ea9248c157fe2c228c81870f22f90d852f06864e7c7a3691a9ee" . + "dd79f0ec1af87e40e488691a5fe1c37505c4469adeefde8cebda9dabf5314ab8" . + "574080f921e429b7113fc5666e177caad683b1183a604ce2c11b05b631907b46" . + "9ece9ca021b9a96141eebac77df62a8954dbce7646056c108e596ee9e5b2f29a" . + "edfa14b88a2f2b9a0689ac206f2f07d9857da47adfbccc52db94a8118288f2de" . + "6c64869023312f201d909239cf0693b3625d5850bc3cc7fbb0fc04f77b5a8334" . + "8fa3d10861089886326c9a207f999ae455f3f7690cdcb6e2e1c580b3fa745eb2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "e8ef66c8efb2cfb9445f3c08fc44f652b939bb66a36a70088bf6886924344be4" . + "d3793b661bc6131c09fd908af0b615d92424074e6e05c18748026f78b88cd864" . + "4f54e10bdda5c31f9477850db4307b9b1e7a6f3b6faeada5acced56592fb20b8" . + "95dc3c91a788690333a73da451e04515ec924a8697d8fe82c5d600407a2f269a" . + "209ebed3c0e76cfde788ef85fd3bc2a024019b9e99badd1c14a797568e950220" . + "6c6c95dd37c2c7b69642839baea4bd273f650cb9570ab80ea41e861b67523423" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "c2a946d3f6a9315493121782015c2b8ce8d29aa291b034915bcf8c67fa405beb" . + "0073367a42b932cdc982fd28d1fd68b2a9238ce7dc6fc7885f7f01bcc3844b1d" . + "8f2ef4fb443655b83276917d5d5130fabddaa12384738e5415f7279ee9211086" . + "8783d709117481baeedbaf377bc7fa0de3d3d707ee415ddb9b345d603176b96c" . + . + "fa42d2c33b5fc111d447da25c352e17ace4edc9b7976109de872e04115b8d7a7" . + "9c2917be6e082f04901de768358a0f4a1dbf4a7db4103f1fd2f32ec927ff2956" . + "84d822ffc6dfa2565c5bb73f10ae681fe525d5ba34baac057403fa204b0aab0d" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "416f2ef1a33b54ddcff19986713a0fe201fb9781697990e2e09217829f77edfd" . + "ef994bb60949976ea0261659b2f818e88318a89185df83b405504f760c3d4bb7" . + "a0e54b4cc555240a42ae8c2fd5f9b1bca22cf16fb667ca881fd4400efcf94f21" . + "6134678af73052f7365a550b75cfb3af4925213a472b933ee2967c7bc36c47fe" . + "1aa9954c2b484249ded1eb208727e0ce15e429f47b53e80a22d84d81060895ad" . + "e80b3307f6cbbfbbd70510d87e331aa87a0596fa0d714ff00ad97977446df373" . + "b750671aa3af57fe493337d681a11b1a528ace8db4689f65635eb467e30a4e88" . + "251f18e0da44d22c80b632e0c2004117ee7e17dac4626ada3b86469b7db56334" . + "ad963ef307b90ededf12e3217606bd88a7c3a56df01cd0d8d1ed17883ecd9fac" . + "019a8ef2256f5a03e8ea1271b16c7363e5ababec083b36062cdee4dc972ad7b6" . + "07e3562a950ba9e8fb75a5b33f73a05065c6dc81e4d138a8c9901bafe7e48999" . + "4b68aaf877d216e2c6f81075c485ee36ab40f099ed768dc8b16d5599ccf636b8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "a17dd3b3bb1c5fb903379e65ff9563df4757720a56d4714cec802b0b9b7f8237" . + "83ac0ee613a9750f47ede123480e8046b3ee2f938f308c6a5a5e6347726cbf72" . + "2d119a58486c7ef168b7d7d8af06189a2ee08ffd3e71549bba7a0f09cdea478b" . + "ccdee21d340b84cfd3d0ab818dfc4f955d459336db57d1ba3b451e1ecf5b6d69" . + "cb2215f9679289f58b8ab3114d4d36e4fda04d5486fa8adf18c308f77d960c1b" . + "0533b7bac8d02e10be1a8e2e1bd8e845f76f3e485c81874ee0cf236ab5502813" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "1b183529e63d3f67bfdd9ddef189760c0e7cc81613159159be72a03d5daf3ec1" . + "371e763b4982e814ffcc1d68645e25f5e1f569ea08400ae5d3ec8fe0bd3fad8a" . + "0f94ce473060e7c5503d6bc14495551118663605be875c111b20ae9f9a3080b9" . + "0940ba20f1e6799bf584fa8b5b6e897d93a5671549f68916666b98af03fc686f" . + "68bf6510e9cfa789154b8835e7cef857b701ab3d3c9457662b7740107a358f36" . + "a70dd05a9228d821b193ea90cf00ad7058693e0c7617bc8ed9579789b0f45084" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eb626712e8bba64d6788387589ff946fdf0037f7e488d6ad8de5a92695cec7fa" . + "eb626712e8bba64d6788387589ff946fdf0037f7e488d6ad8de5a92695cec7fa" . + "d9200fc9b4a142d8a1a3024726c43d4ad4077b8501703156c5c45c27e4d824ce" . + "85a1b36beb7a754844dad449f3c8ff933ce22c08a5ddc02e1c4e936ef29594af" . + "eb062e37cbe09e5e8f9eaab4998ad48398b4a2868c67f8eb84688b42e56da69a" . + "a42fdc79fd47bfa651e99dd36c56fc9990eb75c943b5b40b5e0b19b7c9c43503" . + "d681a8e0c5ffdb30e81e231c11c7a98f25c544ea85649864184929134d076c97" . + "9fb3d6f8fadf140c68f4ca62c5e33f2485f31a32ccf31de85b67d6aeaf4893d7" . + "07e3562a950ba9e8fb75a5b33f73a05065c6dc81e4d138a8c9901bafe7e48999" . + "e8997550aada3a9c98815bcea3c7f93086900b29dde5a736e544152dbbe19047" . + "bcee9f30270de6a056ef801e03d37cec2158e0c94a7a7781cd19e4a38397bdad" . + "9e34432c9efa34a3bc4a5d90bc1f158fa36cb980bbadf082a5cdfda6515af086" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "e265ac36ef815689e05916980107dc29cd61fccc3fa34c690898e343dd23759c" . + "ed8c5b915bae9f890b64a3980ab5a34ab30f60503ca413c02ce126646ed82c4c" . + "f05e384966b70426b5dcdc34a983caaae09029455c4e56c67a919cd51a2897e8" . + "2de163dacc0d7926eb8b581dd954880a4f5fec617ec1aba5099dec4792186927" . + "a259b009d3c662cb93e09d8beac71c9fde16db77c77a5d2e58c3fc258367fce7" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "5a0037338e9c89eb6ad925ea80522f1c27637c60055f9781548b02c1565abe26" . + "46d194d62e46b98b9b60cb13cb80a7650291ea72a8c18152922b273472f6a875" . + "5405bb419b1b7b154ec742af8acf48a40c7ddb4aef17141c114e8f6643efc41c" . + "510de2643ed4c29dffa850e8da158a9f347e4a9dbf0d1c7127796a82b510edd5" . + "6a9f25870dd4b28427ce4c8ee376344d176cb59549232380a62ae960e94a8bd8" . + "19cc6be97bab0a4f7836711fbcd64103c2b343d095f6fa19a8d35292654b0be0" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bdbbc22d850c78c87120a75bc1542ef31316a4194177713819838709b8c08a7f" . + "bdbbc22d850c78c87120a75bc1542ef31316a4194177713819838709b8c08a7f" . + "60632feda92f6f3d2143d9c6be7eb0bd1d4b9ce7fd9fff2d333b3204dc925440" . + "6133f834b52e188436d220a4cb17f8562e04eb020799dc43ed5906f55ac7df77" . + "ef5c0e6228996520761247444be00ece85feddb790ba4966ed6883dfca7c8f6f" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "c38724a96b524d0f1339d84ba1097955047ca1411b849675094ee5b871a3103b" . + "363525b27f909e85034ff4b4345e0486be1471a8af1b13ffbf996be6acf4c7de" . + "f2ec94679300dc78b69ddd2351a74d26187fdc8869747b3aae68a4754f7ec4ab" . + "0d104984c64acea54b09c650f50967efc8398f66f79dd56d4ba7f77f75b86d3b" . + "20a5165b15244386e59c81488f9c6be17834b813ba4d74d3536b70ede7a950ab" . + "dca31cbdd91d7a8066d308335562fa8f007d251451c566cfc93748bddb932b54" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c12ad3bbeae794e523a237ae16a1380cb28284ecd843614e3c598685387c538e" . + "296be7ba8f1f685c1125e9051bb41285be90304d65f9a522c32ec9b87fccec59" . + "07a9b8a69302b48c0215f813c7c0347f518b87922cd6b458cd14ca12325ef403" . + "b2bf0f75d299869fa7e2f4ca7cd05770b24e4d55b206625fdf69cb4ad42e3db5" . + "d3fd9970cda7c207c3259ad9dd79deb8477d978fdb8d3f76bc39cf3975fd2be7" . + "756a5d215d298ed43998bb009945589e542f729d5cc1f36c8a29797f3d5539c1" . + "d0e6e7cea34a53e9639c96ec2f91b5219f134ff494033bf3e4f813ed65214e3c" . + "7a1af29cbc0ddcb3019be131286375596b6d773df2fab0bc0f433565ee3e0916" . + "b33f6ada91e8f66501b2203214e7f40c5ee678a56388dd3a603c79d132d33bc0" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "039321b5a22b4b221dc132c316026dce56d5ef4d8a0bdc91baf298b08a08a44d" . + "74eb9ac696d9b39dddb958299e9508af1d4957137a1cb846c16195694dfae6df" . + "4b8af33ffaef6fd60642ad32e0b38edb8384283f60d27a5f4f9c33d1adf8f154" . + "ca8f7d0adf9d18f592ee2cc92f8086b2a6c47ac576575d50485acc8ba183e6e5" . + "e0f0c00da4c54919e34250d22c7fcad8333a579ce5f1062045db7203865615cd" . + "8431703a70f9bae85afa9e2077b63a0cb2a1d647bf1ff8f3bc7a6cec68f5d2c5" . + "af6396f511f79937c93a44287806c3bfe2796ac0b19b1a8fdaacd4c9fd01e4d7" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2f09181d178c66df63340ca01981bf950d2ec154ef3d9ac4a1a5031b96ff3afb" . + "2f09181d178c66df63340ca01981bf950d2ec154ef3d9ac4a1a5031b96ff3afb" . + "97775b8aac4392b035246c9aade69cde5ed951e87076e6b54a6630e60c408298" . + "3cd426f301f2fe1fa65794b2019e1d5640200b6127d5e332282fde5acdeb3850" . + "460fb6551c9ab63ee96eb61da72357afb9ed44111700fb70d7dd6f7e5c2a8d17" . + "0c968d4a9a3c701e90146a136656e1d3586041fc61eb5a12088e4bdb191d7a04" . + "67b16614db4bafdc1a4ec0f8cb40c2efa3de0d3ab62be1622c87d95a2b3d3ad3" . + "2a80be8a59b0465c939b48807dea6a1cabca184bf2e501293b8f2c3177bf4aa2" . + "d27860a4731b39e39368b4f22f8db7ada9f3f6357778b7738f23c8611b553942" . + "d118597330e0c1b444aa158d109599ddb7799404bc77ac5e2564b335a8170382" . + "9ca6faa79ecf978dc628b7391272f53bc1b2e21a662fb96782386b92180b9845" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "e07237800f5e69e831ea288530b165ebf026919af837ec92ce017c0698a8face" . + "9939433b6462b6d12451927966ebea8a947bc8049d43442c9ad06e341b06cd11" . + "c686d23a81c67a11fcef316387e11d731c69ad49e4a25d1b9913c33b5c536f72" . + "c092aa541f96653237d145a64d790b2d7ab1da8fd16c5111eda57b03c39fd5d0" . + "aa140d408bfffc1463880acdee0ccd64e0b715be3fb46134b80e22cb0b024855" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "9a449a6cf068e5bf07c688147c0546f12a47ed9bbbcf5cefea89d417c727ca7d" . + "d86c4690a9998f014e35adfc3011df0a42cc1d109442eac379364e25caea5fb0" . + "d20da41cc3ae14561ab7833d6d0b0e98f24410c7456f86a1fcd7993e60313567" . + "58dda1a90f1969937f69bcf6a06391fb2d7253744f35efceb609a1b16c54696e" . + "79df2520ab4b953f59a435fe9d8242fb16f0dcdac4a5627727c7509e20f9f125" . + "9a62bc1d07cc401834c629ae8299c7b87dd1fd8c5dfc2105de79717e6d3cd14d" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "994ab62060d9b97c7a010339f7a5fabf89001bed1d112b3b4e2bf1356e66b10f" . + "994ab62060d9b97c7a010339f7a5fabf89001bed1d112b3b4e2bf1356e66b10f" . + "bee65927f811aa9e35905a04ead45cfed9ad59a2e50a50b340d62a04a6647c64" . + "efe5041e892d1e0496b65e224278516ad53586d50bd8a58d864b2951e4690e92" . + "12464b7acf06d428ba8025ebc6ddc2acdf4c9e8aab06e1f974aa2b38f09e575c" . + "1551a792281b45984ef6344c823f5ecd6cb3e7356747cb9ce8cb9de7bcbe9c9e" . + "e15c489c90449582e238f8ebc620bb0f32bbad30dc3105283fa739b5d12c1ede" . + "58cf889a8be070044e8f9f6636132f9c90e1bd3cac1043b1367d71d027f358dd" . + "d624fd890ee9b0d7499ac2c6c3c52b7eae5ba3df3c5f4529a2ed2a7c3bb316ab" . + "17bf713647848f0aa8c1428e64bc758b93594062c5acf2aaf699a7ac0c9a3de5" . + "07059eed3607b3199c61fb9e0745ff0e31152235e1724aa319f0c878a410ed16" . + "00557b47681f9463bba18a6b54293d42055564442ca1dbd37ee330091218cce8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "dc5f47b8d9b804d3b680e78067a8bcf9665e30d90fab2608c2e78ebe80d3077f" . + "07a9b8a69302b48c0215f813c7c0347f518b87922cd6b458cd14ca12325ef403" . + "ce9a82839d852a6f67329788a36a61bbc18a31f0c3d81d96251d5e6c321eaf43" . + "6e340c3b3d9065f27a7c3f73656b6c799dc2c5835dcace453145c9e338d93983" . + "cd25321611ca4ef465a5f03332c84d45cf334df8bda3583aa93c6058ed8d69fc" . + "f5e560f7ab5200e975f6d9d96e108c78a9e822129b02bf3af24e25eefad31485" . + "fa8a763d236ede2bfa23c7d6ff640f59756372e392cd7185afd22392e5d21b88" . + "96d82f776bc8e4315ebb95a1346c522f718a96af89a62db79539447eed16aa9f" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "7be5e813abd335e29d00654f2232496510892a2a398f4ed8e4ddb011c4ff8d8b" . + "5440de2eccb092fcf25bc65f98ab1d5bb291682feacf0836d4c41feb4fdfa12d" . + "fb5c03d77e424d7d7bbe0e5015e06c072c87fd63c114e96c13f7850b83c1b7db" . + "fb1b5cab74443d4f4f726aadbf0fb19d8150245d41f0ebaa040cc0dcd4e2ab83" . + "7be5e813abd335e29d00654f2232496510892a2a398f4ed8e4ddb011c4ff8d8b" . + "5d7eac4bb098accd3e994c6c23f6b82d5f44e773c99ce1f59ac076ca35c9b4dd" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2f0f2ba125791ff1cd37e43903667ae316d5af6c9bc14c96569a0d2abbc58a71" . + "2f0f2ba125791ff1cd37e43903667ae316d5af6c9bc14c96569a0d2abbc58a71" . + "9b7475edbf42175f21be15a295af37b4aa86de9271579dc158ea05b6843bb5ee" . + "8de28eb81cca77be3398db48ec3918ba7216963b678e150cd96fb5b3443bbf03" . + "39a96edbb6cf64e3a80f3b36dac027165b5bedff13f947e64e3afad2d03bf372" . + "6fe91b2a6e365053aa3b9ceb3f6dbf7be3ef12872afdb710c590e012460683d6" . + "421e794d0df19eb5c58188f798727188e419709a584a8e419c2bded45b72483c" . + "e99e5c152d7eb688618d3940bd97f242ceed4aee16a07f994c4678718dca9901" . + "7682f8ac141f9bf134327bc80310a056d1f59f829af75cb463ed647ec34b279d" . + "088970f7b12d3ac2c9a8b46da7cb781faf8c4acc47af5e0e205fdba6e7d7b6ea" . + "b8163c76dd5f00856bf2f86f1b6dae6f52e9e4c296318b6ef0b767b0e23c3520" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "f7fe7145446941842a77185d85ae5634de806ae6b07751c63ef757463c4225e4" . + "265421e7900a93e4cab9ddfd6f135ed452805ab6e726e71f38579ec60128e70a" . + "c032f0654942240c2266bb0914765fb4b0011111eb77dbc1f6d4183540c5e7e2" . + "c3226989d3636d10f8ebe83a37183bbf18e8162786e518984e33daff10868dc4" . + "b1f1a436305b3eb3dbdff47660636b75dfd1b3bc974c564497c1366da3e3055f" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "f1143a7302b12975a18975eca030e0ef9fd2c3dd633418d36f4a8c939b4f080f" . + "ed92c0aba0b050f7e7bad1d8c7fe65190da7616a0c0335fac6f2bf614d1ce76e" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + "f1143a7302b12975a18975eca030e0ef9fd2c3dd633418d36f4a8c939b4f080f" . + "949eaccf7eadd905a5e8eec1b7c9b4a82303fb85eb594e1e842423d3995fbaf1" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "61a24b87e1e21fee9d30b5f2be425c0a38fae4d55db58997054943fab26708af" . + "61a24b87e1e21fee9d30b5f2be425c0a38fae4d55db58997054943fab26708af" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "76977e0fe037b3ab2e75b7e703b29e70d99b293f45fca9bdccaaab1d82a6f759" . + "31de642ced3f0464c9d7e8b33e2946c0d57c02a8ab29f9157b88cec5f825727a" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "d17837265b2850e6a491a0d52ffd2d630059c36ae454736a4520688ab3a135af" . + "d638d62f2a5e6c41919fa3cd99de10472563db3bc3738e1a7b228f89b3f0ee2e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "94c91af7c800e2668890dc4176d5adda33a2f66b8d8eb10acc70a3e86a2f269d" . + "054e1257d35d6be819c28068f5b4873d3d25414568f0b4c236295c952d5c885c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "3e4b5c0232f119a0cf51c7207e50ac91f2537adacd86ca48565a88d399e292bd" . + "cb142cb2e7880176fff440131951aaaef97e059f232a35eaf903d57da5123bae" . + "e0921e1910dbfe7c3c7bfa1ed4df3fc217a678177154bf2ba423c04f85dbedc3" . + "059c2515aa77742f1defef2e3ecf0c93a52cd6c5224377f0195b0e16faed7849" . + "6d226c4f5d515a8a26a4043ed6a1a0d6757a4ac6eb6734e92672b0895bd629c0" . + "0d4a1f22a573d69c97b7f9dcec4ea8b98f4e3cb1e5055b197f93d855e869ad66" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0af9142ae274187c15849d0221544a1b0e57a8f94bc0d08c4d3155888bd4fe91" . + "0af9142ae274187c15849d0221544a1b0e57a8f94bc0d08c4d3155888bd4fe91" . + "a2d86762e4a23157a160a52bedab0a5c9eb1ac2da82a31fd4d6fcdaaa24b2100" . + "2fa84ac8a33a5cd9a0ec137b877ce9d058986bdf990fb49535a4602272fbde69" . + "899fc5eae874640a8feeedd6016c139eafd57d5934a75ffcb6987bdcf515d588" . + . + "4c012832f6f5a24e83dafe3416116029e77d1185ce7ffa1335306c0e27ba1af2" . + "6c766bacceafea0bbead9fee7026270c93b9d741c3c56b4f87982e77586fedbd" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "82e7585995ee5f4e0b6e55400518bc8aeae4d67262ec8306fe59005b7419c8b0" . + "35cf94b47a0d566b36652c6feda0aaba605cd113d9a2e6b0318fa27981806afa" . + "b2f6f5412134f794ea20e74692083ac3fdf6cc28f9f94d8776565041681c2aa2" . + "c71584744d9d2ec58f1784e3410cab1e416d2fe3c35d0c4479420c715fe26887" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "ff5e8d7d28fda1842da3b98de0a6268cee09b84261e0a2561253aadbce80d396" . + "ff5e8d7d28fda1842da3b98de0a6268cee09b84261e0a2561253aadbce80d396" . + "5510853453ce4ee8907794273e7f3b624d7fc10cd5359112f8d4d89baeb2dfc3" . + "04e1a0828c6778c0313939a846e02aabd87cdd254b6de5e767e0e5a9ab6702ea" . + "470f30608aedcd1054ba5ed40ba5ecf1335d6daac7d6c33bb00f3fa0c2fbd179" . + "d05bede8f4c95ec204b3553408311c97a8ce6b8a198f9a112d0f78bf5f93a73b" . + "33c5dce09efaa4a158102cff7e77517ce0693857fcfd197ab39080df53874091" . + "5aebf67a37b7d53cfe63372246280ea70be3fddc9f31b4fa2f96fe47f23fde03" . + "2f57ec08c8cdc1bd4d93090bfad573e9a7092509a6bd2f1510f1c7a5677f2a16" . + "2ba1104cded90e74452b7df0937a7ea943c6d205ef7e00fee32ee313f9a48678" . + "8ec8ee13be7fcf1b79e20084874b82a6807de726d0850f91a85a71d1e8efaedb" . + "4c7df960679f8df24a50e7a165e510aab2404a6e34f822b4fa73d2db9fe12e60" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "bdb416fda2f51fd42623b1a1279baa9b291dd3d5212376154bd427cdfb6f81eb" . + "b0342923f536df4ad33ef5978d5687cce0adf6ca59cf3d9d5a3788173a4736ae" . + "7f555df77aeb6374ad2c802d5b6c978111e75d40c83127c890698ab88a01e78c" . + "a768bc21abab03c6d883494965fb316bc99dbba457caccc9dee8d5d6c0e9686f" . + "d6d789b81e8958c434b169a1bfb85a50647aa14a80e58095c358d0677d6fa6c5" . + "757dd30583cb4ebcc08210d2d06c7450a155774d50fbdb391da149260ad30dae" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "59a9e94d49b29a0a8218dcfe985e950a3d8acecf6c20e81da1bea3d8536320ae" . + "a1f9f3f734b7450487c27455d1c5adc754b39ba0d056fe8b0c70f0f8a3f52e4e" . + "db5bd8b2f44dc018fe83e5c9fa438c45a99db56ab1697c3c62e7206da5038c05" . + "53c162c4cb6200a5b2bd543833cd2229088dbbc48aaa7371003a7464c014eaaa" . + "ce9c633a8266b0770847bdab92ca1b97553a5ce29eca160ec0afabf0f783bd4c" . + "8def3c3be332a7b51bffc03b65d72ba0c363759acc637600dab93f2e52abf811" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8da37a18718b368480219ca26b800a889f297d37f6ac5af6afd0c7c840ac65dc" . + "8da37a18718b368480219ca26b800a889f297d37f6ac5af6afd0c7c840ac65dc" . + "c4751234d92292d9c50f7118fb008b479e3b82aa5c706195bf3fb3b0e0d8b32c" . + "cadfa71f20b99c44aaffe253fb90dd74f50ef6ef33bf5d82e219217e71c36fde" . + "99592d309cf936346a9c2fde3b9cacb1a63cbeef99f494b02584eb4447ad3364" . + "6cfef462ed0516f61eeda6e1d48cdb13f793228089f758eb131aa6ebee928499" . + "ae047901500bec3fa42ce9692052bd0eedfe5f3563fe87f26120a331296a73cb" . + "7de6b809934197d013e9883304515312741f8b2a268d26d606e022a51bb6f893" . + "1bf4dd142b4d41ffcb732dfa8515762dccf3f366e236b8bf948c4154c35ed49c" . + "d2f3d497274fb058bb8925fab1fbe6fd9e7b648cc7717a5148535bbd384dc7f8" . + "3c7bd073d2df3fe0daea43fc5f995cb90dc773fb300bc1a5841ecf6877b0d8a3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "773a410a0afd9901ef985e4dd0467341fc51587c4850df4a92eda009c6bbbcdf" . + "babfb8aa23909a7d780446bb0e3cc54867f806abf853ba33100fa51f9a3d4074" . + "459f1064aaad697692662035985475e1e25eb7977136ebfd1fab7060afc2e738" . + "8e2a27806739509ee23a4c3dbf0902d6c0bb01530dc2ab828c9d6ecef02d43ea" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "e2815de1e36778751481cff67a0dddcc76e0a9e7df256898dff2bf6058e31d6c" . + "bf9d69cb80f0e4bde1e3ddd3c5d5238dab832c379a33c7a2397883f170254ee4" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "f7dc335fb1c240552a68c0c37849b4ace3b71c715cec0f672e975a2f1d1aed50" . + "85c161464ea1253533ce80af104aa8cc50f0e39ec86af2f695a4a38ce0f6e353" . + "5ff0c21ba6723a875cc99d2f267d0c1e7ee56e660659082339b6cab39d71e749" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "f4b8d52835da0875de2e6158072229677e48b11a4946368414f3fc28c6374b23" . + "e0b6592570da8ec249955091a638701e1f26c07af1323b5ef6ab86c919abb836" . + "2023b409ba772e7ce1db3a2322ca3edc4c3a47ee6f4d022bc2fe957e324d216b" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "368e2c80e507f26648c1284c9335e9992a7029defd321b958dbee72e688f6b36" . + "368e2c80e507f26648c1284c9335e9992a7029defd321b958dbee72e688f6b36" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "6eb372a4a6c63f014c8649826cb4c051e35542a7656841e8c2bf8e9a08d8e017" . + "9d7fabc95137b82bd50c8e704aff096566214948d99bd5e9c3421ddf769ca21b" . + "be78601642048a889d461b77a7dbf180682a91ed452f7863033a46e2ab61842f" . + "50aaa49f6811417108ed7c711a77c890140aabce6f8a8a0df2f99c9986817296" . + "db1b090c8fe6dba7aaf4d62165a1341a13c6fbfc3bc9353690abb17d5b769790" . + "23669f174d232fc3b059b257d9724bca41b4bdb711146938c79f94954478fcfe" . + "2a02d7ecde3bca1f1f4d48122897c8bc9ee2e2757f59d95127cb5247deb7b9cb" . + "4bd62ae87c34abe932ffba1dd6fa3f4334a12570a6adf5b0ce0922e69cf4c737" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "983218c947937fe596a35b5e27cfe821c7ee66039fb597ce58dccd332d3f2617" . + "742059262f6126714dbbdf5589008204993da0351135817bae7662eaa37f633b" . + "71eaf5735c35beb1affefe23c2036aaf9e16d3513d9f4e4e16128ab329330e39" . + "86f8031836eaf898822506d2641a8755a79b1868135f2afce7e43974abf27b3f" . + "94abe2cf2ed0c2af24397799adc0ed9970128848c78c3ebc83eb0333b562616b" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "ba519d38f163da3f0fc9f98d2fa78e4dbc497e789145d40166c2d74a2caf4bd8" . + "b492a9c3d7e6ce910ca0a2f7c43336cad4549fe75507dc83ff33a9d8ab61606d" . + "fcbed72acfd853d8df61064a2e72bc4a5364058a7e56b0529baa455e78c86ded" . + "1fa4ff1989a6008ac80753f58b8efdf7df1243bdf46343a097c07181030d5f1a" . + "877b08fbf22857712dbffcf12b1cefdf14309eb39fd37b0ac37124eb188e056d" . + "d9cad7b0b7f0c6d1d02b47fecf0fb332baf6fd8ca141b9cdae53b2e3b8385de0" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d12482604083405fac290075ce48c8ee020b49e1039a8c472195c125485f6329" . + "d12482604083405fac290075ce48c8ee020b49e1039a8c472195c125485f6329" . + "a7b0927aae4eb4116815293513f9aa92b841a4a517167e06474042a16898f3c3" . + "f730728f6d2d78558251f94e872922f7114aecf479a5dce6af4dcef1cb437e17" . + "22244807b36c825b54ee8a3f86fc818709c496f25d314eebe40610cb78cc2119" . + "9ed7f5e9145da575956cba405066a6764af438e0b336404090e2fe68b420e526" . + "d7a6e33f63eef1525ecd1612857049b921859a139849af661ed69e0a399d310c" . + "5c812fe87134ffd8d91969fc3470bbb0ad7b163c651af6f44a17ac214ea04e86" . + "755f339ecfd97c5249e03f382857186a53e2bb59770e7ba4723ce91a26719c7a" . + "065d37ae664fd3f5ea43fc8dae52e68508eb778042f68c1afe687102a2382d5b" . + "3913d805c8b1a6fc46df6a19161297ef30334b963e403d38c2f6685dabb88458" . + "5e6ae46e84cac4fd616c61fd65e4426bd40c6a5496482cb58c55bc1625e31c1f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "aa2f2d951082fa39c07fde899dc4a812e41771db0b26a46328dd9e98041a1ec5" . + "cb44352da8077fd3dd65e413930181d6a85c1a315f433520b66cd40b14630ecf" . + "1ad4721d84110cd1f18f34a4dc713c589c828051583a56f8928e9d00996fca27" . + "30c048cfe37a0a21b8d22a0f74cfe9a694e8dd39f40080eece350efd50e47bf6" . + "f33bd83ebe99cad1bc4218dcf8f4816231c36d73d8fe3d63d1d393f41abc4ff5" . + "df40a28b9490689dff5ecc8865cb8a149159d8f1fd813cfa60155034a955e215" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "43ac50da626d8e339e1305c77f7ed171b06837f13416defff232b470f38b0943" . + "92341dff6dd642674329b7d9e66f9b71e58e9b87dc95a9e399da2ee569776260" . + "b9d03f3bf75e831568b312843f65e1d8de2416e74ac1a9264caeac578969557b" . + "537ff9a6c545f03864fff7b3e2a835b9fad9bd0c2049e28f977050755d4b7474" . + "43ac50da626d8e339e1305c77f7ed171b06837f13416defff232b470f38b0943" . + "6604c73442278171b7fc62d39f2521c8180b90abd60508c71cd7a5022ad62856" . + "fe182069747887cd77cf5209b72a59226bbe9de2e0d9ad570cb98f351d0a100b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2223d57c162b512197ddc691996f7c055bece2b6d4be69311f7883ef128e9402" . + "2223d57c162b512197ddc691996f7c055bece2b6d4be69311f7883ef128e9402" . + "7fcb06ba62f119186cfe2c543258756aa83881f80a45ecf79364197f265568ea" . + "35ce1549aceb2814e407a761f3db06b0d05d3c0474e299283c6bd342207fc026" . + "642c7ca18dc4493e04c10faa742822a4d3e9eaf160ea9c579e7abadc0934da74" . + "05100d9f06065c22ef6c27dd0542143e528eac7dfd9d91405f013a35e951bb9a" . + "b626dcdf1454faff1bdd2f1198a451e2269a3a8f512c7d7d96739f1df3939c87" . + "f632471ed0f9dec376087c16f02dd8397eacb752bd6756b667daa35084650a6f" . + "1d7a5db80daea3e51a7304b85e69007b7c96673c086a9a5166fff96cb93fa93e" . + "a76c8ad4734a326e3d13a042745ff57632820ef5c05d3e163d37fe170fcc36fb" . + "ea0fdd53e44f89508a890e2cec3149d176b51c56586e0f910d5cec38e2518939" . + "a3dcc809d06543d299a257bbab34dc38c87a0aa807d2f9ccf3e4c1ec83c71339" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "8f9851496f4049af5d6f0c90d1f4713e0ae7ccd0b1b443f56d1ef7e8c76adbd9" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "c12ad3bbeae794e523a237ae16a1380cb28284ecd843614e3c598685387c538e" . + "dc5f47b8d9b804d3b680e78067a8bcf9665e30d90fab2608c2e78ebe80d3077f" . + "6394dec0fcbb026931c8d194155360393f97622918093c818c4af904d3912f0f" . + "5d1d6dda8d6dcac22c3d6b815bc1cd0feecf14809c0626fb4bc5489cf5ec0744" . + "cd6b385bdc0a4cee3ab0cd1e2aa129c1ba4e7422c0f7da447e1c34e65f103e98" . + "e438085f2b87e6adddf87481bd205a5b9957b1d7c9436dcb656525882a329336" . + "dd4aa40c746de338be0e77dcb638fb41f0ecc7193d434b8d7fd4615f33e10682" . + "0e03528663c794072f7d46fc150290f5e32d21874623ae9312fb497c5211471c" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "c23f8c6541519dc61993e457052b50597a34575c5d2ecb6eacf32a182aad10e6" . + "b50262de32d5670d0b3ae709e55e73fb5417d53398d8da571a689bbdb13bd074" . + "daae11b527580d218f60bee2692b82b31e9e34175116404b2e749e123cf750f1" . + "d9442ae2eed5cd10652fa55ab0ec21a8528b1365033e719b95782f7695d0122e" . + "17b100ad70f9a57046eb92cdc778c638d838978c013223cfbd4f502ed7addc94" . + "5174c1c966616a3268660d070f52f7e41081617b2658b86c7b5c56160fb52a95" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a6f0ac82fdcd7763495513d2101e51b050c2e97ed1a0834bcabdba3df1a4fb73" . + "a6f0ac82fdcd7763495513d2101e51b050c2e97ed1a0834bcabdba3df1a4fb73" . + "3a83a993a41ec8d2471a0c4895ab5d2c3f778775a3c105b72977642213da024f" . + "5c7610684c52e9dae422b28191b4c09cde41a17a605cddf7febdb54bcd19305e" . + "7ff7e6a5b8b35c348a7dd38cbc4d2aff8753c1748cd7dbec4d69a0476c1e8f98" . + "315af2c06329a9e6ab43ef870074de29db3df30b5198ba1e28c54e34db080bf3" . + "5b509a19c23b83219a2806b8a6bf591b10773df4456dcf292d6177f12b71d0df" . + "abee27f96dc12c885681c91ad406015e463df68596e49790b263dd53f54f13dd" . + "0045bd94dfd1509e9c2012faf1b187312972dfc4b50247a3fd7042e235b0f969" . + "f9f62f0aaf889d1627a67ecd82bfbe1ca9bbbf1d8fc77ad0c19e926d8cf393b1" . + "98c90fb8e17238dd1cd14fd8bb6a02f4fac1d8cb550d7efc288bf0bc6965a777" . + "5406fc83a8875d5e5a13217e2e7d9444c3f9c16cca7c451a5b82100232b14277" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "90137e5b78921536e9d3fa0f84b831bd861fdd4ad1e53de3e4e93a73bf426b87" . + "e728de1da24d7f6eae2c25f2d6111e8c08b4b1a9ba3a863bc2b511220793c92a" . + "c0c0d90e68a8b2374b1ab0e20650ce2c8134f8c460e69886ae7f4d3d983d0522" . + "0523b5358b33ccf61f9c922fc29f4e2f9c36b3d30733f1f84c1beac0d9e3b68d" . + "db8b32f2b30a4119038ab3f580880c980b47a4f21b8067cadff8e00cc5c4189a" . + "f9a9e8f9d57ac53e0647a0944a34b8e073f9327dad40f49bc8652cd3df664831" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "7607ca48c4fbe487b302d10b263fa3ae392cd65ef866343ffba1b749a3d3629b" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "f74bb041507206fd35d3a7df319af66fceed97702447d3131fa1267f087b592e" . + "fc87095ffd7a360e11df03ad7e7e5ab789dc659e3ff90f18ea0590ffeb53039b" . + "8914de49803f392acb8ac3889aa104d8fd7cdfee42230086559288b52a902dde" . + "ffcba3dcb170d703a639b443dcc3d98cf25c923f1728bc29b72be012c402c080" . + "591075bd64a5d22bb8080d2956198f3385776a1f1593f65661771dbbf84fd8bd" . + "f7d33d14b2bfc72f7f747a0bfde354341b3f05006456855774fdf3cb4cfd8ac6" . + "f6ad7bd420bad52c1df63fecc5f77c4d4934fedd553e519e1aa26fbcc10adfff" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0aaff3b084f01f784115780b5b53dae532c8b87a1b70764152b0ac799fe9c0d6" . + "0aaff3b084f01f784115780b5b53dae532c8b87a1b70764152b0ac799fe9c0d6" . + "04d993af240b4dc367435a24367f9f76aae22a58b42bcf26478e9480d27b8a53" . + "c5bb301bc2375d049e1fc985d0e7f9faff880e627b818ae5f8848c88f05d6360" . + "472df458dd6b1ceebfdfeecca50ba3b00d4d428538488a65372098846db0bcaa" . + "ddf08399bc178f19002360fc13f35c66457f468b9b9b84e9482ec369bc9b2244" . + "a4df6e0d3f858528a19b1b172b851a6b3dd7868346713609afca4cbc65c142e7" . + "85db53262e09052d4dd1e6669415806ca48af7b0a9a34e9014fb541126ba262d" . + "fe9f82abe055ca6f714599342c69e418c361b2a7ff091aa78f5b6e662ac6bbf7" . + "3d688b193fb8968e15ffac39fd5b4a43b5ee58f3bf79a41e57f18f8e38e1f5ca" . + "2a0f98d712975b605cfc16b1bcf549a8589242fd3e88828422a41556da0ec300" . + "aa02e825d37a1efa8362a1760ca5aeb0552610de59063dab50edff55a629a523" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "37113b7bb4df93411fad5cb749d3edd0cc60fd88798a6c78433b37ee2f84c0a0" . + "6a75535cd71b221c17919d569c308dd1b6e107676b22f995e5729a4f4147e491" . + "bf0c74a525f3b24fb3029afd8c7f54ec5f710fff63344e7cc8e9a3e43a366bc6" . + "75de7c0b267c98673c03a17cd5a4eef32fff44b3f7b053b54cad549b52ac0f9a" . + "52f48ee05352e3201c1684ef041d2c53bf947d0368744531807ad4ebd06107a7" . + "cbc4d06cc698c168e151b5bc830005abfbfbc9d5b4b67329e9f7d7a52c41ef0b" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "8448260c83b5b083b6cb4f85ec13b882a6f5deec5ab7628ff6e16dfde43e0bea" . + "0963c0b9ab686295f00b9bcf58f36152d689ea3c75436c91323d4954cd98531d" . + "e1a802544645beb87c65df7631117e1710ce398e34baee51e7c347cc560044e7" . + "9cdc0c0ac68a154f1fabb593bd636c50447606b005696815ba856c0d57316f69" . + . + "3795736a9d071ab7a60281d1d6d3553636cd9312df9e5b6e61b08f65f173b38d" . + "f9ec8b79327ad8faaac9287ddcbefb74c4772ff3313925f5242fb085df5c8a63" . + "8514101ff6d04c27888ddb2c90e72033c3256e0332303783ffc386331138fecc" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "32d63120d83562a5e80a6f4f604cbb2e879db2d43d097d174c4557ef6917edd4" . + "32d63120d83562a5e80a6f4f604cbb2e879db2d43d097d174c4557ef6917edd4" . + "7f8457c5c376eb51651850ec09503ca5e063385a216776e3bbaf86b1a3a4153c" . + "9d88bc5e1b4b92c95f4e1eec72e469f8d9b7fef015c815de58a40736c513b129" . + "83cc40d2d5b85776c80346d45a5d099ae3ab5512b22fc8eb06bd95cf66ccdb19" . + "472656345618dcd71d2c5bbf4f72a3415b61e8bc879e0992461bfefa4632f52f" . + "9528014bc2c8cc2e0657ba10657f517994c168b6593f75615390526dd04e59e6" . + "9b21153355e1df42cf74558bc75b6c0ed3aac227180a7299bf161f07ab652667" . + "ffe81c50a87075851740513026b1bbe317e36ef4a95d83a67946e0df720fb832" . + "81e1c2583b57aeb6c1bf61aa6606ad14d101fd12ec3d0c2781cc9441e75116ec" . + "ac9554a7bc791d27d211ec44edf2f07a96524ee0406463c18014090fa169facd" . + "9c66fa6c1c8b99b83a67ed8346383252b134d2e7961b82acd88a9766f1a78ed6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c12ad3bbeae794e523a237ae16a1380cb28284ecd843614e3c598685387c538e" . + "c1e108fd07a7bfeaea3daa948909a1e0752cb5d8f52d4a52cef731eeac583ed7" . + "00d3df5105484cf78dbfdc5d5a730accd976de53e2e7a3e236bac2117e301de6" . + "db2d244bc90c6df8a094083992438802760d6a51266f099293158d0233f0f032" . + "983218c947937fe596a35b5e27cfe821c7ee66039fb597ce58dccd332d3f2617" . + "756a5d215d298ed43998bb009945589e542f729d5cc1f36c8a29797f3d5539c1" . + "106f91bf999769b858a1fcd695e0cd8921353493c67c2485aa024d921b610ce8" . + "4dffff6d1c9e4d7c809e32e7ed941003da0b465aadd1215bc9ef9a692df91f73" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "0c2f198ad7a1f7397e69b23c9117d5062179e1f46fa8d6cd1e141166495d845a" . + "835b4ea543cb338a0f5cf4d4a0a17ca15da048a21a8d0ffccb677be5f15ce263" . + "e3c43683d8ffb5e2817327ffae2549bea0aea0f2474f2c2865d35f50a2e2504c" . + "8444184bd1c3cfbbdfc38c73b7864f334b4a873c8a537c657935e3338949dfc9" . + "a7d0ff5059a126e1abdfd04a6ff43abc0a23c8db45e630830562ec843b8f7fae" . + "4f72b5aa7b4a42787402128f018d5e175f9c49e2a6ff48277f021860a7eae38a" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "066d837fcb1b029061bfd5d992aa6b833088cb2b14ad870946b2d0e3f8a6f380" . + "066d837fcb1b029061bfd5d992aa6b833088cb2b14ad870946b2d0e3f8a6f380" . + "9010c0b824a082fc5874134ec485c2b5be971c5ba6ba4d2f2833ce9e8ef092ab" . + "70e1810350f9fc8cf28714f4dbc2e0616873030b655028e6b19a5b1853b21ab8" . + "95c40aa24e4f3c8ac7c7bdf170944367d842281298c35604babc5b3e70ac63fe" . + "3be329c281fca7d0f56796b4b9d5a9864d93fe6530b2e4d09034187844ada5c2" . + "d3b3606d31e47250dd37f956ddbc58d4f8e6829045d88975b1f38c063bfa445d" . + "41b13e3e877d2b84e9bd30b4703fb0db7e495d76a8d0ef9d73c5e5e3a9d67545" . + "395cf90388421517f27ccc36bbaccb6fb3ec975d4e5e599ea9e8f4126686777b" . + "3ce6cbe50d714b7b89c76a155a97abc087c4d3363f99673bedcb308f49279910" . + "4fce82378779915f7f875f87a3bf98af28c2de6bcab92c086d93d250b07f57c5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "8f4059f657f08511100bf476a118e43bb17d83327da3cd4245a779ca7da6c155" . + "3686337cb449ace3a19ab3500b01b5ff29f08ca19f2dc093acccc8b00bccefd2" . + "817bfcc24c2e1766d060f2ee0f64cdc7b33e0e902b31491936d2d9e258636199" . + "2a18c956b365b826d99909cae2ed06813dc34fa12818fb619250218de7a6b5cf" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "d36f190fd278461f447c950211e11e604db693b19dda37325ab1f089b4ad61c6" . + "ea6453a337b2a68637dd42f9346f0d1bb7e7d0c46738f1199e749e2864572ca5" . + "ff4cc966f894502fb1cfa3191ae0827d9f447a3da10e10c557a2fc90b1df82f4" . + "d25ddca4a60d579cc5b4ee9007960c0c6ebe06eb5393dea861d867915fb59486" . + "a1434a2543d6d0a600ad06a23297901d1d97cc88ae74eef3e09e92ef50353d6f" . + "c26235ea90bb92b46fb02581e2782652ccc2e96441ca1b33ef1aa8814fff19f4" . + "9f36899d000baff242126f3279ba3335966b2c8d92a02a4fdf0f66d9cba8da4e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "64152600fa4224d9a249a48da060b6d0dfb8aaadc48933c63a041843a6b52c6d" . + "64152600fa4224d9a249a48da060b6d0dfb8aaadc48933c63a041843a6b52c6d" . + "f24ff3290ef2579a20b7a8d06c75a6049daeedf95397fccbad0e0ae53c0430fe" . + "7fc8056a1a329ae584dcb0a8674de65b08c49a55376a961918c89cdd39cdbd7e" . + "c57eae9378304da29a4c2dbe605286dbbc7af254640a527cf510986a30a55800" . + "a90319a30bdb9377acfb216e4a750d2f6309d277df9088241ab115be6b0d9f78" . + "2190c751ab73497b76c78f21ffddd3a1e3be0ee7d86ad1f46e2abfeb02ebdd08" . + "f5fcac81901a8bb20804ffd60fc74ef5d2c461b84df10474b22f61cd8316ea27" . + "36884a7e06756a21d6b76d044e13f76b5373de5c18d982efe2f3d941b2579ad8" . + "8785045fb8391f4f59cc882f2dae2b30f37c72166414a13535c4c0100c904293" . + "ee53cf89a92fb3324b51141e283697873121662fb35a6c53eadc9a77342b0f7a" . + "e813dd459b4df0a617742942452b60520e1be4a38677b689f1271259b485823f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "223f2c6806413a6deda725d2c557337da2534b1d79858f8718d4c4ee66d4eed8" . + "6a98c6d2a714e999cebc433fcdb78aacf441a85628b4ae649dcd479c7db57e36" . + "cf7cf3fe0a57392f8fa4f8e0ff55855a1dff99c500854448c0ddcea285b550d1" . + "fe4d73db7a5686667292c0f4efd17a04dfc7da4833aaafca80e728f54285d376" . + "c2616ebde3ac8d90c89fb3697cf50fbeabf0a330e263a53c307659c87772995d" . + "439b17197e5d193a3fdfe75f5c7b9c6fd88afd6cb1db663cca4d465af8d2bc48" . + "5ed550180204cf32365a771f870e22f169984bc068b894f27a52ffea18b1e768" . + "e4207c29cece3dd9c9f2c3f686a162256e0d72ed9a7ebf8502a9de6ee0bf821d" . + "531bb581eb3900fd41392ee49b475228ed57e37500e642439e05b283d05ea5a3" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "e0d060e2728f89dd75d71458bff9883f2c6d17c09249296aa4149d57a4638b93" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "6f9a87c1a665ec860794eb98548be7169a342ff77c81ab80cbf8f461e62c1654" . + "c3faeb34f11464faace23dedb302074d31e57705c1e9afb19111caad9ce2d1c4" . + "2700cfb07faded095b0980074ce448336a6ebaff52d91ab77eb7a92d416dd7f8" . + "c6824509e14c1cd5f42e0c3c3211e424961509b1d239aa71980755ea6bd48143" . + . + . + . + . + "ed4532549e8db548aae7f01b63c0a3a4e064ee15b918c8aba1ea8ea32b64c190" . + "fe031ee2fa083444addc02e8a1cb86c47caf956f1b03b097b83ae8be107b6b00" . + "18beb65c8eaefe1f4ec9cc29770619c8fecd7334e4e77c55460212387b8a410f" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1ba7f2991a108ec38d69a04eb9f8141a5911e0b35952681d64c82d1b46272a70" . + "1ba7f2991a108ec38d69a04eb9f8141a5911e0b35952681d64c82d1b46272a70" . + "f3980393e81693f01cb804ae1c37df97d18b23d45ba9ef8d63f9415d46258487" . + "4496830f0737a78802f52cd7709b37500a39b669951d90c09fc59465797fb115" . + "ebb95490e67039879b71cba89291b87acb7f2c488b4096e9df38f0e4d457d683" . + "b8468bed49377269f57a807384ed0c767f18ba1cbaee60863f571f00fde43f0a" . + "5532f73bf444867b67b49c2d1bef65f07ba7a126f40fbabfc5d3f4c651f1c9da" . + "34e66b6d420382986ea0d544837f1c9d61d502abbf3a66e2c10a69b7e35dcdbf" . + "39d558e92f49bebf36f7d10f23140401f3d9d9f73c4869c92493ad5e6a69c199" . + "61ce786b28fd737869996824f6f60a1b58d27bf39f99dcd3afa37208574eaa6b" . + "31f4b508ddf6863325fc813294dc9c4ed72d920a808e7147b3d51246100445ba" . + "112ddd6a1bc36266e24434dd603b1e46929c9e36a7bc7a2f7881d8ebf019f601" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "d01e02df63c154e7ce71bc3f3a54a11a76cc3ba205e92e7306426ef7cac0df87" . + "f53da32d39f3438b1e7d53fb981c0762a51a8a5ffcb99f0713dce38924ba4c50" . + "dc5f47b8d9b804d3b680e78067a8bcf9665e30d90fab2608c2e78ebe80d3077f" . + "f3c7c8f95829514ca00d2e0410deed55f6b203c309c5113c4c473e82dc650e34" . + "9afbe44d58d3a3469cab93869900298f088ba9eff88d3fe16ee9b34ce201de94" . + "1d91735cec44695f464fa2d67e2664a763ae94501f04082d4a5979e6641eec54" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "fa050e73ccd78b699122a143b136554c112edc57b8e8a587ffb93df4038d02bc" . + "02cc05233e5a7297d90037debc49961970e24101127991b5050b19d7def3ecfc" . + "dd8d3e38be817bfc9386543b369045dd88b054c3bdf32ee4423ad5d80236d762" . + "461aedc1c8cb6eb3844a3d95dec1ac9b7e172564076e1f3f533403fdfaaaa49d" . + "7339513bb6bbb7767224eb759ff2b43bdced89e262b507280fd3d79737b79cb7" . + "382d2cec9335ad8681b24b6d81c3687cfb30a9243f8554f3498d5260cd0cee28" . + "5c071f170877cd2d563ef03623fa1a88c95ef615c4327646506bcfaea5b569f0" . + "0e746a42ba178b7f1298ad45360ecc51735067a63ee9c4a12f2e930d1ffca42a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "50e1033a5f306a237a41a48f198bcd8ed96a9cee5a1be94578e74f1de784de67" . + "50e1033a5f306a237a41a48f198bcd8ed96a9cee5a1be94578e74f1de784de67" . + "3e35d5a10b31b03f0f84b4263669b9b09f17c1cacb244d159a3e94df3faa9d9b" . + "42679e7ed424f754242945d98f282baefd417bb5b8239b03a614c419d08cec7b" . + "725e6129d20a1b2769ebe0b7eef130d5f544e420c574ecd2d5145f5222a6333a" . + "03ee364402d43b304ca981a5cb47901efca38bc4bdb918f4f01f0244993e8127" . + "90ed62c85433ac8dfac2cc1819bcba70fa846ab5695a774ea67712ec7a982e82" . + "58557c4b8bb7f8200495adfe2ded85ac9e062f5a12efe2b7886105686f2793a7" . + "2f57ec08c8cdc1bd4d93090bfad573e9a7092509a6bd2f1510f1c7a5677f2a16" . + "1ea880d538f8ae0d22761272e6b4855d0f0904cb7be23be6622ab80dc6c45ee2" . + "569080d64d3e21d49ce77476b0d6caed05d62f653411a8702456c61abeb2430a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "533163335709f2aa65d97ad8b6afe4e2309ca08a1ae7e4f84c13a992447e2212" . + "bb655d99b221881c85f921952fc0a8e265bb873d1beb18d1209360985bdc627c" . + "3f1f912d9bd3391549823232c3f755c919f1a2b3bcf19823eb1e124f0e671c32" . + "f718a94a05c950bb5c9f78954b5a6ebb597a385800bb832ebafe582e1ba9f94b" . + "93199e268834c86cec1086b8478b2858b7122333e4d8f5f40d4681be5bbfe2f1" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "4e40610a300262ba9c05adf2b2bee3ddbbcb3bb4e03cda9b58be1e63a230631a" . + "45ff05d602f7ed851ead3650ca42b113075c8e5eb218e85484472399089f9ab2" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "f38375415ef54281c4102cdbefdda1d39011c7d7253656c05d4c77bbc92021ee" . + "4c4dc7c70f68ac31f0dc14f547e79ac5cc7278c9a3fd13de2512b4ec6c3481ba" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f675f326e5c4683b0f3ab66c542ce1574342126b307514d2ca299f7402ac4c73" . + "f675f326e5c4683b0f3ab66c542ce1574342126b307514d2ca299f7402ac4c73" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "efeb6b74c061cba4fc733cf3bd5abf31b78e2a123dd8e0ab4287d293b0268927" . + "d28e4cb03f57822cd4e4750d69375beaf5b49e42befbdcee91d508d31587f7ad" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "2b674837f4a1d4fae442fc7f43d93b3af3edab7ab065456f0a56c6b8a2c762a4" . + "1fee4f02a743a4d119caa7969441c84b03e9cf11270bc7f3a81bac145fc4e6cb" . + "0a9626b71b1f0a52ba79fef2dd09a4046bc594e8d74944246e6f0bdfdf6ebc21" . + "ceddecb8cd066f62f0f55be8a28c7f156e3e94caf3a36f8f7f0c330ecb54381d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c12ad3bbeae794e523a237ae16a1380cb28284ecd843614e3c598685387c538e" . + "129873ee7ff3d1db5108271f71504179512a607fb55298b807ccffde4c8072c8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "d19a49a91f2472dffa24ce6d6dd32db7effe517d5f03d542417fbefdeed70c66" . + "360a89f7be9db9488229dcb47c0c4f9721e922cbfa75c28137745bcab9175ca6" . + "a42344c7437c8bf3db3918d67e77163f11a1f2e0570faa26cd52031a2733c70e" . + "4d71a227a27bbee34c174fb418356edb690b58f2a5f1a801379a258701cfc4fa" . + "4477df0fb59aa90f5c7a19dc724969a1ba9379c3a79fc3338181e8b35cf98493" . + "4bc5f50fd5a5d7be9f77856491fcaea08d77107e5b0e5b42e3a35cae17ec212b" . + "7b29930a983c69bd3f457f966addc473888f6ed96ad871b6e19e748db099931d" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "39ea0e98ab38c8648f5278db4c49045a648b5ffbc5002d8cdda53570fd365ce8" . + "39ea0e98ab38c8648f5278db4c49045a648b5ffbc5002d8cdda53570fd365ce8" . + "ae17be26003d0c4eec4d541173096a87ccc642e38e2d344649bb7686382335f4" . + "4a3d7f2ff3d85006f46241ef4262c5cf124f03b2e4d278881576245490f7a9a9" . + "6ee4637001c80ff2a9e9aaeaaa83a90be9f5c5c71b7f356385e5186ddfde7282" . + "f717c33ef645ce24184c1a463e9fe7b3c3745c8d636082b7af820eaa99ac3af6" . + "b3060b5d03f26ea5361545d481e25175f1c0e80fcdfa792f4ed92360ce314ea3" . + "2040a68ec77cab5962baa9aed004ebd3e708567d9ecae93ad1ebce282aeb4d84" . + "7293336f41f0d40a330695ea891dcd59f5637473eb88bdb423de5f09f9d34e28" . + "446e582a4cade49cc7081ba2022e84e121840eaafdd1f1205b2a2a964a17cb74" . + "91c4a1fa713c28c53ac21891b0cf9247e3b5fa70474c1d75154698a68d1bfab3" . + "49dba71a3a08d2009bf7c7d2052559879dcbca06f0056c3f0a114901270a08fa" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "93d04346d42ba7f194a2631f30988cf7e0d9c7454cc36c480ebd1b1a722aec4b" . + "d882bcc57426b3a62ee4c1412c225c84bc0afbcb45654230b6be03a94d421ad6" . + "f320c18a4f0c0c19c3cad97ad52ae75fcc7cf3adcc96a46b5cfb848ef2a43727" . + "75f96491aa68ac4338b1a5792c49010b948d4dc5c13259d2aa8951be35fbd4cc" . + "c8e9d44a9b84ab92d1478d72f320033303e570709acde7e305d433ff50fc8f7e" . + "31326537a1752b6b824a4e8a57774bed3562bf84652bd2f674e0e4315e12aba1" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "5795365302bdb365bce4fba971224c9989f1ef34bad00f4ba29d484224146514" . + "b0b47748617e749cbaa6385632e01ca28d2369ee39a0073f685c33520aea19d1" . + "615a9db56f8588738db0236cee996613293f9be2bc3514e809e979bad6c25b30" . + "d5ee1d44d6d5fbdead8de3b65f8b284b1e5607a14291426b5dcfe68b1cd6b766" . + "0fa80ebecf482f1a28edd1e79d9d68b7552e244b96d7768ee1f594cb5b00725e" . + "fbf58fa6644f2f71fef19589a8ec6c3ec4e8fd73851c34603a1330fed578769f" . + "396c2f4e9ac841a33050fd6a7d50cd2eb905ada45fff31d3d17bd4b0b906ee65" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4ab606ed4273c65cbf649abd10a3af93aee6b112de6d8400f0366b5f2d4a1464" . + "4ab606ed4273c65cbf649abd10a3af93aee6b112de6d8400f0366b5f2d4a1464" . + "c760b2c1c1bfb98f6acdfd45403a18887d3276df728f053ac345a14b2702d37f" . + "88b226c0d6819991d17f127d5716e13620394bd8c2e19e45b6b76b738c3f5d8f" . + "48c0c0ea984d3c30d298c99d9248b8f146e5cda24c39c5b8bbfa1a64d1fe07ef" . + "f365548576f1e5ffaca74ce965157d68ef3b65685eae414b45b2e4bb75c10172" . + "c7ce719e78e1923e5a181d5f0ecf561764922d11b43b3b897bcb097273b7b7fb" . + "db7711dce477a9df0a54053381fdfb58e4b0afd7433a41e0847897d10cb235c7" . + "d01f9897963c4094ad97e89f0cb23825b88f8779d4762387d4d64adf47d6a378" . + "19253746a94afbf4a2395f194678b6adf1137bd721c427e08f9582a85abf0a25" . + "c59b287efdcc2fa8fa5d8c8d27b074479b4801a70613cda02e2cecae6673830e" . + "4df03fd8430be8a1051332da2a46d8a25da999135315af97a3d20141791495f8" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "4441633651a9c5b127b8e41096566b19be1332dddcb64ea1ccf06709e4996912" . + "3f0cb30f81a0326909da7d42e85b90fb09a8e2d5154367137fc06210800aadf6" . + "e8a2c6d0cd29bc004f2f315be9793dc8e6784673c2da5d6191a41634082073f3" . + "000d792d88f97713646c9315a62289d7422efd13c27e37377827e5f0b8b47c98" . + "4dffff6d1c9e4d7c809e32e7ed941003da0b465aadd1215bc9ef9a692df91f73" . + "c064d330eb36c6bd83b91f631d900f38b6583663642bd12a59051e7edb5aea6b" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "cc11dbbadf5b122e8705b0e5cfe218e40a632752c7cf7393a4729f235d312a4d" . + "ccc0a4bb3dc6b3aa700666fc5bce17f004a952e12c532cdad3d2eff9af555f4b" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "f7bb7fa3cb0501e501915bf779a404034be33df6980bf6bd35f9ad698a5ea379" . + "1134c7b346d4fd9a84dc218f395f0ad9a73565fb8e57ca9371c4998173089ce4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "588611778e4056198970e29e53f8511355e36c779d749cdbe74ddf14a4d62775" . + "588611778e4056198970e29e53f8511355e36c779d749cdbe74ddf14a4d62775" . + "96c35cc982595f373eec85a1254bcd4b93ea8043420b1ca57ed3154304ef85ea" . + "c78fffc53170867854faa2302d429ccb8a245f6a30cb0acbdc2123120cdbe59e" . + "d37446b9c36802031c61d22f5a62a5d4eecd73bd807f56e21ba0d7f54916c85d" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "2a5f5de3fe08662e8cab9f6abb69ad6ccaf42eceef57551d3861ede489c015a3" . + "b25e70e2ce11cdea25503b4dce87e3835beb196f117f040b599486dc980f41db" . + "d836fc8a2f8d2352f530c8edf1ae54ceb5b8528e65d2885710ac5bdc1802d62e" . + "31f2ab237c0f8d89894cbcf0a0032f46ff48059a694a40fa4c227b91c8eb0f2c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "21f47be103aeec551fde540bcf63180165519c11983dc6d72897d9c5243524a7" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "fa317fbd65e68ad46df2624c4baa448d3cb23701ab2993d6c832d010a6bdbec9" . + "e1f607dcd3ef820150c7da63db37e11bac3c0da6bf399c875234cbdc2e6f630b" . + "5cf40774b4dd5aa34c8e1f8e908e53a9d279dbf7c1ea28367604393788aaa061" . + "97e7441cf5cabaf41a86f814ee4a2d022bd9558b449e34217f055c0d5bb33c00" . + "7fb658cb27fb5553544fc290a1aeae85b68fa3a6588572b07bd9dbaa06183828" . + "8a3b6e9c194c775c84cd1df339c205bd0de2843c738ca06ee0e3dd7f5bdc84d9" . + "429dda9564f42656042644d5564d9528224566c584189bf1099cfaf280f2e802" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2f8e492c5b086213ab684cef2da969d933a8be99e0a0d19b0b89d5a2e629cf86" . + "2f8e492c5b086213ab684cef2da969d933a8be99e0a0d19b0b89d5a2e629cf86" . + "5319cadafe5a615f7e6df1baf8a4a20ae04da9dcd6602d1d13dce5bc00485687" . + "66f58748264a4735d70d1659abe0fb20cf4d18ea9a99a70637b36b792aaecc54" . + "a0f1defccb5abdc35fa14dab57b38db49e4a7d0af7053eeec070ebc84571297b" . + "404c7f327268e65e3eec2a9698e96ff34737138eddc6cd2d2b791a4394dd61c4" . + "dd84392f47438504715047ba26ae7f73b8438845c8ed8ba82b4aef6db044e9ca" . + "0f70e46c15f9907b877e638b4dc318d850d4a11d1a99758763ade50e7e9caa41" . + "8520c5435d97c9d1622f7f91fedb6da4175b613548a313f69707f68afe0a5ad4" . + "ad0f95d19b6d8749eb0d39b0d76e06572193ad6e621f85e79146ae80e2cbe2bf" . + "4841d00b679ed5c9682ef83c1c81093cbaae29c222dd7f4ac205dc74710b5fc5" . + "30ce8b022fcd26aaac847ae632a5584c7d8ec7f9451dac5eef40df3152a1fdf3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "f96e5c093e0031933ead32ff625f38e93d64b4392676b9c8a7d920278a9b5e84" . + "19e2e65707a093820ab02a7f5912c262ebd5f0959ee3f292af93bbc6b04e0f90" . + "ae3590b42c2db702b7ded780808a4c152f48f28504b24cf8704eb6ed4922f0b8" . + "d713eeae77b7de3705064c30f8fa987283f824898ae35373e5048a24508e4464" . + "46871242c21505130f062814d66c38e550e0ed9ff34dee073d1b846ff7051570" . + "6200571aab7e01c05e1e7db8151a2b6a1f619823881cae052c8cb7f0669d2907" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "676bcb88fa3a172c7781b515ee2e1b6051af85ab734421f296ef7774024172dd" . + "9b0a08c56c8db7d303002941482304ed53132905de5b3d2130d7a1ec99af4ef0" . + "d6f52605ea40f900227ae805c18f2145bd3e52b19972ec0ce0e8af69c7231adb" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "015e497a8cbf878f2594b51db8fb1f77c430e7020bac02fe1841505651510de7" . + "817d2c0114470975a0b8a7991a4f01586e9c6c9ec5bb0f03a15e5896487eaab3" . + "1ead70694a53afd91d7efffbf6614ad9466be45697e144834364a2a3c0f66d75" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b66b59066595fe130885c411e81b0b4fc3582d3491323261fd0768867c04268b" . + "b66b59066595fe130885c411e81b0b4fc3582d3491323261fd0768867c04268b" . + "9d21270ddb54f1e7f3d16f18c72890d61af66151c8320a76fd662fa5a1ce5ab8" . + "276e3800ae5571ce04c5b74949346b4ac6f4dcf24a82dbb1591e55877155cdad" . + "66c540d037be1decf54e264acbec979bf16bd42d59a0cf94e164d5da7290a3b8" . + "3256cc3a1cc0ce8821acaa6dcbfc45356b50cc259489850f2874aeb91906c8cc" . + "883607475a2bc57b369901fd3e52dfe78fc6aa8e712179ff62f75d0b76ede412" . + "12b797f407a74294a0761a4854f1ef753720fe5490519ebb36aa81e7de6be4d8" . + "92b831fa4455f7dcd6e0b3ed2e6823b5c49e1fd7e9291e44964ad0bfe570c3c0" . + "fcb6400fed16147905603e3fd84315366dddea6a819a85f19dcac97a0c547d99" . + "048a6980ad50db779aca65ccd99e4b493b4c66d598bed9bf5ee17d7e33064246" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "d7f425c00bdfb9e1171a6fbc7312bb4a60fd230b5808f6bff417c4944723663b" . + "fe88ad647a29424093adf97918f612e4f878d693bba60c30848845d09c57c360" . + "e27b811f7286f0daeb130e22265aab390a29bdcae3432d86c7e8820fa0531b15" . + "08c9e9943901cdc7b09d60d213e7b2202e5b21f6010ca080371848a01830c14a" . + "29d2d7d469c19b8a8975fcee23d4f979d83e4332ecd9bbf81b56f6250d3986c1" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "40f718b49bb7ab9a826c331184b94b2298a8aee007b802d37e864c40107d82a2" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "f67e3293da15babb947deee5c8d2bcf58685c92a593083ad59b33d497676fd27" . + "e75fc88aa312038b9f82a7b6ce498c0caf320636f56682acc9b754efa7ae6935" . + "ca9bcdd6448d53ad56bdd570ab3ca5fd99b05c0e5bca4b67a893c6ed28019078" . + "fbf019a58589ed0642c314291bbbf4555274cbe810d80f1665c3b4b6d7a6b9c3" . + "806bfea5432e4f1619dd4a9fef7cbd561e90c4b938af62256edf3408a8b20748" . + "197161e1c806f3b833f91befb4ea643172a713d3517277057260d9340513c674" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2298b968e9ca1224878f16f5f0281db7f72c5911eb68446a2baaa8100a86d157" . + "2298b968e9ca1224878f16f5f0281db7f72c5911eb68446a2baaa8100a86d157" . + "3ea2dba7190b5557fe0e4ecb60daae008078980e67f5637c9f4355cd82cc4005" . + "fefa66b0e2cd12c5ab7b70b6b168b3a735656fcbcf3fce0879d5244ecd8065fc" . + "369c8846f15618bfad2c34ce504f30ab337e61b5af76b2dbbd4b3b7320dbf79b" . + "a824e4c3166aa15883147195dd63b34c8bf8bebf59f5d571facaacbf458fc079" . + "28a6a7666478da1a06dc67d0cc5680a01a1329d939f184d72c4450865204ec13" . + "31f4b508ddf6863325fc813294dc9c4ed72d920a808e7147b3d51246100445ba" . + "9fb3d6f8fadf140c68f4ca62c5e33f2485f31a32ccf31de85b67d6aeaf4893d7" . + "10ffc82f31a72ddc92653d0e8114d77ad81a78a167cbd6257cd855313f036eff" . + "3b6745ff6a8361d524c6d3c62ba140ee8ab56e0b58e7647c69852bd9bff22139" . + "4850e4863d23c4f8603c58c497f4af2f4d48cf06ff51e069f0d6c47e58abb005" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "2603e2d4625e43eb08c30cbeb66cf4b7897f84e3f98a8b64d9a616818beb2d55" . + "7154428033a084bb3d916617d188bcf355ecdd99767af777c4acf36a29feb5e5" . + "02261612945353b8cd2073f80246b9959688287a425989a8456b1a739ee0ac55" . + "e6a10f2e91b0041a66ce830f453208a934f15c16909301376f51162065caab60" . + "d638d62f2a5e6c41919fa3cd99de10472563db3bc3738e1a7b228f89b3f0ee2e" . + "7353e6706aa239cf9f68b39e6a3f4556072356c57d432ea91b648c80a5ce5f13" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "2c9285e63bc145dc1bb1cdc9ffed7c9a7114b54982b98c72e7169742f6253ac7" . + "e0e7a67a72d9c3c149330a396c5ea8e9d7d337eb954b417c10a1c506024a8f7d" . + "9c4fa637b9243e6b29b2a635014df0fbdc2e5cce4abe00c971d6787211ae6874" . + "6297397692e3bdf90d61f3086f261a93d1afb1c5d0c116f440e40a6a64c4f533" . + "0f3db7cab44121bb223c5718f9bec32521bc88b076cee35c5f05441bc0d66dd6" . + "451a031cf3cf14a1618ddc1484343cfc52ce86c18a2ca6f59f36fc88dea2031d" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "55022921a051b2b80c5601105267f0290796ca4abba33913cb3c658d150f3b0a" . + "55022921a051b2b80c5601105267f0290796ca4abba33913cb3c658d150f3b0a" . + "5fc8cfce3ea3826a9ffc1b8f37bccc3d2f6fb2773841acf1b7579f1a01270b43" . + "937a177eb81fe82bf92a7a4c96fe3146a93fe5b8493f5cf64334a800184b7aea" . + "8be18a138eb2942715bf20bb03bcda2a7a8d25a93b65718bb2eeb268214df8bc" . + "7fe62fdfb62822fbf51e8aecd968217ec9bce5de093744942dd554dffed3859a" . + "14217fb25f473f95202cff603f7cbc105fbd983cf3da88ecf8eb27cf251c0720" . + "0a395c5aaf678cac5ccb510df7f24b2a2bba6971625ac35063f3add8cf688d9a" . + "d768cd84d3d47e2c89042d1c5bcf664a42ffaca234992be628f40f45d20f1623" . + "6c64869023312f201d909239cf0693b3625d5850bc3cc7fbb0fc04f77b5a8334" . + "7ac71c7707a6c58034d3beb466e5bd244d00d35a33bb3681a5d6da70bb0b521f" . + "07d010de940dade583422ae9193df0a324b8119706743648d4bde85c6e1ebcf3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "68c64e0627576881e2aa679337bc2b208bf392f8824281c25471f2787aded575" . + "3bd440c5c275b390315ff99235f1a7545c25a6440e82ab0060c9c4ce3bdd6df9" . + "716191ae382843609c13a32c56105ca863f6c193f6058e1a398c02fc18fc16f9" . + "749e5028c486b9d6bc34b8b05a4c6793fca1927f0c99f6e5f0314cac96a1ec5f" . + "de4d7c00666aa9dee005ffd4a4261b767c1ae17fbcabe34eede3e258c86c064d" . + "486b511598710e2d4f6b15ac098816f5a666bbc9789ea064056c0f4bb6dd9c86" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "e7f933d7d4c12824f1aef140d9fbb466aa5125b1c0b03532e84f321621acbfcd" . + "3d5691fc53900d4a5dca845c348ac2d986e4e147e5cd86ae087774fb917184af" . + "7ae0ec264a4ea5acf5c1fc20cfa775bf565a7f0c1115aaec41b5583819001c22" . + "dbd6e4fb05c11a973f4f5711d2e3be0b675350f2f15101c5fb398371502e29a0" . + "11ca3bec69bd9f956a641360af1b97c9acac83b78c7ac3973d9d07954adae25a" . + "56049822ef73a8291d006bee3c56dc820f13511d0ed83fe96ecdba624135a29b" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f6c1c92157f220e4f993754c4196e9151c09fa74d32ec83413ed14f3af40be51" . + "f6c1c92157f220e4f993754c4196e9151c09fa74d32ec83413ed14f3af40be51" . + "3e640d4da060f1937569c070c80b28e94495d1ddffbc46cf8e3b021fbf137141" . + "1fa653e21223862ff1b7bc74537ebffadb4505fd71904fec0d5aa2f541dfec93" . + "1f887c7609b4c7c35161cd971c16492c00b05f45aa887b1b4c203a2ad27d4040" . + "bf82fe269747817bbe53cb0b296ebc3ffc562026f069dfe23e70e5f7d9f15813" . + "19b4776f7d3b4c7b6b36a7ca60cb972849edc2575054001f8cabbc83273d580e" . + "6b7df8a2a585614effd4b213487f5187fbca961dc442ed210b29cdcef43a1a91" . + "2205d4536083ce035c273f727757aff43671480f1b5c63b8de884eca2853584c" . + "29d2d7d469c19b8a8975fcee23d4f979d83e4332ecd9bbf81b56f6250d3986c1" . + "5e72cd720123e9cf6ef625b943ac7767df170226e661304e929783319ffea24e" . + "f9e64922bdee785b128376a3cae09f82e79287f28225d4eb6d925cc2af450181" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "e93a80f80c4a9d975b683d39ac7a55d612716aabb3922769de8ebcdde6b0e993" . + "c0a91cc28fe927c3d656b6c556f7b03641328aac9c08b950e94b595648784a42" . + "a2a5429d9e38bf4009e6d8685f65ae4cf4ed6ea90cc3e88d7bb57f6ab8ab6eef" . + "d10c6c4d323c5cb47cb985a2c907f48c9b46fbdb8ec92d45bb58f25d92b69b49" . + "3ed0c893b65057df14e7887c5c3d62194095df6aed8d2145953f7c7abe62a449" . + "94a6e8af7e1b18d45e9eee878627417bfb50d02c4cb74e195f7b613ae0292fb5" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "59e439aeb603481e0e210f654a54537b206722a9c5e70094e059466777793772" . + "25d6456c93e4c27141fa3188f966fa872b2c4f87747d7c0a49c98e64486e4bb0" . + "1572791ee2e6845a7e1beda62bd2a200b9c9c401c543ccd7e72fa4d9d7c1ae7c" . + "7ae73dd18f650dacd17d665a5c06ba64417a234f93514af1a499469c0071bd51" . + "c0b1d0240e8584775515e2d4f84247299a3b621ed90895868b989fc5626f9655" . + "51ef95a770ec2ec11a5da1ccc7cf0d1e4886742051702ee1946ea7da437fb4f4" . + "62cd61fc051c9317584afb530c719f63fa528f095861686d35759a804370c8c9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "706a913127712d68b8aa9d534cf041e78f04ef4fd6e294be176fefdb85fd6069" . + "706a913127712d68b8aa9d534cf041e78f04ef4fd6e294be176fefdb85fd6069" . + "15e3491af5bb9bb656c696ae2a0f8a27001adabc8462314ced3d9f9f77263634" . + "52dbb03097f4f431170f4aa575deb5ebb7f67a437472ba46150042ab14f7ed49" . + "ffa516e7854b803b20ddc5a6897c34a3ded2309ca43ca3309605a4f2d8d05aca" . + "92c6ceff791058fa7b5b3a533b350269e7f98d9f61d2aa767bde14792b493b65" . + "20859c3404bb40b1ca777b0f4b0d7c436be4ff5ec8d1b5adb8bc1d1f764d963a" . + "34f90b1a3607e7c2f2184fdcc209a72c2432e34236fe2415b4049d342367b81e" . + "a6c42000294846ab04e9275c5d77364d19dd751836114f1ebab90f120a7cb622" . + "52f48ee05352e3201c1684ef041d2c53bf947d0368744531807ad4ebd06107a7" . + "c68d52eb904059389586811d23c581bc13cb26b6ba914dad470cac5f7ae67fe6" . + "3e9aa6730b16a56c2b4a3fcd71ead9e8374d7b949890c7fd67969f6f8c87a413" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "aba10709d4fab2fe074ddee0a8ad9a62b92e96485b9ce1b5edd5e2b71d2518db" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "d5c31364c44646daafc2c9b870e48dcc48c22ad87ebc1a9ea38f932b19f6cb45" . + "1b4f0a3727ea357cdb8d88138ad3929b7aaf57f51e8331bc34d974209c418c98" . + "5159a36b016a4c697af3ea3bed02e8afb1cf99cab38788b254b761b2479de702" . + "ef74d6b6d99cce0033dce8d90ed8933ac922f3a7f662f315d5c0dae889349837" . + "9730fc62208767a676b5f98c632228edd9981889774888f763f11d28da489b27" . + "538fc64e1cea7dd884b8a51664352ec1667208d22ccf6c1e8a8759662598368e" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "9d1ac3c10f1843c683a82e70508d2eb79641a61698ab7758688d35ca21abd866" . + "6baff96b432a32229ff69fef44100f5c596a8c704f15f44f7997190c7584060a" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "112ebbe930d8923b57cfdd2c649aa194a403ca6db0561c7d4bf69452cc4a4e20" . + "018496ec9d154e7070117ea41a068dbd1c4b6a92f22af37b92a7e557c1a32581" . + "e8e1023336468a59045f82209926c9d921441a52e63a9619086c61900208d1df" . + "24170f5927c8fd937fd786101c75448b1c18bb7c42bcac54017a170bef97b138" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "29208e9ebe936da87c8a7aecbdc55e6cffc5236e230f039ed4f41b972fd2a9cc" . + "29208e9ebe936da87c8a7aecbdc55e6cffc5236e230f039ed4f41b972fd2a9cc" . + "244ffccbc7103f800a4061b4d0b30c356730560419f6e959307c5ee6c298a2a5" . + "13b1f411b7aa8f5b23c0e7294cce6c0631d27036a84c5c1b9341dbd859da315c" . + "0592a8bbda48ea0722b65db42ce9d768812b8d4dc9ac5dad4a12346e1abce4c1" . + "af2c8fb72710710139420db19ead98f186e7a9571d8cd8de8c87b7dd9123d8d5" . + "d2ed26b6c86230a7b31bb876172e8e7d136b8ab6db4dc1c0dc78aea4129806bb" . + "9c66fa6c1c8b99b83a67ed8346383252b134d2e7961b82acd88a9766f1a78ed6" . + "fb72fae08393c689b527b7d6ed321b75964bb8ece0daeed1f9d799b7c0073806" . + "ed9bae3ae8c6d493ba5f64f1d02c13809d8fadf6d9e1974c1a390e6825c7cf59" . + "7da5df594686c2543ff90d4a0229a865c760f020167e8c3af3b8799b4693df4b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "d0e5c028809ebd396b77ec9a8ebb57bef3b2daccd71253be1ff456b9eb3f97a9" . + "e7c80892af9c077174ac2117a19573408264ded4f355471b63a740834c281494" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "1b769d114203c35641dfbae731511f94406835137e4dc7517a9ee307bdcc2aa9" . + "348a7f1791374dd948da0b9f1d9bf14b8a8d59bb289a709b5cce0ffa6e02951f" . + "0c26b3d69ba4005bc54cf8fa317a5787c5607d0e4f785fe09f04f53f13d21600" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "bbd15b88b592588415f9d1f8ad9a3eb32ca76fd1e9d512bbaed4e2b3df8e73dd" . + "36497b6525ed65a4a85207e5d432fef3f8bc65d8aace4a56586921b66bed99c6" . + "f6eac97c000903b0b70b0891eb514bcd0880bb24f138d1a26d5a53b8001ee1c7" . + "857d8b0a2f227cb343200ddd6aa78b62269b014920c96a0fd2b2853622d95a31" . + "bbd15b88b592588415f9d1f8ad9a3eb32ca76fd1e9d512bbaed4e2b3df8e73dd" . + "12e8a5bf2a7cbb47251e2e7bba94538ad9ea988f03b3f8e465d2a743dedac327" . + "b67384f4be620d6af0c73e7e452a58cceb7d2462bb2d9a0ee63ce003554491b3" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "995c0b2b40ba3bb99b6a6325bf78ecdb2b674d0c2f082c2f81408398c3e0f908" . + "995c0b2b40ba3bb99b6a6325bf78ecdb2b674d0c2f082c2f81408398c3e0f908" . + "669dbd57f436b03dbc87df53f0623b5f2df3b140470a79a2a3590c66d11cbfa8" . + "fe77232d8df8075642390fa0231e6ebc6f665c81a667561751965652a3b1bf8c" . + "41dc5c29d63dd5689d0560f8403e3ce395a7ce34ab3141339a6f5c68b43eb6eb" . + "c1aa3dfd9f857eb6d01fc8e3b64095b17877f769a1c41348810febf89feef1fe" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "a64afd22ef966f47a699aff1fc90b412657b1c3f4fb75f74d3f00349360bc197" . + "7a3b4cdd33212f899ffb11b1f6f93fec770f17c21bb5ad750581552876e271a6" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + "a64afd22ef966f47a699aff1fc90b412657b1c3f4fb75f74d3f00349360bc197" . + "22e472de1a3bae727e84607ac07cd3d6bb312e04336c355813609d3fdd10c155" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "df7fdb6b2b69f556a8b6e4c9ae206c5e3e57f821fa3c8845a5b811d12cb79727" . + "df7fdb6b2b69f556a8b6e4c9ae206c5e3e57f821fa3c8845a5b811d12cb79727" . + "89b6baf2dddbace10bad2c222322a595d7f3649aee99b526abb50f2a555a46a6" . + "46c60f916d76ca50bd2552586d5315ff15a6209b3273abc2cce78be629982751" . + "428e63ce6d0baedd3a57dcb66fc8817464a79cbd2a732344bbdfd8450141565c" . + "35884b587f831e21c5e98008a7c5fc23c7968d85c0484387b3dda1c75aa6465e" . + "83a9d7b3e9c4402766ca1f1d718f4cf3d38137c5a3fab9646903ba91709cd9c6" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "34d353a74b9b9c3cbe503a155d7add7cdfe438b45691edfd83d6e5d9e44cd171" . + "26eb72ee56b40a8e606d0b5e2252a3adcf991abdc2dd05767a4b509827e74657" . + "0f7c7f582c6e88d5bee0cfc0fbc1035996dc40b26249bd3c976925f68c290f3e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "dc5f47b8d9b804d3b680e78067a8bcf9665e30d90fab2608c2e78ebe80d3077f" . + "054e1257d35d6be819c28068f5b4873d3d25414568f0b4c236295c952d5c885c" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "b529718791349d155f2fcc36d4947ccd89d18ee49bd31a145cde2224aa4d367f" . + "33c885ab76a3bd2b8153b0e39f88c2ebde5efda066b871758b59ffb29959920f" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + . + "df0d1c796df68d74e3ba9466119442fe64fd648d8440d46ca16969a7b39c292e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "17da2fe2916699d79c7b89014418aa3f6585ad5c6dc7f9175b725f5cbf3b2817" . + "17da2fe2916699d79c7b89014418aa3f6585ad5c6dc7f9175b725f5cbf3b2817" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "8bb63f4ab716cbf6fadcf9aa8d3030215bd4a9f33fb2d9c25533e447540cc698" . + "7468197f02a6b6d5ce987fbca6ddbd721c9d9be2347a775261038d8236577b33" . + "a3fc34af46867c90cd068e4ce10c53eb52a2427c606c248dcab8442adc824e1b" . + "218176c22d5171b9df3dfd50999a31afef88a9707c18646024e06c7f53f0f82c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "68143720f1ba009d996909187e36b0dc921928596e6f6610ff7faa1c0cdad68a" . + "1734d6bcfb538d453cf750f93b91f2ed2995b358f101cdcbf1d5c7eb96675221" . + "7c1719b4ac20b6f3e01736f606e080b997ce38ed93ef38aae7d5da82fe3e5b7d" . + "f89072e789198119af60f67da4496b6b7d6e5c1a733583e989ea9d4d2cc14c70" . + "e7e72faa169a2f49daeb298e7a9ac4c3aa86c5e31054f0f74767a47d35410afb" . + "71d7d546ed537f557e28613e495be2f1068cb7fb8edc3f5e65ab54c4f51baa0f" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "180851af44c3a4d0bea3b00ea646bc294206c085c09d054c7e6235269533e5e9" . + "180851af44c3a4d0bea3b00ea646bc294206c085c09d054c7e6235269533e5e9" . + "0a237cd46bc96ae66295bfa912f9bff64b60e92a176f34b50bf384442c5873ce" . + "41bb5020221fb4790d0e9e6ae17f7de4a479da4fe853d9cc0e8efbf2387a446c" . + "6353c885608261caceb5bc977aaa68f3c2919b8db37da001e44dd71eb7600a8e" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "cb03ef061a7c2a7a72449684aada7efd3b5118e86494b911e88588564bfdf2b4" . + "48e8e9ba51aa9800ac79babaa1578c8c8c3f0d3c80085e4d4d8602b72b59c0b4" . + "5ec7d911715623d17d1d06c6393bf03fed29c2e2c09d5634ad80025567fb6f89" . + "f527932df74c5284bfc0a6a657ebb5ba9e8a24140d8c8203f47ba4599f3772d9" . + "ffd0a00e9eb7a3a0463322711d0cb81a3f0bc2cd633983a822cade8762298cb8" . + "b950db0436f71538ed9d399158359c7769ac03e373b0e9de992ff6293530fe01" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "ccf9dfa4f2812708034b9a00d6428f3e9255930543ccd3852f6bb7545283debd" . + "d882bcc57426b3a62ee4c1412c225c84bc0afbcb45654230b6be03a94d421ad6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "31a785a63b00537285966acc7ce0d9b317e7efff9ff1595de6dc50aa81b9d893" . + "46812c85636210c0065c8f25870da675eb9983abf163bac03dd18269c85197f4" . + "868001e9f4cab3e40167aec68a944a440b2cd723270df94ad81afb37ac38c37a" . + "0e78452b48420175bda59944d3367e2c359bfab7f925e069f994453fdf2e9595" . + "9374de43eef6a0d82850456cab5de2a7c0bb169ce4603baa56d82cc02dc1a4e9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "9d088de51dc8eac5bfb0652b73fc5a5cb93ae50f6171f3c84098f2fd0ee30f0a" . + "56675c14de9cf0446c61b4dbde9e4529a8ed4dee47607f08f59b8dd984ecbb9b" . + "a337ee753c72acf1b1466e8cc6c86a017cd8472d219b21fdbba5424ea7aab676" . + "4e90931480b18786b41e928f3e8c45c280195dbdab261dcdec94e9a36f3d2de1" . + "655b3dc578c58dba8fdf236c419d3212b8006ce899d0205f929aa5d021829d1e" . + "9d238d0f6dcabd95cee35055911095b616357118929d1f851c1a263695a4667b" . + "e5d0603f0493bf08d5760db4f02c05c63ec150421a9c4348f5139c4908379c55" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65d7f69197985b88cecb16905ec479f522f0a53cd5947a77c00230739ce6f625" . + "65d7f69197985b88cecb16905ec479f522f0a53cd5947a77c00230739ce6f625" . + "18f927661423a1f3941280ae74f6f00bc69560a141c2e3d49038c9a31225d8e9" . + "b78f4dbb753e7e2e57a94aee2290ca3ec03a5564221ec19d69e7142656abb76b" . + "c1cbb1b2b267735edc9f98c25d8241470c21bc541f39fb9d14b42741cdfc42a3" . + "761b114bb2a3f948d616c19eb3444af272fda961fb7d104c0f0dec70fddc5de3" . + "32ea4236493b7b0f4e526f36cfc5f3e1f0baa05ff58702ec42d7854dae947ff0" . + "b8e170be24de2e3a224ff16bee6093b6a59d093fefa60666eaa13f1c6248e7c3" . + "3e9aa6730b16a56c2b4a3fcd71ead9e8374d7b949890c7fd67969f6f8c87a413" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "ee88d1a1c2686f9c3c1e16a785e6a4140d9cd0a705b80df6bb8e7f99196cd5a2" . + "389ed846b4889807f1630633ac25edb18148b00f3cd4ff488d8ed5e6ca75e952" . + "d558b72f6c732a9ad20ad57d553ffaf4517b2caf631c74abc66f2958f205a998" . + "04a2004eb9202b7385ddc7f1379af75f40368f56760f005c246cfb546fa825bd" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "abea761f90629d1e62be92caf847288fea6d23f37b88f33c6ab5863c464f43ca" . + "57ee6393667f6ba020e99865c2e31b0a22007bfa7999fcdddb2385229440b699" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + "bfa9d0dae50eb4f97cbc9996254fe7d1d91810dc1470dbedde798a3f982aac2c" . + "d5bc5bd13eaf6f9a4568e69bf0e6e685d556ef87f5348004da982204d08e5aa1" . + "dbaf93c0850ebb302f5e1029799b5655244abb5db82262419698e1786fc42d28" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "59927f1609f083fd20081a29a94ec973e7b247f49cfc3850ce7ebbec1bb99a56" . + "59927f1609f083fd20081a29a94ec973e7b247f49cfc3850ce7ebbec1bb99a56" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + "d516b454093881e024f5d615c7647c22edd55ab4648624e7d9d86a00929f9440" . + "de12b2095576c2e2ff02a6d4c486d76c33b478029addc777ca70d7c6fab6cf18" . + "331832675374e5c2f88c612d22e1d1b7bc956ba6e4253a5482e1443c3b67b324" . + "180b1fe0a37edc9c033734461a4c3ebcfb81f100a92f649a993d663c1d367ca2" . + "e43170b82402658c9f6495c3271679874ef456eb1e0b835e09a4851a6e0b98f2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "df46a224b81e2235886ec658e14d806adf7de350d582661ee630392feb173127" . + "3b9c82d67a2f92f625f89a4d17a974bbd8cb5d097bd70234e6d69f7fd6ad714d" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "152559f34b9775e7628657d27d8b22d87f70fb265129cd02efee05bffde029a5" . + "3ae1b719eb29026ec5b53c5730aae82863328c1cc62e76d4f54fc7518d19287b" . + "ce59e5ce644ba82077ec26d854efb99d5802f9998a07cdfc1afaa9dc260fd2b0" . + "643267c744c2eab72cdab7d120cd25f13f6c225cb92f7d61e6c944c2974fbf2b" . + "ebe7ec00132ea18797c2bfae5d6b87605061f9e682ce967db912be0687d58db5" . + "b507548b75eb254c9635c5381f8194bbd8beacb482ecfa164ad62d830a2f37ab" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9aae95737c450074a00ba8c9db285c61a263ef6b0c7bc598dc91e393455ea54e" . + "9aae95737c450074a00ba8c9db285c61a263ef6b0c7bc598dc91e393455ea54e" . + "b3eb81b216310202ea3ab75097ed351aa2b7893189f6266248a8f2b58cd87884" . + "05224c4c3c9ea73d352d47ece5d04914997f48f1da994924611cbce36b807413" . + "67727cf5743be98838b95ae4a6d21086d11c98ddd42ac75bfaaf6a9fff4ccee3" . + "fcce2de1aa960865e8dc0e48c712b9c1fc9e3a394f1b7be9667f7a182e4dc73b" . + "ad95d0db5ae5d030a54139c6156419454bc626f273daf9db31a8aeb49fe26142" . + "cd49ac1c7c06a1ad0f8f327fa9a2de2390fea0e923973ac2e38dffbf025f6ccb" . + "2d79593e7e45f96269bcd18814dd97b3c6176979155d7f84f73dbd82529cbbfc" . + "31d236acb843a5e9f2de6490f99557e84a8bd8fdd1c8aaacead0edb8bf1dfb66" . + "9c987ac8f15519578380a021a024bad54f161e7b815f9d71a58c08895a77fe44" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "749e5028c486b9d6bc34b8b05a4c6793fca1927f0c99f6e5f0314cac96a1ec5f" . + "0c1ab2960e4073ef65b999e9ab137e121d4920a2c15c146cc7b0cab4ce4e3044" . + "0b47757a5630e830fc792449f89152d96bce6ed003854c7fb66e594c999a63d3" . + "ba0e1c4308b8de7f4ee386f5a4bf141fb7ef506e459b08bb5ad03cb4ba70a118" . + "fe65d9e97394d1d9d267c63864fda9f35aebb70df5b47f4b599dd0f6aac0e102" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "5fc5e4820319ae86d40c1b6cd31d82a2778ffc942347ab9b6e0743ffeba080d1" . + "28ee26efaccea5934e2410297e820322b6b5a048fc6680134309b29ac054a8d8" . + "005995449c83fd5ad0daeed00836cdc32972df0b21a51208cf5881722a36a166" . + "2325fdab3e09d9c861e0c868ec06bf571907487677c439aaa3f45972f78dac35" . + "caa5a2171a12e97eeb884fe77d30c60d8a04e56c496e1d5cbb6c8b4625158fe9" . + "e1a4ed90912eb28308191df979e8bde495fd797b111442c08870cb039ab2263b" . + "0907e66e31d5b1daa1274a0f8c77c956af19d948796d321708f85a50e4ff406b" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "12174377b036cd17b3e16abaa41491debc6d5af65584ee675b68b0137d8faa9d" . + "12174377b036cd17b3e16abaa41491debc6d5af65584ee675b68b0137d8faa9d" . + "d9fbfcb90673868d9585d3beb1221123d920609d189120283ce57252fd4d8b9d" . + "1c8fac606e17bf39a9747198ac806ff41ab67e22e76108db0349f9fcb39ef330" . + "72af4f28f9a50eae226deab498c4fd754961cf92abb777be74ccf4b2e3dfe358" . + "d0439d11e7ef5ab0af0a662b3151a71651c15fd94d57a856cf2f3d34e73a2bb9" . + "ea9fb4b10fb2bf8b4598ad76b2a4868e68d7db15770d6e0d047e59d89f3398db" . + "e0d060e2728f89dd75d71458bff9883f2c6d17c09249296aa4149d57a4638b93" . + "0b87c0982e2b0b69ef13ab551fe8396bbd74261146444d7b444b76b4bc0b2a7b" . + "6e49118925270afaf8c791b91e5e94f698a1b1785fd011cbbbed6e49fef29388" . + "acee8c0cca2c5f87afd61cd6c01c0837cabda6e8deed57275cf8b61c3d62085b" . + "93e3fee365a973f4299c042218d9624c7ff85c8b42094140430232406d0e3374" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d03833333a047fefa4095b772d34ec9d68b786c19c11dd07fa7087db714b2ba4" . + "1f30ef90ad7c346c4b4e89ab21166f18ec509dc874c21a7e95745d9725e65361" . + "f598d799527b7cbc9c019c6873f5534dfa0ff7f4a9d424b711cc7b868dbde9dc" . + "4841d00b679ed5c9682ef83c1c81093cbaae29c222dd7f4ac205dc74710b5fc5" . + "31780c5c5a6d5a94e1d2842a140fbfa26342c962ca3c722b261cee1d230983fc" . + "3d225dbe72a6089efe63524abedf73318dc567450d4559def147ec64ddc0cf67" . + "a851d0e4b63b00e1399a09eecee535ce039e9045e2b01a32368633c18358a15f" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "f3c87e09bb048d2a3b4519beb4504e8e87024809731c394e49469aaf09d241f5" . + "360c2713510cd98ac67524475a185275dc138f18610370b6825908783a4f3819" . + "4d1eb80dd56c513f80839d40ba68fcf144b1a4579f9f4e1c47679ddf35466449" . + "f8c0e98a5fd25cefe721431cbbcfbf2f6ec4d95f5992aae8ce8ca34834477384" . + "b0fd3c000c0a8faf03b3a8374bc47831e2aec99526b40587dec285e6c23b2508" . + "af439b40e2bef1b7a1305775d96563c1d8fe82e05a212c5072b7c5cbd45caa3a" . + "81622753b2f1d1c97f12a455057b7d253b8698b47412ccc6d3ccfd8ba19e8473" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "23a01fe5828ba27b16bce7f4aae593bdbaec90ad81aa706d60b302b8c55c68b6" . + "23a01fe5828ba27b16bce7f4aae593bdbaec90ad81aa706d60b302b8c55c68b6" . + "85635f310c49ece052a1b6c8860c486c60413aaeab05360dfcfa9e5915161814" . + "ddcb6c8763610d344c8f9dacf6d48dd3834928bbdb4de70c818cae0becf0b5a2" . + "9513468c00651bb46a05965f63b51e4b6835ceb9b6cfdd91ca660db3884258bf" . + "6e59a53d7b8aec521f176d53c5a3b8d2daeab6f8a35f795e94830498928663d0" . + "4c97d995a8ca9227724cb2d7aae0beeb90a5a6805c2934992b9d9667562ee650" . + "f9a2d0428191ac6c45aa32c015119e4bfe641119bb87acd0a053a405293a2fb5" . + "c269bf25a205af6157c553c520e71d74f8721f2a06598b936f76057ba0a2da6c" . + "9b6f5d59a24fbccb866eefc71cd2dc2a3312dbd23e66517f071b1577bc9d26e5" . + "c50e6949763bd4167f1e866aad4210d886ae3a6f6829a9a43203bd87b237dbe2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "52c34bbb535e7584d4a4d865c8e2c4cfef203ab9c0d05dd8cf72ed107f40859d" . + "fb5a9082adf82c910c838e05567dd5327034cfff37e34e57534cd244d6c5fd9d" . + "91c4a1fa713c28c53ac21891b0cf9247e3b5fa70474c1d75154698a68d1bfab3" . + "ca4b44384ff03e8497305b7792c105e2e2d9ebd0eb51d76f29011722263a1759" . + "2bc984539aeadfbba4e5d264ae8534c7d28d5e1c2e16f77dc88db839d4c8f4a7" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "50dac666e6d5ac958909e68444821b448573f7b93fcc2b9a17e80dc38bde3c09" . + "14eea4e5f1042704ba51857bde7590a93643c7123f9aa66535a8bcfc87baabb6" . + "8f9e48ff5cb39f83a7dd78010435226ddb8d6c75cd83fc0a2d4cfe69d8081fe6" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "c422d297945fb3adf28cdcbd834c0d62411291c8853dc797778715a9550289c9" . + "6056a80b40ef30041b0f036cfa15da827e4b1fb86ca73377dfeb470535b2a5ec" . + "36f5a63b54a9bfeb487d6ee9d8526c6c4820abe3d65014e348c93478970f8239" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2bf835f7e2c5ef9f81a023926e89d24edb31edf92cc9cf2e59fb9a3578ac4e18" . + "2bf835f7e2c5ef9f81a023926e89d24edb31edf92cc9cf2e59fb9a3578ac4e18" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + "efa542c018b72f8d1eeff2838f5eee1a53ed05688862df1f9f904f8df04fdc1c" . + "e771a8bb965bfa8a1beb498a2a63d5ce481bbe2c5d4cc382a3d4cf7efb85eca9" . + "40da2d32732bb49f71c13d5e3bb8f516c4e36840e097ce405d221f99550d574d" . + "0b70536cfe9dc86b6cdf0402abf0a715bbfdf85b241c549d583a72c8e2d54b3e" . + "fe0f2de4394665527755087be08984cb40021cf3e43ab216133c30d9d7fe7dbf" . + "a55ecdd8dd74553f2538857bf1ee1c3b8dc55d8f797a498f95a0103a09cf5711" . + "0e03528663c794072f7d46fc150290f5e32d21874623ae9312fb497c5211471c" . + "59cf85b3896c7e1880c3a8f820631d4bc33f2ddf7a6131ae3dfab553e0bab5c3" . + "20710c1919fe17fab6171b93c937bbaa715ad238533e942334934800d6d04bf2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "d0099f37d034ed690c925bf774e9df38cb4519a2186c04b940c269d6082c4807" . + "76262416fcbbe201d50a63f51bbf202c4b54295cead83d11f5ccfe9be162c4d6" . + "bc7218c4f0b08f4d1902fc5973bafab12a597e3c7d25cfeb66f2d2de1aa8aa85" . + "e4bdba72315a8dec65e5449929f0ac233e804bac1d459ddab0f84cecbc3a67b2" . + "7592e8ab7dca4f807f44f04c7a46b11df48a345591117525c3b0222ca255358f" . + "f6c8d7cd4d2553704cf0a771da9d42358cf174af928d9e43e58b292f7c36c638" . + "474d4fe643dd74ce8d1fcc5648687faf27d87d169130012652b4ae2279aaa095" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "fbb8ef873d5b510bdd7d9b034674fd30ae9d4d99af9a653ddf5f1d590b079c21" . + "5bce95853a9b4ae1a1f269e8e4d37a0ee3f4b4f0510ab35f4c3efcb10314ee0a" . + "f464cd14fc43c86fde02e2120e225c8a4397b766c48dc18a94033791466f0255" . + "5ee50e5a9962c910bc83df94ba56a37233ebf8474d5916a28899f36c5043e5ce" . + "d8a87602a4a452cc6f36f0e7f0d1bad31e35ecf04259a0d5289917225b51ea06" . + "d4576e4925ba8f7fbfa4e0575c20cc5c11e562c33c8215a44749474f2ea6ba67" . + "f7c6cb1b918498b8cdbe998baf20c0ad37f7064f08ddb108b2eddadb1a58e00b" . + "51648db51d77b8c0c379b77dee2d7108da4baadf89ae31f2bd158e4f4ba99658" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9cb7b338f7fdd18ee07249689d0bd02e7d19b3036d27876b9bbae556b4cfe6c2" . + "9cb7b338f7fdd18ee07249689d0bd02e7d19b3036d27876b9bbae556b4cfe6c2" . + "aa23a37e3c054c507d9c1ada5d2033a6163169a1276953010e534c51cfca75ed" . + "1fd08f097d9b24596a9e605d72ad3e05ea525d84be9b7aa8b822470cbf9066e2" . + "325791871dd03399773385b245771f25671be7f0c0e347c64c3b2271b0d47b24" . + "fecdd3c5ad934be4377651266953b44775c5121b9e79cd2b7779a90749976152" . + "7034345d6ee536685eae719ec6e07d85984af5f78c454362e0ae2d9192e093b5" . + "3ea75b7462c9bfbbdaab115cff75ab0152ba410eca98473fe2cb14bd1deea665" . + "112ddd6a1bc36266e24434dd603b1e46929c9e36a7bc7a2f7881d8ebf019f601" . + "717a303b1f5f3755d3bb2783a006e0f5b7c5590d6f7a9969d45af80e2c70af7b" . + "d9f9bcff47452e5c3562395661b842c8ba25b007221d6a8d25bd8aac1356417e" . + "c011e6b3741de0a7c70275b90ecc30046539eee8b759217471fdec951e38e4aa" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "f9ac7385683b4f21dc21de6fb61504221c87ec6078f71179833c4fd4e2e9773d" . + "9895602219748947777666742f04cf874eaf312edc8b64f6c8ea7b86294e398e" . + "c5d375681fa3c040c4643f3e3524792a9f30e7ce3dfed7eee118e1ad56e90c89" . + "fa8b0f5df9e7af8bbb330d78ddef16ebbff20f5811b5eabdc1c1caaeae6c0e25" . + "859b6c5706e3a601ceea6688eb80d3cfdff01aaf989a316999663d975d45e64a" . + "31326537a1752b6b824a4e8a57774bed3562bf84652bd2f674e0e4315e12aba1" . + "5bd6d91152ed5476a48b928e7c23ebd66be9db275deff6c86c799e0cc431fbfb" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "238160cb05823d66348102ed58adb571543f2ce783d51af55f140528102a03a1" . + "889e04a38255389396f5c4d5aed18f9d13833b9cbe18f878687d3e240594bc7a" . + "cd97c78fb21e8d6e836089d943a7367878f6ac2239cb74d5c7092d3c12c5e18b" . + "105802fd9e393b3f874d1a1e025ca104f44731e0774ec36a5d5d2b69411985e4" . + "4b4d81bd6b16052cdbde42e4b26a00ab0305614b617f7080bc46602892364818" . + "df0588399180a63c8725a0f5c8affc053e4680f3f2d3ba099967639cd65c0d20" . + "4635d70d3b95b3e8ab8f6c30c9d82e3a3c79deaac2cfdf32206830321e0e3896" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "94319bc995dd144510cf06e4eb9639756b7005a2a9866c6e83ec1d4de7681789" . + "94319bc995dd144510cf06e4eb9639756b7005a2a9866c6e83ec1d4de7681789" . + "1213c7ec14afdcf7118999c40c3ce68b554bed5942ef8579cdcfc93998cd119f" . + "d61c356531fd8e4cee68da783976d4ca9804910c5e39e8f9d28486d85b093697" . + "e809487b69d005a249b2d2613763eecfc40c5ea4ac0e5ec4f812650e142f6ad7" . + "28130bd11b6ea78a3f79e15ea732be1ebd942f9697c21d7945e592d7ec0a2684" . + "4ba53b441711d2e13173de51f6f5c4e947e445fe072870d8f8ee4058b8a4cce2" . + "7a8f661f1f5e20df57654db825b40d70965a59de9ddf8a832ce3278670f65243" . + "8995f9c59bb759aacddd3086e4fef504259f8bcd70976aa14282eeb5f1e57286" . + "3da71e3be2b4100240cfe247895552580bb610c30ac97ed4963df783bd722d74" . + "0b78e147ca3b70f0342adf35f10aa2d4d529112c4803f8faac2bf7b9ea5872d1" . + "3633436950fe8166699b2c29a2e279aa18bca53bdd93cd4213e883feffef24c0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "16b7bc93e649ab6c8f4c9e22a78f19fa2273422866de535900ab8a5e636d8daa" . + "c23d972f082aea68fbbb9a7157e4e32f39ea73adcaaa9645e3c108ec3d9e78d1" . + "20099f9a6ad1c606ff7c248adca6b7da1e1446121b7c796d831bdad444ee06b6" . + "4768d8c985488170daffd98c280be2b8d0b0176e42dd1db2a68226ac89d4eafb" . + "a0b521ebfb10e1e5a86b1d11875cbd920859cffddd7cc7f53f520badb61a819d" . + "3b75bdf7ef3f6db2f275d56cd4ac95d8df2474b4357c449a65df376f8f0ec4b5" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "64c9d8cb50fadec66ee2411f4879ba14792fecfe8a51c49a0294ec917ea9c2b7" . + "fce2c5d3eadeebec85f5444cca587f368c3533b92a2895ff8f49bdbacaf6d1f4" . + "bf47e757f424094ef7eb5e6a03fbe32f9167252f30f8c10cc57cddb10283ef21" . + "7ae73dd18f650dacd17d665a5c06ba64417a234f93514af1a499469c0071bd51" . + . + "64c9d8cb50fadec66ee2411f4879ba14792fecfe8a51c49a0294ec917ea9c2b7" . + "e99494e6fbfdce4b2a35792b7873c9008ca217e8601d95c467e2e8a98dbff13b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "152905b850785c7b0a1a53f98d9fb29de3512d9530f037e6707f29eacbf35409" . + "643cab0b7b30542cebaaf9b6e7f48ac1089fa932596e85b6323fe2c2672ed85a" . + "0930b0ce23a87864a5e9a6e56f67213e0cb3d1733b78a498ca5824320ed2e656" . + "b9e41b9987c2f95e4d9600d789a8edfd1ba0c5ba15636157b51b5a76cd23582e" . + "b09f6f22eb3b695ed1ae41352d0f02c8c9f56117812a0d58b6fab3fc951094c4" . + "52b07707437ee2c6f9550e8318bb9e8f184ea2158ea2bb78b6d5c3f79aa90ab1" . + "4a1eebc35094dab4a720a1dda22f92b9afeb9ede31e666654502acfabadac614" . + "a75ebc430b19f9e9c958ef4fc800817714fff2e36d15fb6a7081a6598028a669" . + "17f9d61b60f42075bda73ac1bff3d42cf1b04c64e80f6235f1519b405764cbcd" . + "fb93de74a01bd28fabb32a51c088d00cdc0cf435277cafc50be2fc654ff0615e" . + "61b6ebc527a4fa924bf5988413ee35183c2afab2a4d3f051179479b898c42c42" . + "bc2cb4f9cc4f3c9c7eda189c2662ac44302ee872970b5dae2dc1249d5ebea3b5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "83a6d61550b4b44cbd74b31eab89d930aa152bbffab21ece0a7fe9ee0683ce3d" . + "1b769d114203c35641dfbae731511f94406835137e4dc7517a9ee307bdcc2aa9" . + "4378200a9717c0aedf2026f3c3c61af017e1fe5cf059a156cfad6af4407ce778" . + "7ba4d0662c23ab26d651366448d1cb911b5053594882bbce27d9a46b699c3e5a" . + "2c41947f7eaaefa88c17b8fc15184ae96e5bcabc7e28125c940a6c7ee11eefc0" . + "6d41df636309bf52a87e74e250b099ac9df9a432508555bc08d8aa98f38a09e2" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "9f0af01ca675d39edc2267c47e7cf63dea9c83cac88227c6c97bc7b978c9622a" . + "4db7176a2e9dba265d8d8528dce7da2340cd291c7abe7b748cdfdb4af869310e" . + "7223e171bc393a27019f00209e80c4022528d023e339b337645c8cffe564fcca" . + "5a92f783a7b183653ac11a41ef7b5a417bb5bc46c63d545b793307ed5f5199e0" . + "3fa3ede84d5fe7517121e3b38c3a04d34786ae54032078b6fef2a013f412412f" . + "32aa10ddf4f3eef5e37ea9fe73e925759e197e7848fa6cecfe67b20fb3bddf45" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "901f23283001549dc8bdf8b9886c6b99f9425369bd8c8bd231f34ae952dd3ac4" . + "901f23283001549dc8bdf8b9886c6b99f9425369bd8c8bd231f34ae952dd3ac4" . + "9b2d33e8dd9c9eb5ea7ccd167ee543a733dab2c1575c5bfb55e7b0eadccd82ff" . + "2684b2b64a4e508cc0f7b627265ffa39e16989be47109426edb1b4e2088e843a" . + "cbea04df224e6fb26cd8742afd64f365a9731ca894693b8405b0f7eb33592dcd" . + "868bd8c7fe068bfb0fdb72932831adde150ead45179b06b6b1b4ed5837b3f882" . + "3110ae1741e2bcb5262e8e1cc41097e5eeaa3c6c5757dfc7b859c51eea6cf9fa" . + "c6978179d98cf48b9ab8e57a5b45043a835cfe9b3b397093820f47e9b1aac145" . + "35f1829ee7803c778124c1ba28ecfe82d8da7734b51e877a5c16b1b7df75e13d" . + "b931b41b1344cad4130a162dd35ff1198566aa931018366038925d70b60b4143" . + "fe6e42bcc1b7debb36210bcba465206d4aa4ffe8c5c5b5dbb300112abd6defde" . + "d3be47d60e79423c81d8699afbff2909f6a0f97f2a0333a5dc419df99e22ee96" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "374ec3734fe166477fdeeee64688e4545c5f2dd15c31164c0948cbbc82d23d6f" . + "5061cbd09e6c7788df7470d3a1d589f49a9ec0825e75b4880701fd04d47c48cf" . + "26951f3eb70e0b7d21479dbf544d67f34db08fb17512f699e3f7f8c35c455c47" . + "de1d3a71ac4529c2e6c2723a7dfa6112b95b42acb7ae9744a0f9001c07bc8e93" . + "5aebf67a37b7d53cfe63372246280ea70be3fddc9f31b4fa2f96fe47f23fde03" . + "4841d00b679ed5c9682ef83c1c81093cbaae29c222dd7f4ac205dc74710b5fc5" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "d3dfc4fdaf7f481ee489330dbe611509a223d027becb5c36ec31df365783eb4b" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "39bb54fc1a75954dbcb03888fa15676fe02e57e4855626ad8e88e05cfc2b1f89" . + "83a7ec0f3e858c59429ba5b5872d624249eca778f4b779bd68cd8b7aa381a592" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "6f5a28d7602928196f355b587b24a86198c091c944c0ed0a0f1f5e1c29ed0cf6" . + "7cd7b96c375575755ac2aa2e69238f19aa21cc9c4520125aa3d7ed7b8d963366" . + "95c3df903be0c4a7608e76a9623b43f11dace89abadf0ee316f7c4fedc3418a7" . + "de4c00fc106b5a09746d623a0925f59ac5d582b8cbf419fa21bd8140afa33976" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b7d6e9be2a5f97dc3165eac4d342bca2e551bf73b2bb46b9ff7190b6e78e877" . + "9b7d6e9be2a5f97dc3165eac4d342bca2e551bf73b2bb46b9ff7190b6e78e877" . + "3ad396519a8763750875fb313734c6632d76cdd9774e7896e742869da7f5df63" . + "d5e6b8151f8b8959c7099d106a6fcc76ddae95a412977e5795af8dd54a625892" . + "32fa3a39c5975dad623eec67a0fd740f060bfcdb4113c6c4783079507596d074" . + "075cc53d10aa6318604a81acb066a746c97bfaa9f6adb514578d8e8562657c0f" . + "9de51862c69a9f9d67818c88bdbe11d9f6f1057e37b84f6b32dd9fc2487f2460" . + "817e4e4ec6ae9cdb70fc5a22560bad192fc0bb9e32e8d47d9f6bf4de8cb5d4f6" . + "b960b900e5421ef78659660cef4e2b40a00b7605220085e616b80c10d4e581cb" . + "85f0469c3392dd493486e1f05b1ca9e8c311d000912d31d9010165b338e017d5" . + "73bb3eff664a027c0eb7fb48af36abf897e7519357888385c023d3deb120f8b9" . + "dd97ce36b3faf186f893f842124519f6fff4e12009b92f1fb59da98c7cc63d97" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "4659aa164619da32648a0b1268de6082e9d5ba7a1582449ec8c955b08757b595" . + "e7c80892af9c077174ac2117a19573408264ded4f355471b63a740834c281494" . + "9e15fc11ceb2cbf1a23fc9a7da4324c82ff0ca8708c31c97087420154898be66" . + "b90e167873dcaa4547f662fe9eb99e36352c6215fae2b99c51b4a495951a3bdc" . + "634c227a43f3e4d892bfbfa8a74af3d22e228b1db2f699a6ba4edb31d28b7b77" . + "ec86ceecd6b751975b84e98c389320b243c676c413f01ce8abb36712ca493f51" . + "1f7a979d2e4c0279a9828ee1bfb1afc55c4b4301c97e4096f3d275433febe5af" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "8c5ea3e6ae42913dbef26a6e8970324a7df24b73bcbb6735178f44e383695906" . + "e628f728f4f923c7eb2e0842e6aa5b9184f8003daa45b3dc87cfb10e914df1a3" . + "88d90ffebbda29f629e13a66d5436a28348c132c61587f758df7d094f8f7cd62" . + "27c3d37ff1e602093b708610343aa2446a0f145c0556ce8978e087b550bdd25c" . + "b77dd3d9f034d70639a615a34506fa9d56cde5d0ecce6e1a01668ba77e207ba0" . + "d45287ee6bd7f2aaac041286fa3dd83c9952ccbc3fc8d627355e9891463fac8e" . + "a9426d44fa8d3eb6d9b83c1eac1b29ef033f6d97d3d85a26203d59249cc228dc" . + "29990bc4a24c6315450eeaf9410fde4e9c030c6ba4c040a84ec0bffbe8f13cf7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aaa2468c01fb8a7b4713d198eefdb0c3ebd0d4be5807f5f9ba58ca3f20caf72c" . + "aaa2468c01fb8a7b4713d198eefdb0c3ebd0d4be5807f5f9ba58ca3f20caf72c" . + "af1cb8354f5e3d3d82107fc36a50dc5b6169e6bfb47f6027bc7cea78637f767d" . + "b3ab6184da2fd0c53cd0f4797899d838e79dfa2f90df81aae3d6a1c372a22dc0" . + "19a78fb6c72ecb57eaa43c4fb708b8031aa8655ac1f985062f8ded8325c96b5c" . + "7a616ca96ba689c60a53790289bc2f8773b1735802bd486d0651d1c931b63b56" . + "c3ed93da8bb502ede44adeafbc33bd8ec053e04cf57f96ea584c7f49851d6de4" . + "9158cc98ac9dbd2e17dee448501e5d8db7e6f86a93c2086d242eb70f6e1e909a" . + "c77f532d8a714223a34bb215dbdd8c9fa8dc3b2bbae3d64da6c3b54ed8702d23" . + "6695b4c00f4689472cc44f0e9c9e418d151225032e3eeef76594c1df3345e6e4" . + "b51b23f6c54359f6534a12213bc8214e4819114d124e69bd1f70ce5e3f1b5305" . + "da0cdf6ab7c62a4190d5a1e42b445bde41913422116670e49bc6d0cbf73acc30" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "78982e048e6ca4436fc69d24dd0de91dbbfe809669096e71ff11d17ebc73ed06" . + "43e8ea97bc70c00826ddb27fcbce682eb74682844c0097aaec0bbc912c2e6fac" . + "72fa5da52f7342380fc623c03ade1330c3a6ea6096f690991886ce7808bc7c80" . + "0ab17afb2088543331c308525d06b1be9f3df0dc934d486a1b25b740778ace8a" . + "486b511598710e2d4f6b15ac098816f5a666bbc9789ea064056c0f4bb6dd9c86" . + "f9bc702766f39f58a9c9d624afafc40e288797034b9e2cb2548add299bf00355" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "e2815de1e36778751481cff67a0dddcc76e0a9e7df256898dff2bf6058e31d6c" . + "e4207c29cece3dd9c9f2c3f686a162256e0d72ed9a7ebf8502a9de6ee0bf821d" . + "851aba0c22b41cd68549b372ce8522392b5f2b000fcfecb9f7672f0210791ecf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "bd14e31feed03aef6c5b177233a658b61764a95e4651f65372f96b4554c26da2" . + "ad91c3832171e03262c2b525cdce5167db343ddeddf1f5daa3bdddeec2698dc2" . + "980674906345fbdaf4f3591983f8ce3562872aafc7b97266185317d7f9f7be39" . + "6c9e4f693f55c4f6a43aa3e458bf005581305cff7ab691c9c777a25455af1f59" . + . + "0b3f60ffa1dcefd5f89a6db44137ea80a28a10a8b41a40bb16a6911afebc439d" . + "d58b27c211c167de7276015a0540d190f492bda543e4da8535044a39e925b744" . + "82bb07f31f579764e49f58aadf74294e86e61fbc090ba0ad1c5de9ec917569bf" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ace0c09922635abfad1e245faac7b3f9949857241490ebc22b731071522c277a" . + "7c49359da167470d15f223bb219db5b718aa0cb29b7db32650799269cff4a1f3" . + "7e5e29b650361dc86ca877b45e524b30e5ecc019ad1161ae3ac64f7b61d39b10" . + "08de595bd48a57d79751f54160110ad78151340bba71ed4bb53f5cde3689e0b8" . + "262d83d4bf0284efaa182f41bc916b8d41d10fc5f7d52338e86ab41e0411af7b" . + "a50ac015317ba8b256777e0314791fc6a6ecdd4c92e5b5a0c2d69960002c4978" . + "e45c413fe057f063ba9005ff6317627e628f4240a9865be4d1ca9e1fcda32024" . + "8720e50480a01d728d0510bd7fcea41c0d6266ed99815c885a0549504e644690" . + "5962e9bdf23f0f7a265a429233a534484c23fe9719be7a5072f43984f764fe88" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c1df978790e706e1aa9c9cfb02c2cc762cd3c2ac220b4931bbd0d6655f92e52a" . + "771786602cb63c6f6493cddad1429b0c73f80c40ba766a4fb116c01f00107dd2" . + "8515f7671886568ba438b0a629a52cd11922ce004bc19364c23cab26af342c88" . + "118792913fffc45a6a4ef1175abb260631338f4d303e579d2c5f4e40243a1640" . + "bc1b83ff529765ff5fe0a9c16686791ff5be5801016527b081645f6fc518d7df" . + "582a5a2f6d26360df50905106a9c272d7e2ed640d8e7a90b7061194dfa1f6728" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "2378342ef65d22c36eeafd757617063008e11b829f5e59b215962b186c11a617" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "f7f7507104e5983139b63c8b8a287e81b2231cc84e8da004d32b4bc6eea3d0fe" . + "0625693bad72193f0277cadf6abaa09323eec90e5961019bdfe9dd2d454832f8" . + "a4228e6449a3ed551300981706c5b4d155409519e20b2aa4cf8be00b5be67361" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "034b348cbbfd60755e26e76a4843d05c60d803bbbadca45a4ff7702aa5720237" . + "17c24b3ca926c60190d85f7ecbbc981aa2a394ee2b7c100d5eb8548528205b86" . + "0907e66e31d5b1daa1274a0f8c77c956af19d948796d321708f85a50e4ff406b" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fb6a16e0de859777136d71b052326bae9aaae41bfe4bc7c9890301ff6b038e29" . + "fb6a16e0de859777136d71b052326bae9aaae41bfe4bc7c9890301ff6b038e29" . + "ca654e57ba20f7145f4a7f08d1a1a9444a72d20a06e58b94e8e0167cdc49bbca" . + "89dd199f56b7cf32c29884acd946b43e34ae9cbf470c1eb8fa99a5327d6dd001" . + "5e396a5eac145cf76877e6a50c76517e7248f9cb2e5e02f6e0cd48901ffe4ef3" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "a935c31a76f22df50d3184d715d93674b362aa6633b5fa7dc8462981cc77c640" . + "3cbc8a5dd057036dd50995a60fd43a30821d7c0491ef3c41a5687f624ecbb80c" . + "e0b83c9ed5232306f5e0f57f59ee97c916ac351ea7c9ca388312dc44ffd970bd" . + "36f059d781440baa2022549b717393bd3fdcad8ee45f9db7799d82e792bb601a" . + "bc437b496a8fbf1c57ecc8b5ee3a7d896d5fda32b97904b42df5cd753f101284" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "665e00e2c9a55193b60966af95ee3f68bea484747179e2e209092cf806c2dddb" . + "665ec8a0f2650403c2453847f3457f2261558fb5293d570361d7749f50c784d8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "af57419837fa322799c51f3c88fdc43d3b23595e717101a4003f5e3921a0640f" . + "8ea3f18dccc27aa1dfbccfdd595511f4cee0802d5f33dcfb2ca9b8a7d4d71f87" . + "54996a81ae3ecef50a513ab01dd1c358605a52d6f84d3dd3d71692b822f15a25" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "4fc1b5ced360b28a12bf907ffa2b6092a64b92bbfc64682bf35e320c7f28b5c8" . + "8bb1fd16e290f3606e5953fc61128115de9442b9beb8f5858a36481718d30333" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "189d10efdbb6513978c998e5e982cd8ca964311e4ec9ad46a128340b6a6c40ce" . + "b63a196ba272f1e738f88e02ce588a2c44db34e1b90dba1809981614e59ae498" . + "3cd465f81d54bd3cb1ce6ceefeebe4014bf955f4298f5ac3c2e064b7cc50e536" . + "e23d08b8159da97320002e9ea2ceb13769d0a646a249fc2695a45ded8d7c7af9" . + "b7c1ccb5006c7aa09a8be98f15e35cd1039da812b04224194c60899958afc112" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b96ec83c0b0e9066fa979b25f1f3ed52ce9c2ab65466febde3d4fb920c2d92e8" . + "b96ec83c0b0e9066fa979b25f1f3ed52ce9c2ab65466febde3d4fb920c2d92e8" . + "08cdeab113d093628854c7bcf0c202e15d6440e120366641d0a0846e199442ed" . + "63e96eefde33ac7af5f3d28aa54f7401cc68f8ec92460024ae84e214a31763e5" . + "e458c8c4edf2ff7c3221c2917c5774d45437097aa16791cdabbf4fa909855cd4" . + "0d7f7c92156ad8e0bf5cc4ebc4c602aa844c6e4e449f7f5ffc0b4942e66be6fa" . + "7b00dbe1e1f95d8d810cba54c3ae3788f4a8e719b35c0ac7ea8ca59360172600" . + "68aaa479c64829013ae226ec1af8cf9aa20277ef5001b8095b67caacf21ea24d" . + "ecde474be05a27611bb2547d2bc2a2de3ebb1ad354252c166b58f7315a3ef9ff" . + "4e4d804437419f346af9acaf6fcf7fe8239d93ce6913305c4d118d87c6640d64" . + "b2f8c281859b45b5736c1e628c3ea60f6db12d82c837a31a08082dd50f198094" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "f6c8d7cd4d2553704cf0a771da9d42358cf174af928d9e43e58b292f7c36c638" . + "d246c1c895fcc3bd14918133f8c4b5f18d63122d36229417571b8f7cd0426166" . + "1191a83252905be68fee061eae906f644a196fa95829c1ee909f945b02413d51" . + "953a7357ef1d11d0ccae76d4d629dbea87c84ce4fa942ee06b54a2b953e24854" . + "7778aadbfcf43f710ce2df66b90d07949dab6fcb57a3d5b2a4f2c0c10e009cc9" . + "733b591287f39fd61150ba1895487ff35f53152cf62da8552a03a0b9b98a5d59" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "3fea7621caf2537ac4a47bff4080913336539d3c94ca68c9c336f3882ba1c634" . + "ce0673762fe398801349c01fdd89387891e071a897045125a18086348125a339" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + "8251ebe0f4941e3831bde8532ea63c6e4abff6d6afe7db3f97a7b4f1909a55a7" . + "4c7dcb26620bb35abe8f9bb7a51a085a55ee3157d7b36195222668751517c5e2" . + "689895131c17cf3aa0e7b9f17594fcb1ff3e359ccddbe90130ef41c7a27c8e32" . + "24170f5927c8fd937fd786101c75448b1c18bb7c42bcac54017a170bef97b138" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6b0ad5762109426558b06dda5f18f46ab47122eedc465df10d134072b9059840" . + "6b0ad5762109426558b06dda5f18f46ab47122eedc465df10d134072b9059840" . + "e3dcff12f1270c255c7e5649ae5df6cd631cac3c7f3b3fd1a19f4fd8cfaa9488" . + "b5705aaa60a84333f8fd105d86c83af184b52047dd993092b65cc53bde79077f" . + "eada5ff5f256e681137698aaee5944a94e23da5af974083b00d68a7074cb4696" . + "67b0e5854197cff37a6b0e9120ce80e53923156d78d3f9c3a11f83f10a06cf89" . + "e453544e5c6085a95646cf7bd0007daf5a39cf18f39e6539ab8a723ca6bb27b3" . + "c70964feb214226c42c0ac561502d3daa517256f0f813cdbfe289afcc9f93407" . + "8313a47218c2555738338f9d5a888e0b54c39f3e4136c51baa28f99477332ff7" . + "77dc471a47edb90c78763f5be65d91708d24373cd027b1ae36eaa1c6be7f1612" . + "8e7dec460e6e0a354e4eb7ed154d6e23ac8b5651a8a9d2236485189ecc1fe997" . + "8f7452b17642bac82389e4af67e5614dcc8249fc8b8ae0e807e759e4b5dac273" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "923f549e3fe56c21e765fad13da8d4f18a843d504856ad0980b266cbd717b797" . + "713c880ba4eed65767a71d74beccb758bed760a608bf74653dbffa6b3e60d41f" . + "58d5ea4dd0bf5c59d1f9aea15a7a92f58c3d47c246632e3bacb287c3aa3d2928" . + "76cc6e30b2580bc3be18182762cbfe0d9bd495f35cabc1fd73962adf15928608" . + "f7fb26ccefd7d1b066dd1823008afa4e4cbb95f812792adc5804308ac10a07b3" . + "c5019e47286526a170c93205389a827153ce7a2267709ffe9b64b2806b15604a" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "11233370cc9f6a8ec7b7edfb824144585d86aef9d7cc4278e8697301e6806666" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + . + "8fb3afc4fd5b75c1810a7ad77e47248e7fb008dd2dcbe4e19714eefcab6b8757" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "638e92ba806accb1e9d588efeb98c5e2add767345926b388119fb2db742b739e" . + "8f5a3f620a343f61a344e5b8e601579b5e23a93e8a32081e007f2182f49029a8" . + . + . + "a5a6a4276b67d15829872edf3941026f347ef27b6d8a23b5f8122d8944efdb8b" . + "a5a6a4276b67d15829872edf3941026f347ef27b6d8a23b5f8122d8944efdb8b" . + "c71554c540717ae8d91b72106f6da545aae60b3823dbd5f4184f415c81c4176c" . + "c71554c540717ae8d91b72106f6da545aae60b3823dbd5f4184f415c81c4176c" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "5b7bec0a7de50082e677c6839b7deaf90bd26eff30a3947bfff1cdd912e9aaa8" . + "d0741d879c5ba023272b51280583bb5a6b7d53ebf549c5750a50a63d9028e2d4" . + "a5a6a4276b67d15829872edf3941026f347ef27b6d8a23b5f8122d8944efdb8b" . + "a5a6a4276b67d15829872edf3941026f347ef27b6d8a23b5f8122d8944efdb8b" . + "9a62000be9bc8fac7cf88ab51cac7a72551f94fddcf7d5c2c89924896ad742dd" . + "9a62000be9bc8fac7cf88ab51cac7a72551f94fddcf7d5c2c89924896ad742dd" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c9eed7739456d01329f4c8ccd737c7afcc629353e4d6670afddbf0eceb136094" . + "c9eed7739456d01329f4c8ccd737c7afcc629353e4d6670afddbf0eceb136094" . + "c9eed7739456d01329f4c8ccd737c7afcc629353e4d6670afddbf0eceb136094" . + "a33b42a342b6a43d32d59c90da0a49cdc68a27ede6f5d473572357bfccd602fe" . + "a33b42a342b6a43d32d59c90da0a49cdc68a27ede6f5d473572357bfccd602fe" . + "03644ea8c90de3c20a4e789ba5bce40b24b57cb8cf12eee8729010c73f8de001" . + "03644ea8c90de3c20a4e789ba5bce40b24b57cb8cf12eee8729010c73f8de001" . + "19e025dcd5d9e25544bbceed6d9de84eb0ce7a36604d4444de3d865e0f4766b2" . + "19e025dcd5d9e25544bbceed6d9de84eb0ce7a36604d4444de3d865e0f4766b2" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "2a5f5de3fe08662e8cab9f6abb69ad6ccaf42eceef57551d3861ede489c015a3" . + "f92e40da5540c9d5df18328d4204a5114318f12e6f1db9f402b663671e98463e" . + "7736b7c3fa7daf3a3eb6d2ca73b503bfc6b996c18ac2803dac22c3d143e2bd13" . + "47df98aea74d58198fa1ec19097c99e48fb93c0e122ca2308c3e5540348b8ce4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "151a3bafbd5c6fcb2dff00ec35f2de63bd46639c6878934e4a06a31b25842603" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "8d83af47468813e862001faf8f92360705666baafa9de0af6f231008eee091f6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + . + "bcf22da828b0e2530008d8c4cadfee0165a6a7faa0d8f762464b2b1d2a49a6a3" . + "bcf22da828b0e2530008d8c4cadfee0165a6a7faa0d8f762464b2b1d2a49a6a3" . + "b67b7d807e6a3542c42b8246e6d1121181349228464c23e0823650313383bd61" . + "b67b7d807e6a3542c42b8246e6d1121181349228464c23e0823650313383bd61" . + "a9d4c2079d327f2df9ddd7d3fe6fc650131cf7487baa1646b24ba65ae9df4c47" . + "2b15ba655c64963bbbd05c27611eb36e14b30ef7abe854e82a40f8b05effdd31" . + "3a2197f0e3a4a076d623592dc208e1695172aa465d2737b1e60824a56bcf1125" . + "859c5834bd5ed736f559534f8e087e7aa0fc45b0aaa208b0e9fea3d8540addd5" . + "a9ef8fee8e17bb2f0d8232841226eac9f3c90c5edd5b7d6d3afcc4e5498ad409" . + "d8513be3e9444efd2f054b7964b302ec9966a5ef91a098137f29fa8182757945" . + "4c2e0590aec19a36bc03f114eb843776b68cefee53c13c16a8fd14351ba89f11" . + "08204d6ba60283d9385fea54e7b24af41bfb6f2ddddb1115e72c5d0fd48ec182" . + "cbfe17c7e61dfd9095789d3bd15408c90c84894efdb7a6b0c5d7f13f61ec844a" . + "15bf0c6c35426defcdd6846bc78c312dccc8b8048f03b39987f6eff1cc11aaf1" . + "b0f8d136e243b0ea538af8fd793cc33cffeafa1609123b5d53cb89adf73b2dcd" . + "dd6693b9948ffc607fde2c586977bc8bc5efa011d31ffeac0aef828c74d6b693" . + "c7232897369df5a5c9e0910ed47aa49a8905e193e8ed2d4af26dbf5c71303946" . + "55016f08078069b7811a22ba743a1bf32354a2c2e7babff84c738101922c97aa" . + "1e89447c5ab446c453808425235503ec7f0ec57748a97b191a4ea75fbd53a2fc" . + "ac1ca8369c639b784d1c852f6d21b20a85f02388ae62a6a16c8cf96c97ace091" . + "2f5d8d65330a7019fdd5024e76b8e22a8f00f67acde2b3bd78f489ed73419a1d" . + "529d0f5f8069b1485bf5e6d41922f85c0bdeefb7d9bcdbdc224cb865ed59ed2e" . + "b7992968d311b4465f388107fa785d7590c2c00473a3dfb21e787a4dc2bb8f78" . + "9af50af66d1188043263b794c2524e31b99db9bc3ee5f541eda9ac8f42d732c7" . + "68496636704bcfb0741800dd820bfb68b43bca98f05c7a94c00e32d3aa2cb812" . + "08340446fbfa9b0fd3b0ab36534209ce95d5ddbea35f5c381172260b9306fcc3" . + "ea1903d98241f180a4609e9f0df2ad89b6b5a3a3ce9b9841ece4f0c6c382e3e6" . + "e06e0dfc25dcc36ba610b37457dd05efe8a75acd0db39970a25d9476bffccb3a" . + "35552c8697f07ae58df836ccecb38ef2a83240a9f6d8bd96c33dbce7ffa95e39" . + "921a4adb805c2ea667933bf27cdff83f38128a2832e8e0b598bee9da082297d1" . + "921a4adb805c2ea667933bf27cdff83f38128a2832e8e0b598bee9da082297d1" . + "576d50089fa4b14bd72124482496023dab43c1031e6125c997439ace973c5ba2" . + "7a150b33d88dd89e26618248c7d702d22c9771690358c89bf70aa293988a3102" . + "b5a69f21f0e8a03d3ce1c567a005b2a2898bac2034352f6a1b40530394003bf6" . + "1566fca2edf0ffa2786cd1a72721aacf7084a78ba026e842025e9e6e09711d62" . + "99faf3a860fbcc9183823156299819861d53a3344466b291c13bc1bda3f55304" . + "7fe01f3aa1411a55694feff7a6159c4ef1f938689d15deb7169bd336276561de" . + "cc37919d239430c256b7d565cc3f01cefacb26eba77bcb2fb799bf6f0bcac28a" . + "31dc939b07c51d5661f8d740b488e965e0304025a597ca304fc81e1480e1c420" . + "25f24436355f89ed83dca7e9e5b391dbf3c98d8ed25689cd384b14d58dc78f92" . + "cd8d3d8009e2b73803230eda974985c76c0778d4774723278fb4d1c7ea157c07" . + "0e44e81b1046c178e66b6fc2b398af62c3cb52a71edc5165f0cf5a0545fe8079" . + "a9995588af2b3b05ce298adebd3adc06ae287065dea918cdab5d900fac5bbd4b" . + "4bff0dbc6b3e5ffce458cf43260aa7e6bc76cd18ccd46300e3cab1e0ba06ab02" . + "caf09f2000816914f77e3df9d47903133d510d758d305929810e03550fd1d50a" . + "06e0c4dd158b0098f55049820598407d299c6444c11658703817b26889dcd403" . + "996fe402f7b073743c401eea1a2423e14a31986970396001702f35943e18d0a9" . + "a5eeea939f558bf1c379009cb90fe27af796459489522b8310beece0277a5578" . + "6307cb72922771b4690b28d5bdc6f6e54767250b2bef9a564ef748f073a7f1c0" . + "3d6e008dd3aea6426004734892eaa0d6149f196a05c19442b2f1f671ec936c0b" . + "1d78ef30a742f433ff7fccd6a5ea77f3b8901f6f2507f37d6d2ca4a5a16c750a" . + "db94252176f9d9d7e2094918c221b642427a8df5307433995a1290249a7587a6" . + "ea39a39757e8c5ed3ce801cd98a947fb5fe08bea98ab53ef305495017dd51cc4" . + "b702a53e257f6d17e6279789dcba5f2e0a5d5a59392fe5eb60ad7578372e6d2d" . + "1ed17fee97e301f8555f536324c79233f681b0248beb5bfc0b023a5f6364a88e" . + "13c9e67c617b6ec16c11cffcbbb26cfcb5fd119440e6f59fe1156113ded0581c" . + "74fca76ca1e49b33e5f943b91049873f9e97606fbc01a171d715ee459724ebb6" . + "d34cea4fda6d3cce781656ca25349e29a026182cdd1e00b91d918af0b944671b" . + "09b0fb8938564cb19118e1c75262c7b422277382b8f9da1967947e50d56371c1" . + "79c676a8c23b44fe80ba05204402221a16e1d3482b239eb974e7d58638688cfb" . + "1f0a7b9f32a93947f3cf88ac021dc3bb94689ddb6043914d24634330c8daddf8" . + "e1187957b51a6614c92837c3632eae0c97d66af9958fc4fe3717d0f64d7c820b" . + "b3b39e8e093b3a7d0f981553fa19b770fff1f5ea4a9cc0eb2aabf7800d05b780" . + "5fd1b2a79d02add14c2243ae5fec74c376b54654bcd841fd462ec2a3868fce02" . + "2bf8f555e78cb1dd2d2d39330301338d5084d9e2b3800db4caacef86e3e7850c" . + "112889803d8590b43cf669a5b31bcc545af8d3660097b325c0d85d6c00c722ea" . + "6fc54e70eee8162867b5848b8ca216d48b54254700a007715b57fd1c975e22a6" . + "d579b123ded4f286737d823dc1073ef9c2e09b4445dfeda7c5479ab599309c5d" . + "1c5f38e66d5bf7217a48d69c0543ee5a8cc3b8f211195d9d7d13333cba2d0381" . + "88a08f02931b78aa3229174a9af28ab2a139dd43c422d5d3b0280aee7ecfa10f" . + "ee32b0febbd790e42908a153b5c27252fde64a5660752cdef17c7235c66498cb" . + "afb599be060f90162707be5d5b4540fae062e4271319fab25c2ab9ceccbf1b8e" . + "0b437c5355fa5d121069638733aec21370daaf6da5acae058bb159281cc55d6c" . + "1a19d5f007527486633d285f7e97fb2037cd9f7f96a6a7ad0a290cc0e5651a0e" . + "bb80740dfd7d01a555c26916467256f2c187795c7defe477cb265762a19d8e26" . + "17e69911f41f7dc391ed2514fbf79d7d1ad3b6050aa01c1df61d78fddf6cd83b" . + "bbac8a915f1b49557fcd518fb22436d034377e5ce682d6d5f636531d89ec2262" . + "1277239e3e31cb686e160b39e655e548410742646b2aaa0b669dd6d35f0cd516" . + . + "ca6971a700612cd2e430e9b42b62958aea7c48fad49ab8c0a42d236a4fa47fe4" . + "ca6971a700612cd2e430e9b42b62958aea7c48fad49ab8c0a42d236a4fa47fe4" . + "66ceb086f17a1bd7879697571d98504bdda0808b8593b182b0dddaf0683310e0" . + "66ceb086f17a1bd7879697571d98504bdda0808b8593b182b0dddaf0683310e0" . + "a5e07e9c642647ebc328de31bbdb60054724c5e6d908669269a2330a30a370ec" . + "a5e07e9c642647ebc328de31bbdb60054724c5e6d908669269a2330a30a370ec" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fa6436bb30e4d3b11d0ae04a5aea074c3e4f75ea398e1158b68f225fb5fc7a41" . + "fa6436bb30e4d3b11d0ae04a5aea074c3e4f75ea398e1158b68f225fb5fc7a41" . + "da0dbb009c900e89c55339a219eaf70281dfea437af627b278fd868bbfa57799" . + "da0dbb009c900e89c55339a219eaf70281dfea437af627b278fd868bbfa57799" . + "fa7580aa69f28c20f39d91635bf7774225db27133fa2900852e893eff230bd73" . + "fa7580aa69f28c20f39d91635bf7774225db27133fa2900852e893eff230bd73" . + "b97e770e4c91f042a5db4179738ff82345a5c31ac69906e44120302c6cbe65fd" . + "b97e770e4c91f042a5db4179738ff82345a5c31ac69906e44120302c6cbe65fd" . + "2855a38e38fb4fd6de1990902550fe12dc6d925bfddad9f4d0d3aca115df76ca" . + "2855a38e38fb4fd6de1990902550fe12dc6d925bfddad9f4d0d3aca115df76ca" . + "04c566492313e983d9f4e755c4c4c40ca3a3dbd4fbb4b8fb9b86270adc513192" . + "04c566492313e983d9f4e755c4c4c40ca3a3dbd4fbb4b8fb9b86270adc513192" . + "e3670de04339bfa2f97788d62fce2e0e008ca388b11d97cb2447707c90b0b5e6" . + "e3670de04339bfa2f97788d62fce2e0e008ca388b11d97cb2447707c90b0b5e6" . + "e3670de04339bfa2f97788d62fce2e0e008ca388b11d97cb2447707c90b0b5e6" . + "b305080cc52e852c1117b61b1c3174fedfbb2dac0b1ce75d28cfb62a0486232f" . + "b305080cc52e852c1117b61b1c3174fedfbb2dac0b1ce75d28cfb62a0486232f" . + "874f65a59333fa8300ae1c78f4913437360c2cef68ada23c97d2226d797647db" . + "874f65a59333fa8300ae1c78f4913437360c2cef68ada23c97d2226d797647db" . + "6b115697105232dbf084a4fb9aad1a4c2343531b4efece55e19fa5e06cdc7227" . + "6b115697105232dbf084a4fb9aad1a4c2343531b4efece55e19fa5e06cdc7227" . + "913289c3752264e7cee168c809ff58310d4ad46705333a72c4e628bf70c71c7b" . + "913289c3752264e7cee168c809ff58310d4ad46705333a72c4e628bf70c71c7b" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + "112ebbe930d8923b57cfdd2c649aa194a403ca6db0561c7d4bf69452cc4a4e20" . + "95bd6339157e328fad8829d49c4771cbb3d60588ebf0dbf84c015f794933dea9" . + "f5b98bae1cc2e293f4259181611db1ab5c39d09a4a39c2ac8af1f9277092ced9" . + "bbaf699987824c322fe65c8d6ed4ca0c3829751beb4df4744843840df92fa76a" . + "e5c2e788d6aa1289b8f2f9cf38b912c486054161c779f4ae187d84b90f8315be" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "f640b3a7da52de9f89778eb6162b478b8ead5794b33dc10fbd208b25648c47de" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "368febc6c5e7967dc9023618e59f8d39bcae1ae98f0e5376d7b74522cdbf54f9" . + "7d9659310f52dffc9f934a9296be36dbe3f2e63ca6e308573bdcc0fe8eb2f15a" . + "7d9659310f52dffc9f934a9296be36dbe3f2e63ca6e308573bdcc0fe8eb2f15a" . + "acdda12e18b760fe3bbdf0adf4da9348f6436e7bcfe952db60c8b7566f495b8f" . + "acdda12e18b760fe3bbdf0adf4da9348f6436e7bcfe952db60c8b7566f495b8f" . + "664d22234ee0b99f4200f2ec2bcb1c237aa7e9a3621aa3169ffc57a004279363" . + "664d22234ee0b99f4200f2ec2bcb1c237aa7e9a3621aa3169ffc57a004279363" . + . + "637f5ef99e734b7bb1d4865813e08eec8085844f120fd527cd495fb46114eeeb" . + "cbd85be5098a4e6272a7835558e9f63239ca3a0101fe11c50bcac92e8f29afb2" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "f96b364db91aa1e659efd835d8e48e991fb43e8bfdf4158acf23c9b8b7d997e0" . + "50b5d2e0938a56d762359a917b72249f5618ba0fac1ab5b3ad3c7cd4ee972af4" . + "8d0bb115a180b2645c0a5ff280db233d2e3ef56d8f19b47a8868bae159afbf08" . + "faf20787a435178ed622b213ec173eea3e7fa1f55d908e960a749e7549d32036" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6b75035c1497318e7ddf9e7bdb54624a9563c34d90564f1d31caa61a2ea24e8d" . + "6b75035c1497318e7ddf9e7bdb54624a9563c34d90564f1d31caa61a2ea24e8d" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "727c6023029d9118fc855b700c285d801b6017e6f7dc89804234cbbca9f62e34" . + "41823cd5898ca20d76dc5da0025fd6e23a143e2e22556f7efcecaae3d5bbbd6e" . + . + "e35116797889d1cb6d370d467cd0c55450867efbe58d5284da0938ee7e0736a4" . + "b1052e1934a011acebf164b53a9ffc2cdc232ec3a7c703bf5db90730e07fbf81" . + "0f94ce473060e7c5503d6bc14495551118663605be875c111b20ae9f9a3080b9" . + "7ca3551ec7566658644f2bb04387edfb5c42a8d789dae3f3a3b15728d1c5b119" . + "14b00433b38c9eb88f6b54795297fa8b07515fa49280612409716426ffb894c5" . + "29fa95a8a92552ece26bdaf5dc38a5f7b878eb1a7612c42915e8f07b904acaec" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "a8ca122c43e235feb7e5d7e7d26f2ead06a9b40515a6415575d884c49d3b792e" . + "76b79f4ff3be5185f36a6324c5ce40381d0d068eac6763c7c3e2590d561e9c24" . + "76b79f4ff3be5185f36a6324c5ce40381d0d068eac6763c7c3e2590d561e9c24" . + "786ffd7081ceae45ad732928c8f25c8136f1a0716ea608adbb0e0099ad57ed22" . + "5b5f40e78b4131ac19858a79f86593f2ed551cc33728596320b395b9c6ac05ba" . + "8000ec2448641baae9c38643ae1cc52dc7b81461b5f82b5b7da242e9e05aee4d" . + . + "f8b6e529650807d46f1551e3f0b01e556b07a99200467f070d8dbeac3fc10a08" . + "36f7b47235b218d2273635dba31bcc9c7ada92e8bfb578059e05cee9119e2873" . + "dcabe0909eba13e9dca62875bd1593d20b29bcd14db811d939f49ee1518eff53" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "98ab1085b4e90969d38afb07310019c5547acab2091b722c18ffd54316c0033b" . + "c313545eac4d1cf2b40e2da4b6adda0651b3a7a9980e3bf071c0ac1450f8abeb" . + "fbf4e657294924acca4862173ee31b86b300ec94f8c3e0cbf291c1c1921f35a8" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "26d4296b0140085256614e706d0f5b307418bd7c24e164b1de5e155ffce04e8f" . + "f4cb78d9dfd3a82a96d1aa76810b4dd6fa8c7f68bf0a1179a1b8f134f4ca4d10" . + . + "4388f8fd772a95e2c4de2e65e6b863915f64150b609b264cf5a8529695f17ac8" . + "0c1bb1b2646f84239d7dc8fb2be89397e8077b600fd8e30aed4a68d4f3f6314d" . + "f3f9f8664f3742f1576c95822bfb0d16f86950364cc44085f65fc0c6578dabce" . + "ae17be26003d0c4eec4d541173096a87ccc642e38e2d344649bb7686382335f4" . + "b94dcb8b2f3ea027ef16eba75bab221ad0d6976f32e8e06b11b5021bf9ecf958" . + "0a18af15fa40bff76d64f3c71104c07b8e32a6ef1a792efc9377001ccfbace9c" . + "66783d32703910b4038c55158549bbb62783e7826e86a81e7401445589a500c0" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4343e3ec5e9349bc3fff9caa0b71621c4f3b7c937e7d7314a63b2e348ec82513" . + "4343e3ec5e9349bc3fff9caa0b71621c4f3b7c937e7d7314a63b2e348ec82513" . + "7ae06e664a0f47fba9b43a42485faa19f3b3ca1072784cfe2a0f3dc45ac84779" . + "5109fca269672492e571e407b22a99e98ee6317b251587711ea45f4110eda57f" . + "bf58eb1656d18d12b871f29cf55019e771f636eaafa391a8ff7faf41cf9de23e" . + . + "1ad2c9055b6998acfce32160e5061771e835cb8f6eb62ecd77b4abd2cb87df03" . + "a737b87cb54d33779487322bf4800448002ff958a3d48bcec4bb3e1a4176a11b" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + . + "1974ff65c83d293555c0040e4bce47c98c1e3510e74257c0b15eace73c1e267b" . + "d5a6f2efe6790f6b9066dd1348f13953017ffb7b6d84e62b768197c6002619d1" . + "c7feba3ca718a0aff812d76536e5886570ba1f3b043e8678619aa649c0288960" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "d6e205d1423e4d337dcf36635b1efad9d9284c613e51ebaa3be2943bdf51be58" . + "d6e205d1423e4d337dcf36635b1efad9d9284c613e51ebaa3be2943bdf51be58" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "6cbf338c9075b312e90dfe3d62cba5519565d0b88d1edbb1df279915177e847e" . + "3b0c7a8a5b0e9275ef6afadb0ab4c4e56a90c1eed619f02c146d5ed7a06818f0" . + . + "4e8490335fb4448fc371504147a6a72577aeb483d62a2c9f5753a954a0346ecb" . + "af7bd62490678a32b3a3ae4d020895fd3745863213cb7075e177c202755901b2" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "9dc8a12d11c009e6699c6ec2736311bc37eeba7f2da76ce1a8cc76bc855aacea" . + "1940e6504433ba230d13f9737502c8c0d58157f8ce7b1806c9b1d41762165132" . + "ffda8c224a628d8cfba640ac2700e120b259dcfefbe039cba328911a01179789" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "92fc8731fdfbe966db25f6ca870d0f9f11afb425fa6146cb71e1272c26b4c0d5" . + "92fc8731fdfbe966db25f6ca870d0f9f11afb425fa6146cb71e1272c26b4c0d5" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "5069e0ca2e371e35e08210736c5cb51b89440cab4d6ec6f454889180a50916a8" . + "0653f649127e4ccb8784b87dc2f2bf6e2f4755589b7e1421c287e9f67fd4727d" . + . + "90c8df59de52f9ab69aca702b0eb100c34e578c5d9139023f30f29870694aa21" . + "5ed8b0dea6bcaa72eff1ddeca1beb3e63c639e89715df0583a99d68e06d0de75" . + "b2dc400abad9dc82f5d9b171ebac4d078cfa18a01d2ac7d4c1a06719d2062e51" . + "4585860559ef19e744c593ead9003a4737f46e9eb75cbbad53e019a6c6fff9fc" . + "cc16774db32cf60fc7894e422d3be612472b5a5bb6a1cc50af9bb6e3c8909d59" . + "b95daa7df649eb4718ad133daeaf1a673b7d4a64a309b635abd3f6487622f2ac" . + "b86991160d0ab2c0d1a912f7600c8fe7a2fffd22ff1731ba20fbdb917aed5457" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dbfb34a8c5433a88ac75e80fede9bce504504d16a389ff472870fa3784344303" . + "dbfb34a8c5433a88ac75e80fede9bce504504d16a389ff472870fa3784344303" . + "69f3de6762bb3d4617a77400a61e61c098afd052ac804f8f17e97d6058de21d6" . + "b3a873777c8da1235259f857510400e0e5f471570c4fa413c23e415bab8a6f2c" . + "d68afd8480c315b1e6e2c7e889ba5b549fc21c02ebc79bd36845e89f20018a81" . + "854df38357aaa4b19be9d7f64d848de83c3a7080461c388cce7d0b262d416dd1" . + "5ed5c8c810841cdc40adc31fe58724c696aa71510ed374c238f204b4106ab1fc" . + "6d5409f7eab186755b349bf16910f46dc6fb0116a71c1fe38ce50915111ed1f5" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d408a092cf7e38e6f1a757605ef73ca537226ca115b0d2eae126be1e9970fa0b" . + "c1d74c7e45725b0e394d204c36aa96107ed728dbe402130ddd341836b193e8c8" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "a504b0848b66ca431934219b5cd9ff5dbdaf7d5e10d9a53512e9bc0e055c3a82" . + "ef525fa897d0d4119d6faa47f1a415a604d173e6c8ad84ef34b7ce27695e7afb" . + "dd7de0eb947833d245c931b73098c1b9b76f1437c91cb51b89fe317940460b34" . + "6be0f9d5d4a55db5fb3ce0ff16617d2fb34a6e82584b298e56a629c837c03cfa" . + "300c559134272dbb3c659db3a52721048000294fb0a16dbbb2ab7113873ff352" . + "68730813632d95868da43e51b788e613d29ab6017b47ca4344176f07fae26dd2" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bf41d2ca97fd173d929eca206dd87885d13b5e2f16e552e0098949bd7069c0af" . + "bf41d2ca97fd173d929eca206dd87885d13b5e2f16e552e0098949bd7069c0af" . + "0975b584593dd30866c8875394306b46d1d9fa99b47c4c6af1ac1ee18794e41e" . + "b8de0627155b627394b455821559f14102100f6228017a00b9cb1fdc6cddc88a" . + "fbf50ec4d5226bb278ebbb649bbe931c6933a5b898dc4d8b4bdbcbc6492e77b5" . + "89f739092a306ad1db3aed6a14d2a7b572ea99584d9891c153449934e593925b" . + "a23bc10e8b7caee542c78ee0e828db03f8ec524726ab19c724844cf4e05bfb64" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c7cf7ee1500177fb4ba3d788a256fd12477e14e4729758818932a7780c91ef64" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "51bfb3cfb45a55034d863e605785295c7749a91afe815490b6ad672db0c7fbda" . + "563819d5bf932cdc8fe9215b16b1b515b1abfc8eb2218e5af8ca57468111509b" . + "efe73101a5eed5278706676ce8725e6e6fe83132cb95b51e72c5a9308e4be6cf" . + "9d5fa9f69f06bbfe14a3663129e6f40ad3356ada85e9369f6660dd77dc53a7b9" . + "9bbbc5b804e167397d6c4a4a1c34f16382c354b48e8adb403b8088e8cb405a2b" . + "94be9b548598b8eb8d3e7198571976bfeafaae7e5f26a793923af7593ae62784" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0e7c4f4012e195cd0c9fbc6ccb729b12f0ff78d0ab203e889993c389aea43387" . + "0e7c4f4012e195cd0c9fbc6ccb729b12f0ff78d0ab203e889993c389aea43387" . + "8c3979d7cc325327ee3f797b126a4445104eba36d598eaa64b1c49da65e5931d" . + "3db2ed151e127584754e3ad1351d7a92586ee7b348ee8a0b6db345978ec13f28" . + "87893984b8cfec384da4b8a48652c58a618998a37158e8cd5973564599cbcc83" . + "183aa8ba2d84d46b1a655d0c12c1482f48bbe2af0d3c7bb1897ee96d7f4d9b2b" . + "48ef56eb9045febcde9ec57a7bf75702e258ff9cdf65502722f5085b4addb104" . + "fa6862236b8ef4f958ab12ca5ac547d93faec582e419c148da487667bce48df3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "df85a1afdbca58c04ec27ecd9ffcabfa8d675c8c1f0b2273260ecb13962b1007" . + "ea9510ff4baf7dc9ad499a730ab73bc25fc3231ab934704970553ef27fba453d" . + "e3bd280368f01880f9353ac90badcbab2541ef0f135abc260930f3a19c535295" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "fd37f5dbd5e3130d41952147b0d845bfd3a177ad438a682526dbf27ba0963ccc" . + "b846fc1babd41bbccceaf45b4fc3295d541cadcdfaeff9184fadd47b90c3bdd9" . + "bd3d59d164e74b847412c357f234cf57e3261a0e71b98ab18ee0a027368f9c1f" . + "2b0f0771f9913f0ce6ed85f9f03ea60ca1fe1ad9d23d5dac1df6199930a712da" . + "1f89c794d8499baab6f4cdac5ac13af33be3e28fb5f2f4b46cb017079dd9f3b7" . + "995a71ad79cfe05493eb57db47413c421b5e9faef09bc2c876bba38fd9870f57" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7faf26de068721f19c2e862a50e89f1c5fd86ca9a63e16bb9a289ce8f5219533" . + "7faf26de068721f19c2e862a50e89f1c5fd86ca9a63e16bb9a289ce8f5219533" . + "98cb7caec60a7ae01eb7a291172785b43355bfab8f5d2d3ce1f628fe252099f9" . + "75c8bf095c21122feb2e8c6cf7cc84d03c3583b64de9ae8cd08daafa4a6dd811" . + "a56d823411d7ce5fff2cfc319acc42486839a63176367f27fdc6515963052bc1" . + . + "6720f83c854930e8fa40b1cac21971aa5720812bad24713505b9a640eb18906d" . + "65d8e222c59e3fa8582fbdc81ae5ebc5379170a8cd3b06848921971b4d8777ec" . + "d92d7bea2b35aa4fd934066bda0ff3388e04786e767d0148972f60a3b36f9c81" . + "7b1671a54f68bb3eb15807774fe0446f5aa29660222f8df6109d06940830fa44" . + . + . + . + "50a89e26dbb844a354c4a9a9a9ccb4ab7f78298ecc607f9efb76ac64bba9dd06" . + "ab556a7e61e1f45fe0978561183812127e1990657d433c9007c6b18f34c56b3c" . + "42140b8aa8d1d6de2422c31785e9e2f51e44698e6cf93a4d40ceff54556390e2" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "de230c372bfc237dbf8cbce920f2f66cded8b22140b65855bb24aa893be1db57" . + "be290939ead9d0579db6b6954a2660ec5a4fcff15637cb2b031d54989a94775b" . + "eee8c107043df32995a08b8145cdc1eab6e80e12516e07d9474640bcea377b54" . + "ad35a91a4c3678f9c1dd0afdef72b3172150f0044be2b9d5b4539e3f874d3e1a" . + "af44e5ef010c94e329165c08e309596875cf250d2d2e8bb5dcb27fd70487b768" . + "25cbbda7522c30d3b6861587eaeae9566b0a12bee009226c4884245121fc01c2" . + "84a39de85048a1dddea47e5f82335c371bfcac8f74162e137af0a068c2fa8318" . + "afdcf3a2fe4a15d88802585d6cf571b7cbe43b184b8c2b243c8aa9beb56ac8c4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "1cac2ddee42dff7502d58e9b97fd4c5ffade2fa0d4f622f875cc0099ef76310d" . + "f3ba1c55343303dc25ba8b5cc44d465f7c616393c5297eb73c511f8c7b64ab70" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "00c4d170d7ad736492086de42f9a9efb81584367c6740cfe33cec40f4e96f06e" . + "c9583579c77757f74ed9b1a4f77dca530532a9fd0377a558841754ff190cd5c0" . + "03dde32747441418f8bbb7b6cbc148de8ed3e0c20f2b2d294ae6f38ba28f607a" . + "def4c8ab08b17fc34ea70927e25b4d672211962aa26158bb984eb99cd539004a" . + "04411769f5b5a7f58fa9dc5a1873753b35d00b95fc52016f67e4989c8cf23d1f" . + "400981e219677453dd082a5ffc238cb7c4a8ede9ac38a3c00e2279972c250cf3" . + "a51a6ab701a610552353f3fa1c45aead9fd9ef8a0e1d223207bb4467a2586cdf" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "267257644b4306dc95ecaa168492702d45bccec0aabe385a0c2411451f49852f" . + "dcc1fad04ff7624d3af7fc1ff942747a876035f3a80afae074becc09ca7de994" . + "6a0783457b19a307463eb88f5e27c652f31d76fd3f24de4fac663f4b3b9edabc" . + "cba08fb458df5619c9c33d65f6183e9fd7f9044110135560662a5f6cbc5499bb" . + "36bb7040d50a91918375add41e7f30b80eb17406ea2d89310da5f358df731433" . + "9e7e7a036cff750540114084bead6060f3cbed87ecfe4f3fa6d2a0524d2f9f27" . + "102cd4ff32f34838740e9111df56c7f0b4b6cbbc4deb26061a1aec0a3e8544e7" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "223f2c6806413a6deda725d2c557337da2534b1d79858f8718d4c4ee66d4eed8" . + "d71f4f555d5c7dd17ecf4e50c8c4dedd664c2de5cdbf1d1b8092846ef998f147" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "b01d52c62d7d00c9b1781e1a59213ac20072c0e136a003ad020d656cd7f3fd9d" . + "d65e9faa13aa0fef2fe68d7ec4da87a71defb702ca1f5022c56dd1aee63e0acf" . + "5f3d8dc16e98ee2ae4126552fef42cc7a06c50f1b1eb6dec83b8062df081fb0d" . + "2055f66209cddae9ac943960c2d96ded98fcbd5de2633c0e23b04de4ed882a4c" . + . + . + "03170b93353a4843b9c6461f2ab13a1b5b4ce947a1f819250b0f7175f6db5553" . + "a21523584e90c2dcaf22ce383d26e746062e66771207d585fb4b135aa6bb22ce" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "aeb65b9473cdf9019200629db70cb4cbcddbc2f249249491a75a505fe466fab1" . + "e7a211bcb57a87c1f6839f4dc4c74a3a704a7a6a5d95889fad49fd41da452af1" . + "d80fb38c1eb29d7bed5cfa4bc5125f31f52eb568ba29fe2f28e80a7494e77fe7" . + "03a08cbea434a9922d4d1e07d8eb3c974ac57022312e5a9fdf09dab9c41c75cc" . + "9467b14b4891562fc5c53afc35cbe56af3e934f11ba5078a799ef0514e47bab3" . + . + "d4ea408fc27138b7d170bc57045572087460613d1afc1c7c9aaf64288f4c923a" . + "b3e392fb74225181294ed058791a405919fe24289a99d556023380e1a0b74d31" . + "aafb1dfe342795d8bf33b384faad7c2043129ecfcc422cb3c269ad5fcaec13d4" . + "3bd27571fc99bb513a96e9244407166fcffaf51e565e5df3af08466e5ac1e9bb" . + . + "5c6fe58e8b6c43bd72f0aa9e89c7824bdea6b0a9feda7739d8564c3c91bc5aa5" . + "6200553a27d82ca126d2ad49cb6beeecdd393d3593c7a8916479c32ae1307df5" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5614beb2aaa5e9fa79a7184bf6646ca50dc7ea1a81291cfc05c6714d2b669f57" . + "5614beb2aaa5e9fa79a7184bf6646ca50dc7ea1a81291cfc05c6714d2b669f57" . + "42bb2daf919fb95f34eb2ce77f9aeeea32f9ae0f4d3f3529fdc9474c612de5d3" . + "7a9d7969c2c7414e1fa89e066f3bf0a744a3f62a1ee9e4096c6fba60d87d65d8" . + "e61dd1b87f91a7448f60626c4136be049630136dccfb11a2f35d918743de2bda" . + . + "5a2bc30003799a578ca55f89e2ff3547bab84c3448d9935ea6f392e645cb98d9" . + "94168db1a369468e488da7e1df178d05bedd378864674045339c4f988bdcac1f" . + "35eb8177a0b03b547f135fc0cb0d4690014c7787bfdea03a28661055f5d1fedc" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "d11fcc119c5b087af6b4e05e626c0195e73dd8fc9d5a03176df90cda0b167404" . + "fe87fa2622646074aa6be8219af631b8dcbf84495fc872a6c24a5a95ba4dd248" . + "7c541e30b1d8d32eb3c889fb0f6993eaaaa520f531d8073660ca5c463979ae82" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "030cf0c97be621e5433f446e189fc7febd12d45bef6b847c5d31f3dc5199f520" . + "030cf0c97be621e5433f446e189fc7febd12d45bef6b847c5d31f3dc5199f520" . + "8f336e6f0a392807a778db03887da67b0d967d148aa2232391c0f9635cb23dfb" . + "afdbd0ed21bd1ed79cb38609080cec75ac8f05555e89ae93b132dd27b264590e" . + "9fd4aaf7c3aaa8eee24c1202631ef2925243aeb4d984d13dd3729f157118a621" . + . + "60215c53bb3430adea6440649f1c5ba34044a90b2a82b75e03b0f29f456975c3" . + "f50fcc7812f0ea580c54355e4bc64e0adac39d5bb37789d997d339be67aedb18" . + "a8ef8cee615d6f841d2b42a7b6da88aab2fe91e8fea9e894277712c5eb9a5b04" . + "3cb40ce9281b4eec3a0ed786fbf976cdb9351e739c1e0807fe9bdbe286b30056" . + . + . + . + . + . + . + . + . + . + . + . + . + . + "58588d7ed9c099472831493dc24bcc5685af912a625dd8f67379b8112ba66342" . + "7958e36db7a49aa5eb3c7c9325c83fa1972d928f9f123a8a864cb830cb39a6b1" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cac5317c697a9175502ec1f09523ed1b0f89d501257777c74b84aec31e39fb73" . + "cb8810c1a38db1a6ae6089aac67789e9bb02db356353d9649cc8ae95753db55a" . + "4f449a9db5954ac652346760bb99ab02db9a3ede974f159a468fb155ef99a6bd" . + "b1c7e59bcbd1b94c530cc90c7a7566f275dc868a43c691eaf999475adcae875c" . + "50a43bc10f1d61e99439ec3ac714fdbda65783056c6aa7de730f64b3f0e5455e" . + "6c3a6b208ced401edc14fb3e7f10a7f68501b129c002bff2052888d3d0a575be" . + "cd01a967e5e70a46da7aa485819be4f587ef00bb4ae7e83137b4ecb5d25859ec" . + "aa1e3335b475070ed491486cc9bb2b6f238dc55858b14d6c50855740d833a9e5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "9dfdb9c8ea17a9b1939c807c46759adadc5e389bb9d8bea36544610b65eeb576" . + "a8647ff1b304610470a52c16d2421ab1df38d19284c6d5b1966493ee14d36ff4" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "70ed4c70664c6d86c2bb8bb45285a0ba4ddb4d089a6d426bb4ebbfc196462433" . + "9ab56c4de8fb918cafe1d14304e88496ab924926129f454d86e91912536ab6a5" . + "5904744d7b61bd1a662f78456e945638a5fba4dd48e4ba5e2634f2706c5b7de0" . + "55a177cd2310f9488d06382efa3abb9802590c5acc0d5cd9efd94ac975d4333c" . + "19ba4987e41f559de56d7607580fff4dc4f70cea744680ca63cbde50008d6466" . + "08d0172be58722e8db9697b466a09b05dedc60cc4bd05733064cd0a88089d9d5" . + "9f65716ac35756d442a71fbfc1d0c8bdd07d4c040fb4d7b0d6e9e43fae8b1aa8" . + "1aa6252bae37926536ce56c83104358bc14caf33ff6b20c9bd7b97afefb62f25" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c2ef4a2b8aa9c18871548263da7439e3c1014b6e0fd04912c7874942eab5cb25" . + "c2ef4a2b8aa9c18871548263da7439e3c1014b6e0fd04912c7874942eab5cb25" . + "735806118565214879be771c1f2ed2385ccdc6326154391831e683664bb2d51d" . + "1f63bffc9416662ed9c5a7c8ea977ebda5237df8b99ea11db578e1150f6e8dad" . + "0129c727c2b06f3d6dea86e7dc7c23431c6e9164169ddbf2030372d99cd7c179" . + "7f3f01d749537e2c7b63b1c8a6062e81d3b3fbdb75129eed5ae986f2677220f3" . + "e538512df1bf940f5a64eafe32b756dbb98a1d5561f7b2f1315eb3bc6f54ad24" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "7151325cecb5303a1fb700abc6a73b4aad431267071b71318461dfdd9b0d79d7" . + "e0fe94fcf3f5e770013473e0a2f6ce2bb6d1f43f19f800dca5a9cc5aba499b6b" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "a8ba101ee4f3c7017308d82636b2eeef41d35de145359aed2195d4fb785bbdfa" . + "0159265e18d0be9c991687d640e29c00d6c0cd74e88e47c30760186d5d7e4f3c" . + "91a34c6c8b28bc1529b8ff0af87460f9b16017338024f0902e97ff6637b6e677" . + "445f14220f39e34fe62327c3608fac07e8a1b830d948dc06a6d6871bf139b4cf" . + . + "0c1155daabc40c24ca47b2569d1c94826aec89809ca17c9df683ca66c3f27ebe" . + "271b85ba61bda29596a82aba486c9435db0202905c3c495db28fc5ca004f9bcb" . + "76e31d4bd4796566954942d7c6c7722be98cbe455b7b36777e473a0b88a3497f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c23ab3713dfc61698bbfa37490b37ffbc4193e06c46c5619fd46948fc0750baf" . + "d956fc08bd6e6b58fd63197fd8b26f9858cba4040baecf1bc3fe1c2e92dbbf28" . + "63d6e8eee99b45208c1c8c68393eb17faf54c4edd6f1cc7f74d25c8ce5ca2fa1" . + "3a646e6f75f7f35e63eca8103fa5ec1f316ef339d2c3c47d885ff19173ee98c8" . + "3b0d127239659947ae60e199c9158b78e2f873b53ae8611ec6e4023b83648dc1" . + "7b71c676b41af69c2fb195fd38ef474264aad8f51c898fa50512169b2f2436b3" . + "7949e72d8c63b31a66dcac1c416c02fe53ed13e1eda0fcad67575e02e9e94476" . + "360f0406cdf2018e173a8ad6dfa70b1edf37de90f181a22326b59363f92fd313" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "50aaa49f6811417108ed7c711a77c890140aabce6f8a8a0df2f99c9986817296" . + "2c6ab52a74fc9d17c16a5704116e4032a360ce8ef948df2304e8de77d2fccdcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "1f78a4bf41b5bdd91672594c6c11c8cd52196134b1e8a343fb6b11072c1b67cd" . + "47b9b9d7f65329401166a515b315c2304d09d232cb02c6d35ed1c35ca8017271" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "394d34fec049c58793a3cfddc2459649598c594c7fe8ecdb9be349e27dd29577" . + "b8f1f0c66db28cf24b1faa38efea4fba04dca63e746371a8c69f42f5a566d7b5" . + "be0a0fbad8454f279a810f3b1da740018b581b3c02faa89ea76b9d74d3ef6741" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f9773316393b0b4dbe9d1fa20f77c3fe12498dbfe053cd3e626ccecfea5943bb" . + "f9773316393b0b4dbe9d1fa20f77c3fe12498dbfe053cd3e626ccecfea5943bb" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + "6f7438fa4bb6c761cdba9a2a8020c8c517597f28e6ae5f7302e0918e2c6377a6" . + "11c76eb76aefdbbb9ef26aca0c121cf5e0db674f19b6e4ded76b6da738a750ea" . + . + "1737a7bbefded74afbee322ad334601daf17e6d3d979a64d6938ff1f426baa4d" . + "c75c146732de08a9f317917012847fc426617169908257aef62652c810e0b286" . + "64d11543dbe44e34e8721740fb933cca58fe235d8bb4516d0b666d3b38e04b27" . + "597839a01cb05d9c7f44dbb509e7d74bbd9845b3a0a6ab731589167f7b871b31" . + "e54c8ef9c443e5beda66fe48f8e1319e44d179105bbc0a8a7cf5fd923ebda7e1" . + "1540b4f2e6adeec81b4f186aa054b17f04f95e4455e63f58f61c30edde7d65e5" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1914112f0ac7ef1b2013ad1caf2e57ae1aba8e432d6f6f6c5044187d768cdbe9" . + "1914112f0ac7ef1b2013ad1caf2e57ae1aba8e432d6f6f6c5044187d768cdbe9" . + "da7e9aeec6bae49b156195b0202fb383fbe6519b025259bfda43174cd002cd9e" . + "7f4e6a543ac8601e2084e5c8b8b662a57fb8073305a11b57fe10d47dde65cf0a" . + "afd7e5c86903d79f8e505b630f5d853a632aa0298985b2d2c73624964856bed4" . + "e61004190c67d6159617947eef6c8e7a31f60916bb4242bd6b8b2e80a38c5890" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c991194e9da71aca3c6b4c832259dd589527d41bf26cc904d9373225c29b6bf6" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "72fd40682419bf3b9d8d0716fe93c34a2c23f7b8483d7d314725113d635c6a4d" . + "9b32f53efe007ec56c5098b04509f411b0bfbe6ed09da080f9c270be435c376e" . + "82f4287c2478ccc072fc759950ce7c3ffde510bf5959aad00a2146166a935d9f" . + "ed0fd6e2fd1eb0210d37f3c16fd898ebf1f65a01f49d23ea18fc6f18bc84415d" . + . + "8aa871b4be452be334e01e735258a70f3e17d707a2b1d8fbdbe9d840be85e35f" . + "9706a690b1b19fdd09ee581a424d8a52f8d28a9596df2c10e856db82305b9367" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aa1cbff8b71be2b8c65aab3580198a43968dc5d79f7bcfa7dcce5d351bcbb052" . + "aa1cbff8b71be2b8c65aab3580198a43968dc5d79f7bcfa7dcce5d351bcbb052" . + "afce873d7f207ab19461f1ae9e2499006d112bd9aa4cd63b953cf2d1fab7f2bb" . + "01338db7ca333b5fac3b586b32c37642b2b1edf8fecd6894feb30dcc60ce3234" . + "bd058326a7f91a9a65c4d2b5f90d6b8f324ac2df777ffacf14320dc5306e76ef" . + "c2616ebde3ac8d90c89fb3697cf50fbeabf0a330e263a53c307659c87772995d" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "3994fe27f5a59523a55b3c1f66053472fa11de21fb5e7a449509ea2332be6933" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "983cf5c5a7af483bf57470c577aa1f6c76d742d305436b9315abdb00feb15439" . + "2c3e25390c1be8b163fde9d196841ff8398869a51cbb77a484d12fe3af7bbc33" . + "04d9746daeb8bdf3ed98d1d7d090936d2e3aeb68ecdc5508f59c9ab615115749" . + "643267c744c2eab72cdab7d120cd25f13f6c225cb92f7d61e6c944c2974fbf2b" . + . + . + "d5525a0ceca839c2ee857c45f107d785966cea06c74623b6c40a3d31bebec343" . + "8d9b94b5a4fb28ca9684f4eaf9d407db3eb468b00912890ac5eeb4d375b508ff" . + "5f626765a87f74d99aee4484a9f7a3d293d01b7935fb5d091fd64db53e4eba6f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b6f5faacee610bc6700e431bec250e77a16360a576ec54f473fe4ed71af22025" . + "322887cbee7dab27f5cef4cecf9df08870683822a18eb6551cfbf2ce1903a0e2" . + "a0da2fd203e521983b38331a65f64378c62c8f4869c51d161f876b6745acce73" . + "45b6af760e7525a65af1ebc625b102f3681d8adacb27bf6c609af4f2133e6fdb" . + "06047e4b0e1b5de33fd43336162d4095c79bec29326879424e22af85aa2f58cf" . + "8a9f5648bf1264a6d3acc882ae1e2c1572017455e908b41e304fcb4132b233c8" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "660eba508a49bce153404fe036b3067cd6baa3f921942e611b1932f255fc6305" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5bc8d64dbfc5398bbacc9f3ffc4ac5eaed2088053360d426a13fc34b4bcaeaaa" . + "62d587abc20e87b94d9f032cea99f7981d3445a16cd3bc0d1075b808be875ae4" . + "fbf019a58589ed0642c314291bbbf4555274cbe810d80f1665c3b4b6d7a6b9c3" . + "b9b02620fabc04bdd1767b823593dbb9c51b24c4db75c2680154e5854f8da2dc" . + "782678d317d517c2d86b9fd48574f381f33039cfb98783e1f7a5c5d321f79d9a" . + "49e08e9195494d8a0d5ef1fc5ea82ee893db3223d19c54a80ff7a7d6cda01cb5" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f43d76092de4c8fb8775035547b355a79be2e73d27e0558f88a64c9b99722754" . + "c2f383181c18362b84080ea4834bcf9152a8bc17330e04849b99bd3465dbc4c8" . + "c2f383181c18362b84080ea4834bcf9152a8bc17330e04849b99bd3465dbc4c8" . + "6b7859b08f5c027cc21384bb38e85c4017ff9af9cc1e390ec0370983135ecbeb" . + "b8c490d6b7fc1013c07e057477a60ee3b55e3e9a99f9c860b36ef4cce8485ed7" . + "c76bda8a3ee63780cd170297ec63a804d776d2809e4a86aac251b3e3501102c2" . + "a1fd93abf6118ae1c5eb88bb97b35148c3ef16c3f204ae3595bc780fe5665328" . + "229ab6f891a02ba423480f7fb8844713c2cd13363c33f609d54740ce7c07ca2d" . + "a2e0f543d62d4309b2f0068fcf46d51a3e944bba84e42594f034ef74fd835e89" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "0da3d046f0180bf2b4fa948f43dcc20702e0e8c493fa092900eb8d67625a65ac" . + "d527914567e7b2e88f8d857916f071099e90226e2f6eadb41c3b64fc0c7381df" . + "26cfcd52dbfb8298ad791c97e48f667751ccd395b703bef71b630c5fc7042c6e" . + "6727b143fc0b43cd3b8fb94f6fa511616ad85227dabbea7db85b6a71828f0439" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "7273990bc2d6a5a12bcd5019c118a3bb57ad4eacfbb19f3ccc2ff783b57e2c0b" . + "9ccf777351a302d0c6a685a433ae1da09f2992277f84ec4ba0ba80dd25f35e0b" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "7dc361c525eda13bff3b0bf32aea17bc7854452e9be14aaf4788e72df4704974" . + "7273990bc2d6a5a12bcd5019c118a3bb57ad4eacfbb19f3ccc2ff783b57e2c0b" . + "04e3d30569e3f895ed602fac35349458b5a7af3dad34027d1f42195bda3fae08" . + "b5e86cefc9cfb8c972b2ede02131e8a270e7fbc4216e7be80bf800aea5de029b" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8e959b56203f847740dbbbb60a388647a4051c703072cdaf07756a0a6aeaaf12" . + "c3909be304d79b41ee88c04aa81d18d056b6795d7bbed7e5967176606da37953" . + "bb34a56210dab7a76bcea707d9e0898d2aa9e818dbe9e0a4ce7f764c2f0944e4" . + "55013eb8246f8a43141258febb0130ee474b526d1e4216f19b0679b1bedbeec6" . + "497ed51bfe4ba36215c52104261d2443149e0247232e31e4a5cf12f006c54be5" . + "8720e50480a01d728d0510bd7fcea41c0d6266ed99815c885a0549504e644690" . + "519af87969f1a759b36219ed2824f7ef335b1794f1a9f316f3c1efeffe452521" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "35cebab785c9ebc69b047593f86d830e467179f79ed7d4b2733694e6510a322a" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "cee4af89c2727f157a2d51f73ec41e30948f068d9ca07170aa13999a6804f53f" . + "da6ee4c82729588512ac7a3476dcc842781eedd742d1a97b44eda9b618567349" . + "7d11480e5315a644c52b1b9650ae49292540e536e6b7499c0e3117a276b109f0" . + "59c62695637ecf31df079d81dc61b549a311aaafda3d40cdb5ea0fc295b0cd73" . + . + "836e2f148a2bb3c03471cc206f5e06fb8fa82370620c5fd3bb730474623b7595" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3a555c84c7eb1e83030dc432fa34ce35b2ad6237cb816dfa6ccdbacc8984aa62" . + "3a555c84c7eb1e83030dc432fa34ce35b2ad6237cb816dfa6ccdbacc8984aa62" . + "a896cc0509915afcc42c3141ed911fa3f8a06f40a5e7b674bcc2ddc39e37bae2" . + "c0b9673aeb4850e956de8bb06791d6606ad5b8233c85911e0f8502040724c829" . + "db9bc075ee8589d1f18278a1c6c8aad4a35135130415fc4f083d8d3986579849" . + "4ba53b441711d2e13173de51f6f5c4e947e445fe072870d8f8ee4058b8a4cce2" . + "7e912fe219ead7d5c6a722f31384364ba01ea976a7ac2b614d2e0a71cbea2678" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "7004e4a763a729ae49148839694d88f832c0ed842327ef314e5b925a79d03f08" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "237cba34be1f15e727df1cdac34ed1c8cbf4514718ddd250a0909018bbc96446" . + "7642d6b66542e29dda2d07c2f5e3fa36dc7c892eadd85bb702f73adb39a87dbe" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "2550aa1fc284e7fb3c45cb06fab5135f67f64b4dcbe894e9cb00a47ca50bdaec" . + "237cba34be1f15e727df1cdac34ed1c8cbf4514718ddd250a0909018bbc96446" . + "d464c05e02cd20c778aeb37bbc669c78282e286d771c03d3b88405018c38372d" . + "5a27623f87094e918ec6e03dd8e182d2da6a610585da768b127173d293b00e4d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a5319bab3d6e7e9fc525b8b0af2ca617ab7e360396b2a0cdadfda50fe49bd2a4" . + "a5319bab3d6e7e9fc525b8b0af2ca617ab7e360396b2a0cdadfda50fe49bd2a4" . + "9658da9dc703d946685d86f44aa9f53b984485693563681f7f73a7f60e02483c" . + "c51802399b919b6c1fa4cd3127da801032983ed8d0ca8c5adbdafdd2350ed610" . + "3763b77aa5552fb827bebafc9c6c6e010abd45eacf9cba6374a8cdff9c163790" . + "130a02df166c26ed1bd7e2ed307ff7d398c087127a883b9bf0d8c8ad153788be" . + "0020a95e8cfbc4ab7513cf764c6d79acc69b7b96a5aefa0b043b25c48d01627e" . + "b1627aaf6a2f4a1e11299868576d1127a1a1d0f5f0542eb899879454899bacdb" . + "6695b4c00f4689472cc44f0e9c9e418d151225032e3eeef76594c1df3345e6e4" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "1a395e94ee1b968a53b8b98fa0a77e140b94e26721dd4a699f19a26ec17ecd13" . + "62aab8234ec770548f8bcb0dc11f747d33779dec019554d763ad40a84aa31a29" . + "18363dc97af7ef0bd250a6c35b3714e60e165454cbdb636b25dba11fdadab4b4" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "c73fc0e53a02b7ca8adf59e32f384fe792e9d679c9a3db8729ec979360e43732" . + "164d4cf933a2bacf0730cefab4e185ead68b6303911305c2b34e2fabe70f624b" . + "9cf0732ab8990ccbc27e9cef1c64ef24d211e3f915a213bbf743beca3947669f" . + "1630ce31d0091804262a02b32d77dbec3500bff7ec0883c34607a6f6988cafef" . + "6cff23c1abd980c133fc809aad1f73f56d24a5f2f4557995f1c54dd4f0af2e6e" . + "5e493c3da543df1f828fa7a324df4dcc604a0d7cc0c9120fe986dd6e4f02b608" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "880ac6bdbe2f5630e548d37fa055d671080b3042f8473dc31c6d1191785e6c0a" . + "880ac6bdbe2f5630e548d37fa055d671080b3042f8473dc31c6d1191785e6c0a" . + "70bbdf8fe998c3ad1579ba64078d9e87051d9234c92cf8f59671f80755a97ceb" . + "3c690d659ec3a1989891e8777f66668ef426b055217b0fe719cbba0ce1473729" . + "1f322c4b780be4c87c05d74e474150abe4da8adf7a65da046ea4835ccc162aef" . + "3540d5d880795e28479bd51bfedd4ca392b0a0f289ebbe54d66b4920b2995e76" . + "15c3195b0f6329210c0be7177fb67c70d769357dcbb0b933789dbd21da31c4e4" . + "748329eee283404aea8d93f20da373973e8ac26e1093331595d8de0204f073fd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d8441a0909c04291ce7b696f8e4cac5db1101295eb18f75a1bd00beb29bf2932" . + "da05debf66500fcb80dd209dc5a7f6f8c5d43fb41bbc5d1f1b338aa6ff46cae8" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "84acc2fca9645d29208ece4444b8cc1129fbefd627abddc4a4b6da9480128bbb" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "e576fbb8ab2629d61bdfd90acbc4b51acc3ae895705d45bbf11b53261f5c17ce" . + "177c12cb945cbefe37c558073ef3bcf22e7231e332b6065c5e20c71e54031894" . + "8df5bedd52c46b9396e6aec1b2c93f2eb866acde39662d3d6db0b12508db6f8b" . + "e72d5fa9248e4c3483a6c6c65dce3b5f4ccd4ac60bfe0758f6be85b4f9d9cb66" . + "a49b69ca0dcfb397ebf3ac17b55c09342374003c0546d7f3a6144b59771c4c64" . + "b071e28ac08b804903aac8e0e61f7059410fa9bc2c50146149e281bdbab0882c" . + "e104097bf30447ae37f1fc3fc5b8f7dc87892c4376f9f74555bc31fadf990011" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "73a55cbfe01af7faf8876b00c9ce15acfe9ee839c82f6f04d7ac468fbe63f972" . + "73a55cbfe01af7faf8876b00c9ce15acfe9ee839c82f6f04d7ac468fbe63f972" . + "33b05234a5879a664d7118563a0c9b425fc99f90adcec6c4ed99332faf98775a" . + "28101f62f45f087025ad875d37b48a3b8179946a1bc6e480663e924f5de94536" . + "4ce13e336415866ac58ad9404d046d9ac70cce5ed075296ff58c34b3b2d4b004" . + "cd5059f888954972ba9b635f848c45742b5006dc074c9e72e72c618571b60082" . + "618f872ec248ab519cea24ae42a5475898d5de189861169862a47aa3b1d3eb5e" . + "000595f96aa4a8344fa433791c08dbfb2d44558298edfe561b7b22bc0a11ac7c" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "6953326559682246e49fabf403ed6e6eb2c8622e7b9c446162129204cb13f4c4" . + "e837bda30f756f4395b5b6ab3514c0140784e4cadc635eb65d3645160df4025c" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "9baba4b2419c339dcca5e4947a2c9e0f8b2d6d4e590e0f40ebc358e49c431955" . + "7515961aa96f434016395884a619b4e860c9db527279872f07e5bba43a9ecb85" . + "a13cc78a7f769517f5200374d87b978897fcecd7bd3d781f2debf6a963d1cd87" . + "ba005279358134c6a369da4868b6629741318c9e191cc5e64be03651cbce087e" . + "d7996d3f51d060ab661023a29a35f38a2d43d24e0cda550a5f72366ef92f9dd6" . + "571b5048608ae56d13b36fb473cd4b9f35f36880d872fc325046a4cf30fa1e95" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "37d751e40a1d31160981edf9c73ef10532f2fe7a662e82ff65c0d366c725edc4" . + "37d751e40a1d31160981edf9c73ef10532f2fe7a662e82ff65c0d366c725edc4" . + "984a55271d780bfc8785f899f79cdb539883ddf63779d68a48ef5f8858db6eb8" . + "1b0d6239b09f85bf60b0f7b89615baeffaebd2c81d99faa0a59d0a956ca9c4e4" . + "d356787dc0c4d1b75337dc5d8e07705fa619e86e4c5b397f39293b9dcbf1b879" . + "712e07a4d6cefd925458ffdae3a00503e68693ea86a0c41b9d2d1246709a1574" . + "7ad58628a56874741cf64d1bf13150a55fd7f185dc860ab7d31c46b90c5815c5" . + "4da934e1df46c182cbb1e7531cfd5c10b5c6218cb10001dc8bea98b152001b2c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "6a914b02711e025f841e913280301e7e4b050702958dd41aab5ce9da1b7886c5" . + "c022e10cc712f3b114bcec8b845d0bf8387c55c359f3d47945f1df042b4ca642" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "8212d2190e4b077e31578d65edfc9dffab2d791c55fde70d6409e2df617d8d45" . + "65e79971bbd4ab0a913e8d02e329fe2fd196d51248539a1a89428adcad6402ff" . + "9918ea3fa61cf60fce550635e64d982a73d7136ed39d4e83bd84210a0762d21b" . + "737768a2b241b6465fd2d9cc7c14933f323f13dc25c6392c66f94b6ed7615f0e" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "41434b0a67529e8adde43e52c7155b835b63ac3c6b61bedd00203e2b57e094b7" . + "72e80d0c882775010c74ab462f4f3b038e35f7483debb5ba074e7c9dc2462d7c" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "f167ba06aabfe0155b24beeb11cf96296fd2cead6cff323477ee3c5ad21a1499" . + "f2985c0367889639f3b5aa4f12b14bc931941f430d450b89d45797535e05d802" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + "2517797299122631d59877b40026bdfc22310034087ceff53efe6ae0770b397c" . + "b2b663a3aad42202494c73fba67b929ea77da8613a5ad4a07d0a60cb26841cbc" . + "d0d16c349120dbd9cd5663fef0816e7eef5d67c40a0401d70bfb6b4dc39e4825" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9781ff699c85db934b35fcc7a9cba716a0996f34c0b160dc559e7957d61839d1" . + "80ad1f1f53464ff66c231764973e864e7b72ba835fafa7e7f8f5774799c20b4b" . + "b78374bc6cdb1907a6d1cd94bfa62840a8b370f16a704fa4469ae0b66ea2fc63" . + "944f8f81b2a10f31d6ea09f6ef11571cd829b4a9890f420bf2ef405c7d5068f8" . + "39f0a287f58d8e97605d042aeb1af0d080163812cd8736ca2e30015e62f81bc7" . + "8ec5c31bf17b712cd07a52a2d9685cf7cb5623717c242ac83b7d2187f38d403e" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "5769d1dfd9719d267a7f75b738eb8b611be1f4d73136fbaf617dacbb69f0a255" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "fa8ce4b82dae3ac51a1a8b41bc57460b403227bc29ba54e63fb10b74c0ed3dda" . + "f0f5dc40fc2284491b1d3067233f80b0893eccf45572951ef01134cbb515701a" . + "5a84ffb5eb39c03d23c435d423d0ff064881807a607ba3fa6cfae06ab419d868" . + "ff8643a280a64fb6a3c6be4a129c777bd3c9108fc93be6cbc500f898cb952a5a" . + . + "9d69973b3c9806aea181c880956f7972f4e1af359cd5463f8586b290f454ae03" . + "146bf7ee066997cc7803135ffb0ac03b77bae2db7b91ae88a1607c7187f09354" . + "9e89586a202b11abf4852eafa257f84efe658bf3c4b30ff94439e6f3856e3f1b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5f4cce733cd331370c018fae9401303eca232d3f350a770fdd3d6c534d9760fb" . + "5f4cce733cd331370c018fae9401303eca232d3f350a770fdd3d6c534d9760fb" . + "739d5688b68f50a81823440da19b4c0dbbadcbd49766903eae5f3841a0fa8ee7" . + "601dc76965c902445909c611ac24231b3cc271bfd5ca44c91fecee9388d0c9eb" . + "ceebf8ec13f4ab8cb40eb913f19ed07f25dfbb9aa8e8f605a1eb3f5edd926a4e" . + "6f2b30e271923cf922dfccd27cc005328f8791251dab360e0339794fceb92176" . + "922f74eafc8062cbbde3a7fd98a7c393b37655d00c55236fb86f21aa4c1d8473" . + "cdeaff84764b89553675500f2d8d449da8f40d69d90c562dad61b3248960d65d" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "dbe1b2a819505edc7d8f2ca88a925868fff7b444eb375bb2a9e9b14af84f421d" . + "23165c6b9d101b0339bf1a29afe25168325e27f62a7b55d35ceef65ce728423f" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "432ed95bc6b3e43409e240afd968e0a1346c5723ef3f543735fe645d8d588ed1" . + "2e8f898429105489b5c0cd17268a376934d756fb8940b5c5059eb85f0f7fd5bc" . + "3763d620216013e68abf0785fc1631a1df4f14ae51b5ae95039fa7d216774cf3" . + "280445abce0af07414dc6dfcd73d8c62df1c5a0fdf551030eb4c01c70ab69181" . + "432ed95bc6b3e43409e240afd968e0a1346c5723ef3f543735fe645d8d588ed1" . + "3a328c1d94dd87feea32e25dd51c276171ae406712a6724784b5e89b3c17bad9" . + "7a74734f8e72692d13bfa4bf51a6fc41c6991c0bcd22dc9c70f785b485b97ae1" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d3c8f0c4751265624120dfa73048af6c6889d263775b748ba6988bf4d5b08f30" . + "d3c8f0c4751265624120dfa73048af6c6889d263775b748ba6988bf4d5b08f30" . + "876d8f99b3b88fe7ab4afa9060b9a97c4ea5ea405b2d2e700312c391c158f7fc" . + "bb12ca1ca12b0141becf30489cc1c7100f8d1cd3e21e25ac0fefab475c4e9308" . + "c262bcdcf12e5016417111ba594cbe02fccafa4ce1ab0e34b201e0c01d10b2ef" . + "fa8d9f2ad69b70b760496a1ad37867ecf284176335cbdf64313aa500b97b8abb" . + "e80b3307f6cbbfbbd70510d87e331aa87a0596fa0d714ff00ad97977446df373" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "549185931850b763df61a108ab22cf2c216746d67b71e0803c9f44fb7fdc71b9" . + "16ba0dddf33dad58fe7d4bd3cfac7d455451cf057b7bbb588afc3dc85988458c" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "d7936405d126eb7717f9a65b98d406ec1e5c4e6a747f46342a23403ce7814d69" . + "7ae90fa9dc8242c98d390b70411cd911799d48adace5fd1b320c8a404c2a4d96" . + "8d94e432f49b80754cb173fabce2ed56e876c399c31d81d4541b532bd798a48c" . + "3cb519c8e37473c6e60bc2a0c0adc3905dc1bc1626ed95cdfdfd2e48df74a7a5" . + "5a72f1d16008f8864f0426bae0821c10a444124d0760a11b7aff0aa97a2e7dfb" . + "dce0509b357688c8c73b13024366a4daac892a9b0069c4968121e54e630f255f" . + "fe182069747887cd77cf5209b72a59226bbe9de2e0d9ad570cb98f351d0a100b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0fcbf4749dd9be115111adaf0e3c5b278bc2378ed49241ba927cc79eabe4661b" . + "1d1eec3904753b1b007ce0e4f3d7a27f3104e3ef43bebc32dd6e98c72622ee31" . + "d7a1063bcd2f5636672ebf83612adcd15954d850a0c0f8f9269d1365d76c957b" . + "fc0e4bfc6692e6cb2a52fdcf373402ba203f4b5447a4c69945f9fd2380f79e6c" . + "8cb136e699e95be43ca22b030d0ba1763550cd1588313ff130d4c8659bcf765a" . + "c90cc44b213a73bc3623b5dd83b4779a5b6d49c24b3e755c1a170447acae7afe" . + "699cc018ddc8cb1edb332654ad9fc86d8aa07c4d6f97f3cb5fa7cbaae42f9793" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "6e7216eeea0c5c124a7a87840c5779a08add6c7341a0086e5be57fb8848052ea" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "0c0de14de7755c1b9b4c0625efbf51d10ce5cf4b65cb4b5f99a55349c1e1a778" . + "dd89eee81a2827cc84572e0f84f372b3d8451b1ec7778b71c5d94805b69664e4" . + "0d54bc3818d44994b97d7fc8040d3036f48ff6b036712dd200afd4d474a2cea4" . + "d90749bd1baeab383f53868270597e0b06707d6d79a8ef70feca95613b345d1f" . + "09ec887c8beaf6811f2793b3270bb6fc4a15c61ee1d02b8ad911d1b5d3f2e5ba" . + "5b5e5662ee5416b0b02b7d12cc904b093a4dbdc36e527c9c86165629223259d4" . + "e80e26457f12c2abda3550315fa3bd796de5ed0c77ef692327fb28c1ba2b5d38" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c01cad4d70a5f00c8a4f69b4d7a473795241d31f9b44d2356d629db62f4e3511" . + "c01cad4d70a5f00c8a4f69b4d7a473795241d31f9b44d2356d629db62f4e3511" . + "c544aa62e8cb313b7186b00c83fd6e494911dbf755bccc761725314fa7ccc855" . + "205fdf1cec44e2d45a648ddd85855c926200484067ddb193fce8862ae0783ee3" . + "127c7008b4e8c54d2889975e43dbb2aced3fb5be6829d1e3d1de006ac8ada8bc" . + . + . + "11c9019526f63ace7fc82b9f63c8b532ab93c6bc9d75de5881137df79c1e9352" . + "db29beae823ea4516de1685b246339ac50b51195a9ee15370a03ff1f04139b66" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b950db0436f71538ed9d399158359c7769ac03e373b0e9de992ff6293530fe01" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "6aa8caeb789e1abf7a3bcdb61e78a16cdc64868268c7875b209ab41cea09398f" . + "d3d2b81eb896cd7064652cb9bb1f1367ad758c54f24ce23987b3016cda91de4e" . + "8c970d8244364a5588b642ec60bf12a6875905b3d468fe7642a7d9b18e277dbf" . + "4382b2b904fac7cdcbf8a00851c4812a5777b0a11f99eb8a0ae2d780368a767f" . + "6aa8caeb789e1abf7a3bcdb61e78a16cdc64868268c7875b209ab41cea09398f" . + "8687421c5b281c1cec95a806fa851d32ab07260b2cfa23c607379eb9ea36fb86" . + "1f441a132a66be95c224928294cac2fbe374823b050040ed506cc6f93b19f41f" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "883219d4121ec5381a2f2b95a4c1908e5de75dd353a3c4af46c78ce7e1f24924" . + "883219d4121ec5381a2f2b95a4c1908e5de75dd353a3c4af46c78ce7e1f24924" . + "4cd688b851f03fc7d6c6bc9931e8a2ce4cdcd912d79e794e007776bf5aa1c5c2" . + "24b1bb323eb8d1a39a5508da6cde345c6e1965c748e42c5d98803387e93f49b2" . + "cb88b47c27e3bca070d39c0c9def07830793d19ce067122337695769649680ad" . + . + "be14e76919258487b0ba5dc80dab1eb8d0567a45a1f5122b0c5c258f12a3092a" . + "344635ac9041563e344e3175ac1c50985f9a2b6462abc57a97de898cf10e9052" . + "f28f3d0b3c0c546a268e3e8dc487c5a45d23457e4ebf1b67e654779e91c9aa22" . + "174ba1079549feb4e13e0033c2f328080b5bfaa7f401946fdf0e2f97c3ddd823" . + "be14e76919258487b0ba5dc80dab1eb8d0567a45a1f5122b0c5c258f12a3092a" . + "bdbabeac9c2e58f8eb2c01066545164f3ec99dcd398264df432a741a6a174c69" . + "bedc6ecb27a46774299779d1cd2fe8f12a2b6e79712390a2bebc58145da6bc61" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8698a71491ab3ee9cabdb41ebfcca5c0918c86a93258981b94ef25251432d9b8" . + "8698a71491ab3ee9cabdb41ebfcca5c0918c86a93258981b94ef25251432d9b8" . + "9f9a3a76af1eeeeea62591fe481e8e9243b86306e0165524c78c2d24b113e3d6" . + "14f294f0102c7d48a5c458a3cb3cd4f91103d3de9ecaffbaecc4fa6f1d1fb2e0" . + "c99ad8838e3ece713e5a720b8a42822de5f34dacf8bc8130997799e811aa6b4a" . + . + "1d3d1599bbac0765e6305ef760bf929f2e68ef0e45da26ea277171cb04782e1c" . + "44e91703e8228bd0db6181731a6c9094b8c60a31b3235e260b8bbe57e16e65dd" . + "15473927454fe9114e91813aa313b280a8a5d3ecd3acb6d72967c881e4d7934f" . + "da9e869aa96f41dd3aca2831397f9c2e411495515628d8e9353de64f031c49d5" . + . + "b62eac700373662530e4e252b603afa443653bd389f731cf4d4e45e3091488ff" . + "4bea3f450c35e8594ed88eb589e94d190f28c8ae10160add0ee90724b72cf408" . + "91b659c5b7596b69643d5acc175eab28da1fcc50633167ab069553d7e5808fa7" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "77283a60868858b272b23ba2c6d6e60ecacc11cce766de6589a94a017a7576b4" . + "77283a60868858b272b23ba2c6d6e60ecacc11cce766de6589a94a017a7576b4" . + "feff9b7c4c942791fcc0a73bb13e2d332f7e02eb8d9d471485eb7da6f3141470" . + "297c31f4472af6d9282e09b0b79ddfbb4f12a1e48607c141c5db073d66e1c2fb" . + "1ce60defa7759dc5b7d86e7b7c1d50c467ca336c01f8c3e4eeb0d768eae6a984" . + . + "9c1eb975e992281d82e915e6c73d61ef74fd068b90d812fbbfeda498b48b40a1" . + "71d75e43191b461c298618a0cd300ff9b1524628a91afed1affab7bc9a9710ef" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "3b227515acf30646be3dff816b5b19476ccc79c43c9a8eda7f8d1e1a8823e0bc" . + "76a33e450b9702b79d7bb0121192f2b02eec3cc2fa883b1168c2fe1a700eebb1" . + "411055510c3f52442d465c4c6c1cc4eb449c43ac01e70b34015385a3c0c7c10f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e2b14fd3152db63cea632edd0a46cd937b46f94693a5de3081731905725690c8" . + "e2b14fd3152db63cea632edd0a46cd937b46f94693a5de3081731905725690c8" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "1f7978c5393f1eae2b36af799022d1db40181f7bb0838a97106e19921def4302" . + "4f84a3f37ee5b1135e619384d793fc7743f84238a2f099c3030afd0b2e3cb54d" . + . + "d2a0692bf6004ac8198f65ad3cc717661ae1cccb642808267dec33096a33dd1f" . + "78c18cc99cf89f2c5493acc2bd2ec4e70d7b8a834d6964fe4a909daea4c5688b" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + "ed54859b869e19d57dcf6774659903978c1fbcdc0e9f8438ce53f4dd1d23143f" . + "0607b01cb52fa1e38cface6b568e90e74ffac502ee145f081fb5efc2197b3bf1" . + "495340a15c63b2c7fcb9f10ec26cb5160b8a0752b18e860a03a26df41dc8e091" . + "744bbbf4c24e4f58c730097e4ac3ca457dd645fae336f1680e81ec958a92ff67" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5eef06b9db524a2958aebbc93ac156ac808c419c065a2eab78f637e26a615873" . + "5eef06b9db524a2958aebbc93ac156ac808c419c065a2eab78f637e26a615873" . + "5b16126f8da59ab516f1dbdbd5a7a04f9355baa6bbc82d8a62d160b725089fa7" . + "c7fbab23cbc207da635ce2db51501c370f0b8c97af050002ab6863b32561a823" . + "9b2228a05728270e09b480bcf8bf8a8aef6947a6e87f1031b1f312cc1290b37c" . + . + "f60b88fb7e585e9025dada0e28a4c8ce47a94627b965ab46e3d34b8fddea4515" . + "3a44bb492fcd5491e1d8d0ef02610611476fdc09e7026ccb261640db9881b141" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "fdf995737acd518bf916c2409c4c17082d846f9ea1bac25b23692f5b5857980d" . + "8d00f82159bef9e7f7709536acc2e8b9ba37734f09caef42cd0fed5a8e67bc16" . + "e2b5cf2bcf22dd45756205201d069135396f303fe5362c9b93da33d14fc57d0d" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7252cd30deb918f112eb703396d368fc3a6afd0ae6bd88bc1b00a879f105755c" . + "7252cd30deb918f112eb703396d368fc3a6afd0ae6bd88bc1b00a879f105755c" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "8922861e1529fdd1730f33d06531178f5dec4f0d53b0b603190733634d9120b9" . + "60c4719c152182de622b52427af28f4ecde37ab4ab9f401e58939eb13d86f824" . + . + "248ab21e73b2c354d8f7bfa0269ec8d7b736fc2dbdf6231230d8fb640e4213c2" . + "013effff513d4b72fe8d52bb7e5569fa50099df91e056d0eb7434b1df54e7b49" . + "5751825747d4a4b56511836cb22022d918548b22c4e07470693b8902f08e26d6" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + . + . + "75c7a8783527c477e90eadbb67bf7fa402bb8affe4cf7a9a1cf8d3cf79c8af3b" . + "4dcfab473fa2887ae347bcdd02e9b34c7d99067d8511a898dccfe4f5043fbaec" . + "3aff223a6849dc08ac1c96c8490d8f6938c2e9737948034c8099ae3a288e8499" . + "0e746a42ba178b7f1298ad45360ecc51735067a63ee9c4a12f2e930d1ffca42a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6cfd64141d807330f8b352760d47e27ebe53f2b349932fcaca3be08fe9bb5f68" . + "6cfd64141d807330f8b352760d47e27ebe53f2b349932fcaca3be08fe9bb5f68" . + "16ea7535427424e2465245ef7079398a0f3f4df1485d0d6f9a4a38f77814299e" . + "f175535c1769670d34e49362a4e75909b934c68214e7a4fb58e5012c66fa7e4d" . + "61139dbc367d1dae7834b8850b9e59f5f780724b74d6d760294c874c3f03d099" . + "74c766b45edce10a3998a0e91a9249458780dbfc6ccc322cd676d0dbb4da4cfe" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "8e6b150bfeea156f1cb6be22f981700224e83afb514d19d35968857b04dd74a8" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "af72f5838593b3d1c450988b34c4dda0d4fabbc3c42ae0a263850ba9da4b7bbf" . + "146debac32cd25b8c5b2db1abc8d836bbf9d1fbe0d9d7d9d82f478d221e1008f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "ed809bced8421b73deebb6847cd9b9aaadbfc482428581fd751b44554ac59c1b" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "690c83758dc080ffe08aa2810d372b4b0722025b767e80a6c12b3341ea43d988" . + "ab6b31032ebc093792d6ce3de913e2c6474e1d45e7f7d5df68d64b9ffb96dcff" . + "f3ed393b90957f3a99a5adad03e83acfe9d5488fe046c3797517de46c53f3506" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + "fe2de463239490946985dc2aea31a31686220a2fda308f19df13a45db5775ccf" . + "d2cdaecb78bf953dbed419a96c1b0845653bde17c6f6411e08e0e6a33d17ec0c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "805598e380ec76e0ce657d12b0befebf2dfee241378104b48259dc243726dcfe" . + "805598e380ec76e0ce657d12b0befebf2dfee241378104b48259dc243726dcfe" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "a428fc82f9d4d41121732f22cc93ba98cc3c1faf5835bfad800aa0f3aee350e0" . + "a447c5837bcc8108849182be2a8ce564ed943bb1264ba41c364319d64b8de38b" . + . + "31bdaa4aed59be7cd4e10b86db3548bdca5e5690fb70c55da1081b2173bef294" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "652683217b6a7f2e3d8cd12a1506b3fbff1d1f12eeddefba689bc9f01183073a" . + "8eff7ac950bdfc3cae2303f3bf18ea700274eb97987270d727a7bbb953052545" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5c4149dbef606a5760e411405758fbc6ac364252464729bd4b759650084ba80c" . + "5c4149dbef606a5760e411405758fbc6ac364252464729bd4b759650084ba80c" . + "6c03987a8b35e51edcf449b7d1b7408e998f7acd9041298192850b0865090c38" . + "e5cc7204b25cd735554bf6dd6b8e0146306181cc26cfe41162c7a1abcf00e55c" . + "6a3b69dea5df2a3c4bdc0928f2b04fa9b2c053dd4e5be150d0b6f10c9cb84cc6" . + . + "486b4b58c12e6fff06efb2f338071a0a5dfabe0e90b3fad590e90514955c5c02" . + "abec678a60d196141dfc381d9c024499f00082dc5e7c5d209d91bed6a9e792b5" . + "35aaaaa61250fd310204b27a0d526073cc80260f7c2a58293aa24757188a7b56" . + "c12d8440402ecd931a45fff2bc83b0f11b351032a8efd1a577be67a8ca262faf" . + . + "d4b934546b47739099f901b9157d3329c1bea63c81bfbfd9487c09a1551d5373" . + "37b7a136f7603fdbe2bce477fe8846dabe0bdfed8fab7a38d8a67b7a1d008b08" . + "66783d32703910b4038c55158549bbb62783e7826e86a81e7401445589a500c0" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26b5189fa196ef6c7703e67ed7a59b1b978d3a552f2cbdacfdeec3ba40957362" . + "26b5189fa196ef6c7703e67ed7a59b1b978d3a552f2cbdacfdeec3ba40957362" . + "2b415d6c84c67f565f59fa81bf218e70550cc0189e911aa4e593de3a101fd43a" . + "02e0d56b61bdef89dc982cb9ebdc22f9cb795bf179fae48e415697f31aa042d8" . + "8f4a9e98b6ebaf4dc6a683a1aaff0bceb6e2df416c5be31c7fdeb7a891983b5c" . + . + "6cdb66bb3d343d006701766c1bee057d38d4a340fb44f397778955165df444c5" . + "d1eb5e2a096c01cd45797c5cac3e80154dfb66f65585bdc27ff4a0d751c559de" . + "be87e90472db17885f058784d582bc8e78f05e4e9aac48879caaf327395db436" . + "a99fbf614ee9ae3f84814d6255ba4da3c327acee31cdbe64ae3626fe16f1623d" . + "0b4f002291933ca1714763baf07c11eacc1cae7bf31368233e8d756469926c0a" . + "55a6b1b949c69db26bdae8441cb7e774b78a530a0608586adb29601d48a8c415" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "582b0be0dbdb80fb22a119f344dbf3d761bcc6b48b634520d1183c7d2ac50822" . + "582b0be0dbdb80fb22a119f344dbf3d761bcc6b48b634520d1183c7d2ac50822" . + "b0e9caefe2d7d085b80d9bec3a79d0c0594cc25b5b3a3cdf36ea13afad34bcaf" . + "c016fb9766ad36ceab17a7961a1c5aede11c10f711c3c020d1218d95a0660337" . + "f9941d0abe1f20d218e4e912a2dc9918f2e531d6568034304f044b275b625e8a" . + . + "89f5d5930c86546509bdcb0731aea3dd1c2231dfacad55c468980c6ea01e518c" . + "320dc8a0e7b13f270dd3bbbdfa61ed1761045cbb43273533eb9bac3a77140450" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + "f388ade5c80205d90d1109cc8d897fd16a13b74b0cd992ed47313c4091620035" . + "61bfe177e1b59289221e4383886d45861652878bf1999f5ca88c40b43609f572" . + "23d33aeaf5adb266abfe3dd816d1b4aba76782457acc62a9f1f68ff56ea1a80a" . + "7c3ab6d5f9bee13c4695393381e8da1e355d38f4efd8eba6373d998c9f4775f1" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "de026052e7744ab6a6dc54eadbbf889306ac838b4882ba51e94858b31b5aaac8" . + "de026052e7744ab6a6dc54eadbbf889306ac838b4882ba51e94858b31b5aaac8" . + "81ffe29167b1bc9fb7b2c12a5970d6b377d4e54f4ad132e1f45cc34fcacfb432" . + "794f837d44f0bfd339187cf965dca4da2bbdb4c00deb1059ca3bedaf474090b1" . + "9c2b452880e4fcca59ec282dbb22abbf7f295cb1a42e96be646351bf425b1b3f" . + . + "abb42fc5b511b18d14d31bbc7a5e7f70a18e3746dfcf9c69e8f1e3068237dc32" . + "e0b6cc561984d809992e9c86eb99759395fdee17bcb05e28ddbf7caf15714d3f" . + "c642cbe7224447b157b496b6eed5d08cb37b77d59c0447dd0336360d281592fe" . + "a33b42a342b6a43d32d59c90da0a49cdc68a27ede6f5d473572357bfccd602fe" . + "f50de722651b5ae65e08cc34a218c0934f5c450c08b4917b5f7bd4546d1d29ee" . + "523a4e4ce52d44afc265f6fbe0d5c7076177506ee79c45b5695e3ceb876a3eb5" . + "7c2e1efe13a502fb8dbd25ab377bd195b3ac9d7646b956c284a9ba00dc8358b9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7f00495004b339b3fd1908f2c3f866e05e63c884c4d587c219b694c7456c28a" . + "d7f00495004b339b3fd1908f2c3f866e05e63c884c4d587c219b694c7456c28a" . + "2e417ca1febe508d9831bdd54155124e31ba0e8ccc4d80a35bfd72c5a4fcdf78" . + "f04b88c5674566355de00b36fcee20430d0de6997b63555647797799565f5196" . + "4371fadcf5036d9c56fa9a2f87f0b1fcf24aa8cbb714ad9c27acea1c1c96408e" . + . + "a92059a3ca0a6340842f4af2ca539bba828ec7ed74f28d51058be4c6545fcd52" . + "263d6d8e2d680f40f527aadfcab2c9dcab35c4e38c3edc3cd5c2f8ebb0d33643" . + "7fb396d993ad2f53edb81938b7ed7ecfaac4bda1cdf7af8bd9ef3804e7d6be5b" . + "e4af8ec343837e0baf4c9b4a004a98a6b8ece16df5200c8f9076d23991803d2c" . + "57b9f8d1e0585ec28a3ddc5186484e1c28fcc105a5c98a64a34b74edc49e62d1" . + "3bf08a39b33a6e69212e4f2871ed5f7443cf8afac621a566dd32636a71e47fc7" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9c47461d5460a3aac51f31a171fd16dd4ccdbe85a0317e5c5f065e49f8f6c606" . + "9c47461d5460a3aac51f31a171fd16dd4ccdbe85a0317e5c5f065e49f8f6c606" . + "53f05b3b6fcb3a5408f9d92dcfb3df054ca769074fd0c8945f2edcdb8cec0f69" . + "19405f8acaf46e17d4c3d3ff68444b6eaad2c6ba5723daec3b042c7421dbfac7" . + "d1f66c573d7c523e0358c548f2ebc50b75728854fb5cf9b6d89c54f592e46b3a" . + . + "98f9bd6a9c50fdf426ed54fa6d0b0c8698fbba38127bc5c8c482ec5fa1a27903" . + "149db137495cab6262b4646d4e874c9a8640c45f287d8e40168f12b6e3ed4cec" . + "f37f763959548f87b52d9ef3d98eacf18eaafcf23779e205f0e2bc982cd42617" . + "1d1c339be92eb97d9cdb7dccdc651d2a8532b9b5ef40b714b8eb1422cae5a2b7" . + "214c0aa8a09044448d8b68be77db1ebfd209f2b32504e233f5888a7635d3dbad" . + "6c25948939bcc83bc6eae1f46a59a701082969b5469a76efbc2f739724c746b1" . + "00cfaee5f61ae09b8bcea2b369c4fea4fb62a479e7cb3c04d15fbd8ccb746ba0" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bfdddbd9605797b2680f3f6f96040d017f42616f5db1b1af747d177e4e39924c" . + "bfdddbd9605797b2680f3f6f96040d017f42616f5db1b1af747d177e4e39924c" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "73d321a75b8a8a57782bde3bb551dce79daceb062aff552d6f5802f713cc968b" . + "65578265e43f8ac7c5f29deec020876f638c2172945047272d39891b0ce4017d" . + . + "ed0bab7b59308b637e90394ddf63a70bb9da9c5ef3a765553d14fc475ce982f4" . + "fd3beadf55cd4e76238eeeb0ff094abb1d2b272f97c4cb27fb0d326c8916220c" . + "712980171bb9dccde365c8a8f698d08e138ac86f1f8f5f9f84bbacac1301dc4e" . + "786ffd7081ceae45ad732928c8f25c8136f1a0716ea608adbb0e0099ad57ed22" . + "8b6cbcfb253073fe8a1727d0234a657e9f0be70d29c414f88565b7363601359d" . + "3f7de9acf3429725de4c0336615e59778063a8e90193f1c55fe283cb7f315817" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "75e99f54330a6aacb644abd0e97d611e153b53ada7a6776d4a80fee4b118e188" . + "0cbda5f91535fe37d54cb809c620e8e36ab2f3720854a49269f3f328c57b1b62" . + "cca5b40a332e7ddbaa0a16f94b9e37bcd5ac77c5a414083da239e03d4908c35d" . + "754742325ea66adb5c794dc523a58734dc9cd0c267bd9d8a849a3b7c7418bb49" . + "abd93467db7fd31f73ece1306d165a4336c74b63e603153fa9e42beef2f08b4c" . + . + "37c58337c5df680261a2302ccfd8eb1c2c2fac95c8bbf515f3c76d2b46674c56" . + "b9bea44b839bd0aa8569d8e6a6f0318aee4e88338cefd35226fb78f711dbc59c" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "c30c05f473dc11ee15cbe36a2a713dc55cbfb70ac5724e52e1584a5f303a2b13" . + "22ca587d9e0e4444a75f23079279b05095d6c61848b8b66f56ae38885796a8ea" . + "36e2584fc2077e1c0d1c6cab252a6ac568d30559eb02d87af6571a5851d9d417" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3fdc5caa0e3bd93360e40955cc9bbb3f41d48d3a989f262b738a236a37d93403" . + "3fdc5caa0e3bd93360e40955cc9bbb3f41d48d3a989f262b738a236a37d93403" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "917b686b1b78355002d84c61ec218e81e491f73690a54b8cc55afff3e119e08d" . + "eeffe477416fb5a92816e2337525c3d975047021c61debb95eb971c4c3deb8d3" . + . + "aef17f4c6a51508006e2113d7952dcb42d005bc024f6a80d7bf9d99f2606b71c" . + "c1082ce9e2aa7e1aa284452bd78cde273e531fdc9eee97c90cde8a115a6e0ba1" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + "241c0af81b609d680e0de1f25debe2ecc3dddf719b9ca49e38840e2089b3af52" . + "30a919b55a9ca45a0c1fb00b33b529c08f81ea302e7f53ead2bfbe78704b6016" . + "b13d44d23e2482f4a9c9b99524e4b56453d0a2c129ca0dfdae7b91066482ca45" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21a5ca840200fe18554adabf85329cae205f8260a17502a2cc62347c168adbed" . + "21a5ca840200fe18554adabf85329cae205f8260a17502a2cc62347c168adbed" . + "1e15ea8baa86e85627790a9e0431f3d8b110a7e7415ea30d662bab7283209744" . + "790c1daac5b071c375a662af39af4ec6c6f5f3eb99f49ca87fa48d696249836a" . + "35f934e372d22db24f931e624958a8173f52803ac8040c19a209dd4332792169" . + . + "289dbdf6dd685e7ae45758fd517e15f942273ae241a2bf737cb8ea0e5cff9db5" . + "51865e7652a5c184cc697c98874ff04e6122d9595a89c7730f03358d98b47fbd" . + "e149e3ab58aaca707945d2fce78e26abe63f8208b76e66ffeae9918031bfa7c9" . + "1d7c7487688b90cb96fceb4c57507b54ccdc8aeb84fd7e2603ebf2b1bf884a45" . + "f3f668b5f0225ea0d8b5ad5d04bc6a054ea9674f8e6fc3cdd3f5c3e7f857107f" . + "962b2ee82ba27b59502c20bdebfef332d7dc284876585e51bd32f371cfb6ea03" . + "da7ecf31e92fbbd72332bcde82ae0815a7d9e369bb3c39f905accddd235c04c0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "82b088b5e0c4358d4862fcd41e3dde470017ba3a4d28059382109d79685ad69d" . + "25adb4b8d58c7b7da6e3394d64eaa446d7b298f46a68a9024ba154ee01a6b355" . + "54965099710a90dd97febc1fa003fa626dbc9dd78e7e446986628adec1093c9c" . + "5aa54f0dca882fd41d4feaf564f2ba150d2fc55ab08c13491966858d7ef5dcb8" . + "4c9b1b04de10f0c60492e4f8edaabef22d6435fbb6352edf36da6cf10e2e0e15" . + . + "462a5e5302c27919d05c1c9be35c81aa9b7c41565577a11470f905b763e18c51" . + "aed740f6ca7d88df7f533315af5f14dc024f77600b550a06bd973540a7964cc1" . + "bf4ff78b10880659ef94195ab9a6972c5146a9a52c8be2158bc9ad57cce002da" . + "43b9d7cf9e863d77c22db30c53fd1208bb3a59b3eb308933b798c2f937d885a1" . + "17e5426443475ab8146c88e2d9fea6b6fca4585ab203335151facabd414f6c58" . + "7a6847ceacf7b8a463d923f066ba439ae2d8846c5805d414b02a2ba70eccfa04" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2cc13241fa8103d985b000bae2ef77618ae4127205aa6d3c404c25624f8972f8" . + "2cc13241fa8103d985b000bae2ef77618ae4127205aa6d3c404c25624f8972f8" . + "dd434997153dc225b2191675e425c8b05a82e8aea688abc05316fd438758727e" . + "69f630b6819ada1a694502cf7817cc86062699be7f91107405ce409e8e546e9e" . + "88e3f66646ffafa4f7392d865c14110aaa18f93f14d44a1076cc517d36ffdc0b" . + . + "e3d0182d1f73b95322e849aa19f20313862078e5406537b1f2b90fef17cddc9e" . + "9b0334033cacb7fb7c0fdfd198afdbbbc1142016bf0b9fe4698006acf38853ea" . + "ed2add28acf0086c902c2053eeb7771304dc1b091687518ee43c3af6c4a1edc8" . + "1f8767e6162dc86df8e45202c2884ab2cb2c954366c381e571b6e7a4e7ac17c0" . + "e3d0182d1f73b95322e849aa19f20313862078e5406537b1f2b90fef17cddc9e" . + "30ced93f60de71157b7d2dab2dda23152580dbeef28d339ac32d5453b81e0e67" . + "7f6af7a95b8a635b03a99f3a2b5e8b34c8684fb0f9862f4d4a184a1155a7e465" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aeb121e4f7516115b238de60e279d3d7c80497706778be65ca5b2f5e2f91a661" . + "aeb121e4f7516115b238de60e279d3d7c80497706778be65ca5b2f5e2f91a661" . + "f368fe2d4515bc90e078d09a78d32f037d87374d78ba176428a74c0f3b69e118" . + "bc8da9e7a8197ca2d1e3389589df42cdbf8e9b134c1d2bd1b186d0d97c681683" . + "0ac54c1b6f2c64e02a119310dbc5e212a7cdb618c8850bd11e1e0a4b6e107d95" . + . + "afa003f7ece8048bf653e92f68a4a3c456aeea4f866bd3c8e32cd72c656a1adb" . + "2975bd70fd1c60d73b5308b477f1759a2993a02a7fe4071edad93e3ab4f1f2b9" . + "ba005279358134c6a369da4868b6629741318c9e191cc5e64be03651cbce087e" . + "0d58a6c752bace76104f66e38abee9c11cf8a6c098a725d53913e76b2a595197" . + "0d33f866d578f1d179c75becd6d37ec6314863d1b9dcfeb5b3435ae6a5755afd" . + "0ae286f75b30a6a3d882b35141877f100b6d49b68be77daa1c3cbc523e94c2af" . + "82932ddce217e2199c3cd9ba126ab94c5a0bca7f820ad501ad2f39d4dd9d90cd" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8c3b2d243d102f3f2b6c4717bfd6282e068aedf30286598241452f27e0578e1c" . + "8c3b2d243d102f3f2b6c4717bfd6282e068aedf30286598241452f27e0578e1c" . + "6e524b9ec4ce4ae29c2fc8d78ea384599afbace154d06cde8494e980a115352d" . + "92fa3cae9806a5130ea9b942d0ef1b6744d4f0244e0886df522024fe1b09b2d0" . + "9eb195d623dcb79ec00ead36aa855f84dc623cda94962ee28a253c51cf502242" . + . + "c9603fe545eff424f7264ee49b176ef85e624ad6ed6ecc29f7c2190ec189c6df" . + "502d30a4bc31e246c2606c37f6955ee698a94e0c938479955ef13b689ab0ab43" . + "01862916a7378c7171be10e8e42a2c8fe83d2e8343306cf70b3ac95a72d2752b" . + "a29d156448e5fb5caf404492d0c331638ebc760cc00d6bb89a93440ae35a1128" . + "8583af7d5d32049162f8be177b2ec23be65cc292d169fbcd8a8ee5743ef8c765" . + "3385bedf4c7a163d928abc90579ffeed671dda6dda6b1a2dee3f3bacd16c17ad" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "132bc1b1faede309530797eb3e492440979633537b11d3564fd0272377c61ea9" . + "132bc1b1faede309530797eb3e492440979633537b11d3564fd0272377c61ea9" . + "a8298c0a751ebfb3e1c383c790e81abcd4df475d1798a0e41d5aa2966a32a592" . + "0c96f741f3c98385f36b74ff8788a00a04a4e942a37dcf29657e67444e84308e" . + "c0d814f8218c6970019ee64febc5d4342ab527765f11ee5b87e62d2035ec05d9" . + . + "e1725331f3915e3bfb81be6d3c4348d60912d8a3b959d10db7860c82de51dd52" . + "9fc36ddcf1cff229cd208282d3d59393fb4fcc95e20e994e98d7d8e160134649" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "957826aed022ce7fb8ca7e07f0d785ca0ca8c6e07436069227a6d5ffb77b4429" . + "0816a32c3515a271e9afdd3d826dfcd0df924ab31267a301b87722810f8108b4" . + "4d319aa1fd6c324ced67b7a654971a72b5441cdf8c68ad681c57a0a414843772" . + "7dd2b7c078efc5553cce08ac661aa91af92de1575a4933fafe09780e87b9ccaf" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "738574c09628b1f929f33327ed66e74b65ac27ea65b2b16e083fc12f95dd3732" . + "738574c09628b1f929f33327ed66e74b65ac27ea65b2b16e083fc12f95dd3732" . + "5b1098a3e072fa1717f796331b9c439ced9e333483d16911c4c025e2937e9b61" . + "0604da33d128052f1ac569cd46b8d37743f7787d9e256a1925d9f87cd89e78ab" . + "74f2a6c00d4aa0947ef725e3ae35433c9b0c420f23ed166ee5dcb418714ef969" . + . + "76a72332415dfd57b90b93341cfaaea874de6dba0ac597b99a1886cd9d10759d" . + "bfb88001ebe47eadd2a61b52958021d7bab2f549ac4c44a7d771d31575ccb2c0" . + "82f4287c2478ccc072fc759950ce7c3ffde510bf5959aad00a2146166a935d9f" . + "9d21270ddb54f1e7f3d16f18c72890d61af66151c8320a76fd662fa5a1ce5ab8" . + "65085c0d476a10f8c174b68fc8e05978792f134e9666a52684df572d7ab1f36e" . + "c4c01c5c788480db0cb3ecc97816b4cc9d4a6e81e2bfa6651efbf1c034d9da7b" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bb43d1c7a70f3047ab7d1546508298fa3e054b711d3f2f2072ba2065564cad6f" . + "bb43d1c7a70f3047ab7d1546508298fa3e054b711d3f2f2072ba2065564cad6f" . + "5934ed58f4999b5910a9a43c46257b09c2fc7978f14150336f28c6046bcf4c4a" . + "494a899c52ecb570d431a3049312c711ca9428965458fe652adc59a08abd114f" . + "06f25755d377fc0981ab2da9478f8379c6345dd2945f0280e04e010557c61ef2" . + . + "d83665553a50da6b8e7dd59db3517c9a006faf049e738abd579afb8975baff5f" . + "89745afbc812b8a1190dca14b79f9f4b4287c714025935fe8a544888e157a1eb" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "68867e5fcd8dc622fe1b395c89bc862dfe3f45605ba506029bedef59596b673b" . + "5097503d8cba7ec84b5bdc2c89abaf792550e40e9bee76b37787b0e8bf197617" . + "345f4fbdf720e507594dd56e914be362ecdeba9ed31bd15f34f9eadd26870365" . + "ef60b11be84eed42f65389941170ee61c21465ee870a2fb9e62db95b98a0ac82" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0cef6ef89b10153f500aef242c0b3c30e082069421063f1f498f8c6866fa598a" . + "0cef6ef89b10153f500aef242c0b3c30e082069421063f1f498f8c6866fa598a" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + "ad04f08176dec1ca64c759424034bc2a94893545d7ec82194906a3dbefa2e005" . + "24f577adc773264cfa1b8073c87ed115ef563344bf98b0b11530550e1831e9c1" . + . + "220768c35cfd90f46cfd5a3adff05dedf622fb28c3990bbc7de870e6379337b0" . + "63d0860d50cba994b7c1b6cd616e7800c7dae63c79b34cbd65e9145c1758248c" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "7131d3cf4e55afad35a0dcc5d0d96d4aab2b966ccd99fa07beff22e82f7de5d9" . + "dce9c42ca9ba91b2e824a547d1b06ab542be3c5d6a21d35b30a7b89f3dab3f76" . + "0d523c4ff4621f8a8a6465bf6cc377cadbddaec9b40b1f6dfdc86fc5fda89fe0" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0cd438c08cd5a9d21863146c851d58114ecb00de9326cb45cb6fc26e72493415" . + "0cd438c08cd5a9d21863146c851d58114ecb00de9326cb45cb6fc26e72493415" . + "6273850257cd414bc98064ee4e11ebdc49ec671b035a77103bb5e368b3d932ee" . + "4e3d1005124abb816163fb42257affd7af80819eb582af28a67e0c888e930b84" . + "db8cb919d9a2676566e6cfdc0c15106cc229a580e94a7c82c33751af76663fae" . + . + "19d46f819a344e805871d01d852482d23c64762f4f0c5fa0639acdfaf30c4b96" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + . + "7ef2fce81ef70ebd742145e6690b5eb7365ed8aa388910861f6cee20bb7b6a90" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a68dbc1ffad8252d5ccbc1fc5a4110186daf14cf1a46479c02d24da48b1a9d9" . + "9a68dbc1ffad8252d5ccbc1fc5a4110186daf14cf1a46479c02d24da48b1a9d9" . + "2d6ba55314375d0a6cd5c62953f16d704baf3d58d6f17da2172d0a7b7b9eca49" . + "a917314fb7e277a38d34e583548f0b1c5762ff41bbcc8a1553a882a3b1e55b80" . + "d030d7d8b02e9b8c3c85590321259895d3d12010c0023da8b1e192b8525e4e3d" . + . + "fb36a0adf3cd1519577dabc83263709ac1049cdd0d68454e75458bacab966dbb" . + "1b40342d06a91e11fa0e4024c616d17d9255c0e7e2482c32a11fbcc00a374502" . + "712980171bb9dccde365c8a8f698d08e138ac86f1f8f5f9f84bbacac1301dc4e" . + "0b96abd53ff13b4df4683f1e8ee5c0412d5de686fe896af2db65d9986e89fa21" . + "32f48a8cc601d6f9bbe14da423f0627b44fc6ad9c80a7f7779d5620b0997acaa" . + "4113f3cff80fbd135784f17963f588bb266f3910f5720edb7693f2d4db18d06a" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7c7e957c4b4cd1074267ed874fc2b3fb2d9ff7b531920cd21cd220f04feea9f4" . + "7c7e957c4b4cd1074267ed874fc2b3fb2d9ff7b531920cd21cd220f04feea9f4" . + "3901933ef76f5a0f830aae10c49bb6713670d83232bfd0a2a39d5064d67f4271" . + "4a017964cc1f4103c922ea7ab98ce5887b4c96e75b93efd0e2916df34a0f18df" . + "025b0b4db1652dee5c3a6234f2af6caf855a0f414012dd62fc53538eab483c6a" . + "c6d7a8247fc011a355c3532d90599df42c0f10c084d878b24e4f5735a9c2c952" . + "9ef09538e060b461c4899949fa7cefb2b10ef54548972349c8b9fd665a595513" . + "ee107c49c8b2a752de87bf58a01a6e8dd706504d2bef4e65eb890f0768cb423a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "9dfdb9c8ea17a9b1939c807c46759adadc5e389bb9d8bea36544610b65eeb576" . + "b9433a0c9522916d4d2744905be6bd89fc10078f63682154305c3b25bdfafaa7" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "5d2bd6150f64aecc71606cac7cdb70ae5aaefddfd036f1b8c569b5e4514b8364" . + "dcb32789d35b2beda42fa2e25beb55ee80c3df2701cba953b705cfb4d2e4f1cd" . + "80b4c06e9c9c3da9c87d46e159bffd767a20cf00dcc181e7d7b847b299332564" . + "e8c3331b02b7e599f2c1c8a2446bd2d836deb95f2b8fdc61e15a9a6d53353b94" . + "aa1d6aec83b67d1a7ad5fbf70bf61c101b7c79226172cc3a7bbf19a09a1c0faa" . + "dfee0f05c9acd8cc95460b65e3eb8a54be144560bddf25e3cb2ce350e1ab4c3f" . + "d6ae3529729beae06062eabaa881f4c42e8971eaac9d9fadb59e4604becfa88a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a2199148c598ca689e92d0800ce96586a667761cf8d5e7a330a73607b0dc8ee2" . + "a2199148c598ca689e92d0800ce96586a667761cf8d5e7a330a73607b0dc8ee2" . + "2e54615b8fd01c18a8622f496c7cc9684d79c8ba955935597d8bad144da66a22" . + "76b8d8c99e2db7deeaaac8cfb926614cb203f69672b9d7602aa0a850cc5f4b2c" . + "89271f5b7335fc3aa50565fdb386f73d802f3d54b094515b7d56f54ce5fc41da" . + "bd4b51ce752c3bdb2ba64edf728b91f7d9344d44706571c425dcfb8a0dc5ea43" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "7004e4a763a729ae49148839694d88f832c0ed842327ef314e5b925a79d03f08" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + . + . + . + "fb38ee8aa717e53572f03f1088f3ce491502b9f1ad670a3bae4ee3d14a01de1a" . + . + "267791405a1c422502ee1f83c76964078913d7d9dc3d19839424d088d49530a5" . + "25002e5ad2f51b59ea02d246010d7ebf69c5d66d97dc84a9778f7186faa89dcb" . + "741ef9cf6866040e074b59452242e6fc69c6693a7c0baa0f0acf448bcc205287" . + "507412e3e1ca034f77ef843bb5b0f2bc8f35ee827bdb4273a072fa1fa50fc331" . + . + "84b89a4283bf964987948aa04843735d31709a271ece8d96884e37a43fc03490" . + "e717383ec5c70c9c429552bbb75128c4f4b78d50178134501d13cc212699eb7b" . + "cb92bef5d997a0ba7f7f7649b646ad503281f835c36b4c6a411480caae23b07d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0104e914edcd92d3ac8e808d270964837453dc1a62074d8a5447d5aa476e03d5" . + "3cc89ce35ec03068138f2e80c56e41edae7181f126bc062a8ee7622b00131b2b" . + "22d3ddcf65b90ee58344074ee3af7e26b794df122ee6ca5a5d193a839a28e038" . + "fcbc84f8be3bd0f262b0e3b8c1ff97004ab6ca83f415111072ea8e61d38de273" . + "298097916d54ff3092537e514e5eb076d59cadc160e96c360b9b5304d5d09e27" . + "2d4acbc8b81fb4764c8ba2cf971156aa8e9e142c24e618fc4219596442f86e4a" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "8f8223ea2cdef96cebd47b5fa8449544f638e2cc75ad7ef6f9d288c86070633d" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + . + . + . + "0b29acd97f7288156b0cd3895198348613f3cd65bf5a339fe2ef09cf4b81effa" . + "0b22501e025dc73b092991675ede915e2834512f0f296e94a566bc69ceeffb3f" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "f1ba7a5d1c34b8be425d5eef6dd173d206dcfe62093d6ea1147a1d87e9521cda" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "20e2217b0bbbab9e5efbf2768ed4f798da7cf9086d5e40f3f5fb97781f019238" . + "f6844d23cc6e5cfdde16ad86d2f796c84720a986dffaf06d8987b961554c9233" . + "1021b1606ccd0ea95655b16ae4dd62266e3fccdc66b6df65cf583fa19d661e71" . + "edbc108adb87703d4fdb8c9927ec3400b95b91722a747c799dc3109c14977770" . + "875be6fd626cef50282614ade97001eb0d5ff14db8ccf49c08bfa4a3488aa913" . + "67ac093f88707bbdf72fa22379a2cc8660ce1b2a9704199c1b78e9c464d2d7d3" . + "807a6e9c5b0c86c70da95a93868cba74d1e27ff54c61e60d7014cb8638445e29" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b32d08593cbf954fefa3004667cee209d7b2705e78009f480c6144fe5abe55c5" . + "b32d08593cbf954fefa3004667cee209d7b2705e78009f480c6144fe5abe55c5" . + "6a14547c3c49a8a93387f310405d8f02590ae9f9e84d86fad43f76e7f8f232fe" . + "f7fffa5b7525cb43b81f5a9e6dea0b502b7345c5d27cb3f27b0ae1053ab2c7b0" . + "1dd5d8b3f4ba625f41e9d6111704d5015bb0be0e5cc9565a192e602150ab5b5e" . + "d1c549ab1536ef4f14fa98164ae2ee574390d6229d5668181b037e8083c5e5e9" . + "e19d5b76f002600bf545af6d24ff1e68c01ca2f895c37832ca4fe775bf970b3d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "5a6f53d73143c311a572ae507f0400d1c83e7c159a7655ccf12574b003a8591b" . + "c8820c352b83f7c3abd5c16f3c976071b642c8c947e8a5838d7eb7ac17e0dd95" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "d663c6c419c60077c6ab1cd1bb4d80a5e65b713b0f6517e2be840f8cc64f878a" . + "12c381a774ec895816f18a5428c38fa55f9f1dbd25912366ff9da0a4fd6c9fac" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "d64171c9b60df857684dc95da1f30cb9b73e9145f1fd337c6ffe4c5dbce9c075" . + "51648db51d77b8c0c379b77dee2d7108da4baadf89ae31f2bd158e4f4ba99658" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e7a422c12b04aeff9a524a6345ab528fe4d075e1215c0812f5b01ebc6c9ada7" . + "5e7a422c12b04aeff9a524a6345ab528fe4d075e1215c0812f5b01ebc6c9ada7" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "393670acc04c27ec61cc1ebe949e10a7c3f60e9540dd21cd09f5eccbb03bf9a9" . + "c819a69c0580002c3f6900a62b7baca00a8eb714a33e28cb10fbd4ece697daf8" . + . + "9e7c1628b67e34da00898ab5150c37958c7199c2cfe45842d923da9eaa0d1db9" . + "a006de5122dcc924ebdc02559f2d9117eae5130f4650bdfdef5acd5359b2e81e" . + "bdf448efd15e55ffc5b66c8ab743637ebead0f9e273f7cf60ea30ef50dbd6401" . + "1da7593eef1427511dd4f33b8e6dd2a1538f7707598a7901eb14acbe374f068b" . + "8fcea5a26ce35ad0ffc5dd4ff435a6f8ce076f42b66cd1994eefcd69614117e8" . + "fee272cd42c08e38a08d8f9c1397360c2b8f883d26042fd0a8307ff5fa272ee0" . + "e77ab54f3e9edd1308d414240bf2ab46e0c42c5236533039624a12967b1837a1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b783a00ab71fd16143229f04ddf8954b68a4987bc9f81c065242751b84225bd" . + "9b783a00ab71fd16143229f04ddf8954b68a4987bc9f81c065242751b84225bd" . + "c81ef5b7ddb1de76caf8f113860614694333f51f4dd631b67f1c5ee01c3bb159" . + "d9d08eba1f48c45e2161853cf3d313e271da955d3cd383d5a7de560861a13a34" . + "f424c57dae93f8eb1e85f0d620a8734dc352be778bbbd6aeb6428f900393eedc" . + . + "5c936c3afa3818affb32d65c0e9f97fe40a78b0517ec22df2c9587840dad92e8" . + "ebafc51aaebde04aec0a1d761e642dbc1142ac6a41d34c64ef563fa610d3d65a" . + "c759b624f13fb436160b8f1096bfb4f687cc00f94430de2aa9f0a67a276eebf3" . + "988044426e34254bdeb0226cf33cd3f369f7d222cb7e544d0725cebd40f47385" . + "45bc744e3f8e2f9cc8e612ad7f19c61f2a858f99cd9c3cd303ee483e20b4ba66" . + "7925a59c3b55d2b8e846b95c7e1c5d00f77a70002bc566705e66f8ce241fcb82" . + "6ecf13547b2757b496cafe7325e811f4fc71b7fe972493caede698d8741e7926" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "85db42ed5eca3970d739075613cb4314b712093ecc56d7da247fa130b9a21471" . + "85db42ed5eca3970d739075613cb4314b712093ecc56d7da247fa130b9a21471" . + "f40f52688c1d20566a6a313b6dfa775631f1061acb78be420ef1433d1f816d3d" . + "87db1ed9cc95dbf2095c755f8e0f8dc3fc565296fdd7d05baeabf5034eea3413" . + "26c8ecc630a02eb66c27f1a6f12487c256d44e9bf1f48b8bc56cad1460d0d1ea" . + . + "9ac89e3e4003408206c30222b684ee7b73569ab2ef6c4aa502559a4a6a7b61a9" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "907d492a532cdab962f52fdf1b10d821858fd017afb5a633ba04e07938371fc8" . + "17b92a1db208a45b4f9d06dc3da3cbd74025cbe92ab8e3e826244fca9f7d8a8b" . + "acfe8a77a91235163dacee5b50f9f0cae3d86ed49382dc8c535375f220c5fbed" . + "13e2c3f57ba47d71edfc741db8e7e0bf4171a488241ae18dbe2d2dbaea176471" . + "f431f98810ae77e48b8022b92ba692ca75fd34a0773199d1c2efebcc7bc87d85" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4a820dbc6464d698ca559a8001eef09afc44f94dbb1450692f752c04ab8ea89c" . + "4a820dbc6464d698ca559a8001eef09afc44f94dbb1450692f752c04ab8ea89c" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "095e684b6edbebf4c78e6c3107f39bb84281e99a23b4c320538464f28a508411" . + "11510180671af323d8c0e8bb306fffde54a572069420551e2fe0f008ee46a640" . + . + "35bbc72f1e10835fdfb25ae3e34cff58f08bc07e19322e7e05e17be81226f98e" . + "fc84d3e5932229967116a14fbc278d45039de83dba2f517f957440e117a2b234" . + "9cf2aa62235885c1016aa11d160267ce812a1579a973d10f793141db0dc180fb" . + "60cb6cee819b3e77c947baa2d13c369e3005eda52e53ac122dfaaf61c37d187c" . + . + "83ca8b3d01b3703ea522be71ad2d1dc736dc96d47a12ad7e3827e402872f04bb" . + "4aa1f4a1f52956c837ad1126b6f7e903fb982b6ee61dadd5d47a86cfd27c7e5e" . + "da58e72c5b56aa7c204ef4061c35fa16ee4c305c276884851ee1447b75d52488" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ef29af771c006090bc589416c21e762c3f1cb2a31a8d9818279f6b7b29c19425" . + "ef29af771c006090bc589416c21e762c3f1cb2a31a8d9818279f6b7b29c19425" . + "717be593db8e5efffc77cfe71cf8e528acfb8610bf41d9bc506c1c7298dfcd79" . + "c36c5e4e5193786ace453307a2fc1e673b173608ac4d5c5e026be147d3d585d7" . + "7c6970a5042563f5bcc63207a7ddbe85180bc29e95b41c91a194fb5b8ee5e584" . + . + "299679428886fd014607d8272843eef3f6ac4a3c3aa1996b91c0814b5c81c4b7" . + "74b0927236c45be6812e4afdf68ba736b487a002d7d2705d6d33def09c1f66b4" . + "9e16690d06dc729b371bc0a1cd8212c013f2fc8aab73369349f96207987daf48" . + "32f2e829b2ab8796464dd1ab744f8420dff5ec270d6a0675e2c10158b43f5ab4" . + "84c6d1692f828336e50f39db33b95871e51bf02f7edaed56144673b6f4d866e6" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e1699fa1d7329879325ac6a5c8518bc14d371d3f713db70f5ac5266d39c4612d" . + "e1699fa1d7329879325ac6a5c8518bc14d371d3f713db70f5ac5266d39c4612d" . + "a2cabda81d87b31c6976ca218f68b4cf2c11f4d6b7e7f293db88a332be775b67" . + "41e0f54dddbb4d5ee20d07d008690dcbd0209d52c69a48e6d37c03c4c986d1b7" . + "e3b0dd1d83173708d427af9a94e72b62efedd7391891ffe0f7c19e2ad562124d" . + . + "a2b72c560c0bc5ae61a996d70ed7b8825f27952e142e509f71fee126355a2a3a" . + "a67385d8658bcfcd955c128f94b694cda701f0596cdb14401a1d12b319fc7872" . + "88d90ffebbda29f629e13a66d5436a28348c132c61587f758df7d094f8f7cd62" . + "b96bcb97081dbc4fff9a48cdabd44829be5b619d6645a5cb548da46ec962c5f7" . + "98c9864cf9b0dd77d57cc94b5649a25371e9bff1e71d6343ac52ae4b85de5c6d" . + "add5a5749b941e4db2e94caca31632447cf42f7907eca320ee8f2fa3753b565b" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "82cd02eb3e5c5ec93316b65722850eb8ae049bce0e741b2fefd74461b34f69be" . + "82cd02eb3e5c5ec93316b65722850eb8ae049bce0e741b2fefd74461b34f69be" . + "078799ab3b08187151a27ab421558f0ebf776765b08a40c5c5502187bcdb23e4" . + "54b4cb46235a54df69a2920244d7e25355b2894e3adb6d1fa2e8d72f1f02c575" . + "fcb890bfa6b33a05ccf6ebf66a6ae3d25359c59c54c909c3b2d96c35fcec4aa3" . + . + "67c19568610bd2350c17620b0f06618af833342c6ab0c89caa8a307735f1f2cf" . + "065b0b2722636733b4de7d108d3db09d216fab8f596182ff9ff57fd6a8d7137e" . + "bdf448efd15e55ffc5b66c8ab743637ebead0f9e273f7cf60ea30ef50dbd6401" . + "c32258116fc5820123fed50bff6cc339d905df30fb9474f7cd5b5abf5f7c604c" . + "daace3b589d25b6c2275c538e4306016131ed6e0f7aca4e3a114b9df907676fd" . + "23daa3cf8628294382c5a79f94a8837b10aecc82a1ac805f0029f83f661812a4" . + "fe1f4acc9beb842be0a81dfefa11e651db54484b387f7eef65ad5a52913a3954" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "258fcbc673897e304a4793c3434dbd04565c4962b131d0d8b4358bdfccf0d467" . + "258fcbc673897e304a4793c3434dbd04565c4962b131d0d8b4358bdfccf0d467" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + "dc83badbe5ead7589dc4d479c2f4410ff9f325e61d69b3b594cf2437a2f5a568" . + "4964779b68fd3fb82b6f3a468f309fb1f8cdb814ccfba0a5aba4f95b3c5dea8d" . + . + "3672ecd03cbceb11fb9badbf04903033f5f159cb8998194cf3cd8b517da68033" . + "1857a3dabdcb56d794daa4ac8f13de0699a245ddf68d1f8ed200fdf6f8579b3c" . + "8d4077e7a697866d311c0c1c6766720cb6b6e91d1a53a53d818fb23f7dcff194" . + "c46f92a5d3fc157df70029e24c6b8bdf27279cb878dadc3cf689e92d429ad404" . + "d72c2f1183880ae8009bc2bdef404609da89c2bd0722070739d05c9a800b18f2" . + "39fcccf7d5884fddd7df95947ac54e2b6a1242e87a255b3feed4a851a94dad04" . + "3bbe71f60356e7c417862638372c0b76c0d874e11c77dec4cbfbd86803d97eff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d0aa1e145122b096d742492422a5d30655899daf3b04ca45d974b588e9dd441e" . + "d0aa1e145122b096d742492422a5d30655899daf3b04ca45d974b588e9dd441e" . + "01862916a7378c7171be10e8e42a2c8fe83d2e8343306cf70b3ac95a72d2752b" . + "8ba3bed88cb67a6a413b21d86f4f26f470c3e4dc23e02818344cf840e40e5899" . + "600c85a69e2951148690da767a6fc2d3020f70d610b8c7c8d29de757cbc3f713" . + . + "84f2d01c6cbcd0f16d389911c474837c9e0cf092ec463da5c14b20e01bf0c1e5" . + "618e60b6d5e5ef4400a09308aacdbea852f12e1212aec2bed94e2763e8888c75" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "a91dad2e631b75b945d827cdc590ba953d43386f1f42f1baac1bc03250551645" . + "41102d497ef9c0871e7a306f1a2d477a7e1aa21a37bb0c3ff1ce2d2c1b9272e2" . + "4654a5f3aa426393fb544ad2b6cbf873686d9432f42b1da5074a3ec8e1531d4c" . + "d401094a6ecba495b83bcede54485325f5d9b695329864d7cf377e00deaec9f5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "599533de4b981cfe8eaf572d2d68daf329f2c1b0365c32f7f0f0b3a4860ae51b" . + "599533de4b981cfe8eaf572d2d68daf329f2c1b0365c32f7f0f0b3a4860ae51b" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + "7f3567a7a3406ab73f3a7b5547c125bb30143823f90208720baeb448333c6cde" . + "7dfb08d9eeeba7b7d85d057d14b3389982494379bc6e3e904b6cfb48afac5bdf" . + . + "04a709d54bb57115299895b121510e5d83a103d65a475afee931d3caab99d22a" . + "ab8d5996bfb9fe10291588dfd977277e5d49f07a1e209f10413f7efbaebf597f" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "11ed7dcb8ebf8916633106a8909484a1a62146df83fe5b70bd2676391cf1c9b8" . + "228421b97650072d3823cbd9a8db5396d59ccd073d0af3556551970052984de2" . + "e5949bed48b7d894f40bf3cc9131b1e0a6bc48d6c7bc46f9bb796ed4c1fe67cf" . + "091da9667877a3a56a0f857f0ebec93114f10fcb901bc73945b57f67b6d9501e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f2daa3dc4291b179c87cf4fcdeba40ae37edceb7118fc3a39de358352d8aa8c5" . + "f2daa3dc4291b179c87cf4fcdeba40ae37edceb7118fc3a39de358352d8aa8c5" . + "bb1e6a7e2aed004a12a264bff6a8bf852a5922136e4b11d90bad4cd7da812ab9" . + "c5bfbe7c9eba3f79554609d329bfd6ec6b3aca6e1b0563e016c964a84af8ac42" . + "80d56af57f6f8c4b61819e15d8244060600c294be22775ff6f40374d094063fc" . + . + "092d9ca7cdd63e796d749588ba28909894832006b4e437f3dac93131bcca48bf" . + "5d66ccf2258aad2f449debe0631da41d2a3b22ca1fa68a1a896be1491d7f31a9" . + "69a2077960df86512555e22aef48d93174665e73d9e49f7cc077347ab7a9407d" . + "44d245af27f75a1d0b72cb7069f1bbc93ccf9b69d10b8395b3e0cba788f6ad96" . + "d4d0f57289e3f710fadf3fa7681f248bd88455210c458083f95984f5a00ad9ee" . + "e0f21b5354613c96b4e27e1e6833a6c4341765216f987d2f3d7f93a0fbe84317" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6df92bdcd907809defe4ac6bcc819058656be0abfb169d6ba7784a43cd1dbac0" . + "6df92bdcd907809defe4ac6bcc819058656be0abfb169d6ba7784a43cd1dbac0" . + "a102b8d1e74525fa45cf9926c0c67cd7acd22add36347065b1919c6811b97206" . + "2c0673b53294ea921efcd07b2c69454e3843a1fa8866fc3dbacd5d25856941db" . + "980a959c564bd9792824dfe38384c36898ee9ef8eb192aebf558efdc9ccb864c" . + "3d7053ad6b168580ca85121e981ea214decf4f5f1580bdd54b2f04e272cd4361" . + "ed3981d8394e6c7ef7d637601e14b53ab61efe835feac5930c1a818e32835eac" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "9bc2f74526e5ef3ff28a81033ff29b8eadfa68599a35f372bbc8bcbec9d547d8" . + "f6fbb7dc3a4b36da4433e433fe552b7754081660cf687a5700473ba713f1ab39" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "7525dafd11c48e9c750ce276eed992e1fd97ead43f625ca68e4686dadafb0cd8" . + "8cf408e23843ac8c3b844130837d87ec999d1a0b4f9b7f4062ed88db93504573" . + "af57d21949e3cf712f7794c4ae73e24dfc855dcd5a147280dfcbf9e73ba977b7" . + "fe7a6980d86a39d130aa623a525b6b405f7a074d0e3ef17854e14dc993ca39ba" . + "03410070f36d4d0f1072f37d1935774d018c17a8cd5612bb9967b7812c58ea17" . + "b7b93c5deb60c5d6bc2d5fccc4f31ef44e0e713152bbc6c7b6c51d4a55252138" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65c6baa3813359bdf211726f3e890bd8bf28495ff65827f6b76166ab01def0e2" . + "98d1371491f8c6b085cf86905099605d2a32d84965c008fbd63d2dd864e6b08e" . + "18e862df0117d6b48f6f2e16640a6c7d2bf94a61d7c591ecde36221be574c763" . + "147c8c948858819ed95420304a2211b3519535de5dde2562f682206153bbc62d" . + "6be0137d77c4f2e04a2b55e12d9ea55b88a4b728859606968028d54a3a791a5e" . + "37b6bd03d0501bfe33abde07d421741bf4d57193d4ee945ce737b8f151f4676c" . + "bea471d65633eee957f43669d5f2719c9beabd1fc10e2f97d57c8892d03be21e" . + "7edac4d1c9fb586aea378bbe552e1f4bd69b42fbf39d7862f292d29ed53a0537" . + "56d8ab3198fcab7886c288d6301838d1a4835e06a43c7675082bfcaa66dc8a4f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "3fcaf3acaa6f79392bedf58f57497e0cb8e90185be9aeea0297d81861b6c58c2" . + "1a260eabfb460beafd70064e41d8e2a73dac7161d682ba5ec006b803023f7683" . + "8135bab747e5d3b63de017215e33296d2f3514a19fe1ffb29bf469a2f116d880" . + "84819df6eaba1a4969b928e8dd13ba68dfbf6dbf407b2f5822065b265ec65c1f" . + "62959577bf841db4149f11f82b7f26ed7ceb410415a8e8d40ce00e46911a4833" . + "89e62cd368f85bc8ef66a5de3502ef338ee35e16fbb671b6d4901f7de0a22cf2" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "a67a9861103ebf99a1a215b29cdae2f14a1eed3910d876d74de9df41b037a36f" . + "e627710d7d6a4bb8922136aee08bc4b41249873d5fc0644addbce5ee135ef01c" . + "53535913557f7ee3f3179adc6f41bc52fa5662db85220941ed4d28c62a6a67fc" . + "36cc75527f8054858378792a17b4a8ce19fe2b1064108b18453d8442ce99b9a2" . + "4d5823d02008f18e9e021ec87ac48c2aae9bcba8e02f7796f210d615645fcbb5" . + "15d9b565869e2adb825b331a2a7ef7a12c8e9c51b7fe1d9647f77a80c90c89d5" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b590e4bbb3b55743295b5a11b8c1d159f66e22e49c7850fea8beaeb62e10253a" . + "b8ed4b81404c79c7b27d1c75c700528ab51550975ca3ae0508fd15ad1905111f" . + "0be81d7881ed98e5381911585a0f2670b0f073d32dd90e93b03c00e748ce1467" . + "ffb8a54c17b5b2ee2b520bb07c76a18434b337b6287e47a5bff340ac9d39951e" . + "c723a45b165493e002c235accfeb5360d5c177c5ee0233cb00f84e3195ff0741" . + . + "d03d89e778eb0f0e7dcdae40e76d1d1d7a8c7f6cc1ca2b3c7a1816b1d731f2eb" . + "83d86707482e000476ccf805c13f368783e15cfc63081d761d802e55647772bf" . + "e3c43683d8ffb5e2817327ffae2549bea0aea0f2474f2c2865d35f50a2e2504c" . + "7f7b5273556b3dcd78dbade7f77928d4bdb0af7a68cf5e2233d6a605ab13f943" . + "6313c1050be875c834f3ec1cd2811b5092e81b888ac17edc92756ebffce527c1" . + "ba380581d3e3c4313fcda665042c7653eeabc080b1a970d972625a4462df3015" . + "66425ff80138771c2aa5a598c4e86dce73ee3c5484eb447deaa2fca8a3cc54ae" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "82a74e8ca27c6d1f1f5a3f0a2bb92380269f9b9908b33deb1f9bbe406d37d9f2" . + "6e51edf4a80a6b3fa0d853b73ef9ae7460efd9af4f1fa7c1bee4e2c5cceae8fb" . + "81a86fe2eb07cd9254cefdba514ce2fb8d4997d2abfb7b056c817e4fabd752e9" . + "de2dbafe29f3155fc3790896726ab4119889c4475c2b466c66e44341c59d5ac7" . + "c5f3836b6dd4c488ce39e2ac945c3455a1c02fa2099228a61ffa020fec032125" . + "900e36397fb8896892c94aae63b5d0580693b70424332eb7f755daebc4cfe9de" . + "d616c49dea7354d46be09696e976118096e544c80502de1c64b261e720fedd50" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f9be91ecf491addee07fb6ea9b7d72ee7751886eb90878a864daf334ff78f3ae" . + "e61fc41bac13258c248933e61e0aa55d09477cfb03b8bda0741576c428aae4d4" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "9d66a553acac794d6e56c6f3947da89bc1be58dae9fe6bd63a1a89ec8b59417d" . + "b25f6194c1422acdd86572b739a0e0fc4d562fe8947327c60c8f3505c60289c7" . + "da9e869aa96f41dd3aca2831397f9c2e411495515628d8e9353de64f031c49d5" . + "7790185e997f18d85175c75b0852b10557d5a60a6d15335691ee244298cc2a52" . + "344f95553612eb787fa47fa1eabdea636731307de0d15ec0be8a51775f205544" . + "078917b68aaec6e59979bf92a8a0beb4a1a74b7c39297cfc8baced28ad942518" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1186f5995033d3f7a97b24d7d25da6b9809de3c845d7463bec7611ddc284a06c" . + "1186f5995033d3f7a97b24d7d25da6b9809de3c845d7463bec7611ddc284a06c" . + "e2bcc98472b4eb3aeeafc7857daf9a7dc3e1e169ea3a463a41c1d74d1d984bf0" . + "8cb5b8276ccf71308ee9e85ab1cf39e6f9966ee83da8d574edd5af5f37efa1e9" . + "b960f54f2e066e5163219039fe59b7afc5a2bccf51f2af5f5b9beaa0540f672c" . + . + "0497c331a43262fa87282dfc816f62788c039f3eb0e9a7e80b3602f0ce967d36" . + "5e294d404b88c09342a878ab494d7e47e895ef3ea044b70329dedc946472a571" . + "2ebfb356a09b2ef87f940fe675e8d2c6e136dccfafcf6b2767acda0726740259" . + "8dd17cee2f42720faa0c69c0790d609f813c29977ae131fafac4b8e6c88f6e74" . + "bac7ef16eaf2c4ff987dbe091e294bbb3e72193575e8b1a891613820abc9b7de" . + "ca29c8c5e2513ced0da637a5c4f1577ec65be75ad81675fbaa8f6598344b684e" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b2f72c1ab6bf0aedcacd8cf871cb56614147155ae0ee07e2ca0745614d696118" . + "03071b9b1b324196ca4cc13ce0922f3bcb13b498e71001fac17264bd562d5da8" . + "d0f2253f38699dbe18d6189401168f595af3a3597e27bbc9c0b6b355b68fd827" . + "766d7523b5ec230195dc4a681719f5ba8c070d99902a07fef69e20d9f12c8263" . + "5a4db65ccc2b3de615d02569c5186ea152d0e86f1f48ddb78803ff892255cc88" . + "fa3650e5ab9d221e8ec3e613c9b0fde2b0c4cdc3e28a5830f81b27ca270c9708" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "815426df1ba4c2b3a5a53b0267029c84925478ddc2b4f7ac108396878bcc5cd0" . + "8004c218d07db50e7f908f8d5b09dfb6975e558ee0ea309f1829528f55945786" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "252d9837152b2f7777c267b730bb0554ff7fb2d013fe877d82c9eac53cd3a7b3" . + "6fb5ea98aaa2217b472ec519ffdedffb8988e353b455cd688fcde830592675b4" . + "93ce28024ea7695ffa7343f1d5d22ddd417693db08fe7b06c69123cefd330883" . + "58e032b15b85eb4a8da88ea8daf6ef71daf1437a6cdca556ef5dfe3299b501e4" . + "41616f170e9b77048d8ca04447438f0f727debae3e92056b37d5a75c7076d158" . + "e38e0757b7fac98a7b9230615d4075c72c6fd3bbf12ef06bb699606698c4bc5f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4fe4d7582fb4283d9bb36cf9ddbcc6149c716dbb9d9bb53b3e23c95a0f460494" . + "4fe4d7582fb4283d9bb36cf9ddbcc6149c716dbb9d9bb53b3e23c95a0f460494" . + "35753048b4635df45bbd3ff7de8649113a6ee2afe47cb6cdf34105eb28abbbcc" . + "61f859295316a18d9235272671bf2cb76a0a7fcb6e5af37e9037a197149a6827" . + "573cec80d76c0fc14405c1e9b9849bbb44ee74123a23c5f122bccad3daa8bb8e" . + . + "1a3da913494b4875dd5648c2a0f086941a58eb2cc0c100da8c9a6403e192bfe9" . + "a7a687b418b299b4a619607185422405d28ace57e738e2c4cfac0d9b30abc8b3" . + "335221c4d0d949a73fbf099c505b78bbe23700a423c7907d7d6c8886b7bbe08f" . + "a0b36f7bb6960aa3912048e2db937a6a9e7ef26e32f044a0417474f1693d5dd8" . + "abf0765fb7939bebb22acef8ebd4e97e15c6a413325e0da9bf022c5742c11cde" . + "00689177c0bad6da156cf923950989f675c9ee5773878e214c08fff68abef425" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d5643b4f6a683d933cd5014ad1191eb5f716d11f056b2f6e2b81b2115194d9f1" . + "d5643b4f6a683d933cd5014ad1191eb5f716d11f056b2f6e2b81b2115194d9f1" . + "bbf67cb28fbc7c697399907205f472ea909e109a3603dff69e608e03015625f7" . + "d08379aaa80753afa8935cd2bbb540673cb8ecc1d00f5ca51a4d30dfc1060438" . + "826c5c3fa88293a30e11e92808117216c7ea99abe8bb7990900294ffb236c43a" . + "98c90fb8e17238dd1cd14fd8bb6a02f4fac1d8cb550d7efc288bf0bc6965a777" . + "f7c1831156f19aef9b91cd655c8575c44155a175b726ee581edaaf191a52d2f3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d21fea105df84efa5d54717888bbbf5d867a5ff6c3f0ff39bf3889decf223916" . + "11c5b3f2b334a044f1feb70620701e69e93afb9f8c17b74b7f1adbe8e087aad2" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "6ac2d4f4dad6a47dbef2ea2366a0c58dd829f6792205755a563c0aa40024f34c" . + "0cda109feb3feaeaf9a78708b133ca5fa3d5ed2dd02a29c412391b810e8346ec" . + "dec34e88e7399155286a07596b00f05b416e466b6fb1b1c823bf86fb27fa7eb3" . + "df984cf5df99c56abd2165d4e3af4b2884da82bc686ac7da9af76571680bbbef" . + "6a180b3a19447709d13ccb5586d8310b191f3ee5fb93c2beea0e3f115e1dff05" . + "c9ece2908659693491ec10c0c650baebacf6f75d933ad00d36c3a99fd9a940d2" . + "61d221c50a483740d39e8094e00ddb1c4ce7907ab5c0c981a6873676de587b1d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "af9792569e0fa3e31099a7a7cac8238e5eb08cdffd1de161d3e70688efb2809f" . + "45abe09450f4523691ee64eb830c39d6e55ad591dd95bb67cd5879c08c461105" . + "dd41b9b3ff3c10218a06b43d9fc0b5f67abb4b27d72556ead84dfa406e847b5d" . + "9bd3079fbb8cfde89adfa80d38a29356ae44e3e10ddb4f36b70c63ea600d739c" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "3a380ebd61b0d092983f4dddea2f46ec4ea52c4dafee8dc25aeebffe8c8a9785" . + "fb0a880e18002959d5524206911b4abb552474efd1c271f828371f1f846042ad" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "ef12b7dbc85ddbc61b62ef2fdbf62d55561b8005b90f9b0ae23f2c25cf91ba08" . + "74a9fc1321d9a2614404d95f520b2db5fea0ec4e198741d030df1cb9444c7051" . + "4aea384f08ad57490cf1d537266ac15220504647a057d2bec9f0a949967c1059" . + "b7e0fb4ec2eec5d461bd8f312a64ba34ee944f6f1a1aac1f09a71127eb0d548f" . + . + "ebc3574c4139cee8ea340672474ae50ca52e9a22d6e1586912eecc9c90c8dcb9" . + "e3c7e2081c43c99ed05e7751146c343e774294afc7288841340c3dd240b7d599" . + "74e91bc6a82e7f088e8ae4e702e8be8f5c303234280e1d657e5c48c7f95af6b5" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f75acb833eeb64a250316e6711bd84bcd72cc3a73989ba8fc886adb9f7c6b42e" . + "f75acb833eeb64a250316e6711bd84bcd72cc3a73989ba8fc886adb9f7c6b42e" . + "5507f344d6ab402dba848fcf592334ea177c6b4c286818ea80c4ff4965146eee" . + "d3f562dccb145fd9f280d078012ceaee8d1380fbce0b3687957858f477be8ae3" . + "69f121000ecb7f27a2465c3d87a25b58774ff129209fe3c43494d43e53746833" . + "7f3f01d749537e2c7b63b1c8a6062e81d3b3fbdb75129eed5ae986f2677220f3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "929d1fbf1b1ae53f4714a29636fbc3792bd9e8149cf26fd71a4fd0a167bc2ce4" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "b5af8afb890fe9eb5156c7d8b967fc2e7dc7cef312607b35ca747ec05656ddb7" . + . + "dfbcf6dd6cace4384e3dc929dec9fabd522a7ed27d463892eeaf827b1127e7de" . + "8629fde56406ee4723d3446ab2295443c27b53b88d664ba9a39fc7862116f3b0" . + "c21f418f05ef00f955e2487a3b0f306c7b468e6c9d41f8d59a4f659a62d75b08" . + "9681c36c6fd0797f547a2fe196ca325e865c6833035675c5ff9178a1626d9357" . + . + "5c4ba0f8e6df6d58c79c81db98cb856e08fd22dbb86f2ff174912ade66ce77e1" . + "9ef35378a7dd8f8bcaeb0f24a2b7fc233f2f46dbdb334f439cd49e7e57329623" . + "b18f123907b589817454a13adefd2ca757766afaddf3414175f988e99ddced9d" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "74d92215f5cbe47289fd1951d97c086334ec664a69060bccdd498adb33d48400" . + "4a3519bec0bfdb3c27357229da96de3dd7951c672f9322a7577ec622206cdb43" . + "e8dfbc8dd0444bd9248c1acaeab818a07245b3fc84d476352b2b89c8f565cb60" . + "3678f24210d3c1f66b74705bd1b846db96ed20097e38b55cb2785ceb0eeec6c9" . + "026390cbb7f8364a33cace74852f89fe413bfb0229e9093c3cd4f50521ab91b2" . + . + "c25a0137c4655164312cbdb075e28c7b9f68a66ccc5bd2164a6d8f31c90b453a" . + "8952b4ab00882a65e4e599a513b610da91e88614c133236d94ad3ce905701417" . + "82df32e143152c3b0c0e9a9b837996ff37ee87873e6d7fbaa544f5beb6bd6dd3" . + "1fc362d7fc573349ca7ad8e4a9c27bbbaa62d14662fe0dc4884c27c160d8555e" . + "c25a0137c4655164312cbdb075e28c7b9f68a66ccc5bd2164a6d8f31c90b453a" . + "8b6ca878604068137c27bfefb8904430d63b2821cee06d39f68a3096f609cae9" . + "f8a77ef32ab49848b2b423093874c5843a5c4ae3bff3558b9106aa2a57f70f28" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8fa8b500b698ec3196b744d741891adec97477f8459c8ac5cb8664e42bf2ac32" . + "8fa8b500b698ec3196b744d741891adec97477f8459c8ac5cb8664e42bf2ac32" . + "5910c07af8fc764ea8b46d1e6311e30ffde4d525c5e296da107230cc9b52a54f" . + "46e52c7071a53b41ac3376dd0da723e4a6ca68fc8ee7f67dfefbd9f36bcc7767" . + "43c77361f4d64235964f07546dcfafa40dfbefd41b0240fc38469e90a31d5f3a" . + . + "e822eb7fde2acea70579c43ef626750f06942ca1c62569ed5aa4d19bef7ced81" . + "0c8a7c2e6171c7018e1e106d2ec24f345e9a46d2d078efa9bb77489ed2081a4a" . + "323f6ad3dac939cc9ff484830207b1ad3b7fc9122380d5e72dd0bbe4440b95ed" . + "2bd3e4adccb26ac299b16196e2f5b934ebe43089849db8885568576334e49c45" . + "65af4a963a8f4f69ad7c70f437632f7d277883645baa09b40fe5dde39a745853" . + "1c8867f1c5f07590feb8949775dba00a6e4bd0e8a0a6afc4f03ae1df0fce01da" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d678eee227ad2ad66a25d3af124e2bffabe512d66d071bee954807e3fc733162" . + "d678eee227ad2ad66a25d3af124e2bffabe512d66d071bee954807e3fc733162" . + "1142ed5f2e68c46bb4242e5ea426c80cda7f4405594293582fc4e2926d70cd8e" . + "5068cfae59d8171d75ea869a69eeba84ed7f1059e715a9fffe9888e0f3e354ff" . + "b0d6dd1401f2c6d2b094b43daeff1b00f0c0ac0fe7570b652bfb695018e23477" . + . + "bb315a1c9fec69c2ef96baa0a0dae445c7cba5be6ecc61128b3f381942e1eaca" . + "8d10bbefc88d79cdb217159b90dc230408866af52a4ab6f246497048058e9047" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "b55bb7a3402acbc04a3c6855ba4358158b294b52347f0c863de03ebacb13f2c7" . + "8ebe15c615e09e3df9cc1e9eb4cd08e76a9268433dd929ed13574abf2aef1d9b" . + "05e0dd1b17d60f80e8ae140561e1226352a7ff06d8b4b35edf984c4762f587f3" . + "1be38706daf9e8362e6c4a3bd3cc1476fc08224c195610f06ab848f79ae19f70" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "853d9cb34e71ac6dca18645627e36b2abd5f9e6031a0b7db2b6b4a52de2c60eb" . + "853d9cb34e71ac6dca18645627e36b2abd5f9e6031a0b7db2b6b4a52de2c60eb" . + "7d090b1d7ca951538dcbe500404e1ea9f0acd11475cf709f85198aed1169d39d" . + "ac857e2e326a915ae37a2dab396537ccc5876c54f420a022cdbb1115db086e8d" . + "11efc981b5db2f1668f861d8310961de28f1d9cabeefd80c4a5e8ed2214df59f" . + . + "d5b0463799830b511db9d7bb5ac00733014f56b0adc3315b4284252265fa1a55" . + "19bb4434f529ff0729af6631088420592ef4797058a27f44c5a832c6a2ab0e37" . + "d9f5ee82e8e10a05a8b9af01753951fcec65ed6e9e5dde1b96685e3c1e18ad0a" . + "0c322a8fe3aa0904f3ab49f65317d8d020dda46e9a482ebae51b8df972e11e65" . + . + "71211ef9341a3e5b09cb828ef53ee3db23dba429b6a6067580d7f39d0eee7566" . + "05e523b367d6d2554ab376763688abfb0739f9639a344deed9d1fb7a20d324b1" . + "82932ddce217e2199c3cd9ba126ab94c5a0bca7f820ad501ad2f39d4dd9d90cd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3a93d0875a98cd3c98018b18b2b04794df2291a24949aa464ebb30fdcb8748c1" . + "3a93d0875a98cd3c98018b18b2b04794df2291a24949aa464ebb30fdcb8748c1" . + "18af155413776f483a491c6deda34523126b33c7a41f3d6edbf16c8f57a149d7" . + "0a8b8af23d1cc8b74da00dc8dc63f246fec46acbf6e0b642726de28099aa7924" . + "4db9413ad25e7fc2817419a68e625f784e108aa3305962813c73c752bd8a8a59" . + . + "d2739fb4b31daaf30171379e8cfd8274062a9db8c50eb1de79436c4b7c94c974" . + "7645dec216f6a2ba3e17b59816ebba609ce012019ef6ec93738ba17f74bdceab" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "0eae78c97fd728bb862d60eef573feb6af6740f5d7c7c2f4e70a3412cf9bf41c" . + "f6464dba56099537bf249b0000951a43f3436e5f66a97cf2ffb6cc8c31a4994f" . + "66425ff80138771c2aa5a598c4e86dce73ee3c5484eb447deaa2fca8a3cc54ae" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "43dd88084418f7a7d45dc1eb56574032f642ae76fbbedf5d42587e377a51ff94" . + "43dd88084418f7a7d45dc1eb56574032f642ae76fbbedf5d42587e377a51ff94" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "a4d123687dc72513287a48a0b301d69ab581b29ba10645255ab8d95b1df45b72" . + "ebd4fbf55c8a71777157361c21d8e9f373b6172c133fbb7e61c1fec78b8e9601" . + . + "ba03e3c752374b83322d43173a28695ba50ef7b262ca798c3ceecb8fdc9c5faa" . + "ab9af5b145816eec3a2a48d9f04451993e63011d1f321e7d35bdf098960afc2e" . + "84ccc81cde19eee60f2fb6697c96f582cbcfa262cb4c921c27a05fe16c159050" . + "17745a515426841697251425c9c69b3da00eaa930034e1ed7b1ed9ba7d8bee72" . + "0ce280ee62db8ba4470e88d3da45ff90f9b1bd27c6967e4bc44779c486edbe57" . + "408e6bb947b358f09647f80e3448249139fb911dea116857496c6118550edae0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "28239ed87d3d664481864897a2a91f471f6646f01f166fc5c1553b4b3990f142" . + "28239ed87d3d664481864897a2a91f471f6646f01f166fc5c1553b4b3990f142" . + "bae7bb9758a66e8127cbf76a5d47a465eb58ef64332a2154809b630a440aba25" . + "21cd56311ceed41987fed998120b50ab6609c792d5e8ade6271025a5f4d14d3a" . + "81f46e28145a86593f69d57025cb53558365eeba0e43801181ffe63dd137b4d7" . + . + "aed356eeaeec6f969ae120dec7df68d5a942e0307093a5382d5a60f1032e57a6" . + "017ef305260f88920efb876207244e18b6255e9af5a13f2fc99755edcd45892c" . + "438dadc9115c050b9c2123f650be840f50802fd85abaacde62e6713d5dd4c02e" . + "4cd688b851f03fc7d6c6bc9931e8a2ce4cdcd912d79e794e007776bf5aa1c5c2" . + "aed356eeaeec6f969ae120dec7df68d5a942e0307093a5382d5a60f1032e57a6" . + "6f37090e112cce2cb4f229c9c24306c18d96701578e6384133e3a45700a42d8c" . + "a7b23fc78c0b97fe0ec723e737a95f975fa55b102bc26554a29717de9e810e22" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "680dc235d7f95cf46f4fc9d437ecbac4e581f16a4246ef4906c9960f96b30e23" . + "680dc235d7f95cf46f4fc9d437ecbac4e581f16a4246ef4906c9960f96b30e23" . + "25e6290ab20da7f59ca75f54c349618ded6ed16ce3fb398d9501f77fb340bba3" . + "2c6ffa67fdcb2a38e6e949138dfdc92db3ee0b2202e7a060e0382d4bf241dc03" . + "b05a8f693821a4f773ba09e92468c02ca0fb17ed3801145865d81e1ecd860591" . + . + "44effb6abd2dbbe7cc06f509bd379a9a44546d5886df12e5ebd390063ec2b887" . + "11499efe3f4db839e08e66ec13def879ad17406cb6ddac8c1e8c504e8dda4cb5" . + "09a7620ac4f73286cd18437ffcff276be74a18ec9ed283fa799986f7664591b8" . + "60efcd3bf5aedcf4ba833f0a01c6c479eac948b9ebb5e7b33d9a0adfd6a924e2" . + "ab76abba591d0415046df70503423a2de6e9ea8e13999b0188bfb57bc5d97ecd" . + "2febfb9ead1e8807217a4e4d861f214b8d0ad03a5bdc2d7ca973b1161cf64672" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4567ecf1e7f9b058b407bb72271720acda51d77f824a1cd0114acdcf2cd2d143" . + "4567ecf1e7f9b058b407bb72271720acda51d77f824a1cd0114acdcf2cd2d143" . + "e7371f2b2ff48fd2ac4ecc87ed6b84b33068eab0aeb894c39f52d42651cd79c8" . + "3944cf7ff8ba7ce8b1552123a77498ca660c5a0884bf034f8d5b5c0ac1a8427c" . + "70669c6d221967ba9182d5e54fd8dc45f7ecc35069ecde51fb804dffe3c02e4a" . + . + "d85abcf4ea7d05bb19b2f8ad52200b9b5e0d659ba93dcdf1d4503b6ac4862931" . + "3c4713b5db0f2df6af3a775012dfb5f1caeda8e93f9830c14cfb5cb15ca01d54" . + "4d5c9d932bc8c4a6850b7c38b78b1f395420ad314fb37b75488aee1975bf2dea" . + "cc080cbdddac41c08456c42841304c6bbb7b677975b4f750f14fe8eb4e455d53" . + "be3d8126e3677a27328e5e5ce2e7f313d01af3d5fc6dde9c3f6ef238c9327705" . + "5d067c865dacf77240b611a7b556d3be835e1da378844766bf859ad0706891e1" . + "82932ddce217e2199c3cd9ba126ab94c5a0bca7f820ad501ad2f39d4dd9d90cd" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4edc2f2b983c3c62873f4aea37be9c5f8f45e46efc61ff936bbcc75f4d406ac9" . + "4edc2f2b983c3c62873f4aea37be9c5f8f45e46efc61ff936bbcc75f4d406ac9" . + "1b1b6515b1167be2f0f5693b9d9be7e0a55c948cdfaca542c7ff99cd58a6c704" . + "c9f79ace09e6cc88012868ee045dd92bb9c3fb8435fc72a8fda600177c3cb22b" . + "ceb3dbde5f786628f0f23a58f826938dba6bc03834f5e8677af46e4e98fdc057" . + . + "2bb9bccfeec2a28a2e17c847f6ccf47b10af605769da7ec10877b27275c02481" . + "11a966cb5b900799f4eaa1f05391be1184890ffec354874f3d5ec4b0a73954b0" . + "07b1dec88163c8c477ee87aedc3a19160271bc8c4d95afa823aee247f7071d7d" . + "7dfbb8a82e38d1564868867ea313a2410584e8bbffa3adabc8a8ea69f02a5521" . + "ccedd159edf3f6a02d5ec3952283da0a880bffef6bcd3415c1e508a92eac5839" . + "d10e87299066ef9f650df601a9135272906ffb84174146789c069cd85dc0daab" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9802e6abd9e9ce81d6d0871815ac8f0cf2175659c1d442edb8ec7725139436fb" . + "9802e6abd9e9ce81d6d0871815ac8f0cf2175659c1d442edb8ec7725139436fb" . + "a2797c1dd1fc2a40af00e42ca4150e8a5f3abba278a4e840531bb1b66c860e13" . + "f3f1d323cb9f03787bf5fe062d970f874482ef20bdfaeeb9e53e10a542086ed3" . + "68c26d7c0f90802b9bc2e38974ff995f678544fe35da0ec9d35fb8025cf78c77" . + . + "f1f2c4c28d262af6cad18fe904f23504083361f691c75b40c83d083ff863accd" . + "8534c73e650ac6a2ce2c15caf4da89063683895044fb4abdf7f9c8bff9c03956" . + "300e710438b7b1e25ba243d92a07f63a3e4f9ae8320868d9076271750e855f71" . + "d9d975680e723e60622e6f122a8372d983efd1098b7683f8e705c9758b697909" . + "a9f0e4bfd0e1f58f6af8a034f17bf1f3670c90cd30136b036f9d6297548d73e1" . + "8ae31ec525f521b49301e789c2df60b65803a069b4067805f277b217be835148" . + "f93717bbe978cdb82121c4c27578d54ddc326230479d12405e475a841b554b86" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5f760d8c0d3278135600fa7474e55b99551778e6432116cf55eafc38b0d5451d" . + "5f760d8c0d3278135600fa7474e55b99551778e6432116cf55eafc38b0d5451d" . + "ef0b82abb2cf9ea8a649712dc056a9a7d8440339a07e090079f28f7e55ac7bcd" . + "5bd4192be3de520958f07d18b247e929b53e3872ac99a35ec971da9ffe640bde" . + "799580a28aa3b8723e9a369ab82532717b42a3bc63eb7da10133797d683d3211" . + "21ccdc998ab9304c2fabe3bce22095e86709f1c241be11e31197b03ec97b9ebc" . + "e08a4f33a2c4abf9aefb6e26358f262a53a5e3e5e89d41669ce13560cdbca572" . + "ef1f7e3d067bcb6720da082512e1d1cf741d727a8567afa882336967cc1fc26e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "6347969c34f1b8cafefe3d2937cfb87d032f640cd9393ad20e97834eb35de033" . + "0e96a0fcfe37e909cbbae20ecc5ae83105f26b6eabcc79085727e4839ef090e8" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "e65c15f952b5b517a77a838579b0cb9d62465f2dfab239226a2d3a9ff41a9d91" . + "29ae050550f3fa175dcbed21f8223be110a80a275554a4e80c465e7770fd083a" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "500b22a926aaa767d1ca3f482a918aa184928e524938842dc640def5a57eed1f" . + "adf5fbd9ba268a60d3f250c08f3b4947572988ebef0bd47d668588efee482bda" . + "15213cf2ea5501407e879ab927107b90ccbf77df13846b5a22ef1454f7ff4c6f" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1409f0e10b44d80c187538851946f724303220b5651b9d983e3ecdc260be6146" . + "1409f0e10b44d80c187538851946f724303220b5651b9d983e3ecdc260be6146" . + "b1de429c1c97d21f21f46f875e0f4b653ef08596db731075458fb85119896cd6" . + "2fdd3121d380a89006ec3fe22222d8b3a02c6cc500a7b3dcddab9bb33703c217" . + "c74e04e637d8de005c87889352fb2557bed1d217ef1ac9f154df170916d4499d" . + "444845e843510755d8146bdf3e532f7f17387ea5f1adb83c671d1fd29dcfb688" . + "ae232d147ac55447410071ed966013a5894e78955057eabb8bbdd17a97aaf0d3" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "786219fd1f5cbcff432178af13c79208a1526b5acf950caf287b16eb7dc81504" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "7feb9df80a870c005c95c92bd0ade084f588bbc0fd422c487288901b809816d7" . + "224f5c49a6eab2967d90eb123390397f4f4989ccc8e7d84f783e43b7908b724f" . + "c163c178708e65277992cdbd0a83fe43a8c37b56d3e1da6549c255740eaf357f" . + "1f1477c27eb2a538fb9254f41e1aa4f2efb8a4095e6b3ad342b4671730db34d6" . + "7feb9df80a870c005c95c92bd0ade084f588bbc0fd422c487288901b809816d7" . + "c06a759870aa136d0762cc00588480d8caac9bede12f9e6fe5a6782609f0eba5" . + "d456a73498bb291cb82e6886b023b4ec50a039c9a3f14e72bb21ceb14eebf4a4" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b10fbb24d0340b148a4e8ca22546f7546bd6c013d4cf668a6c4d36c4dfe76f7d" . + "b10fbb24d0340b148a4e8ca22546f7546bd6c013d4cf668a6c4d36c4dfe76f7d" . + "b4c7f4afcb03b3c7c307aa665d8f5ea392ef6ee22808c1d27cc87273fe05d173" . + "5b9b023d9fc3566ebbe8367427d37ad31d40954ec811d081bfef934125591263" . + "08452143e4af0b4a3ace6ca4d3f02474c734ff0beff9cf98c81e4e9dece668b5" . + "506fa9fd8db28a611eab426e564e51f62bba6e89b34f897a3ffab60fe7defeb7" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f39f2810f7430014c9c779e92b9433e39cb178479f640b3784608cf643a28b89" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "8c96a64770f13a3fa299165cdf11bbd12d3dafbd98ff2d751b680d3820414f86" . + "e072adc4fb93d822fc5ea1552c8f330c150ab440b113d3c955cf02af0e8acfd3" . + "45d8a0d6bb1d7268c0a12151f3fe932802bfb5b59c8988f37bb5554bc57765e1" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "a824e4c3166aa15883147195dd63b34c8bf8bebf59f5d571facaacbf458fc079" . + "cf23b610fe34f162b27bb2ca5a8ab853a03c372a06cd248241c3f3292ff33a39" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "44b034a0dba847393852f3c03a4f592ec4d62e120012f1cc6758d62649beeff8" . + "14a7f208f3875e208bf0477af020fea35c903d76a10e866c3332b7caad852469" . + "403f2100b5bdcc375d641e10c6375babcff4a6df6d556f6558a1dc3bad5f5973" . + "8e2c1dce61e67ba200dccc8f6c9580eba7959e853706e82b3f65148398d3d7e1" . + . + "8bc159c23f1c0cf96375362448810deb608c0131da1088f59b2b58f4b3171de7" . + "ae06ed6716e4cdd5f86be7211c56bbac60289b456ec97b99deb6b3805a712d38" . + "32f8eeeffb6b29054845934dd8358f975a8689b3e1c1a0d1b2e141e6e497dcac" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f27a221e546f1b07bafae25ba955f4e06078888e432597babcf1982a4a6e5a9e" . + "f27a221e546f1b07bafae25ba955f4e06078888e432597babcf1982a4a6e5a9e" . + "0ac5b15bdf71244bdc646d26455df5aed5af3faaacfc4bbe656daac9d7bd3bb7" . + "10ef3b1ed66bb4c2c51c04b1aaf229eae655c6b5e71de5590a42d065278099e8" . + "5e6ee4bf3cdeb91d0a0f95a4f42319637cc930506628d596f75c1d806ba2f00e" . + "9353f76227eacf3b3d20b60d7086399d87e0863ac5a9170070f274cc3bf4ab1e" . + "bfb83e95a89a0d7dfa103650a4a823413ff0220090a77550b8fbf14f5ab64b10" . + "6966313d70912c5a2e800de2337301159ced8db32cd8d2e4cad8fc8b48cb5c11" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "33548097c0894e2d0b15a32d8c2c2ab034038b27283b0a7258f7d69aecba4052" . + "a3aaa7c1c191466c9cd40b9fa291d42ae2a15fee2b8959267ff6d393bfd8f2a9" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "3fad718363517b21364e457cb9959cb6275335e2d6bb85953463146cecb3c845" . + "445a4a43c69c1fbda15de1822afda5ae78582e631a435680bc415057a443848c" . + "e2db02bbab2fb07af33462db21b34eeb874ac050287231ce151ef82040154412" . + "2cb642717525cd4fc7b9fe3e6d383ddb9fc425556fb272e7c095bf0b0deb7155" . + "4bc3008ffef4266517584daea29469ce55ed2e12e5d35ce97a59f13268408ba0" . + "3d6cfa2f37468643374f614c214ab305bb29a663b3b1ff8ad7f04b546886331b" . + "47c439f44a8bce80a953bd0bc62e5e44daa7268ba2d32e4cbe4063a70611b30a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6c26ae996d54a466dd02cf410d3927d2be887ddf9a8d1c5eb09ef1e112645f6c" . + "52089cb9410d776973f5fbc1666081a8648cfaf6ac6a084265ec764e4e5ac2bf" . + "ef0bc3f6ea11732c1b23b0ca25749eade12e92fa4891d19d8c4e7e7275db6c65" . + "dc10cbc2af97aa9f51027ec96ae253675b0513914d2dbdbdf20486b9d457ffcd" . + "854ceea3e3be05edbbbf81a514a0de1ae258b7b29df011ec30c31e6bbfb5fdf7" . + "600ffe0e13f6cdfc43a8e9f8455035a27e73d984df6d04c25f0dcdac1bba7eca" . + "75232d9687a82f0f3c0060e8fe6946c89cdd7b6e4cb6ab668aee28b30f9c7cd7" . + "6430c962714c336a222084bc36cc1e82a4d8c20e37d326a34cccfdfd912538fb" . + "0f9d1565859d8782d287a405f78c806a3a58915bb89201725361564c7a2e6a92" . + "e499760110d4837db2b49200898fa4ca0a07d513541b34056876697504ef3b8b" . + "a0d82a74aa05f5a3632c9ed750526cf2e046574fe807857332b3bdcd5cc084a9" . + "ca50c2856236ca24e7dbc3721eead999c231bc500b3226af39b181f6e48f0270" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "a76e35b84cbe48e23b166029b6e9ef9e2caf5e4f5229d60a470be319cccf0b8e" . + "037bb32ac490ce0cf4a04eba61dbe7d51f67ea3eb5d5f1725b102aed486acc9d" . + "2639f9a602168076971d3c0686373bb8fcd68c1757de40b0193c047606c7f027" . + "17c6867b0c9979e890caf17fa45dc728fa2b0af47c2330415dd18f239a1b0d36" . + "491e1531a2d3787c256e7b1419fd3d616c228a2729ef3f6f479fc2076e96e1cb" . + "4cc3f715e7858db36ca39b1f45beef8bbf2012bb7fa06e77c6d98195eb7df3d3" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "883607475a2bc57b369901fd3e52dfe78fc6aa8e712179ff62f75d0b76ede412" . + "c77f532d8a714223a34bb215dbdd8c9fa8dc3b2bbae3d64da6c3b54ed8702d23" . + "0cb40722196fc6cfb12f0fc335258b0b9f485ca67806795d609311cdaf1e3e71" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "3f9ad973cd2ef0e30a357b44bf066808ff5728afbc050aa02697102c2cef1fe6" . + "06544a814266e1588878be03ce134ce1127e3f1831c68ccc16d0c49106d7738d" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "848eebea5815bff108607f506ac1a9c1b4a3af4e572cdfde345a7c2d614a62bb" . + "773a410a0afd9901ef985e4dd0467341fc51587c4850df4a92eda009c6bbbcdf" . + "229005505c3d9e7959bd3e8031f5cbb0db7087205a208af21b201a1d69a78c89" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "1c714467ef30e65aaf761e784c0cd707dda353cfc21fe7b88037f4e6a1bbefd8" . + "3583744951e0441d41217382fc255ecf9a3695648ac00338dc05ebf68a4ac4b1" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + . + . + . + "b8265972758762c525cd114135692b66f93fb5de9d21e6c334653dba25f5c3b8" . + "80f043b67393e1762013c96b1941ae04f4e56c1eeeaf17a83f1cc33491301e23" . + "579ca324643ede08c40a93252f175adb49d473bfc2552bdfb2f9e6203300c7be" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "c67bd53cac498aa46602ea4885062f1449f6810c6d211fbfdbfbe48bce2b64b9" . + "ddbcf52271034453b49d85c3ecc66332e89dd2373f4dee22a48954df37480066" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "7607ca48c4fbe487b302d10b263fa3ae392cd65ef866343ffba1b749a3d3629b" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "47f7807d324b355010f2b3188cf7d82caddc3cf9b974231c06c4c6fa2e8b96ce" . + "ce479cb0e9052dc3a31e895bde023d33664f6fab6c04911964f1a5367ca6b16d" . + "51d6c0aa33a47cc508b0a2de00bd0e62a68a2243e2d645c5343c656c4b9bef96" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "3adeef06c4e2c10bf06d07efd42504e6315341d2a5aca196be6d6c67be98b1f8" . + "f1511442e1c083c4df6a357e26e2c4ae25993574dc4ae6de5125a9fe0b11ce71" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "454382b1edb17a5bd039cce07f5a23eff9df35ba631fa478a5e9310899d048d9" . + "d3e6430d41343df97968787d4567e4f4a184c6a566e9e24f6a4c9932160f82db" . + "871043f36c9e4c425db28509d8ddcf051260e69fa1638476843d0efa554c0fbd" . + "5904744d7b61bd1a662f78456e945638a5fba4dd48e4ba5e2634f2706c5b7de0" . + "f9ea5f7433ef537894db178d8be68f696339ae30b05670570da13e051aea37a3" . + "e91deb9a896a606a93a27fd8488ceca8f67a10807ec65d095a1e16604534eafb" . + "5effd14a16c3ba4c8138c0f2c60aef16263461a3e8e117c9c0b1ae644a9d5806" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "55ee790be66e21c2689ad5d48e971daa0638c7602436f0b6a32cad79b942b824" . + "55ee790be66e21c2689ad5d48e971daa0638c7602436f0b6a32cad79b942b824" . + "5013e0453185a74d4246fcbe366b5535b190da2f9cbe5dae51e54a5bf0955f30" . + "1d51a9e6fcef3e3c2bc3ec76e535c582f9097560f8d41b0d35ecb3cf10f48ca2" . + "86cd4db58d6f2645ea44545aa4ae35f3c04cb5ca7abe79f7bbe681c2ab85aafa" . + "bcac6c5f51d3b94e39e882a8acb09c271efcb83307b9701d9a6bb1153348b1ae" . + "0b78e147ca3b70f0342adf35f10aa2d4d529112c4803f8faac2bf7b9ea5872d1" . + "60d0258250984b20b54fbd69e9cabc7eebd4558d31a15575caecce013c135013" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "389ed846b4889807f1630633ac25edb18148b00f3cd4ff488d8ed5e6ca75e952" . + "c0a0de1d6f65f9f7644ff30251087cb640b8c8798a9541f19b340ae1fbd79f13" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + . + . + . + . + "4cc0e8b404acc886a26bee767319700895abd2410457d9657888dc4b982e3d00" . + "da4a8a20ada421ca08289269f066ecb7e3bb87d2fccd667b3d6d85c6ca912ecd" . + "c7d623959050f6b248d38d2483879c5edba89549350e617e588ed973d7bcf536" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "063162a96ce356ccf5f09e98264c6cb089227c372967b234d46fe20389a58a49" . + "9065c50f7099107dc175759fc8e31c4df6ed3102bd1742182ab4cd64df5b6c0e" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "47f7807d324b355010f2b3188cf7d82caddc3cf9b974231c06c4c6fa2e8b96ce" . + "e6ee2f3fcb41cf475c56685635794f8e23a417f6184f1440edb32bc70c9a9a39" . + "62570f45954b6c0d069e336011ec9043e93e132528b4b4bdb27e30c42ea22270" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "09b2be2494345f3c2c6ce75dd8c22d45ea671b41d3e273a6d90a1ce5cb977fe8" . + "364446896bebad858d27ad64703f515628dffd8679e977e9faf4d9721ef580e1" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "485a12576f69d522b364d00505a250feecee0ed99534648f2d2e89257c0222a8" . + "f8a01d79b4270b26cf725daf0888fd5ece58abf64eee9ad6ec7aa2ad5592b5ed" . + "581f238f95a89843fca6faa4a66e14e4c14e34d674cbfeb0a75850af4e03defa" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "8aea0d36efa55b6613fd0aabe3eada60390b8f180f3b1a7fdc282a7d272bccf1" . + "c445571150929c42069a73ccb45faf19a73e395a6e507069a5ff9d0f25849135" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9c3c9ef096ff64a790027f0f0c8b82043799fb91cfc644fd8d830e5ef793e576" . + "b3821853f7e088b37fc3e750cc9684fc4f000169093bc511d9113138034de27e" . + "d34da378abacf4e572586121d78f9abf997fb3b5ba056934f6fd586f1baa9fc3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "bd62a65adfb087bccaac48a41c804f6487d8ca5879403cf35f55f3f0eaa912ce" . + "8d6338408a62bc38f16c06f10ace69427ab0b5c77fb2052c532315f3a4c6615a" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + . + . + "1423bf9383fa548761333db729750b3827dde1c35e2bb52ea70b5820145467ab" . + "7a92254b52842cc3afc6774ddcc339103c617cba557c1fbfc5292f4bd8aa4931" . + "b30f67a7d8c4c656894b37d6dd6bf4c8c87eaaab733152ad39b90c7c63bad38f" . + "d80dd7aee76e96f3f45c05d752cbd3277064392ea4d79d07ceaf1dbaed36f6e3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "e79c3df84a1447fe054fbc6b1be4141eaa400ca01c33a8f312aea3464af34d60" . + "e130c0db96426267f3fcbf710522c3c4428fcf806b81ead5bcedd6da2f48977e" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "0aeb7d75855d540b8b0d08176941b67f302f4957acb3303a3663963e7d9524d2" . + "0a395c5aaf678cac5ccb510df7f24b2a2bba6971625ac35063f3add8cf688d9a" . + "07a4e8e82d36a71071f11a1db8a23ae9732675b9081bbe61f132e114b654ab6e" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "29b454c88b0cb803bf2f85e0a0cc40db0d4641ffab906dbe4b79104cab24edf8" . + "3d1b787e0dd3a0f241caffc5e5fceecf2029c229e1263200c509e4243e7d6e21" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "fb9bb173c156cb4a2bea47fe5bf4ed86502e153b6e1591989fb1270b5880504d" . + "bf05711d3672ed266555610ea3f68d4928ab305b77ea5aeedc5658017b5b65e4" . + "20b8258eb7d3e3f8129e8896a3c9152a502f68300567257e1b659eb2e954d69f" . + "915f8171d0918cc15457b13d5162bbe39b5a5cb4993754811ed603ddad0100d2" . + . + . + "fa43ab63221291383e8ca77e630b018640ca7887d1692caea9459a4ac175ca44" . + "7488850fb9dea2a82cf81e8b970b4e976a6f40988803953e63b5c34439e2275f" . + "b9eb08d9bf872dbdf18ad1f02d4a99357d6bfd56eb0399f25eea5737449393fd" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8613e6a63644a60b2b33298aa948578111e928065897fe4ec01a292696eac3fc" . + "8613e6a63644a60b2b33298aa948578111e928065897fe4ec01a292696eac3fc" . + "40a6d83fddc6c97c519a128283844b89cec21ee5a38d413c4c3c886e39597686" . + "27c13a2f3f10d784941096387abb9fb0489258b5e07efff2f97d9b690f63185a" . + "fc70f98429cefdb8b24510092bd37fcee4c4361820737413a733737b748caf60" . + "a52cb016d826c41b6a3465827baa8f4106311fa8b3bf3bdbe49e2760da682631" . + "3894010f66e74e211cffd076dbff758af9aa1790553e80242728dd48fca66138" . + "d070bb6e38700424b3af842724ab1ab13ae8605dc36183341086f3e3c073a0de" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "68972c815f25a24ecd4c9b53ef24e1658b2364e170a3714e74d41fd7f99382f1" . + "e453544e5c6085a95646cf7bd0007daf5a39cf18f39e6539ab8a723ca6bb27b3" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "044a7176fb50f04594c4de179c1dc7a7354d6b021a1486daf29c61563c6d6833" . + "bd313236cd680c17155a8634149b356103c6e0eca1eae7aefa9abd9e6ee8d675" . + "f34da4b30163b32b997c2caba6853738d8048ccc65dec9a7e91fe1d8d0578b2c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "e6862a1afa16b962408f31f7ceaf5c99b0f797c9d13ae233af47443a714af871" . + "921b5b8f0c44b83f32da270d11fc36c711a162c34b9ad2e262f3bdd8ceb05845" . + "eca213e0182e6e138d7c28f08b8fdb957e9620c6ddd24b25d5089d0f72177d55" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + . + . + . + . + . + "e32c5d89776bc2af79cb7ab3cbacbaec9001f427e10ed8895b22c8fb6847d54a" . + "6f906e4972766e3656c2b7c9a40c64b79eef48c5fc42d847b929aaf472640eb5" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "93cddc893de729a0393b7b921fd85ee73721330055a5f3d14bb2547758a1d3af" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b0d16bec72af0899e2e707cf2e159d918fd0ac9f7e9d070d4376151aa88bfebe" . + "3433122e717d3e8e6895189856b2b308d13999f466a18b6d62c72693808de2fe" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "c58f702eec4dcb996e1da6afdfeac1640a27a08586f2a17a8a2dc44f4c9a9824" . + "8027b6f0662ccc25f04f9bbc509f84dd9fe01afa8890d99c21bd31c5359b07fa" . + "917ee9f0ee9fea4cd329b8d1a4d194b5ca10e1e693fab7ae13ea0c383b78eea0" . + "8d94e432f49b80754cb173fabce2ed56e876c399c31d81d4541b532bd798a48c" . + "0867c893376029a24291fb40a06f5c27e006b7d2a226958088eb0f98e05fde38" . + "5315924bb437cee79a6f0f94bb6515035cc6a7a1e1bb24646345065ffd733a80" . + "d7c569e11b9b496b2003e0710b14c44d41f16b975fe327d721cd51b39ab14432" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d2e94c4f9253a6710f235ea9617ca9a2055924dc9fd58fceae3f2c4239c0d79c" . + "85370ac47b813bc7c33c19c3dd1184b66c28be513f82d7a6b82fa5456926225d" . + "6f5092cbdf6766aa6b1c3d745f2f5edb45edc0ce8d68d19ed17992de68ebb1d8" . + "b7a208f2e36ea5f7bce058aac446e504dc29a25ec13174835a4c6e2dc3382469" . + "7ce63fe1ca189f28c15c24fe028f618528385ec2ce5fab9135d28fcd8cee5c54" . + "7bc02343a4acf23c206cbef392a1a2a36f14f723412eadc887f1d450dba99e14" . + . + "91bcb4b76cbbe533682447c0db894abf0d937ac6efb9e90433d4a5c790f26bcd" . + "ed9a66c73fbc7533c5de038d98194511a1ee73930689c5599227614a16056010" . + "bc7e94f2b07ff3330d85f4eb200f76746375f22474f46ee8a4d600413ca7b3c1" . + "4f48b9dcc65fac52ac2954c1c52595f0530962ce5e2d070f70030805681416d1" . + . + . + "91bcb4b76cbbe533682447c0db894abf0d937ac6efb9e90433d4a5c790f26bcd" . + "2ea477f0c06dfd7fd098368af6925fd9481de97785eff2ddd9d701af785b6b54" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "90b36d2c1b22558800cd547c9e3a2dd2bb112fb9d25280b0e306bc88e10c02fe" . + "90b36d2c1b22558800cd547c9e3a2dd2bb112fb9d25280b0e306bc88e10c02fe" . + "671175e3c4fa5327d678e5e16b65d67824eda061f172d5129f617698c5283420" . + "5927c56b51e350e613fc87865f91e9e2f42bb83bd390886525c792d2e7298bfe" . + "d1449b1cc102628591ba370bec39be301c456b638fd7825893c9ed625a324935" . + . + "56ab81debf9bc485bb92eb487cfba547a0a6cec2635da5aa5cbcc7e4b43baa53" . + "69468e7460ec4d48831d3c6947776142fef705eab6eb3d1363aecd8b94aaf6e4" . + "4b8af33ffaef6fd60642ad32e0b38edb8384283f60d27a5f4f9c33d1adf8f154" . + "20b74663099e3ba8780c11d5567b1449f80b2da99d4ce0641fc5c63ed21e4e51" . + "01502b5e274d0985ff4aa70cb159e2eecb5d10f553edf4992ee0a8b926cdd68b" . + "2fcee534aae4f39982488bde28072c3ce5630db2f87ce08bb704dce75670864e" . + "5b22a7d4ca6f419de910b7f25e9cc7f4773eafee8737276f1a63c98f2e910ff2" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "584478f9d5d1b17d724a1debb9911c6dc067c5f216abc8afec58d2418c471a1d" . + "584478f9d5d1b17d724a1debb9911c6dc067c5f216abc8afec58d2418c471a1d" . + "a5906cb7390e55ef146bb0b39d82d5787e6df41514f614d004af6b14b85c117c" . + "d3c9159230485ec5b8622c57352f70b8501b9860e0caf096c03998e2356e7dc3" . + "81d8ffbf95494d7e391c941a047fd411263df3daa8d136ad9be3b77596a0a3d6" . + "491e1531a2d3787c256e7b1419fd3d616c228a2729ef3f6f479fc2076e96e1cb" . + "bc6977b598aac388199d36a9b4e0323ce80ba130e3ebbbce551aeb2629ad2e98" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "3cb649ff0affddd28f8712afac09b7f02ff8186baffcc598c259ab066d164462" . + "02f8e14ceaba0ab299b01111684e622109957cc263416d60020e5dccdd0eba9f" . + "2b85d03cec3e6e0353a2fa589af2d55850e1d3405c40c580b5a2779e21728cd7" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "94a5c03ae662c3ce78c459ba53f136869390399d0aea965fe100c20f46194180" . + "18ca1984fef0ae3cbc4a29523beb7560c2f387037404f77defdfab2f468415e2" . + "a31945099292bb2f4ddbbbcc063dc551aef77c7c69574f48875d70d14c658607" . + "739d5688b68f50a81823440da19b4c0dbbadcbd49766903eae5f3841a0fa8ee7" . + . + . + . + . + . + "c6ee51d5318c5f92f1a13abb045808e67a1020decaf69e2e43faa5ac2ca23fe8" . + "f50aff3a0f61716f7fe704a6a2f6e4a377fd27606b14c7be2169bea52089d106" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "11377d96037ddaaf4455a25969593df01b55e56049564973af438fa8bfd2387d" . + "224a0455f1b3ab04eebd4fda364d55bb0b51124ff796d619d33e991fceed09ad" . + "bb0a727ff7b48ce63f5e356aee9e585d7372e3dff4148b928fb035f8c280724a" . + "6ea99144b0363a43d8261bab52041abb86bd6df78e2573dfbf8014abdede73aa" . + "df24e7f41b7da7e8666746e0596312b175f291ceaea36628606247e8cfc94fb0" . + . + "c25d29dba6d46ec4d31f55bbf56873673e1f35991b8ad1156ab3ff42cf037748" . + "10f0ec3d33ab82993b234989f64414e5be2aba5ad660af13771a4ec1d765bd6c" . + "c4e8da17725247b855c4a814fc40f08c544674a262b2067ee148331e209aee7e" . + "717be593db8e5efffc77cfe71cf8e528acfb8610bf41d9bc506c1c7298dfcd79" . + "8f5a11fec29de0a74f7db631fa4200698712f18ec27719cdc24d411b1783dc2f" . + "8bce28bb5a14b240f90845fa33d2ebc9a18c2b63eae1be38d36bbc655d7954f4" . + "175fda903b14a73c701c587eabaf25e981f282aa0c84ddadde8401999177c8c6" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ec0230251c9976ab1e46c47bc04b0d2a07e1bf91cc823f9df710d215a03c57a7" . + "ec0230251c9976ab1e46c47bc04b0d2a07e1bf91cc823f9df710d215a03c57a7" . + "b8a7a195fa91224f842c139678d809c25539abdf93efe86ab77a24ae65ed55e3" . + "b0418d935f95b782b5d8901e79b8227676916ca8559a639d4ca9bb58f4ea4efb" . + "2713413f5524fccb4fc049c2dd7b586f4ddc709cfafdff10a442081bec28831b" . + "c6978179d98cf48b9ab8e57a5b45043a835cfe9b3b397093820f47e9b1aac145" . + "19473794256ae9c17a004858d42aa6ea99ed206fd3d3e069580c317eb116db48" . + "b0b4afbdec601f33323df2330b15d4f5efb4eb376378c0d77ec6d27dacdc1852" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "82ec23d39bcf8450648905829ff3361084188251001b2705aa8af2e0eb84e188" . + "a45a638ec36c5b95d06a3664675147ee8261ba2350fc1e7cbf85cae366513aa7" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "b5eadb836ee7c8cc1222fea9616f3ebb3f8796d16f6369666416e3db932fe32d" . + "4f42c4a91ae506b05dc0b4c4b2e7d6feb43dd44c8e22556fd78d972bfc6f7f82" . + "f99c150dc4527c62238ce4079a5e6478a79ec7cc9a4ec6bd3e34e9a59c42d48e" . + "84558bdd3de5bf301643d3f0dbf235ec7e57dba898f77221eea76cfcddca646a" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "0b62686771993388336483b31598e3bfabe0de5d0f2e1068ae8d1a007b8f7bc5" . + "51fff4cbc473c103bc7b4c7e33cfd9c328a41cd162b866d006b1988cde95caec" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "ca675f120f090ad4b305063505706a3615adaa70967d52afbe5f314bf9c3fecd" . + "9ae8aa45487c49bb9fabdb2a741ded4ec87296bb28a3e934494fb76f79fd4ee3" . + "02ab32f24c24a4d0f408da8d5806ce9b1605191b50a8e8075328261bcde532dd" . + "35afd9026417c7d17f8700a4104626f96b77b2b8545109311513c8ad79b27933" . + "16015bebef354ed67febe958ca40370a97c33df40e09509649d02837f448f43c" . + "6e021b9e86951b88a42c5cdcffac0b56fb552c3f742f529e13b21ccf9ba06bbf" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d2a3e2903b2e9245da852e15d2914c5088b2d85d8a4d766dbf4a56796be32e68" . + "d2a3e2903b2e9245da852e15d2914c5088b2d85d8a4d766dbf4a56796be32e68" . + "6ace94cc2ec0da02078222750ba773f3b922617fa09f53f5dd6ce06cee0e9f31" . + "f6739a188fbd72260f9bd9582543c23dbe0a5c09ca44f875c3380edccc6f9147" . + "929ed0696ea46dd2f893f80bbf77534e43f43fbe8f6d50615c6b805e5ce3b88c" . + . + "cb4db2db72d536f9c034b275d0e2691461882ce0fa2d6bc084a3e290bd88b708" . + "9281b92fc14d54f4c39a7f52e199647881e8e82aad4c4453a2b7e30d89b400f8" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + "e3f60b970c2cb7174d2302417369e0da6654f5e44ab89de1ac08e8db831233ac" . + "741e8d808639cfe6b05dd78839d4950cf1577cf6e720440906a7283e2071f323" . + "4affbf1d67604ed8ba315bbf89a6813dde367175f9ecd29f0ac0d9e48ad07c19" . + "9de479eeaa005f9ce9887da9d011366048895b77f7fc0f1e27015f962800d2bb" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7215172dbed33c38fd8149e76ff99f6c7ef1f2cea0bf5e63612fde9ff9b683be" . + "7215172dbed33c38fd8149e76ff99f6c7ef1f2cea0bf5e63612fde9ff9b683be" . + "08cdeab113d093628854c7bcf0c202e15d6440e120366641d0a0846e199442ed" . + "67c0b796c0915226da55fe99e1df4f166c9445aa71b231d6613b62c133194784" . + "f2aeba90e4dcea9a408c1814739dbffcc42e93081d93cde9710027ed735d55d7" . + "11556bceb41cc801fa198dee2b18ff1d50da1643101eabf0ab7db64ca4205bce" . + "b344f162fe9536b4c37588aad0191e08e2f1d6a03e43a065194388ffa516e885" . + "bc2cb4f9cc4f3c9c7eda189c2662ac44302ee872970b5dae2dc1249d5ebea3b5" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "3cb649ff0affddd28f8712afac09b7f02ff8186baffcc598c259ab066d164462" . + "d43b1b3a07a16f47003d87324e4985272fcdde1baece334dfb41e8dba09afb03" . + "93919da65db772f228831c625dfb949177bd2e5b8e5d93f0afdb61ad730fdb6b" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "ca7e8bcd15d70fef1a9363c010f3ba506eb30f3d167165ed22925bbfab575422" . + "17e05ab103501b08a118dd7018766d6ea2e6650d6d8479093b23abf28a5eda29" . + "051a7a6db85621a1d5011d536595c39b8c9d54ba249b8423fe846020326db11e" . + "0d7f4f862c9c1a1f8cd19f20ca2f48b01300fb1b7849702f00f34115058ec0d2" . + . + "e36edf2aedecbc4a62dd857b6106a87e842a61bb71ecaa72c470d6d327c6f2d3" . + "98c9596d487339bb6567570a43acb9ddb5f7810a8d49dc143e4778330b482faa" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8e0c02ec3383fecf9d3d8d8f625f5c541b17cc4dc9ecdda0baaa7e322dd1c278" . + "8e0c02ec3383fecf9d3d8d8f625f5c541b17cc4dc9ecdda0baaa7e322dd1c278" . + "43896e382f2c1890b06a0ca2d3d729c2bae902162d38d36274593fcfd103e9a0" . + "727866181de452728a431c34bd9cd70853f977bfcf0290d0621206560409eee4" . + "549ee81e28ef699c33c9e88cd37120500301d5a359bddccd3b3e173f7a76bdee" . + . + "8a406fac62aa668f04b394ea19eb1f0bfaa0779952ff5cce159913207fdaa79e" . + "48ed2b15b552b7c15517d770c5b9c4718ecd7893909c83402b2987f3ecad81b1" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + . + "8863a19b890e05ae7a88d39996344d37dbabed5908f11780d5319784f4e452b8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5d98b57aa8325f9f92244e87067032e44d40627639cfbfb8d0a0b1387f3c7f45" . + "5d98b57aa8325f9f92244e87067032e44d40627639cfbfb8d0a0b1387f3c7f45" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + "38e9c28b7e7755c672a1284399ad129bc122559bf4cb78fd04d11e1450e6143f" . + "4a8b8b9378b4e58d49aa7c322d62c9a3404fa0ac44aa87ff82d45cd1ea06dd49" . + "164634ecac853e53433a13d998afd28f5528aab4d35636043903336bf652c6b0" . + "90042fa3d282eab5fb01d86fb703fd8862d800a66c7159c1bd415f3986fc00f9" . + "0ee0094834c06195f5fd25e3be3479afa1a1cdcc383ad4503f1696025cd31767" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "6ef7ad344709a90d58214562deaed252754fa4a012af8c42a217ae3626390256" . + "2c2c5f0f4896c002d2c30f1f8101764145368f2d1c5c009556f04c8b71ca0efd" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + . + "982e539741aaa979ff76e9568ee54aa746b0e93ebf40a03a495c191406a773d1" . + "2c22d052ff171966a24452436f9806492fd575dacd8b2c3ccd25e40da17828c0" . + "2eb1515361f0a645cdb9a255ddda95ff44b222ff4850f2bc1a3af61b49bb442a" . + "4a6f732b249d5d4831b9dd0c3340582a79cb912b80ef02b894345c0d2cf0780e" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "a6e230ab6fc30ec8bcdd0769c21b8b0811867d95876198dc49911fa01021bfb9" . + "bd426bd5800e4c7d9079ecc70d9df1f4439a1e00281a286f726ed51e7878d7d2" . + "fde3e35e7e5a4c11fe03b40708634205fa64e1d8d2ab197be86c1008c92a2722" . + "8782b5459b1d244a4d2f2e743bca88a3c89ee703cdd8d439c7c25440407ea7e9" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "494924525eda631159bc80bd63c426b327de6e1588e4daeb44595073c4c459a3" . + "6ae3da7576e2b78c3d604a0028c974d6dcc874e5f93f3406cfa91b512f9c5786" . + "510de2643ed4c29dffa850e8da158a9f347e4a9dbf0d1c7127796a82b510edd5" . + "55b8f22ceaa0fc69d4c80c88c8d256f80eab1433ab55f231bcff6c5f9d79e9e3" . + . + "557b7dca600dd9bd95c73b40d37b2aad48bb456a98d84a6eb1517c99b57fb5ec" . + "273ac2f9a2a49da4924cc59a17b5859d8837d16485bd100ac8d44b4249b316a9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e63643abb33142ca2d753083b86aa80f2a4c89712ff1b7e2a180f32f09918453" . + "e63643abb33142ca2d753083b86aa80f2a4c89712ff1b7e2a180f32f09918453" . + "25709af370dc30c42183c530bccaf3259beef091d0de7313ebb3bebd710e672f" . + "6acb6f7a55870132d12bcff89c025c5ee5728297a355e70ce2e7d4eb2a1e0a4e" . + "ab6ceddbe7005d7f23391ef0ac1d551936e890448880c690d6ae8dffef1f9dc4" . + . + "fa7fb7a63ee95429b8931c3013604c68d4d7079277f443846850fbe9c699f7f1" . + "52f747af1f3936f5f7ff598d6226f6a2ae0c4f42195fccd20ba4332fa0037a8d" . + "f4e4b9b278c972d112940171094f339432e67a8e42c5c11e64dfdf1cc572c38d" . + "13a5e56e6ed8c069632dcf3eaae52b964b9d201b3b1ce0dd53f91ae77f087807" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "063162a96ce356ccf5f09e98264c6cb089227c372967b234d46fe20389a58a49" . + "8ea3f18dccc27aa1dfbccfdd595511f4cee0802d5f33dcfb2ca9b8a7d4d71f87" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "47d34eaeb995356963cac71e1366a9ca3361b6d5877e5c1100431b89ae28ee86" . + "f11832d3a1d8c3988ccded8e8fb14016e735f81c3b6423e6211d1170af097836" . + "c1893a02f3b685f1f35081ac7038601a3adab551ac627c71bf12126c547c7fc3" . + "4b597327b1aa840ec825e26ec91de7302712f16c38067d679d0dfdf0200d52b2" . + . + "8c64eb991789c5b89024ee7767180160aebbc70b8ba71bf056c27183ccea1e23" . + "5c559992f1d26c550332d16f50070dc9618c8d7605f9566ba18a54dbef0d12b2" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "feb156e1908b03d3b92860b0b0686276233390e12006331b53daa6930c5908d2" . + "feb156e1908b03d3b92860b0b0686276233390e12006331b53daa6930c5908d2" . + "98bd21cfbf843a75be3359fe51f7f7f8de12885f97d8d95f13cbb9f9217e653a" . + "8db59a674bb95b8007ebcaea3c1cbbd9a133a0f63f553f47e7c47a5b7ad810ef" . + "7dc1a039f5da4f9dcae626d18f88e4a08abdfc3936812b0be395eb765ea3d9b7" . + "67b0e5854197cff37a6b0e9120ce80e53923156d78d3f9c3a11f83f10a06cf89" . + "596093a3807f5c658edaded7379895d55e76c827cd9c953d17014cea3ee4aae3" . + "151bb37148c7e4ae5e1593205e6697f9127a76641b087dbb48a26a97a0d696fe" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "150e8375a52724aced5759c2aff14d1265789b95b6ffd150510d30662e4c4945" . + "1718d701710d83370fb5c74b704047b5651e62c299c8402db0df2d55c879aa2d" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "d803ee65e3bb878506c0cb903063f50780f3675ad77203a60e05ae8f55ef4ec8" . + "af2b74c8d05101ee05511a1c7771c4c995d1f1a6d7a6e30572b468c58db43c81" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + . + "0a6a90b581c12745bd1fc8317e0d726a1c6b5751001413d37ec38bed741b1fce" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5747369ef673afdb6ead9cb338c89ab5cee9d431e32f558da210d38878d73da2" . + "5747369ef673afdb6ead9cb338c89ab5cee9d431e32f558da210d38878d73da2" . + "d1fda1ad1099e21d022d52f04dbcce69d0ef6175d9c9bdcb6a94eee61c55b9e3" . + "0372246f5e6f5fde809bbdc28ec21d6c78f28bf60fd1fc352a3a1733f81db458" . + "862d81f5b9219d7724b849e2cdf87013fe6e783bf596bc1d14f29924dff53f6e" . + "542486420aab57f893c9c03817cec874b836ea8cef5f88b56a1d3f7d632c0e57" . + "716191ae382843609c13a32c56105ca863f6c193f6058e1a398c02fc18fc16f9" . + "c7d623959050f6b248d38d2483879c5edba89549350e617e588ed973d7bcf536" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "5a79b0ad2a9a06b1c6cce76eed7a0e9ff3fe325773e3fcc5bbd45c53f5556222" . + "72ea806f0c847ea14ee43a3b5f34d7b0e9159f5e134dc0a758659ff26b0e7d65" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "da8856a33886b75ef3905dd97c100ebbeef15f82c6949f088d6e0811eb246bb5" . + "343980fd13ca9930c5ada7d505726af0424e8ca2e3d94cb55658bab8a17e5f60" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + . + "4cb0cb0aff513336c9dd2eec3c316d84b9eca170246966bd26d0b2d7078db738" . + "5d1157104e7d9a5f9192bb43410d8334770b265b461bf62173689ec864559e34" . + "8514101ff6d04c27888ddb2c90e72033c3256e0332303783ffc386331138fecc" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6ddc5a9b86b0398c7e5badd2022a7c4c4b4e37c0c6aa1ac1774fffdb0b38e218" . + "6ddc5a9b86b0398c7e5badd2022a7c4c4b4e37c0c6aa1ac1774fffdb0b38e218" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "db6a49f7c11d55511314948284418da043e23f481bfe5d7484672f61d6ad2359" . + "2c4b2e21d39d3951a2a1c5fb43d1989003c8238421e9ee66f6be7a29f83504de" . + "213c4cd7fd0f5bd3eeedff989631b9f275ec79e581dddbee23c69fd6aca6e2b5" . + "1448df2c599005c44d47a1458e7934896590e6e18498517bb97b736cb1fe99c9" . + "e7f580c5ea386a966158c0fd67b68b27585d1c1a4bcba0da1844d888cf88cb9f" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "c2ae8e22d6a6477c1f29c1a38d2a93cc04fb6b7b75ba038283bfc5e92621cb4a" . + "4ba63210c1f3f6a96dc3498d28a6b7952edf9a0ade359113332670b058b3f77d" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "ba018caf2d2612da12ea27bad24bf8f7e8baa4d7e24a7d92e3c498c3328e562f" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + . + . + "90b01aa5805e8bfbb056d07d405c0877c67d7e462abbe6fd95b6ba71229970f3" . + "9eec3c3d6c69b1293596e8a0e894738d5bc3b044fb326afdb735c932b6a9f92f" . + "fd68ac70505c8545a36f4590ce52a5857f0c2f59c2cb89eae37f5c34aec57b93" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "28aebb464746d4591b30f8143f059c5effdf00dc774df72d1c57fb387248d3cb" . + "2412c0aec85e180be956e4630e66244c597eb7107df808b6239259805dcec159" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "96b9be1c665ac8783a965a72d251b4d35f0a1a560c94b38119d89d5cd877ed9b" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "338b68f9a6b8550950cf201de3ca72cae3fd9503b6f02ff2ce317a0e97ae22f2" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + . + . + . + . + "3375f63642901c48bfd86a1df5e136d182c19315bf425a7969ef7557506d4912" . + "376fa30ab4a0111b467e5173fe807329eae6496e16e942e187ba9403b0cec7dd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e41085a86fcfedabb3749f9dc43943fd953786c0de2c0f84227f125c0b855992" . + "e41085a86fcfedabb3749f9dc43943fd953786c0de2c0f84227f125c0b855992" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "12cf71da833f19b9d13d108384d7fddbba250cef77f1f9235123adb5fb42d4f4" . + "a94d44bd658b260220e541d263a0c080ca3ea14119272093e5fffe27bb350960" . + "ae074c182f90a70058288cf26c027befa271feb1e13609a5de79d56479cbeb3d" . + "935d30afb657b6e8a05d461ed88b0edf6125a6a40dcd080e363827232e706741" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "4781bce638e73c2450a29dd15f97778e4d84838c6f36defde047112c64663165" . + "3dbd92a1acdf987fce8c290e0ac576d99296a65605c08f18d90fe4c390fdbbe3" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + . + "c7f38f5e0e8f33357b7d417ab5e1910e9b7262275efe326204a8086b668beb3b" . + "e3d531236264b45b20ef8caa47c6104f7f8b5cdf6899324bf541a50af50d3e3f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6ed1a0e169855fbd980d50c89e19fead6368e288815af3cc55b30137abc1721b" . + "6ed1a0e169855fbd980d50c89e19fead6368e288815af3cc55b30137abc1721b" . + "ac41f1d6870896e39c4c9c2580defc92c8a259ba598fe077a1e0971924cc5df3" . + "f0edf8d9b319b8a2a2e123adbefe4275b21950a89ba273e2f9a96149e1478e89" . + "03010c653af79baa6cf8f8cdd61b604f3c6fd78740c800c3aad5dc7ec573178e" . + "3186457110cd1de1fa5ca24b1c22040f82dd3b4b77ba75a5531b486afc392305" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "b28096340b05ee8f54adf208b7dc82c08ef01cc40bb8759c6c87b51a016186fe" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "12f799f920236d7b761726a05cbc194852c0b5a9b1a070f8f0ef848f84a1bb05" . + "36142d68e8553d2f630940b86c9d053d6d4e30673be311c8446e6532d7e22150" . + "2c9d90731d70c383bc17ae25aeddfcc767f7acb02a2dc6e1950b2289e7911ede" . + "edc74bb1df36118f152a351d15edb1da87e06599ad9bfc5c2f51c7194cd4229b" . + . + . + . + "c6f2865899043f658fc350d6ca030f4ce44d110be8c8a94d710f51969cb65f79" . + "1a0c5c51b04543bc287727951e7b81bacc9151d2785a14064f0fa83157cfa21a" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3c120142121eb973175d99a9f538571aff430b324f4db27f5175d13cc020f704" . + "3c120142121eb973175d99a9f538571aff430b324f4db27f5175d13cc020f704" . + "f8cbdb8cf59722b4b7699956abac3de22d2a9147bf8206441e69e19f83967db8" . + "a704ca32cf8e64f883921febf7791f627dff946a8ead284eae4bde026a208b5d" . + "a5e5e37711f8e2c5a496a65df2ce903b010c3628810dd6400a065d414dab8667" . + . + "7359597c998b5296a4ea053c117e81c58ff9caf62a0a5b42481f4b85e2657971" . + "e2871540a6a9ba0109b868ce93b343bea4e39f846c724e9640867b2d66506e71" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + . + "dd495339eb9ebc9c5ec6de7c2555b6aa6900c5acd79edfd81d834e0930c91044" . + "45a562beb494fca300cc32a723c34bdafa2f36e0cca6ec5e1d4615c92bc4bf0c" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad8c316dcc03234d72fd6a7aacbdb6abcc21fc3f3c1b3cc88487c90a913c530b" . + "ad8c316dcc03234d72fd6a7aacbdb6abcc21fc3f3c1b3cc88487c90a913c530b" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "3f5a5f7ccc491d155ff56c514485aecc20d0968ae480e161fa9519dde80f8f15" . + "23ebe4f8c76ff716578d0e25a6e019d958e119d47fd27196d2b78884b3ac5d35" . + "ae3590b42c2db702b7ded780808a4c152f48f28504b24cf8704eb6ed4922f0b8" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c8e9d44a9b84ab92d1478d72f320033303e570709acde7e305d433ff50fc8f7e" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "0db9efff3f947c0e5e532c27509eff55ed13663818886b45a00487f11b94a0d3" . + "098f15b755eade85ce9aa4a8c73bba5799134e7e6f3df9505f5aa32738ed3c6a" . + "d71c13e6ab72d6a4bcfbe3c007d0baa1e6fc859336a74a602eaa9ba8493d482e" . + "22747fc054f4ac08285ca6cee6429667aae323d94c352d0611bf0396272082a9" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + . + "dd02b79e13ebc2ec378cff02b181ad3edb70c16404415742c71e430587953345" . + "2cc1f4ea829aab631065b14d77e8f0ed5604aa43fff078781e096a65c8d3d5da" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "fea8f3f5c9ac3279edb4d6f08073afe300ba8052aa7fa4f1e01a73ec01a4f941" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "1c2b15e6143bc1182ee56422721d5e2bc440dbae54ec9cb3b284811e365caccc" . + "9d68f78882dc24c5d5c6dcf351dae3a6ac81ee05bfd7232e3f05c942633b519d" . + "9c6b480c30de3d3bdffe075432c72743231bb93542415f131a3d3464c52e77e9" . + "009b4d9e2fdf19adc2f6dca6bab779e55ee6de32111e60e170c824367297802a" . + . + "83a56c94e326e407ac47f65455f7a6cf11e50039fd915f0581b0d44b8324e991" . + "eaac50f49c8ddcb912e5d3251d5031f0f3a0e899d09de0d946848038813949b3" . + "ba030a90b81b209788b7ae61d806f98c0339662c04946d27bfd4bd1edb5815a2" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bba8da188564113b8aaf3cc8eb93f5d62e0aaa8cc2c3fc02a5938e42e88975a6" . + "bba8da188564113b8aaf3cc8eb93f5d62e0aaa8cc2c3fc02a5938e42e88975a6" . + "2685479d505e1f33fa8a5849dc15d703cf012b70fdb8c2ea39968b0b354353f6" . + "e5d19f23f513e661d6bef8aa694abaa2a46e51c4642a89307d0e397c0c561e43" . + "d28dda860b9043f6862e2a8e5a754bd1ae96eac4a49d6ae7af7751c6a8fadd44" . + "5dc301a07b65eb37ce018e7b3e122a13b333abf405f7f26eb4e719eece190e22" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "ab63a6eb1640fe6db9f5afe8bc199eeac2e5fc1d72615315dbaa9b472ff2cb9f" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "bc435ba537b361a888962ff04ce110ea93bacb3f0b5ab69d258eeafada606b62" . + "9217b459a4cd4563862200479b588f82ed3c965dac43afeba2cb64c2a1cc28a8" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + . + "c3f7bf2cb5e172dd74d9e9ed5fe6beaa4a67fb231814273817ada2ccab9256a1" . + "eae7d9a094a0f84f571601e0b9926a685c29941710e7a59a41013eaf069180de" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b1488cf266bff4c6264e022ae0d3e655b36ddd50e6d1a6f91e8ce89775343944" . + "b1488cf266bff4c6264e022ae0d3e655b36ddd50e6d1a6f91e8ce89775343944" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + "8597542a9a5d93654042fd73b9443a8dfcd3eca9ef61caa7d3a18e8eb1ca61d2" . + "fbebba8ce4ce63343e57c9b2b4a0b944cb851faae6480cdc6afadf7614cd22ae" . + . + "6830edd37e582afc77dbe9d25e96baf3f46c33ad6304226324cabc8fa554b245" . + "509acac9ce53bcd9f38b8ed7f437d7c4c06489192f5f2f32310dc5630bf0b5f5" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "6171d8906cdd17be8d1b413eb510fe4bfef6e08ac99b92dbd66bfb556364d008" . + . + "46ba34958a2a9e34acd02d249e94e0febd47536febf92bae1a956ea686fa991e" . + "561cb5d160eac4357fbd87b1aba97990c8a085625febde4a84e71c79b8aff213" . + "b18f123907b589817454a13adefd2ca757766afaddf3414175f988e99ddced9d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "50db594e393411d9ef812b756549e4cee1ed3ecd0c2f44b3098e1f956325457a" . + "a78e22864b972158c3646c3bdd5c58c6d5661fafd836093dbca57d6ad134043c" . + "6f906e4972766e3656c2b7c9a40c64b79eef48c5fc42d847b929aaf472640eb5" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "d43b1b3a07a16f47003d87324e4985272fcdde1baece334dfb41e8dba09afb03" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + . + . + "23bf091cf94283654974717fafdfcfe14cc408524091b4baf29d040f4561081f" . + . + "46e7a2c484b61187d24ed38e6a101c6f77c352576ca8d1a9f5c611f810f146cb" . + "9ed3b652f3e44fcced33fbbcf2e3645a12fd086ef35826de6c657951505b98f0" . + "26687a68e88ac833ad52ec624a5b490d6a27f0e53fa5a22f92d7c55bc80d007f" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + . + . + . + . + . + . + . + . + . + "52d9f7ceb0ca803a3a743d6cd01319ece8d779038beff7c0c7fb5868e55c8537" . + "10f4cb5168491679cad0dff6a10ecd99fa38ec7f5c2521aa299fb3451d08035f" . + "99d54c80794bdd2a41b1343d251aec41b9ab2048922e0106515d10f9138a5573" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "735e93bde90c1c535c009b649d81f672f7b2afcbe6529c175284b5f3e4bd3a4f" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "082f7c7c1863c9236dc70b0e4fd395769a9d6d69f36018703b453acd9c2a8a6f" . + "9ca08a3839ea61448843f487b91403310d64080a66374016377749db1993e821" . + . + . + "069c0450f19dbfee1bedaac340750db711e6b8740b5a94dd71bc102e0575fcaf" . + "0462c2dcf3fd499fdb7309eaa1e54bb860c0bd277677a762a17e5e2557eeef57" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + . + "c92b12088d95c529fb270a3d2640ccd057984d399248f468e9b6f186ba24299d" . + "450eea4efc2a431762fda5d4252d9360e815864eaec90528565f578df63c8978" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6eacbde63ab1907e273df5c430f5178fe5d41ccc8ac48ad0e0fe449ff341ab83" . + "6eacbde63ab1907e273df5c430f5178fe5d41ccc8ac48ad0e0fe449ff341ab83" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "17fd585c96206df927af03b9fe4dcaebf3703bdc1b2236c336470de50c8fc736" . + "041f3f2769a8ada5a8deff6ded84c64d97d1ccb4373cec2b9eb2fea522b197a1" . + . + "836c066b9a241849a258ad51027c4f9eebc02e2f8bffc7c90cf8c13bc8d68168" . + "bfefefa8a9f0ca9adc06a4b976552c0e1b38eb772f4040599100f03d64224e26" . + "b5bd47b26b071a084e26cde25bebec268e60f16296de379089419fc0942723a9" . + "c9144c2edb951273e0d90ae7299e476c8fb5065dbd55b2f02d4aedbc641998d6" . + . + "0fab4dddd69dd1c754f32d86826b5f505261313fce7242bf70d415a2cde0b847" . + "8e992e3cd90f8c6ec80069e72bb2bcd3e57923fb3ba647a15e832a398b319521" . + "8227433763362aa355fc99c2ee83ac20e19160c59446630d1a52152e8f3126d9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bad0d5d3c300a6fe232972a0a2f25413908a83acac5f661e8f285b827dfc34a7" . + "bad0d5d3c300a6fe232972a0a2f25413908a83acac5f661e8f285b827dfc34a7" . + "821ba5a1e698ddf5c09ab58c145b6bd454d7b335f797a5c88ce8d829b89e37bb" . + "f6a50cccf9eacb904d22f7559687aa09b5824e57e61836a545cb7bf264e2c610" . + "233e595854d543d47657d9558870be35b8bc6ba2f3de0647a1145b9b69de439e" . + . + "34c65d7094ccc089544a1fd57ca18b7ea8d0b790cac705f3d06950e18a89b1e8" . + "a808d9db33daa42444abbf9a4c07a9993f50644af457c3c6baf140893ec3d24e" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + . + "641228b022a8c28c1ae4287e9a5cc1d3f1b191afd8d5e9eafce121b147ec4ab2" . + "35061809202734bfaae867e08f79253b39a7bd6b7b375ea7a140613e8000aba1" . + "3ea7b5f07063a7bd5ec06ceb2fc1b6493bb88ac1da6f77b7e31c74c8705f6e4a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b04393050e76fff85ecbeed1642f157a08af7a7c83b7f4dd561e6e70102f1e91" . + "b04393050e76fff85ecbeed1642f157a08af7a7c83b7f4dd561e6e70102f1e91" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "5249dd5deb395775f8cabb00a8d6d1d0b4c73e07c2d25dbb166304a9c402db9e" . + "5c4657fcddd7da6a75b4fdc1e45f8f23657a5bf4b580533bbe7008ff131eb05a" . + . + "e7ccff4564b14be903709fb494af9faba4e8b31ee35df1a9c0328b1a9451dbbe" . + "0392269f9864991820b93d636a1aeebb2f329e9481feee647efefdac8b5d43c5" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + . + "8681f348f50fa175d9309e84d6feaff5014f24476296e8a95bf471897f21d3fd" . + "ae3b9d940d08b3cde0fb1c005d212e9f86d73e61f14ca86d1c4fea2623232c90" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6c53cdb1dfdb40c1b594c52fcb6176f3ff206684e2c2b01856f67703030709fb" . + "6c53cdb1dfdb40c1b594c52fcb6176f3ff206684e2c2b01856f67703030709fb" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + "f5853555bd7c1ee0de5e23bc5649b22be265a5a61bc10a5bfca9e116992a22ef" . + "cc2275f7272be25eade14214c5a79f2339078bda79e1593b1a8f366c6555a431" . + . + "15a6faba9c690ebd99d6d747193f67449056a2b1352c0426af31ca09a973472b" . + "59f51feff25ee36b266e7002155a9b92c79004301fee6e9569bda90f23c35dae" . + "65f515cc210ddded79bbf98630848382b7c6503d82bdf280bdf75991c6af497e" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + . + "3037fd116bd364b8ebc77a17c70d35f287ff26a33f6e76a06ae3c375f2d13b0f" . + "7282f1548a94c479b3d67611e76b5eab50854f5c96ad95ec3ee4702e61109400" . + "2436ee7563a887b08958c56393b60515a9b74e5fa82595a72e2d885ad59c55e1" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ce5d8ee977ac437d3fe5137a393cc600ce1a3fbab0cc875f4d63b4d68e4cc9b5" . + "ce5d8ee977ac437d3fe5137a393cc600ce1a3fbab0cc875f4d63b4d68e4cc9b5" . + "d7bc7203123b56bbeb1c0b082e7ba0941d9ef46adec4163416e52b27f9c83672" . + "40b8b1704275a3b9c838035535f96c7ad26b1d3c2ec8e34b395705cc316ff7e8" . + "ae3fca7ce051c7328debe1256cdc185f83956e1588aeeeeb741fed5895e66553" . + . + . + . + "37900c1f7bfbdbbbd0689b3eee6ec24595709b401097ff656bb8475981aace0e" . + . + "9388c30e451fc37b00a2dfa64f6ec3cf378454120e351deda4d0bdb962adfa2e" . + "0a30bda5814f13be99a7f4702d1da6d7625a3b09aab305bbb524d9ef24e059cd" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + . + "9a3636e8a8f26007cb9f5ade06f5d1e11a9369d1dee08e51c85c524772ad4deb" . + "338947ef1ce62dd73ead79d2f05d982a8eb73700869966ffbc42c59def25cbd9" . + "c84df9276d40aaa192e00f008fb4ef9a9dea4276423f2116e2ff0f4b42c145c1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "524470743999f14e1ee1aa3e14604cb2387bbd5a7e48913c664bb5d0cc2e0cc6" . + "524470743999f14e1ee1aa3e14604cb2387bbd5a7e48913c664bb5d0cc2e0cc6" . + "c1fa2443cdce35786d680f6c3b113e7d798d76ab5fd175bc1ff16dca9619c744" . + "75adcc2e0405a88109c8f4a2b68b7c7c5e85f5d56909cfb8dd9e14172a1cc134" . + "6632ec03d8862db1f68d2b2cea477a3460bcadd5a34851df03d502cb1e85dd3f" . + . + "dc18fed7730f2c54b0f986de0a41634ed6d2ecf6c58ce5b3b03a540f85c021c6" . + "e2eaa1384a538f707e7f43b63c219824fd1c17fc1a5b0a9197c0c40cd3a78c86" . + "6a522c214efd2b43a26a63f8bd0b6f58ce8e117ffa55c0ba0764ce9e02c18c7d" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + . + "dc18fed7730f2c54b0f986de0a41634ed6d2ecf6c58ce5b3b03a540f85c021c6" . + "2fecace66a4d6da4bcc639b4d0f3070ee8862fb06d9843cad72602a16ff4a4c6" . + "f5e956bd2d1246c7440c81bb15c61b663977ccbed0b6420700edd8354793c991" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aac9841cf3f5bab1bae8028c4a881816f2c089282c0f10be8e502c58b91ff309" . + "aac9841cf3f5bab1bae8028c4a881816f2c089282c0f10be8e502c58b91ff309" . + "8ca3d2fa061276c783c53ccd801aca1dc20a6bcfdef88d8aa5eaa3343ff1cb05" . + "10d257fde7aee7496e9daee73f5bbba1598dd159d072a763268d19bd9f20aa60" . + "e11cdd886dd23b1c461ba7a490a730eda4a2caa88f328392a4ffd5a30ad9ba8b" . + . + . + "a4ac30fd47fe5d4cf71a6bbdb2d1a331a4a93a81c3e576fd96560cfa48f9f662" . + . + "0512bb8c6fe6b504b2b6bf6506ee50c089c4171532a81547b802656c5cc298d4" . + "92a6e8bdfbb319efff4a5cc326409b800c85804d64cfb8afdfb992cafa330327" . + "54b5037e452cdafa0eeba7aa257306c78f671cad634e43f53d8c2c0e6871f484" . + "e010705c4a015483b8c69947feb3b579232b8671fd5b78e4abc7854eaa1ccbfe" . + "57c6c983d38e9187d09316fc445142e8a685e6db2d32d442e1c9237456ab1e6d" . + "21c11bd0fb43d2d02684660c976bb1864b8d2e182dbd6669fdd51c05402b30b1" . + "423f6e66ba6188dc3dea317d012beac0374938ebd3490c9fa8f38a87dbf252b9" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1229647883021f7c95f1aa8ac79cf74e1108987b152fe46fc55aa6a5cbdedf1f" . + "1229647883021f7c95f1aa8ac79cf74e1108987b152fe46fc55aa6a5cbdedf1f" . + "677e3e55c4953cbc130c39f5630546213accf85c4cdfe1f828f410aa4eaeadb6" . + "caace2cb9c8cb48392b7933aa251a8d7d88c7b024c2f812004816b3c5319ac67" . + "dd448cfc0af011d5a893af327e628021bbbe3586e4fb669bf958b5ab59b07449" . + . + "ece210de9bc7a23f7cdef7109a7c955b2d944aa179a5fceef15c489d1f921e68" . + "ab7c3ae5684d5da69dc88cdd13a36df255cb5100b815aa1c3003755de0cbedd2" . + "8f9e48ff5cb39f83a7dd78010435226ddb8d6c75cd83fc0a2d4cfe69d8081fe6" . + "02a0d52e6bc4a7c8908f800237dc0853bbf60a2a2940366ea8afadc0413ae604" . + "683f59f15ab639fede036fe509548334a83634dbb72375dbf43540b273801101" . + "0426ca409541853ff3f6462cfe69a4cee7ef8ece40130d4ed5ee651a5a98e7bc" . + "02a75f9a82e9d32ac4926b504d87f9361b9bf2fc13931ae4ea251a88d13a1fcc" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5b39da4c6b1a25d58139606f60c6171db51d5b62fba00989ac30c6e175369f81" . + "5b39da4c6b1a25d58139606f60c6171db51d5b62fba00989ac30c6e175369f81" . + "fede0d7af54393516959a5e7eabcf460c7bb4f322e2d301c275fcaa1490d21bf" . + "91746be0974740e685f8cd644b48802a65cd698380d5377ecd0fa88c97371ed5" . + "806bde10551b8ab8a816621a263136098ebcca7f551f1d8be9253b4c587e41d7" . + . + "63ba2db57e1522341cf24a2c8e22d733ef35896933e0aebb787b689826f2a8e1" . + "9cad07efcd358a17d10b89b9983ca7a7392d8a29118b5288c5e1bc744a424a8e" . + "b0d86e92dae4406c599754b16c8a0fa6877d50aef19c500a5d3b6039782a6358" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + "2d53685fadff9fdf498b54eca82a4245f6fe03a974d801720ea56eb98062a77c" . + "49f53bd5bdef1cefdaf37a667e2d789619f953f9bf5bc7d610a19c6680f99e5c" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0b78d4a2e0f2a0b53c9d94a79bd88aaff28a6b82280d91c4c84c5d5750f08d2d" . + "0b78d4a2e0f2a0b53c9d94a79bd88aaff28a6b82280d91c4c84c5d5750f08d2d" . + "8bac80babe1363d9f730983f08602382deb71990fe20294a477b03508ce8e575" . + "4824696f5667781386713a5d8c741c168f571a52d36dac170cee46c8045c8697" . + "05c4ac65dd1468a8d66a5bd384628645c61388b5b3dfa6d02033f77a4e2ee66e" . + . + "a06eb400ff219596fde93b2589f5dbbed7282fc9a46bec869c8e2b48473a6da2" . + "78407fe00ed1ccb11ed56f128cf3c057808662f3bf56dc6ae529a0d070533ccf" . + "4c7e98938f9a70e5de4407e9233bb73659c7202d91dfad4b53e5ae3bb3a33bf4" . + "2684e6e314d2b226f2faed0c615596e9f0f564c1f9ac367560c7802300f0d1f4" . + "4c4fb2613500ae763ce3075d44b2ff5fe7cba1bce044354a891cd46f64cc0b4e" . + "d78313543efdece79a52c7eb246747adab1fc75699390e2b322be8b359b83911" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0348b3ed6707a5bc52991469826648fadb3fda3f715bd7e406b42834fe9165c1" . + "0348b3ed6707a5bc52991469826648fadb3fda3f715bd7e406b42834fe9165c1" . + "cde2bd069b5e9772dd4b75e943c2d4429d85eaa7c4987f8862a16ca3ed5d033e" . + "929ccad9b0734b4ecc2b37d88c2b5cac8f9709893c749e106e6bf6c046f25037" . + "337168476a41d6033e621996b676b8e259fadf766736d8eecd0f760312cc3ae0" . + . + "15423f0092b5f2a45b2b0d7f7c402a0034e38c3fb0353dadc9097d0276885b31" . + "1d39743870c5735f37069932c6e4d1682ecd481c937e9a8b8d17386ce4cc9705" . + "9670ec016a58577083674703db530d9a95c10aca59a6112009cebdc02f723f45" . + "8c72e6aae5f9f04d9cba270e9beeadfed3a9f8eb712efb04858b38dbe646393a" . + . + "62fe2e1cd916a465efdc4d62f578ed54bd766041249ddec285d7da63fa7a5349" . + "254cead05e7da0a3d91d19336491721c4220459113bb426a4f0b171f51ca54c5" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "91992fd84162b324eaedb8b89b58f6abc7a88a0af98eaafdeded827a8e52de9f" . + "91992fd84162b324eaedb8b89b58f6abc7a88a0af98eaafdeded827a8e52de9f" . + "6f5b0f0478d08a5ba99d1c49fc3b62a88fc82fbbe05d87cde8dcadd346a34d2c" . + "ee3425cdee2937c044659d381456eab231b4b12e880fc0685b8ee48d9222aee2" . + "35e681ccc748c180fe26b3efc6bbdac54030818892830bf1f5f0378a069e6c45" . + . + "6f98973627798326eec6d68a467826e9d46612b9696501f1b179d54579e0ed4d" . + "5e8f62e2e835d6dc540d93f1df9fc219ff6435f8d5696d82767c0c925f142aa7" . + "beb479f3c195101660e285c4f90b75e296ebdc109788a13a3572a8787c2de3c5" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "bca04a5099d09c6c38f05ab4aa715c6ed617ed1e1824d446552fa1f786054a41" . + "48d176615771a81fdae8c4d2b227d624a53eeafe88da2e19f686827dc9eac39a" . + "5c6628d894c835d917942b9cd254a7ec9c52c49969f613187892053c55e9aa93" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dfa436eeb3a54df3e69cff527543b15f1cad664009c91de39d561cb5202cdf2a" . + "dfa436eeb3a54df3e69cff527543b15f1cad664009c91de39d561cb5202cdf2a" . + "ed11904a5ec814782c8aafc5dca1340de8b544d7fbf599825a5d28b581e600d9" . + "0361823fa917204e1f0934a6e8e7fb40d0b4e7352da9e2cf32ac63005431d1f0" . + "b03f9e82f3cb36cf5ee4f054ebea19295c49aa00d7481f1a196bad0bac4f314d" . + . + "e1447be29377c0eb21fbb4a0e488fccbc2a52d43fa120d112b8512e6f0cd0bba" . + "a324a6fd15edc02df7aa7a65d3c6fb847f0116f9fe764651f4f144bf2777a512" . + "9173b8aba7935f45bac6dffe6d36880691c601fdc9233416054ca57bf3cb77b0" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "9de046fa478fffa78f01c11ced56d73c5b3b68a2f6a3a13cf6b434d2feb5202c" . + "5dc8a45e855381679d546718d8620ab10fb6c915951cff38f31f0bb23a06d863" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "813199a23f85e656482c3691c7ed028a2f66f554ae483c2891c54cbb7772e5ec" . + "813199a23f85e656482c3691c7ed028a2f66f554ae483c2891c54cbb7772e5ec" . + "d70815de25ff088f154dbd9913c7df7b7a366d0a4e33db24ef66cd4b3c206c89" . + "38c98f7335d0984f886e879ed613c0833cc7177461f2b1a7d9159a06df761f3d" . + "c6c25b54093ceb1f7c6eb28cf30c4b6add93e4352c57b60bd3f8e575e2b2949d" . + . + "1c2db4f6b966f335f1b73f267573fc08348195b6b9d4bcf81fd6b5585899790e" . + "b4e403187272485c99366980d76647f4a4f9b4fecb2da3a18dde03a44a46da6c" . + "3a70ba45da328bdf55eaf5589b29fd0f8e862ba77dc09aaa3228b8287f49976a" . + "6c03987a8b35e51edcf449b7d1b7408e998f7acd9041298192850b0865090c38" . + . + "7ef8fb111a273f1895c7dcb2f61d093d0edd792a3b9001d66d4e1c01d154ea6b" . + "4bcf460a16ce7554e8473d00820d39170db569248fde3f7931b9bda2677a6791" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "931ba4fd7d2a9e617b741dbcf0a58c8e1f34ee0ae657bc7a09084364c215a5d6" . + "931ba4fd7d2a9e617b741dbcf0a58c8e1f34ee0ae657bc7a09084364c215a5d6" . + "9822cfafd387cd2c9dd630e19a6d634d21c79b6d7b4e0b2a877880a868c25a92" . + "e3b4060cb446d5cc1c928d8e791de1e8fb48e948865dfec9a5c492400d45fff8" . + "f96d6384442057e05da9ceed5244d6f49eff491c5000aeb33b5bcbe9e6792564" . + . + "ddc683b3071f8d7902535ae9fdb723139defb9e7520d3a594270ed76ec514c25" . + "92592257766dcf47ac3c096201a89ce8adfd922587fa744950abdd2e7b885420" . + "dd8d3e38be817bfc9386543b369045dd88b054c3bdf32ee4423ad5d80236d762" . + "2567110cb06e83571f3462c7ca69b7df4ec5fa2671b8070754e237d3df13ca39" . + "d0ed95a32610b41efa8188ce6a13304f2aa2135f3c83785d60d7ccf251751122" . + "588a6b003e754a403b35a0ab3db062e554d6b44817629c7e2e8271bf01ac099d" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6fbacf2b0ff53e4e09f9a8aee7985311610b4768ed884e5c0b6dee53cc4095c8" . + "6fbacf2b0ff53e4e09f9a8aee7985311610b4768ed884e5c0b6dee53cc4095c8" . + "33a606a6de394124e24fd1df21b58c90ca84921295edd24895c8520e37537741" . + "e3ecd51b1af0950b4eb6d4dfd739d061a698b87511a1c3ae6b7bd7ae26729825" . + "6fcbd4c005249c837d44af5e67a6f1b619eb8eea9885b5cb5cb5e66ac5020745" . + . + "0910b14c118a016b40901ea3ec20d36da4cfe312cffa3a8f475fe27c11470409" . + "65e7e5a11b167daa7e9de2284c9537eda275918b0582c2bf7059c2bb53aa6f44" . + "fb5c03d77e424d7d7bbe0e5015e06c072c87fd63c114e96c13f7850b83c1b7db" . + "7ea3b5fe9191e4cca6246f7b01dce874d90447e581c1e361d4e0c6c3b9a86f10" . + "7e9053f9dfd4faccbb7fee948d62032c2786d74f932e332646eadc015feb67e0" . + "142e47c220101e5b09ba3bb25070022ea9398ae5cf1c4c0c94bd9233d0a208b7" . + "e596206316265530dad531d0136555cea56bb04ba1e2a8030337d8f7915b8eb5" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c7ee2fc6463605d857a2a70a14b16aeb03069cfde0a5c750b55a2e4aa717477a" . + "c7ee2fc6463605d857a2a70a14b16aeb03069cfde0a5c750b55a2e4aa717477a" . + "925aa8206f0bad5e12f5d168fd6c534103b00feb288f4e60de5c8b69b7738bd5" . + "5753aa63a46196445c663e6558c7a9a41d01e14aec19238e260ba3798541a85a" . + "a17c7f27a914239bfe8f552803edab86dc1ae0533e31a02664f23558e0330dc4" . + . + "290349c56cbcf11e49a32827995ee823ac37ac10974104c67409fbb5cdcafa62" . + "d5b2b66edd19b5ce7c647d501585315ce40c5cb45406c8b0679d78df27ab479c" . + "c6824509e14c1cd5f42e0c3c3211e424961509b1d239aa71980755ea6bd48143" . + "5859536b6dfd0b3b2c334e2b7f9bc7a247aed7a06144d3769ea60e0ba1b076c0" . + "c2c956aa477cfdff60e445c01b9f53b265cb10bbab172861b2ecac05846a0447" . + "56ec7bb011c62b302ded326db5858c7b88102c09abe72759a226ba75866479e3" . + "09ff57cc0276654ae4dd299fc88b138e8e84917643b8c0f85840cf8cb30b6cb2" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "627198156fec5d11fbe21bf66fe27b49db8c88824d3ca5c1dfd9e03ce8b7f86d" . + "627198156fec5d11fbe21bf66fe27b49db8c88824d3ca5c1dfd9e03ce8b7f86d" . + "18edb6a916365afea5399c45c2940473af8d88f457971c12fa05ffff55dab36e" . + "8d521659104f3e30319f0ecefc8e3ff268b5d7132f742e5d992d936c4c4ba5e7" . + "3b9c3471a68fb5df8a9cf58169f3eb15aa2548440c4e3e7cfd7a4ef88d0892a4" . + . + "1be05c539c10a15c50c45bdc1c542d96d5e6d53aa026437cbb334049c2a9609e" . + "5ef73db380b3a1a78f8a1dcd21fbc11a254d1c35d62bbf22353cddcc8b32ca49" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + . + "9aa913f854cb02fedad45da21ed17f376d7bf08f921254c7bbf404c0c26cd47e" . + "4c545273eb1e19122af4c4c6cc112254e25b304e0f542c440e0716099b59c954" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bea1044a983ac4975a5fd9b19b81ceafe8f6cf01cc49f545f273519bd78ddd04" . + "bea1044a983ac4975a5fd9b19b81ceafe8f6cf01cc49f545f273519bd78ddd04" . + "b4ea367eaa259d56e3d46760d696a0e5b550fa257b3013c970dfe5be5e900bdc" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + "24bb2c7f06c9760496afdf12e7e25fa7ae8ed18b108775cd9ec79f0fda5ca6c2" . + "60da3eb5de6ba5f231f3dc71ea18bd429dbaab7e6d000417a72a254eaaa31511" . + "74412a9899e12126187ec7d77b4b4d171aeb8108d9056db522ab22126c23bea9" . + . + "78f74f9639cf09a0b6cf896244dd2821a0dadc34353a067fd284a3bdaaf49f64" . + "073fc8d778766325b68ed9479b5747dea5322b88699b7da7259235b559075ab8" . + "35eb8177a0b03b547f135fc0cb0d4690014c7787bfdea03a28661055f5d1fedc" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + "cd7ff9adbe398b3093075c183cab80a2fa57437b78cbea4895c0ade5b41851ae" . + "2c60d844783d0a15c6d0c409fd5f3621edd0bbab75d273105b838f3ed169e856" . + "02b35ae708c6a098e6d3eb8bc6b0587fc60405f29b26b17c42cb3f30b94668d0" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a362d96dd5099021dfd93f1ee8379e3beb57ddeb9895f6bf48e8b07c819da18" . + "9a362d96dd5099021dfd93f1ee8379e3beb57ddeb9895f6bf48e8b07c819da18" . + "8c54b76d87a973b2304cf3787ac08b25b70f872834c963ebab8d2fb327738e94" . + "7b865565b805188ec24efab9d41a09dd001c1189684e1b3b53562a7f3af617aa" . + "e889d5b1d26bd7888144fd5a73e0a4c5428439f321b98176218cbc637e26cc19" . + . + "b0c78d8c3e5bd018e2c71aa23c726116adef601a33cc70563d91747504397067" . + "5223349fd2e96e1688f57f474c62d86efd41e45ec72b6fdf56b24de5274e3d40" . + "d1b4d1336abe31e620f9049d3f94c8d2eaf3b9944e5e9876980380c4e76223bd" . + "0221107a524b4b574af3434a024cfb368312e31c7656b06569812544eb88b9c2" . + . + "f7118f0d55630672a1c00e663d0545789567b3cc709d138b9196236709a0f6ed" . + "fcdf1ecb6a3680b6fdf44b96fa1c37c2876a0e053252cbe8c991172dd74a8e15" . + "f069dcb5dc482551cf4005f4a8076993a445ef10adde5c864f224d1184c28505" . + "170e23f81cde0567d18c6b15f51eb2c173568aa639f671981f2cc21a7a272ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "66deb4b20ed12e6f84819cf182ad15983e226887fc31adcdaf945936871b0103" . + "66deb4b20ed12e6f84819cf182ad15983e226887fc31adcdaf945936871b0103" . + "ebcc9bfe45a839cf96e8de2b20e6effc83a3cd500271ff3d1c9476c212d9f8e1" . + "fb5a5ff6147e6f509697da08e552d40863216b71876db85a5e39c25d0bc80621" . + "4bbc11faae8185e8b475e46e820acc9280bd97b720f84a429a89a346caa34826" . + . + "be18190123942708dbc29484e90d424a293116dc46d3497109aa55978c95ff02" . + "d11ddb06c5d1278cb084af27baa31776b13d452d9b62cd94beaa17b05aa0da29" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "e30262c6dd556c127f1ccbf69fab4dc34e487370cd6e932da50b6fd64ea6c646" . + "dd93f2cef9b79a493d109c720cc602aab1e840e3cb5971a8ed2e36376114bf45" . + "f2fd9345dbd87c495bb8a038be6d730e70638307418152e3a1b21f7b1a913342" . + "0ef171023429321855a276c5df69d538fca4802484f25ad4ebc3d2e3e875834b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0dc4a1fbdaff16c0fc9b61a434860ab535fe688b793a86d6aeb838ecb4236b57" . + "0dc4a1fbdaff16c0fc9b61a434860ab535fe688b793a86d6aeb838ecb4236b57" . + "9843786715701604b4f4e34b1bb6fd6111bf535abbefd29ed9e25c89d2ecc548" . + "ac1caff7cde52701b0c12fd9d890ffd17a6bd66083086f160001aba458ee67fe" . + "66d7b6f9f85e93ae04d7685e27ffbcf7dd3a7085680d96a9f2847b2df8be3d0e" . + . + "0fc7d00e34cae4eac9693bc8758b9b97fa2782600784c55f0ecb5db2fbe4bde3" . + "68e8a990fa1ecfb5d64c7122632e60ea7c8a71f2be1d3e13723a3ed9ad00c148" . + "73db25f8182b6928d00f0b1fac882c8d4bb3c81e35afb4c751bdd10d264e3043" . + "e6392c3860839d6334e57a5b735fbc16e34c0ff96e7880c62e08625989b80306" . + "07f5912032cc0f25c5139eafcfe14559086dccec6d037cf217b0135d12b688d3" . + "a61d162a484c984817f701bc0889d471f5eca2d22008fd78133d1de536f6adc7" . + "7f98747107125af89787220e452f9a25404394b8262cc581afa45f5901b4fb6a" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "df11336088967d52c1bbf4928b6549caec98c97d9d6c65d060c0dd34d41127c0" . + "df11336088967d52c1bbf4928b6549caec98c97d9d6c65d060c0dd34d41127c0" . + "8aff6e8a9189dc78312f9d1f485e86a3b5edde1a49c637ee0329e8c062d6d5d3" . + "f46295677d70b260c1af4cd600b89560c560c5f7f0943784a9091a16b552ced2" . + "5f17742b7d62cc6fcfe5b283aab407fdb46521fa039531ee8b116053cf895c3f" . + . + "fb3b4a852edbae4a33adfdd590c5cfb25ac46e103e77f6792d82589bf3b5cf36" . + "d11f9baaa5d2cb6eeea7ef0e65a7a2b1a03139501dcb6bd47e2630ab3775a366" . + "aaec19d0985e172d92de1bdd4e108cb5692aded3b3f598c18c824d142c27e3ed" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "d747a876d1fa0756327708b8859b76b0c889f6898f319dcb27bd473ca2ec482c" . + "0b55f664b3e11770f220a80b909de0a2321f08acf9dac30d423a081680c21435" . + "2145faaae1e1e9c4f6aa06700512c087996694c5b03c5c6e22461c9c3987e573" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee1be96a597b8f27fda368eb0a08a36cc41617e8f7c71b38e0c74a2c3bd99792" . + "f687b6d6cef86283b1dbfc77df2bd9476ac8a536545c000c145484d05d858ea1" . + . + "9afb6b9fd453f6f8e3774d32eaedf8bc419f5b35687300026db2de025f7a32e7" . + "abdfa3cf2be9c139c29e1b2f98c9351a7db35657d6da6c37fc63b114ff077053" . + "5665231b8b74bd03b3c90ffda29f2cd4305a15b79d3cf8f44002ed39ed9c0c5a" . + "beb479f3c195101660e285c4f90b75e296ebdc109788a13a3572a8787c2de3c5" . + "9afb6b9fd453f6f8e3774d32eaedf8bc419f5b35687300026db2de025f7a32e7" . + "9df744c63a208a9c2dfd11a20e5ac0e0c2a711f65863dd3881664a30b6b3c42e" . + "24170f5927c8fd937fd786101c75448b1c18bb7c42bcac54017a170bef97b138" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e9b881e33924337621b88671ada772a0baba85d27f51afc74153e3b55471b3e5" . + "e9b881e33924337621b88671ada772a0baba85d27f51afc74153e3b55471b3e5" . + "1131b2942666d03ac263689b8b472c6a59590af97bf9d462cccabd171212fcbc" . + "0ddd325fb3039984e648217ad5cfaa49bf084cdb82595eba724bee93b50b223a" . + "fbe38445ef2809a49b158856bcc64d81f55d9c69fa6d515d24fe4461ff339a07" . + . + "c083e500f4926d6d1d26bd59eaff7169c7d852680583b27d7a0800a5dc7ce894" . + "a369761d6ac3f7dab4eef4cd8f54e41a511d8a338d41a38a2eee11564d52dc74" . + "7ed0cec8cc0acefbff172bd9f53c86c4ee381b770e81026cafcde27cd750d5db" . + "3af7dfd521fbc1455346dc00c7f0c604399697e173b1cc12069b076ac29b32e0" . + "c083e500f4926d6d1d26bd59eaff7169c7d852680583b27d7a0800a5dc7ce894" . + "666f0e43656de6eed82ebba5ce6ab65c28a5682c8932e124a1fa475270f27f19" . + "b19b83fb6bb0db06cd7a524830e1d2dbc0887d6660c0c260e5cdf827331ab175" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8b6d7aef73e73e4e14daa6ff6bc2299a346eb02ccc6409baee1a5519575d0aac" . + "8b6d7aef73e73e4e14daa6ff6bc2299a346eb02ccc6409baee1a5519575d0aac" . + "7fb5f595a8829cd7f013193464f8d40dfacf4db34c25c81e0691a4b38a92d5c0" . + "de4d9153beb8ae36f31703ac06c9749e0a5762ee22e567be409e4628550a1b12" . + "7d110a40d1bf1347287ad4dafe0a7a44d106ea95ebc8092ea1ba68f359df995e" . + . + "bbac54935d77d2b20b30a8aadf7dbb64c730bf6c47dea51985d45fca80794a35" . + "5ce872ce775e107da11dd92764c691797e2a84ebdafa8026ecb5bb2eb9fde8e3" . + "75f81925a9193cf74ae991ea13d0a06b9bfd1e9a55ba536a88d4d469885dcb49" . + "6a522c214efd2b43a26a63f8bd0b6f58ce8e117ffa55c0ba0764ce9e02c18c7d" . + "0bd2df1a589398cb63dc15ddb6a584003cad64ef01c1321e8b891d980b32ada6" . + "59df8064528ccae48c06488abefce9d1bffb84443e159477958fa9c607056dd5" . + "15dfff690a35040dae2ac8a9bac719aacc2d1564ff5aa48d86aa8307f4be6d41" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2e110c705a027a920cde9b87bb5ca17f83960908efc5e7419a4d966d2c15d6a1" . + "2e110c705a027a920cde9b87bb5ca17f83960908efc5e7419a4d966d2c15d6a1" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + "4c433839351306199f03baab8a9c1559cbb68c7bd1e0a251aaf5569139fffc38" . + "d3a56411b896ef173d46c58fd34f357f6dbdc97c484a93e5158515fddb6d164e" . + . + . + "8afac9add6c274657106d4332293b9f991d01d0509290ffb7b342a20435c7ecd" . + "e152d3441a94e11472a4921e3f2ce44591bd88d9601098097f726e538afd2e51" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "26e1f24a7fe3459ca09cd6547a0d6dba43a4807482d03b00f92ed16494bee5b1" . + "8afac9add6c274657106d4332293b9f991d01d0509290ffb7b342a20435c7ecd" . + "7810d9a6714cf3863257aa94a76d4b1e90406fea852a9075836e4d0128d35f6f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ec269ff4ab6afcf4494e121af6b3bcb36faeb489d924c0c862cb7af7ae261d80" . + "ec269ff4ab6afcf4494e121af6b3bcb36faeb489d924c0c862cb7af7ae261d80" . + "1721664760fff8571cd1bcdde4d33bfa13c7f42e8e8f404e42d2064ac5a0829b" . + "a747b61a9e1d4d7864bd800022978039888b9976173fca6f5aeb1380f0332898" . + "bf1b13c0381bde92d01e0c901c824b32f8120c3f8bcebeaf5308a08de3c4ecbc" . + . + "efad6706fe6787ebb5ddedd91d0531eb25daa75af7f0bf5ad867af5f78661b7e" . + "cc908293a81ff3d060e3f1556a1dcf2f0267e05ac94dc94e67efde68c66a0e3e" . + "8b0fd381e11a2c33fb7418697f9e00689e4c496ec5acb37222bf2e17219824c8" . + "9b4dd45cdfdfba632c674b5531f5254f3f57c16338ecff61ba794440d12a5ae5" . + "b059579910e69117e87207c3f5512fa1881185f6664530dae4c776495942d0e0" . + "cf10eaad2cadf13ff5f276c9c039076374c7802ed11c9b9c96dac52e39283611" . + "6f069c747cfce205731ed29944456dec411c97e7f690114399f2d8f182613fa5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "afc73ec9e1a454c7f6c0a99562bd9b9d8a1cee572ed2b7ae33f88aa0f9a08d7f" . + "afc73ec9e1a454c7f6c0a99562bd9b9d8a1cee572ed2b7ae33f88aa0f9a08d7f" . + "50073cb8d04dcec0eeeff9f5584796440cbe445b2e388a659c85500aa58c9200" . + "bfab1d11a589314cbc7b6af89b77c2ff853ab3c22be38b41bfaa8fbdb81fe64c" . + "851835fd053fa45e085529c7d8d5562488af1115094dc95e835ae7d45d0bb8c8" . + . + "6df03864bf9135fad3d0bf9d053d27b36edf9d1a7aa920e730315566fa12c66d" . + "a89402dec1c985ff5ac55a195030a44c079293be90c082d5caf910066387c0a0" . + "36de581302ad9771c27e689c8a2660b657138cee873fcbee2d96a31c3966f1bc" . + "739d5688b68f50a81823440da19b4c0dbbadcbd49766903eae5f3841a0fa8ee7" . + . + "6df03864bf9135fad3d0bf9d053d27b36edf9d1a7aa920e730315566fa12c66d" . + "a7891dce47cb8a919c3747eb2574e606bc61cc201926bbfc8221319c92f70127" . + "23bdf1275ad65f03a2e525f7fff3d0397e5e7fad948c1ba8047e50e1a96c9cb9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3419f7772e6b0a3110a6271c81f42ac6bfb40f454a1be77c285c32ba499fdd82" . + "3419f7772e6b0a3110a6271c81f42ac6bfb40f454a1be77c285c32ba499fdd82" . + "13fa3720e3943b5b93b1f2eada25d65be589e665edc63edc5034e4eb99b6d6a3" . + "e936bcd54627cc9ca754b63b8ea85f776c834d0cb35d0a7cb2146b390380c04a" . + "2f6f8660830ff544d4fdf96449882949a1e194aa9dc855ca3e518d7bd9d27d61" . + . + "2c83955a750e48479476ac54edd682ce95a5adb8e9cbbf03a2531031c115a0f7" . + "ce8f50f5c1f820d78791cc5c7d80263ec99cb111863f53a1110dc1d4e26e31aa" . + "5ff0c21ba6723a875cc99d2f267d0c1e7ee56e660659082339b6cab39d71e749" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + "d34faec153d8d6de5c190df1b053e895c05970dcb6f65985cda374e12c5ce946" . + "1430d519df53cd3756ead041460df768706299048707e807a4d6958937521f58" . + "d63bd63d13b970c148c9114eb5569012ffd3e3a5ef96d5299bf0aed70fb3863c" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "4b798cd3465cd40eb662a4d48c2ce8e3aa78017a0183a80a14da1f4974cf7547" . + "d190fc0fc52ec8b56d4d94173fc6aae4f3bc991ee779a38d16fd1b0c6d312243" . + "d190fc0fc52ec8b56d4d94173fc6aae4f3bc991ee779a38d16fd1b0c6d312243" . + "142ed85502ac214031d26da5230f9101640a1b3a82f5df6ba5070d20fa51dfe5" . + "50b748f43bc2fab3bd0283cf2487053ef7acf2be067891dabb0e722e2f972773" . + "1fe29211dc95fbc7910128a18ed255c1bf4bde12f0aa7dd62a3b1193abdbd366" . + . + "82b4c4b9c70ab43240f191c7f3c0e979cb4be1c8dc498e459195e85c58f5508c" . + "7c0e3314bedc35e9fffd0d150f5a671dad9bb46850cfc9632091a31aceaa67a4" . + "9010c0b824a082fc5874134ec485c2b5be971c5ba6ba4d2f2833ce9e8ef092ab" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "dac22168c878f75dcf02d4d74c8b55023a6985fa32045d0a88a63bd96f08587d" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0addb33438e5ec173b6f8c88a0db11080fac2679a037fe044b95ad4a6fd9a3fc" . + "0addb33438e5ec173b6f8c88a0db11080fac2679a037fe044b95ad4a6fd9a3fc" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "4464da11a8917cf2b8e0b76d5a6f35f222fc81bb7feeeeb990ad4149be0ee00b" . + "99bb6d58fc0924f463c9c7cf0b0fe2d582aed5dc48443ba10c9a0cee3a6f40aa" . + . + "77d9ab30873dc58272aaed8d229df6a505862280957053a0464f288f8504d35f" . + "92bceebbc380bde195b48975432f10c28273958ea058d46eb2b4ce1f477c6314" . + "7d090b1d7ca951538dcbe500404e1ea9f0acd11475cf709f85198aed1169d39d" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "24a278f9b16c11c6b40cd79e9bad036aaab96f28ba7102447d6e3d0a93fea26e" . + "29f898bc7b890fd2c908af10a230b41d01c31ff3c20fe5752ef09e0e9c17882b" . + "6b1c517b4bf6ee0e469c7307674016cb9de57558417f154b1e6b98beff96ee00" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5cc302e741cccfdfac953cc346db7d48a41dcc93db0df9a7e7759f83669df946" . + "5cc302e741cccfdfac953cc346db7d48a41dcc93db0df9a7e7759f83669df946" . + "d9eb6e7da4c63f48191a61b91a948edfc289f64cf2ed62f950184c77983e44ab" . + "cedd5765c66691e486e4d961a039b958abb695ab470256c6d776e4faefae9be2" . + "f3025b1c884da9cbf54ea628a2e8b19c221ca70f0eb86e533246674ab70844b9" . + . + "7563bc28e4b1fa53108cf1df3785c160b9a438dc60b78360c868b2fab3671b6b" . + "b5b4fc3812885bb9928da6f615082ee74f6be57857798c09f2096ec321002ba8" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "d98cd747887dbe88e7885e14c8d110d49c1c5736aa67dea120300463a955633c" . + "42769235b79541aad8df81d1ca39a623a61abae7db3a8b8a5c5daf71031d7992" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "079cdd79ca1675b47cf7a358ffa371230f130d82a25ce2b114843e264cd3459e" . + "079cdd79ca1675b47cf7a358ffa371230f130d82a25ce2b114843e264cd3459e" . + "8c5ae9160393e210ae6a7d43f2dd2cc10c8a8052e5bc5d24a5d5e9fa789f2185" . + "ecbd4b79ae9553c21f94c510a376dba3cea669b495649997dc77924d87eda1e7" . + "cbb681d3b0757895eef57979d91dfdb055d23580a2fac2a2a9e43911cd94319c" . + . + "ef7eb71e984b073be5d41af45ff81a9e58b047ae8ba2bc706d27fa277b772b4f" . + "71c5ffd21badd706f8b3582a0b533c4386198d037f26c9a2b0d028ef6cc5904d" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "a3f25e50218337fde052c06e3c9961dcdd84590d8952ade7943bdb3d46e41ca3" . + "f9322de798e83e86439223a3b1505beb1422a661f1242cae05131ce049e6f1ea" . + "3bbe71f60356e7c417862638372c0b76c0d874e11c77dec4cbfbd86803d97eff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "698b63560fd1751cefbbe89c3a4c7221d22c1407c4d81c5c149e6c4927c56185" . + "698b63560fd1751cefbbe89c3a4c7221d22c1407c4d81c5c149e6c4927c56185" . + "e3f60b970c2cb7174d2302417369e0da6654f5e44ab89de1ac08e8db831233ac" . + "6fd7fd71e4a9f0bf96ba4a17e9ba5391affb8fba34c0d5a9c975747f95941d28" . + "fc76300e57be9ff42d5208987755a0afc405ea569a66bce728b88ce7400e0453" . + . + "9bb7dce836564d6e3a5f3f6bd04b6df5e71762549e19e913388199775e50df95" . + "af36c5700fff41c5cb10656248958e7f6c566c41de300d9cac4af1a03c1301cf" . + "74e7be917e71bcd13f488bf56fced4668b6d0ad283aa3463dcb8d8030b438da7" . + "0738e891e77cbca2736d171f6b8c3c17a07d458688d263a25f43f3e7052f278e" . + "447cd6a66b451daa38be207d2de893eb433619d22df6fb83ffa8df292fccdc09" . + "466b040863ea7b6f6e6567b8f6541de0d67f911ea75140fd4194f9ff07036cf7" . + "23bdf1275ad65f03a2e525f7fff3d0397e5e7fad948c1ba8047e50e1a96c9cb9" . + "816f101f35d2c3145a0fd72f8091f717d2927f5243f7fabff09300103911d0fc" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6c01a025c486812ab0483e3b838b6fcf0da6dbfedd2eead971c5d3cf7b68bc88" . + "6c01a025c486812ab0483e3b838b6fcf0da6dbfedd2eead971c5d3cf7b68bc88" . + "f55e6e073a7f51b53135d60985ba789bc3b47d05b23410ad481ea8e6bc705859" . + "7daee479f0763266ec35ca59fb7f19115d8c54aecffe9c738b23382bbb5d4cd8" . + "55ecb1da988ff13c7294c5ad091b12c2a628ac953255654dfef0dcd90da1ca67" . + . + "42bb376c1a8a716a2983ef2659b86159568cc79feae533293f3dc5ddf0c83f14" . + "d497998eb5ce58126fe0936dea999da78139b2368978466f13326dfd64b3373d" . + "cd17b09823cc8601405c82093034df2922c3f94e0e6aeb44ee5293bdeb6e5f04" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "6ae7aee88922b09e2e3d32bfbab274f847d5d882a903f6f5b4d55e5e241b2813" . + "74b54ad8258a943b10a21e34e227f6d5a53c097afc1b4705bc88e97a65f9bfe4" . + "5c18a8b51363db096c54f5c0122dd3637da9a686eaf38fafd300efd85d4bde9e" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21fafb8fe0744294901af32d0a98c12c8f8426a35e8b1d47e8d8b7d9c459fc90" . + "21fafb8fe0744294901af32d0a98c12c8f8426a35e8b1d47e8d8b7d9c459fc90" . + "c2316c9bde76c00b57051ba68dbf87ccad7aadca31fead4fdf4c91ae9f7655e1" . + "fd4bdd5bfdd577f49a38dda781ff314593b869e8f9a52a770c2f4c46be3bee1c" . + "444320e20bb3cc40cf8c0f7bb48a02377f233070db4c6026d5323deac5fdde9c" . + . + "435c92a2180ee7eeee539f4b57a7d99f96dfe7e00d9a4c6bed580d6b99d28371" . + "f39e8f8c4116e74de521a9c9426bd6f1d2ee12c7d3cd9d7c70955e8af512c4c9" . + "a90526e8cdc8b295be33de5fcf35e032370a367baa6e01c7965c2b68641c207f" . + "07c6aad7509775655214e9d868606b9ac07aa2a0d7883be1c912bafbd84afbe7" . + "da1bd0f90ad12ea0698e1c34d5bbf83333e5511fc5f0066a3d5c6385ed5ffb7a" . + "2be4ecdcdafb3c3545499f270e5b7345f3c3725a7b0de30ce9ea56b416ceefb7" . + "8514101ff6d04c27888ddb2c90e72033c3256e0332303783ffc386331138fecc" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "487af6caaa54bdaa7a5a2360d35ac65ad7348ea5dfbc012f68d0bc8ea78e215f" . + "487af6caaa54bdaa7a5a2360d35ac65ad7348ea5dfbc012f68d0bc8ea78e215f" . + "14235e340c12159571ef3caf709cf7568917916cd3ce759e3c7eb884014d8596" . + "6b964d5ecaec655cb7f8a4973d41ebe503a46c26e16e901c82875fd78f50110d" . + "405303d5c7ca161f01ca313e3dd49cfda634d86f6e5fb55c90d623e26ba275b1" . + . + "005b026f883d99e589ca571d1f05e8a1d0080fff6c9cce254ea730440b43c66a" . + "50b0b952004b27bcb4dd64e35716840e45ee5046a47859ecc3c0a05703c83a85" . + "045daa014617aab6d64110a83080c52c62f2c8b025e7a6607942253819a8eae4" . + "438dadc9115c050b9c2123f650be840f50802fd85abaacde62e6713d5dd4c02e" . + "e011ded65eccd492b4e553fb3ab56300366c2a2d86c2c33af7916097b77bbc09" . + "0c24bd74823d847b67a007404a41f43ce39a50ccbbf31ed7829df5ccea9f99fa" . + "08807dde48e633f4b04794fc7f776d08630ced4202ee7f08ac37a26b27caa1e2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9314d9f46f7fe2e3ce74bdde06eff97fb5759f50f4d23bddadf53221132baf80" . + "9314d9f46f7fe2e3ce74bdde06eff97fb5759f50f4d23bddadf53221132baf80" . + "d7907bafcedb4642bc50f89239bbc347bd44a10acccf6d937bd0d69338e95ce2" . + "9405484ba2d2ee22917356f1639163f9e5a2d8c307bc884515b3f77a932abb05" . + "15e6e740ef899790adccd6b99a2126da99ec7d4a83c3ea039afc2964b1d8d805" . + . + "2bcdc14fa62cac71c1d78242a63e286f8f9f6485402fd16a409b4d22211a0212" . + "45a3533de39de450b5a35a7a9045ef5a98f1107d74d89bab32d85619a6ed07cc" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "5c40ea9badb9dbdd208daf3a958254214cd706215ad5d4be3b637186e31aa70d" . + "ae8a21ee6b4be559e2f3768f648151bffbeebe95a80de4288411df7ac7b7fb86" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b44016c4e77b5006b11a64de39448624a2dfe129de578399dcdd987e70d573b" . + "9b44016c4e77b5006b11a64de39448624a2dfe129de578399dcdd987e70d573b" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "38ab8defd9afcfef8e5582afdb5317521dea9552535806c0d7b17db7650712d0" . + "8aba65842529856490cf986c299bb5b6944c60ff94c3857de705e6e8ef7be8f3" . + . + "6e9820a240717cf7daf5383f00f99f2a661d4ad0354b05c3e85e98057998bc54" . + "0c22db8012876e608b65e446e73fcaf7a8e34e124f6bb35640ef8c74ba7c9747" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "bccda7ab9fe6a91f1d054b445fd24f228d4b69646925a4758341299ae7d94033" . + "ceedc42c6902d804d9e8e8e97aea0ded1b62561dd7e54d711393efed6471c8d5" . + "3b738ad7190fe17a2b7f0b158f4cea080be43f774aa623e96b1d22b6838551f0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "01a9ee25dec7fb7075131f250557d865d26c396aaddbded83a917012808fe043" . + "01a9ee25dec7fb7075131f250557d865d26c396aaddbded83a917012808fe043" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "621c2a15a76ac368de432616e949604f49c7172385b099bcdb960a50a6849eac" . + "8afe53eb0304f3dbb1a210b86cfdb98896b8f3ccb02990dee77f28ad12601ee6" . + . + "9b5d121515c15ac7e3a0b4fdd6b64577d28e81f3bd590e547be284c701762319" . + "ad8979e6fe415e2b79e0489d97d37f0775a09eda5b2d70c24be1ea549464480d" . + "ac41f1d6870896e39c4c9c2580defc92c8a259ba598fe077a1e0971924cc5df3" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "df6d8158bb8fcc3f4bda4893d7f82a3c9518bdb06ce2c03d38fc06ab029ad2a6" . + "b896799aa669cda03a7ee19c064b57b2a94eabca46086368c92504ab7923d00b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d5111ecafb89ae92695039fd02e0937261619c9cb77001d3e7cea9a6e6095af8" . + "d5111ecafb89ae92695039fd02e0937261619c9cb77001d3e7cea9a6e6095af8" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + "595ddc2da7caac77798184784f01bcac02a8b2ee0fed88e2cd5894e11befd473" . + "5d6e8a6faae7f4d0b110f676922cf799cc918190963be57be59c4767bb1e00d9" . + . + "e316ff3a0d3d5e3d800116023dea8805616c4d9b4965ea0a077b7a2b14fe315f" . + "ec3dec816a82c872f4484798b806b0f8f322819be66b2da222585a1a8f5dcd97" . + "24963959aad5c002c68dd8ed3c79ad907b2e323f39bf14a63dbfb9727d106111" . + "d3d24769a2f2f7d03c84e7685115a1f3fe4c906b23e98b68fe3f77c5754a1a20" . + "c622b8687f24790c556359d107c762146df54fcf5a0f63a5fe061da7a654b4b1" . + "f1c86c50ccf53c6f6daef232583b500fb058cc9409da9e9d7486743a890c19af" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b692d259062a06946a9873946c8a5630e2dcad3e3d336db86b5181c1e9fe1ac5" . + "b692d259062a06946a9873946c8a5630e2dcad3e3d336db86b5181c1e9fe1ac5" . + "97e7441cf5cabaf41a86f814ee4a2d022bd9558b449e34217f055c0d5bb33c00" . + "35886ec6dc899c1466bd6e0bf310686f5bfc692a881042097258e17f6ddce647" . + "af931028fb3e8370911d935ecb48d93d94d2ddb7c2965ac0a9113a80c3459618" . + . + "6f4c6136436c2f70c804cff365c9997c54a96b53a00c0451073a9028ff0399ee" . + "3e3c2adb7652e65f9c2611281cfdcf1c964207e9ebf88936cecad469cc12b6c5" . + "53be02edee29edc3ca019101568b0d8fd29b7a7ad6ca7227a06a01719e121518" . + "56c7ce9a582b17dd9e07bdb687cb55c6c69d5cd0d97276a09b6134153ea9465b" . + "cf25f4be8b3f2ec19a7e9df249d52f0144a9c58c5f45c0dca83e5bc82fcd9621" . + "c0935288b0d4f18b100183bdac3133a25b62d29a278ca755a3dc573ec96a657e" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "33b081b3383964c7ae77c6bc3fe82c958a86eb2728fae2076ee4f61657189b58" . + "33b081b3383964c7ae77c6bc3fe82c958a86eb2728fae2076ee4f61657189b58" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "b48ae6f04431ba4853c20d9be99825512230d6db0f85935b135c2402190d17e9" . + "c036fa45263fae6dea143e230e6848ab7ccae1568e110020edd4bbe3de4dde72" . + . + "c0851b8ef1afd37318d938462f5e9eade7c8c978883af75d67b00b252bbc9b81" . + "499c5c1c83019ca6a4bbbdb8ab29f29266167eb6d39f58df5d531c88f63cc3e9" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "4216cf26603d1604e3cd47e22e51623071610eed5a4b26df3f0fc56b653b75da" . + "265d4a1ff57b534859bdb4cd9f4857a6388be956369efc2f3f7f0b6a6a813433" . + "4a9d8918c1526a6922b623758bfa5d8642f9b037aa6c8b3e449a997a8b143e17" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0033f6477cf5c628e596e42d89337efa23c21835acf47f1aa9c4db0e15bc8e83" . + "0033f6477cf5c628e596e42d89337efa23c21835acf47f1aa9c4db0e15bc8e83" . + "5e106aa3793a9a82eee69c03a441f8994219a8dc35e529c6b756f70cb2502996" . + "59a5bd80a74ade385669d51c532f7a0ee4a6fa7a4c87671cd304a75ba581f570" . + "e73151ec12a822cc01ee35e1320dbccb4952096cdeb3f21420bd9f099aee4272" . + . + "5934dfda450ae282e1abd71662059969388689a1242c3cdf774af08489b8a75e" . + "0bf207d310d9694e5ee97611d46c3030d576f7a7350728a565bf2d703d7440a1" . + "70eca76bdd748e0574d4a5ed104131f1d188147306744893f33143e59236bc17" . + "252fc75af9cb97345f2d4fbac49fed4a47488cbac0e1941ec381355af3bd282c" . + "d22a1c4017349e7cf5a198d611b94c0799088bf2995ebfcbc001614aae823e15" . + "6dec7d7c7ed31efbf9356114a634d757cf64b528506db9c065197167b9bfd29e" . + "6d720a4c198dad21adbcdc44438428e55e50c6c80d6a393ce9fdeb7ac9244faa" . + "9f18f191a5114f56f107f8c2d32bff7f59d71c34253e98f6b6cfbc94722de6cb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bec5b1f4c7400b4bf5aad8cb566dce2d0673841a8625eb960f46eb87e5f9d6cf" . + "bec5b1f4c7400b4bf5aad8cb566dce2d0673841a8625eb960f46eb87e5f9d6cf" . + "452df0ad6b1a58573550af7374a07770f4648ef382c442af9bf48f3c8a48962a" . + "9655120a079e86afb0e32ee8705f74c1ea8db1efec602031aa80b761dfa80be1" . + "c477375d9dbb5c7aeabf32ff892eac775fdfa158e7e5b6f9068838a698ce305e" . + . + "b29eb3268a7262dd58bc82ebb63a975c090a95ec9b2187e135b455fc9fb44482" . + "782e5d8279afb17cb1d88266affcabf9a0655293458cc8f0658ef8880d0e53c0" . + "bf4ef1876ee6af2a4aa8732187d9b2c7f6db3fbf909ea017d6795d60676b20c3" . + "e69573c0c4a48f649bd04d3010617710f0b468e3e754567cdcd319608ff4ca3b" . + "b29eb3268a7262dd58bc82ebb63a975c090a95ec9b2187e135b455fc9fb44482" . + "135b9ff6f7e9e564c2b95de49529b4d982919b008767cd8b13a1f6eeb817b2e6" . + "4a16413a07b887448920649c1de4d34d4ce41f45cfbce8b508c0a38d9d5a3405" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "92ad98701b1248cba3fd9ed253a77f6dc4d7e4df23667de164d9849a15b925cc" . + "92ad98701b1248cba3fd9ed253a77f6dc4d7e4df23667de164d9849a15b925cc" . + "ef156a655d0ce340cfd7e036f3dc07bf2ad79bcbbaad4336c9989ab83590afa4" . + "488cc0886b64f505825fe90c6d7f98310eadd5f740f2b036fba5e4ca84ce8f8f" . + "21e0e23ecb8e3d45cb2f199030019e033d08ee31231636b2db426e49cbfa270f" . + . + "ea03dbab09b8dc5555e0bfcfe81180bd0bb1cbd1628cee4c171bedc3ca2f5f96" . + "5f532a203b6231614e5af3f7a4a1382b62a03b6f90ab8477f2752dbbf4d09459" . + "b55bb7a3402acbc04a3c6855ba4358158b294b52347f0c863de03ebacb13f2c7" . + "a91dad2e631b75b945d827cdc590ba953d43386f1f42f1baac1bc03250551645" . + "ea03dbab09b8dc5555e0bfcfe81180bd0bb1cbd1628cee4c171bedc3ca2f5f96" . + "365a97c83cbfe052ebd26b6890523adea4c3b946d9503880d717ba7bea9e92df" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2cb31f1a9151563e701ec2c50c1425a62527eaa4fb0a486d2cb6c028eb899190" . + "2cb31f1a9151563e701ec2c50c1425a62527eaa4fb0a486d2cb6c028eb899190" . + "04d9746daeb8bdf3ed98d1d7d090936d2e3aeb68ecdc5508f59c9ab615115749" . + "e1a6b4a1dd756d16a7939768a9bad9a3f11398c289eba8f02de547de1f1c7b1d" . + "cd8e5a88a51c41838a35fb9609b59b4e5cbd76abe3543c6631fe40ed63aab1fb" . + . + "45f34049c566c496941ce6b59305ea298d42bfc2808e5355e78427b66ad42235" . + "027477e14931824ea497f623eb4f90a4ae6b26630d2c12fb7c8dbe954febbfe3" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "a4228e6449a3ed551300981706c5b4d155409519e20b2aa4cf8be00b5be67361" . + "b27d7e52c807ee6afd51eab1bbae3e155fd69c5183a4763c65cdb23cd677931e" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "359c0c0c5e724b747dd9308e321c0f05ac3d48fe6ab5f7c4ba0cf6fcba73dc96" . + "359c0c0c5e724b747dd9308e321c0f05ac3d48fe6ab5f7c4ba0cf6fcba73dc96" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "40054d249d648f8d680b8f560c2fcc9e04dbcc3ab43fde361d18f7d192171630" . + "8fadb8ed797cc97ac4b23f9a0472db8ae97df0a47efb16ea5d572172e7870d86" . + . + "3d0fed1e15e720fd8cba2aa54195f7acc237abf2e6193a4acd9494f71e04477b" . + "3383e8b8e6969354ffebde7b8e6c7adf7ec499f7e770a5471ce2e72efc3dd576" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "3f96b1457c04194507e9f04b508544abe5f36c4a161c4407cc6c513d72ee330f" . + "b00d1a52bc9d1306c36e46e9611d32681a9e4079bf5e7efbf1a856b199326faa" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7351ae8a9210ceeb590f3b9f335d7641167e9f4c52b2455b9a00d5e6ec6a673" . + "59c4c30feacef7d258d1826eeade6441f44e7aaaef0e6da4f6921e147e552d47" . + . + "91da9ebae3073c5b23160223f8fdb77f3444c0bf47c8786201f3a4586d19c40d" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "83f0e939c892c78abe6a8a3388337061999777364d2a98c4c49a668557cf07b5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5495504e3a22e75fdadaccd4142b8f54adcb493a8704aefc37cfacbcf77ba41b" . + "5495504e3a22e75fdadaccd4142b8f54adcb493a8704aefc37cfacbcf77ba41b" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "345e174149d4d7897b63b71eef108c638134eb33a5183bd96f81ea5d13e16560" . + "566ae6c025bf344e410f7bdbafdea599c6d9469a8fda7a6c567ed38e562b9172" . + . + "eadf96cdc3c5dc849ee3d1c1199e3ca0d51a4408dfb64610e4b1cc041e56e5d8" . + "1816778632c056e7d6985e9277fe3a4bbbecdcc104e06e41d430e2db95f0a0ea" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "5f19861abbda51f8c4b87fe45ce0fb26547bff08a62dcbccceb33c2205bf5561" . + "99d54c80794bdd2a41b1343d251aec41b9ab2048922e0106515d10f9138a5573" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8776659139d8834b1a14992955f25caa923e1ba5166c0567502290c5a2699248" . + "8776659139d8834b1a14992955f25caa923e1ba5166c0567502290c5a2699248" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "e62f1204e1a8181b306306375562a1be889cff2aaf4c608f6c1f5a5fbefc7c1b" . + "5bbbfc1b58f807f68466b87c033acf06a5218900a96810960a36f9d74737511e" . + . + "f538e2efcde88a7d79e7bbdde53b99c665f07a54e290e9c4a9575630d2d2c76a" . + "6cd687cb9fde109674a854f34cc7c74ed16902823711bc070f0b19c34e901d04" . + "23c2a356eb7a9a1e7983bfa9c85697dea983fffdf34f03ff605be4676365d0e7" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "5ae6d35a5eaf5255ae48e352cc7f2e267e83cc094b864ecd6ca8f0f7e491428f" . + "a35595d42bf8448ecf88856778a905bd40dda40efe116345f577989c8002dbfc" . + "85c3f7b45307321450805c74750d2a41cc9f4aa9427c7ec023bee06cec7d36be" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f17fea19e35d1d6eedb59c68a29a61b92b9358c53858f6fb0d0d0c08920f92b8" . + "f17fea19e35d1d6eedb59c68a29a61b92b9358c53858f6fb0d0d0c08920f92b8" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "90550fc92046b7d5eb26b8f563c0b01ee39d5495e16c6386641b7c0654675494" . + "03595b8d088b1dd30539df3ef720c00c8f3b9325528849be41a5aeebadb7e4c4" . + . + "407fbaa3fdd68bcde74120b5e388fb8face320303a732aeb837559bf692cae9d" . + "7edf1d9354e463e6b43eee68f27b6f95e321798a6e6267049fec4937fa153632" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "bcc9de2163aeff91bfdaf9bc43b164a2a6b0797434f84375eef407a15eeb53a1" . + "bf90fca55cbab7cb78f4a762a2df48810f06e2bce8f98f90b0a64761a0cbe928" . + "b4cee62800149bd7eabbb6efeaac8cb42bded6de930a327b4fb61e2339befd91" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6bb3cd146d81ba34ea1ab4a73cc6f69bc3843fca1f5fab7dd5948aa78a2d532a" . + "6bb3cd146d81ba34ea1ab4a73cc6f69bc3843fca1f5fab7dd5948aa78a2d532a" . + "f28f3d0b3c0c546a268e3e8dc487c5a45d23457e4ebf1b67e654779e91c9aa22" . + "516027d58cc9d9a49b4efff2f521f8104db3a00348c7c8a1c12808132e807025" . + "e65b851213e55451a6d5c9d885bb9c507226745d098137c4fabd3d7ac20e6f8e" . + . + "677f7f5a3fcb7bfc28d904a2ea8661a8b205a6ae188fef90ae0043966db29602" . + "93ddc88ac3e7e19b85d5c2f971f071f3e9baa9f4fdbcdebc49ce4115407a1c61" . + "0f94ce473060e7c5503d6bc14495551118663605be875c111b20ae9f9a3080b9" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "677f7f5a3fcb7bfc28d904a2ea8661a8b205a6ae188fef90ae0043966db29602" . + "c6606b414f553d2bb000131d38962c6aa3db85513c48610b096d7631089d75ec" . + "cb2ce5003de179634adff086a17010f201b758093f97c5192385e387740cb0ba" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7d8ed29147d1da3df1dbdf0269da7e479bec21639a2a5ee0292c6a31dd7eb9ed" . + "7d8ed29147d1da3df1dbdf0269da7e479bec21639a2a5ee0292c6a31dd7eb9ed" . + "9dbc664b7bd664c37409520df959adb3a81df293f1a1db6ac0c1d38d121263d8" . + "89384164ca12373dc41c015f6a3be4755d61496da886beea6d2185b7dd5b8aa8" . + "0071d672b741d9a1a50524bdb6843e44a961dcb02d2c924b4c7badec794645c6" . + . + "b6037a5f3bbcb0ab1df1a0aea5cdee21bc7c425c9b9d88ecbfb860c51a82b0f1" . + "8f53250456803bdf74542dd5c1213f6bb89a8d2eb9f6e7cda1c703d37f1be7c3" . + "6d543a82c0ff0220f8322c4bdbbdbe0cad4a04b9e35ee983c709a10e35a40027" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "29870373e54009ec8baa9873582b05a1afe8609e83447d3576ad6407c7c12c28" . + "0f4d16d2a8a001569a866edaeb88bcaed58314d51b4408b58d64449575649407" . + "d64ccea1fd23acfb9277f16ed78b2d24d16e8bb9e3f5c8552ee987c1f4ba5439" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e15f8746710b6a2fb98c42b9a36ef5dcab7a0b66a64287f6b358934f9d9b2432" . + "e15f8746710b6a2fb98c42b9a36ef5dcab7a0b66a64287f6b358934f9d9b2432" . + "b2f694a30614cd41066c66afde297448bda80a24b2fea9823628072f04fbc491" . + "42be07685ce259dd221e91e42186f49bf05be0bb675e106e3eed5e0c9fd6ab72" . + "1bffcb8279af74532a4f8cf6f034e6f2066d57c3043f01f7f3081f38a2184dc6" . + . + "4b163ac7cb4440d815ab2574e1ec58d98574d24885602e4b26373cf7d7645357" . + "86550328ff7b6a9213da4334ed00ab3faffbd67bc832b7ac9f59194e3872d459" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "81a294cb0eb9912bc2a0ba8da214203fa987955c43b1a113b58ce0eb2036d2a8" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26d93da0d2a8432ba3d8d5ccbb0825fd755e3142146168833960e31d5131e4ba" . + "26d93da0d2a8432ba3d8d5ccbb0825fd755e3142146168833960e31d5131e4ba" . + "ed2add28acf0086c902c2053eeb7771304dc1b091687518ee43c3af6c4a1edc8" . + "bbc3a0d444ec1aaf0cd70590db26fb219c6553c694497e1e44c5b73a284d46ff" . + "4b25ef16898d33a728923dd9179ef2d7c887a5c9fd7300a5e5c9b77cecfb2219" . + . + "c2db23e277720c7d0a58f2155ef7688ec380f611fc9a48aac7bc1da9fdcf2516" . + "62fefdab6cce03a06a5ef0b78a3d4cb9a845d179917de55945bb619e8d890946" . + "7223e171bc393a27019f00209e80c4022528d023e339b337645c8cffe564fcca" . + "869a078a1dd4986226e0ddff89ef739a945adf05028a37698d23e428941af696" . + . + "8604312c85b815f4aa18505785c76ccbc2802b4aac96d9905f96cf2c6870bcc6" . + "cd1e7a42da9265c975702a4ffa42a4e9cc3ac70805f1b32d46043bae866cf1f6" . + "6bdefe9cf42f1efa0821aaddc06acb84037a14918a51c17224430a9483471897" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d06e9f3b327e3078e914bdbcb35b698749f1cd823e793fcb45dfb8cc4c8812ad" . + "d06e9f3b327e3078e914bdbcb35b698749f1cd823e793fcb45dfb8cc4c8812ad" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + "5697599266a98be806d40197ff754f4aaef7c66771beecb3e32d46bc70f9029b" . + "95cb5aeba7cf74fd83bb4fa8a9e4713770a25a353464923abb8312b920e3d6e7" . + . + "485accabcf09b4db4bf4e14f8c5a9a6912d0e459c5d0b359924f6be31a3bab1e" . + "4910e0312fc8da5974a269afdf65810ac8da779dd1ac904fbbe862ae2e48d7ed" . + "876d8f99b3b88fe7ab4afa9060b9a97c4ea5ea405b2d2e700312c391c158f7fc" . + "be7f6dc27352cee8bf0460de0c86183f236e116b7000b67559bff8e5ccb2da9c" . + "2362e2c67c48513ace35a1befa7e570e579391d7e5effa0d046b102c7dbd34dd" . + "b63d89ebe4041e84fe9f91ec9919b965887e2b65b15a7f03ccdf1e80ca1e9dde" . + "04d1023d3b738f69f1451a09242b6b512688a849ab74eb05921f4d74ac12eb55" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4b14b393f4745b8945dd889b8d20be5276a0d7bb80b096abf1343215e1914097" . + "4b14b393f4745b8945dd889b8d20be5276a0d7bb80b096abf1343215e1914097" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "86679422bfb010556a77fc4612f31c8ca90049d7199ab97d540be4f34cdcbac8" . + "50b7ace2f1fcbfe84cfd7d07733d5d18a9a0738569a535c63262878ae679197d" . + . + "0c90204c2aa317c5adae89bb72513c02b7432add6b5a8538f743b36fa4a126c6" . + "bbc3c8bb5f44a38b8261561557e645cb7c928f318a30ab942344abdf6079efd5" . + "19f7f3dd777bbcaf0cc491f6f8adf119a8710a210e81f08fc548bd0567060da4" . + "067228384bbe28af84f3ca5b8e8bd8241af5d4178ea00f46f5d06a9f0682af5d" . + "f681305defb2c7669e8ec938dc97a514802e3f8952e2c48c6880a5529e618730" . + "0fbf47c7186ac670c08c722443260a76d38223c8942449c5ff144c1b5d977b20" . + "ed200f0b594abcc4acbdf8db9eb75b74bcc7cb26e747c4c52087f33e1a1d78f5" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f2dffb06b989dcbdff9306473d1163ffd5868a0954630654213065420ff75bb3" . + "f2dffb06b989dcbdff9306473d1163ffd5868a0954630654213065420ff75bb3" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "548b4eebc9a7ca89074ff70cca5e1f30717c60900cf7dc20a5ec9a2ca16979b8" . + "8f00138ca5a807d1f8129bab682582759a8d7bb6f6b09eb87e176cedd438db87" . + . + "b620e8af8fbbf4531388c876290c2acb02e90e97fc95ac3b80ae978597baba61" . + "695593090c9052ad38ceb11632911974a9124a50abd4e4a4674c14d544950aa9" . + "5112851fc48a83b301f7d5ed0b2e40e140ac3de6e4908a1396c66962f59ba6cd" . + "c3014a3bed93fcd1fedefedba8264ac49ff5398943b29e03109242c8eb6c8422" . + "a7f33edea1254d1b9509bfdde8b9c302e3ae3d0f72a9848398bd43ef4a6bc9d5" . + "4ce89d8f38aaf2f3e9d263874137b7c62dc0b73b0e5e06b3d3dc716a7b315853" . + "90912725206f054a25ea40457f1aaf7f88349bac05d8550ef9b2cadf135ded7b" . + "0294769e916ba664d57ad1e4184c18ba754f3cc1609c892bcebe8ca6bb0fe582" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7b32ffddc764d91e397035bedd1f91558afbbaede8d4711dcb26a20e754614b9" . + "7b32ffddc764d91e397035bedd1f91558afbbaede8d4711dcb26a20e754614b9" . + "c045c35041d4f6e5471dd1780484d49ec0bd9ba739d08dea9e2a51a74c0a422f" . + "366022110f3934ebaad5ac097812685e3a3613a5e06ec9f2f2c80154422dc629" . + "5920775b9ac70968cb1a3e2758e63aa04e254bc1fab8258aa9da848ef837aa31" . + . + "7c0c451b8dcd8772371aecefc23c24ebb4ac5c737b24acfad5a3c8de184b07fc" . + "597e357370fafa12f979607543208d5e92c758f88ab58307cbfa155298cfa363" . + "2379d7b0f02dd828cca0d375d404c6a15649a568dfb4c6182530d698b98eab86" . + "96c35cc982595f373eec85a1254bcd4b93ea8043420b1ca57ed3154304ef85ea" . + "6ded7d61e87f2fa76e9532ae590cc339654b88f31ed8120201fda8ee64135dcb" . + "010b3b0230975eb2ca3200bd79edcc403772d79a446f0bd72e5d30f177bef900" . + "ebf274cb95bde207e4f378d02d4c8e3670d6a36fe91014fca2f53a4b8dca990d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9ddb443bb4fa8a4c7f7fe42f79980fe68307547c3e4d95820e8bc5c383438b9e" . + "9ddb443bb4fa8a4c7f7fe42f79980fe68307547c3e4d95820e8bc5c383438b9e" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "92180ecbc0286f677f99872b1c9a32149b48642e9c7ad609ad951a92b2cb6aa3" . + "807d06d9bd00b03087ac018b18ba36d7a4e28ec70712a46e000122640e99c8fe" . + . + "59bbf78466cc7295a2758202e6ed24c228e014968bcaa5418dbbd6614c46e9b5" . + "7475aac5c4388c57bab2716fb6a221a8f701c3fb8bddf59e7bdd047cc182f769" . + "cb40e65835a39b4ac770b37beb7c90eac24f78106024d2827f1f4b7cf14cb0cf" . + "2ccbaa9f1cd96fdadad41b139297d91480420ee9ae49b99f8498cd067319fea9" . + "b2f45846d6a88d261a5e9011f3928fed5c959b98e73b4df06594a779f9b4f4b3" . + "86e2196148845ba85f3e21d4a1a606f5ef4756f79f1ed7b9a3c5e63633fe88bf" . + "dbae9e5a636d2a87fe44f6e01118cf2b64053ceea260ff4b65325d9700df08bf" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0cf31596ef535e3b3bc827880363f4e074d218a0f4e3544a7afe04b9b74fef63" . + "1b6b1df2f198208f1300038cc26bd6fe5aa353323483b1882f38c03be4fad7b5" . + . + "2f5392fde6d4742803eb5eaf7b20945ddb723e49250e36c928db22f4a3d4ab16" . + "ba3d976ef54a3ef58a4aa7974fb3967c55ec7d7b126c15088a567fa4f991e793" . + "7e2f259e2f27d3b87170c9e3d9270c2c3b842a418da5fa3f6ab486d73a69e4ba" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "bd82dff58821b53306f8d8d25c9a66e26a3257e29551db8548afe9ec3a447591" . + "d261fe52337cbacb0cd5e998ed8cdc20f79398644ac86698ba1d710062a1423a" . + "bc9d4c5dde3c21e82dcc0e8faafb445abccf5ff6ca6ccc2681ae0a5804bef3c9" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95328de3b352f5503d8bee7e27a44817e2726cc3cf5265ec687b1ce25ffeb13d" . + "95328de3b352f5503d8bee7e27a44817e2726cc3cf5265ec687b1ce25ffeb13d" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + "5f2533d85694bfb590ac95049b01877f89e6387b93f13005f5758b6fb0dff0d8" . + "9fd86ad595a0f0947be1999db45adaa489b9679c48c01efeda4c43aa24396cdd" . + . + "802656a716ac01e33bd707d4a6eeb9d8ac856101a95f2ea15482d19da438da0f" . + "5f2751219f3884ec29addeacddf7d6c8ad7baea7a86621b1f20368b373348177" . + "efa6988b498aaabcb1a4fda6431a15f5c4dc2de10925ec8c89fcaafd2f78b57e" . + "cd0e48ba309f49cf8fce4bb93d11c7044f65959863b85ba7c46dbd7556b1f59f" . + "b5fdf3da4666dc2c257ca2f2f50c747a47c56e3bb18746d6581c8c56ef9aa84e" . + "036aa1a6e861d59acd920572840766269e4d9036840ebc1fb92ced7b54795f05" . + "3b56ff8405f329c1057ae6a3adc29a86a4b82c271adf8ef21350dcf2a45dfc3d" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95ae4f4b76040aacbf462e611700fa80cc73361450a083c17f5e0abc378b48e3" . + "95ae4f4b76040aacbf462e611700fa80cc73361450a083c17f5e0abc378b48e3" . + "8032b5fccd8ac0a48e3c94e4c524700528747a824d4adb6534fc0b08432d7741" . + "1a90fe4d867ff43f90c1e400f39d729f49123e9ab03883f6d93ed9198064f4a9" . + "c0003e74bbeadf4d147e9a0d36d5a29b652e31ca125142fcf3fd5f1626d9fd66" . + . + "e3bdd62d13326e16b37433f7ad374b0cf004d7fcb823eee8dc5c657dd150ad13" . + "332ca53aefe5eb54afc6600b209bc058c3b59e9a71c4f90528b870255dc4f62a" . + "9acb7a8221d06974649aa19e29843fe208b51d2a7c3a2a305e489413864caeb6" . + "40b6b366ac2dd2bb53c2e0c3f8276e7728c764b328810cf22a320ddf79e915ec" . + "991e07229d4eba495c2f24874cc67fd52630f578b422c20da194cb43d3658536" . + "1fa6223074962e30fec98ba7a1f7957d0191f6a59bb8ceeba004a685f85148c6" . + "2411fac5153110f68cdcc7b58b8fe0f623c948e3a0aed4b5f144c7dbd48fb63c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "56ae408a1b8db7f521dc3aa0fa63d1951afe5e45ad779205a0092575e7b2353c" . + "56ae408a1b8db7f521dc3aa0fa63d1951afe5e45ad779205a0092575e7b2353c" . + "0052c3b71c0bdff56b0d5b68044ca1a17c82d3d7d95b2dc83a06f01485b53006" . + "736b4b7b05b6272d4f5bdb093db5db593982be2e2cfc3e266e03c3c09e92d08e" . + "c273549211149f6c67f0b346c005a918f6ff7bb2ae47a00827b56293218137e7" . + "6d46bf081ed10d14a5e0599bbf91292e7cf7343c080f0bfceeabf9cab9e036ce" . + "75232d9687a82f0f3c0060e8fe6946c89cdd7b6e4cb6ab668aee28b30f9c7cd7" . + "4c14fe8cd79ec859f736b2e1a872baa9465283c42f09eba1a056c46aa84b0054" . + "c909fe7cd76e4381e7916717a561654cc34e24f9279f23579c8051c8630495e4" . + "a68540a054e37bf2dc8291815ca617feb644d26875de5ee2a83709f52872a09b" . + "0f905964ae14711adc6aa4cb876b9a12fdf2f9052d2b1a858f6b7aba2684ea58" . + "5ecf9863415fd2fd00002fee5f0c1c798700843e16c9c9d22090d0da53f7fc4d" . + "c4c125c6ff44ce0b0a073ec7c6360e13346c3fb0b51775ccb3a8f7009bae2964" . + "350c29a9ac93278c6c3affc873856280f9f425850f6f24a56bcb4e4be16dd094" . + "a2cf2fbb0f84b67e0840537b4bad84f6deb1401b251e365d7ed7e605fd9fa458" . + "06b126b3ad35b488feb707c29157236b10071155d07841476ba3609442bbca6c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "6b0d1ae380652ca416a029bf96d540960b56c184d4ccce204ef76a496f8c75c2" . + "d6c3a68f3753b1e3ad5c9efb19b3e4a6f91513a89d50727879801fc34699bb31" . + "90d5e61ac22547b02b67328422bc034924fda02c253ce68ed7769a25cd77de51" . + "2639f9a602168076971d3c0686373bb8fcd68c1757de40b0193c047606c7f027" . + "895e34ae2269460965f5d394030dfa7f6a76f8a3fe69d38ba4b5a809ad66fedb" . + "241165e05163266e1fa60f23983aedf506a4ba2d8464460446ea69cc9999f446" . + "7210d3a5f007d9c20f87f2e908cc66754cc266b92e2c6699b342c9fd310c0e33" . + "f279f940468a6d36f3006c84d6072bcf7506eb5e5a131cd3c9b70062d7d8e92c" . + "a757c82ebe4b97aeb8751bcf9dfce185af16485400334cd6be055d260646eb10" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "34884f60864603a9e8933eb870efb3035b2fe32021f3c190a70b5f6970c11f8f" . + "94bb6e3236e18a22b0276b994e2fa125de5287e3fd0ffcc393c835ee23b73eef" . + "0c4a81e30afb8ff53cd237bba8704f62fc458d95529f8ded120c8849d123259a" . + "8032b5fccd8ac0a48e3c94e4c524700528747a824d4adb6534fc0b08432d7741" . + . + . + "67514b345c5ec37dfeb8111c2e570ee76e3147afddb4a27bbde7be52a2877fef" . + "6037ce87bafc1ce724e4aa0fe660bdea9e1a661d4d3fbb8c7cff5d17c2112039" . + "f0f7ead3700256b823e0b3bc7f9fff2e2d2bc8ea767a2125b0618b391a820113" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eb9e2c2882f64c9b3365cac1dc87dbcf77ea940a6f0ab333d6a158e037187977" . + "eb9e2c2882f64c9b3365cac1dc87dbcf77ea940a6f0ab333d6a158e037187977" . + "e251ec5cf1c2d6511715c2c134232edf2bdcec6353706d6560e883f1b07cffd6" . + "511a963e801f4bf9846fd2b1ed3ea585b1e5cd2bfe07e5a11a32a2b8a817b154" . + "7538c9f9ec8bbec9542b9f7c662ae547513ac4cc60b97978273a7aa3e7252264" . + "340409af89c7483bbd4396cc7077a604206bc814311491b3dd742171a6518cbe" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "509125fecf7b4934e455b3db3124cd6b3a9fbce4f93455d24d085f76e368d0b2" . + "28a1a9511ffd71219672688ae7cd2850f0ca0e47abd0ceead31c00070d8460a3" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "6570c7864702ff1885d7d7e3ac65d9ffa0b5e8f4fad1b0f1d219c7db32ea417e" . + "617c9d3170068a47a9a096c2b92c131f208f6a23973ea470e775ed2c61442062" . + "8656cfe3f168f253655cdae74e50ec7b537a927887cf77a5c49770bfe93b244e" . + "71962fad8ebfde4e9baed06defcd55a3037c8e33675e6cde02f821daf8916b0f" . + "8573c101f73384fb91f72eff4bb859c13c8a6f80ff95936a411b5df449584e01" . + "1e4ab1bdbe2d2a4a0f7987addb1a208faf7a1cdab740da034918053c7a22dbc7" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "017f5efc514e373756219230aa9af9e617d4f1950eefd1af29029dd60425b3b7" . + "017f5efc514e373756219230aa9af9e617d4f1950eefd1af29029dd60425b3b7" . + "4f8670edb66001d8d8c1897b9cf2c25c6c495aee8a3945da24d8be7fddc9800c" . + "128ff580d008fae92bf07205cc97703f18ea3fda98508bb94de5b51c36548d33" . + "b0125271f7daa134e7f764f073972a19a872a847e976f2ec53ca9f4fccade1aa" . + "a9013d2986440a9a8fdb86304028def79e6356e99b725e81f06445864396de25" . + "8403a70e1ef4487d9eb730fbf9f8747e9cd3df79d4367bfa6487fe9ec4d99390" . + "84ca0fe28516044e8a2aa832ffe6ce22f97d4fdcddbb34643d2c58f077c2d6b2" . + "5742f0cf5f6e5cc164f611809d9a1e9140f9ca18ac2d33f3a8e3c5748de45899" . + "8ec5c31bf17b712cd07a52a2d9685cf7cb5623717c242ac83b7d2187f38d403e" . + "5ecf9863415fd2fd00002fee5f0c1c798700843e16c9c9d22090d0da53f7fc4d" . + "834afa51093a628db119bf7f1c9fbc4e2f323abb1ebcd61d8cb46ccf891c0858" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "d237e810e4cbecfedfa506a4e57fee4d17ec383e337b71ff4dc0848358f94e54" . + "68f98ab294b72dc5cc0771a2eda9c92a367e8b526abff02ca96cf5bb4c27fd8a" . + "f279f940468a6d36f3006c84d6072bcf7506eb5e5a131cd3c9b70062d7d8e92c" . + "633f74df06f45313dcf448bf2de79c10b924781be0b3561d1e5daf60475467b1" . + "09ca5b36e8584b3436f24af967fcda9c42f64d1fe9799102237ab12c8d7c7306" . + "382776e8bdd9ad12d5487b5fd42c7bfe4bb6263ebeeb97efecdb97fe0cef12ba" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + . + . + . + "cba65cf6363bb695082efcd0e27872646a7259c9b343d08da21dcde41f34e4ea" . + "e2082f7221aff36ce8bbb0950d19f111d63b8af9eed70edb66220a447f83ec4f" . + "47e1a3a7c354cdcd393095d5d6cf4591ced58cca7ab0989334742c87258769cb" . + "e0fee771a2cdedd60c74e6709a73aba4fc0e9ac08239e86caec661eca0620709" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "5a35e423c4da0aecd9dc914f7a22e8a75a22d6ece98474f9505c57a7a926e23f" . + "57dc31cf9361092a0582c755f5e34db8df9ded875e3b2c8d9a90b81edbbabc97" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "668ddc608d896f5c20d4ce3b19fdaeadcb74cfb92b124564b3850da25dba30e5" . + "43423b914c49d5565eda223bf1cf86ed6cfce361fa98b184b6db86015f8321b3" . + "9a83e9e52cd76dd27ff2a932382b5461424ec292c9500e44daab4a4880df57b2" . + "fcdae535ab9f527dcad0dc72d27b635bb2c86a2c4686e3d262612785671d2de8" . + "a4ef352a53aae47370e2e68ac74d324bb4e16823618f2a7439952b5b2d12f4c9" . + "0a53b51cb2f5eec4379de33839e635d3e74070b4bdbeceed11359b6b6dbde294" . + "477c910bbd5a022da47e7997d3e89d3a1493a180a07ab4a65e5bb0d4cc97952c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd27cd206a25474123020889ce422f20802e4dadb8779e39f68a6e52ca2edb68" . + "cd27cd206a25474123020889ce422f20802e4dadb8779e39f68a6e52ca2edb68" . + "9ae7cb36e6f8f61c952bc4d8cd2f177689d25dd188b06eb7adb97848eca98f7d" . + "bc70487e39d7097c6fef39040610e7899d6212d0ec998608b31db5da34a425a5" . + "d17dcc96a96ee29bed54dd8cd24ec9f866f7b6cb643eb1105cdc3ea19a55d087" . + "1bcebaf5ddfec81406dcce476a84e49aba13f9630bb78639636fb80a94ef8d78" . + "dfbb1a27f35a70b478b49c634fa56d2c3ceea76e2625a83b856f1be8be22d530" . + "2871e9e82f7840dd37c4da2893f52e9d083ca69b2ed540ed441a10ca496346b6" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "15ea7bdf1f57f4fc341d8bbc08e01d6d251feff0ce8b56e29078b28147aaf0f4" . + "0d0477f674d9ada05d148b4fe11cb3717dce90e1b40b09e4fbc931579df2bb90" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "d9a14a4ef7055e78b99ec13affdd0bad34f57b5b34cd13d6f39a051b91fb0254" . + "4507b4483be8e1378d3b4c585c912fc038fa671c1c59fcf67975bba1280a6ccb" . + "b72fa1e4317c19aa4d17b7d983bb7ca574f4f750ec8a6818773d3cfdcac8f09b" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + "b71534f8ae65779c9bb23be2fc7281b3147c51b937d0b0bb66e81d38ab19527c" . + "840eec1cd6ab493f1de93abf8298ad055fe58e82f58274217aecb00cda124b5b" . + "b7cd5a0b5f47f5a11bda8187bd0572a59549ccfee0f3e1547225df561b0bd665" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "98c5100b657e4f02ca3e579ec5172982ebf626bba9e86143847a653dc70d13cd" . + "98c5100b657e4f02ca3e579ec5172982ebf626bba9e86143847a653dc70d13cd" . + "ef40119e6778e4cb7f47c4100ae053300d2cbe3bdd9164a7cf83931dacfcbf43" . + "cdb7805da324acd44206a2c6a01514a5292ecc5be529d260fea5cc52ebb557a0" . + "5d6397dd09852843255271339f0621fae8d857fd981d1f47000fb6926c8b5637" . + "96dac877f6d57c75b466c2cf7ddbf28d8c87fb2ba4d835eb7a715e0da07980e1" . + "cef8034a54853a1d2415c2cfcda1bce455e7a513bf03312714bfb81a385a0a8c" . + "072509cce16a3967374a698c47657d277ea3c160d9ecd8462a18a59646b94b45" . + "c769420fb666460b8c92c0c55e922be3877b2d99990fa38694d6de1a68c68b04" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "72394ba6ad82e0ef111ca8dfa769914d22bf3e9f0a406f8fcc079a6f7ffbf903" . + "f0f46ae54438f120623e11cbca1972e85c572d47516469cbcd17ac41e628de65" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "390ee0f8761aad2b1c6fe12e75b4c4ffbb0518cae3050cc9b3c40e655fc95232" . + "5cdb5dba2843c786c3bf409e01a0d842553156d44cf59eda03aa3259a9123b7b" . + "15a4003571ceb1499f1f061fe469448e21335f7d52453de475228f6c1b7806f9" . + "842db27669dbcf5a21cd6f1ce9724549d622fc0d0f05eabbbb3e1fd44f5d5a42" . + . + "af5b97321cc77cebf96ae4a2b3c27fec806c9ca33acb6663099476715d487d5b" . + "7154149e492b6c9b63b219690ac4d5861a28b816cac9780dda88a29cc9b504b9" . + "01862916a7378c7171be10e8e42a2c8fe83d2e8343306cf70b3ac95a72d2752b" . + "f692fcc3b23347903956c49d319f513b8b58b3707a326b8c1154d90e38bad7aa" . + "af5b97321cc77cebf96ae4a2b3c27fec806c9ca33acb6663099476715d487d5b" . + "c029fd2ae85b3b5396b666db4e3e876629791d7bfec0056641ce32f119efca56" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "86ad55963923bd46981031d7a65517f1bee8d665e563aa5ce5a0b3e8864e9902" . + "86ad55963923bd46981031d7a65517f1bee8d665e563aa5ce5a0b3e8864e9902" . + "18b44c0880e1a13f3cb64338230d3f341d25746f1b9da312f3ede62c04ec316b" . + "604dc2fe0bbae84b4c074e502f87bca562c4ef5958036a4131fd7679dc45a0ea" . + "f770fc5b44da63a26df2db4f8d162296b8acbda5b2a6ef47f67b08ffbed6f0b5" . + "286fe61c9f49e9f344bed50c48f0c3931b0c308d7f1487135de64f2e4f8dbeb8" . + "c10a9a9a97bdab8fb4d9343b10cbd39c8249ce80fba488aea081413192abae80" . + "bd1bb2c6e6632d5d76372d07e87f1b01edcc1cde2d352a892933aafa78c0d566" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "12b797f407a74294a0761a4854f1ef753720fe5490519ebb36aa81e7de6be4d8" . + "e12ae7f542307e62c69936426f924542819cda515f05622cdafa8b5af1110b28" . + "63b0206e611311ec1edbd7fc5236052e2003b8e88283717dffb4df45addf0432" . + "7be2757a0c2f1ebad924d7fab2365210d2133396d0c48986bf81a3ca9a72ce56" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "bcf190460052bd2d4f2a683bdc66022c7adb537fd084aabecef285c610e97989" . + "a5c5e0a8ba6e89676a4d2a934a20a757f414dc7a576a2fc02eff617e7541dd94" . + "5112851fc48a83b301f7d5ed0b2e40e140ac3de6e4908a1396c66962f59ba6cd" . + "0273cb401b03db8a5d0fd55e51ecbc862a374163ceceba93c624a9e222bb903e" . + . + "bcf190460052bd2d4f2a683bdc66022c7adb537fd084aabecef285c610e97989" . + "cc6b9d8c52a686c53d85384ed4bbccb46a1b99a11c58f84c948d867f3790dee3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5f2de97203c70dbbc4375001a7e24d653533ece4ee66a40c38632b3af3d5e0f0" . + "5f2de97203c70dbbc4375001a7e24d653533ece4ee66a40c38632b3af3d5e0f0" . + "246fed3d387a0939b3b1acfdaa7dfa07aaf4e3f68937fb170b954d1fe601e4e4" . + "b86c2a21d60ba102a6bb6c649542ca866d616472d0c2ded95ca5765f2dff0386" . + "9db63cfa02f301e9793d9487746e9f3eb1af750b81a3cc0d747aab9304ebfefa" . + "d19686372f7496ae6fa31640b07419938676814fd0d92e4205c4fafec2b41e8e" . + "badffe1199739d6aa76d8ec03b392134557d168e376ddcb58b18761d120b2f5a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "b63fcfd4f577306e113647a36d4ae3b42783e8e2cfdbf822a771d4ce1a77451e" . + "d73046062d383ddeddbeac1f5b64966a7b67d9c221654c9c6cbff5e73ccbbe18" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + . + . + . + . + . + . + . + . + . + . + . + "0f75ea53ec36f08191c3712b0d6ae0f659fbcb8793fea0d12dbc495d00a0e906" . + "34b4b9c967f6f41dbd7a8a4ebf7ee8d791a02c6302dccdedf7d4e48117e998bc" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "5e6d9d27d667289aa5a3ee4a40ff8b893d931f734209d0d92d2cadbbc9087ca8" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "4b26a27ef8d1b63e6e74a3f98d0050fecba24d79df7db3b4ae07d11605fdbb0a" . + "72c35aa9df7c165f89737bacda6c3b6a24d074a8d60d3a0351a556310bfb9a59" . + "42ad7f7f7f03bc9e895796576de8d65b0ddc6388dcb001af6c35c5068e2c326d" . + "82df32e143152c3b0c0e9a9b837996ff37ee87873e6d7fbaa544f5beb6bd6dd3" . + . + "a06a8c9adc84a861f54a04f60359b75336a98793341db5d3dde98b1f452afad4" . + "aae5d1dfb837d9fa42288b7708eeec781a9b055660c803354448342f15306464" . + "b2ddc18002cf5ce2f85c66eb6b498c3be36b06e8cae6c152e81464362b8bd3fd" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5f38e0611be0a07b517dd143f9484263d3d9a869fa839f30991165e2ba292677" . + "5f38e0611be0a07b517dd143f9484263d3d9a869fa839f30991165e2ba292677" . + "a3556567e35c50c0777a97149b98a524ce5eaf9aaa7eb65a0cefc2869cdeed9a" . + "474f422a4d8d07819c4ce61fc3e3e244bdc60274ee0d4435bcfd311ccc4ee761" . + "2ab26c929b277e829ff8acf08004093b5d11d25e35d6b138a44373569a5318c4" . + "644ab875263f893551e186a665f1b8144aa997cb364db772f07b5ca9b684a3b1" . + "26951f3eb70e0b7d21479dbf544d67f34db08fb17512f699e3f7f8c35c455c47" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "6b194d715f8647b9767ff140561acb68706f81aea41673f3f8cc0804e1e775a0" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + . + . + "6912f281db2dc1a5d13975468996f0486d3a41b3a9b4975c8c5f5b13f0222ffe" . + "d118597330e0c1b444aa158d109599ddb7799404bc77ac5e2564b335a8170382" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "00af5346abb3e951d5ed2d11f10554fd50e295aad5cb76535ac11b26a00f2567" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "e924c6ebdaa148b8428d5742b21d3f4893cb5fb56869eacbb520344f0fbf44e7" . + "3d84eaafea0ac7146c61b23e1b5e5e8073d0106be0afd0a3cd80822aa018c35b" . + "55b04b6eeb150638c6bd47c262906df873409831c98649e7baa19515cfd84a41" . + "1e644f511cae1c98062c1b8528454ff1c73da61d263636e622361a8f69717a3b" . + . + . + "e924c6ebdaa148b8428d5742b21d3f4893cb5fb56869eacbb520344f0fbf44e7" . + "8cb57276a229a75222325cfb5ac10c5074c80c76777fb5cc081a492e656eea26" . + "4286425c8ec52c4c5869c98e8b7ee5904ed68ae1ad21127dc4b20c10251ac6d4" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b4a78cdeb3533219503a5cf6b920cbebe794c4286251362a1fb4709f317ad085" . + "b4a78cdeb3533219503a5cf6b920cbebe794c4286251362a1fb4709f317ad085" . + "86bb08f842bcbc31b7b8ccb80f3178cf59dfef90dfa1127873c264ed9909eef6" . + "e5f7497bc63549dbd3ea17a90f6e5d6f90ec22426a48a74448331d9cf8655e35" . + "d0a0f01dad1daea09436fa58557da3531239a073d3f651366f2dfe45e99ef2bc" . + "36af45f047c25696e0e4704c1cc005c7305cfc19d253683107a0741f6fb855e7" . + "8a75196639fd1e19c49996aaf437cb1d85c47093b4f9ee89ba478dac1b2823a6" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "cb97229fb1cca2460a76c527f7ffc33100b2c9a91f00cd8d4640be5b6e67b724" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "d6005f849d736f79b837dcf02484166fd4c6c81965f76fa3e1525771eb9155d9" . + "f1c8ea0555b0eb7224a8bc7a0ae3b4944817a2ff5324f6f3d2c59623819a56e8" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + . + "f53c889315cd90aff52ee4f86e6e720983641978e954b4c14b00b760bb2b66e5" . + "d0c70abca7783720b6be2f33867e530075334c08043ffec2461dd824c5b9f611" . + "168a0a0d4515e231fb8220a4c9d25876d1c56045572f7a444db736c49338f1dc" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "25809c124afeb4d712734e330c21bdc5ed708818754ed1f98ce3165a2a573537" . + "25809c124afeb4d712734e330c21bdc5ed708818754ed1f98ce3165a2a573537" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "95264ef7a3d65762deb4ed05bed5dfe542c66221ae1420af0395516cf23ddbf2" . + "9c7379c1a2a14fe8530cc06cecc484a21f3f195309907f1a53ee991fbdbb76ab" . + . + "8e0931313e6367eac5ada2d88ef65c4663af104b4687bdba18c3ebb61cdb454f" . + "9d835071e76da8627b631e99d91a0ae1ebfcff1f6d08fa40199e7c4a9f54dc94" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + . + "ae6dc2644165f314503c4a301bedc84718c59964a2a45aadb1f170ab76558cd3" . + "652db34b7c6eb3515475e8b6b1926dc5e36ff5461885f153c125648b747069c9" . + "ed2bd9b1678000cf7ef036e78de86b078988dd6cd8ef0766eb44085465eca3a1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "532f630d07fbe11b2b6f6a7268f941ebf5aad828f001ed923f3b23d78cf8197a" . + "532f630d07fbe11b2b6f6a7268f941ebf5aad828f001ed923f3b23d78cf8197a" . + "95bd6339157e328fad8829d49c4771cbb3d60588ebf0dbf84c015f794933dea9" . + "3eb986c42639f8e4733dc4605220a904b7ab38f5300f2bd2e22993b8b60a8611" . + "015380fc9afd293ad1b9813c1cf94a5f679f5a742ac9003cb10d09219159915e" . + . + "1b970bf1a54af0d1d2ec5c1217e3593be5d5b7adbadabbcadeab347ba6210e52" . + "7f5025c214228be92b6ffb1e7bd48b4fb61ebeaa2f22bf2f5786ccddf1ac654d" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + . + "2c54bc3dbbf289c749d674faf2814aff71c32c24522a21f1bf3cb310b2012791" . + "e5da0c62f751a676a990b3b128077d6db058d99e948fb51ef134aeda612de711" . + "0d04d8892fb0969c4c3fab53c26b8201e4f0455e21686ddc72b5b62a2839f5d2" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc49cfd8c1a607b068044ee1135c865e54dc269f6e58bc607de9778cf8423357" . + "fc49cfd8c1a607b068044ee1135c865e54dc269f6e58bc607de9778cf8423357" . + "c46b555d687865f8cdaf3200bbeb3cecd352d625961a21737dc6f52bd9e96949" . + "4b15b49caefdd498bfe8cd602e1b859266c83b58a3356c079b7de100cc60efc5" . + "16d43ada12857d1eb32e178a29ff5a0467b7aa5b4151ae1ce8bf194fa211c28f" . + . + "13db67a3d570fd837544953613256ece997810f4c9e16c1153bae9fe4ee133c1" . + "bd86171238ba34629af5fa59bd9edd982700dad4a416f81454f87562f20e3c20" . + "3128d54f27d000b6d8e00894342704529972e959f6b97514b3fa8b3977d81195" . + "43154ad934203307e5a028d6d14dcd7fb484010b4583eb9c1a61e66dc3513a7e" . + "fef3e324ec01d081afabfb56ad7d5531209330d54d2d67ed19a623251708bcf0" . + "81364fa5554ee107ee9347fd07f9b0c872e424e8dd6ce98d2d947cee7ca308ff" . + "01417384962f1cf16bb1c5adeb8b58362e04d446c3750f32107e5cacdd0de56d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c9c04bf18c44abb66c2d0fe4d635bec63eea5250b633ddc3b2f3a77fe8335883" . + "c9c04bf18c44abb66c2d0fe4d635bec63eea5250b633ddc3b2f3a77fe8335883" . + "4980384057e7e579d8d5fbee2ec9127edb1bd390b0867d0fe34a64fdeaef7e40" . + "ad1359dfc36ade5394dbeb9224f46e3fd67175c9c8687807e10486076618cdce" . + "d7537c79a1ca3a9fe2cdb06198ab3b4c7f3973c1ffe121613965dc324ceb2b23" . + . + "73dfa9b5e5fab354d4d21d9ef635ee634c23fafd52ba57cea64724988f8ad2bb" . + "d284612e60c1a9a14e925877d36e0080e563aa9b2e635e3112f0ed3338bc7000" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + . + "7d8c6e2d371c917a263edec261428f5418d89a5840df145814deca9e24fb55ef" . + "6b1de177c98e7a7d46b94a2b206352310af133b905d92312a1159f8b146b3a8d" . + "7b29930a983c69bd3f457f966addc473888f6ed96ad871b6e19e748db099931d" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "4054fcfb81092c4a7a9e5ad9a92d040137da1e29296cf7ee14300eb0f069f931" . + "4054fcfb81092c4a7a9e5ad9a92d040137da1e29296cf7ee14300eb0f069f931" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "de7e69c286281dd92c2928e902c14444957ff57ca224f0c57a4fa19cb7172f14" . + "42f1499935cb1a5366f50a140dcd42871bb9e7010c596c0da94a02d71e776beb" . + . + . + "bd59af04b1e6f1892f4407abe99ac878643c67f24e528257d1f4712c3f5b33af" . + "d6d797b55e0488fa1e7885cb89eaebdd7b9fa70ae5a818829ca832aa5909c00e" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "b117b6554d55be307204e08e293fb2eb7d70d1f897709bf92a1843f0c5aaf63a" . + "519cc5aa3f0fd22a32174dbe3fa432922430aba486854dd5f022fa0bae623d9d" . + "18a0ba6d8909af03ddcef8c3e32086ac27202eaa19ec7e57bee63a775a0762d4" . + "5cc8f8e0b458fa8fad4370162bd5078dbd8d8b65dd082ee3a6233c3de451df63" . + . + "72c0a070a1a3941d03403d8d2c7a5b5fb3a219c0d3460f46e2e36a16d95ea5e0" . + "740906a36f4ded9d959c705d9dc3357fe92da1ac0c03bd676170c43bc32fa993" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "597c9e853174dee23f634d82c3ca592a7c747a1e5f5482f0994e8faf574eb86d" . + "597c9e853174dee23f634d82c3ca592a7c747a1e5f5482f0994e8faf574eb86d" . + "c23a9f095498d9138c496709a860b6e859c58919d275d584bc1f5f528ba89360" . + "f975f3b06d7517d7b87076cacd653ee99927be3627e55a794c1b0f07a0f77683" . + "c0a156cf8bb7822a45ad5ec04823c748e265ea9832155094fd53b74b7ff44ea9" . + . + "6cecb0f847e7ea92297ffad9c09c179761700850ff031c4951a20c7060d04f9c" . + "f107bdd75773ceff4a0b619b5ead2b7a36bb1c47c478e8cbd3304c298ff83e18" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + . + "360f25115f2922dd4350a06bb31d4196dcbe3f61492aa7750c9e119cf2f79dfe" . + "c70aeff8993f99f703c2c6c96d616b5c42345c2c8fe567fbda8d4afeee26266f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bbcc6750f07af826d09af75ec03ba1e8acf195214f1e680d4acf622ca34858af" . + "bbcc6750f07af826d09af75ec03ba1e8acf195214f1e680d4acf622ca34858af" . + "20fe5012bb3730d4fcece058bf9723efbc6c6146bbf4caaadb3273bd1b130109" . + "98ff6c68511a745062844274b64744ffbc407eec814924bdd1a0d2f822b88ae3" . + "1e002950cd41cbe5f40df6392e238149707248f75aaac296236afc01bb472446" . + . + "3cc7c3d8355d4d8f6e370f23fcea9433ceee2dfa8596f926997235be59064864" . + "cc2c8f5e53562600dabb14a8065853421c2b80f978f7d5752cb65e47fc897fe4" . + "d09da99720018a4ac5727fa9cd1c6e12bcb34cb21b111fc5a4f54bd45de56904" . + "e48dd3837804309a11a776ddc2be9475c60f4576cbf8528c1000de8cc4608de6" . + . + . + "937df9c51964db4ac468183794eff029aa371b67c4d66485d3d583debb960790" . + "d9e454dedb83d9ac4c9a2a6fac9b93842f020b7dc38453c576028ac93c7a448c" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8cedbcafdec0f1ecdbedaeaf7c3849ad2fd88baf6e1e340c26379922b1fb8aeb" . + "8cedbcafdec0f1ecdbedaeaf7c3849ad2fd88baf6e1e340c26379922b1fb8aeb" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "5874c78a294d59bf2318f80ce2370357398dfe6f6ab7d9628b1f032a2b5550b5" . + "7f1cbd62fa5c42f6873c907f6f572b28ad08588a48bd16d3cbb898894967dcd9" . + "c140214da52749d6e758baf9b90fe5305872b97c0a130e05c7ef3156201fff5e" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + . + . + . + . + "a4727130acb8509c8e12b8c27adf8fee6fdaade2a952114617634ff01e54bd6d" . + "d3a89691aee42b447e05fefc813754a4e1acd83517f7a394fdb7a2aeaade562a" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "2fc0b5893c709ee341704b539cf93b292ff5752cc00f81e92cf2dcbf6afdc109" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "f8778d701bfca8882954cca964fd30fdcf9b3be7aab93708b7bc134329ec1f08" . + "9a482978843e3a0939e534be95a14d8651b1c050b92af24c05b0ecd2d874a1e2" . + "4a673e34f4b60e20305dd081358a3b85b106e465201a44c2bd82a5dcbbdf1434" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + . + "f8778d701bfca8882954cca964fd30fdcf9b3be7aab93708b7bc134329ec1f08" . + "2ee8be2ff9b902584f8a5f8f6b21e7e797071eab406a61b5fd7c81c56f898406" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0d7f3fbb3428b15f930898e9d4c34c642ad8a8393ac70f11cd0e2f37db0b186e" . + "0d7f3fbb3428b15f930898e9d4c34c642ad8a8393ac70f11cd0e2f37db0b186e" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + "e5f3a2bfad3642e8c9fdbcce1208e8a636588cfcb5bfba702c826a61f23073e5" . + "0c2d40b2cdfc1c4d2f40f56b757ea843df65efbf92049f17e3792873145d649e" . + . + "d77885f55e834f2928d9aaf7d22f4dc634728156b50108323b0f8136c854d6fc" . + "f28b42cbadbd632ecb9c384c4f0e3cbdba232cffb8637d44e3ae9281470cfde7" . + "fff12018ff27288307388d09332812e68db5acb716adb043d7a46b10546aca2a" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + . + "1a3e8057906cc2b9c244a177005d44aa871e77938954eb036fc48a2e822cf4c1" . + "d99600cbb9ee4567e01ca4f4b57693c2dd4e8f8fbdf63f743d93fe52c076e6d2" . + "965e753a8d47f7b02e63b95a0cf80a0a98f0adf9846e9f004a0220ff700baaee" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a08558dcff986b70b165dc39430a491d2b1ceef13841c940dc0f470281531282" . + "a08558dcff986b70b165dc39430a491d2b1ceef13841c940dc0f470281531282" . + "36de581302ad9771c27e689c8a2660b657138cee873fcbee2d96a31c3966f1bc" . + "18dc11250515ada306541705cfd4e5e8eba027238ae6d2340d5fdcabfd330d28" . + "094c23cd20a0ccaf41647737c23e4e304914bc89dfe7d48cb9d7cdbdd4a429a4" . + . + "bf9f3fa80e0c8e23b9e6a8a0c04192d661830dd45986132dd0198441629a6dce" . + "cf003c712f2996bac60f7a7cb4bc4f99eb8532a9a0cdf2165266c0423faf0487" . + "be7b8d14902454037c0ff3738f9ba4ed4c1eb0013ab2fd4cd6805f33268dffbb" . + "c79954f907d30b00369b5fe1c5c6552450d7a8a548afcc46ef073585f558f5ba" . + . + . + . + . + "4fbf875dc8e9ccb369397ca1e806373463094a7e0f165543ac7dff7098250981" . + "37473520180389ecf1766c64639b31a46701ac3acae391a675d48bc11f922b6f" . + "542fae80622159f5d5acb66cb2977a5fdc53ceb3a1a9c239e2a85a11d6dff6b9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c63b8835ec1990680968dd765dabf9789abcd6083f86025e9558ddeedddf6037" . + "5edf201bf495c4e46cf540d3faac1d5667de34a6ede9dd9c34f1bc136c568490" . + "bf47e757f424094ef7eb5e6a03fbe32f9167252f30f8c10cc57cddb10283ef21" . + "21d063b0a8c6bc09e0e9585c4e0ed6f5d1b7d4ac9396f4befb9779f4614d1bf1" . + "d36a6ce0219ce380f1426f82188ddf6853e0b746cbc182bd4eb6faae5dc7eb46" . + . + "7d67fc90ddbe6455f6797a9088a4e7de79eb1eecd403aab688c930cb9570331d" . + "80f4f880eceb5b1b6fc5e28a7302f7e349cbcec39ad1f3888136b16f097087d4" . + "887f05e038aa0e20f936cafee4f451e67e1bc943fdeae76eb3b41199b0b87970" . + "bfca2b2b8b42eb9031b60919882fa1c35c798364c234038519c31386be20e396" . + . + "81a80a4b81292283bddfc892fccd6376d17b798c9393d5f2ab62474b70bbdc3c" . + "cec281dee75c268a1ca914c6d8e8bad6402cbf4873bc5e1369fed1c2acb2e22c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5277b04107b5527267251ea440dc692d6c886db848d7fa28db5d89056af5b85b" . + "5277b04107b5527267251ea440dc692d6c886db848d7fa28db5d89056af5b85b" . + "86beaa845ae5f9a384784fe173e8f962543cf3ae2788a3312c29b9de41c42e88" . + "e523b3e959f0005e2b600cd16ddfb534d9115f3b211d413b248aae190349cade" . + "db86c11ad934d345d2e8a3ce7eee73fda168b51c5a1dcbeeb1e2e5fc5728ccc6" . + . + "45d5b1c1637466886db41fdf864d627cd1c4ee5df1577fa96510d1c3cf5ee62b" . + "84041c456686de4f9dfcc10caf9368c3ec8eadbcfaf7c5b2a3dfaee4536d2a77" . + "86c999b1cea373ff9e45c9712b1062708e26efdfb190bee8e9d80dc507c61c64" . + "b72fa1e4317c19aa4d17b7d983bb7ca574f4f750ec8a6818773d3cfdcac8f09b" . + . + "0a6dc5a4a61f18eee741589406d0b02d2be7531f79b2cb4ce68e04cc5fb07984" . + "c527bc6e6e06b78443b8c4b1c636cd13dad3f327fb41f1c25a9878038e6446e4" . + "d3dd7ae7244a2021c8d566deb15256359c508a6330d5eb0b6f7e54af1fb65c75" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "795c09e5616a24646bd520ae7d07d71b762423c3a253e0500e46548d25abbfae" . + "795c09e5616a24646bd520ae7d07d71b762423c3a253e0500e46548d25abbfae" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + "e6677c8c031026467aebc12a1246d6f794c9abf7905e5762ab377c73334f6676" . + "72a0014e239e550ea6dbabed55b3037a4f78e708150bb11f0619a000a659a04d" . + . + "0e47438c148e2208f7c5d81919222da05b72ddde779d5ec1ba154b9290b44f92" . + "9c2ebb26b0b5a8b7404cb7a08ceb0dfac0a09b9ed079c6972bc5572b3fc0882e" . + "c52e6f513b13f965cc8cfdb921e1024708147ed2461bc35754619d4d883ba5fc" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + . + "d6d996e41aea1f30bf48b22ff26c01a3ef9d0a8086a7bd91ba9859469cf1f8c7" . + "b8555207006c1bfc20a88f322eb4b0b051afa76338be128973093f5f27ad55a0" . + "2288789e9c0e1f07c7c178552253faf7c18bece3ac0e5b8ff87114b3e181a031" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "67eb71c99382825cc3f0b461538c2874c76a8fea310f4313f73217dd2f717595" . + "67eb71c99382825cc3f0b461538c2874c76a8fea310f4313f73217dd2f717595" . + "cb8d7cccee6f39cd143d753537536ffb3a0bb40247026f77dabcf6dac1d9d536" . + "51432ff6e5e9b9db5c0b387be3a5ca57dac18ffa42f55de3ded5787006e6ad8e" . + "4d66e347ab46a46d123d1af1bd6bbd81d3552d61811b286fd6341f5e7f76363e" . + . + "d8ef68ee511a5b25af0e57fcfc1447e9fae06b76db5ce26542b2915e61ac705a" . + "4c68d6ca662248b39bdb03233f4c75119c030a335c39f5b98f13bb8ca0666250" . + "b956b1aca9ee9e30265dd3598e9146da1d72bbfc1864c4850a6577da89882e58" . + "ea388de3ef832b4e55efa33634dc963f0b54bf1f4eb20da73107a309ef1abe9f" . + . + . + . + "e9ecf446289704b981f7507cd694045bdc8c6bd1847d62615eb8fb52b0afdb54" . + "92e3fa20a59fdd7e145a21eb027b1b8c3f2336196665c799e952dc93ff88862e" . + "f53ff315fc8570e57487dbd1ee27e191c3279c14104ee798230753f3243f472c" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b425a649b03cbe1bf97bbab1b1b6780423610526cfb5e816795a5b3783babde" . + "6bb2c4d2b7279a0c5c566ba9d2e395910d5e0d05027022235e34b6c951753b69" . + "3841054272a701d8d1525567bef4da95baa8aaf53aee5e249aacc70e485535f3" . + "694458a71a3ff762a3e3b47023142160df6f65ac2237b21a2b85730a963b1c81" . + "3fc8a66eac8202cf7fa6be620f8f3f3fa9d17e99f0b7b5c703f89c1421521209" . + . + "c885eb93f4273d022e836d3f9f5e4a99136c3286092d3199cc1418c8c88171f4" . + "61c832e55a27620d6c12480c19d72249510a512dc7abe893b9cc4cc624d81d15" . + "692c7c8c2f495abbdb651bece0c1ee4eff43cb045d6c48508f4e0fec64ea1290" . + "1d1c339be92eb97d9cdb7dccdc651d2a8532b9b5ef40b714b8eb1422cae5a2b7" . + . + "c885eb93f4273d022e836d3f9f5e4a99136c3286092d3199cc1418c8c88171f4" . + "a70447337bd65ede600de0348f6d3e4298289080b34207e3248d8f19fc350f84" . + "00cfaee5f61ae09b8bcea2b369c4fea4fb62a479e7cb3c04d15fbd8ccb746ba0" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f8f92903ac00a7cb00fccc6f32f20ef8564d3e08e3ed06f50f354a101650c87f" . + "f8f92903ac00a7cb00fccc6f32f20ef8564d3e08e3ed06f50f354a101650c87f" . + "96729fabfa9be0faa2beb558cf881559cad2ca1915c4da87b33dfb76c056a4ff" . + "f0312857adc1eb4ad6b471d22598ac858fed55e319b2c0344226a4763d672147" . + "fd64037e49f5f79ccae88bc77996f834e51d6c4c85a5f85fc097e18ae4bb84d2" . + . + "9d3d4a1ff8d106805b125008e0a81c7476510cca517901a1fd4dba79bf64d091" . + "2045ed05afc661886d3be4ba08489c4b98022efec1d54aa4f3848138d57b5dc0" . + "259ce079d0ceac95c4994e1cb858c4859f60fb08ef27f2b699120642643774f8" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + . + "ff641e1b0e77b97ba69bd7ab988862b477c39ce95382cf38c30e82e7e7d23828" . + "927a56e347dd4a10b505490f4c219c01f68fd29eaf797e21e4576b17a0fc00ee" . + "ce4d2a853fc9d03acec82ff69ff5f69b6d850b3420746f3a2c90363295076e3e" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "eff5ddf8c0f26619fa95b6f91edd4cd571a1d9e869ce8ed7334c4bc2a4a9d56a" . + "eff5ddf8c0f26619fa95b6f91edd4cd571a1d9e869ce8ed7334c4bc2a4a9d56a" . + "16bcc4d5b7608fbdbc47b4cb9612681413ed0bbbf2730c4fb6c04a42adc6d3c8" . + "b35389ec00cbf25aa6f2e8cfe5b1d9b8326e3880860a8afff7ef4cc450d50897" . + "6cfbf8ba7f94093eeadc7e361b3053deb6c1d0cdff8ab57485b71f60f4c4279f" . + . + "101c6c07edbf58076820bc2ca0ed75117f323d7b34f32c6f8238214fe6898695" . + "2707c43e2b377445ad79bb14ccfaa07c40248481941586bbcb035123bac9c12d" . + "3f8a3413035fea3b9befe5aa12fcb11712abce9ea4288987da6f7da10eb5218f" . + "c4ae901be81f56233adbe358df78df6fd24150b57651c6cb8ba1bef38acf2b34" . + . + "f6b8033d5b6d83ae797694bfc80f1e07d987d22c8d2b72ea07a68f5076e8903c" . + "8346d2d32af4a0c4df6fa2cf006aa0c5cb29096aac8ce867951559b5aa70c110" . + "03d991442d36c8970dd4fc3e26a9eb8fa07ebcaa8909be7944c61e53694a6235" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b2428ad3b1379d20ff9a9db9146665b45477e4ff650aec04e535480de85542db" . + "b2428ad3b1379d20ff9a9db9146665b45477e4ff650aec04e535480de85542db" . + "7726a94abe2119131b6e4d10243f75eb047a37033ae9db2b73d2d5cd67b941b2" . + "43764d5dc226c5e816db54c8b95c6c4ca56449a1f50ae375e535e64820284298" . + "853b7df074d90b52b79be2dc664c6f6023dcd9e9708fd962eaee6443699878ff" . + . + "0f3f353628cecf60f713486d6964f36379e1779cb15d6842c40143177b4bd137" . + "2e266258988adda04134b1dda207ea5d7a91fb971dfe6e6f83af8024d65e22d8" . + "f640b3a7da52de9f89778eb6162b478b8ead5794b33dc10fbd208b25648c47de" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + . + . + . + "b11007ea37eedb1c590c81c4c1958c59e80a3b00280e7162f159b40a83c944c4" . + "84d5d0484262456a57a23470d2adf10a63dd2b2a76f483a55d00caf9c79cb8cd" . + "47ffe97c9e345a52abb453e524c91eeef3cea3407d85f7ae6dc6cf847e1910e8" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1c212bd9274794adfdb3ea125c6b766971a13822b51e914616d9ae0d109478a3" . + "1c212bd9274794adfdb3ea125c6b766971a13822b51e914616d9ae0d109478a3" . + "f28f3d0b3c0c546a268e3e8dc487c5a45d23457e4ebf1b67e654779e91c9aa22" . + "fdb0d28ebd6d133aad9a23972bc44a58fe3e865b431c49e607618c4e2e6ce3b3" . + "749de470a44fc8e502afd38f476e69ce8750f0f8d9d309eba6467b1128a531b3" . + . + "27d0f35be725a3df1e6891ccef2df311d04090fa85749ff44fbbc166f26442a9" . + "285b5bcfd14b4fc9a12ff36b7f77d4931735c4f925e517648a288fae5dba74fa" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "8eeabf6dca13412bab051f2bdc465197809e9917f0a85fe3da039c15e9536ff3" . + "9246212beddfd3e49d5e32ffa29986f4a974204209ec554ace27e9f07cdb7117" . + "9427cee458bd73ef7f249c93154de78375d1bf73080c968f7eeb2619fe75db7e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9465c5e7332dd3157361f896298ae5ace157a4c17e19de2390fd8f557598f356" . + "9465c5e7332dd3157361f896298ae5ace157a4c17e19de2390fd8f557598f356" . + "cc692020dc3aed3e0eca7eff15f870a0dd309de3722f8de8ac88bb704f2fa254" . + "40c88061c83d4f3f1053f34d82d034876d7562350188f3a6e2951c2def68b261" . + "6d5ac82edf84d72edc0e78ae01a79dc0a9ede7c5183ffcceab13c40c74a02145" . + . + "1ab83762418e2c30100ac1a5882abbd54eff30be0e293183befecc96ccd86073" . + "6c7887802de317c52f7f989a42908bc0801505eca23f27772df3f3ac7688295c" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "1ab83762418e2c30100ac1a5882abbd54eff30be0e293183befecc96ccd86073" . + "92b2ddb65289203c28094a3309da23a0a139b7aa4082eb7450720ca810c1a3c0" . + "0d7d676526f8d9617a899cdd997c9db39eaabd6533b762ed9a6ccbdb037c28a3" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "29c1358fdd6b7ac7d96417dd072c1ef079f6194cd2dff5d7b050b77ebba7c6b8" . + "29c1358fdd6b7ac7d96417dd072c1ef079f6194cd2dff5d7b050b77ebba7c6b8" . + "8d94e432f49b80754cb173fabce2ed56e876c399c31d81d4541b532bd798a48c" . + "dede30b3a0348cfc0ba981ce34f7b6051f677a42a6cc4b91123b4273853e8730" . + "70b410a59e31572c00185f5a8afab7c9495240c85e0fb88ad7a2ae2916e0686d" . + . + "10e7f4d2e77552b554ca8fdc165f1b8a9b2699bc972377f904722c35e18e9791" . + "0921c137735cb6be14b77a9cb5b506f76dda69bcd7cd0af7080483a77817955b" . + "59f559f1319c35c38c6c6ba11033eb95f69f184f904722d234834b40a4e95bc2" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + . + "c66947a2aa18d53d353e4bbb92091a344c8e35e6b604abfa2fceadb8cff8c749" . + "20684ef7ccbf21b700238a2d8331a8be1a295c9962ac0a17c29a102a307140fb" . + "444de2e14b60d6d2dc4ba1d1b91ae7d5cbd87d6cdb203ce5c09615d607211190" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d5c30d2ee5b84f180d291c76c7451110646fad81229cfc3717120ccc2c3a0996" . + "d5c30d2ee5b84f180d291c76c7451110646fad81229cfc3717120ccc2c3a0996" . + "70613f3c99eb7fe0e788f075c640f321bc1446a8d18f6d320f0101e4e45aff2a" . + "cb38ce18dd2adb3cc413c0a286b07b6e4fdcdc0f745d9af64550d8cde7bddab0" . + "5c9a2cb1db1d20a03368f956945ebc5b9550038413aaf3a5a11dc29c94119fa5" . + . + "25b27b0728feac50e7c66e11b37b35608528c53331d1ae4adbad3c4e7e1df597" . + "d49381294ea7f247b0017a56e6d2e5f23ee2a5347858564f2f2e7805818afbca" . + "400e754f856b17e4de1222cb9ce30db5b3cb877424c5f67dfc1874bb1bd53052" . + "4ea2d0a98e72727220c79051badf6bdcb1dbeed0c33d65601ba6bd4eb72fa9c8" . + "58bc06997155606ee45472edfcd86bb4d99b3cee18d9b6b9119aa70ab9aae206" . + "89fa70f0014587321e382e10cf395b9bec00ecf2416cc6e32f083b21bc29ec4b" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "71ee6d611fd1e8c19ac2889df35b26461afb0ddf4c137d9fbdf40ad1b1256522" . + "71ee6d611fd1e8c19ac2889df35b26461afb0ddf4c137d9fbdf40ad1b1256522" . + "e54bd7202b971a1f3ce324ad3760781ded5847471aeaf555bc06bea27fcc308f" . + "d73ae5240898b84a5bcba793a02d01e8289129096e7a82d3c8a11ec60f78b0c8" . + "12169c4a3615eae6e837940f186695f765f92a45d32997377abece3c9c50f4ac" . + . + "7f3091f6dae026705e8a9ec407e1fb773074b13defbf65b38d2f46d5daf94e69" . + "1be026f7b1d7e27d8f1102d66cddd1ba7d199cf1268ac445c5d5eee8757855b8" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "d5d5467ee5422e977ab9261ce44a4cbd08598b2715013b84876678b2228ffb3d" . + . + "ed3a4e37c10b764bcdb4a5693a9fa50f82058b473cca24dbb0be7a0656f47817" . + "ba1e78596d864069c46e1fb50984a91373641ebc9d3282d8f3edca75d8460adf" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7c0a51800e4b43db8da490ad542d442bfaba0a37462225acefad54d721007eb" . + "f7c0a51800e4b43db8da490ad542d442bfaba0a37462225acefad54d721007eb" . + "b617a819f68ce8d8475d4ec0bb5fb7f9d81e62ea47fb463604d22f60cc8b0bca" . + "f5fb2d0a54c9cfd38fa4b7c15a89c0b0b879b377f00a369cbc4dca550cabec6a" . + "47eb65af557134b52c7485af12718743ee0d7bf96ae4794ac3fd2d731d2ba9c0" . + . + "8d5acce4dc5a80541988d85010b1200950073ee3f7873d6b89be3da382fe13c9" . + "22b540d2dd5d3a70a57af85b2c1cbd4b41c7720934413f0182b5fb7be677eb20" . + "ad6d85223d2fecf2a728e710cd0c84ec6eb54f14c04657b98372b550a5be6b58" . + "15473927454fe9114e91813aa313b280a8a5d3ecd3acb6d72967c881e4d7934f" . + . + "c40c20577f708a9aa69eddeb5b0bb6197764b1bec5c09cc927191ec8225659db" . + "8163445ff8b4a287d103abf91a24234258e5207960a74a3d6c6ce7fedab3f795" . + "65122e90bafcff9b339f18d3d200f2de2a511568b29514a49b2b8a7f224ef916" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4d5d1bd4e9da03c61d6a210aa9b337e565195d8bf91dfcef7727e0e0960b2562" . + "4d5d1bd4e9da03c61d6a210aa9b337e565195d8bf91dfcef7727e0e0960b2562" . + "3271611352080cabd51d97e0c7b8993f3f6ee6e6a08fa11db153f72ab8427c5c" . + "e5c2d26b5816f6776c2275f6710e634b917df63c3482f3ae3d4cdf154ed60931" . + "76ebd3cc531a10db2c032ced60dc70ef75f9e6cb2a0b89f6d695e39ed6baa870" . + . + "2419151425997e0d212d4b7b6e4efcd2a4fa29bd780f1ff56f33616a80585e83" . + "b9ed8ddf9d1947800d5e1b7eaf84b5360c86ad0b12d9ccd164444139f831a88a" . + "ea729466780dd6d20f3f10aa2d0765c037a69acb3079cd11aa20a6cb18ea7f20" . + "ddfe7d4bf75fc664f0554eb817970efccd04d5f83ad6f13e789044b0f09cd00f" . + "aefae78db97f71f964e62df5884882f04078e6a0bb3da6c5c1fa1b2f9490801b" . + "f904eabe0bffbe83eb602913c5b3ba0280f703db90b5e7691ea78e66b7e61bd8" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d2ba2818892df50d80255470a4b3d6573c5bd9d4dc9eee2603516ee6312235a0" . + "d2ba2818892df50d80255470a4b3d6573c5bd9d4dc9eee2603516ee6312235a0" . + "a578f00c9b4c8e5c863f99c93aef900246113b1ad1d037d6e29dfb0228cd76dd" . + "7f94aa1990a1fd462afe5091938fd31a4a2dda42b34e1beaa2c81dcd8a96c5ca" . + "b2c584150b26beb7ee5c8e8bf6b435be936141e5c5443b6492915ad66bed8d83" . + . + "fa5c8605e2bd0a21cbf7ec53c28adb00c037305e61392b61520f86f99d43be8b" . + "ab94936dffeae17ba61e3bf62c96d892a85418413932f8684bb6ecfb3bfff0d0" . + "871043f36c9e4c425db28509d8ddcf051260e69fa1638476843d0efa554c0fbd" . + "e6392c3860839d6334e57a5b735fbc16e34c0ff96e7880c62e08625989b80306" . + . + "f7b7b978d27a051976bf4225e3138bb8d263f9faf0349297d4b649389c9563b4" . + "643cf84917b06e94f4a9bf4e18560267a074540dde1f584be4bec38cc2221768" . + "9f9f5f29699ed00d5a8a79ece5d09d051391aaf5f3de69f4c275b1077db139b3" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5bfc371a16557b20a05c45946233df14f9b978386353dd89b6021531083f08ac" . + "5bfc371a16557b20a05c45946233df14f9b978386353dd89b6021531083f08ac" . + "0cc6a5ccb75e8192ae8413783e66dd7c7e5c0f521e2ccad1704a055cad1c51e3" . + "a397f9be9f05ea631c020fa39a6c9e7a899bc311d02356e3e7d70368b03d2e8d" . + "ce4911a71e52557cca1b673e841b4980d15465459a0225db95ab44629edb08bc" . + . + "6594e0b948ee071ab85e50c19f407c7629b935672d66dbb76ba0a6c5ee69ed80" . + "b20aa47bb79fcb0526f9b2ad07ac9ca8c9af1f17b64a00df274db09274a64d64" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "f7e71dcf2e52e56c9af2e2f450111d0007946aa84c38cfe12e0279e1b3a3d63c" . + "0a54940a39a968bd95310c5bc138d19f45776fa41e51705a09e0e0f3ca68f41a" . + "0a54940a39a968bd95310c5bc138d19f45776fa41e51705a09e0e0f3ca68f41a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "afdfe027afca541e2abb6a1a32d479ca9da3318d70527d19d094fe1cb70f32d8" . + "afdfe027afca541e2abb6a1a32d479ca9da3318d70527d19d094fe1cb70f32d8" . + "9a4177cbb00fc4828d83313de2f1f41fb4a164984ca6a4593605022eb9313dae" . + "038ecd8a932b9909dccf9266f9ac5220cee485443dd8291eb0302f2be498fa41" . + "60ab358a54f7a29ad730d10b61af0075c43bc964c37b75d65957e1c2b07ecfb2" . + . + "2e4e255d3184ca8f8dfae06221c67424ef801c3e4d884ceb5348f6529d1333c9" . + "61ddd8f5c1a3aa0db416458708bb4c71ca0778e2c83314e8df84db6fbb268245" . + "7d11480e5315a644c52b1b9650ae49292540e536e6b7499c0e3117a276b109f0" . + "da0eb97dd58c15e1046dc2f72e7b6b5d7ae1d08b142ec7a99b7a2fbc6da972e5" . + "9f97ea4322194042eda2266235ac8492179d86d154efddfd6b6dd4f988cb8be7" . + "2af59e89110dafaa487c10562eec63b312dcc2959e0ce2b395d87616a5be77ea" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "925286bc004b66853b6839a63466bb5ce7d0301980ed931d8f6af98d65c6181b" . + "925286bc004b66853b6839a63466bb5ce7d0301980ed931d8f6af98d65c6181b" . + "379686210716f41b9287762b2f10337306f3882810c4e22b36f516a2fae07066" . + "ce329049bcda6fcef17c7d03f2586e417e582fa6b75d42c73148be9b9b9aae42" . + "02dc021bfd7e87957f80979c5cc8ea29691da4da80d8f1317d87dbc4fe4525f2" . + . + "f6e8b65600eca48ed8bc1f9feca69754a7f5b9fde922387e7e4577a95c7f8b4f" . + "8b2fed1f08c050b42f8c6256233005cff735b64dbddcd2b8bd9e71ab40a9afe0" . + "da9e869aa96f41dd3aca2831397f9c2e411495515628d8e9353de64f031c49d5" . + "067228384bbe28af84f3ca5b8e8bd8241af5d4178ea00f46f5d06a9f0682af5d" . + "4dec92fb3226812b948f03caeb6715f8e3a78953503a1cafda1b61f489bb5914" . + "3a33e9d7b1443499c583fcc0fa47daddce8c51e432d9643ae9e40c7fce5bb24d" . + "dfa28c290ba4dc1db4ac6caa30a1fdb0d9fcc7eca9dba1cbddb42f0e4306afd5" . + "d918e21e6845359780b08a47926dff2cd90a8b0622178681b9886e1f6d4c342b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "15bfedc1a088ff589d507922d33ad243309af928d17915b28a4b3b6ff7d0093b" . + "f6e0d0f5ede36dc5195cae303a32c54f5468e364db7a043446cc16da73441011" . + . + "8a1aa40718fe7b8719b191cc6802e0c12d44d5a3764fec4978576a3008dd320a" . + "5338a85dae2f34ebd2a1c311a3787dab9a6dfbc5311b3f69ccbd58c1abf7653f" . + "373c7acd496a2ed0f76c93f66c084c05608a672eb3ec13b29ec616ea4e9bc8fa" . + "7544065126eb616e77d840abb719d83353cbf02f4ed3649190e91cdde76c0232" . + "234f2f984d687389bd37dbfef0f506bd918c633e19e83d93d67c9b823c1b729b" . + "6b8e06f20f3f11b1ce73e729c905d4c848c6b3a5464a491320afcdb489877970" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "55a4d5d7fef229d25772737044295b985a4247af5c46c5d9c8f9d2230d7ac3f4" . + "55a4d5d7fef229d25772737044295b985a4247af5c46c5d9c8f9d2230d7ac3f4" . + "a702f70b2cc7745a956cadc73745a9ed9f7023c1366862e3785ead51b08051ec" . + "2634fe3eb53177b466a88add728e66b22f3626bf95916f6ab06bc01a522033d1" . + "a6533450ec67f97a2172366c5ec5921ea29d9af4c28c30749f2d6e2170b31fda" . + . + "e38b7ca918e034f902cf427291e1fa5b0dcf7ea5be97229384062eb95cec0592" . + "2fce5240d4ef003b60806802f6f637bd88478046a922f875ea23ec6869691b83" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "d3ee530cc44a3fa4f0f86d1139a9409fa549e5130e0c8b31bd9fad5265cead56" . + "0c0fa03193e68e063f1830d859ff30f349eb97b0a7d02be440813213610b8756" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8e27277c5b61c9a633fba4e36568aeee02e0b24782821a26675ce9d54abf3741" . + "8e27277c5b61c9a633fba4e36568aeee02e0b24782821a26675ce9d54abf3741" . + "881d7a64c565c3083d3f2ad549dd93982cb966a3bad9463aa8cc0ab59fa52024" . + "6a5c12f5d0954d2a45995d9117fd8ba1441b95481a937c21fc75ff8d14c78937" . + "1a31c56d95382bd84a54c9fa571fd7225504f9300cf452b832d448d4f8c8889d" . + . + "136e10bdbbbfd9b3fba50acb8048e6597a2123cae4089a0b38669683c5da170a" . + "2f95ceac16012af3826922243b504fc4ba24a13a066c992b0aa8b2545c670e35" . + "5cf40774b4dd5aa34c8e1f8e908e53a9d279dbf7c1ea28367604393788aaa061" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + . + "cfe4fcb3688dad5c490230a711f694f9aadf4ce6ed7c7ab9d2d2f78fecdc5c9a" . + "d95dbbb7133630ddd014facf697e795e288049f21c76c71320163d04deb80fd7" . + "0b52a96b6a47c3b1c4c3747b77ca6e5089bef61ca7e8bcf1077e639020ff2f79" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3299b6aaf6f04e46ca67b43e3a999ec2a5ed67b65004e9b7235983ce407b22cd" . + "3299b6aaf6f04e46ca67b43e3a999ec2a5ed67b65004e9b7235983ce407b22cd" . + "6d543a82c0ff0220f8322c4bdbbdbe0cad4a04b9e35ee983c709a10e35a40027" . + "8b97777ccdb62889c25deb8c625dee0b3206385622e3fd386206538e976a21d6" . + "b645332aab2d634b7881a28c2dfbce217eb9ddd75540aebbf9dba293a4b3ee83" . + . + "c0320481d202a49b8017c32325bfebd74afe7d9f1e9f816c98dae002db65b721" . + "d47667f7b1ae72dacfc545347724ffba7a1bbee27ce8cf385dcb0350199a8b27" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + . + "50ee8675807c0f050d324f3791b4914141e8eaac25dd03a929849084bf3e47fa" . + "2299f44ca529dafbe8d9e3cec55ff0717b7bd38fd95c17bb110cfcd431dee79a" . + "709c9304f230fb26db8a9702cc857c1fd903576c0192f3fb8962e383e3f6a070" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f83a71c247feeed477cd6389b5ea71c50769482d27446e550b09a17115089e16" . + "f83a71c247feeed477cd6389b5ea71c50769482d27446e550b09a17115089e16" . + "ceb527c004687a565f1b13fc9cf4400dd52124d6806e81e6aa767cd11ceb98ab" . + "c6bd8e8e200f9fa8206dae3ae381c886d1294dd95d5e15e9ba34f1d7bc06a400" . + "3fff4b427c1b2d06a0542292ffaf7a1263115120979e3acc88b01d64a56cc47c" . + . + "96765ef73fdf0349d88b67eee46af846bad77d5ebf0199d0265cfa27a16671d1" . + "74bfb3deb32b728d332a087b0b772e4d84ba6fb0a0182b15de324fead6d518e5" . + "bdf448efd15e55ffc5b66c8ab743637ebead0f9e273f7cf60ea30ef50dbd6401" . + "24bb2c7f06c9760496afdf12e7e25fa7ae8ed18b108775cd9ec79f0fda5ca6c2" . + "c1b4551fb44604bb3319735d4c899b92bd13db37b1629440f36afe0c59716a6b" . + "997399bfb76ae42dd5ecc8b6ab6ad911140b2be34f6da7bf6434c4be601f6aa4" . + "042d8ba5d8563e465ef2d4d3845649cb4582846dab3b78c2957134f9b9231c4f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e4185c5b19e740b64dc5d744017b3b0bb424a0d5ec6f6de97f2dc86cd13491cd" . + "e4185c5b19e740b64dc5d744017b3b0bb424a0d5ec6f6de97f2dc86cd13491cd" . + "52996bbe3349c798370ba50c0a0018cbb46ab41865e70911f2a993c1daa5413a" . + "914e90b1cea523f39393daf74a893054a431b0071ca0e9af47558d37f4227b5d" . + "7c387803ff0acb08c34204b8ce0df61f95c6e5bbd49dc55a6b6d6651874af72a" . + . + "38e2264955250e2577d01fb1f671fdf62a6b9011da9edc97bc4e2cc1424a3e39" . + "f600f51714b706c12f6153d29943ee7aa5c5655dc226ad1428cd6432b7ec206d" . + "b875775b7ef4773777e4fea8b548aab1b9a9baa179f1f4c79dc1e97da80412fa" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + . + "814a1b7499a8fe3684deb279ad88aa4bdccc89083fe3d2a8878d12dca03c4419" . + "f34968af94cae966c7421a7dfd595684b5a4aae6022a2eff99360b81d99a08ca" . + "aa0cfc5dd364d104ee2791aec38999ac279ee8a2786eafd7b7a0b707f67f30fc" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1569bcc95ef817a3298461dadefa34c915c0723db8e9609eb427ed820a56e5f9" . + "91113e9e80e376d7bbbc6be94f8e72f31aac42eff0ccb78c1f8f28625139cda0" . + . + "d08297cdea8d3f7acb7b02ee5a97abe2a230f54fa8583ff47c9699698d00e09a" . + "6ceb470c6859151424ecc9deb0b2ce2c53be2b46ae3535f2a2fa5948c26b51d5" . + "91e6ed0e7e8061b3d8df981205a3652a4ea5e7eddd9e95d5690d1f62385fec79" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "2dc69a34e6e8f1b61d654ab19fb8796473c9a4852529cd26ce76a449d3f74d20" . + "e694fb3fcdf61c5e995dfec7161b3e9bd87997cf7910444fb546ad4296545fba" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7d10e736ae2b2b0cf2120767bcbf23ef86f051253b2a569ddfefc0e8226a42ea" . + "7d10e736ae2b2b0cf2120767bcbf23ef86f051253b2a569ddfefc0e8226a42ea" . + "876d8f99b3b88fe7ab4afa9060b9a97c4ea5ea405b2d2e700312c391c158f7fc" . + "3d0b5e5cacff84b0fe911bdedf0a09975a2537cee4fc7fdb6ad0716d363ccce6" . + "e40ee4fa4aa0a1fa942ae26696f824628ee3fb9bbc37a16faefa0c9b9ecb1b6c" . + . + "e12ff6d773a4f1421eea1617ca71055ddab0272e6ff669bc1658435a2fca57e6" . + "8e50e1c84d6c7c0df0d6e6d84faf95e98301508126a233de7fa03d5b1501fd95" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "be273d8a566d0c421b5a84dd3c04e2955ddaacb2fe8f468bdf1150dfe7d5cf5e" . + "72b25462d1ea70977b23e51ab388e06608d4d7fbbe1aa60fe3318e6d6873e31f" . + "6dd3b12feb4e12f305d3be98a1402254952f9ab0b1f82bb4e54a4568ce9f6e55" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d44449e2817f7d76374615c3087ebce4dc4d1b0c8d2b8c650229b6003c79d250" . + "d44449e2817f7d76374615c3087ebce4dc4d1b0c8d2b8c650229b6003c79d250" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "900a62ab3f5ceec3353217307b8d0ea31308981580589542f7c8e8739f8fc801" . + "f09db84c04b5098a707186c8be7a7ba0c16576e5bdbec7b3c8ef3115a23b2631" . + . + "3288421db18188f82234b4188165fdb39b8b8f9dd6602be19b8803ae389ffbcb" . + "7743c4fe90cf9a567b07260065560ff9c5a8a0e24d438ee50dd3283d0db869db" . + "e9daa000b01f3526411cb83949e4892b040681ee095e83c995c7d890972642ef" . + "aa008b418b7d5553a7614aa6b2aaf51ead88ef1145976ba358c1b41a0ee164a4" . + "98a7ef92c90ffc049cb52cbf5882d80a8d614fddc0da75ed669b93348b65e78b" . + "c857615772d4db5f171afac17d65102017d8bcd76c331d6e4bc66bd298575357" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "29b3508c5f6c3f9079acdf4ff108e31de94b6de56a59be77c0658963d3939ede" . + "29b3508c5f6c3f9079acdf4ff108e31de94b6de56a59be77c0658963d3939ede" . + "630b2b2b83d4d9f80262e937279ec44c3082c2148de6c76f2e6ffdcf5355d635" . + "cda0e1b8446f917e703fcbd0d0636ea4f237976472754b12fd6199d48d3d302a" . + "33507a358179186b49c491a98af7c0c443829b1d6a5ee0372730a180703f6360" . + . + "5870da83cdfcc5771a795c8cb6892ef2cf439c9b5eac8dbb6c605ea57e3cb66c" . + "08c50efaf951dc2f47b49e7213c2c7107a9786058e95707c9977e1fbc0335cb4" . + "616f0f67d4c912a1c72d654c26b5f45534f21c989988a64ec98e346174366fc7" . + "2ef068a19b4cad57f0b6b9006505833552e3b691aabc2638a009fccc033018ce" . + "872d47192fe29a44b444de19764a85831a363c2659f040e19b7794c8f6bc9cd4" . + "e6610de6074d0fb024c120d0fddc3e1effe7c83eb81387f77e1dfe5f15441026" . + "f71d36153c2324d8239235c9ac58c7ed1f223853b935b4fd80c9692a97b208c3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9beffef1d0ff446c7dd2af3740b7a21b45fa8fa647c7705c0e5705e46e90110b" . + "9beffef1d0ff446c7dd2af3740b7a21b45fa8fa647c7705c0e5705e46e90110b" . + "e74cd6e65c924620180fa0af5b1996dd04a81d7e8e51c55914d431b11c9e9728" . + "72d5b4eff3121c25133e918af7f1ea21c2715aa03b2d812f7fd93c417c26bc4d" . + "b6b1d08119542019cf262721e994acd0428e10f293d903437c700d6c44e8f904" . + . + "b05b7de14c64ac630eccd07f0400ad80c7c4485b020e51fe9c33b45827cce078" . + "195f5a425936852484ed26192d6c4c280c0afd083efb3e7020c1c98ca5b36e45" . + "8ca3d2fa061276c783c53ccd801aca1dc20a6bcfdef88d8aa5eaa3343ff1cb05" . + "b55bb7a3402acbc04a3c6855ba4358158b294b52347f0c863de03ebacb13f2c7" . + "53418a1f91d469322826d54f701e66c87c804eedb694e9226bec4303a85cd3c5" . + "87ff305a2597c0fd74bda6649891d5c3578ec824d6a0d541f5e2f0574d74af7e" . + "af16272ac8a9f4b197bf08d38982e78e35f1d58328c8b922955a4efac6db13f9" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "62e9f4db7acd218aef15a8dd3e7d9e9d14e4e529fbf489a3edc038679e61541f" . + "62e9f4db7acd218aef15a8dd3e7d9e9d14e4e529fbf489a3edc038679e61541f" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + "0c1614fb3afc4c07b034b76b01d77955eb58d14b6c2378c629a4a864b7163e88" . + "2aaf1ca4ac4cf2a082039ce0d8f484620c643bbcc0efb57c07ac9ae57faf0182" . + . + "696a79a57f8769749f1b3473c8f1cfd8c4d8ac6aa2d9d3577f05946f070b024d" . + "d0e85d83ff89a11502a2009fd61925680d2735ab4b40db199003b7a618f9021f" . + "a2cabda81d87b31c6976ca218f68b4cf2c11f4d6b7e7f293db88a332be775b67" . + "5904744d7b61bd1a662f78456e945638a5fba4dd48e4ba5e2634f2706c5b7de0" . + . + "e9f7ae948f9386e188dd74da9d2b18fd7774f9bf0c03b5d68d1c1c6a1ecae8e9" . + "aac0892df65b6e97a49415d04a83bc9bc9a1042b2768f7bb0c8147c31898c115" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7c0edfdbc2f5a33f8ab4b28bb566f82f692a0a52ac7f957d60aa0096bfa2bd33" . + "7c0edfdbc2f5a33f8ab4b28bb566f82f692a0a52ac7f957d60aa0096bfa2bd33" . + "3651e5b49871afd5a1112023faeb31584ae983313887ab5656742c60a845c133" . + "15b344af10757f95f2208f1c9fb7b12881654f6382cc4845db1ec72ae1f6c368" . + "8ba440aea6319238952c0ab4b57167b12a00946d918502d3ba968e066edd092b" . + . + "7737ebe2a79cf96c50f75b53fa0c8b8036695ec76c56f46fe470c3401ddc23b3" . + "97520b0520dfd7eeb235c97136ba7b505d422369ecd5e918c124eed8b5bd33de" . + "0e2ff46cb585b98b67d1f2589b91493983eaef1c59a7bd0a067111cbc78edb75" . + "39cb6341a9782bb577ba867f16889d0a75df361cc4ff3e5c66f43ab6b0abc6e5" . + "c69cc1ddde3f37c45573d7b6c67ce7cc89fd990f45424c4e751f34483d280a18" . + "f8c3de23a93b5ad6a9e425e20705c4262d86a09e9eec8346785aa546b32cb62d" . + "5f626765a87f74d99aee4484a9f7a3d293d01b7935fb5d091fd64db53e4eba6f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f5acbc5d9bcd20002c896bcfd21b8fb348a7239e266861d9301c4df00809a981" . + "f5acbc5d9bcd20002c896bcfd21b8fb348a7239e266861d9301c4df00809a981" . + "0d988e5551d14e3678c65206301f35f0d0f7d1275487c3cc44126de681920ef4" . + "8a7c4d347d93e9b5f49d11489348eecd24e8ae5f380a3cb7050f535c72b7a153" . + "db4bc60b617463af48995066dc90f50c3b2a80ceff1da7d508ae9a437d5ae9c4" . + . + "232af7862f623e8111e50b8a041bb74fa40642306d3fa08d400b440d5f1ec9ba" . + "ef01a0ecb8cbab8e6607b80535a947e06a733c9de18c5c88e984304cdf5a6670" . + "672b25f4f9d7f4488ef47c810a926920b017b3edae013b34df71828a05f21d02" . + "f63072cc7cfbdba3b5dd8389f84c3062abe1d26c15255d5e867d4d3586919911" . + "b32667830d199a704c3a9d1f8af5d7b0932769fa5b46a6e6dc6c36f4ad5539d2" . + "0f68dc77ab2e725a19a17e7985c1f2f0479a9015dc4370d319721e0be97682d8" . + "2c37a9cc22f6307949015eda8a4abacf94d666018e0f850c2d7a90e5c105639a" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "abfa06f577ad2aa69c4fa97bb0099fe071ec1b192adcd0eeca9a1e1ad4a05146" . + "abfa06f577ad2aa69c4fa97bb0099fe071ec1b192adcd0eeca9a1e1ad4a05146" . + "d8c97c7858cd6dbda61912266742a61ee1290fa99f6b179888a4675527b1e2c9" . + "ba32ecf2c2198849b30f6fe6bd97c730bbd45b64a85abe6254ffd8e940aac2f2" . + "a57ccc1ba3681370baa9da442b4cbcb94b849d5cbf5a72b3c2fde607eb7694a1" . + . + "2220b48d3fa014ae3720f2f635bb85fb34a2af3852dc1c6914191ed9fe4da80c" . + "e7bf595561381d9eca8bc6031df6e68403b77ef942a20f6ffa52888c5bce8b85" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + . + "0f07d236ddff7e8fb977133399a94c631b94235f7ca13525ccf7cf051be0d6df" . + "c795f68fb9f4831824d05b06e8e34ac631d0cf6ac285a526d3d87d7ba2411f6c" . + "92c4e5d3811e41dfeca49f1c03e466b922a082236fe10a99fc2f697b4204d67f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a2f4da807c3fb486189bfd9be60df447096550748be2060d54beb625383c643f" . + "a2f4da807c3fb486189bfd9be60df447096550748be2060d54beb625383c643f" . + "e3c43683d8ffb5e2817327ffae2549bea0aea0f2474f2c2865d35f50a2e2504c" . + "9ed589d470c11bbb95507dbb02b02c0be36cec2c80edd417f69bcce48ddcb447" . + "e94740b168862d858b5b89275618069cc5904cf04c27c1309046d8860324046a" . + . + "f86fba25f6a698a7a813b44ca101927b1d7a5e06d0f6dbf874cff55030b370d4" . + "a2d6ffe5576b5b72e0b4df70c8d2984d6172d05fdd6b98f3e96a74ccb4b78606" . + "5859536b6dfd0b3b2c334e2b7f9bc7a247aed7a06144d3769ea60e0ba1b076c0" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + . + "d2c7feb12aa042234abe1df1782518327d5da6ff5ca0b2edc3d3e3f7ce85bb72" . + "7b28d1d9952f14a9012e065f25fbeb2b6e53076bda16885975c0de9a3524077a" . + "2bb9b0a0fc66bdf5538a474e28546b8a2a2af045595c578f05ace5077a2f488e" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "41249b2c3dd4b41f582a9f881f9fcaca25cfaf806d28a0c0ba078c8bd4b18546" . + "41249b2c3dd4b41f582a9f881f9fcaca25cfaf806d28a0c0ba078c8bd4b18546" . + "d4f2ca559ad369ac0f8d85457e1ebcef40005509c5e485ce7592b692e58e58d2" . + "62912bf2ea270d6dd9a5c09b0dfa08ed560850a2445f5a93e92710f9669af2c2" . + "2f3f4d08219c82729e0aac6aa5030b8b26c76840303e3f13f903abb2d7cfa383" . + . + "7bb3405be1a46542321f42a2355b654a68a6d84ad451197db208d66bbb5e8d63" . + "54ec370ff881d2d93e54e8d06c51ec7e34887fa33e967e6f001883d17baa00ec" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "1dcadfeda3637dbe0020c3f5b8911e4c288270f5ff5073dc8976961fbec7fa0a" . + "7bb3405be1a46542321f42a2355b654a68a6d84ad451197db208d66bbb5e8d63" . + "1605c6ad620da48a37cb22223f3e879e6ee5011cd7a75389f242b02b97528250" . + "bd7608420e5c893d063109dec9de1a15d49347d07ab5b632c1708ac4dba4dbf3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f33b2bcff478616e03047b7fe3e08c947cd3556c72b738c308ae4cc262c625d6" . + "d84d1d41d832f951447a12d71b1249e5fee369cd578acea75c5815f0fc5f8342" . + . + "8cc304c45039d1cbb686107bc75773ee4ca73e14c17d9919a9b7625724f2f77a" . + "3b4730012c1870f0efb73d7aca870ceb511f481bf25aa3913c64e5d33d46c61c" . + "6d35a339272e2bfc9f2b1e9398ecc119553408437d09cb21d462d640718d26fa" . + "3a939550f45494d0cdf88dcd8618787dd67b523bb0eb705ca6b52a3a8b6aa2f4" . + "0dbaad6db780b37adc7795e8b98139b837b47178e470b72bb4aa744e9f3bb59b" . + "53b8966dffee45f171b02d4b2c123211e9700d78ef42807932c729e4f2298af8" . + "9c649dce7f21ca5b5275f8b891311cbfe294ecb8aed77f1971c577bc2aba360c" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "86c59b25f47811bd71f81b466fb1e50fff8138fc70609b6a30cd995747dc9b05" . + "86c59b25f47811bd71f81b466fb1e50fff8138fc70609b6a30cd995747dc9b05" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + "caf5b946a104a1b9fdf97cc9f7478caa2a2ffa47a3addbb8cf42fed37cfa33de" . + "f0dd5712f08d050889179d5383f9503f6d70cbffe9e55e681971b4cbf4366fe8" . + . + "ec4e9ecae89b3190879215813f24f7bb0bfb13717a389f58226af4280cb797e3" . + "20702b36690a0216343a39e01f39699bb6d7c17f0eb98f6aef25ac848d57d5af" . + "438dadc9115c050b9c2123f650be840f50802fd85abaacde62e6713d5dd4c02e" . + "5fc511de482e8a51f2c1a16a88ca28dd231aea8e2aa3a9205451e6994d967c71" . + "daf5b5935481b59f6034524f64598ecf599c45832369517209687978b76a6654" . + "8847e4044861e6f2f88db0035dc88beba1e40edcf32be35fc63b895077f64f8f" . + "9e2bb17d8e66d9094b9835dc2566cf885311c2857a45c6bafa0db2179f8a4330" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6853b55c03c28c660883d00dc60af7d774712c91a6ce7c3077cc3654f947dc1f" . + "6853b55c03c28c660883d00dc60af7d774712c91a6ce7c3077cc3654f947dc1f" . + "404940a3b0c651c96a6bfb0bd743abeadfe2512b32132dd32c06d56efef41b45" . + "99ab7a1c95619b80dcc16050a4b86ee92502492b3e254ac91d59ce6d57d1bb72" . + "e2d017f017dfccfb04c4ff954a07716e3eb4bf94fee90fd05c36cdfa72897568" . + . + "46e268ba1d56d733d25795fc44961a0cb731486ccf69e317dc2b407bbde7d7a8" . + "bb8b24664f71881a7cb5d8e7d9677f06a016a86c224b3c1199517102adf49e83" . + "bfd5c7e60755cdba2a01d5b2fe81e65666d89a8c598624f05445b51bbdaf5bca" . + "a9e654fc5c4b02045588618601cd326fa78c4245a3ccd714137cfd672cc2a59c" . + "3ac9f724492a5f6901294eff53bb5a72f891cd10a6258e03410474ad828a270b" . + "43afe065e48560afef40c856be798007c4df4a1976f27e9aee6fce7c7db521ce" . + "c43efcb5640e4aec86f5470e327e20fb56f4f389199ca750c8e8872909ebfac0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "50ea6ae4e24c0c59ff7a0d2ae11af41315d4c7a1c61b5c6d599296be819ec6d5" . + "50ea6ae4e24c0c59ff7a0d2ae11af41315d4c7a1c61b5c6d599296be819ec6d5" . + "6ac62702d5be2bc68eacb2006863e63fa4f1c56a92d1aaaa359662d908c0b0b4" . + "0cdc95b2de1ec644fdf0c57fe5574ee3f386fc003dfd6d3f01b35fff6a40fc4f" . + "b7551f6b5a221aee7908f1712c4bf02e80357df5fb77f1a4fc7eeff46ce4e42f" . + . + "5f6cf0498cd02ae1e56e3f2c89293ce933d3657be67b361d3924bb5ac8360a60" . + "ee3d909ac1764073345142d3dbb6358aad59a7a4a4547006b896f7784d004369" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "8d99de1acbbe8cd999f636bbbabc0538be23738db036a5a9dce51673d4a5989a" . + "18b8014632f4742ae6d03db01b63c38a8f36f605041e1f4930b3103aed7f7e26" . + "d55c2bede727cd3cda22d388dc0fdcddb32f5d5dbb9045c14250c1acfd1e7de8" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53c6637f97d4d7b64acebee79629090ed18b8f1dfa49d6471205810bbb8dba03" . + "53c6637f97d4d7b64acebee79629090ed18b8f1dfa49d6471205810bbb8dba03" . + "984a55271d780bfc8785f899f79cdb539883ddf63779d68a48ef5f8858db6eb8" . + "03d9fc6dc497b9b262a8e908e8f3f2dd38ebdf936b98e2d06d3076456a226c8b" . + "562d1b8b9f32c752d362929e47dbe8ffbb8976d5485c04cb430f075ab60f2921" . + . + "73c32a58f28ea7930dd8f1602aa20656921ffd27df99ad9a06dafae34a3ee0e1" . + "7788a921179f2c9206d3379f8ee32bbc6c639241c09763ed054598a53571bc2b" . + "dfa92c0451e031d358c6d34c5fad92bd60cb9d6b963cde90d677efbb3fcdf9fa" . + "a10a113ed1b9f32f1a994a43c7e6060ca99c4cb4872e730fd557cbb0a1a46405" . + "e855c39abf18d5945c8d2eb9fa0ea4eeffe3400e10e3cfc85c827e6e483747e9" . + "99f1f86054b644a4426d8fb36b7953a5d645c61d1bd95df81b9e2e2b731c68e8" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "01054cb50c15d6320e653b0e0b70ee642f7b36dae3e76f54ca716a12159323c2" . + "01054cb50c15d6320e653b0e0b70ee642f7b36dae3e76f54ca716a12159323c2" . + "72b5d242019595bf0990b77f9db47b4669ccdb50180c5c1e4750c35d480afb8d" . + "47d9b2b5ad502144bef90e744c7b5bc0a4bfc84648e5ce15d7bdb8ff33599ec5" . + "d447d5e5c55d361ff8a4ca20dc77121445572bf311acd4dea5956e3e974d0af0" . + . + "e75723122e8e6f4b91640921d28a0eb7b098af1c01546dadbd718bcf26f67dbd" . + "6a1664046398cf98981106ffcbcbc59266f886e3b9687d2009cec14c4f52b533" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "2a8f01402587239b8dfbeee1be04159b7b23fb3a802396875095f2cfed4dc221" . + "2b1692b253b82b0c6a26361160309d8bed684ea70050bd31e7a77a571c312ae3" . + "b1efa3e9005261c70f23f2e7f430ec785c3def2d743d6c18d6e7060637f5d4f3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f810c993b57bf0dbf4e9a48c37a6bda1fa8eb09a3ce028adf7ed28a6f3648ad5" . + "f810c993b57bf0dbf4e9a48c37a6bda1fa8eb09a3ce028adf7ed28a6f3648ad5" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "f875aa2121825d5da03c6e3cd1c4cace8b0aca73954ed46a0904b0fdc04b6320" . + "a412628f5887b07623f2c66781e25e00f6c1d550760f33dfcfce3c6ab6831ef5" . + . + "522f14c0d92557c7486da6919b52b0828225d545de45e7736e745f9cd6f2b1d1" . + "81d766a54262bd5608941d7cfb0066bc5a36f661dff4d662e732c18547f93d5c" . + "2c21594311c00520169daeb14667311b2f098f678efa9d40b6c804f812f8646c" . + "1721664760fff8571cd1bcdde4d33bfa13c7f42e8e8f404e42d2064ac5a0829b" . + . + "069a751433cc9fc38d548aea221606537ef4d41b289c158380ce65f2cfbcddac" . + "d3bab17bb013f318f769bd38f2a1af8493c9a8b41ee527e6f4f3b63086a0e966" . + "be670c77186770db8c31eb6d521594c1c5a93f724ace53fa7c96cee52a36367c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "612fa1874f92fc3ddbcffeeb3f57f4cbd37a9ef83c63a4b5cf2cef70fe5121c0" . + "612fa1874f92fc3ddbcffeeb3f57f4cbd37a9ef83c63a4b5cf2cef70fe5121c0" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + "d8f93ff2aeeb78d5f00c8542c05af5dd1307e9c00ba74bbd721907cdc5073e85" . + "95b3ac7d68a3525e57e988d2f5e055de4f5224ddc5ee98d3161d29354652e63b" . + . + "9d0daf6a0b70e7880fcdae5515b428c10b76033df925ffa05df47641227572c4" . + "6b8b13cfb512bddb56610e0f85fb34979122a30598b285df3e9a47531d28b46f" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "b63c7d9a543df6a8a971590346fdc52a1ab8a338e3c7ed996edb0e6600b7b95e" . + "6f129ef317adfd4ced4b4bf4fe0142b5b8bb681c15ed5f780d9d5529c277ac50" . + "e40e401acf716a7cfb4c147a74fc4d3d28108be5049ecb484f4a9237770d37a7" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cb09aa4d7cff61b3d0fad051e3a2aca66d4bb9acd05d6f527cf89a1f8849605d" . + "cb09aa4d7cff61b3d0fad051e3a2aca66d4bb9acd05d6f527cf89a1f8849605d" . + "e221af795e3d619313cc0c6c8343d3ef38fac0f5bc66fd62a0bdafe0356462e2" . + "7599011a65c8a30645a80e752ddcf956b32234c74682815bf9fdcf497af46370" . + "95e671ffaa1d3c09528cec5275c44a156a9b98a2660de7791705d48250dc8a6f" . + "7034345d6ee536685eae719ec6e07d85984af5f78c454362e0ae2d9192e093b5" . + "a348ae1431130d4d8734d7565582b2218261782e7e2389f8716dc81f09b18571" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "769fe5c69f71091074a743e73096efab0a7f2e0521c7a3cd7b8177d40a7df908" . + "68121c37b67728a1ae61c6e4533866118a7de0be89c9661e96a7a22fad0a9af4" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "128db9a8b6bc7b5a44ec170466c889b87d577b3fd76f43f9786ec36aed284e46" . + "9d7cde8db382fba70162169b5f49176dae266cb352d1de4cddbba86e2f2c8f00" . + "8444184bd1c3cfbbdfc38c73b7864f334b4a873c8a537c657935e3338949dfc9" . + "db8781fdb302563f4e35950e1aebbbd00c19e013d181d052845df752263c14a1" . + "b3046e14566d9e5243210224c3599547fab9491d232b41e9148f1309a78a3d4d" . + "329bada93aad4dfd3a39c0cb77f7f331479542ea7b7600f6cab53a80222d2571" . + "82932ddce217e2199c3cd9ba126ab94c5a0bca7f820ad501ad2f39d4dd9d90cd" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "785b8aff2d5cde35bb8833a2cf6f62f0eecebc42600d80282319d55f092790b7" . + "785b8aff2d5cde35bb8833a2cf6f62f0eecebc42600d80282319d55f092790b7" . + "8b971440c4a5a323f3704bf3f5e4fca7f6bc8f4af9be110a7cda46d5c8af0851" . + "da0d29b0c212333af6725d8fc53d9043e82bc5a85c2beccb0339624f88b4650c" . + "07565b969aa6528fc1ad3aea0a7293cd45399ff897026e1c1939914790955ee2" . + . + . + . + . + "353594e692000c17bd50a2d745f92425c3557eff883575750bcb9466461f2582" . + "2bbcb46122cfc8b4b8497b7a5845ea83c7006c47552176e268bdc6099a79b75e" . + "b99cd808d4df22e982135d5880a6b2e9fa9d6de7d17b3cf3c5be1e1fbd80afd4" . + "1eb77216bb8310334bc75dc4c41ae4c7c0e15e5f466d843a82dbbbe3c90392a0" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "a3ee8402470d3541ba4e468180abba5d4332103077646da38da585f69d79e9a0" . + "a13fc388135bf0f94047da23a5a91fea579babb3a627b1a94abcf3c91a02d0d8" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + . + "2530696fdfd1f3fc353c151a64f73be36f3867efac5a6569d7abc964ec8940c7" . + "7ad58628a56874741cf64d1bf13150a55fd7f185dc860ab7d31c46b90c5815c5" . + "fb043101cdcffdc016d0acf042c664bddb0e998c7f770a56193213e3821bc67e" . + "b5da46ef98e7ab78d596c59cc182c1fbaf1765d46f5580a96529209c1c1a70bd" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "c5019e47286526a170c93205389a827153ce7a2267709ffe9b64b2806b15604a" . + "433272de653329aed64f6f2a41de323ba14ba26a6e9c1239d75b91f3c5d0448f" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "fccb1245de8ad6eb9dd69a0e8232234c87c82f592d31f45299f160c5b28cb90c" . + "961b382e64f3344fe2b82ff51b864bc8b10425a8404ba7970c4c328d55e7762e" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + . + "b5b363b5c033457f15689f63bf11fc0d24edc3e3d8dd41e087cdd38aa2a72074" . + "f8934ed470cfe2c68d8baf3628d600a523306d7c0a38a72d9e9518311eda98f6" . + "894f859d19f6e24850aafc3ed230448a59a9cdd336017383b887d74dea596ec5" . + "745fd3ab09c557878eb817a04233f81bf31c8090c729e614a40d51676cb98eb3" . + "f0b0b669fa50554202a5e23b1038b9d5c171c5938534437e86356281f88c0dd3" . + "9848b174253830c149581607693e76aaab74caa16dda4c0e679019582a7ee14e" . + "9848b174253830c149581607693e76aaab74caa16dda4c0e679019582a7ee14e" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "75e504198b1248a23e9fffd49392d52674ad69ef18aa69d40a3b5d97b2c3c998" . + "e4940ef39c0fd34fd3c4c6527fb73bbdd7ae9f7436e2e597cf92728348ab05f9" . + . + . + . + . + "7ca9bef96383fe54c5bae8b4fa4605d81205f7d7f23dab2386feaa2d3c4f6259" . + . + . + . + . + "ce8aed9e680338672ffdc4fe019e76a13db225db04ef461ec3a62d95215ae792" . + . + "64c356d586f1d77e40f819fbe13c89d0bb2b8cef21df8dbd9dbd04b22eaae116" . + "10eae4e345249e46f06a8c2c5bdc4d5504876e0b00bd11ac7ea36fb06245d044" . + "566d1bd5cfdcd9a4826277abc752c39917e1fc20a1d3ea0b254cec48b99f1f64" . + "8805c833570eb23337ac9c3c7536fd135bd4871c1eff2b9d29738bb1aa7da115" . + . + "1120f83496075aa2b21a50e217ae50435ce680a86dd6560a7ee634a940e49c33" . + "dad1d10a5bb03120c26967087f39143617f949ef1f3674385465c4fee95032f3" . + "db3623973970b681501395a524607c82751e9cd9bcad646c410779ea57eeac2e" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65b2329cbe0cd3d6394cf524845fb48af45ecf8a139d9961bfc7d03a9693a90f" . + "d1305a8a9fc53ac52173be33f9730df00ab1c95e5f8ce6d9b6550c35e772e628" . + "60be0ec8246070c32230ce9afe7ba2f02c99c4ec96a78ca16ee25c04caca0797" . + "ee2e7e9aa0df41a7b40fcca312d91289857c24b67df83d0a1ad89cd1ca3ac35f" . + . + "c002e14ca5debd06737000e5559e635b02dc02034a592ec061fe0770dfa8878b" . + "f07e6ee3fe6367245c7b7b8c389083d6f0f5f73a54b9c8b55e7d2fca54aba0ad" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + . + "7913434f5f84f23520f16766dc0160da372815214a42c23f69b126bbd4332ffc" . + "8ddb8b4030d56485d5bb6651ea63052ccaae038682e84ec6d918f1679e636c09" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2277282ca212cd0f22563ac6df2f9e9321ebacee279a4098a072549e31d38d91" . + "2277282ca212cd0f22563ac6df2f9e9321ebacee279a4098a072549e31d38d91" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "31c69b621dab3331a718c97cd1cc62d83baa8d4f6b16f313d31926994cb48204" . + "e5fba1264d389d8b07c70328a80fcd55d0b8381913ba4ff701839fcddf7e681e" . + . + "7be258dff5d8340c89b375e352aa7ddd8c3552140dbc265e544f8937e4a00fd3" . + "a21e1fa7071a25a93469870a75c0cf73e8e4bb643b25c791526c72d551aee348" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + . + "8a34353a021892c15405963eab64cc269e7c398bace4efec40f153710e315579" . + "22fc6940ee2e94f907697d0e68ada2371b2b201b5c2b8f3a38a398cab5dc838d" . + "f7c6cb1b918498b8cdbe998baf20c0ad37f7064f08ddb108b2eddadb1a58e00b" . + "51648db51d77b8c0c379b77dee2d7108da4baadf89ae31f2bd158e4f4ba99658" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6cb0d808da79b474051fab121489dd35f4fa3fefaea55e98adb8284cfaecfb36" . + "6cb0d808da79b474051fab121489dd35f4fa3fefaea55e98adb8284cfaecfb36" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "bba02de6fbf3d0ac00ad0e9e973f572d24e6e087d53c1cc2d51267177c42fedf" . + "026f391dfee7db1b4fe01651295e823bb3cd19e7d1ec661dbb0ef4a7a722f8a2" . + . + "a82231e1b3a74e491c8a265cb4599e45b4be34055d30a2404a54d80a9b1418e6" . + "b4e02e8487acf6030fb1b6827ccc41d66d1c5468d5830022d4fe345f01a56bc2" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "67d9cf9d224db24cbf1a0250890272d26833208d47d66df06a7aa6aa29870970" . + "a82231e1b3a74e491c8a265cb4599e45b4be34055d30a2404a54d80a9b1418e6" . + "5fd3102d197b2599cb5ceb5d9099cd98fc475de2dc024cd26ff4366530b4cc48" . + "d56bf0f94d214df95487e5e222d53a64989e92a857f52e22e1233cd84a52f349" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bac09eec7e064e7012d37539842e2336efb92a59421f08363916d46a667a86fc" . + "bac09eec7e064e7012d37539842e2336efb92a59421f08363916d46a667a86fc" . + "dec34e88e7399155286a07596b00f05b416e466b6fb1b1c823bf86fb27fa7eb3" . + "639e8a2d7c347c967999f58a951de1fa29dc7c6a100759e33d977e7bdc1cfea9" . + "06446a4a8388216ad35430ff1552b8db0e521d952afc05420f750cd2963e4e92" . + . + "70a9adaf2a4df76421e00b859b92982fe2ec8ad560ddf8700ef4e5c459b3351b" . + "585cc56293702bf76ba8ba0ff9fc217fe00f15594ef8f82f3be41608c4ace6d9" . + "5d119a42419341e7a9a24d5189c13ab3d649183c9a9a8c2df517a0130a4185a9" . + "8bac80babe1363d9f730983f08602382deb71990fe20294a477b03508ce8e575" . + "70a9adaf2a4df76421e00b859b92982fe2ec8ad560ddf8700ef4e5c459b3351b" . + "c19866f9367dd46f262e7d9043ce2449ab1c75fe19b8a9156cf83fbeb3365f76" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "325e78b4a167da50e4f36a7ab5653ecb5fdf9c747cd54527e5a90ac321df5991" . + "325e78b4a167da50e4f36a7ab5653ecb5fdf9c747cd54527e5a90ac321df5991" . + "21519250c21393162da9517abfcfe4d7f9379997ca4ed68a1536b6e516a4a418" . + "33cd3b6f9a10a84f1e08bb3915d27a707f4f63fa5b5866d6f1c06241b96532d4" . + "dc38e397f0b4f3574fc9802949463e810621513695f522c6b0680f82bfbc401c" . + . + "48e5584b3c20650992eabe4556585504f7ccc48672d0ed50b86b103a53394744" . + "454d4894bfa152dbbd4ffb2be5f34db01a3d8cc2ca2ab429946ce242a0ff0d6c" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "47c7c8f2207a26c86e97bbe302bbf94aae303828d97f0ee8b4a5c7cd57b8735c" . + "264ad61c6c38a019aa3adce073f551d14147216cc04371d86814053a5406d604" . + "2647c2d38a0ef692012795423e827ccca981668cc4aa432472272e2fe90b810a" . + "b42184fb61741745ce3418c7aa7ed0c00f0779ac743439043270e4b920766593" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "408cb327ce3ccddd9cf9a569011f0cc7376f88d55ed0170bdea90ea595f8b9c5" . + "408cb327ce3ccddd9cf9a569011f0cc7376f88d55ed0170bdea90ea595f8b9c5" . + "7ed0cec8cc0acefbff172bd9f53c86c4ee381b770e81026cafcde27cd750d5db" . + "4e51ff7d3e4e8c76c5ac09f03f3cfd8a674552595f2a8bdb31214c00d88a2c4b" . + "44b065879dab0a5b9110c38b60ca91d48ee5c627bf8843620ff92aa115f4740d" . + . + "1299e7fcae38a2a4c8c5696d0b602756a180a0928ad3763f7e2dd550503f1d6e" . + "c91849fbf514308138a07d3e9717ca609db2f424d39c4a57152b9f2a37dfc913" . + "90e066af0d50ee82fe1820f171c984fb9c324d4f0b10b4b1180c7e8cd5ff50dd" . + "88d90ffebbda29f629e13a66d5436a28348c132c61587f758df7d094f8f7cd62" . + . + . + "43cd751e0b0142b4cb03b31b736419f04dd11ae4f6dfe0a8f61fd27331b05a93" . + "5078c93feffc49e6c84bf40799f14f68d73de70a0d60983c8dc63747ec1fd18b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b8d136dbef2c54a3c5a62fcab0ebad3537919f456c97765709d5a9bd146e8369" . + "b8d136dbef2c54a3c5a62fcab0ebad3537919f456c97765709d5a9bd146e8369" . + "a102b8d1e74525fa45cf9926c0c67cd7acd22add36347065b1919c6811b97206" . + "4abc8aa82c0eec1c1676eb0bba5b22f17a0f62c0e5d0d203eb22c11e5c6e2feb" . + "18f18402448e239613f46281c83b64cf04e63d14b4eb141b86d14ac92b32d1f9" . + . + "6bdaad34eef9ff9ba91e52d705bc52b7904a633c03025a1bcfeeb32aa45e5874" . + "7b37e339e7551777f15c0268145150cfa134bb7426ee0d0398cb895f1a051901" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "07b363f9a825cd06d0e5fcccdfcb10c91459e7cac80f049c74ead4a400e1b06a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2277282ca212cd0f22563ac6df2f9e9321ebacee279a4098a072549e31d38d91" . + "2277282ca212cd0f22563ac6df2f9e9321ebacee279a4098a072549e31d38d91" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "65ff6ca39eb282ffefb0d2ecc690e156cea2ea0b8f0951afa03f2982f8cb969b" . + "506c3bf54bede1f2fb03812476507c3ffaea58cce0bec6651392484b2c996b25" . + . + "6613cd225f13403487c32d1ff9268d5d341a8eeaee7cd87328ca94324d516435" . + "1864740109d85253403c9f8c74689a54783e7cc2b5af9ef4217f25ae73871264" . + "6bce0012271b06938d57231ab42e9eaeca17dc8fbd00e0dc9db4a977da61389d" . + "2e43189c33253ad40fd49819fa20cca23b75a89df79f08f08be1b889f3e740b7" . + "3f1031684fb95e9442cd85ba259f3e0a0345e81a08f4484b4148115707e6fd8f" . + "1d25bf701222ce3d4902af868b778b3ac49c65693a5418919df6f25977dfe74f" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0637a3cd66a903994aaa1b4c9733a201b66a07b59fe7a6969116338add04779f" . + "0637a3cd66a903994aaa1b4c9733a201b66a07b59fe7a6969116338add04779f" . + "b63c7d9a543df6a8a971590346fdc52a1ab8a338e3c7ed996edb0e6600b7b95e" . + "064c7db3b9e98a2087a122cb482fb5238645cea756b13b29b8581c3383a00f8f" . + "df7bde45a52492eaa68a2685815dbf9aacfdbad4909a0ff883411c65dd2adff3" . + . + "a2c91abdb1743983693136ca8617e4bfec17a2d28303ca3c825c03650273ea8c" . + "d0fd718b6e6919f97a52ffd0b76aa608118a32e95f191173ba160ac0559ae41b" . + "b956b1aca9ee9e30265dd3598e9146da1d72bbfc1864c4850a6577da89882e58" . + "876d8f99b3b88fe7ab4afa9060b9a97c4ea5ea405b2d2e700312c391c158f7fc" . + . + "abaf61c0d5f6bc14d063704f77c9b8d7296f19f137d5469ed518a5599eaafdc4" . + "a98d9b192eec17f0a504509f238d88e3990eaf4fb839adc29bc78cf326e77b65" . + "2eff022df1237b5975bbb7afc04e669b03598c527f7956c2f09778e05384b489" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "292d24cd3e53123747a32395b488b3bc07be026815743ed8feae61474bed2a54" . + "292d24cd3e53123747a32395b488b3bc07be026815743ed8feae61474bed2a54" . + "c1fa2443cdce35786d680f6c3b113e7d798d76ab5fd175bc1ff16dca9619c744" . + "ceca530084d01b67546fdd70ff1bcc49e0c3b80e3d2d9f69721cf2d91e0f2373" . + "95bd34bc35b6a45750c8f5d857888f578f80153a3c6079380123b69fc9543f35" . + . + "ee71aed8a6f007d1bc32153a8fe6dfe8e39cbcd769cdd612f284df6b3e6a4443" . + "acf2b7caa7482f7f2c10cb94f023c9c03562ef07c113f96fb94f67a51f646268" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + "f4447df816da685aa5f956bf10464aa6f41c252ad4692bb788098997f2ef288a" . + "df0251b269d89b84a71eddd9c29043697994c5b37d030d8c2da3d4bfcf5cb415" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d04c4eb963af10fea6274660537d85020bb78218e1bec3c74d89c6654a79c848" . + "d04c4eb963af10fea6274660537d85020bb78218e1bec3c74d89c6654a79c848" . + "8bb9f0410f3034286b95d49ed6ceaa95996874bf673b936d9ecb57d5e5d837e2" . + "01e992ac2f6e14c17d03e4e7e1a0abd5986d9f6251dde3bedc1138c6e3ea6219" . + "4b0be1b831ca412bf2a34cb990b3dd79892338c50c52625d8605ed5da03f6616" . + . + "5a9c9e95bf519b04b383359f5f713c166545d249d5d3ee321859761aac89a071" . + "2ba8cadcc85c63958a7d9710f0fbe9526c6061dc2d0547090c1ff0c1d3edf4f7" . + "2379d7b0f02dd828cca0d375d404c6a15649a568dfb4c6182530d698b98eab86" . + "36cbf80f9e47041ab3e20cbce0468f91bed91b9373270305e35ba66c8d0426b1" . + . + "a7cea3c884526d74e8d6773df30524f34f6c54e4cbac751556cb94733f8f7ba6" . + "e6be8fcff011eb15f22e17a2ddce39b95a0a3ba667f3450ae50ddf80f4bf2f05" . + "7069a418e43553e63727fbb69aeb7c3af6f96603ae8a67b1f4fcae4df4c7fbb6" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "344d949ebdf5c5f94428fe9ee3d7ea021b9d8348d10614a85c36bd2415966455" . + "344d949ebdf5c5f94428fe9ee3d7ea021b9d8348d10614a85c36bd2415966455" . + "3ac3b17a4aaf14e5ecfb31e305ff61194f735d8d17a94f5291175c355db0f2d1" . + "baf4487525b1abd505c6f2f0510a5c7e82988a474abf2a3964a3826ddde9c884" . + "2d65b52dd31d546b3e8e3b10910aa497ce6a1b84f36d1c2fc0221f330e2966da" . + . + "7f4a165d064593b943f66191b36d9ceb84ecf6925d5fa3bcff2d38d8601d700d" . + "5b772bce8c877256ad5f116f14656c6354e263e186ebc55d2278bcc2c0715600" . + "8805c833570eb23337ac9c3c7536fd135bd4871c1eff2b9d29738bb1aa7da115" . + "7a4161493cbe1f9f9c7fab1c8a21efc0f1a6f6730382c0a253019e4b7b03a8dd" . + . + "3ad2804f9285e82481cefbc7cde2397d3d3753531d9e4bec3db877c60aa147f1" . + "1ccab6fbb68420375de4a43e02a9f8f43c08a3bf1b177e45284e0ceec67b5ebc" . + "3ae0fa876fe160a33f2849b195b2d26c06cc0b73a191db38fec095b3bd42a6e5" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6e4325d203e3b1ca59a9b3e6a45fd35c4cb00451035720964f8263c91e957cfa" . + "6e4325d203e3b1ca59a9b3e6a45fd35c4cb00451035720964f8263c91e957cfa" . + "f87e88df0b2eb5fb8c0a04966d744b5ea41cb4284f2d1eea1423eff3b72a0f56" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "fa9ea22cad2f24a305c07e920fad07591eac290e7249903a426b9e67e5c3ba7d" . + "4a599cf47479cb73cd7d65487588f44e3c19303c9893cfbe68c0181b2073d3f0" . + . + . + "2277282ca212cd0f22563ac6df2f9e9321ebacee279a4098a072549e31d38d91" . + "49d6fcc0ccd21c12ac9cc801558eaf4099c6ba2049538f0daaf27d012498dc5e" . + "284c6822f0e279171593521e1afdbf38bdfe7cc8592afae05d61c0e7ec3ff9d4" . + "91ee03ea87c1d5baac0de433e35393b0f3c7356b54db9c7af55161a84e59362c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "d73046062d383ddeddbeac1f5b64966a7b67d9c221654c9c6cbff5e73ccbbe18" . + "2099c2d83fd687d085a73832427ce5ea4fe71f3ef24b71575a7800fc14f4172a" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c7148aa9b6bc7260665607985829824b8bb2e3b0933bb24bc2cdf4d4df7b7c26" . + "e2c10aa7a284d4d5d0cfac8dfa232bd183d37aef0798e2c9d0f90c3ca7635c8c" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "2296be71b52e39b547767f9c187927b83b2259a89650f1d697daba465019d7b4" . + "e9c5d8df7157dc93b146a7d5c2d2e8ad0dcb3621bae4cede4b003d78ff9d760d" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + . + "cf88324ccfabbc96dc26d36d20343e97fe5c085e4a9505b9237ae7c03a81de40" . + "64256180e5faf569f8cbe74aa10cb713dda06a02b5e85684eac0e357ec8b01a0" . + "dbae9e5a636d2a87fe44f6e01118cf2b64053ceea260ff4b65325d9700df08bf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4a2e3c4662c75e3735ed648d157bc067e21fd05bc7aa73c554f1e5717adf14e6" . + "4a2e3c4662c75e3735ed648d157bc067e21fd05bc7aa73c554f1e5717adf14e6" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "fb3db3918c5e55f3bbf84b915f7b0f52db0138c8fa4682ad01dfea1cf3f54498" . + "d98c205693ce4402c829816226daff84a60bbfa439900ab095392315901e3838" . + . + "3430f0995c7d42ebb5919e1c353da2eba417ce0b2bb42e383a1b3e9fc932713e" . + "26280db11a60591599d3a9f87abd789250f20a76b288f6ab788beabacd4bf6c6" . + "3ca77045fb69c3338c58c1a99423fc1079be92c88b4059f1bc1a26f7758eb6be" . + "28b3e7b35b0a485e82c6d2d01971e097716c17f75bdbc351120cd5ae214ec814" . + . + "a6829d2dfd21e154afb8e090a6372e1828f4c6f58d47b82a0bcd7c08f8e92b65" . + "2baa7866e8489f8ca54363bd5f198bfae187f0ae5c44ef319eb1a3100b97c1bb" . + "531830604068845bec78c39598c1ce9f4ba8ef8d2f2bab4f2e29b016a99f2a5f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f84434edc4805e26437e2b4e6d44924050e6bda06c9761f3e2d366040134039c" . + "f84434edc4805e26437e2b4e6d44924050e6bda06c9761f3e2d366040134039c" . + "4872bf85e62164507ea77275a62408c7350cc5e03a24a58f015846ca5c49a969" . + "1c98314c830f5ee2936459d28d545785fc0eebc27483052397f24b738fb4e2f4" . + "9108f9e7ad0226879bc1f8e961f2e6f09ab27e8f800c5de440355d33b098517e" . + . + "5001b6b57e777ef7791031c848f64a80144a4d43cf0b3fe8b5c415679716b4b8" . + "9a21308d50a5bb1ba98c0e7a221cd2d945b94c73bf49d6ee407c70da8b78c1d8" . + "dd8d0c9abc63287c03b96999a14c594d5b8fb70e694ce6b81a5db56fa432384f" . + "a47a6e747738c7617f88b800182e56aded71a6575c0f8b8ae6ecec82557472a7" . + . + . + . + . + . + "87c81cfedd4efb8ec8227db6ec4fe79eed6462ba74570467f3833ca76dc67116" . + "42ea64f8c42e3ae8fe8baffa61d173cc11d7a56661845867bb03aa7994231634" . + "cb379cc566c7e422cbddd3adb469cdca9d0e0daa05b0526f37644d9b8432d13a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a8b321e12544eedf6ab26aa55b8f61e175878167c848ca7373b6832e2fca2bc9" . + "74099f0e87890827dc4831a34cbe3c22c0bd95ad46147fdbc5ec747732d4919d" . + "38afb707c22981f5004e1ac1c97b98fb642ca1c84dc92f8971cfe3b498fc5ca2" . + "8f9e48ff5cb39f83a7dd78010435226ddb8d6c75cd83fc0a2d4cfe69d8081fe6" . + "e67a84c3a6321e1bfd5775548d66cb76b40f10cb624a332332db824655f28b5a" . + "537c7e2f57d0ee4b16416a9b98202de3b788cf6f64056cedbbb104f993b11624" . + . + "033b600a266820d14a66879ddf342ce60c090bc04a8c62cff0a8eba72a67afed" . + "a82d16cb9028f1f30894c3546a01fdd03a4ea03258d610ff4f52af3987406b11" . + "f71fd5b761cc410a2d2e410d8a7445603ec124745c365799a8f39525f5337c66" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + . + . + "6d6c5b64877a6671d4a21ed0cbf3d0cc9269c503f364f0fb1a8b3d4f2f0c3960" . + "0ae02a1d63a068fd45b787d19d664b08e69f4839f5050e5af26d22d32a33f2cf" . + "ef60b11be84eed42f65389941170ee61c21465ee870a2fb9e62db95b98a0ac82" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b2820cdfc503c52e67459c857b66198ea5337bc867930ee1c8d1f51d8354e1c0" . + "b2820cdfc503c52e67459c857b66198ea5337bc867930ee1c8d1f51d8354e1c0" . + "4d71a227a27bbee34c174fb418356edb690b58f2a5f1a801379a258701cfc4fa" . + "7132847233a4d9b42c12dae4081cc81d1a6927077f571a76669b43cece4ae6ba" . + "0c49dca8eab6862a9b8f1cfd89dcb5fb5732e6703cb964edee1cb5277885ca45" . + . + "6afbe7d7f1d3866a52c5420ddd3e5ffa70e03f94646a754f63f315f3ee3c76f6" . + "d4024716477f9e6f153c59f4a25ffec57b7cd3c8fe76b9a94ee5a4da0cceba16" . + "ca186640d8b363769283e5cc5fc4f909cb69b933b63d0a54a32067499d94862c" . + "248e91b35cdcd6ab2269a0186545a3adba0a28010840d87e0a658972c9e32310" . + "b9de3bd875eb396c8db20600c8646436f248afc1e02e1c9dcfa118d7e8252733" . + "a096f2c5ab62042e6f14dd70e1dba1f57a26078f83c838a5f8e58cb2468063ae" . + "44e0b4cb02fa4414e8a1afe0fae3f25cba7e5d93d20a302293ea8b185c586f4d" . + "b61f72611f85d5d16e75d10240d79bcc3bace79daba87e0e40b52bce6e2632dd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c7f6978da6c0eeaa4457247027118d2424481aa4267efa897966dfc0259fde92" . + "c7f6978da6c0eeaa4457247027118d2424481aa4267efa897966dfc0259fde92" . + "2aadbbf9cf9b646f3510acab4c47c3dad6394089af4dc0d12fa0dbaab7825c7d" . + "26b821f85bf6867d21e87496f81e8c632182822aa746229cc11d4620a7c4bfe6" . + "51aa1402a61fa5c07ca907eb940b850cc7a5363b3ea92cb22ed763f2d69ce6e6" . + "35dac259b779eb47dddf624b452ed31b55a221fa95e96c55d90069b31530ffab" . + "db6778d44dd140c60947941257e09806e1664a3e97081043d6483eb1c36a12a4" . + "3c34ca7f169d483ead36ccece593326148e3a15789b9e9fdd7414423bc8b72da" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4f51ca2e99ac62e1dadc4fe7e7d3e284fca7346859bfc233adb1292643ec0b6d" . + "e7f580c5ea386a966158c0fd67b68b27585d1c1a4bcba0da1844d888cf88cb9f" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "9ba0638c206c2001816125eec625bfb5c0414f4c04c6da172ce64d4bba479ea5" . + "39b1820b23e2d815c2b56e6b9d74a3b3ef83d9cad84d1f009c3b995712f06e24" . + "4722de82f7ad98639f73a8166329c915c2e1f7210b9a6ced38ce85d84bfc7c6c" . + "1c91a45490f78d3cd14b72e4a9258333f19e468e2a34741153c35ff7ce9833af" . + . + . + . + . + . + . + . + . + "85826337d89603a5b6d4eb25bdf5564f0cb1c06e1e40b23ec10ead44d94f1d62" . + "3dce76eff2e3c0788093df58aaa3b1f237d9940eaaf05c6a27b22a3871f388b6" . + "aa7e657bf7f7b2baf623a8912da4b010795e3b9165d10945f8cea588df928b3d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "47177d9c65af40ea1c7970f2ac80bf9b8f6500ccf766d9d4c2fb1c6dfd87ca05" . + "401d1a33ea035840eaac9874927a1e64114132325b56cd9e890b945913e3ed00" . + "56c1b9d28c5e6b768f9373e2f032ce60d042735944febcde273e5f4dfe1e651b" . + "eb8db46532ec19c124b952c5d8ae2daedbd3a9d3e423bf6e53a27c87e328d9c2" . + "cf0ff05d983036309fa90ca59e54cba3c68e486dd20645e1f886c500f4a7f6aa" . + "b99cd808d4df22e982135d5880a6b2e9fa9d6de7d17b3cf3c5be1e1fbd80afd4" . + "3966fb21c537447e7f617994d79c65d1bf7c86f755bcfd32acde3cc3f618487f" . + "d22db3de50d7733f32f3ebdc7cc39bc6f82f3efb72ef5ce0c4e6d924b5f55301" . + "be72c6c14ebc3b4f16430cdcf12736da541db4188da4d269ff5ab376bdc1cd2e" . + "a862dc73b987b2ce91b2cda1533b670f91d9c50c0f3f73f9096b1aa021632bc2" . + "6d49e41af21d8cfce9e96459a015a569acfed8c45fee70bf73f8270c91a38f9f" . + "78cd7537682905693d8a0c45b1d9d35538a5180263e95760bd53428869bab2d5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d0faad75b3ad049fa9e1206b62fcdfe539e8e32ded128661299260f9aec50185" . + "9d0a188f4cad070f6207d9d189f63d46a6d929b55df4f04aa7cd7d2fe6887cf6" . + "1a260eabfb460beafd70064e41d8e2a73dac7161d682ba5ec006b803023f7683" . + "4cb434d176c143a4879bb2e045a0ff31a662cbda19a31d31f64c660090de9737" . + "492b9d49cf817bc15d0d5b900f3b36066b134f2416867ddf913e90e086bc8952" . + "50c33bd49a2c174f02416b53e9a3f4f72d67bc7faae11043d806d663c218a01d" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "d03b46a3d13df1b2444b08d5c5f6eadc9f9952566aa0aed41970b70ce3637de6" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "08720c9dbebb87d4bacc6d2bc48b9ad92e4aefad13eef4a63dc255cafe0b5e3c" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + "5295dbece33fc981ca478ec81cf7b7f746d667e054a9ca36d375f1ff0be262ec" . + . + "ccb52b53cc29ab14cd2636d1ce5a90531333084e7e4ada4239904af565b70a2e" . + "36e04b18d6833047c1040adf89521599bf42c9fd7c733be1a7425eeffb37a684" . + "5e3440d595eb665f82477a41ac269a8afb21b09ae90f071f86f9f8793521fb92" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "c63608fc7507a2d64601b604fc54ce0147409fb737123a11fee3ce2e95940b46" . + "a2950a6798e1b92ecdd15e679d9d8f33fb1ccc4db44f911666502e3bd6fbd3c3" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "d9f1a2cf95c66eae396175e27390f90532c2b5eeda71574235fd7745932c60cd" . + "45e4e04f21a0503f99590a5899f81b066b74f22d9386d616a1f603cae67c3f6c" . + "5904744d7b61bd1a662f78456e945638a5fba4dd48e4ba5e2634f2706c5b7de0" . + "f4da9a5d956241efbfc09fd632de4d1fdd549f8b9a308a118be1bf0268f4cbc4" . + "5361eef998567e761c1772b34a52f7f77c1add87a5be34f30e3adf44acb3ba74" . + "21e2c59faf809f399f67b92d6274362093550f67431e0ad778aa8bf76315c79f" . + "2411fac5153110f68cdcc7b58b8fe0f623c948e3a0aed4b5f144c7dbd48fb63c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "097858eefce7126d78e1df5caf3e9f8383ba10b8324962b38fcfe7c81fb69922" . + "097858eefce7126d78e1df5caf3e9f8383ba10b8324962b38fcfe7c81fb69922" . + "f9d237d2af5a05a0b28ee5942c6f7502fd1d5e81c2bf58f9c4102a7efb1c9030" . + "0b18106a4a83cdb71beb85c42e8975a72f7e7d8b6b8691982d2e00aa6fa95157" . + "7521aec12d92e0851a6d1f2bdd2f3ac8213977373f5e75b0f79b981240c12b1a" . + "8a17454333c466cb65bdf81a07cd56ea4e60b94b5086290f7f86ef527cfac0d8" . + "64cc6b3c106aa91bf7e4b18042500bcbbc7a5741544dd84fdb47001006e36b3b" . + "43c51606c1744253527bb0bf06ac18856e3d40e790e11cc37c4a2e9a1aa392e7" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "90faa8b62771bcee2f948892fe17301465e6a82a3bfdb3881c870fe60194a0cc" . + "ea3ba69cfe628264f1c16a2384da8f13b924c10c31220434c3d6ead0948f9ad0" . + "9b0fa8c89eaac919ec013ae386fadadab978eadb14bf33297416ca9dadf5c4bc" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "5236fc7dc8b3c4e9997fbf8afb925ee2ba3b5b8563bd97012a02238c608f8232" . + "75a6d4809b5c6b17f034da66a50fd8be70c6a811c0ad42e5977022989565c9eb" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "8de240da0e22646d020a9820b59bad19a08260a89eca9509a5718cdb29d83c56" . + . + "166329ab223c51274064a75db4ab558502b5f04bfd04cf78d51ad6a320f60b68" . + "08b2542658911db8893750aa8f2ad7d7a52b1401a596621325a63be41fb817e1" . + "52c8aa7f00f7d695adc731293b40cf5e5dab2fcf3df5d2c536885a55845032eb" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eb22b873a0c43f93236db3748b0dbcba1a18b609b04a1c746a818f98d9bbabd3" . + "eb22b873a0c43f93236db3748b0dbcba1a18b609b04a1c746a818f98d9bbabd3" . + "3f5ab5935fe86221e7edfa4838123052087d01d7ddaca433e9614aebd3850930" . + "da0604d092ed4a58e15c38b08625812f2fdba4552ad922e941bfc7f7d9a298f2" . + "0d53f5a52fc5e9ebee2ef9ff0e023214b856e2dc1a5e7a9dbb7dbd61e4866cba" . + "65b6c115b8216f67de4ec898948337c62eaf5911071d2ffc9b0fffdbc9a935c9" . + "9745fcf620887d7d777486fa737e8a6b632830e920ef40b3a62c16c69bef6d04" . + "59037dcafee4ed94a3758fce6b9e6351ece600986d704dd2814835d35d641d71" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "254f5068d00bfd340fd3691218d7ec50428cf6642a6dcbf12e6696f383bc3358" . + "cdfb604dc410cccef0b0f3956bb157c80f0cc59674893ca664ef8e410ef75847" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "7a80efe9cc31367f604a3895367cd4414dfe523e403f7565938b36fe7e8b239d" . + "6fcdbc0fd384dc0230be75ca4f6e61d424bad3be25775dcaed827ea06eeeaae5" . + "c456463b1eb40f14fff16e6d09448c117a5231ed47a91d7fc1598fe96b5a1c2e" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "2183e458937f0a4fceb275d097239b4f30028cbf2ad4bf328f8205c20efb6ebe" . + "354fd63ee5a670e19e5e41780928d259d5844c014a82c299c0cd787436e122b1" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "3101983ace4b14bf4a29061893456c6d987b243245668a41456ebd5741d43665" . + "74619e5627e2a40104393b10617d4f894009f657fc104285db4a24986de81b06" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "262121720886f2b6420868bd3e99f0efc8d25ef1f3a3480e0e763ae3a7a046ed" . + "3101983ace4b14bf4a29061893456c6d987b243245668a41456ebd5741d43665" . + "14d73b24e48b5c87e8ee8a4d90861cf245029abfc0a284bc55b878f457dddb82" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "41bd1a269df4aa308a06c2be73fa59d4f22d0708242222c3955d22888beb7ff7" . + "41bd1a269df4aa308a06c2be73fa59d4f22d0708242222c3955d22888beb7ff7" . + "b4adbd99ce8909f656fdbacc802ac95e71519b5270ab7c6c66be07def3163e70" . + "958e6ac782ec97f13e17b820bbfac8cf4f2d75981213e3f72bc070d26ba175d0" . + "b5ca62749da13a0b78b585f9f4f9b27a4f54bf2de13334a90a1294efcc1a1d95" . + "25fd4787ed61f712439cea76399e0d98171c66175c6803cf0e4f539e6af46403" . + "fa70d27c385a0beb1c6ecc64c4e1e18f53934a16e87b4e639a32e461d0a6a4de" . + "4931a6887e34d08460b1595409635ab2ad40ee211bab9676f80087dc31eac93f" . + "9b208076e6d50bfbb1fff1c2b1361bdba89eed7fe5bb6bc128f438ab1a5e7245" . + "db91e2e5faae5fa5c9d781e5abc6024aee69c4636f7c89127df6c5a6a468b125" . + "79c70e7153cc86084d48956883eb48bf4364916cf22b27e94ec5e8f84d661004" . + "4129414da897e486c0111b3044debcff14fbaf3f60a904957235de93377ff144" . + "13fd08693d7f5aa98b57915e6e38167506aa434041d5983429bf4000c38cd7f6" . + "e2ab2e3e21f0f60203bf6aa2b29326cc3a474ddbc5bc9a03c0805fe16f30009d" . + "ceeae5ccb9ce0085bd7aabb41e22bf45e62764dc65854bd00476ce97cfd01393" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "2edcfd873facb10950f826a7b6faa987e3378a9c6618d5d7507d57f0075dd3cd" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "3a2192a0d6facf5ce67c4ad284ba38dec95794ff2980a3430047db72d71461cd" . + "c78e27bdf51e1d1000b3411c777b45bf39128799cd10506aa23fa9b9f86ce0f2" . + "0192910bf0f465187ceb2ae6af25dc7779cd7ed354ef4ba582772d4975e14b87" . + "cd26c3b757a7a7469e7c7277159b562c70eb8539684bbf12bf4e7edd02c8fc6c" . + "e190b58da30d9a84228492521cb6c5b30577f5f794a4441b02202335c6c8ba69" . + "e6e2afd8ce9ff880d774d79767ce2647b3b05302c5ddef809c3b779185b6a316" . + "aa07ecf7e958325db5758b4e36f2290b600a5903203fd571def28151b1cebf37" . + "e6ff98a657d41ea0ec3d1cac2deb6223730b478cd1da3349e2413d3b9cb2c58b" . + "22747fc054f4ac08285ca6cee6429667aae323d94c352d0611bf0396272082a9" . + "f8f9bcc4291af5c698dbac3075b48caf82efb84f12797cca31b565ab197b368c" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "b5ee2522859c0eb4ff1d4f2cdc949380cb9c303c4593b6e7ce407704a06d6125" . + "5d5f8558504f4ee2337a39404fa772ce1cf22586a032235135cd0bdb89822176" . + "e16581407cf0b5e90823f583ab87ea02b5907ffd894726277e01e2ef240b45f2" . + "39689bfdabf430c829199401f232f2d7d055b83bfead83bde820c9b14ebe4d7f" . + "ce7fe274361847ec6887f7d1defba54f084c6625d1ba6afe81c0d3c237b986e6" . + "3745747513b0546ca14f7397f6eeb872f732dbeefd11b7d3f8786dc1ec167a7f" . + "091da9667877a3a56a0f857f0ebec93114f10fcb901bc73945b57f67b6d9501e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3cc40331f84b6e59725c34dd19d9259461a89ff8f94f3980afb8a1e1007ef07f" . + "3cc40331f84b6e59725c34dd19d9259461a89ff8f94f3980afb8a1e1007ef07f" . + "1ae813080061feec1118834e008dd0edc01f69991e228a424b8b48a603184047" . + "c0c17505361ce65dc5ab19aae259f9c30d723131bf976ffe12ad242d88bb6f2f" . + "34a9045dadae4ad05b1172dfe7fc1a6f8ea5cfa70460091dd84dc362cce2dc17" . + . + "4073d5ea068327a27351bcd8e9f2ad7a2d041767380e2ee83c2749c153e2d3e2" . + "801c5e60761e9956d0ab1f5a6845d1b1666ebe15a10de29baf695510789ca3c2" . + "ee29b33905a9a0a090ed173c7bf201ee33e2183169c08e6b2eb56468ca0a1825" . + "4310c342407b96242ea3f3478ad55f0b6f071a58d2d7bc90c00c102452be9dad" . + . + "ccd95271d9fda8519d8ee49c132a5dc5f52ce62043c0e0aac08f6c29c39a3673" . + "117356fada5829f35a92e799b76f55168ebcff74e5b167689c6385a688aa79b3" . + "ad7a414c0ebca58ce63d1c394d6b6d8cae1756f77429d59bd853dba3169af7d9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be9152cfc365cbb9d4b024fa6443a502604b6705311178d39074c515e39e689d" . + "56194503ac9fae2cf6de79584b982c76809baa0534013f2e93d31be2af4248ca" . + "5123ad944f896dc5039f85b74a4218d58da862f6fe979d969cf3ae696bd42b51" . + "5d901f3ebcfe4b371203d3013e978c95705473cd365e686d26b1a1894540d72e" . + "eb0b65f49dd28708941d4b1999d62acc5d463f6589dd90484a8f14eaefcd3eaf" . + . + "bb0de17cceacd7969bce8b4b87c27f39095a59ae340f7d97d37dfc7e54c1e3e3" . + "5d60c742d169b456ecf6928511a26726ccb32bb51c06eb3a32336f032220f32e" . + "ed2add28acf0086c902c2053eeb7771304dc1b091687518ee43c3af6c4a1edc8" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "d9f6faed7231c49d3d22ed0127dbb2af4615c45ceef8ef86513534985e4b636f" . + "f372f1663c4c507ff5dc2cd3d98126ba3ba4bf2dce18d6becf07f997038e92ff" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "39fa2c10c9665fdd410c0c3074e91f2c4442b2ab14abb3e1996efe77ea5efc8a" . + "39fa2c10c9665fdd410c0c3074e91f2c4442b2ab14abb3e1996efe77ea5efc8a" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "8a649baba179e624abe4a9da0a935db15f6485ab3a15ebebe258d8681850be0a" . + "79c06c8278389ccb18fe7355d28a431f649c3a99118ba73cff71b277c5183b00" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "c6dd9dee86a79687e78e16abb5839f50e77ae0a25b16eec5dd51c2863aea2b6d" . + "ba9a2f0f45d569ae36a50e61207b3f2b7dc6895f34e38d0e6bdac16737ebb3b5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "b1b7de112f9b83504bce97df029f6cf7e4f89eae0d86bd5427fa5e8c0a25b8f9" . + "f5927d3eeb726a8c44ecf9d9b9e2714e071a0a4a8cf6216e5844f9b0ab9f4a9d" . + "5b7bec0a7de50082e677c6839b7deaf90bd26eff30a3947bfff1cdd912e9aaa8" . + "9d21270ddb54f1e7f3d16f18c72890d61af66151c8320a76fd662fa5a1ce5ab8" . + "1fd9846aee19395ba0bf4258ac126f8a4768bb7a5d2484e9d5465e2698e3beed" . + "152f423473ad6da799a5e3cb849c973af06317580a3edb73988725b658f5470c" . + "1c544327616a2a732d870e1a2135527c7bba79a430e5efbd6d7ab4754a4739d5" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "04c03ac1eb8c02b83e8f43d183de8e244ced0c1e5f7da74cf5a4bc52f2035614" . + "04c03ac1eb8c02b83e8f43d183de8e244ced0c1e5f7da74cf5a4bc52f2035614" . + "f44e46f689885676973cf12699963d53e4e7f1f3773b85562774de8dccf2d106" . + "c575e2466ad7cc2fceb8f45ad01467f3cccc311d1c12464c5126105a9810ccb2" . + "e66c98176ab7c01c2158f36f68aefdf6527596fa7203fc59f2a5fc6c98436e9b" . + "cb007c1e68b014b9605b496d4b48f802392b12eaf4ab313b0f7ecee5854a07d5" . + "8be38f5e6f5806b7e5c189a035e7f3a9ae8abb867c3cc8b3cc21f4de500e5d1d" . + "388cf7e3dcbdf2fba3beaa61c52e4a89da92569400f5c94580140fa7494eb5a8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "07321fd01f2cf906d249fc74629c3b149dd13b230b8e9e08e223dada833e66b5" . + "ac2916ccaeea1d362c6ebd87d19b6ce8a352e391b1f94446e22f99763881f74f" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "324b45b72d2ef41e2eeabc20ed7aa45e46429aa27455d7590801c521b354f348" . + "107203e8c50d16d14c3fc2acaca1cb80e4be0ad67559fbaefc68e0441fdb83eb" . + "ba8f11118438bcf612af3ad41f925365a633ce1d9713bdf1dbbc760d3e3d2c72" . + "7ad8932f0435d075a99e3a42f7a5901286d7707ff8ee6ad581034f47c6925880" . + "6256c06f8cc18d716b77b4e9dae233f747a672fd9bc759288c5c2faab7b647eb" . + "c0f0edae626dc8bd797fd085b51acfbb827af8fea5d64ff2f77c0c7ae990d440" . + "d720fe1925ddd3065dbeabe80fed20e0cd2d8805b62e62ad289219634c48288f" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "50c66915bdc3c25a3487f420aa517809ca8f16f5f1a7ae5f1ccff1b31da35e8a" . + "50c66915bdc3c25a3487f420aa517809ca8f16f5f1a7ae5f1ccff1b31da35e8a" . + "72380055b51a9295fd363599da14ce1560d890c2e0be00ccb57c6f3bf273dbe8" . + "72d70074b10b837f1c5e2bc5e91019645ed38d3a6ddf0beff9316503bb668a99" . + "9d753ccaaf1a230d9ebb8eeff63ffe4e89a3d8b7e6429c181bacf8fca34b5fcb" . + "b9e25c972ee756536b9ce9f07c99bddfd97669100d8b7d2c6abf91bc9b68c6e7" . + "2314725d64d909bacf551a3467d8ce798c3659bf3a92b647e0f026643df7a98d" . + "47a137226f7c7bf987b09f2d712d85d17554f8f01efe49f8764ed3b61874de10" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "85432d6299d9995130dca41c152f13d742c474349999cf5df3b21c1f66080b72" . + "d01f9897963c4094ad97e89f0cb23825b88f8779d4762387d4d64adf47d6a378" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "e0683d963a2a2f629307e49ffad3d95c96f2fa0e55d5c305dfc02c6c212c6928" . + "ab95d9723d4a873d106cdf541a9f8866371a78c08b0a70bb76dcf5f8abe66717" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + "36de581302ad9771c27e689c8a2660b657138cee873fcbee2d96a31c3966f1bc" . + "6ebf3ed8c5468b77ebd89636aebc7eeb61d1a6da75e20db3f40779da1aacb09b" . + "07e248f41afb299ff06f0e6ae6b928abb75ff10716b595d945bca842b3d63820" . + "dd849b234c95247666c075f18be9fe60e98b07bdb4e4a7b7d7f6babc26851a4e" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "77eb1bc74cf3b57598f5a87d61c8055c5361ca51821fd88420cdb6f60f522b72" . + "77eb1bc74cf3b57598f5a87d61c8055c5361ca51821fd88420cdb6f60f522b72" . + "60806b5696af482dd2902987c29dc62f2b4171426b6cdf6fe4c403e5d52af1d5" . + "35a5cb69e0b92c639ea5c9535c0e06813470ecdf27ec3c3cc89fe8a715a7921f" . + "401ec82bf6534d80f9be1c795b419f6dc1a9acbe150e85b98552ffa9b5e3927f" . + "cacc6bf0b5c2a800a36868416dc9924c71f74450c1edb57d9e8f161445346e32" . + "514bfd4d51d6d099ebf52fa1dfd7f83aa80bcce8ef2e697f4cb0a28cca249fad" . + "5150b6e595f24fffa1d00fa73d217df6c732f82c68d58f35c2480736edc73438" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "c9e7f3f2c10229363951ca42f821c0b20ab0346b72552f64af33562a78b09e67" . + "d847089e4181cc8046fce6ef6ef8fac50ac9cdfc35a1d3a900a458fc5acbf639" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "7fae4acef8d611874a03ce7170a07f98a193fb487a1753d39dd916c5da415879" . + "6a1eeb7038524273185ca4eb86115084d8ef2f709ae3f202d14b782ead53acfd" . + "5013e0453185a74d4246fcbe366b5535b190da2f9cbe5dae51e54a5bf0955f30" . + "71f99e8915bc760e73af3f71e7fe3cb74aa6f790510406060379bb4bd90df55c" . + "bbd19695ff3237ece5deeb718860b16dce6fe3dbc5fd098b58a5bb5faf673e3b" . + "766e969de0568adf9643c993ba78bb06d837f788a2b273b92d309ac96f544632" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7fe9d5b18946b73c0e67d40e24d2f3932ceb0c6cb3224cd2e9ffbc8326315a9a" . + "7fe9d5b18946b73c0e67d40e24d2f3932ceb0c6cb3224cd2e9ffbc8326315a9a" . + "9fb63b882ff0588cbcd49b8af89367c1a02b4155b67eb2fa6e29163cb275d06c" . + "5f2b35fe1641c3344a74a005ef1fc5b43f4b6762d93f2737d26f32e2abab39a8" . + "58c9e734ea284b90af980f1a27a213612721c154a329e17db205816a44261908" . + "395cf90388421517f27ccc36bbaccb6fb3ec975d4e5e599ea9e8f4126686777b" . + "769464204b0d789fe33a5feb44006448d972ae26efca67e140042609a86333e8" . + "df9ba8a387a7f7391d4a33c7ebe7cc707fbb6061276cb47c970963d2ff665558" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "f09260629e82c73330c57c181f56e5d7c080189b82f319b4173ff42c2245daaf" . + "f8904e4fdba84bd39257fe13ca8215fc8750490e8b84b6b9252311f9bf75e1bc" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "d5d9684b21a7e7a4235479d6da27ab5e5dfac0ecf27c0529c51ca6f30bd234c6" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + "9dcbda463f50cdb34c44230d6139a468d85cf28f4b865bfccb32abe747170e0c" . + "eba0bcc87d3a44b2b9b59f4bde1ed9452e70498bf3c66c1261c240688d63ec72" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "adab9cdedcc2f4e1b73d7763d5a524b45896bdfa2ad1090651b3ff5b57bf508c" . + "adab9cdedcc2f4e1b73d7763d5a524b45896bdfa2ad1090651b3ff5b57bf508c" . + "ab9b2c597092111b98fc2c5367ed8fdd73f4f205b49c0055289180fed26e7c07" . + "02c520261b7b6cdb9b15767c3589117ff1495e5c72db5fc5fc747b8e8fffd57e" . + "1d40f0564c55bab5f6d6be2001e2c4db0d0d0051e010d33fb192a4aaf263f0fe" . + "1a395e94ee1b968a53b8b98fa0a77e140b94e26721dd4a699f19a26ec17ecd13" . + "867db05adf30ad50df9ad2a6d8c5e4e0c3108d2e103dbd2aa267c1a6df9cf7e7" . + "e68890e0d1b7d3d383a88fc62cfceecd8747a9c4c84ddebea0726605a0519bf1" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b918994e0dd366a4fb4e6ddb857776f78315bb7ca8f0b3986423ea5edf7a91ec" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c25ef16cd07375861f931133aba2bfa5a6e16077e73e4b9c605460fed5ab0554" . + "240aa4063120c9220dfbedbb5907c6cfcb09fb53d21e7f7b74c0f7e24719684e" . + "be7f6dc27352cee8bf0460de0c86183f236e116b7000b67559bff8e5ccb2da9c" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "cd4d1065014e7c0ba45a58551eb13ff99f4f6e69a81af1d0dfd24178b83e9a7a" . + "1c202fe52b7c452d823ddac5a494c5e02d77ea97ecd93aed1698f169230777d2" . + "edaa91b66d053307b3b6ba29ea10d8aa781158b1a9a383cecd86dc5941335e38" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f6dcdf3ab31570aed0d74dbf25a6a6e76b918f33daefb14be78a9e1a08e29cd5" . + "f6dcdf3ab31570aed0d74dbf25a6a6e76b918f33daefb14be78a9e1a08e29cd5" . + "a624d68eccc80d9584303db9b3534b9e86a54f471db8061c11bf8f7b6727ccc3" . + "31aac9a7ff110140149b6455537dcca7c04df3229eed1f79d610d635bf7c18a8" . + "00c662ab64a4b8c4d68a0ec8cba35e2d073f0199779ffb355262a4c910d9ca75" . + "28a6a7666478da1a06dc67d0cc5680a01a1329d939f184d72c4450865204ec13" . + "150e8375a52724aced5759c2aff14d1265789b95b6ffd150510d30662e4c4945" . + "dca31cbdd91d7a8066d308335562fa8f007d251451c566cfc93748bddb932b54" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "e5e815d3ad9dba58ec0cf9bac8fab0ca3e6fe0a9a6e12f1a2de0843375acddd4" . + "ce8fee9111431d9ffda953c3ac2b413192a5747ac00c3f333642497ab5442a0f" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "e64dbf4a22891170d134fcbfd65ced9c362e50a1ebf7c8b7bbe653be4a1b9d95" . + "a15ba114400896ac34935582c67627dcdddc4ef14769179797732bd6444c2080" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "8353d05b9085bf17823fa470045187445bf5aa6033b3adbfad382707b1cf5669" . + "6f410e536c0497ab56efa63178d4e60a6a56bcc913feed75d39430086a2bd209" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44450d76aef787ba151cc83e14eaa4a40a89f62f177b69eeea99a321e210a731" . + "44450d76aef787ba151cc83e14eaa4a40a89f62f177b69eeea99a321e210a731" . + "e3b4b2a6181580c56a9cefc31144aa67c86e94834b0bff372ac44294f147db7f" . + "671c1b65e1b5222684a6c76c00d3cf77f2f6db18e4c6621d5f0061bae411f5d4" . + "d3a8e493093976005238ff80c333d12c0694b269a1c2c778296d043552d12ec4" . + "1df91fe6b18e5dab44d4dfe0749e225501d72f75bb35a1f6bd7c54e09f65e70e" . + "ae81ef7a6b15a259438e512c4bbac79b85d93aa583514ea9f8452d71361df199" . + "ab8c7f368032b860a5ab629d0198938b16d049016aa1222b67f9ff7f1599ea20" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "0076004ff180226ab12886f9002b482bdea35baacba532bf673aafdc10dc1d9b" . + "72ea806f0c847ea14ee43a3b5f34d7b0e9159f5e134dc0a758659ff26b0e7d65" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "0d8d237eeee2c38489712ead29782496db941fa191ffb407e0bc6f1b0a1bf579" . + "97d9805c3eeb89b14ad78b66011666f05416f74fe8fdcad6177eded85299d648" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "38611443bd7b744094296e0caedb44eb3875f06f8612db9e731ec2b416051c05" . + . + "012cdf1d782ad7a7eb9910513e50521fcef7af9a27d9595d4a8be2aa3244078b" . + "211c74faa20265348d9814be1f6e799d43ab2e8c8e1d301723b2021558fa2ca8" . + "89f16f2511f5e8cc212f27859328b20a5fe7a14ed1af6f93dab1c56c3d6d0fc6" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c2654354e42d28819b9ec4fc586d7c64ec6b59f54dcb7be37e8000b36aa41913" . + "c2654354e42d28819b9ec4fc586d7c64ec6b59f54dcb7be37e8000b36aa41913" . + "8b88613fe892720c7c76ab29cbc09692cf996e8e25b0b508750a4d48a8189889" . + "ccc82f409625e1fea9e80b59138f2b7f8206e79f7419aee5cf97724264392fab" . + "11e5d07c308dafe62f3caea6f99af8075db3a8829d803c62f3ca07b1b6d93eea" . + "c3c4ceda0df8306881a4b2e7c14117fbe9e80f12bd738f7c590779d669bdd431" . + "f318f6a995a2f82213f4e64615fb3618be458db5ed8dfff26b9c13bb099cfec8" . + "ecb2af6af74680d50542ed0875ff036a3d9acdb00dc84c0e49d3964be7ded60d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "9c1a044fd0f740d2766bcab2e219af498c751754e2b2fe81b8254f7294bfd73c" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "c094ecd248ee6e0e280206af1d0a7848ccd9005bebb223ab8db829cd7f2a0b1a" . + "93848d3a6dc4b487f8560cb0d16d0e2ac8b556b2948e25ae229093bed4aef9b3" . + "12778af8c8ccddd423e6aedf916b1f79eac87cba3cac76008ccacc38e6a00485" . + "deda9dfb2d0fea12f9c6ef3d1d827e0c27a3caeb6e116e68ccc56c24f41224b9" . + "5687051f58a7277ce1c9af78258de7496a818d15f44428a5c4448b7304a411bd" . + "fd992cf95aa543ec1052cbd5c85f4e721e3f868ea5ec0e7b0eabe1d0ed73fe22" . + "c43efcb5640e4aec86f5470e327e20fb56f4f389199ca750c8e8872909ebfac0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d8e576c2a3642dc4b9757114ad581ca2f711df71a60c110da8c16b8f0c6a48c5" . + "d8e576c2a3642dc4b9757114ad581ca2f711df71a60c110da8c16b8f0c6a48c5" . + "6609f500bdb49a5bb983750dcd28a349f4eaf2d27ab4b64bd98d73cf124b1dda" . + "c7358139ea1b17170fe4916cff3480f924bd40fb2ae30bbb7c5be41faaf0643a" . + "6a694adf05448f8e8245ccd7c4bd1283b7478d92a89ec3fddd2b2c1ad00ab934" . + "b7b4cacc16a965956f2aaa2d4b738d3e839bad4adc4949801523043bf72c2905" . + "80721dd4aca6954ee11794e5c3e46a191bf3c30452981ba7d38f7e8d1bcc151d" . + "0a7738fc409f3e213d67f7d0609d47332dae1c7ed5739b4d0f8963b229434a9c" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "1367a52b81efd86315e90f7019bb361c9ab5a111b26398a0868dd921b9e385a1" . + "28aebb464746d4591b30f8143f059c5effdf00dc774df72d1c57fb387248d3cb" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "3d894b5d34dc51e4564a33f0210aa971eb8036e35ad8da58f290001d37c7b49c" . + "8af8cf0ffe1dcba29cb2cd6c24fc0225c781968e869cf99a5a2f9b13eda74103" . + "da85b7c53352c254f1c8ab2503abd4560a7b7276288bc90bff4d1b094ce69e49" . + "9151f6aaa90f3dea503208157685049d14e5f3c429204c2d1a45ca75ab3d1cb8" . + . + . + "59f0f4784441552d6fdf45830cfe7abc9804f5a563e3fa65eb5f8d32670361c2" . + "e75424a17b7d2b43308f0ec770ce544f5dbd12ddc24a8395deb81eec2f6846f5" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bf4cf1fcc3f20a0bbab8288aae0fd06b6c1b776738285021cb32249410507357" . + "bf4cf1fcc3f20a0bbab8288aae0fd06b6c1b776738285021cb32249410507357" . + "92deeca25ee0c7b2bfc78decd26ccf6c81bc665de0b191faeceba547d7f7f6a5" . + "8ec96bed1520d1b98219d4db6360f37c485c5fcabe7f5e72f232e20c5a7a86cc" . + "e54ba9edb77334d1bce12685f5c9dbc8d23b5c1b934e41374b41ebe0480b7a16" . + "1a39e13eb31ff3f085374b78d8818fdd93d3a10e130a9105d89978c94bb79b28" . + "064577961cf5fe025a7fe3ab0b5aa630a5cf150549da67686d2c0348994715ce" . + "4223e97e50bceef3038e5c273aafd3f110d0195480b1c3a778a0d82b385789b8" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c67bd53cac498aa46602ea4885062f1449f6810c6d211fbfdbfbe48bce2b64b9" . + "5ef4cbb66620b2d83fd09d6610e858e9a8895d8b6a23249992b52cc0348590a4" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "3165944e4f085824920e62db310ec2eda9cdc2fa7cbee7c72f93a4f9c5123dc9" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "13c2036adfce72477e87e39bc8d7ea5996185f7f41d316cc97ee14119ee7f459" . + "de1efa7cd8daaa52f10cd06a4d134256bce6060edfec6520d0757e6b4eef2587" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + "815e1153981d38e21bda5a426a16f95b14a51b32433b9b27606aecaffd7aa23e" . + "2448d6a5c5b0c9bc99ee6279bc5820b8d257f056d0a7bd1695d3b81322f6050a" . + "745ce3593c0dd8877d83b2faf8a95045449d061357b0b29dcc19daa478f4f86f" . + "f9b7b72f8eb03b767a85ca8b6bc58f634d08d4fa6e28ec2fa98eb1d211ddb014" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "af4d6e4facfab468f5addbfb262601e0d1bf4ccfc379d32e893343e549cf8734" . + "af4d6e4facfab468f5addbfb262601e0d1bf4ccfc379d32e893343e549cf8734" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "25835c0405b42e021a9bd22841ef4dec0f0ebc3f613311d026f51ea4c38904cc" . + "3bc0c56b3e281322a67b4f9064d4fec7a45fe34da9276c18f31f7706cd63689c" . + "80fd03e6bbb9a184038dc717105c54c0abc53e3d711555996de05de6465a5341" . + "ba5d43f46d1d8c23282d7b330652e1d898fb0d978aeb584b6c14ab87eddaf34a" . + "497b6e62b111ed78be9217e19d85e616fe1a51bd25bb0a8a7e28464ad6813cb8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "0b2b835b2a384737263c5de422d337cf70f0346f58d2bbe3e38366217bf28612" . + "17d0eabb6b52617ae8c71b8441cd38c850a35dbbc69caf4df085c284dd0bb7df" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "fe3f67655e679d1922ff9e6ff1532820d42e75ae31e8a88a2e2b22992afecc03" . + "79a900d5c503a04fc1ff616f5696bfeab6a310084d79a5fe7d6426874f69e533" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + "35b5799f3914a48026f7365c2beda06c0b0ac5f5b88784a64652da30b704b98c" . + "a6898479ed78fd08ecd130eba18abb9aed7a7e26a1c068922b2e7707d8e6935c" . + "edc13d2101088c33be8eba73fd2ec6b78cb30a5c272d9438bc0f4f600d7b6b6e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "487085eada63b49f91b8b3fb047d02cc0ef78929965d78ab8fdc23f9f13fd21f" . + "487085eada63b49f91b8b3fb047d02cc0ef78929965d78ab8fdc23f9f13fd21f" . + "085fda52f6783def7649a762af5cb2b495447ee6456f60f1be948ed5a401976e" . + "bbbe5ebf47f2b157d7d2f46ffa623ee66a91509b33b06b5cf357c59aed1506da" . + "f610c935da94431fa197fb0af656fa9fdebde7b29873e0552bd7de639bd8535a" . + "10196dd6cb76de5f1b621ba5e4230f95c36ca1847c5e0ff2308477651f398522" . + "3e9aa6730b16a56c2b4a3fcd71ead9e8374d7b949890c7fd67969f6f8c87a413" . + "1bbd4eb655ec580e9f3b1e7e4ca009b4e6573cf73bc8b8637fc36260b8c8345f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "986f41e2b90121208d9f512e8e1c29b1f934015c63460710bb3202d27025a63a" . + "9c1a044fd0f740d2766bcab2e219af498c751754e2b2fe81b8254f7294bfd73c" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "a273a719f96409169d14b3e294f250cdac096e6c050450a0ee08bdcfceaf6ba4" . + "f06f1c07f56406ba78766bafee619f39a98facecd5f6c3056c19b1a61db77ab2" . + "000b1dd7bffbc6469689f06908736fda15adc5818ef576b82b7ce92b6d5fbb56" . + "0b3d87d6fd2e7e4f5d8283967cb51edd0862545164117f5149ddcd2ca779d518" . + "6b2b756734a791aa5085334a6852ba3ad5437e69ac0277ad2a2a9c76ab6d2dbd" . + "3f6737f3e98a2319fc79141e22e5c082d5cdaa84c3623b78db7fafb4f1278c38" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d9ddaae3d3e3021f54052c33604e6c4bb4c22025544b642cac9ed07374ee88bd" . + "d9ddaae3d3e3021f54052c33604e6c4bb4c22025544b642cac9ed07374ee88bd" . + "ec118142bf817136bcbc99ef4a5ee36cbd4b5201b243b6cdd3372e3eee27700c" . + "891ee0653eec4d68cb7b6af2979456e050736936b9ff92ba57225ed0f1d28a22" . + "e1a023db5cea786431c00d02baba82babc630a8448f129f592d60a66011f530c" . + "9506036121474991126c44160ea6e3e090c2394d852d1beb0401dfbd58557ca2" . + "db91e2e5faae5fa5c9d781e5abc6024aee69c4636f7c89127df6c5a6a468b125" . + "6205879bc1751cbaf76a5b3c93e3b893ebb24e9676067df0438c8e2560c23c49" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "98916f40f6d61a413deca0848a05c2bda4471976bb266e0e6324405951852c3b" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "89c663f17abe2d6678a6d66b8b6630afc28e24f8328e39581e67427ac0561a46" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "89c663f17abe2d6678a6d66b8b6630afc28e24f8328e39581e67427ac0561a46" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd44271237a515a573318c3be742e7ec9f32ae3d33864f7a781d8aa8b145d046" . + "316208918c68b973914d564f3958eb7fbe4eb6aacca26e7a6ffac9a1c5b8da65" . + . + "a76303182788273b7fe2b2b7bcbb6494ac0a499d17c21bdee3356d7eb4b33e47" . + "107cc9b461fab6e048e5c8225d98cc3fc4bb25fc2cbd80b5762ca2968d3adbbe" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "231f2c62c5983faec5d61896d480c84cb0dccf1cf16fbbecbf128c7af1981281" . + "f86eda35e2a79d0f28e8718ced16577618811a7d1a36226d6e68fb31846e92fe" . + "3ed9dc6fc6c2d765d659647deec369fce2ed22b28c310d228a9e5790cc18d2ad" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2a39a809d30f31525111adbaac87e7d0605b940a430d7ad28ff5dff294f3028f" . + "2a39a809d30f31525111adbaac87e7d0605b940a430d7ad28ff5dff294f3028f" . + "bfbdf5f1bdfe8257ef02b90ca0807c9f0c8e1c5b588a58a84288930223d5016c" . + "a50bdf6de6288c0a2f383975af7affada8310cda2a67e09aa43522c0951913c2" . + "8acdb727b985d9e47d5eff0ab14b698b420c58ac3120239ff2e5e66a7e424a3f" . + "862ac381f2bcac917ec239b2f3d8e0c5a599b564c3bc7846fff7b9220c516ea0" . + "e0745ada1a29a84a0dfe328ff7ad44fc4d3752219e144f1d6c6bb467b1039629" . + "0568fa05a3cec589a6b09a3d3f8c443f474b615d619ed7bd19cc3e72b991494d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "e9ea166625521fbbce844f497b9bd0a75bc1718fba650fe138f14d8fa2b50c45" . + "ba204c073d7e09c4323c5b9f00d0d606119f44fe604d8d15188bc9fb9f72d9e5" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8a226210c4996bd9022884cef5a0ec61d85b2f4d7729395e106de4fa64697c1c" . + "b7008b55b35bb3b2854bdac8f88824e348cd39c511b0c15cdf2ab78918f276ae" . + "0d6fe45d175235988167286637d78ac8f62445d932585cf869c191d8d768be8f" . + "edffb34810561c4e597762b62c415d7a41d8f0b2bf792f6ed9c3dff261c85800" . + "8a226210c4996bd9022884cef5a0ec61d85b2f4d7729395e106de4fa64697c1c" . + "7f73fa8a46917ed58d59d55a834126679f985e7461463b2f9210b40d0a3fd82b" . + "f1c0d739ee4b35e46789cb5f280b3d2b43abc56f867a61c828628b4fda47e7b2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2239ce2b764fbeb1cf4fc47afa4832d8c2e6f595a4500d9655b986c552cf4473" . + "2239ce2b764fbeb1cf4fc47afa4832d8c2e6f595a4500d9655b986c552cf4473" . + "be4f314b719f7a24ea86058d4bd929793877de5ffdec6d9ffc3e07074f152c18" . + "a6cafbcf167d2c772a2ba5d005e7305d0e4ae14cc4f99fbdba0fd9d0c8d40135" . + "dd2977e6a93d4f0d131603d368d4d267756081b47744d064314e901637808748" . + "8a8618725edaffe23bd9ad2c51e07094f309d49f316e14255cc2f53eb5377ad3" . + "2b6061cba19aba1729b35d53c9dc417b230ca6cd5a92e4fabd722c564daa58f8" . + "06c19ae7d619dd3b20787b3ee915094f27fd326d974d7a221eb67e4becf8a84c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "0a4ef44e625fee62382addcffc1e2d1b9d1258c9a0d1f5b5d9b08776fa5a778f" . + "f89b08dfca9725a98a7763f14611f1403dad34f90a264e60094d978cf9441b9f" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "1225b45a8955c54f00db89316609403cb15dafa0b720a71f5159ba54a53392a1" . + "0d9e2e2e80faae1b3231d7ea740e3d1ae6206758c0c4daec2d4cf5efeecdb4ad" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "854c529f94337df7fd347ea301c6b5af6589d083ff341c6d886bdef7f0ab24cf" . + "188ee5acfe37ff9a4b45523ac56e0cc15c53114c33df97b1835b1dc65d95eae0" . + "f4268aa5acd34cdf7a70389d0db312a7be40f1d66b32abacbbafa0e70b40b65e" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "92a9e5fa4afa3aff6e88323047056cf353644dae278c2e61dd8fb4be2f596a63" . + "92a9e5fa4afa3aff6e88323047056cf353644dae278c2e61dd8fb4be2f596a63" . + "79d88833058183da924c88a3ec614cf739d2caa08db09e6e482e62bdfd3efb26" . + "0cd4ff29bbb051e18e5262f33319efaf141eea30e0b6745cfa6c1dd8f89b3c36" . + "c5bb88af340d878281200114e1008d56687e46ecf99839a65c5a2bcc0a06ef81" . + "d58b87ede6637b32103cd62938829fced4417f61df0ee34396e965cb6eb4cfed" . + "1b9652863e080027ebe182d233936a183fab4203df717365a5e0737a11b8c20c" . + "eb08951827b819d2226b5fdab0738cbb41c9f813c2b1c70ddcaac363ec70f271" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "383558b203d36052006efc3af74b90191a90f794b0c9f91694bc1ebe6ce567c3" . + "78683009050a1a9aab669eb125fce09268e1d1b799ac81be6c35c6c1bdf7dedb" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "ab08a7087be7c16e2e7100d4c9bbaf11514fef897f40d54515b741e9bf425b51" . + "c9bd87cc415fca81ad1c36e68d0844b0e183f55626fcabd6acd4fa611ec4a89e" . + "8f9e48ff5cb39f83a7dd78010435226ddb8d6c75cd83fc0a2d4cfe69d8081fe6" . + "2f840ff2c5898c89de2cecc763b87afc4e057f7ce69cef8257ba82bc014ed5d1" . + "dced1add669f237f50884283229553e683f3fb6cef4a3868466b14496655e85e" . + "c4aa072ffaeb1e32e03713efcd3ae7715391bc6e030085a0f89198245d5765e5" . + "4e75dfadeecc294ffbbd950cdb8fe1780c261df4112eccdfc943822c40baa122" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "93f23e51762abcb49de622c4c53799d88954ebd7ad3691097a8e31b4aaa456c5" . + "93f23e51762abcb49de622c4c53799d88954ebd7ad3691097a8e31b4aaa456c5" . + "18edf29a277c1fd577055b7b226b38c839c6b06ddff6e843088f85f81c691f21" . + "caa46c67c8363a2a78c3331aade5ab7a7373fccb0f37f9919c4da307f60f3c9f" . + "328167c3f9a5f9d8672f9754dc1166edbc52d6b8cf3624bb98e19cd83192fbfc" . + "d5da2a2518250e2de83d78df8fc0ec7af889303a1a5719e63e7f9895de586ff9" . + "ffffe3cb90227a0edc46a8c25ff469baded6aef4d25f023874eef6b8913ff0be" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "5c66fa2cc8b2acce83fba9cc7a507e94a27f588611f6d29283a9c788eacf036f" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "4550be82ff5d0a2d5b1f0817167b18396a1c4a9f515c3c6caf30d0f924973de1" . + "0d0bacec0a38085b0c9322ea53d005e5956c78457e226dd9fd3bfde41556ed04" . + "2a8f01402587239b8dfbeee1be04159b7b23fb3a802396875095f2cfed4dc221" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + "f4e768c1297a3f17ac9906e8d0800f84052d56ddeaf5576a658f92e65f20875c" . + "0fb0c9d277927cffcbaf2682ec6bc7b95de338b500d0b3eadb096629d8860dcb" . + "83db3def644feca2b740bc37760af4679a234ebecae343e2bd167577ae7fc2a5" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8b0aa207c5f259f65dbbd77c72b62291787aaf1cb60b2e4ca0d8806c0ad1dfc9" . + "8b0aa207c5f259f65dbbd77c72b62291787aaf1cb60b2e4ca0d8806c0ad1dfc9" . + "5934ed58f4999b5910a9a43c46257b09c2fc7978f14150336f28c6046bcf4c4a" . + "0c61956115d2b23309fb6e10efd76b27b998fc9719c394c1ce4c49a9122636b3" . + "a5360c268d241bf2b0f0d10601d314f6b75707dda608525f5388a9b257649aae" . + "ddbcf52271034453b49d85c3ecc66332e89dd2373f4dee22a48954df37480066" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "e7584f0e48666437e24902042d1b69759f0511ad9fcd323116519453928734b9" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "0414ce2d6e199230ecd2ded69973e9bf676af09553757ec955df19a924fb37f3" . + "2838f761ba98916f108872860ecf2edff0c3b68a301eadc323bdfe317defb197" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + . + "c494240d73bb943428d33c6f7b140a1ba2fbf7392fe7fa9c6d2d53f9b2ffe2d7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "febdfdc900cf0557e4dc7dafcab45b2a784b98b3b186ecea4f37e12df7cf3d78" . + "febdfdc900cf0557e4dc7dafcab45b2a784b98b3b186ecea4f37e12df7cf3d78" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "5645c3de990cee00128ba66839e72d1b2015eba499dfa0c8a24c886e212df8ed" . + "e6f3fb5e1958b1ea4c7ad18e0608b0bebdeac7cfcdba01135ced0c94734ff3c5" . + . + "a509a4a0c474c6a575cca103f54a694722a41a5b754be3bf5f79df3e34791e1a" . + "72442e20195609d4efd46479740b88bb317a93f2af2522e46310349c275e417d" . + "b825a05f925d646361afbd06cdff48175f4aff91e3307342bb619631305ecce8" . + "5bf67521704918c10cc557b56e057f1c9e4361a11797f60c38c64ba304463b02" . + . + . + . + "080017a129ee4229f6919b986e8f55d25ab821a64027a6e7bc5cccdd8dc89717" . + "29dfa03ceee2fa05d6ef13bf0fa0b7ba319b9aee18f852e5028efd8fcbf15a37" . + "7fd9d9ba0fd4ebbaff3960a2a5350475dfa825b48244e0056c50dc68848c4963" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "938ca781e40d4eeb6ca0dd534d675ee635a74107285d7e2115cd419539f4bac5" . + "b07e32e0387f4d354d9d075e0d553805a87bb7bcc3c4d5ffb67b138deeec8852" . + "fff12018ff27288307388d09332812e68db5acb716adb043d7a46b10546aca2a" . + "41523d1889c16b9aa7126f4c481b125c03c6d128e6de3e11ceb4cb6b3a7ce7f2" . + "ec9ef9d31c5664e2f5085cff2f63208117d9fe0eccf31a7d25711e68de192f1c" . + "79fd2323d0728bdd9f53a1393a7de82f46d6f6141d2f7dfa4ac57d68d86d152d" . + "c809a8395a4b51cc947389e010d337361fb899c1e6d47b850efd14c6285c4a78" . + "cbb88a9d1061e99d0bacf2e86f51d2a7086ccf60ffb56c08f72379c858d58695" . + "1cac2ddee42dff7502d58e9b97fd4c5ffade2fa0d4f622f875cc0099ef76310d" . + "bea8b87e549af42498cf1ebfca8b80b23e4404a8744179491e5e68bacfad6e99" . + "21dbbf4eec020dd49b1f3cc66060a9f134c3c36664c16c8c756a71e6554112c3" . + "e12ae7f542307e62c69936426f924542819cda515f05622cdafa8b5af1110b28" . + "00984f09edda5f07e5e8035ae024686ddb1fd9a2b42b3ff887417441f4951d5a" . + "f1c6b508a093fe0ec7984d80186824a9a1a5f9ebeeb801c4a13e4f99452255ed" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "5a79b0ad2a9a06b1c6cce76eed7a0e9ff3fe325773e3fcc5bbd45c53f5556222" . + "5d2abf010ba190315c58292d522dc5d11c891161b2a585fb695775136b124bcf" . + "f227cb3fe983686f37d7b5ef48e475a75a4c46643adfa1cf4c8b8616d169c24c" . + "afb58e1afe619c11058b9f007c7aa96498ed92956aeaa5ff39433feb4f8d0672" . + "60a5b5e6160c99bfc4026d921e3d878501b4c85e7f01c1dc7442e8c2f30dd90c" . + "0da9138df218625768290fe446e6bdb83d0acb9041215be2ac69cefde4ac7258" . + "1b86fe060dd6e26c2371dc06f46dc5d0a73e425f39b9d27b04082530c9dfbacb" . + "f58ed5b7129c4a950c30cc14002461199c1ff9214facb189c0d37dd391a4c0a9" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "88c45372d1c97dc55daa22ffb6951983317bf3abc21bfb0c6ed8eb42218df4f4" . + "7f49aa5a9b802e73a3fb6cbd8cf919ed40e189218b86a91f125a4470b48e6577" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + "fe18d19b23496f9ad76bd24316a2a88e33a19dc6b00d7caab79934e5cf7787f3" . + . + . + "7fcdea83aeae7097dad38d46855d8d851f049cc78263310bc805477f5d21f7b4" . + "5abdcda15d39b0bb39d43a652d9ae53260268ccefc0d589243407a19e063c8ed" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "7bf3afed5fc5920312bc043cbdd354497860f72e3b882bf876364eb8600b3844" . + "6252a7b3baf8b101edb30aa3d228b8e42c403ffaa0c800c0821798bdb2379a29" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "3d9ee26ab2a67f9608daed749bcbd95e1b6b1b5b991ef6b982c03a53a8795c40" . + "f59cdd1704710ca957f03f0b917ce84a01123dfbd7fcd7900a50075eca7a170a" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "dab6fa2c3d396bf723c832ac2cf197dbfc007f0f403e8a5ce50efd248cc5e51b" . + "02261612945353b8cd2073f80246b9959688287a425989a8456b1a739ee0ac55" . + "6a12ceaf75a7f8282f7763ab2251c20018677ae1d27c7f68f512ab8529168e1b" . + "4057d2fbb029ff01c0af74c7d13de8efcd71acce9df1a940e16ab908b4a9f014" . + "8015aba7e35863af2005f14ea1c29939083def7eaeea82002266e47698cf99a5" . + "4cf6467a7aa97322672d3731d487792ba4cb0dcbe3b8fa8b08b3274dde5698a3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "9f537e6fb799f427300e3ece16ec1d55122196793af5ded034868d30c0af73ec" . + "39a4b2a812606e6f42409177de8b8fafa9a6a16fe9fdbcfdd0c8fe728d9b68e5" . + "db72e0e0705452e87fedc65e8cb84242d2f1fb14f89bfd407fe80751035a2354" . + "c1e108fd07a7bfeaea3daa948909a1e0752cb5d8f52d4a52cef731eeac583ed7" . + "be42de4b8d570bc21366db979692750be5f6a5141479c4469faa3aecdef974e6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "437fa225ea255dc8a17d36a828a3a1eafdd27f076d805c3d084674eb0bb63e14" . + "f1d19432526d27717cf6e16efd427223661ba3327ea8e6d7b79027caa42782d9" . + "2f90e7d651a611dffe7a36d0bec7cae392162203b0d190809ba8d7a540f49024" . + "2ab32e2537f4b24b19c7648d7dcc23f48605b9c0adfe75687c15cee13d18259f" . + . + "f544b4db68168384c772ad22cc95c2882d55bfc0bae0cdae4d46894ff93da4ba" . + "7e2bfe2688f2c32549c51e6715186937a00686a974a1eb925cad34d87d1769f6" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "ea0dca1098ddd905d069405a26c976cff4cc268e10a0f77ef41d930f36424db7" . + "805b981cfd71f1d20fbba7275285a2cf360eb1b943a6b5ed313fa6c632643943" . + "fffd6154243e0002129aebfe42300b3792d426f646c09a2dcb6b6ce61ee13eec" . + "05b57b1046fe2a167bb06d827b7293e211648e0f4654f476eb5e684fc4af6ae3" . + "554fa914248dd799b42a2e0466f7d7d30a47bd6fe6eb1cd6c878df9430b3ac23" . + "9397688c91b6c95da3df971364714427a2aaf84dd6313c31fe9a224176f5521a" . + "f7e07adec82f9aa02752aa06d3ef1f5dfbe9e55405caaa018b44f50d751f3964" . + "0261609f6d1d52070f40c7f838c253a622c6033a2722aab782923917321a8893" . + "69527e38ce97813844395c09c95d82b3d32ce4c73a9e2bbdb22c71504f178152" . + "b1285d38abfd9566ca53dc9e5ca2d29d90396e331e0a3403246be777c101ee5b" . + "a1a33ac2a6067e0db2aeff86f803f9b95822c70963d6f075152b97470984002b" . + "c11222283a941e6405eef57cae730e4b61b9a270a67ef5d3b895e21c6a0b2b35" . + "8cb60bb455ac08b005c8e219f1a41f38e4f913264e029e3fccc4492443eaced0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "37c7c311ca17dcafbaf85d5ed7f4193fa926b173e35039f779aea0ce49204433" . + "b918994e0dd366a4fb4e6ddb857776f78315bb7ca8f0b3986423ea5edf7a91ec" . + "d35ad397d2bf0b6d88d0a085039aadeb00f5ba2fb156ac0f3f134f3721c29cf3" . + "61705750403b31a9f294c0636245629f3f143c3f172f029490066b70ccf09722" . + "7b2f825642cd557aa497797c990549847603716e13878e0e9e88e63685f94868" . + "a3c7b34f8d5e643b91de39e71efc2991a690c58d5025dc25b0f883c7b11eb926" . + "32751ca30d8f181d6f912f875dff578aef22e99e892cab94aecef1435114694f" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "c561ddcf655c9cf1195594c9f972815d2a22a670d725b91f8641bab684ae4f0c" . + "ba737332e049c0f0e511d13135400004c37f9783e3646567a7f0833a0d2b4e4a" . + "ca9bcdd6448d53ad56bdd570ab3ca5fd99b05c0e5bca4b67a893c6ed28019078" . + "20b9be7807fe9750a6e36951f2dc43eb16dc1613cfced3e62ea0b0a17c791619" . + . + . + "d25bfee31d738ab433f65657ec77a8cc48732419a2c0db8e049bd5f42a74e769" . + "e0a4dc6f8a6cc978f8aee749fbf255e5778fc2dbc137445c38ca91ddd7bcf652" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3ce6b309b40c5272f91bf1061c27b68d338b3627e2966c7d81865d1f928de0f2" . + "bf5aa404c90cc5583cf3a3f24a2c7a8def9e89cbd0830b88ef292f769378879a" . + "e6d65e7101733aa0e3e9d9b2e37b7775a04be8ac962a0d64f79d76f00652baa5" . + "94647a31ed4f9ae12cafbd0b0badb4aa965d2f5b4722b807fdf3175686978cc7" . + "1367a52b81efd86315e90f7019bb361c9ab5a111b26398a0868dd921b9e385a1" . + "60946e5d73a63cbb987f3cd3f5bf6023fdbcd731c4714034f7c5f5d28108410e" . + "ea3cada3a86001f5a414bfe5ac67a5a71e79fdeacc79c1706659558a20fdd5df" . + "8015aba7e35863af2005f14ea1c29939083def7eaeea82002266e47698cf99a5" . + "eac6c5b44680387c5c0750ca98f9fead24d56a97dea4938812ff4ab3ab520fc6" . + "11c43fa954059f2729348073cbf59368d2acef63791ce0ac7198744976aebc02" . + "0278837ef2e9f8ddc9cd33e84014da020e3ce00fcaf6021f0238aad8a7fd882a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "84d2d9bf27cb0fb1067e765e85d18758f99374e24d5c02ba572cd7044846fcc1" . + "834aa4669137329c1c705aa9c10d6565bc8230d51ac6ec1c3ac2f653be5e7c5d" . + "c06f27aa0e900c92749e959dddbfbbbdb5133590ec5fe984d97484c5e703fa9f" . + "90f195407df67511e6752629529aae62559965059e972cc8dc5f26a260dd1369" . + "91c746fd8dd077fda86661912259b1252a2fed99df85e115b90e82fb799ea21e" . + "129873ee7ff3d1db5108271f71504179512a607fb55298b807ccffde4c8072c8" . + "eca213e0182e6e138d7c28f08b8fdb957e9620c6ddd24b25d5089d0f72177d55" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "715dca01dfff245bec2443d436b41c689472aa154e027b86e5a2daa8b825294a" . + "612061958792cf1e664595ff27fa93454bc9ccd40aa44f7df7a0f2cb6aaa26d6" . + "78fe9b33cafe58c172914578844edb2fd35543ea84f346b4fc6969012eb915e3" . + "edc74bb1df36118f152a351d15edb1da87e06599ad9bfc5c2f51c7194cd4229b" . + . + "25eca35d009a478e677944a695f88a3b0eae292b0807cb95257b660b60d0df2b" . + "2c41e4bd30c0443006d01f979dd0028685ea78554ae0f16fce7d9f559529b4a9" . + "1f441a132a66be95c224928294cac2fbe374823b050040ed506cc6f93b19f41f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2d36d078b3b6e2a61d2aad900f8829372358fc00fe5dfc846a1077950b596298" . + "3a23d72380af980c949a6f3eb2e29382cecc06a2755a579c88f73f9c402dd3b0" . + "91a34c6c8b28bc1529b8ff0af87460f9b16017338024f0902e97ff6637b6e677" . + "1bbf8b6372a4b887469acff58fab9d460a55db768f9ceee12d54dc00ef58bf84" . + "58f07ba619bb848910d7aae37e4eb56d95536d48ec390a8760cb312ae8fa5bd9" . + "07048e687ebb5cbc975b742a04a1718033ea2c89c6418743ba744d961f00350c" . + "2cf2426ccb6b9746b17be5fda8feae381cf00165d5abcb63557cf8b196241eb5" . + "23149b0ab12a94462f656f8b0de8326d783a251c41c73b090b6b21054951fd02" . + "afc7ad8d97ae719bcf84034367b061026fd443323b21976cb7ca59c9c637a979" . + "2040a68ec77cab5962baa9aed004ebd3e708567d9ecae93ad1ebce282aeb4d84" . + "af0872fea3f8044d27341e3c0293123e7e7718452f0ccd25e8dd491f7e0385c9" . + "6c517a2ad05456cb853f0e64944b2a4210a0d153b45fb84943e99f8b0dd984d0" . + "3ca0dbd4c3411ad12aaedb1e940ccc332d6bb17114ff2bc031eb6bdfe243adab" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "201c5f0df7ce17eb14a7a8ffb0d790af77260df274121a52ba8e2124f1d0f61c" . + "c58e08732372d81210a1582dd32e3d91f54178255c996c3852832307abefbeda" . + "93813bf25e984f05fc6ccbe896f5f7231e38e7fccccdd659ddfb87c5eaf42978" . + "e9ea166625521fbbce844f497b9bd0a75bc1718fba650fe138f14d8fa2b50c45" . + "8f1d9034cb6f6800c1ad5265d104ebb251d3cbed66967e355a9b6ca9c4f19554" . + "d49013d559db92cded82c9208be5781f09ab634aa9d8d3f5ce41ade9d434ec10" . + "f320c18a4f0c0c19c3cad97ad52ae75fcc7cf3adcc96a46b5cfb848ef2a43727" . + "ed1cdec080cb7e4dc1ad1b72a9acb9f7be1e3d614500f28abaa053e08507bfd9" . + "4654fabeea7e4c860e7154d89d6ab3621c1974904c1c7665917e1010c11f2132" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c41f9a8ac0feec25dc9341320b44f1b3e22437fed88720081877adb6ce826bcf" . + "56ff0d6b55ea0da41decd2c840e4242e7b4301940a87c23a63b0afff13f70b1f" . + "53f93241a48932ce4ca93d24667fe7531030eb0351d06e433244e49953ba381b" . + "56c7ce9a582b17dd9e07bdb687cb55c6c69d5cd0d97276a09b6134153ea9465b" . + . + "70869d2b572254b15dc8d64fe9ed9d09881272120b4d87aaf8d721e71ff59869" . + "3ad61f6c3ffe2e65a914eb813ca64fb4b7f5e847840db9506c179da445dd0b0c" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9457f8c5a65d820d29e001e2cd79b30de8ef3c91201a116030764a6122ff8e59" . + "4fbe0133f3eae1a17b22e142fa80c5ca897923505f745fe6b413fa978d6572fb" . + "e75a859e75110e175055a9cacf94c55f993a437a5121518a200721c450abc6e2" . + "7e32bb7e8cb833e80f22bc93caef8f0a403ff61d4849a275081241bc7a0535b2" . + "69f67400407319624abd8b6146c1ceeb9c7ed9b4ad7608308f880fb0f889d7d0" . + "44cf6b521f87a710cd993495258f1f0dab4d8af67b4204f5c3a9778cc8a0d46a" . + "fecd2c4b9b718c9171dcfe527ccc99fff7a6b2a406bc67094e4a41ae0f8e43fd" . + "929f28cbfd0a962a9bb2fa1c6efe09a4b1fbabdc8c17f347b50d429090caeae8" . + "92c6ceff791058fa7b5b3a533b350269e7f98d9f61d2aa767bde14792b493b65" . + "d4b8d9d15c6fd332f1de07bfed6705e1983951aa6b347a902574dc7b51d6c9b5" . + "007d28c6b291dcbfcc96fac45362a379eb51901ebec0c539cd2c63adb9b232a1" . + "30bbff51b0b191ed44b3fe9774dd8c59d7a80e71ba8582d783a427895ec9bfff" . + "1fcbefbd02948f3065613999ce3ef1db9a7add35314df9dab0ebec0c1d645b03" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "e93a80f80c4a9d975b683d39ac7a55d612716aabb3922769de8ebcdde6b0e993" . + "35ee6d3e7cbf86ab2e2942007822f125c1bd11a7b538a9d880aceacda4554493" . + "d701365794e2a91c8d19f5acee8706362d27caf2aa59f09cf124d79da871f739" . + "6ff55e5c3efec242dd3acd61e806320ab609526d878cfdc2b783ff2e8d5a47d1" . + "2c41947f7eaaefa88c17b8fc15184ae96e5bcabc7e28125c940a6c7ee11eefc0" . + "357f40dae0efafa3e92c59e196dab23fdc994409a0df79577fce1811a7d6a69e" . + "62b824103aa16244c222e840e213a6960ebaf65abb51f0c556ece47c9d45a2f5" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "cc00e0181a5ea99616ded34126365cd55e846e7dfc086d21025fac831747c480" . + "339e7d780ee094c65b478eaac904a5b06e372932ba59fb26c2b45280532e894b" . + "6b0bb66375b9ecb8851750f65c7c77d40a89ad48cb3f10c899efdff433e55ff4" . + "e57befc2ced1ae286b3c6d697f57654836992af79b5830193847fbae283f36d6" . + . + "cc00e0181a5ea99616ded34126365cd55e846e7dfc086d21025fac831747c480" . + "db248e57168cc8a3c28b471bcce72cc0157b0d843c17791995371b54d2c1881b" . + "3653188fc720269e17d4f102a376fedd2cf91c93df53daa38d1e45c966569d90" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7a6711eb9fb0b066e948d0222dba910aaac23c0d807bcb57e0a61ede1493aed2" . + "44f9e7188920a9765a51d32a98ce26a03a9cdc5d4450d8ff46b491d5baaad270" . + "c4ab91319e37e29920955c7ae9d4fb53ffe5a5acbe3c736a9199cb0405044f8f" . + "f0856fbd4a434d2c56d6a54db2f1842a418a5281f1e1a0aba3748b223e7c6679" . + "62668ee9e89348eb75cf8e2d4bf78ca1f0b45ef0b9b2770f2fb980ceafdfc696" . + "c67bd53cac498aa46602ea4885062f1449f6810c6d211fbfdbfbe48bce2b64b9" . + "644ab875263f893551e186a665f1b8144aa997cb364db772f07b5ca9b684a3b1" . + "4cb7ddc4a688918528edef6ccc24e7bb4f9288dfa0014d431526d5801631c6b0" . + "e1e90fe5ebb1d321eabd8d410b64b23fdee0d2314b66b49e2eed35c1b8fa3a74" . + "178e78f33f8bb1f0663307a560bdcda1cfd113b36e0beac75f251919dd066478" . + "86edf76b8c9ecb6bcd436c56a50f7d2a37f4decebfafba19e42b3b10a7767643" . + "a0cd71b74696ee3d601f1898c4c61d34e6da7637c75488a1c0063461e59a0617" . + "16ab0b6109caa64fa9ee914256f7664a6c98a30d582b81ab096bcc58626fac66" . + "e28abea289ce40e1a9a36561b2d40915d522c170d69849d1653c1dba87f9d226" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "2776422569a3cdc7c8cc297261f6ca0b4cd1b07a13d5325cb7121c89c87a33d1" . + "0c5b81f14f0924e62f57ac0fe26a28def916a9df52ccf15982fb73e0c04d4b6f" . + "2cf4442a84be7078620ca65eedb2e52f822b41272453aad176013607f0a04e4c" . + "3a9946805cb15dee059590db5de988c0a42beda92e4ca406633323190a0ceb6a" . + "f78f74e8bc59264105eb8ab45cfd89252ef4043bcbaaba0e5dc4e63e96454f3e" . + "624f0a13241022873ada7359429325989dfbb463e33b52b74e369189e97d2a50" . + "b307ecacc9730757b32fa9c7b7bf1b6543e287fdf0b599984c10da48c116f6a3" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "416ed47c25426e63d4577dc2b15a0616e7fc5bf0cb51e187370fa15b12f62d97" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "499eb06e128a9ee4e7585dd668b6baf4948ebef00aff8803adfa20e0cb20fa85" . + "30f07eca6210e1de0b4293e7d930696556a580a95e5803848d5610a7a1caeace" . + "bdf448efd15e55ffc5b66c8ab743637ebead0f9e273f7cf60ea30ef50dbd6401" . + "f5b98bae1cc2e293f4259181611db1ab5c39d09a4a39c2ac8af1f9277092ced9" . + . + . + . + "f428e29f48d08955ea6e018605dbc12667b1c09ba47b27531ca728c2dc5fc9be" . + "5cf253e33b3ad84caa25c7292819184c32f733c7dfbb9e8ab3f91c39b958b0c6" . + "5ec6b30133eb4e219c056af80d49b84cae0677931025cd6f7f5a05705b659f0c" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "43372c2070cc8c531d51c2fbc0bffd2985f6041f844100da852df8b059f3fbef" . + "43372c2070cc8c531d51c2fbc0bffd2985f6041f844100da852df8b059f3fbef" . + "a37ff197b7eae203d41ba8a5220dc50d374b106b57aff2f952bc113e83000e94" . + "12fcec3aedfa278eeb3b1036081336a86adbe365ab1edf12b24ca194deb4ce36" . + "e21b465c9bceeb7ecd22908ce2e66f15c842dde2220015f970256b551fd97a1d" . + "5ab7c727cdd79afa1fc112e1340e26b88ef61e3a45ef851791e4aa0bb1054c39" . + "15cdff60d8e483308ebe605df1a696b5f2f18d5040ad7725dbfad52503ccf093" . + "a4b3f3be9efa552a877b45fce22604e0ac87f35f156c51e77cbeaf36f39147fb" . + "df40a28b9490689dff5ecc8865cb8a149159d8f1fd813cfa60155034a955e215" . + "af0872fea3f8044d27341e3c0293123e7e7718452f0ccd25e8dd491f7e0385c9" . + "07220fd0a825d0005624c397493e7e9f94bccfec97a88188f1a849e4b871cb11" . + "122e6339837e069b7b322ea94a0b73ac3045a9a345d2976f98b31905765cba72" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "c58e08732372d81210a1582dd32e3d91f54178255c996c3852832307abefbeda" . + "26ef4da99f14816958ec363916e8c4a5fe4dce766a4d34df766f38ea06fe27b1" . + "db72e0e0705452e87fedc65e8cb84242d2f1fb14f89bfd407fe80751035a2354" . + "c8e9d44a9b84ab92d1478d72f320033303e570709acde7e305d433ff50fc8f7e" . + "9065c50f7099107dc175759fc8e31c4df6ed3102bd1742182ab4cd64df5b6c0e" . + "5d4aefa697f2272fc4f760a4e8ac019bacd4a13f767856e1e5e8292f6c0341fa" . + "f39a1bbc8147e57d2a1e5039f48978088f1df3f75379584e29d144008352714f" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "d9730c7e47e365490eb0c419ab3971aec68c2dcfaf0959fa62e858eb3c75d73c" . + "9a8e3a346e892a7b9f1231b291cebf04ed0366f9f41339d005c6697ce3b096da" . + "96c35cc982595f373eec85a1254bcd4b93ea8043420b1ca57ed3154304ef85ea" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + . + "929e6353ca8d839617209445d7933da916e6bd772eba4be652df487e6437e477" . + "990e3c59451f5a008978452d5c0e2f2986b571e0262acb66f960f5c9506fd14d" . + "0e746a42ba178b7f1298ad45360ecc51735067a63ee9c4a12f2e930d1ffca42a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8471d035401849be380d0d848fdb1358105cb17c791acbb1b63d8f5c26391aa1" . + "60b9379bb96a98712bec5ef91985eda20f30fa00520aedd8ae19932227def202" . + "4f1852774f1625de6eb3360245cf263a66fa34b660e1245d3b4905e22ace1171" . + "c4f1cf30b10f40ded0f344ea036db090753667556f623be34ec39e57208d05f4" . + "c02dace16011dfb43cd9c1b4104baf13c81f976a3b93c1cf1dcf01485b964d0b" . + "75a0fe472d9e9114e75c45f08559cd155090c91f85b970301a046a26d1c18090" . + "f250624506f28b0ef839bb5b26de6267ae5a541ecdc45477b548d978d2a6dfe1" . + "211bb643bb55fe8792fa12744e931f97f87ee7578abf04b2a53f5c23975be392" . + "1dac77cf0fbd35290739a4a48199c976244ace3acce255b776c3d6cff91acf80" . + "2ecdaac88cef8f0eee18947fd82910d1c546856beab0405dd2f4af52c8b4ad0d" . + "783c02f2eb5079391a68fac916a1b3870896a6cb697bc5f0925e3168cb4a3210" . + "79b01fb06395e36f92654a81bd7664ce8eb6cddba52540e3ef88cf2cb1dca6af" . + "299d92928ba1ebc06560c4cb9c9443f357881eae5fece623b2d1dfa2c370ce01" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "6af1161c120bb83964c13dcd3b3a0f577aa860094c170aea5b99f4811c04c702" . + "4162b25f555c2a0546f76da72780a5670822af1730d96d1c306f7fe899f5342c" . + "d6832397f18678381bbc63171ffa371e361f27d40ec98635c7672b57045441c4" . + "8f1d9034cb6f6800c1ad5265d104ebb251d3cbed66967e355a9b6ca9c4f19554" . + "abad38641e1154300a66697ecb7242699453ccfa6ffcc71f874e263ea58f6ea6" . + "ad85aaa89b383497d31c3831b54ea75f84df697a8c43e3920806b19c95da95f8" . + "0e93be27f90b8ed8047d932cb1389e040dd96ed3b90bed7f216cdc88f184ebf9" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "991bafa80dbfbbd5ab6fcc1d69d9608847e1b804d5f8da8b86fc106bc9067e92" . + "33388467903e93503787c6d4df40230073e42a27df0c395e2986516d92301d84" . + "323df71c8909b363da3ece635c07cf203bb30f114f1daa6cfd3a8e5e8a023287" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + . + "df96704e2ee31ce1f80d96c7b2ce7012dc6aab4e0df120301860d5723ab652ea" . + "7c30040b95a27dfdcbcc033c7defd7d5fafcd2cbd80e1121884eac7857ae6abe" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5f152a58775b9fe636fe9b50755465aed7c4fb6c05ca81469931688dd40e6a5f" . + "5f152a58775b9fe636fe9b50755465aed7c4fb6c05ca81469931688dd40e6a5f" . + "d21c773d5dd1b530bfaba4450c9de66b4802774be4f2fd6bebf40f8d2190cd5d" . + "538f9b725c60f164748574a397f857f51644e640cf30b219b10b1e1701566a2b" . + "871455ea720588774abc46bf21ebe40f04660c7e6af8463677842a7bc1bd6986" . + "31768e9911bea443bf7104044578c3ebde46a8b6482aa6e4f708d34c35c75f14" . + "b667d02441a8968a9acfee0f0947b416023063c2b40808ff04ecdd92f526386b" . + "2d05d80876acd1a298c421468767440f585634ed20b3838e09296497ecf79f45" . + "19fe9a644788b32fd6cab272f232a6b28e5ff7aa46225bb014c915042e7a0f69" . + "d1949dd1d43c9c783c9a8989cee049432c24ccdf2bc6d632f13fb9dbf319412d" . + "7293336f41f0d40a330695ea891dcd59f5637473eb88bdb423de5f09f9d34e28" . + "ee87978a899c422e39348ecacbd320ab2ed8f89a67bc2bc40594b27977efab0e" . + "0b0ca6c78162ee5c8624e9cd59081f76e853a6d045616632bf1c5a3ac6c5fba0" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "5e22fb0d382ce5895f0a2df7b04e761aa71d411bb205c247909a7c179e0a1639" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "f53da32d39f3438b1e7d53fb981c0762a51a8a5ffcb99f0713dce38924ba4c50" . + "d71c13e6ab72d6a4bcfbe3c007d0baa1e6fc859336a74a602eaa9ba8493d482e" . + "1a58a27b0562983d62694770590d87fa1d8b830313fe1648934a2752965f71db" . + "604ac8516b086ea9d1f44319c4e92ae83f33b9c551c01d5cdff3d27d45fa5018" . + "70f97819665326d391ce6f78088df980d361e0ca2daa58cb494fa751ac87aae3" . + "0076004ff180226ab12886f9002b482bdea35baacba532bf673aafdc10dc1d9b" . + "455511da39b4b39006c104da70b42133a129491bb7bf51a63bca57b40ea188c0" . + "783ed5ad97b18aa8843d172d9ddfb35d3d8868b626188c8d6c6ac169fe654416" . + "6050976e4060bc204493ac47b82a895401df142e4d5cf8cbb95e215fef16344c" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "9ba4842493df21767331295c9232e4c409f193ea815b528f513c04d81bdb19c1" . + "74d9254e23ccd5a61bfc64b4e0d3ca5409a209d7c8460cf9e8233c54ed6cdb8a" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + . + "a99608ff2f571838fbab493675d1e646759ed977890027bb7f211811a1ea78dc" . + "16e863713a341ca6dee3fb78f792403d995ac1efd75ec2cc0432dd4bf234d55d" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "1e73a2ac07f1ab7830e92578be145862cd44fc95a25b1d45e77d8f2561d42146" . + "1e73a2ac07f1ab7830e92578be145862cd44fc95a25b1d45e77d8f2561d42146" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "1b317067155d491f0b1902efa9543553cf3937a2f28b1ee098c81d1d3a66ca09" . + "b1ea145c987eaf9e5711b7ca40e9d0bf31ccb8286b412fe60bfed96f789ec243" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "5becc972549dd99a33ed3cbeddd993b3466eab595ca48c52d1cf38745e9c34c9" . + "464b94d65a3485b27cb98bfc4d0fdfd613bfd542b523bb37beea6eb646e97816" . + "dde8676da5adfe0b420ab84d099cdfcfdfd5921ef1caa70bf5670e2ae415612c" . + "bc8965698f8988a42691c158c73ba281ea3f4106923be3fa3b4cc6e6b95ba24c" . + "9873750e6598d6cffd53c2e4ad7e8eaad84b0bcbc8a296548be0c9947a4e86ef" . + "2163d1645ce5132cc75868e0458ac6e7a3b09282e2e0d4adf7fa695e5a8960c0" . + "99f9d3a42ac08eefa700a9281acd514c47fc373fde4a42b2ab2ccc6d1931ff95" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "9f537e6fb799f427300e3ece16ec1d55122196793af5ded034868d30c0af73ec" . + "d01e02df63c154e7ce71bc3f3a54a11a76cc3ba205e92e7306426ef7cac0df87" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "7e6f13977b26737468f11ebeb50a350d8ebd81ed86adc04d7876b68f7df40318" . + "6af1161c120bb83964c13dcd3b3a0f577aa860094c170aea5b99f4811c04c702" . + "6e76c9c450e677205047a90bfd0a2044bf4887984a46135dd45e123bb55233d1" . + "129873ee7ff3d1db5108271f71504179512a607fb55298b807ccffde4c8072c8" . + "31326537a1752b6b824a4e8a57774bed3562bf84652bd2f674e0e4315e12aba1" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c79465fe433a936862c960a35cc1158a78ce10d92cd960404b9607fb4f7e2ab0" . + "b0f7cb235f80896f4a83052e979f1780b8583d28e95c63e7c154d3a174634092" . + "892d2861fdc53abb1f83c48d594a1409fdea14257b2bc0424cbcb410bd6409f6" . + "6d8b8fd0bfca205b79cd9a454f449820454e7b01041bfc1f176d0a9edd58e77f" . + . + "e309afc37ec708be9817a3a25b5a61d7569697bc52ef530a428e0e9386cf3431" . + "6b0638a3e655ad11443166dc6b756eb1407c5ad137f2a5667e48a98199362dfa" . + "6ed222262261b750f33e12b6137f4ee83bbebca4ce504de518ae251bdb359921" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1012a2b0153df9bef23127a3c00ddbdc3fe6125e3832a6640b22ddea5a992e6e" . + "1012a2b0153df9bef23127a3c00ddbdc3fe6125e3832a6640b22ddea5a992e6e" . + "c9bfc3065c7ee045eb7f77cd7c950f25d0b9a89452522593afbac678892050dc" . + "2d72ab92d2041714402679847354e8c64fd1eb24696c4f008fb84fce33ab51ca" . + "3ff847fc628f52f30c2b3320ac5d0e4620885e7b8c51b4ad2d086676af417d5b" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "a0fa92036313dd0a9da75b1cf67e9caad4bac29c6923c7be67c14bae8f654299" . + "9f2446e243d87d009088819066dc900c94628d1a1949ca2d892088aebf242ef4" . + "df578756ba08783008168037e0223617f5dcdff874d392a2de2e6ff16153b1b9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "f0080b6ec8c5fd13b94bf02b68083cc13211a4a1469a645990fdfce2f445a613" . + "0b2b835b2a384737263c5de422d337cf70f0346f58d2bbe3e38366217bf28612" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "5fae3cd73f8766d17642a5d5369ccbc1d276e3a18d058424a8325be5153619fb" . + "189944bc831c99f5e7c805dfec160158177ccc0fad249b7cd2966ebb9ff8641f" . + "815e1153981d38e21bda5a426a16f95b14a51b32433b9b27606aecaffd7aa23e" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + . + "f4f98c4b553250fafcad29f4dff27e7df3e77ba3787f241a69186635fd4acb6e" . + "311e279426b2bb60b8c1f3c15718c98e4b3b9244f12492970221458fbc5d61af" . + "02b35ae708c6a098e6d3eb8bc6b0587fc60405f29b26b17c42cb3f30b94668d0" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "bf48ca5183b556a33c71e830443886c99f993866cc007f3ef99dc57063bf1d85" . + "bf48ca5183b556a33c71e830443886c99f993866cc007f3ef99dc57063bf1d85" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "d39ca1281964083c35016914b739b96f439f14feede7f692d89602cc3b98fe77" . + "3c4a6ab62cb67b7b5f94eb6d10c579da9f17ab8192d37507d5a9e344dc3eaecf" . + "2c4b0ebde33f6c906855efd62e803c3caf58429faf1853e104f56918e8dc79ba" . + "195977b22fb25485b2c1ed9ee0a1671520eb01a2a0fe897467981110d2464325" . + "3cbc8a5dd057036dd50995a60fd43a30821d7c0491ef3c41a5687f624ecbb80c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b46fb6d87b0128117b0bb456537b58981db30924d9f0e6c3cbc41ea0cf0ddbd2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "0b6412a583ec2e8bfbc51e4ebe956292d555ffb350a98865013c76ae7784802e" . + "fd627cdb533f3aa4c3f2fd4bdf44a32749e8d79230bdab7ff1c2ee5acf0e5f53" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "0ac3ca7bf3e3f3b8c7643e9e44a8c298f116e5819ee39a3780560d85df28e175" . + "a16774ca6a12b976583b58e73a70865e0546b04d0424b1145d23335476ade195" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "98fb376b2175cb44ff1e4b90256c0d726d7789df0c97ecf4117cd4aa2f6f6f6b" . + "98fb376b2175cb44ff1e4b90256c0d726d7789df0c97ecf4117cd4aa2f6f6f6b" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "88e8c9eda3847d1c6f6e178d051039a048818cd3ced76a949779a2a9c0eb9d8a" . + "035707c61c8abcf25b2a481a1f788ec916adcc8dcf2c20d2e776bc8fe29f1487" . + "0e1643aeead3a2efbe204048a5500c69719c3856e705a229952e9479929255e6" . + "8f4059f657f08511100bf476a118e43bb17d83327da3cd4245a779ca7da6c155" . + "09b2be2494345f3c2c6ce75dd8c22d45ea671b41d3e273a6d90a1ce5cb977fe8" . + "d4e255a62d2ee79c5df71ff67b9e9cacd2b998420137a61e21a052066f9a7ec8" . + "ef3b2a9c76aeaf7300ee722dc1932dc4883dae9b07ba263df94e74bc25f2bc30" . + "23bc1929d91df1e94fec82ba8860af0bf9406849848023a50258c04ec2775ef1" . + "c04af35f99f351e0d74641acac9c5471c1a2c6105910e3b948e45ae27ed02066" . + "eac06b16ef448a4a389b47157b67da4a83aa16736370ae7b258919acd279722e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "c58e08732372d81210a1582dd32e3d91f54178255c996c3852832307abefbeda" . + "3573df399e5cbf7b87bdeccaf12bdcb2c933656be91c76bf4dedcdfe76c0db19" . + "9b9411f439d7634734a2f1bf472fe180ae84b3b2322d366157fdb5e8eb7656a0" . + "f6328db27fd3707cfc27e914dcd33f4d5786dbd20e75ada556f8451de455978b" . + "b02a1a2cb35ed1d65f3e80083b7e3f651ea96ef870778871fd612d39a8a3c848" . + "8c1b7a1d75d4a1a1060a8bfbc81ff2e39418b7937b21318e60adb1bbe7ee33d1" . + "7592e8ab7dca4f807f44f04c7a46b11df48a345591117525c3b0222ca255358f" . + "b03cf0e5814a096e1acc0186805bcad1e6eb7cf15846bb68eede5f5cbc2f7b4a" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "882fd227d64a092a2cec2747167c96df92338b3664eba22326dadc0ec4532606" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + . + "7fa81e6bbece4b097a10e6390169b4c2601fc739674b6732ee6ade67395e7da5" . + "471857f54f8467b6e29c7bd5f93a6da5dc9331b3ccb1205b9043ac8dd576100f" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "55266eb4baa1ccc63a7b6a0b220c017f617b1507a61daca492e5adb7cbc41b17" . + "55266eb4baa1ccc63a7b6a0b220c017f617b1507a61daca492e5adb7cbc41b17" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "a727fc0569c384c0cba12e790925dc0a34951217b54446f0bad455ddf884b563" . + "5922c3e98be0964e15871d1406a6517d69e1e1f8b0d3069d454a73d31122ea87" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "2f9a359439d326beb9dece7e75c41c62bc86d5a4bf0f11838a8f7950d565f5f7" . + "92a602e587311db61e818ebc068a68c56c496a8e27fc1645e3205ffd1faf0ab2" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c579a3f0f4d7d87ec2fc3fd7e0ee6a3b61becdbf501f223f77e86456090d426a" . + "8057584d278d37947571a0c64e5258d9dead40ddcd8e90a250300a3136edfbbd" . + "8eeabf6dca13412bab051f2bdc465197809e9917f0a85fe3da039c15e9536ff3" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + . + "708945cc014b3d624a5bb94f1e7233a613cc16688fb6d6bd7d76069bede353e6" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "521ee0a1226c557757dcb4ff05a3e9526e42c75c3149c08600813b74abb53dbe" . + "521ee0a1226c557757dcb4ff05a3e9526e42c75c3149c08600813b74abb53dbe" . + "368febc6c5e7967dc9023618e59f8d39bcae1ae98f0e5376d7b74522cdbf54f9" . + "f6f0182ab0fc7fed91a9c2dd32f2395f07c3cf0bb36f6014ad1551897e715873" . + "e276861d5888f70dfc831051c864dbf30922d5fb67a055a04ded8dcfc71003fa" . + "ad0f95d19b6d8749eb0d39b0d76e06572193ad6e621f85e79146ae80e2cbe2bf" . + "148b5536888cb0ed4b91a0b2c1c7949c49133484878746f0e6fbe5a1c48f73bd" . + "d624fd890ee9b0d7499ac2c6c3c52b7eae5ba3df3c5f4529a2ed2a7c3bb316ab" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "846ee723fc21567329ff65648908b853fc66d96ed18234ea64a11d372bae8a18" . + "83fb223e7e000c9adbf2326c470e50a23d622c2eedaa22826cbef64543ae4ecf" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "1c6cbefb66497932c62191021c2e5faf232bcf70c8d1d74aa6263ebdbdc024ed" . + "96d123c60f4be7d228229df1676ae3b5cf3b3024f3fabf7534f72ee983b79f35" . + "4c5cec11287709c903d50b63508e7632c95ea396f111e9556da78ba117ab9812" . + "a13cc78a7f769517f5200374d87b978897fcecd7bd3d781f2debf6a963d1cd87" . + . + . + . + . + . + "1c6cbefb66497932c62191021c2e5faf232bcf70c8d1d74aa6263ebdbdc024ed" . + "06533a8373fc5daf21b2df660bef1d754ff4bb3abef57cfb00f7ae2129bc7ed4" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "482dd3393e9fef36a55ad2c9edf268cc689a6f8ed13963678405196bfce14423" . + "802c534abdd3f46911d4f775619b4f3de2860530b29e3f8bd738cd08095d2df8" . + "f9c5a8f492d5ce4d45a7e2af6af3c6cad1388def7ffc6eb3f8a2d9e045145fd4" . + "9f87311b8c31d45391e95f145b0b678d371e8ad8f8f23b9972496abd8b84ce96" . + "4fe23a24be7283f00c4604bd6b2917c62d51317e3ed5af78fae70fb1e1e02e20" . + "245a218881bff5baf36c1b9fc998c08bdc47b202ccd2fa34e3adf6c7b4d859c3" . + "8d6e472de4ada663632b592f70e86b610d48d95631e29e2376e9b7d34d8f6e06" . + "0c968d4a9a3c701e90146a136656e1d3586041fc61eb5a12088e4bdb191d7a04" . + "e96616bef43670941a81a1c3581eb742e9e3b4d261752e46c9b25bb128c90a57" . + "b2d6f5c702dd26a3b594e25b6a0b6c9892c572056320c11678e1571a2c63b3da" . + "a04500949a617abf39c44a6e0f34797189dbcd6b8fad10fd7a45600de8a9dca4" . + "660b856e70028381e0dacd6ae2e4e0022ea52b00c37adebde5d6aa61b07963ea" . + "e6dc2e89c29910b4e6bf3dbef842884a84b3ff1bfb991a8ec6eec4b98f4c7986" . + "68f52735cd3c7252993df64a376ba759d93f04ad8d20070407931684ba6f8925" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "dab6fa2c3d396bf723c832ac2cf197dbfc007f0f403e8a5ce50efd248cc5e51b" . + "a2a5429d9e38bf4009e6d8685f65ae4cf4ed6ea90cc3e88d7bb57f6ab8ab6eef" . + "3f0cb30f81a0326909da7d42e85b90fb09a8e2d5154367137fc06210800aadf6" . + "39d558e92f49bebf36f7d10f23140401f3d9d9f73c4869c92493ad5e6a69c199" . + "756e1a9bfa1ddd05a495474d65e5f6e46a918223f14b7ea8e35f3eff51ae40ef" . + "1f52f0cec090609c7f15e0adb3af12f2a4b302196b7bd1f68fd99c272ab1e34f" . + "f538a9f128fc2d7b78cc4d0d302e20843d351c4a9377f880a904e8b151cb52b9" . + "5c480662d6ab5abf4677f0f2f297dcdfa3fcd4e64357911d7e0b6f57d82d63d2" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "6107be9a4e5f5fc59d36ad2480dd7ef61e6e37731a79082f81c38cd67536d912" . + "6462caf9a8268c6139c140c9224df4dc254258645eeb884c7fae70a86966e6da" . + "da9e869aa96f41dd3aca2831397f9c2e411495515628d8e9353de64f031c49d5" . + "04d9746daeb8bdf3ed98d1d7d090936d2e3aeb68ecdc5508f59c9ab615115749" . + . + . + . + . + . + "040f2f6c6f5bc117ee220d14e208018ff1453cdc5d8bf93218fffbc8d2b8d688" . + "00dbd620b764b3ba96b081df20e925c9115cebb02d8bea7c83bb642eff402b4f" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a9272e5f2ae32225cbe2853cb28925e73f965c388241c8684aec122eb9022e60" . + "970408bd5a022d5bc82f3d98ca1b44af50b353ff2d4c323440a600cb802a4955" . + "bdf77b1dcc5e4e49634b730119c620f866fbcf1f0542c1927174d35b4c01568d" . + "c9e4225f244b999b7e649559d491c48d8daddc16a865c121edd75203960e5da9" . + "4f7069a741fa32a13f70f5a7d94cb7f2baace73183b21bfe5145d3cf7ad9f881" . + "46d88cfae698a4296e9c2c8f41bd13454f09ef56303c1086a86c93b0a119ffed" . + "471359db0a075a0fdc816003a428ec058b7073fed77bc3b7b0f89d4c667e8d3a" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "761cef156a6660144d8baecf93fded2afffee49b1fb026e6b3f889fd49976765" . + "21758e09870624cc2bbe36d1cdb2665e8cc7f51e55c19da07368f61d7483f6d4" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "f5e090815ac7758d3c3b86cce568af8bf8da10a94b4deaf44f6e54cc55ffed00" . + "b2e62966eee4e8bef09ddf5cc949f0055d8fb7164651eef4085b3b53cd66f95b" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "dd88a8e4ea7bb14cdf24086b0ae07b01db860e53201efaf651aad63020436c83" . + "fc89b0e35d725d8cdb006fcf87f9d3654300d4041b7bc883f12f7c0e96c12671" . + "e74f268e6e0912490b6cd4bd0f42c8a6f9e5939a9f26c1b7578c5a23b445108e" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a64c18e70465ca660c11e3ae223934e57c44ae384004356e603831538d8f1c03" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "ac30be6979a557a7a262cc596b2557a426ac8baa5493afea0ca1baabc7c170fd" . + "073088f3027757e6c1e6430f59b0af3a21e47d4d5fd93d5d2348929a245bcc12" . + "6103e90791283b28a8a52ba45b1b838cae87528ba5f0ce0d350311f5477e6d57" . + "e764f03654a84874c2fc3fcd737217a6e41dce91cf1518a3b9ad9f7c031d073f" . + "f0080b6ec8c5fd13b94bf02b68083cc13211a4a1469a645990fdfce2f445a613" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "7949d4f9339ca8dda2315d548689790ef196bf29ab94684e5a0848f8365d3e0d" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "50853b30559cb44bc2f9188a65eda331efffd8325cb7dcba14d41e0df51d3ffb" . + "0938d29b4a52c466f0dbd62ff176f1d6cc549e02f164c76092760b6c843cb1da" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + . + "f948746af3712d4143867d0c6fa063e385e38155f2d99b859c467c18955e5808" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a54779fd41e06ef184901fb9ec9a7440bf34706305b348f730006d00066a8946" . + "a54779fd41e06ef184901fb9ec9a7440bf34706305b348f730006d00066a8946" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "55c106ff7b55605b3a47b78740f3b474dfd3111faba5d24e53cf102662288e58" . + "8c7bd1f5eca793acc000e897067bac8b06148458b3d291a736831c8bdf065ca2" . + "3beba55a328b035f9d1f7fd3e695dd926f273d9b874361c814bc8b7bd20c98be" . + "14c853a24d845d633bc77bd2c0831a3b318d9baf144a7e1d6ca21a51db1f893b" . + "296be7ba8f1f685c1125e9051bb41285be90304d65f9a522c32ec9b87fccec59" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "574cababa6baea4eab2a0da72c8fea2159c3cdaa8990c6035a4fbdb7606a4903" . + "c89cf1cc1dcf6967f9a9537dde40903126f2e814bbad5a19fffaf5e4b3350f2d" . + "b1861769989ab124a4a5054b81c40661367d448a98d6463404419f8854853fa5" . + "2f4856ec0cd348dbda9fbb46aeb1c5b730b29ba05d85dbb68985e1e3336a7723" . + "f7c8e132012eb4b65bb843d86e0c9c3097d31bf3d01bcbc6b0ccd37a786af5e6" . + "b17c9cf506866f4c8469c3f78031a5a82217bbb9826f848eda9cc32e40800a11" . + "65602c77f501886b13c4de5d47346c9dfb5d1337217536eca2d5c5b0de2d47ea" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d47860628a5efdafbd1d48467d19c28a8710a66361026920376aa590f9f5a1b" . + "41ad9159cfc70e19bf78cdc0d1e460cc87df632b42c99284fba744b88425163f" . + "8f2ef4fb443655b83276917d5d5130fabddaa12384738e5415f7279ee9211086" . + "f5b9ca2c70fab85856cf7e039609c1641560677f4392db4332b879c513f5dc40" . + "8cd16135a0ed2b847a22e5fa37cc5c3688bc71af74f5dd76272d489af875f32e" . + . + "5537946c3904b502e65c10fb06304dff1336121d5b7f90e1e447d0495613b0a4" . + "11c25a6f20117e3cc59537369507744313d4ca2faffe953893e707561f4e5fbe" . + "f54bceb459d7ac7693dbab729d3e303f06c082a77ff74aa54d28451577887c69" . + "d3d24769a2f2f7d03c84e7685115a1f3fe4c906b23e98b68fe3f77c5754a1a20" . + . + . + . + . + "7bc51b068bcd3c038d69e35482168e9386bfa0e94f5f7c80292aaa69be036a8d" . + "268272cae4ef92db3930b3cce2d9754f30026d813f407effa2e9db0f2d26eda2" . + "8b64ff036cd7cf457ce8e666abbf356fa8ebed2ebc94eab9b8a55e65ee0dd877" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53d02eb50f529dfa5c66e768895576010dcc2e4810876a55802feecda3b06c0f" . + "53d02eb50f529dfa5c66e768895576010dcc2e4810876a55802feecda3b06c0f" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "49f7fa2ba4e94b71f934869c88997ea881d21b0a29ad3cf38b3cbd837f8a5143" . + "d63f359af0389184366428c2d12a0d385ff8c01512b037662fd5ba193dd26077" . + . + "d6761de46137f9795fb105bf8ffb9e3497312b7e0a401b4f28b7f645e576a602" . + "4dc3067a4f6ec080369d5504b0753799b77ed8c066c0ac81083e3eebb538535a" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + . + "3f9883197b44ca6d82117dfdaae5a420e7d0cc85957316ec638abe6cf05ee2bd" . + "356321d61fb79fb712f8a4116471b3e9ca9b4d058f9737e60134253150d4f48d" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "a20304a46aea1f5d5ae6ef9fa3d8b236e2687f5f922534e3c7a654d0ea5e7262" . + "a20304a46aea1f5d5ae6ef9fa3d8b236e2687f5f922534e3c7a654d0ea5e7262" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "ac495c511ba03652595682ff3910dfcdd196f9ce7790c5957f3a9b9023f40a9a" . + "77fad9cd1587feb0684bf4274475917d97ed4af6b9ab852c28c8feae14c4fab3" . + . + "bf0481f7301ea690f945f3f33e726614530d23a8d27acbf2af8252e285f523be" . + "442e83a605e3c862b5d7f9ecf133fac48c6b884521ec344a39a10cae2bee57e5" . + "840680d6a49263690ebe09642372c48a10b046a99856b1253ccb3d5f7e145dc8" . + "0a59c4db5b881befde5f1035e09fbe69ecbac77347bb9b736892a22a681bad15" . + . + . + . + "25c127df3cdb2e3cada73ac542fbbad7bbaefa98581615f89c55eccb86efd4e1" . + "b157b8a730962e68d3d08ff097eeb89a4f936e02ee62136f64030dbfdfe758b8" . + "1da1656ce68cd4321170bde4ed9a5235ad62f832eb068d59ef6d60ec36714795" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "bbff9ea5023fa5e9ee0979a779c7958303d13e0a6181426727f755a601b2b830" . + "898e643e1dc29435a4355294ea1bbf5e453628b2751f1142d952ab11728e8eb5" . + "ea86f60ef63a3a8a52fa92109bd46e26c3531593f9fc378d389e981cd84b5528" . + "f156016a41f91b5e9286bce82635660f82110ac0c1d065bdf9c5de3117a02467" . + "fcacc87af91c15d9e5eaf492dfb08350f093c99aa4f76f752da5c50aa0ebc012" . + . + "6776fd828ece17927f9f030f6c81bb417793f5fa7e845f1edd02b98904fd2652" . + "dec7626953c937801be0d7109da6d622afd2613b1fd9fea3aa68b52b160108bb" . + "d7bc7203123b56bbeb1c0b082e7ba0941d9ef46adec4163416e52b27f9c83672" . + "4ca06b7ef431283ceba5c265992bf3f3980644f413043a3eee966a0b5b34bcb4" . + "d05bec0bcb21d597f9bbe50f73ddfc9ed7ff21fb72bc119298d62a8a17a63efa" . + "29dd92d500806ca7b5cdb4a43abbc296b8bcce9ca93b78c7c965576bdd4700d9" . + "ffed2fce2249d3f615e3cf6674f746f9f054d8e311803ebeeaf25876be6e16bb" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "38f7fd9ee711d2d09bedefef8c4918b2bd335c0d454604a4c03aececa93def85" . + "38f7fd9ee711d2d09bedefef8c4918b2bd335c0d454604a4c03aececa93def85" . + "5a55fef917e57cf109ebe5a966bd97dbfd1f50b28c47c3b5e0c46b95efa48cc3" . + "ea9f58a2876bc87da0afbed8dfa0126224d511fb2dce2db9cbe832d183d99613" . + "d9434afc43b5ad3ba21fb434c87ebdf33b1540720e0b77747d7d429adf657e5a" . + "5a6f53d73143c311a572ae507f0400d1c83e7c159a7655ccf12574b003a8591b" . + "20099f9a6ad1c606ff7c248adca6b7da1e1446121b7c796d831bdad444ee06b6" . + "0f25766bedaa9dd50291e39795c4e94d95012f1aceb78e9e5a7c4357a5350e92" . + "4e20e33c6149fc7266b4151a8c3bfa9c0ff8bbd86e48c56908fa1a381564b85a" . + "72308ee70a42704db48eed8f7fa8d9c2008624f89253d27959cdf4e1615f11e4" . + "f10201f7e79448dbca40bbd9815629e56f1103420845e82bf9d40f2c1f4c9626" . + "379171fcfa540daec218db79914d681a34ed0934d29dea759d4f326723937271" . + "39a95585a028ed35bda46786eb143019762937f41abf9bec4d9d67def426014e" . + "bbeb8d89b2a83454f217b1f148d00408b979676470754f499c0a306c5bf0a889" . + "fe3ac56749afbe7a3c1c4210ed1029545dbda349d9a88b66a59e2a6b29c1736f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d246c1c895fcc3bd14918133f8c4b5f18d63122d36229417571b8f7cd0426166" . + "d33caca7e009b6cda292b112f09d8b01667c8b2e445effb20cf2698c3ae8efb9" . + "05d42ed412405b3199fef20e4466e31b5f93bfc64918bdeb5fed19f4adde3c47" . + "d71f4f555d5c7dd17ecf4e50c8c4dedd664c2de5cdbf1d1b8092846ef998f147" . + "638799b22da7a64ad79a23142efe28653a1fc3ad70a9c939a85d27848c536afb" . + "d95951aef91516786da7bedb021f3b9f04cbe00661ba07c740cb02a35137347c" . + "4cf0f58fe8b936e65167a1c4f09eed7ea7fb88d69f3f09635051589512d09ff3" . + "6fcdbc0fd384dc0230be75ca4f6e61d424bad3be25775dcaed827ea06eeeaae5" . + "1588826204ff18218c2641c1323ad5e567201131ef0baa783630d65c20ce2949" . + "25d98300d7d56e9b6909f4d245fd0705bd7a0eb58b3e87e52d02b3d5fa69e4da" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "773a410a0afd9901ef985e4dd0467341fc51587c4850df4a92eda009c6bbbcdf" . + "e2815de1e36778751481cff67a0dddcc76e0a9e7df256898dff2bf6058e31d6c" . + "5ed550180204cf32365a771f870e22f169984bc068b894f27a52ffea18b1e768" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "2a921df8b94f2c6a67d049b84a001dbb488ab2c1e73370099e5cd7471e5b46d3" . + "2afe2a1a537619795831a0fdd4988b26e1bd9bff563364f2bed41fe9d5051814" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + "f41543b58bd678a6416874401dee41614c1f62fd7f8a4943214fd149b2265a68" . + "2a921df8b94f2c6a67d049b84a001dbb488ab2c1e73370099e5cd7471e5b46d3" . + "71529fe53d49b1cbf8c5dc34f2c974aa767668f02a688c49f88b1ffefd069207" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "e9c239348c86259d70538c07660da39d49dfe5b07b29548a1c9778b04d26250b" . + "3175c54b21a4526f358ce4400ac659441932f8a26b9a77bf0c4af3492bd81182" . + "1e500902eb433ee50c68615b4adcc9336450fc7f6e0715e2cec3d5ccf8afdd62" . + "a32337c7a0c5b631abd3c9fd21605d11cee676d44c3b92bb1dfe868a6a9c422f" . + "0c5b59e60a6b44a2490af4f798dcb68ca667f854fe71d5ec331a7219ad500316" . + "ea9ae263b82494ac8a9485c1ebd89b259f1a3906a6a0d7fffb9251824a633229" . + "1e41055adf6e9c671a905214777f76d270069156e719d14b9ba3bee0b97241f4" . + "113c51b0e2ed5dbf9b491ee8843db28ed24e572af9387119c0edd595d11a4801" . + "815426df1ba4c2b3a5a53b0267029c84925478ddc2b4f7ac108396878bcc5cd0" . + "4bca7777d801bdba0807d0ee5538e44887951fc90c06fe8391c13a826de53f1f" . + "04d6b921f13748639c1724dafb5975d9bde295da94e631977582eeb6bf6ea646" . + "4f7069a741fa32a13f70f5a7d94cb7f2baace73183b21bfe5145d3cf7ad9f881" . + "0020a95e8cfbc4ab7513cf764c6d79acc69b7b96a5aefa0b043b25c48d01627e" . + "30d00f7edd2963127dc8d7f0b432e7d2d3b7c6be161204c3c929e728e075e81d" . + "b23b9a73e98f2ab9a6f0cde4a49a859c5d1e885a7af7b529c43bbb811b162ead" . + "83f660adede5c8f3a72bb6ec3664c96af1231d686d3b3030ae707bbad51e5b44" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "0a4ef44e625fee62382addcffc1e2d1b9d1258c9a0d1f5b5d9b08776fa5a778f" . + "ebf7302f13e8a658855122dcc6bb9390b57874c1c89226f28f95a6ac66d66dd2" . + "928220b16e5691f2eee876016c1a1f031521dc8e97ab7ab5d7c5a4297353cf33" . + "35cebab785c9ebc69b047593f86d830e467179f79ed7d4b2733694e6510a322a" . + "e0181c0885acc2f51e483779003950a51cbd51dff159097a2e0f714488ae15e7" . + "9dfdb9c8ea17a9b1939c807c46759adadc5e389bb9d8bea36544610b65eeb576" . + "39a28bd0db3fa830f57353e34f4305403549bd20599722f1e57f8bc00b8674e8" . + "86f93760a22ecfd7efd19a238a9e2dd10d8f10784e81491ad4d56df3b19a00af" . + "d2509a247e49bf01bb36a0f677ad58d7f24cf2d63a6b60693423375bab2138a9" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "1df48b8ac95e72214533add7cbbf6d6226005f8858c2927cfc6efbc5869bbf62" . + "69f3355fa0ff83aac573734a8524e2fd12f445d83a2ccad93aa034e9ba8f5cf2" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "9843786715701604b4f4e34b1bb6fd6111bf535abbefd29ed9e25c89d2ecc548" . + . + "30dc71b6617281d142968453eb9890e6cd706835710c70fcf4fbe8c33f8d972c" . + "d89e2bd94be0585fa819a209f851b5e14fe45a4a1f87a0f2c6ec762519d743aa" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53b4005a773e2bf3b71363ef7bac49dc3bb0fefe3488ea166f841c6d73dee32d" . + "53b4005a773e2bf3b71363ef7bac49dc3bb0fefe3488ea166f841c6d73dee32d" . + "320feb45f7c7256e8d9c81c0aee2ffd4cd01f231239b257f5849aca617490a74" . + "d8eb1de3cb400d58346a6889acf0bd670154c9c7912d55d06a23a94324a7ca07" . + "cafe11560386d4f0ad0e3a4f131741c3321454779cb3fc762b4dad6f0cf8f53f" . + . + "0f4fed85c867fdecdbb138c3162a3107072a92ca8f731a3e8c815ad35e9d9def" . + "94a34afad6073411364050e8a721b2570ae64f51359b8e0f1daf3ebe998ac1ab" . + "01ab6808881ec3d5eeba596472f088c102b68ecb651b9eec3171f811f26707de" . + "d1a253c699673b1c2cb5ce6c2a9c2a6b0afb1dc14c8021b3e19eb7d8c4e99faa" . + . + "446ca0afe5fb7837b8255be40797b29b841cb3dc8e82d54246fd078f1a5a78ee" . + "7486e2024ed62cf8e24c4d4d72a1361de783d45caea6ae62aaed9fef368e96d8" . + "5ad560421558bc1b44e377893f0a55c86563718a3844301f779b0f78985b198e" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "a6cb845e90f4908d3b66f19c978dcc1dcff439ded0c9cc80d9c2f3102ce01785" . + "4fb46f71a976b68bbff480102513c3da8f90f42bf79e9ef617b470ad13640781" . + "e55eafb0744746a3c4f4ea73f9a39e545721b3db0ef200ff1a12e2dd7725388f" . + "1d13478662bc673a277ea35188350203b0bb408a086eb43638ca0c0fd95284fc" . + "a058f7ef39a6e2bf3288582ab8d76ed00011ee265e5469cf7ee55cc30d5fec3c" . + "fb660d1502382874641cd0681182b09a28d7d62df46728e795d2afdfc0dc14d3" . + "c138d0a945c70ee7c87e2001a2487d2a6d49fef64f401e6b96b807cc41c12003" . + "62ca8f515fa35210522d8133b29aaf11ada8c81071301c6c5897549a656e1a79" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "1740073349a9a0449642d1355b9fa75b0e871bdbd616209ff5a8c351d8b35814" . + "1ca810270536366504972572a2a175e4954bb8a8a364d3c64df9b8888b972077" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "8f9da74b326ce80db7323257cc91f6d73afcc3543c4a59148e21613eb68083dd" . + "2aa66984e184cff11fc9a47c4e810e61dc1708157dea842e9132d1c54eabe0d0" . + "968259ab436feab20f9afaded8992503c43f8f4d17c6fd0006d3761bac267de5" . + "dbe70f59a012fe295fb736ce59bc2c092063c005b3f4303ec1191528f61854f5" . + "dd9969b7e5626360ccfa9465149f0b6127a4c1d664da2623a0905f1912fdebd1" . + "a086ebf1274620f60c617853eb5f203006d26aac921376fc6d2a226da047a6bf" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd28ba6d0e6b0b246e154dbfda0b5683ab3a8b2a77c9181e30e0d22b9c7355f5" . + "cd28ba6d0e6b0b246e154dbfda0b5683ab3a8b2a77c9181e30e0d22b9c7355f5" . + "7544065126eb616e77d840abb719d83353cbf02f4ed3649190e91cdde76c0232" . + "13ad4d2a694c0ad9dab77a049e5de2101acf6a586272c032f5b44ee502f2a010" . + "65f6835e634342d0f422465d9195c950bcb1d7f400c0732cf54c2b0a4220412d" . + "e2e8cb886e21a8d6d7eaf86b16c5996f3fc61940685cb5ba55ef1993f64ae714" . + "176e1a802044e1497f090227376ac9333c4756bc27733b0365e563198f2e4c11" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "0d7607e65883f12bef8a85048a7a3e09c2d63308c7344029e49d25a311f48a40" . + "b46fb6d87b0128117b0bb456537b58981db30924d9f0e6c3cbc41ea0cf0ddbd2" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "ee6519430da1bdf1c508afa0c4452b2a638e37a62ad9fb75926b7ed485cac650" . + "c283fd644709ff416716a967f7288932c2a574f2af1351aef92d5e18c18597ac" . + "aba7d4f046b6254c53ce796b8c4bb547bbc913f095f00f407c70d6f029285d97" . + "8b9778e08e5a70591230adcb3d9e99bb88629bd050067bb7f94d6fb20ea35737" . + . + "db0fdfd1a5d83afffac5fc971e4db22ee09456e8a1308780d8df85ddb1b22b8c" . + "5f4131c1ef6c744ac8be4bdbee2b2c7f38090f56153098443fb8ae590bf7e6d1" . + "370c5950521c14b8ae08a35ae9039af0d13960cc3b81dcda4c6ce43d32e49a75" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "873a3916f98e029db5e598ae68d9a8f5c5c797472d38521082482fba589f384a" . + "873a3916f98e029db5e598ae68d9a8f5c5c797472d38521082482fba589f384a" . + "6e3a03aaba88dcf1534a99896b319724d984d1d563544c8f12398fdcf1575dfc" . + "4782867489a3b88aa285f106b63038efd0c33c0b7edd2c84796c309190c5a4fd" . + "b23c234478013859c0d91f3454912eaab202f2127941dcf1d48e8e780c2fc14e" . + "5a4630193b55310b004690044ddf9ea404ca8cb5ff239fd002a7fb364e0d3374" . + "89f739092a306ad1db3aed6a14d2a7b572ea99584d9891c153449934e593925b" . + "dc6e5ffb82877b240519c9035339b2509c61cc68185bf626ee0e5068afadc94f" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "098c62f521b1e32048f70be4c04bfb0ab7467cd9d3819d0bf182be215193c770" . + "5662b3a3bf670b4f0f3e41fbaf706fb32e5368b7acd064172bce98188a3dbffc" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7da3b90183cf5f0614696f8b45966c7fab1466c9ef2a5ab3be90c0bbbeea4be6" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "e78ebdda8315cbb26ef80e2d67069fb1554e69ce2ab9425d9accfc0e7c730dcb" . + "c984abda09826788b18e5944c7730368ac75a371efd8940dbfb919ae69b37ac1" . + "9cdc0c0ac68a154f1fabb593bd636c50447606b005696815ba856c0d57316f69" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + . + "1aa85161c4e74414ec6c3b8288811cf6e9f8c33a2ced1ddda3c26e39f74c2f46" . + "5dfa645b9b6a1492b8f5d963a26aecee25f898d7b7f7759cac0fadad78b6a201" . + "a6df06eaa7f0bf4e03799a87888b114ab6fa59b46b5cac61fdbf5eb071c1f16f" . + "745fd3ab09c557878eb817a04233f81bf31c8090c729e614a40d51676cb98eb3" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "db6daf6c972fd9411be46fa6e449929f48c3abe5f943b23f665b6dbf0695adc9" . + "db6daf6c972fd9411be46fa6e449929f48c3abe5f943b23f665b6dbf0695adc9" . + "35eb8177a0b03b547f135fc0cb0d4690014c7787bfdea03a28661055f5d1fedc" . + "71754a7c7fc9cfbfaa0ce8d5e7463db9eba5c8895dc46f2117a81e2d14ed20b0" . + "1c25457d456c597fa8a3c3c8fecccaa4cba6ff99bd8e774291ce329ee6efced5" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "5532f73bf444867b67b49c2d1bef65f07ba7a126f40fbabfc5d3f4c651f1c9da" . + "d6c3a68f3753b1e3ad5c9efb19b3e4a6f91513a89d50727879801fc34699bb31" . + "52d3998b9afdaae0bcf2316f7a015bc731e105086e54a4e4d891214b07dd519d" . + "06e363f6df4c6ec4b8c897cdbaab2c84718545228976c4c003867852c45762a2" . + "62e264c9ff5b37928f397b0a8bafed11e3cec9bec440371351b1026de35da4a5" . + "20bfc90ac8dcc9752d30eee22a56d0d95a6fddda9bee3e328e758b63bfeb44f3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "1cac2ddee42dff7502d58e9b97fd4c5ffade2fa0d4f622f875cc0099ef76310d" . + "438b9cc890b098f65b6c212fb580d53d436c2598ac4958cfd943f1b3c1562b89" . + "a621d71a7c530a04ed1024b990ef5f361f4237f2a4e77a23131b6f1272641d8b" . + "3c48a46ba488d146dccff22a9a44ecfcbf3f32c52799a082e36b342946a5372b" . + "d15969eef9bbdb35e5bbfe91ec61a5851fcd0e33dd3c0a2898803f377ed54cc9" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "b4fc5a856c24811e6488c20fd3c5d8bee1534cc1844d831f13aa5295c9651bcf" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "17f4c7c9ac280addf4ca47326dd7abaf40eefae43bc06b0be1229da3ce984821" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "40f027bc69887ba1af9c1b65027fea2f9c28da6016765cab0713786ab711c5a6" . + "f67ab48a5730ee2e69009f068665244639061ec5102d60d409e0c7bc3feea20c" . + "e59c841c57bfe863aa8e258f54c3741596a944b0b8fd79f42ff344c41cac68ef" . + "5066e7384b37fc40c1926c05ad764993104534bc9e191b0688c2e55702341072" . + . + "7f4158a0fdc72b5166fac35b248863f1c2fa498ac1e37eec0dfea6c22dd9298a" . + "47e2edb5790f45a87125b29e9a6f99ca0c131b0cbe063f0e4f49608e36379d38" . + "7ac13b9747fd63d6d16f011f0949637257ca946a9762e02494e4954afa514df5" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b8882444e840573daea6cce98e5bdfec4df48ea9327e526677c69f10721420cd" . + "b8882444e840573daea6cce98e5bdfec4df48ea9327e526677c69f10721420cd" . + "f5197dd40ae126b96926590e35d6f070c8b7096cf37ee0944645996674865645" . + "4c0348838dd13e8d011c2c751bc2e4c7049fdf354e5cb88157201d84d0fcc297" . + "40582cbb02b004f5703a61e73f44339f05b6436f9406e33d2fbb6e976890894d" . + "4c8ee56b7a1de31164668bf63b33e0573b39e339302dfaf92fd3a41b3b824190" . + "86eee31ddbf0bf64e54b62389b261dbb906c31d7e6b6ac9d0d2bb4ce957426fc" . + "7512553260de527f1977e288285a730e4fd705b818d4963e4f9b0a3310910407" . + "ba1b454ebb2fd9e8789ba975717924b309c547ac652f95e2774341af6c4b6376" . + "30ecbc4b173599c49ec81be9f58c1bd7c0b4b1ad4521d6d901a5432519b77cef" . + "55182eebb7f6e8a068ecaf80c357bcfc65449ae08102d4d03da942012b9bd7fa" . + "d9472692c0d771d5640d1dba9ff41d1f0d50077fe5c8dac0df900d327902588b" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "b0d16bec72af0899e2e707cf2e159d918fd0ac9f7e9d070d4376151aa88bfebe" . + "0d2329adc8665960d605065436b18b57163127725b0eaaa8495cc1c2285c486d" . + "0f70e46c15f9907b877e638b4dc318d850d4a11d1a99758763ade50e7e9caa41" . + "37312afff7822f875c52aa7ab34f2c7fe5b5ff1637b8cd7747f6af125462f4da" . + "90c3574cb32ed3020bce5c1735aff613d1bf48c0e52fb1eb10c477fdf974dfd3" . + "abf0ece18dd65e2e9dbfd4591aac7cb567c3600d503ac71874fbc55565ecddcf" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7d4eab31f2240f5d493fcbd8ab5e28c3c6dda927511017800866d68b907c50ad" . + "ebae15fa26e74fff1ce9fc2fd442326c5594aa480dc65863ff4d21ac97c2cb11" . + "b480ca7b2821082feb690f33ed11889146491a3b810dde8a952bbee2d9147b89" . + "b4c60c8ed13ff08843fa55597886e8fd66d08c7300b896bbdf550deb3f11ec45" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "c66e3d2fc2057495ccd9dd3f485c04d948ca576fc962305fdc8af4456735b9b9" . + "e9e014399b007269b4767d55b7ee9d38f34678093c2432ccd55c75560c7e2ad2" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "9b494c5389f83edbe5d36aeb7523bbace2ac586b4bd93c0faafaebccbd4a6bee" . + "feaa87a1bec20b45e3ac2e19a8138eb88d381a627821c5831d194845173171ab" . + "371447ab99962958e4b4bc503bb2afe4f6b5028122b71efc1dddbb68756f4b69" . + "c7d6246c284696c64c13c0998e040ccf349493736ea49feb989f54a1e3f66ed2" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "8ad15e2205b91b097f5b0c26eec322b1c89a619bfc6baaa5c4536c56d7a6c9a2" . + "8ad15e2205b91b097f5b0c26eec322b1c89a619bfc6baaa5c4536c56d7a6c9a2" . + "3ff3b3dc67ebd7d23d974fb10550ee24d55000ab546789155fbb172c256bf50b" . + "91916296d5a82a617090aa73c7fb74c840ae3503f44e27b69bcd13b0a5e8c6b9" . + "19ce21d5eb7ff86d796c7f765de9177d0a1e3295deb6ca4ad0c57439db1effac" . + . + "98da8ce2bcd897f237926703f92975ad88ca7444996d34b8bb7f65596f71bfe8" . + "d1147f084e916d9d92176470d2fedb8f8cb1b0a10fd77701f8bbd73c38734507" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + . + "e9e169adc765c63b29f3c0dc11f4f06198e5a49c4177423e80bb78921f0b7240" . + "380829955011b9bce16cf5d6b76c806a0d1e1dd62e5d31c0b967a7f49fe651d2" . + "f9073e91bfd4413db96b6fb554706754a5c689422b7a58a6671d3e0003010d9f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "44ca211212b8c92f64c3e4228f595bc738ab1436f3f1eec14969142a392a3aac" . + "44ca211212b8c92f64c3e4228f595bc738ab1436f3f1eec14969142a392a3aac" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "135e58c5101780d0e1bfe9b6270552a9f4f7969957e0a21fb0b0a587965225b3" . + "2c60cce4d9fb1b4604c9ee67e2ab2c5dfb9bbaa1c7c22b6b719bbd46e861619f" . + . + "4646ff55b8eabf28f63d10c356f1e4741acf46a6cd08fab2bf02f618bea6823c" . + "9c6dffa64c59a493a4acd52501697e8d70f61ec1ca2a8e438565066ff90e6055" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "821ba5a1e698ddf5c09ab58c145b6bd454d7b335f797a5c88ce8d829b89e37bb" . + "91bd2c70f60f844e74e97bb1b8041cba095ba4cae39656c8efa1e61c824230e4" . + "65efb6840731f78143ba23a063e39908d559ae918462f4d9132070e8d96df6e7" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "8bd5425391a046a699106fdac1acb5be9dd8771c4fad2737fd1b637380253106" . + "8bd5425391a046a699106fdac1acb5be9dd8771c4fad2737fd1b637380253106" . + "a9630fb437046faf1d2c807693fc8cedf68dc65f8bf14936451b4e6007df7c9c" . + "248bcce84da9fc7c95b222e1c3538694b3a25fe30d4ffb1cd0bd19fa48f4a2d5" . + "3f6d7bcdaadf5dc65d428d10d37c43b81fd76c8b246d073241c4ac8b022f1756" . + . + "0b8f447b503e17b95b69a1cda3085ab27477b07e94cf13a04dc14d9d627fabbd" . + "ff36693f3b70e7051f20d8d8cc3a34f8d886fd03a6c03173a7644aea6f5b4568" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "72ca580519d446c2fac7f21cfd34ef1d83bb4d6ed0a98ff4d22455a5946e9672" . + "0b8f447b503e17b95b69a1cda3085ab27477b07e94cf13a04dc14d9d627fabbd" . + "683963f7fb7c67118c1bfaa410168427d05ff9e6a8059e6a358beaa8b702b1d7" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "156f281d2fa39b76af969bdae397ea0780b3114cb41cbc00e967c1addbe1de00" . + "156f281d2fa39b76af969bdae397ea0780b3114cb41cbc00e967c1addbe1de00" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + "2ce19026681a63344be4ec72baa8a489af4e3732d11ddab4ce284e2073bbfd59" . + "cc285101afbc939600434091d1709a0a9624eca906ed80c5cf127d521e611376" . + . + "55573887e492c988dd6b6c56617a8a15af539cd78eb114100581a58c9f71d9c2" . + "99e611be78ff3e18fa5e9bc681f66d40fd86e05f889808468e94cd6c088f92ad" . + "3841054272a701d8d1525567bef4da95baa8aaf53aee5e249aacc70e485535f3" . + "27dad4704702157e92645f3f5d231bc2a08144a308012efcc19795b84714f4a3" . + "ec3e1c72ae226f2a69936eeec5e8bcde6004a3637ec65a77fbeaa21af3a020fe" . + "d3452fbfea34aad41b96b437f4dc5d735772ebd5ff629e9c374fed4bdfc77752" . + "9d489b99468d91479ed801a5e8a8ee8f00fc246c26db329eb6f0532ce810f3eb" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "53c4b3f96c7d51470d38723985304af9f44d527cbe7ffbddd0c9d4ea449b0e79" . + "53c4b3f96c7d51470d38723985304af9f44d527cbe7ffbddd0c9d4ea449b0e79" . + "ee680c2301526d0d37e85fecc36382dae4e99b44de858b10c38950807361b2f0" . + "1179b3e31768e0201b1e6752e93f3c018f70d1c7148f33b8f22038a91919bd73" . + "6b1b8e6a3ca08198038e7f6ca019edbb002219a21475e2314fe31afe0ba2a95f" . + . + "16683081c602f71f42f6967a825841b831dc486430d5c97bd6f45987b3f2cc4c" . + "3c335d4547f157040310f64c96b03a922723a3c5ec3dfdc31492fb87ab30aad1" . + "94f42f9b9e9aa337e98b63b07a6208ef972fa098ec5c053d9ef6794b036910d4" . + "7e8a4be856a120b3cbb1967fd35689fbba23342f4cb3643786c130022f02f230" . + "16683081c602f71f42f6967a825841b831dc486430d5c97bd6f45987b3f2cc4c" . + "caaa61de2552572d3c308dec7ed10cdf74aa03d1899693a3c8a233687c733117" . + "59b3157913c32d5798c4589ef61fec919a5637ee949a891b971d930d220031f5" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e17e88a6859c7ffb5db9c8d2cb7e918850be452adaa5f2bab3bb62734fa15fa8" . + "e17e88a6859c7ffb5db9c8d2cb7e918850be452adaa5f2bab3bb62734fa15fa8" . + "360922447e0d02cae72a2a9add6d0f93f402b72a3b317dc7755ff79df5710833" . + "c34946eae35fc6e84957bfe1ce6377e20109d2a064574ddfc173169c7392ca70" . + "805e9758ef71ba2303549408bafcec4b2b58ec1fa1adad0bccf7f168edf82fe3" . + . + "d93808a387b9d10d346dd1b3683a8614e5dc5e1e59f44bd7241604d5a2b3ab26" . + "c2298b0c8ac8983efdbb05f84865071d40cfda4212f66cf1b144e8e0cceb4a38" . + "5904744d7b61bd1a662f78456e945638a5fba4dd48e4ba5e2634f2706c5b7de0" . + "5751825747d4a4b56511836cb22022d918548b22c4e07470693b8902f08e26d6" . + "a09a337e99ac4183a391b7086371532b8e71232be7e56fb48f5eb3771333e367" . + "2422da58c7d6b94f1df62b0dae447e0dd2129deba80541340b4fa1e42222a425" . + "53f359b35bd0ca015dab8e3e5a1f8383576b45664ee310efb4efab3799a9225c" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1849e53860a3dfd3d3d24c0d2a7ba23f50869af1dd31c65aef46b39a819608d8" . + "1849e53860a3dfd3d3d24c0d2a7ba23f50869af1dd31c65aef46b39a819608d8" . + "29de6d3b75eb95842a693e8b7decc817d52e93553fb24dda2273458ff023aa57" . + "25bdeca0aa7b17b710a9a4f470cbe9db1102fdf7610301f0569f6c343f8acdc0" . + "19d3ae8cd7ccd091479ae4ea317d4abd80c756c214294c967b8d487a4fe92bb6" . + . + "b7f18fe2cfd559c08edeb1a70163a2625bdba6ade90f9e84c4d30dbef9268ae3" . + "57c5f343b42c693b411463e9d83e67f9d6990cb59334495ab8777590db0339d8" . + "58dda1a90f1969937f69bcf6a06391fb2d7253744f35efceb609a1b16c54696e" . + "a44f3d41823b1e9ea5cf26b98e9bde24b46b545fe5f67c94033f190460b8280c" . + "378083224ba7bb05f3b3de0d4671d4ed61b0e365eb615212d02c6bc38d0445b5" . + "02cdc63ee7a8b4488ffa4bcb870876ec815194bf860870640643fd1268fa871b" . + "8e7b9e5e776f1531d4ff096d9a127239fbac18c3a228f7b1976d2a5e2db417c9" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e58e5934b7ffca8da7b3e5b71b3e092bcb75592950c5126e29af41f9251cca66" . + "e58e5934b7ffca8da7b3e5b71b3e092bcb75592950c5126e29af41f9251cca66" . + "b80fee7903e74068970d0e954ae7e0d282fd2758864fbe47fc34c5ced1092ee0" . + "dd6278ddaefb7d20892df6740bd1f06b9f3add36ca6496e09d71aec7d9d801f8" . + "ca094761c04de6c3b2d5352be13577709095e91e014c05880cfb5ba8ca3cfc17" . + . + "fbfa7a325e635c0a8867cc8090d3274b0f30e032a5aa00adb92d13c99de4761e" . + "72b989332195274ceb704ce9e6ab2dec42df2387676b490c61fdf90e83da6b62" . + "134dbc1bc1df1d9d50b95ef501c8a6bcefdf96bdbebd2f40fa34fd69e70253be" . + "56a08512864f1b02bcc98a0369eeaeda68a82ec6adc21b2508eb29674762de49" . + "fbfa7a325e635c0a8867cc8090d3274b0f30e032a5aa00adb92d13c99de4761e" . + "ca18d38bc556132810b74f83a98addcc6172e6e8eef2993f63c685a63f1965c8" . + "198453c7ab3e68bcf7a5acef2ea250911aa38c908f08b937aca9d6b4859e3407" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c0d835b10e133e87da8458a4b69395e5c6a57e97cccf3fe03fa60491e3156163" . + "c0d835b10e133e87da8458a4b69395e5c6a57e97cccf3fe03fa60491e3156163" . + "e729c89629948d8992d0c56ba20cde19e05a9efa3af9b2cdc29488f5969f4e88" . + "7d82c0b36b8e51d084653bc27c3a723e37f0216eec8c73be1a8142d376bab335" . + "16866d25b330310a2d28d2cbbfb6d6531e4ad85d90e6b510147aa2647382b7d1" . + . + "d5d6c8591854bd9a41be527ac03f3e3ee8f837f5ec362ffae3261310d2af09cc" . + "134c03ede3e7314790662062bc8b3fac90af538be678a46c51b3172d3e372fc2" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "6edc94282d1b095752e4cb45b140013578c72480877bad0a360109f4dc7fa485" . + "987be4157e0779c00409b255870df0375a43542d98ef6becc1b2f015d24aa009" . + "0b99a4bf867401ca43d5f156d256fffbc85b6468c016d2a7c3a1cfe2c8a4baa5" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a1c0acb467efa9a816544cc7c2775e7827bab0d0c6756748635061b94968b53" . + "9a1c0acb467efa9a816544cc7c2775e7827bab0d0c6756748635061b94968b53" . + "24bb2c7f06c9760496afdf12e7e25fa7ae8ed18b108775cd9ec79f0fda5ca6c2" . + "8a07220831171c9635cd882d7c77192c3519def1389efcf18d05f2a393b2645d" . + "52437e8b57b59279f9a6a9fa057de2baaf2300e87f9751d4b2ea773fb99338f9" . + . + "6dbe084fb2af01e1806988f2c996fd14c293667a604dc5c6e2e5e743cc940ca6" . + "8a16362ea6deccb62a30411f39f9a662251400511eda4db08eeac0c3c7a5684f" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "2382a98826585cf274558d30ce67c156765d11c8f35f3a793e5893a5e7d3bd9f" . + "358a2c082ed284212f361cf45127532615dee4ec468c24eff0097f691966c806" . + "849dac818a65fa742fa8d2af9d8eff90610a8b63a79714f29f913b0aa61939a1" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1d4076e7901a33e93235eae7023f8a68dd211647a47261f14c9da9ad80afe254" . + "1d4076e7901a33e93235eae7023f8a68dd211647a47261f14c9da9ad80afe254" . + "857d8b0a2f227cb343200ddd6aa78b62269b014920c96a0fd2b2853622d95a31" . + "885007efb5955bbd160a264866cf981be80090320ca029ce7d08cd686b3e7bf9" . + "bb2205bedbdaf7290820d27fa2b2b91295985b0486c8d698878af7fdeb8c5730" . + . + "a07299378eb2e96564e1dd041b0ff3f12a68f554520fc4f8e279d8832d6ea1f1" . + "898d5e23e98a794f1dd00045717543393f548656750c9ee9e1b9a9f40b46f7e9" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "b3daf545c2d647959189dd682d0fbb77840d0ec6eb882b510afc90751a96db6f" . + "92bf6a52ef8c58d7ffc7834d5f2bc208ea75323db7bae5cfd658f27b6a184bef" . + "7f54a37ac29289cf811c3d41c42b88429690691ef002967e0e3c494068b771a3" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b97c7e16bdfe96ddd65d7a9ee7ac3ee5fe18086372a722199a5b1c7151366073" . + "b97c7e16bdfe96ddd65d7a9ee7ac3ee5fe18086372a722199a5b1c7151366073" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "e3e16ec81101b1da314962e51734d0e04ee68949cbc373d196cfbcb81bd022ea" . + "db88f5d691e24372f8fc0c9ccd91840ad9b713d2e60275a421bbe3d45616854f" . + . + "612a9aff61bf1a3e0c81e118a239bab22ddb5ef06a85b531c3c64ce44b77c79c" . + "81d09ee7452566994d3be97491e19f14685bb7b7f83385ca35cd02a16bf7d956" . + "4b8af33ffaef6fd60642ad32e0b38edb8384283f60d27a5f4f9c33d1adf8f154" . + "833923d5088b01cce11b68ddf436af0be1ef6b628d47a24e4b50ba7dccb4aed6" . + "91719f8548533d4226eb671cc180ce0ca9acf89882007549b50909e60c55e857" . + "5f939f42812a7d28a296d6dfe507735cd7635dac9a3c3b07bd224b93153fd409" . + "214c6affcaf58071a5908cfffb9e623f71deb519abeccdf0a716fb8b81d3a3bb" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dc374e04dde37a3b87b136260a6ffd8449a66e0bf993ff6be039b6b9307aa95b" . + "dc374e04dde37a3b87b136260a6ffd8449a66e0bf993ff6be039b6b9307aa95b" . + "5910c07af8fc764ea8b46d1e6311e30ffde4d525c5e296da107230cc9b52a54f" . + "a2a4b8001ef46855312840b04bc99092c772cf59194ef81e2f381784ca664fc2" . + "fce4b418dd01dc1b4ad2f8bf4dc2092eec2bf68ce20a7a5f69788b051aa68a27" . + . + "88a5a110baaad7fb16d81a24d420ae4027fbb3137dd0008bb84e2db15e1d9d7e" . + "4bc38afa80c3c1d6de9d58393bb61c6df9433589f9d1c560546dab6806a6e282" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "142f21c4ab801bcf6ab87f611a0d3ceec2c0f211c5c073403cbe5f6ef965533d" . + "0cfb323bcfbf711ec2760b8f9f13b4fecd54216e364dcc95370d08d866580677" . + "11d44b19cf438c47c5abf70982e35934535a96021c7de603cfeb5ac932e18802" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "984c01bdbef3a39732d0053aa18199306e3823048f13eac168c32a0de974f5c1" . + "984c01bdbef3a39732d0053aa18199306e3823048f13eac168c32a0de974f5c1" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + "df258fda8340e09c7142a3646c1b935ec21d825db07b7a45e6b445efad4787f3" . + "aff57bc9d5fc43d75a89cf87e9bbbc77ee8a45b2c975badc5c0cf6c10003b7e8" . + . + "ca717c790322d6d8468ad4ce2138efd8ad9d3a904f7cb4ab9eaf74a6fc6e73ea" . + "a30f0fd1a2b550040aa1ac04da8e3dac603ffa31f3020519d73b41aa151a5b20" . + "18af155413776f483a491c6deda34523126b33c7a41f3d6edbf16c8f57a149d7" . + "78fe9b33cafe58c172914578844edb2fd35543ea84f346b4fc6969012eb915e3" . + "00c4ee68ecbdc003325692e1cfc42fd7719fcb88e2b23461244854774f65dca6" . + "3fe670326cf03ce86122fbb85ec34dd46149e3547622ff7371ef4cf44c28b4cd" . + "3357ace8d63213324c46468add8b75eaf2f44851dfa41a9db8fe6bcae9572217" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f7166dd6f7802149d1bb8b5f099381d4f6ced252b5698db276c4e536b9eeee7b" . + "f7166dd6f7802149d1bb8b5f099381d4f6ced252b5698db276c4e536b9eeee7b" . + "6b4ac9e6774cbf052c10a0b7011d6b743c0b495b78f059b8968e460defa3ba6e" . + "7ac0e59eb80de1458eb1f707c510c19e95577b845e0755deadc31b9ce4508ca0" . + "368fb68bba9b637ef019086cff3f7d86f1909ad31e8dc9b5fc00bc343092e6e5" . + . + "cfcb2737b452cd70f36a296bb3ae324dd60e90538bcddb73bb4547cf0cead7e4" . + "aa129bf6881c3d37b747ed5884a9991be7af56284f35bdc608cfbc889d71f82f" . + "d5ee1d44d6d5fbdead8de3b65f8b284b1e5607a14291426b5dcfe68b1cd6b766" . + "51bcdafcf433202a4fe2b08c05ed47efb06b95c7bad29d57912382ee8bd2e65b" . + "b6274d62deef46b11e5e5fae0b639b25a44c35093add33e1599ce7fc366e240b" . + "e1cf98f21da5d2e5a33f1ee562214f314468244e213fe867886b43db13025aba" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "685b0fcee5651ef9a007a2bd0e5e9f371989e6dce1833b7bf5d2fae509d095fd" . + "685b0fcee5651ef9a007a2bd0e5e9f371989e6dce1833b7bf5d2fae509d095fd" . + "52f9f9fc978d0b9ddac705354ff04b983fc16fb60dae53af2bcb9063313beeb6" . + "a1a6430319eb274c16f9e8ef6a525bff1a89e2e1f5d25d70b6a59daae0db48d8" . + "5c6b9e39ed9cda8962de796f46f6f21a731dd7f2eb18ceaa9fa0ef08f90979fb" . + . + "d38738707691585eb6692d86b94f8acea03afbd18ff2d1c0de8a087d69b5e0b3" . + "afc72ba6e6440e4f8cadbd4acb78d678bcab722eb78fa43e06fac3f4bc264c71" . + "12e45a55704212fc4868f9277895fa119ff7d60e8718a45d18074d3604ac9244" . + "ea86f60ef63a3a8a52fa92109bd46e26c3531593f9fc378d389e981cd84b5528" . + "51a8ff071abb668c60ed4b00529af4b2df28743b648e5005236790e76704a3b0" . + "f6124fc66bbfb84dca0ff124a4fefc45d7f4d3d88c813958cffa3600ab69f53e" . + "e8c4fdc21f2ca9dfe7f3f453d3cbd781312a1f426d9b449c2c595c2ed540a9dd" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8e1b4647001685e7943196e41ba8ea4c6bb3716c567e669f1c9dc7f8775e2601" . + "8e1b4647001685e7943196e41ba8ea4c6bb3716c567e669f1c9dc7f8775e2601" . + "182a9296b9ad72b592e68679dbbf7072a7bd06b32df8731321684f4ea63ccb88" . + "a08f163eeaf51cf3559c1b1c633fcf53b9616fde677efe77c1f53527a1cfcbe6" . + "c578199b10f6dd52a5039f706f4f2a8b3c2a115d1acd2ebf834fd72627a5c7b2" . + . + "2e1b062888df094caafa06d94fe8cf1e27dbe35d0863b82e027945c485c2aaeb" . + "935d5b94640f6d969738fad48a092e487be5904f3d4916678af6ac7d3d1b2042" . + "a90950f1fff861f731668d43a0f609c5c94b0339a7dfef7e12eafdc538293d24" . + "640fb04349b5f12ba5431812ec7a8d0cb43fbe44d68f214b2b9f5f941f16539a" . + "bc7aa96a670fa9bc7079ca08bde8e14f12a204447033c774df8f1969cd38e612" . + "47fc7308fa91c1aaf3a7487ea51a78acaa303a4beda346c3e448aa39d5482603" . + "1116fe176f86aa46ed78cd4ed74fbf0ca9826f4f9876fcfaa9ba7ab2355c0fca" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "ea228c15dfee7c0e9fdfefbc10e4a07511fb7f868f5fa9722f97d8a276b1c739" . + "ea228c15dfee7c0e9fdfefbc10e4a07511fb7f868f5fa9722f97d8a276b1c739" . + "39d1faa29077fec03d2ac8fcfe3a72c743b906e81e105008be8c72a5623e7227" . + "dde6db3d6421b3f92123216c659fa73203b8d6fea4ed39de35bc42f026762ad8" . + "7e66020eadf1658a113af38fce1da6158ab54cb7b23ab1751fbb650f902551ff" . + . + "57d24807d20a341093ef3a50a166d025d9cb343ef88b8bc40b7c97298410620d" . + "2eb2dcbcba9ea748dc32113f3043295a82224a1bf28540cce50a076a12c3f561" . + "e57befc2ced1ae286b3c6d697f57654836992af79b5830193847fbae283f36d6" . + "99a2e1a3b9a871ce4452cbf0f48512ab5ea16a94349670bb97cfc4ba7fa69cd3" . + "cbdee5714d845a3fc070c21ec8f5dc44e92ec8ac85a69bf554690f39f980fdd3" . + "46e44085750742a3bb5718c5a2c776953e761cb3757ec8062def47bcba8e059a" . + "187d6eeb01f57002975e5e35f416b2a6c0d7719382b73c2869d6a5f61a0dfc37" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0dd9e17a794cf697e144e433adaf0199b8dd0ce7bffd0d64b6a20ef29d773fba" . + "0dd9e17a794cf697e144e433adaf0199b8dd0ce7bffd0d64b6a20ef29d773fba" . + "a2cabda81d87b31c6976ca218f68b4cf2c11f4d6b7e7f293db88a332be775b67" . + "1010cb862083a82b7d1b0e3a72af693a22f1b557e7e3f7875134278a1548c8e4" . + "780fe0e87010a4937b9c336c9dff707f630f015fe9e3e3b24edb102bc3ffb95d" . + . + "503997561c010fe6b9961e6b53ec3939d71c26ed1d2e7ca73273e2614d80835f" . + "71a9209c237550ae3289a0dc9f3a53f2f7bb54dd1faab0183f141ac66dd96009" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "d039fe2ee4200f54058dc094e21d539d809f37ee883cc74af54fb85d93457bd1" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "d6b0f003784fd2974d55d413145fd10bc93efa75f9f306f09367e0e20bb4ce8c" . + "d6b0f003784fd2974d55d413145fd10bc93efa75f9f306f09367e0e20bb4ce8c" . + "53be02edee29edc3ca019101568b0d8fd29b7a7ad6ca7227a06a01719e121518" . + "7b48343b1c51642b1135de004a970a7643083fb97910b260cdad6cccdbf2cfcf" . + "838f9abcaebb88dc83151526451bee4d30c03084efa9190521bdac5e6aa5be74" . + . + "9a6353c7c7c2ed126a945051214f8ec4b4bfcc7cd4a51e2c2fce263025ca9596" . + "fd8fa981c77b418fa284228a7f9196eea00c017d52b2af6b71983c1d2ea92084" . + "d01424664c998d5e5356b8569fe667c4ff4cc882f336016970589f6105144561" . + "faa441b0793344ba2b8272477283344fee48ac6d00dbc6876b487a956f4f200c" . + "9a6353c7c7c2ed126a945051214f8ec4b4bfcc7cd4a51e2c2fce263025ca9596" . + "a17dba517aec17ea15e1a07d01a02e39d224bb41d7868a44dba4d7d2f23db5c0" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f2cea899d9b4031d0ebd2d5063ea1a4b7a8f8eebed1c1f610d3fc6f95aa2a32e" . + "f2cea899d9b4031d0ebd2d5063ea1a4b7a8f8eebed1c1f610d3fc6f95aa2a32e" . + "01862916a7378c7171be10e8e42a2c8fe83d2e8343306cf70b3ac95a72d2752b" . + "2ee13fca0a2a054582e6025d38ecdd30c1978dfca2f6eca6bab76eaf8ed49fc0" . + "15d296b68f4b513c93bf23d51e91f55e7f4af841da38e44da429a110aef24e07" . + . + "36c250f9e9ab046bc44b37d36cc7784561d658f6545272752d88c28bb9283e22" . + "5c303f5d5a8845810ddc851e70ebd10d00634642a49044a16c65739916ea8c06" . + "717be593db8e5efffc77cfe71cf8e528acfb8610bf41d9bc506c1c7298dfcd79" . + "f9e29daf6345c5e4bbaee79daac8d585ca262df5002642f970eb7f60954cfdbf" . + "36c250f9e9ab046bc44b37d36cc7784561d658f6545272752d88c28bb9283e22" . + "8db3b2fa3414a20755f729a452221a8132ecf0de7144d747de03035073483722" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "93235ac544648b6a3c0967b8730d8e37f1243394e3f3d2d2ee0ac2beec3f367a" . + "0d6590641669ef68a36734034545cecbd22cbe7ab21a6e9fd5211b4b32e936d6" . + . + "b195645b9f6378801e820d042ba79abfd4f68ba5f9af5abd8435de16e7e2c8a5" . + "10f2446968bc963ad1d6476ce6df1eca294b77a4771626ff63cfa67809cfacee" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "f28f3d0b3c0c546a268e3e8dc487c5a45d23457e4ebf1b67e654779e91c9aa22" . + "1dae872b76892e5519dd9e12629486acf7f8411d4b00f046f89d2e6ebe5ffaf7" . + "57111262371076a92f920c44d6519a95547b08ceb1f77c03c8e754a97c646b07" . + "cf608020d7546a075f2d89278b648d0f29b91d0ae139d9d349ff922adaab7337" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "20374e6c6f23272c6c0e3782ce3df2e6059b6a638ba3570902e35077f75084f7" . + "20374e6c6f23272c6c0e3782ce3df2e6059b6a638ba3570902e35077f75084f7" . + "a970c117b5086b15000086785464695fa6fe6680efc69621d0ab5c5ae8be8be2" . + "63489a9b04c1ce6b65c7e986b1eb40a331db6946b06933072f33613d0791eaaf" . + "c0e4891769d9a0cb71723627491ca7d7ff04da39cb1e46892708bbc0f39a1854" . + . + "223bd0eee125a28a0320156d1f376cedda91ac3f08173f92ca35faf3f19eb8d3" . + "2838f761ba98916f108872860ecf2edff0c3b68a301eadc323bdfe317defb197" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "223bd0eee125a28a0320156d1f376cedda91ac3f08173f92ca35faf3f19eb8d3" . + "ffed2fce2249d3f615e3cf6674f746f9f054d8e311803ebeeaf25876be6e16bb" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "88089429056f7f6b70c591b72693ef41a030980144f22ffd41be8ed5a39c1625" . + "88089429056f7f6b70c591b72693ef41a030980144f22ffd41be8ed5a39c1625" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "b066ead143fdbe617070d710c737f12b987b15f014c7bc32465e9bbb38fd7a32" . + "3ea14ed533b5d41154a080e4a430e70f2cbd970c6a5d465e3c08cdb3ed64350a" . + . + "2ecdaf6b48d5438f3d6d009d41983b49d71b5cc4de278acfa4e50e110f7417ed" . + "7bc7e022c7bca252017562f154b7ca84bb0bccccea59095ec329bf7254b896b2" . + "90e066af0d50ee82fe1820f171c984fb9c324d4f0b10b4b1180c7e8cd5ff50dd" . + "181d13a4cbfaa9cd7d3fb6b3e53140ce77d8aa1e9966fddea5ff06a665282e7a" . + . + . + . + . + . + . + . + "2ecdaf6b48d5438f3d6d009d41983b49d71b5cc4de278acfa4e50e110f7417ed" . + "94809514e63727a9e77a03e00fc42f1eda75e0caaebb02fceabcd76ac82ab3ea" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0590c6ea96b7be29e4beab7a62881a32bb292615a9860bc45b74757c4f00081c" . + "00bd594c7f784e126788e473e2e0f375d0dde72eb65db2f87c49cd07323e312d" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "db68b04ab30c590552bfb6f56cf93afe6911e3bbed4e1dfccf3e928a35f31826" . + "a4bd3786a23da4b4834d009cac9169b13cef4da698be660f50a9fca1b7e744ab" . + "07b742ee319d02ea5c6ee3408c55b9c2be77c8aafd933209c39e94e0cfd87da3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "1bf2833f1574192a6e228837aca10bfe646c38f34ca37e88eab7472d873c5446" . + "c07bb04f6a4e0fdd4c2a25054105dc734847699e9b3393271dd7e534641e7561" . + "a2cabda81d87b31c6976ca218f68b4cf2c11f4d6b7e7f293db88a332be775b67" . + "e2e2959c472292c010f7e6073b9312d6038c03c7c3e619bd2e27dc00f67ce503" . + . + . + . + . + . + . + . + . + . + "c1518e3207a76c52a6b9164711ff96a394370f30401efa2c7e7a66ebdfbf47bb" . + "2299879848caf63d39798a02b054ec1cbf720632ae08474044a187fef737eb5f" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a0c68a3f18e12cac1021cc2abd810b26b99408b380e58f5c71a9d26843ba8737" . + "897de7951eecc6ea8e8a46686a353205d82ff80902c26d0d8f2bac8e8c569b55" . + "e785896237f9cd6b78c1b94d5ece05c0182e7aeb82063a507a375c457f4b765f" . + "55b1ed4f060376f06d1494e392efa4b73dbb4391172ae9a73da9b2d4b899a19f" . + "ab84d8de8aab9919dfff174074e7afe53be7e1881f729c01e8c8c8a7398c85f2" . + "7fe62fdfb62822fbf51e8aecd968217ec9bce5de093744942dd554dffed3859a" . + "7a8f661f1f5e20df57654db825b40d70965a59de9ddf8a832ce3278670f65243" . + "cde424a0ff8c570d1e53b80545e352317a8ae51663768d478f190e535fd6ca86" . + "f98fa8df8af89b026ddc0707e50ec8690fa50a4ed306420603ae741a2029f7bd" . + "36550736b8306a2354bd18e759d583ea659fefe779520bd58c244788a2dbbc1b" . + "574f4c0702eb41bcd8855be8422e0062784fb0708d89c37c4e47820991a0fd34" . + "dceb09a820197c85fce36fb0c69a8b166bd032e62941ad8586fbbe5d75a8a9a8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "06d65b4f5cd7e422e136d3bcefb5fe798c5d0ec3f21e23b0bd8b1ebf95637e7c" . + "e6a608fe6c2e49af8b0bd73a0681d8b81825aec245c554a47827cd359edd375f" . + "34f90b1a3607e7c2f2184fdcc209a72c2432e34236fe2415b4049d342367b81e" . + "4859ee6456d859151d224c7af7d3f763015cdb7b277289ea2e0ce07a1f61545d" . + "ef6e770c416447bc0edc013b3f98217f23eb56151eb901e5a10f16bd0f8f659a" . + "2a9fa44388d3db8be677fdce62d9345c87f9c5951fed1359e79bb599dcab18e3" . + "81a00794b8dbb263c353458840b92acdcd0670729b243452406f09fa2eeda5e8" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "29c47fa10f0a1ba6e0ffc47775292dc758ca10738062dbe699f6367ab61866f7" . + "9911ef98c6bb7beac9078d86fb5e9bccb76150a6435039ff09c49bbbf56a1fe3" . + "a740cb31de3185402ec3e0627d89c4b19ab2869a83dba36fc300ccceb1cc6d28" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "c57a47e8a1be2ec8c8288fcd7c771cbc0d43ede5365d1e6255252c40b01df571" . + "ba6931098b539eaec7aa87b95aaf0205c673480d35f1d17c564e357db4b774f7" . + "3108ea50e351957bf4fb5eb0a66011a824403be783bc16002cfe151ebd011b77" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + . + . + "7afba7c15499c6aa04466a1345c25df5cc9fd994c94382d3957c993be68e1910" . + "eda5a91f04d09461d779a667846fb717a8ff24fc8850aaa6d10f81642e70bbc9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7438664247cc1aeb48ecc5bca740a5ede64af04af6f1ceffd99c64405a7c07fa" . + "6a8f51f610b4b0073d9eedd2fcba8d3551a6ae6d3b300121603d81eff7636249" . + "d7bc7203123b56bbeb1c0b082e7ba0941d9ef46adec4163416e52b27f9c83672" . + "05f01e21306e096adc0989c24720d19580bee9d79bfca7204e6b9dba0ee78ab8" . + "86509a731bdac115cbda88609339884fd26c0be78e96af21ca34842222d90c66" . + "7a616ca96ba689c60a53790289bc2f8773b1735802bd486d0651d1c931b63b56" . + "07e3c7011a02dd7ebaf93b6fe4866d153208eb40bb63b5d2149e1b8049b205c8" . + "c12ad3bbeae794e523a237ae16a1380cb28284ecd843614e3c598685387c538e" . + "3cb649ff0affddd28f8712afac09b7f02ff8186baffcc598c259ab066d164462" . + "5b46885d93a83cacf4beaa21e20fdc771f0b3fbfca178dded96a0d8fe187e06b" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "bce34441e86d35ce25bd2d6bc119f09ca45a28b1888768589a0fb49b120eb502" . + "17229220c1d493981e7174e2e17314fcdcdefb563099d36687dc9b0904ea69a4" . + "300e710438b7b1e25ba243d92a07f63a3e4f9ae8320868d9076271750e855f71" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + . + . + . + . + "57c93ba15b0968431074d0731457ad8b20bcec6927d2dc63d1163a81e9471856" . + "52a3fdd0c68b729cf8351696cb25ef62726affb285af4e5b9224e2aefd45e3ee" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "53301c640bee4c3dc03b8e801d8707212918113d32346181f3e423132d014c36" . + "4a08c428008b4841ab56d22e4d35e3761a632906fec9f1c4700ac051c8ffa92e" . + "3818e6a27f556c8cf3cd4c8898c2790f5322fbebe9eb6a3d3cb9670417797c7e" . + "464de9bb90d7d59e2590d3663ee0a37229746800f81411784cf615186d049ebe" . + "ff9623c4cd5d9b04cfdc284e425266b3d62c25c7f29e268e8b18a6c993317e48" . + "195977b22fb25485b2c1ed9ee0a1671520eb01a2a0fe897467981110d2464325" . + "6b0d1ae380652ca416a029bf96d540960b56c184d4ccce204ef76a496f8c75c2" . + "b667d02441a8968a9acfee0f0947b416023063c2b40808ff04ecdd92f526386b" . + "dbe150df787e37db23a58c89cf88b674e9fdcc158a0f59559efa007f7e175921" . + "f5d9d3a8f9a89518394cbb818b9e798cf83251065fd1e3a510798864ab7aadbb" . + "ccd1765b07f04a3fd756e35cf0631f49b09b248aa55080c50466f3204dc7be6e" . + "09d563d0a474c64dce709a8cb239661728d8dc30a1ecacf796455660889d9e91" . + "07a80f75e8d8978526a1ac46e520435bac1a88c51f4968f04a1f17422383857f" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "7df24300092b2929967e6776f754a6f38312bdfa84992f027c6f12318abdb3bb" . + "e52f538fa4f82a82cf824bebb1c13109fac8a3ccc5fd58f291eb3abb7b3a639c" . + "95d5a794e13046e14fde3354be162eb0c48515cbc9b798d3d3d453a573b425fb" . + "71eaf5735c35beb1affefe23c2036aaf9e16d3513d9f4e4e16128ab329330e39" . + "9afbe44d58d3a3469cab93869900298f088ba9eff88d3fe16ee9b34ce201de94" . + "0e0fc6912667ff2ff0a2585f4acfc5117fe3a908e8b6bcabd45964e8e3bdd73f" . + "38a56f06cdbacc08d78ce57809832ef5f64bfb9ce9c831eb52d3e86a00c0b199" . + "48b7303cecaf75e29e9181114ce13cf7cc08110eb6170c31ed1dcdc2a53ab820" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "a0bd06250d7bcc2641f0d72a92b6ebbbbdca737fd2d9d91cac5383488a2bce4f" . + "f03104ef95686d110f0c6421dbf28911611dea503e8a876c13ae27abf7045620" . + "57e476262d6a5e92c2cdd09b246cc1d013da4fc731efb1ba18f5a9db3832c8bd" . + "f464cd14fc43c86fde02e2120e225c8a4397b766c48dc18a94033791466f0255" . + "f23a0773f3cebd06790d2805349567d78b861cd630f1ee1164d0eaf694401c1e" . + "77cb7afe010b93ae4e29917c70fd20abed0bab9e99e48aed24a4c3ec52df1bb1" . + "97a66a82536398944ccf5c2c42eaa4de79d4ad44f725380ac902f3e6826bdf3a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "19a23d4efc833d547f687e06063288e99baeac0e9e4ce14fbdd43cedf1f050b9" . + "19a23d4efc833d547f687e06063288e99baeac0e9e4ce14fbdd43cedf1f050b9" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "ab4d40ad205c16fb88e7db5cd1d2f6abcdd4b40592b947cb3dc540d09c8659ba" . + "924b6919b73f36f264b4cd2396c506abfb689d686505989a0279ee14eebd236e" . + "832468701d84be7874b94405081ed48404e650f3e4ceb41bcf2d8e51c70f1eb0" . + "cd7209cbe01f62297733cc3611232b6785082db37a0327466438cbb6382f805c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "157598fd873f70fccd11487236675fe7a7b3e16b3da1dc58c2f7cf7da7c01154" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "db43922e61a64ef88a10109b23e47fb7e1830d5457d2987ab9931b3ca20a18bf" . + "aba685ef42d767617b7b9e34a6419201ad450bc2257ed161e50bc58008db521c" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + . + . + . + . + . + . + . + . + . + . + . + "9b895c50ec75e9ba3024dda59a503a8427324817ed5ed09b94928ea9bf3fd84f" . + "5ca232920cb506ce8cf04a31f624002380dc34153e744ba9afd0e933b763a61a" . + "625502fcc728ef1eac9c8b69a4642e58f173c9093769872acf3eca844b323418" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d3376a67518fd892fc1bba479e584083e35bf1d1890e5f0f6520b2da1ed9b307" . + "592763f5d11b3dbf6d7cb3dafff1ac2116c72acd5b96a24c623ca12633d36470" . + "93635235efc768848a09bf57ae728233266f3415deeb565d61625d9d1024eeb9" . + "8ec5393364dcde40eed10593ca2ce6da9c20bf43e211503a277e9577ab90c739" . + "0a3104002e8e50bbbd45c13180efd9a14515b547a40b6b989200ccfa89a726a7" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "4af70d8aa37bffd43d15ef4bf95f8bf326292e432eda8a82647b4fe0fb6cf503" . + "a4636ecf7948959d27971ab37abaae92f2e57fef274c72ff6e971bf421c2a328" . + "13c9055fb23ebe6ca851ec136c753ea620b55f24fee2588a7c4c6ab9124ab120" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "9c8c7de272e7e9acedee8115eead5289786f995b22416449ecfbfdb47cf612d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "1d24c2313d41f121a25c89bff07c146196507c957707c6f8e2641065bedf8a21" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "9c458b01855c8d1614625686f1833f2578d8882d7e6465648d89a3e964220340" . + "6f5d65e529aab58ee4fb286e9d1e080213ceedc31923b07d983457782e63bcc2" . + "faa441b0793344ba2b8272477283344fee48ac6d00dbc6876b487a956f4f200c" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + . + . + . + . + . + . + "2b77337d69363e811b6597f7b6e893f987dbb2c483a6084775c015c445505cb1" . + "d8f056931237a1e2c50493fe2c582acc0c75c59f8d44b838c6cbee4605527bbf" . + "42927bc3b00b8524bd813dd930c1edb180718e82f3920103db7727a76413d077" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b5ed2fb280968c7ad37010e825855c082a066109a82979046dc123d3f803f9f8" . + "b5ed2fb280968c7ad37010e825855c082a066109a82979046dc123d3f803f9f8" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "0a73af06bd952995c8ec3f62b2460a1400be21284dbe84739409196358634d18" . + "d561145ccbae809d0cab5acbd2e73af1938398bc81feee7af9e19b2563bb4140" . + "57803335564d9b0c1267a4af4eda4452813a5cd117f48dd9f4db2688d7c0e4be" . + "5ec7d911715623d17d1d06c6393bf03fed29c2e2c09d5634ad80025567fb6f89" . + "c8eef1dd64fa9da5040eac5fdd7d4b8ca743cbdba11bfafead500e8b35cd9f19" . + "495abe20f54f1f5d7c2345ec4b97124bbe1e8caed63b30775ed713fef1562906" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "089f15de20197661f52aa68396e96cffa30477bc7ace260ffd2ad41969e590e3" . + "f9ac7385683b4f21dc21de6fb61504221c87ec6078f71179833c4fd4e2e9773d" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "fa53c0a2a2a00dca94a2dbb4839c4805b4c5b02d9b103f37c6a20c80356e9e7d" . + "ca0c5fe0c07652c86608d4c24b2d0fa912a641f42afd766c68a4c9c5ecbcd099" . + "256819501ec71be5c17449964b878743c9b40fa03b22d2ec0152959bfe1dfa0c" . + "930ad887f576505180fd43c65e15e4cfd6fe004802432530fbb735e908614b67" . + . + . + . + . + . + . + . + "08dda8f080fe3b7a76caca702f10be7b0f6b1587251f084e6bc2f1f98700dbee" . + "8f599f46d091648e8a12109e31654ccff835c52d98efab74f7cdee621714518c" . + "01947c83b602555adeeb26049f1081cb975810bfc0bf4457eb2be117a9fcca60" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b451aed6531bd2dac2acbe02b461e0239348fcd5f2493ce682bdc540d8fd8e97" . + "dbb93665e4336ac4a2f7bc9d219bba5934d50d2b8e8dbb5afca912684f6f6754" . + "3f515c18b6e4d85f39cb4d5a393ff925eb703cdd9226852b83434449ee12715a" . + "b6b476845413eea13fe5a9d7c967eddb7f058ee2e5422b35c619be4eeb4dc90a" . + "1dae05e52649120343527f8a9773056afbae379bedc314ff98640e7099103937" . + "cf3dbf97e83fed7cfe9a74089048ee9dad38cec6f50779e49a5be70c05443858" . + "24ef9b1e8fc4403cc0ccaac06d8ac4ff716f470f83022545f88c1f28aae0248c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "592df5e2270cb6b3d848bb3ce32906b2d1a42a3c5ab2d7955eab4235df8d0d7e" . + "d038c3332970d6c450fdbc9c66c34e0657dd53b0f72d3ca75eec6e5a35f421e4" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "f7c3b12fd1e5334d20d64d4d0dcd1885bc49cb0c02e249857ba4ba9d3aefc657" . + "7d4457b638687fcd46f3a52fd0c4769348474c0d3232bbd52f40c576e3a4e156" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + . + "b0f57e3d605bed2a906aa4b5d64ff140cd785e90f185caf138a9b29bef80bff9" . + "cb7d21d78902e2768cbe61cc47aa31e4aec27faa2f0c6be232fc786dbe523984" . + "54220371f180c572804dadd1bf03fab2d9f04b10ea56c9affcbf9255baf4e0d5" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "3485a3ccd83d379a00f9b3bc25ee715678209b3de94ed2dd743ded861c7a847e" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "5ea8f2c4edd62f5b97ad220901a199a1fd407385426476ae8e7d318a826cabfc" . + "c0aa94d9389c6a598a182b2a1684a8db38872935d0bc6aa6694e4f93a89333ff" . + "18f7b8e3a5e453cd3ce5d6f51dd51443002b1955198b2b2d9f44790dbdb610ed" . + "5f70fb245fa5410011d3a16fe11f60b8336cec88a87d93283040595262d6fbe7" . + "681fe63cb37ab12c0e230d3b449091f493dff0a67f8ee46dc336351c88604b00" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "85ef02547d9981000d49bbd8685a9f42eaea89b19e0afe056875b7ecf5e051b5" . + "d80faa13f4875467cebb7e55fa52a6ade05f6e08bfa030bdd7a5ef58cf0ab152" . + "c1e108fd07a7bfeaea3daa948909a1e0752cb5d8f52d4a52cef731eeac583ed7" . + "9efdc4817d093747a4b0686eecf256f4b8906929552b0bc8236663f44adde2ca" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "c2e1535d42d2ff8873d08d9fbc1adc0fe93f7f57f21ee89c0e3ca8686ee040d8" . + "096221b97074fe9a8c48e8542a3ba57b9a41d051b0aa6d450a68c263f2524148" . + "46e88afe5b6f1c3c1e13e3c1d11ee2646707ceed8ecbc2c4aac68fa17f8fd6ba" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + . + . + "ac986e3b972c430bda438050f4ce767fa7708db588808369625dcae361ef1951" . + "a8ce4390bd940ad19a43a6ecd1c239f3d7848f2bd281a1e8929e453563afd9a6" . + "c47f2dbdee4fe9063f9c1a07d9b5033fc15e10346c8eb011e1958a12347b7a5f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c8844975db13f97a4a349321373c6ed68127299675bc83354c41bf31a400d10b" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + "0b0b4a8f4c2e971d318ffb35c49e3eafb62ef886d05621617380876bb5679cce" . + "2306cf9dfc173f3942b06b4f1e74c0a5db55ec556533aa12a4727579ef692b01" . + "dda8fe983ee3bf7c5b26b7d35be742847438001a057588aef89e5b0ca3f52239" . + "f85e4cf6c23bc676d6161677a602ad8cb6dac4d038732656f11cfbcfe3e8c6c7" . + "bc28797f80178d38838afbafd16b023e4410d69c4f902ec6b41b0ec8168228c5" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "83dd9957529b255aa6665d51e8a81522c58aacfb79b243c490a5ef8d3abac06f" . + "81ca2cb3a9dd1193bfc34ac0df292a27be6bd1fc2267b39fc96089647a081741" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8c643c80961a3c648f4b983f271bf1707eb1aa6eab3f3e773f0999da3763b6da" . + "b94cb3671260116ca6003036c18fdbe40f0a8c0bbba6d5e113b1b6eb33eb1e17" . + "ed2add28acf0086c902c2053eeb7771304dc1b091687518ee43c3af6c4a1edc8" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + . + . + . + . + . + "5bdb4075705299832a217b39e3be9a13f28a497068c9a77709379df390950905" . + "267240f7e747e25eb212b7e84cf4b5adf606630824e4a65985c5c1c34ec6fe6b" . + "599af994bc92530fc594bc4dedab70f09d1c0d613b81634cefb25c39af8f86d7" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "415b03303b0ac80dce2660cca50474f68e1cbd6ce6fbda8535dc348b1bf7dbbb" . + "d58a6d5a3abb70483359b6a1b084d10abc46282197169c735f9cbaa6ea70eeea" . + "f039000993cc05fea6752e906fd88782dbb9c1da5675686359303918a26d32a2" . + "003ead8d0ee5c9fbb2ec1e4b19d26dfc04534138d7354106015ce2b73b7d3090" . + "8347b2768e7ebb7a72d0ce45d64fb29d8b3e930e3e09060df616f40cd1890420" . + "4586942943fe448923905bc7adb62c1ceeaf1dfcdc61bb3b051d477cd6d0910f" . + "2346bd88a3b9c4bdb86ebba6d4a18a068a107ae34b3026c4f090841937113df1" . + "8c02a55653ac00efb29e66fbdf1d8dec30e894c846d8fdd5c7994ced5d4c866d" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "ffe3cb8c93a5abf213a3d00589965c3387371a224fb097c2c7cd6b0b694b76de" . + "2aa8ec7d6e5ffca04b7a089dfdbe7eec5f6ba3106dcfd05bfe32be46b9e96b59" . + "12d245d6577a13c91fe4e0ba01e984d844768e84c3588aaaa51edd9305e1148d" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "f66ce993e84f060b62f443ada3ab68185a8850303989770d6a3dfb7844c55cde" . + "81d93667443cbcd4fdc9e0fad2f0ceb555d50e18d080fc1c79068ac7583ddd17" . + "b5d980df2a0929cad9348f5fde23439548fb35670ef7a88b2c85826abbab600d" . + "9e4c2bbbdff78dc4d3c58e9787975bb36aa609e108a03bbde8fc89b78a4cfdc4" . + . + "f66ce993e84f060b62f443ada3ab68185a8850303989770d6a3dfb7844c55cde" . + "a812a61fad3c987e7142d090bfaa675fd65e8d5ed1850b09a2c86865ba4b4d46" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fe6730bd4f32971eece3c58ab054a2f50634d1034594889c666bca34604603c6" . + "3044bbd38af209063caca306681f13880580e39777bc820caafc548e4d67ad79" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + "a17e49c9f2b4e2037081e9530065d96131db485a4a7a5aa235e643c6f6461c9f" . + "64dea071788d09ca1d35c4da218c1d5ecffe13a6ca914575138d0e5c8e78d78d" . + "7e5e29b650361dc86ca877b45e524b30e5ecc019ad1161ae3ac64f7b61d39b10" . + "dc9699f7a6b14c95858c4241fb3f58cfa273090a4f7e0b94b375dbf09166e537" . + "6050ac4a948ed3115259ccb679d44692aa13c9c35eb76e249f7ae489e919eaf5" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "8bb819987cd6bb7a86ade108ae84673bb5f01a22d1c45b9f831cd39ab04f42b6" . + "12168ab4c82906b7bdec28cd1cb80f00b3ecbf692d590be29f023724c3985e62" . + "93741b7ca6fe56a71e35d119439cb7028673f48e673da3505ba9f0fdf5907e80" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "4d9cdcbb86f34953aca90c543825816b0c78bbde2ff9a2715df100de0c649c9d" . + "c924d77495fe46fed113f790b5dd2e5c1d9e308750ba13ca241d69ec3919e724" . + "643267c744c2eab72cdab7d120cd25f13f6c225cb92f7d61e6c944c2974fbf2b" . + "e1c5795288e731c10d21a44c19cc98609fa4f86e1e6b3ec54b736e3ff6692a44" . + . + . + . + . + "4d9cdcbb86f34953aca90c543825816b0c78bbde2ff9a2715df100de0c649c9d" . + "44b29d383257af254774b1511180ac8ff418f4365e3bebf09f56f361d8217404" . + "99d54c80794bdd2a41b1343d251aec41b9ab2048922e0106515d10f9138a5573" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f50a064757ef0e48460634cad9ed95f0077850456c0d2fc44d103cca1fd9d5e6" . + "4a844a2257c9ac26139e641ea17b3bebf2feb3f49ee77a5e092715629a4de1df" . + "ec6c33f18b527434fdfc900717a32e28e798cc36cd006010592c577cbc47c552" . + "a80a50832f4143c77d6c8f527cf724f8544f545e706717453cc87fc7e17bfa59" . + "e4475911e416997b67dcde098f51e1287622eba8bd767eef9dfeb51be2190986" . + "b134aec189faaf9cfdbd108798ac2a7007d1022ce195f09ff4a1ce41a4259c13" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "4968e11d156f9295f93c9f4526391039650f64eb7021c3b493712d19e8da5850" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "d5b519b28dd4eaadae15c84c9b521f0ef94bd8d08c6f287c39a72b10db6b8d3f" . + "a59639464492a15c76b41d39f89494799f85f6e8778528487f5e75d010abafb9" . + "b5d980df2a0929cad9348f5fde23439548fb35670ef7a88b2c85826abbab600d" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + . + "7279e52031e998db0a749b679d6345c215c0a1625c28d73e538ec8b8a41ee847" . + "e5d52b5080715d0c52fb6ffbed8413607f4a280379cbf7f35877e2f7d6268927" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee7df95ff2117df1740f668510a9e56f1cc1b3fff59545c8d7ba40a3c11bfb3b" . + "9676342735e27bd6dfe63e3c42b74c983becabda21b951ed4237e2e87d21981e" . + "6a0baef946effc8a905cd2830cc642a2f93c683704f4cf64ce3e13112ff79aca" . + "46098a79406d66e9a24b02546abcaea9fa82b1f76e381d4096a19274f49eeac4" . + "40cd2d57d206f522f10a3e9648b19d24fb2651be2394c0929364c4377c75af78" . + "4f53887d4c35853b6ed9cced75799eb8b930eac39ede8f3c68ed6a6866f48eed" . + "5c3ae737c64cf010b691a8fbcb6e1d6530d4f1000ef5d82571bf57ededa18054" . + "e593cef41ba50f107a058f36a1a95c38e11dca0ef60a6c65ee8e88d76be64347" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "64c2c8e55147433a47ccc1b2acb92caba595c97587b6e5474c0fd3f87d632c9e" . + "d0e6e7cea34a53e9639c96ec2f91b5219f134ff494033bf3e4f813ed65214e3c" . + "47cda39d6896045f2103bea89a4a1073a12ae051dc4d26604187138dd46e30e2" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "6d6f303cedf38f2bad81c297563024299a7ca0e5202a112bfc2ec16a968298b4" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + . + "6a5c54bb9c37e32024da819546260c73bd3ea1cb015e506e15ecd549a481bb8f" . + "56b41dc2cba189b98018928c243c7c4ad33b9f0c9eaadb1bb909d8a6203566f8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d6bbfd5f58745cd9559143717db72e8b50a7ee35560464e14ad13c359f6e0911" . + "d6bbfd5f58745cd9559143717db72e8b50a7ee35560464e14ad13c359f6e0911" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "02aab2f69d00dd23f85c2d615b71a23896225462a805a53407cdd09c39bd627d" . + "b03f830a223153c7779067cbc1498b8ff63cfcfb30c1c0d066c0fc7f6097f894" . + "c318bff139dd9f9f3197c80443c4bfdc183abc852ce27af0c239d31e9a1fe37a" . + "ab8b66df6e2dda6012e0ba2c56f568ffce582ab07914444e49aadec9233af17a" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "230cb069d925edfaea967fff735123340e37a54ad170584d272ce1b626029b6f" . + "a57cb0f259252b0ef41eb72ff1476d46f4c3f488dbc2dc1922ea6db6f008e147" . + "c5d6aecdd0887ba2593a7cd623a50a21d9e549e85078379fda96b52ae8a247a6" . + "d2c455131d9ef83ae48b0d46e69aa623cb3b8531eaa2d72b6d86e77159ac459f" . + . + "230cb069d925edfaea967fff735123340e37a54ad170584d272ce1b626029b6f" . + "39276cbbcb1e3d97a47418b83744d1cbaeb577b235ceada26047d0ac4fef05b7" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c857d1f0ecdf5e19e271f52ea441121b6936059401cc9e794369da8bf87668f2" . + "e82be386610195a001db0fc9df55e25266d33f43cdda72c4f3051f927e16d4a0" . + "4ebef8c34a3e8466f67ad1f088c7aa06d6cc63b62ab5f397ba16f851951851be" . + "c90c8e03354eef28350005b356792077f396f67340814c296ca006604164fe0b" . + "86181e8b26efbb620ad00ba8be96e1eee2bd44b88b9651f2e7842892c55a33e8" . + "fb0a880e18002959d5524206911b4abb552474efd1c271f828371f1f846042ad" . + "222563152378d51107828705a43e3cfd4abf12e6ba54be2f9c8e9fef47670d3a" . + "4bbd6f729854bfe4f690d65a6de877ebf463097b41c832f5f928ed8ca61d8617" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "007d28c6b291dcbfcc96fac45362a379eb51901ebec0c539cd2c63adb9b232a1" . + "e94f259458bfa3511bd4be3570a81ede4056265ed2232c648a41e9728e11e9d7" . + "7c68fb15341ff10675a5fdfa3cdf3d5e0294bdb1e035d0f567404eefb16e478c" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "d16f2c6356e9eff2f0506f8428cd46c180c059f3eace17d154dcc517e4701bd5" . + "fdced48af7c03c5177fedae3524c6f892f045499e50e24abf0272bc9cbe3bf62" . + "fcbed72acfd853d8df61064a2e72bc4a5364058a7e56b0529baa455e78c86ded" . + "5665231b8b74bd03b3c90ffda29f2cd4305a15b79d3cf8f44002ed39ed9c0c5a" . + . + "004560def75055bcf84a8958ade2fe55e195189eefcc246d44f073b00cb2849a" . + "3194b49e12127b5f54a931715eded09328edd64425a9d372330acaa243738298" . + "fbf4e657294924acca4862173ee31b86b300ec94f8c3e0cbf291c1c1921f35a8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c3a3c917f7bd23e4f63486bdf8d95e1a8b48d683aa9c253d34a3789bda50a581" . + "613f6649a6a5fec3ca5f5ed1c6b260953b2e06fa69756811d7f821654fccc5c7" . + "85955bb27eb52947d1de5a00d6c7f3a3418cfd646851ea6308a3c86ae4001b54" . + "040956baa4669c210d30912c6169edcf07fa7775a6e03f301b138198e68e1950" . + "c58c3aa804d9fec6fb068f9464abb778d38c54edd7943b37af49453d40183cef" . + "6e4f1b1a499b62a22fc174604566b1c45a8e8e8b10d2447f1067febc1b520c6e" . + "7c111ad593491a3a4df51c3c78f842283b765cd50d449cc1a09bab0def2fc1c6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "0b2b835b2a384737263c5de422d337cf70f0346f58d2bbe3e38366217bf28612" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "26e3bbd413989cefffbb42b7f7e0a93fdb4c13503f0ac7a9b848a014c401e321" . + "15dc72d2bc0874b02a77a1e5b821a00a5f8f12b9f5b3a135e3dfecdb8a2454e2" . + "0f94ce473060e7c5503d6bc14495551118663605be875c111b20ae9f9a3080b9" . + "bbaf699987824c322fe65c8d6ed4ca0c3829751beb4df4744843840df92fa76a" . + . + "a5d9f844e8f8e59c05556eafe5d8b4e90fea9289dc27c8228312fd09123dce17" . + "809245181c3a0bc75ee4cdd2eb10c6bdcbd90475707490c93dfd36c5382bc81f" . + "d13859412c0abc19baf52bc955f70fdf530e971fb96dfe9367535e1285c42548" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3e2c0bd29acb68bc71c319916efdde3dad2b5525886f05169baa55a6453bd29b" . + "3e2c0bd29acb68bc71c319916efdde3dad2b5525886f05169baa55a6453bd29b" . + "5d8a49e864d26e83f3eee385acce87d33b54742adde2f8009d5f68d76ed7a5cc" . + "b80e58e6363abaab56271e4b1953f65e45cc87bbb82077b9824971f6e2719d9a" . + "5a0e244df48971a7ccfbe3212fe7d69e56baf2b9b74df39c7e563f508ddb2562" . + . + "d9ae426955bbaae349bf59635036fcdbdb828d9e04ef8650695f9f8a3a9c12f7" . + "fc90078a8762a2ade51de6713e498a3c229fddd771e4389a94e55c8fb6717d67" . + "e593f5662db7ff660a0a96e3fb1d22a70d8e041ab7eb22957bf2335685264322" . + "4a93893eba7743f9a294ac076d15b8c0177f4db23e8cd930e3812e6928632c7d" . + . + . + . + . + "504f0749c0024d7ec24c399390729a142c795ceb73ff75e5abd69888902e85b6" . + "8121ffcb9b8ab6214a05ff5824d22e2162d69e990ce75b7e168fc6bfd631e124" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9439afa67637ec1dea25c233ec5160b7ddd4ba4c31fb292c91e4faf37f2594bd" . + "d57b49e541d7c56bd0102efd3956eed1964f60851d5ad6108f85652ed2f06aff" . + "e588c2c07ec0f6a3a150f56fbbf0fe8c28fe5cb2c04c7b86be645633059859fa" . + "04339d109f22f3111e24974c7617a2474bf051f7ed252ce96539634b4df779de" . + "cc88f0ac00b0345a344cc954121060531d26e5e743dbea6f008c2856756594e7" . + "78cedd80b456f399a427f59d8fb6c1b4fa1126d0d5fd855a11c4b7c70ffd3c1b" . + "1ce5753ceb97a741a4c8abc3b8c60db2bfbf209044d26fcae4d5e3fcf13b2ac2" . + "eb4ec34ae2eca1e4386761d54bc46761c5101990bbbf74d41d843d1ce4ceac54" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "b0d4d0270a778c4038edd42c2f518ae6924181ae18a580f0c4d76561df5fe303" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "25920c9f6dad5379ea8a38087658bc72ffba7c83c29617b4394620d0ee94d3d9" . + "2838f761ba98916f108872860ecf2edff0c3b68a301eadc323bdfe317defb197" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + . + . + . + . + . + "25920c9f6dad5379ea8a38087658bc72ffba7c83c29617b4394620d0ee94d3d9" . + "5478ae87be9b22854edf82deafc0527d0d5370733a347662a0075ca4f12e4d77" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "07b2d8f6785b69e3b170875c4464a3046727b2c64243312c9c7750e11f0fa614" . + "0477fc94b7106f730e33d4026fd9d63f5d62ac378c2e4d367e4f03dea0243434" . + . + "3e78f1eae5bc47dcca49bf70b429f0725f704d20a54481bd065178f91a23ba4d" . + "5819358f0ea1f5b7c5edaf979dd663205632ea17dde963b93ae58e79db344eae" . + "06b0f31fc4913ccbf61717d91bd368b0aa0cef1f9a909c134ea1f0113f60d548" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + . + . + "02fb0b2357584d24c9bb19a1eea3fdbfaa241411ccb7ee931db54903a2ecb5b9" . + "7e6b4f6794ad788cca2aac4abc2c6c7b503a3bf4768d184a6e4f29a87dbc890a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "047a5aa5c3d0bac7c9256cbd9aead8148c298730d4b70329dc59ba7bb7edc26d" . + "185e090ed2fce0a4fc8a17c521cb2611a16dc9adca18d67a3e25dae2e937322a" . + "9944b1e9eccf4e4981e518b85ba4c574c291ebd29d0704219ebf8f783f354eb6" . + "4dc40f4c57efda734b356fe4ceda348617c1d08fea6bafa605e703e3f7820335" . + "d5864052debdf37945ee1a2d10f7813c314399292b6433ff91f2a6574237b9b3" . + "cbdbb1914c7dd47f98c67d075303b8930bea3db616bb157114257ab0aaed24ca" . + "220ef9bc6826d950b18bb0097f03cb68b8cdd0548ccaa7e750adf885e839e174" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "36982eca112d04f0fa6f27b0f5d05deed7cfe867ad1f6fdba7d21dc308c586b8" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "65a8156e26378118513742d295fe1fc66667da3fcc6345afe92a585424efd7e3" . + "9e047a0d9ba06feefcbf41ec64b8d01d35436b180ee496b266f06f51c4447e1d" . + "33b94fce5230e5d90b837a0db7f4381f55f3a29f5c9eaa6759308c145e16d011" . + "dda083e579310a5e1dc73f23c3d275c2439902577f8fea9fa5bd84bcefecc152" . + . + "d9751aa56cb8f21cd3c4cf58b544008ec28d8f3cc6b361697ba7d3c7ed843902" . + "e93dcec6dc6ffc37af59fe52ce79fe3b5806e3a4e68fa5d5ddf95c3dbb178da5" . + "9bf408f9cc7acb9bd9b5dc0b2f1fdf87b775db5734a5043c048172f5b644f77a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a2088039f0feb546ead249a99011734dfadbd7a809a6de8276e39fd2b7ca206" . + "d640c593c85230457389547bdae54a20084b584e1dbb6f55e758fd31ddb41172" . + "1b09473ce520b4b93da98828f78163f3850ef3e55335b5103030a9be4ab98e97" . + "c3b994c1de36468189a5da9957284ab3c63a665cfbddf05b5172c9265f0fb395" . + "a471e2126d6f0b02a4036ee2b8527e08e7d73aeb3b1f8ece4c6478dcfd15c0a1" . + "f692081f6e1077a7f5a815fb347dd4aa5a42685c6ecb8c733d90c7aa708182e5" . + "0e0ccb3f499265812107a03db2aa8d1effa2080e13b0d495adc6b7feb94826c7" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "23669f174d232fc3b059b257d9724bca41b4bdb711146938c79f94954478fcfe" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "0f957dd63af72ba0c3a5e3cf473495e99e2812d2309b68b16e7d1e0c0665d02b" . + "9573fa2654bd2eacec4049f34615dd57282e4d712bc3113565534c81e86af977" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "06552071ea6a5f8efa252ffa62545c82c4236d502e35a8b372ed6cac136b7f28" . + . + "0f957dd63af72ba0c3a5e3cf473495e99e2812d2309b68b16e7d1e0c0665d02b" . + "12acadf70f445e926d0829a1a90e93948d0cf1410077558892097e2937f759af" . + "73fc96fdc6f1b674730df81cd61e0403beb159a945f8b9dd5cd6302bb10757a0" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e4b227fbe38ad1eec34b1bf32992fa914a5a62a2b560bf75abddaeba6323e286" . + "e4b227fbe38ad1eec34b1bf32992fa914a5a62a2b560bf75abddaeba6323e286" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + "421b7f61592ff7a557cfd84a3cc6b74ce034dd701a97a97a8724348442a84df4" . + "1371dbdc7486fafeea1f2cca8a9c4694895054b130092d279f9694b9659049a9" . + "81af0b902cd4e163537093be57ca5292988931b6c778e07730027fc0a05a4078" . + "f448de7a0af4866001582aadd7bbae860734704b1b4ab0d8292bb61a3c4f6ae9" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "d85393dbe335ff75a7ca48bc09b7237683bf782942c0c82c8e0fb1729c9be56a" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "df6f8b67a797e1aa6f4ad76601edac9b8516b05ef669298f3a0f33b15f5e026e" . + "88cd5cb4917f152df35e8c29ad76349048bedd9eb98d4771ff4f4486d69cdfb7" . + "01d60597b28656850786641377d5b98eac00f67c725452c3d2d130be1fbd7215" . + "60030e450906e95f0f20af0a0433338472cf2f31460348b0e82bda378d156c40" . + . + "62bbf028af9b60b3c2a3e0d340bdd3bfa321d19e608491cc0125ac76b938bd88" . + "9b7c15d991490428052cc07e6c82928573884964cc2e5af646507e9a36f6258a" . + "65fba6097b9275888239aa3d91ebe041974a621fa58fd70938e72c1837f55f0c" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "2374d689724d9be6c9252bd057a0127cf834a52c4fa9b20cff23c1e26dff0251" . + "bef5e9ad75efb752d990f5ec96ddd8c98cb5e1c73c968373a6e34215397f05e9" . + "a5f75d5c7c2783eb328182d731b220c8478fec37b03bb63709178271ed098a78" . + "f15f7d645db790db55a447fad1ccc7345e76b6ed99ec6c24e2c728bfa24844f3" . + "2a50142d7ef3da74171979910ce2c10fb36ebd86821a5f94448534916d713edd" . + "4e181b3e060a895ab6761bb09c7b56d855e4bfd15103a604fad56eadb44b23b4" . + "2f57ec08c8cdc1bd4d93090bfad573e9a7092509a6bd2f1510f1c7a5677f2a16" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "58b816098b30087261d8d21af782aecd7ad47f467a5a484e21d68772c023efe9" . + "032861b91de8be3f1bf2d8afc2dfd25c38552b818fa2f7b65db9d7d5d432a125" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "98c240568d58e3b59d7d3a4a8ddb62e5a1c1ed733053561657c8814546136574" . + "9766ce00fc0e3f9250042f09a80b88c66afc60143af91ca3dd0b139ca3acc0c1" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "af379f0121a758189b6deeb5314d4c194e7906492775bda049b97e444836fb07" . + "02113f4a5aad3f8869dfb47c582d985ccba2c7b548d8c8e51a12df05a0db6036" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2c68a6ccbf214eb7829c6e5341bd38c7ddd166fb57e8a992860ea59e3c867fc3" . + "2e382da953b02474178d3371081606e32f3a3217e77708033a435a8f71eb4a99" . + . + "d35db9c3a1f687398bb2c1c4ae973188f0155b28622e627c03d6800ab7546884" . + "017ebe7b395937cc4c57cb6b2aebf74fdeed4fe4ab8c4f68abf3c983b736b12c" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + . + "d35db9c3a1f687398bb2c1c4ae973188f0155b28622e627c03d6800ab7546884" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4e9950e2f31ce74eca540d7b92034dff032a0da07bf6c7d7cf853dbd7ab0309b" . + "558d5117706457202eb50765d22cac9d363fb0b5d46669f2459789e5971e357c" . + . + "954ec940c7e424b6ceb1a30213689e83200376d66cf904d2d8a336d94e954f34" . + "d762a729df72f35fbf61d7c7c2a0040466203840bf9287963ad1d24b589114d2" . + "c8956ccdfc6c3d30297114e581832018ecc3c4514edca3b47cbeb4c032fcd489" . + "c0c261c41c9d7b8881104878ae0f1992405641cb940af0b206e906d64642af2d" . + "ed98078e1982aa5f933a9257b830ca37a85af5bca31b8e9578865d927f2869b1" . + "9f9cff0a1f518e26a40ab4fbf92421b565b79f8d7d8392188c4094cc4343b1a3" . + "3969e46362b91cfa41f7dfe4a340daaf68981b134243faf7546116ead2873108" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "701b7fd24b35f19c7c838e75d73ce9c02277682333f4b1951645548b0221e6b4" . + "701b7fd24b35f19c7c838e75d73ce9c02277682333f4b1951645548b0221e6b4" . + "fbc48e66c7af983be3232774a1e62e69481c3cbba89a24c86ec398f3d1648278" . + "91a9df2561bfa2d014b2769a04281eba2cc680549cac84e07d58a2912bc0e5bf" . + "d6b853d2d74b4d7b26535b995b02c66979d850bc3eb2531e2d610db43fd19094" . + "8410df66a90eea458b33d96cf631c8baaa8f8f6f02d2d2338a4ce2e7fe09cafb" . + "263e775799c0f933bb6c1aa3c8b1d46a3b8daab08e2069f777a7dd48b0f47b04" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "d786f7eb5e022ae6530e3da7fc7787b314e7e95831fa9260f756471a3c7cdbdc" . + "8c3b4aa36583b28b59f1107cbb8e2fdab305440b31e71b205630a62492c62028" . + "dbe8527cd14146f64170947bfb7add545f9f94196364e2c7661f7a6901191f28" . + "9c7ab8fe742fccbc7de0046a52d20b383016075ffea2bc9ba6e18c7b5d7f06e0" . + "c26c24bfec0df340c6e29a7e24d58d1ef66450eae573d840cc4592fdb60a3902" . + . + "d0b69e98e5d69aa4e81c66bea302d5f16e7e96c61a0210ae8d32bee38efa641e" . + "1a7f7514230f484996da6275c28064d5a92ed69f1a9e6958e6fca1d9e0da08ae" . + "f75701893ce1722083bf062f127a524dbb86e3abde5c917831a2f484cdcbd343" . + "259ce079d0ceac95c4994e1cb858c4859f60fb08ef27f2b699120642643774f8" . + "d0b69e98e5d69aa4e81c66bea302d5f16e7e96c61a0210ae8d32bee38efa641e" . + "86ae6e4b1da964c3e9cee588c1bf074c8fc5e8d376f56bc50b3dbaa550f75649" . + "81f31e9a0ddfc90a9032eff69ec6baccc5ba5a2b490a4c44e4a82289c721d56a" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ab38a5c9c6e19ed42c3971d6ad53956f2e5451edc70716a80505e0479d9f213a" . + "ab38a5c9c6e19ed42c3971d6ad53956f2e5451edc70716a80505e0479d9f213a" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "3a961b23a796d03ec820b21afef1883add594e4d2d881ecdd5348b3c4446488f" . + "83a6eb5f4f9fb756f3d7a57c83e790cff3bd2150daa37d495a79747c870bf451" . + "84bfd98c0d2f4790825179417f5841c90af6805c7e85a2ee4ae3dbefbdce12bd" . + "b3b08ff0d5cd85a8b3be742639e918e9523d964ed9fdb15ae13b77b72b213ccf" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "8d83af47468813e862001faf8f92360705666baafa9de0af6f231008eee091f6" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "ba707e77caf760144170065c10a1fb2b43eff09938ba37567623d4d9ef881bc0" . + "8dc90a33f9d4eca508f8c8829ba344e9cd048118540c4369f76c15d0111438ca" . + "2b6aeaccac7aad724bd5e3aba5e14528bec973a037aaece86a3c9de47224a7c1" . + "f83a28e6c07b05ff54c5d87150a186632e17376032f27d813076efb2474684fa" . + . + . + "405fdf4d0be2b170a64aeb680e9bc0961f1ce545e420354c9c32228bef6790dd" . + "c2b9e9e9a640c2755f86ac1d43daf1887f505dfb2c1773118221c148298c5a1c" . + "ba4004e9cf651bb774aaf00a159662b50b7990c5074ff96ffbbb2597eae3720a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6e70bed26947e38146be11495a31bb3669f582e4cad16fb86a1fc8c5bbd9fd62" . + "ae6b502df8fd58b49b9c1d16a0d26fef5283d069dc31f1cb160a66b64141c009" . + "28dbceea56b96519f5abd414109e03988b70022e9799faf1ccae0df5f97e242e" . + "231305bde15debeaabd49e195d186d7d5cb6098cb8bf5275566a4bcd88234472" . + "e89bafff5bab714feec034ad41309bbeb1d1806bf50a49ad63ed28129fd05a7e" . + "a28e4cadef89275016a39e643f1b0f594fbe5029b0ad5c0970ccb4c55dd69074" . + "a1ced873e7abd9e877fe77023057765271de7852ccdfdf9b57cb04d5cd6acc09" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "69c5d41550e4e39d6c26005255f51f13988492e2852b9d818cda02c3c801fd9b" . + "870ec9d550ab5deee28db577b9bef5c644146d632f732a8165aba250731711b1" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "0f1a30ce5d554190c5e34ea8c7f6a885f508acfa3e03ae3ea6a3bd8a4eb4b246" . + "72440b9c7b9d06e2dba3aab5536ccca16c73f0fc39057ca20701fe57c77da80a" . + "26e9f99fc2e17ebafdedb752509c6583d77b1be0467190e332f3642309c01e4c" . + "244ffccbc7103f800a4061b4d0b30c356730560419f6e959307c5ee6c298a2a5" . + . + "1b22a152d045c3cde2d52219efa63a22c8beef5f91344b332af7d1cbf47e678f" . + "f07e46248fffadc86dae163415466f60467afc88d926573b963675a3e8d348b4" . + "f130a4c13c53f590725b54a6cdb528134afee045324d8a574c4f76eddce6105e" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e5161f2469846d482cfaec0de5077991bb28b9e8ebe9496cc0194bde781a9e60" . + "e8a739eee9ad75f5aab82650ffb35fccf68f7e73f02f87dd218b02436b8be24f" . + "27d2cc270664a3928e85f039a84cd90c3efbe9cd09f3614ac52a12bc096ef40c" . + "69829508a478d3bbc08e6223bbbac69c8fad0c382b483ad79e044f877285240c" . + "6133679ab93fe197e8cbf699f70778a4d986906ecd3fcb145211d3c66e3e0989" . + "6c22a7393f3b91026fae7c4618484ee05fefbb9a21f675022ee66fd5bedc2cd9" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "a9640e3ba899c05b0831921ac45b94a4f642a77c981ebbb142c580c177c3c861" . + "a003f9efa5030d9b74890fa2d3acf3619b58bc92cbcb958b3284269314cfe9a0" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "5d3712fe722a873478d3f6d07b4eabd6433a64f1bd3eb4523e5a7c66c604f8f6" . + "d77fdad2cc4fa2aea2c2b9f6ab21716e0f288db2c9375077f4d8b36e7ec12e0c" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + . + "5b97587c28f50157674195bed39b665989daa87b8b46ee7a5e15c996246927bd" . + "78d0771bcdcb62d423714107084e2a91df84e1aacc738be4ee631ba728aa5d95" . + "e1e7bd1d9b61384063d4e3a77af9e7a1a23e91bff20c3c89106074fc5b112d22" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad9834e719650acc1b780525ae5104d8e5c1b89c586543e952727749e27ac617" . + "495ea9a6b592b1e98afafe09ac71b9e11112aca42d7e0f56e1a5d1a0957081fb" . + "ebac1dda50b409e25cdf20181b6a2b69be191d27215601772dc869cb6dd09054" . + "170145eca5bdc3b898d81ce51f16aad6c385fb42447214891188ac8db2932998" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "ae3590b42c2db702b7ded780808a4c152f48f28504b24cf8704eb6ed4922f0b8" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "14a4735f5126940f7db70d7444403e38b947d97052d09865c50ac5def73acddb" . + "10ed0285d52ed49f1116d49b2969ec92a338a4d2c8bf751958057c6bab8dcf54" . + "cde2bd069b5e9772dd4b75e943c2d4429d85eaa7c4987f8862a16ca3ed5d033e" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + . + "909ac0144b71329a5cd8b7c2ca6a15eb73bb5b2588b288a87838c3c29a424797" . + "255be0db0035432ea7dcdaa17de7c6c90648dda2695a8ca7dad83f499e898a20" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "878ec11bf7533f9b468b7bcc19f1e69c2cf4a568e51953500797c09e7da9966e" . + "ec74f9c563ad82adbdc929b239225b93d4a6907a77c3ba8da0d3d884fef7748a" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + "029a98140ffcaf2f5b265560adcda37135042a67efa1b10c260b5f2baa27f56b" . + "a642923aefcfd61aa225b088f54a246524cd615052a3794fd739f75181afb1c7" . + "88e51f550963a9880cc8a8903cae0486d4c168103fccb66b4f694b5be851f781" . + "44e3d896f59e337cdafcba9b99818b4067814b57503146c713dc6f22421813b9" . + "15bcf184f75e3eea481ce354a6b196cdecffa955559525c2f6b8023001f827a7" . + "4aa076682f00f49a6a76dbf301fe3d0f5cfb906937c3a4e25abd2ac33999882e" . + "7592e8ab7dca4f807f44f04c7a46b11df48a345591117525c3b0222ca255358f" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "40479acd46019b4bd4ac3c50593851f20bd85cf32e91d100b8b7991d0afcb0f6" . + "1b14441e1edae48ce241bfeb72d6229925dd172720a4abc2db3580253eb6d0c6" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + . + "e8c659074b784f0b4f64f282137a4e49b564fc0e9dd502213b586bc939f44ece" . + "e4222e5a0179405190c44cabd30df158d2019e710e4f4387ff4e7de0f0b47ab1" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "639ed5869c059ee8a2ed715f2c2047b2757b619948e7eb5244ffd32ec50b4fcc" . + "9d238089201a559ec4ecc13cbb2abaa4597c7228a4a87798dacd80f7f6044aff" . + "89b6baf2dddbace10bad2c222322a595d7f3649aee99b526abb50f2a555a46a6" . + "d581319942518f25ff20aca9ff9f0aad049dd5f4920f61a53c7b1eee88b34e6b" . + "9c0e06e07ee192f5eca61577437bb717983b56944f17ebd658a8859331b524a4" . + "806af57d94f4968046cb2ef23476e021fbdeabc803fca3cb322b02bf46759900" . + "6d6dbc6fee0573b4f0b0ab44014a8f0b59299971f829e239d91170e60a059665" . + "c697a0f90ca0a2504546747af52595c5e9658d627f7f4b3cd7ec69146e73779f" . + "6d02b3206b5976bb5de621da870c94e1855889f91fc4a2c952f191bba058633f" . + "4abca8063309a9a714cd24fadb7187baebf5a7df6b192c065f2c080d9c1cca7a" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "0c93ba599ce212c0fbdf9ff70029a8688ef92ea6370df5830bc4b342fc460002" . + "1726beacc99c0356f96515a38d90695e956077e3b357b5d8e93e0aced9da29ac" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + . + . + "5581024ec9931695797861ca8c36d2f4b5fd3a2ab9317642ba152eacc6d9519f" . + "b18f123907b589817454a13adefd2ca757766afaddf3414175f988e99ddced9d" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7fd81efa4371474380bf82658fbb4a6ac2de07a8d55d685a8b3a6940af80bba" . + "272d48f07b1a465f707d0c2e61f193b7f5c44d9f3266c55b8050727417967d8d" . + "700f34efbfff6f76e5a4033f9299a457617171794b219bd8714e23079af7d47d" . + "aec2c64c970ca8248dcc38f898d4440413a0c6d3b641be140eb54fba89c6c78a" . + "9f3d6ed57666fbd0a0a9a91f7d25a3a14ecfc34ef781590cb8452f64a803cf65" . + "5bf0559b033cac0fad4f5ac779b2f4177ca3f99023edae39a66c06aeb6bfd704" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "48b19c92ac57d31c5faccc162b43a967356321614ac8386af5b18e2213be62d8" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "8725cc60102fc90ce960a476ca3c68489f9ba2f488d4b8962deb9663d215853e" . + "ee504261e2ba9998800a94d1c07903aa2b60bb054403c53b70492deec91a5b32" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + . + . + . + . + . + . + "cca68fea6a28f507f2508a03417efc17270e4d76b232e9e5f317d9b046478121" . + "bcc055491392a65beb93e02b93dd1fdde8e7356c006b97d66fae52611e166082" . + "542fae80622159f5d5acb66cb2977a5fdc53ceb3a1a9c239e2a85a11d6dff6b9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3b46b92e16cb9e031011bbafa6cf08fbae2a676ad895d0f332e8dfcab3232583" . + "3b46b92e16cb9e031011bbafa6cf08fbae2a676ad895d0f332e8dfcab3232583" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + "ca4f8f12b1327de3bb36b05c3336a7019a85b69abd20bf809d253797669c4211" . + "e8d5c83f6aebf27d7fe6b0ffa209e0f9b2b5292c393f1a21606993280e2b9987" . + "50edf479ec98499df1ae436c679d89a0a516330eb4db2ff43eb2e2f866999906" . + "83526fccd83ed41c5d1b0096c3f40b4a0767be12ce2fed9bb084a880f8d1667c" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "fb72fae08393c689b527b7d6ed321b75964bb8ece0daeed1f9d799b7c0073806" . + "eb29a55e2ebcb8ee73f5e71c72cd73017cebac44576b29e8d0df72f226269833" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "3590ee291e3ec6dcf9824db5dc403f2cecf05ce132e452eae0812628f4e455be" . + "31c81f501580b4a71f5864d35ef0ae67d80c2832d17e753bb93f929ad5f6c379" . + "6a522c214efd2b43a26a63f8bd0b6f58ce8e117ffa55c0ba0764ce9e02c18c7d" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + . + "b58fc41f97a055efdf857cadefcc868991e339a93c21a8976359421b37a2d03d" . + "7e048fe8d80888ddb27aa3a4c1e9ef6bedf3ce029b00b382e74a2a372618e849" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c9913ed3d93cdd4b54da6fe6a9bc6f6eddb20a59061f9801c5bbb949bec1413c" . + "c9913ed3d93cdd4b54da6fe6a9bc6f6eddb20a59061f9801c5bbb949bec1413c" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "d9ccfaad8578c0c558bd01408e35132b8dcbc622bd134382955d2c4dac5096ad" . + "df62af3ddafffc7826335ee1d883edf2107785afad6aca84cb833ba2e26ff94b" . + "31f68619b16ee4dfa407fbc76067caca601906e6be9f046dc26f2b5dca51c1fb" . + "9939433b6462b6d12451927966ebea8a947bc8049d43442c9ad06e341b06cd11" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "38ed9e43425865c610b1757a4a885f90b6a568a42d1f351a70fbdea023776e31" . + "23efcfa3f72d3310dc05625786dae176d8d1a3f5057d37f1b5cf2f3e7bf79061" . + "46189c40228be3173bfeb836d3697475793251929ae31deb565dd4664f236886" . + "ebaf7aaf934b7bfe42c108c1aeb7990aa2a186a0adfa323b78f4f8a09efc426b" . + . + . + . + . + . + . + . + "32d415773705e0e2c065b03137c9781320d25a8e199c4f839d396d117f267dd5" . + "548f75370e603dfe4e404ace625f611f75b5ac86bc9e05d3eec5403b68b2d640" . + "4734b3f1c307dfdb78e9040af218291cdf9054a029bbf79274c608b45ab2260c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3dac743b67b044a677b76b4857a6fdf03927da403c9d1dbfb3084623f0a74398" . + "0b51e73763d4f64632936a70c07cfe3513e01598e42f3b535e9ed9f49268562f" . + "5ebb667f4fa8a83ae8c4a34cf588cebbec171c0e45b17bef7bc79cbcb2b5112c" . + "f282673d54864ebc577a0d6296a23a9bcc7594d8b2f624c64223c505c7035b08" . + "f92592a18f1a84ef5b0b9dfc86aa5313c82f051832a5aef6d74cd56c1c776496" . + "52d5942694711201cf9fa5161507a6322a57e1156c9df1c705ae3b3313741735" . + "c927f30f1afc88077b0b03cff2c7926dd0dd6b7241c2185ad11b205a381b513f" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "7ba4d0662c23ab26d651366448d1cb911b5053594882bbce27d9a46b699c3e5a" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "948978aa2d3c2633fa5b4aa1ed4e6da2ab958853c3752904ca572c4a3be054f6" . + "a79c1a2e70b368b463a6e07e4531590c9626dd2c16f6f9aa016eb3dcb522a202" . + "57b46edc8166c03c30d164a11a64238a710692d569d543158d7e1962866a459a" . + "c36affd4b410d778d2e78b3f1801f7bd486fd33b29030c4aefb8f8ec25fd1f6d" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "4e5b770d3e76f48a06eed88a02455f5ee04162b7f601386b8b0487900a760080" . + "4d0866d7f4de9ee8e2a862de6faa66d9e5c4f912d132b224c4c16a47e444c424" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "7448389e82ad6ce94f1f34cb00651ab1243b978f7fae6ab18185a3f328eae796" . + "74341504aa72ea2eb7d706bd32e3345dc8b829dfe00db76b7a5d92e26c00cccc" . + "3ba67a50aad2dbaa7b0b3ac34f6da8e382235e6f73b71f352a12b4853a357eeb" . + "fc7d57841ec50e4181f9b6f41f97259e2a17c8fe0a31e0f2f794da7b4192741c" . + "6c3a6b208ced401edc14fb3e7f10a7f68501b129c002bff2052888d3d0a575be" . + "51f07aadd19fc10b18299ec125cb90e5a1776967c6a5060b3e58b7e1e69b5449" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "8318029a4801263a1694e925a2438ffecbe4383102fcdfbe660319e9731753ca" . + "14dab9fe2238a0e4233f869dd05fc9585d9bfeb8ce7b8c7d4ce4d0e87edd220a" . + "368febc6c5e7967dc9023618e59f8d39bcae1ae98f0e5376d7b74522cdbf54f9" . + "f1da07179731f3e5e1c12cfc3ba27a3833372363c966914a60fa6cbb69e75b2b" . + . + "021b44fe40441fe045221b9c8e6c631e573f03bcdb2d393337bc8ac7923ab1dd" . + "c6bec06c648f2df5cbb116260a036596a6e1d224c520e2fc6023983c2dd93ab2" . + "6bdefe9cf42f1efa0821aaddc06acb84037a14918a51c17224430a9483471897" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ed871a1e02b10a3aea270321206129885b5027d6df21b22699a39b6f7594e595" . + "3c82dc6c9e7ad4f2cba107e1b9985c753ee3106085920922a3c319c1801fde9e" . + "ea86f60ef63a3a8a52fa92109bd46e26c3531593f9fc378d389e981cd84b5528" . + "d7ec2ad4a9fffee996bbeb2f97d9e221581e7509d257a4e5b047a275ecaa1cd5" . + "0bf05ba4a8a5085302589df55c87deadf981cfc6a6da78b25a200cfd77773e96" . + "5737232b7dfa1f38ff67ea7351652cb4042c677cb681961e2cff699708ba2e53" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "b34f614cbb3bb2b7450c4bbf995f5d6cd3c2a95515720862076efa86060df595" . + "47afc1abe7a915b38cbe8a49b34e04d472d4c01674789bf4f8ee0d332e43f278" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "7eda1572ad4b5fbbae17fa0a8442dd9781d4766f613e5973282926fe55788662" . + "6931ce164f36e8cceab5b9c01e118e750a084a674d5f4518ea11a58c49e34dcb" . + "495ea9a6b592b1e98afafe09ac71b9e11112aca42d7e0f56e1a5d1a0957081fb" . + "2d6ba55314375d0a6cd5c62953f16d704baf3d58d6f17da2172d0a7b7b9eca49" . + . + "3e4ace34423b1c0daa98570b0904152454295054610c663d81335fae107fe108" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ed1035200bbe55c9339b4860be621ae2f3e77e8d40daa6a93c3da06d144c5f22" . + "16c7cef614d1f244d34f9b39ba4b5b2125fa970efd98fea699e3f7abd98d4bde" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + "784ca64e8b607542faf58380deb7b32a9132e327e90fada730a3074d6cd50f61" . + "8eefa65663fca1f2151b3b0182706655d06108aa5774fb5766dc57b5c4dd98b1" . + "d4de3fdd2f9be494e309da0020ed459a25ddf412f754e2dd0ac0e74b89ceb2d1" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "ab1808c395da64601710b92e34c6cdb38a7a02f569f1de6950ebd8c2079d39bf" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "da5e4bed5e05b39817e5e7d073ecb641e002e41071e71d5fdd93bd5298ffcc0f" . + "3b8171c304b787dd193383e74c41386e691655d46bd752168299c181a5380573" . + "800b6186a3eac9ca11f965bb5e1659def83fdb213f8ee1743d966e75c2bc8624" . + "eb10538b2726c0c745e70c5125709b184eac9dd67efca0a42d494c51d34ffc8f" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "2cbf006fcf2194925b36baf46b5c9df77352f56fe65067d13a9166724257b759" . + "fe75031112994f49d2e3fb7efad42176a20711ef0577e8880c5c650eab366693" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5202b9205c456cff8993706b82edc732b4d0a424f98575801b95d2e52128be3b" . + "5ab464307f07c5f27c6c733b96bf5d610f866c6a521106d3053b0fd59b82ffb5" . + "393393a90b938b0c1e5b33ef5c62e646f5c6c32e530dcca29245926ec88142cc" . + "ae916dcecfdfb60a765c9ffc0eff974c3d151a8d265a861b95dac3a8a6350774" . + "3efdbc3ae988708ccc3aab225f9183b7da091b4c2d56577e7cf20641a74e0d7b" . + "80100d57197e482ac9d23ee38211b2b18b553b81adccdb9e82173fdd21c240a9" . + "3da9c2a48d70b07b1d5651f4c7f0d3b884e16395d137417dd0be9b41dfacd719" . + "145f6f24f9887f35bfe3e0e1b6c6cdf7e120cb831e7473edcd2d59f92a767065" . + "e70c07060666a15b66089a6261b53e1c3624d35c848e268380ee668b2f5e3add" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "336496f400f04593d30a10498f49209e613bc9693e49c857553f6cfc387b4bab" . + "c878f1c3dcdfc40caedd32a885f8dbc5b8c258b7ff40e3d7185870e99334a2be" . + "d1fd251f78c209a6ff699d41491556d3cdddd4ad95498aaf0b2fcb8437743b3a" . + "0c5b81f14f0924e62f57ac0fe26a28def916a9df52ccf15982fb73e0c04d4b6f" . + "f887237dab0f377da8fd571f78fd9ce4825c7c52d3f2974b7efcea57ac8b8377" . + "9ab66a83763e2911090b507b69e0b02d19120971f143100a0d0f6c4c70afcdf0" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "e31032805c868a574250917b03bd9994614055c9140b941ff9ac0da0be399d8b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "00fe4188334d100e36a3b933f992e1d1a5cd2b97858350f148508858e824125c" . + . + "c3108ac3d44b0c6c34978c6e639bf29b3e4079f236f32f83227590d10d28fb8c" . + "94f5626b8d1eaf5b8956adb14dc4a6449eea276db0f186c5d47033842a2347ac" . + "bb1e6a7e2aed004a12a264bff6a8bf852a5922136e4b11d90bad4cd7da812ab9" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + . + . + "a5d8cd16c5174b4bcaca270e8616cc27e35e0ee20a25f345fe297d43645a2454" . + "da1812c0af687cf1da3245981d422188b252b91f692b6aa0a8a0de24e696c57a" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4698c9f53dcdd7f73a4acd8778f1f6f2e346f1d4b9e406ce1c99036a8dc54724" . + "16053d31daf745bd10824de67e9ecdd7aa71d9938322b9779b3246bc36df4a4c" . + "4cc5f2734848d54380fa22d601f56d97daecb42d276f254f861d8e6c21ef8ab7" . + "4e283fac2da3ff764202b12b2a371ef08f8e56040380280c6c4c262ab51c8a2f" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "45af2e51a70b60b0c468b91b87912bcf34f303da95ad5fd003128da2e7f80106" . + "fb7cf72fc6af98440cf97da7607a337119295dc2e7782bff2dcda21b05290a25" . + "02ab32f24c24a4d0f408da8d5806ce9b1605191b50a8e8075328261bcde532dd" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + . + . + . + . + "7fb2731523f6e568e38a13fa9eec2fc9c2386a96aa6d40dc31c3108bbd6cdf90" . + "f9fce55bfc496f6b9bbb3528d3be7eb6086ead8c010cccde339ee73ff53bfc7b" . + "6ed222262261b750f33e12b6137f4ee83bbebca4ce504de518ae251bdb359921" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6b84df8ec768b2dae2657736265cfc2bd522fed13626547937b09f08d5bf4b65" . + "6b84df8ec768b2dae2657736265cfc2bd522fed13626547937b09f08d5bf4b65" . + "a37ff197b7eae203d41ba8a5220dc50d374b106b57aff2f952bc113e83000e94" . + "66fac5c47cb3658966f05d86fd1b741baf6ce409f6723c20a59fd4a10f7f481f" . + "2acd3d6c5bd0362c7cede504bfbd78e05dbd7b0b84c386a511d5bcaf92b1551e" . + "0b9c1fab2b6e1c6f4e9b7a91aba944f5f57d25b3e0c1dd494d491bea0bc00fe9" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "0fb06c731a63072f6fb8bfd45bd7d0908155012b14a806f9973b572666511998" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "5dbfd567eb471f425f21c07768a1fc08fabbda065b09d504c8d410495725431a" . + "5e8a8ec6c267d8d4f749963a9b195078ed1a903d57edd3afe593bbb6a72c376b" . + "980674906345fbdaf4f3591983f8ce3562872aafc7b97266185317d7f9f7be39" . + "93635235efc768848a09bf57ae728233266f3415deeb565d61625d9d1024eeb9" . + . + . + . + . + "610d5fb4491bb86561586022c8b8004e086b4f84343c94217ed16cff4087829b" . + "0a24e7293e3f0ce77e2f95bd050f00656543c79420f7aff32b17fc1c02ca4507" . + "ca0c3c830912f1f724c5e8bee3cd3b3ca4e197eda2620ac6ba270e532293630e" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "26200d84214ff5ccc6fe0a4a1952126f9c081356671d4d7f05ddc6e0ec9b92a2" . + "a5906cb7390e55ef146bb0b39d82d5787e6df41514f614d004af6b14b85c117c" . + "e37758541f9f29c7a366486914127850d92d316384b8c7cdb29907224520edc1" . + "5c4bbe11ee3c45a664e0d277513644fd4a6b385c5455289eb537cd20c740faba" . + "58e6c4337f184220311df292811a413602132a5de6ebba07917217a732fdbaf4" . + "41e4d2ec1b627179d0c2d37320df62e78c2d473abea6ff8bc4a047040155c16c" . + "cd63719daa9aee228769614a76e37538e5184f171748ad96f2ad563c408cfc61" . + "8aea0d36efa55b6613fd0aabe3eada60390b8f180f3b1a7fdc282a7d272bccf1" . + "4fa74782631c8fddca534782785ad9c811188eb66a8500ffb54c88cd1bde9dfe" . + "1abbdca3601811dedee194947cfc6abcf5217f57f4223540c7b6ca2482f35770" . + "46871242c21505130f062814d66c38e550e0ed9ff34dee073d1b846ff7051570" . + "261513deb8ff2ac50de947018ffd176b00b062edda63d2e67c228eed261c7af6" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "665e00e2c9a55193b60966af95ee3f68bea484747179e2e209092cf806c2dddb" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "aec05cb6aabfa18f5d41ffaf5c882556e33ed78d1fbe5cc2ae65473d8215549e" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "089f15de20197661f52aa68396e96cffa30477bc7ace260ffd2ad41969e590e3" . + "bd426bd5800e4c7d9079ecc70d9df1f4439a1e00281a286f726ed51e7878d7d2" . + "0a90e5e6477f0fb3db40d82c789f3e5f744c6cf6563f764101864be78a1fb6b1" . + "242726d906eeac20f586d4595e6bfac264412acfea5128004c79df678ce560f8" . + "07f887812a7e50940f877c6eba895bbb757ace1685d49246eb216ed91168e0ed" . + "8f9851496f4049af5d6f0c90d1f4713e0ae7ccd0b1b443f56d1ef7e8c76adbd9" . + "c1e108fd07a7bfeaea3daa948909a1e0752cb5d8f52d4a52cef731eeac583ed7" . + "1d24c2313d41f121a25c89bff07c146196507c957707c6f8e2641065bedf8a21" . + "b6f0079704ffe073bd643d825d3aef632255d5b6c144722a4cb60134c0eaf0ee" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "f99926b86e0d4a1254cbefd79b2aa066e7c66b802a11847efd4badc5990f50e9" . + "848943828c852f17818edec468e943eb039fe37f1453a99135b66536caf0f77a" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + . + "dd428be8b2de9bab03acf898ce9ba999a536a4862ebba95cbdfd71bc4ca8ef61" . + "215aae7624d9beeded71ad5cc216154c2b394fdcda7308ffb1b0e069e2db9cf3" . + "540b56dfc5dc6c03965bf95d3ce3084465daab78d7a36ce726e59de24ea397fa" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e7d6a12c33b989bf7e4b0b596c38b1957a080949069d4faf9316a404eddcf66d" . + "39003a782f324d1c63253d48a25ebeaefc0a14ac935a7d0cff0099e4375381fd" . + "2e37c14967923496a25ba76d7ef1099d1ec8031e29f2d1e6d35761a9474c10b3" . + "e7a72b6974d32a02e20d299bad1e19dc464979b206e5c40282739e6c128d5d40" . + "920cc25d2e806bfa05f9314f7e460445a139ad5aa57a1f84d408410341e12813" . + "1a395e94ee1b968a53b8b98fa0a77e140b94e26721dd4a699f19a26ec17ecd13" . + "4ebd65e36a030ecf46ac2529a688a16aefd7d2783aee94d4ce7adf1a5ec3bf5d" . + "b3f3d956f57a95fa114c1e3091b07f3a03babe6efebb5a24f8192f90eb5ba9ea" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "df887aeaa4ed0af0525de66f88ae93486de0a862d40a9200cd82fd666df51033" . + "c59c2d377b1ad6dff120bdaeeefe1e6fee5e88a10ad98d90989731d38d0e3196" . + "dd50e375e20b5628b33897a0789761ff6353d9530203ba53385ed0e3599077d0" . + "99d89d8180638cab0cba0fde3320ac58dc53c442ed48f48ad2b045ecb1fb7766" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "b8c8f1c9aad9963318b51a07652c7b20e175ee3eae8d1c958eb9f75f5a1c0a6b" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + "a866f0c0655583589afd675285e4867b48fe36494af7b1f50cbd0267562ee1a0" . + . + "3bae865289905a9724d3ade22ece99dad8285823505365411669b0d8f73d6fce" . + "e411f80c4495ae85f08a1e67aa0595f9fcd0f53150c597a27994058b48e4ab76" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "815e1153981d38e21bda5a426a16f95b14a51b32433b9b27606aecaffd7aa23e" . + . + . + "7c4dc57ec2380298447f3c7b5c01fdf8d5e7166c2d9ecea25a7db600f85a8e98" . + "c9e1d29e3bfb4c83fbcc7a991d9ffd8cddc8c1fb8468cdb5ee7d8caff503b88c" . + "33769c4d83bafd3af33cf9dd052fd83e32e1805a0fc4a10621f4f47e74ccf35c" . + "79071115d5984bfa0ed72c32a7ddad2d45a7b883eb7ea4c9c65443dc9a61c922" . + "4fcf2952ba9cbb9a84bb1b3fbd99cee3445eb8c9fd9cb83d1a807d03a97b08c9" . + "15c4818f4c9c11fad67e8452224e2a1a06d9adabe9cb3d1fbda545faf60a0786" . + "db5bd8b2f44dc018fe83e5c9fa438c45a99db56ab1697c3c62e7206da5038c05" . + "c4a5fe0f091fa43fc081252b55f17a9eec74dd018468f53e46b8e79ccdd1fa68" . + "7d836edd3dfbf643d1d9ad80a1b42ba065a4a4c57c8c2ccc542811cc870f9cc5" . + "037bb32ac490ce0cf4a04eba61dbe7d51f67ea3eb5d5f1725b102aed486acc9d" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "96e36e060d734cdc7d73d4982a211d35ccaef607c2e429333649e7f6719e683e" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "a555c38cf372c6346f87b8187d3eaa413ebee7021070353854992763d06b6063" . + "f9b7fe6649e9a031a9e08236df24801c7758cebcdf4a7765f2931d2586141185" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + . + "8681b6a353a05f1451cfa32738581ec98901ba62814b45e01b33b2c0df541a72" . + "45ad0da2b7cee34a62dacbb42bb6f12d4f1d97c7cc2cb7b19e5544095796bbca" . + "396c2f4e9ac841a33050fd6a7d50cd2eb905ada45fff31d3d17bd4b0b906ee65" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "90b2e79febedbd6a332d95d480f9a6cc8f3a31e909e2db3678f07d4e6b272947" . + "90b2e79febedbd6a332d95d480f9a6cc8f3a31e909e2db3678f07d4e6b272947" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "60518c749be758084cffbddc1ade21ada338d05eaba8644af2589e66d048478b" . + "6bac20576c1ecb671b4b1e04c222d6df3f72d109109b062b4e1af7f007248da0" . + . + "3c6b7c2f8da9ea0e092be9254686c7c7ff05106c71a64e52246dd12413cfd556" . + "b5822855ca10dba683952def9f49e18cd0475abc472ed817204d60654614a74d" . + "71f99e8915bc760e73af3f71e7fe3cb74aa6f790510406060379bb4bd90df55c" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + . + "3c6b7c2f8da9ea0e092be9254686c7c7ff05106c71a64e52246dd12413cfd556" . + "a205ea48770e831630fa244af73d7524299992d5105353ce1a37b641a871edc4" . + "e83a3e9ab1830fe0116ba1fa7251cd4085a4a5b157261f8726f902c50e65a391" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "56626116d82d833833d90ef362d816257764f33d7d056fe9dbbf15f9dd051f69" . + "6629e7b82a4ff8c29ec1aeef4dfae4d0ed9d78560cd7f6aa0bc00ffbfb26a2e0" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + "99ff811283588f71b07d88866341592d1f791f2a5bbff9c96b111826eaf3a564" . + "3644f20369e7d5df708e7a6e3b2f2805ff34b6a87a3ae4b391f877704a8e05c6" . + "6588afdc72ded020b4670b4d58bdbd1bee6f3eebb6e086f3c8c5833e32387b37" . + "b7d8b0ebd57675e38211df087ae2c55b7fd4853cf2cfb6500f1f25dc6fd7505b" . + "a0fb2db994150d82eaf2f3255a381c3d867fc9abac11122ae1807ac1458e889a" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "8bd2254d48b70c75d3a9a0688625ae3541bf1c98c2a257d70516d84f1023674a" . + "61df6a7ad99b81f9ddea60288259d40c9821a152d0347b7d404aa7819cef240f" . + "a875e1b88ee0aa25214994ec5f30b915221d44a5c4dd6fb9be018cf05978aaff" . + "e30262c6dd556c127f1ccbf69fab4dc34e487370cd6e932da50b6fd64ea6c646" . + . + "ed4589bcc357fbb992d8a7e3a34e67504700618ce1d2968dc147b33c72d0a105" . + "f8d92485247761e72e63411238b8bca4729da3e9ec102a2e965214357fc9d116" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e91db4f8f2e98a9aad3874f99bd80237b4c1e6d6f92732c6832f7213fcde1b97" . + "e91db4f8f2e98a9aad3874f99bd80237b4c1e6d6f92732c6832f7213fcde1b97" . + "30da0c04123ce59219af6c9bf44e41d7a078e7c6eb0fad6415952ad38b83a8e5" . + "e1345d4e17fbaf6be9d1b0d1e52f25b04affdd932ab633e13c5b7c807dc13d09" . + "fe159626c621ff83ded8ea887982959a3968b51e10857374e24096ad2ef91ddb" . + "98fee847b2b23469a7f9d15c5092fae08fbff25b760fb16c5fb494de58dbf80c" . + "35a6d649ff24521b425a8d95619cc6926fd709e4fc7ca0f5e3396e54e3b7ccaf" . + "2c2b6e67532b6d20a72e61a88226756af27f1e7b409f8bec04cd7fde9c058791" . + "b6df95c6e1072731c4b747bd599ee8634a3e735c687284415c12487ab4570bd7" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "842b419e72abf9a8e087c5aefbf9d48e7ba6c692ab063aa8821073fb3a99b1d6" . + "75df7b4911821644b83edea826fa47da31a83b9d5fe879ac878828c9ac05bcd0" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + . + "c019be9e6381d50a09d0f0b17304c0677b848eaf9d7e98b0e738a192172c122e" . + "654cd1b3d4041f9f2eda4d6ddf6aec53e769e8c9c23e6aed57253da4529a6222" . + "d65095e79deb75da2e8dfbeba098c4ec2864b2575acc154435d5844e7fc555e8" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "09aefa6c50f610e44b969ec535a3d9e71e59db54d5a50dc3bc282e93eabe3731" . + "3d500fae5373a1b42a9aa75a63d50958acdd3661f92ba401d278b2aee78f8473" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "cb64ccb512bf71bcde36e3fed214fd70d27851bb45e164753bcbe3767f195e06" . + "320997547223911397754d632cf481afcf6c82a984bbde5b358eabd1fbc80142" . + "75061ff4b1181b5f571cb0fe0e3d9ec2e0e5dec1d38d014b5a1989cf89cef815" . + "07afdc9cc820a4fd32c0f8cfd51bc616802da2de36e52a9a3395b14961488503" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "eff2efe0ea9074135209108befd1777f642dc59ada71e1953ec4e09722b9870e" . + "e6d068bf9147504835d33bd952662e87444a086cf4f479dd073846417de6a0d6" . + "40a96c5e30ef2cb5be8db57d1b611b29e4e9ae6dc86d8c187cfd3c37d3f4e594" . + "6d543a82c0ff0220f8322c4bdbbdbe0cad4a04b9e35ee983c709a10e35a40027" . + . + . + "e97007bb9c6167afda7491144bbec532369fd1599a3bfeea9de7de64235698e1" . + "0c9d23034e671114240fc910d2f9418c879e390f3c977886b8cec97e983c971f" . + "19e59635678ac9e86e33ed40e23eecbdbb79e3219c44c43046e94ff634bbd67c" . + "c52c1f8726bc1340bf93c6c3fb7d86ec12070ccc3d80d8e2af232e3548780655" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2afc5beb882eada000794329f9e48457c31ffe35a0d051a3304139af2d2dacd3" . + "2afc5beb882eada000794329f9e48457c31ffe35a0d051a3304139af2d2dacd3" . + "c642cbe7224447b157b496b6eed5d08cb37b77d59c0447dd0336360d281592fe" . + "3f1602fabb2221fd633dbb9a53aa52275603f245505fb82a697e3a270f59d54a" . + "27c9f4db195e7d9238ededc8eb44cdc054f189be7db4f7aa5abd4e78310fbba2" . + "ab6e98004afe4ef00b9ca5ccf231313c66ecb5624a00bd251ce22610400a4896" . + "1ff2f9e5e57e133b9a05eabb6acd32b1c2d0f66fa5f5d70232f526eea1d8b0bb" . + "f53da32d39f3438b1e7d53fb981c0762a51a8a5ffcb99f0713dce38924ba4c50" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "50c027a43c5094f1615cce4cc57e596916b55980956c9cf1a971aa530b1d6f46" . + "1daa9a73f53541fc253c58149376508ddbf1ed80913e3dc3524e75714deefce0" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + . + . + "5c8d9afc28265311210ac27ace875eede6a2f5170a7362327a81928bcdaf0678" . + "58d56fa3c1f6f6a90ae06cbea0f358a0602bf944a910e2920eba11bbfcf277da" . + "b1f1fc2ee574a783a1063f1fbe6ce6a4d4bb90ea2b7d6a238481a55b7812485a" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53e8336cfb55891a1bab69f5301183a305069288d9683ac02468a9cf15976a7b" . + "fabc76b3950b14cf0f392776d76fe0aaff2a7f0d99fd27c310025154ed7704bd" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + "7933a45b7e70873921d2a04471b92468a6eb7af87dffa331937d5089f8775c49" . + "d0e65ee867668c5d537f118675b8d2a9a2d14831c0583ebbf066bc4b6894946b" . + "b0d16bec72af0899e2e707cf2e159d918fd0ac9f7e9d070d4376151aa88bfebe" . + "845b39c556050c06116d8b9994dcff3484c94bad9b487fbbbf272ef725a2915d" . + "ec77feebba04c10f6236b0affa69034b31edecf8d1a7d8778d09e7330dca3075" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "3388fbc8ca885130ca9e800361a0f7d659297ce7faaac059c4a8dcce2fa4aa9e" . + "1b0ffe452fbc9355c0234bd5198ad1f9677a851784b697e5abd1253e21f90e0e" . + "2d6ba55314375d0a6cd5c62953f16d704baf3d58d6f17da2172d0a7b7b9eca49" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + . + . + . + . + . + "cda24c735906e0a37145907aace937a234003cd19707e44168480b1eddf41f3c" . + "14ec6c5e0ffb25a9b80888b369ebe4fa8c52c9b1c377b4609cee1c7f2732c12a" . + "a600896d3296f7674e570a19065762d9052ef860e8eac5137bcb859408c349f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cac73b9682ecf177289e2d8e191f6001dd44b5e0b2df1b5355df8df8fb2c751d" . + "e94b22fd8af1a621257937c700091ef20502a3816992eebd1a0cbc7915abe9b2" . + "7a4161493cbe1f9f9c7fab1c8a21efc0f1a6f6730382c0a253019e4b7b03a8dd" . + "dce5c56e229b027aa7c49894ea1281b06855fc1749330de5c325fc016c0a9335" . + "661b0c60218e42776a9f1a8bca71c2d57f45a4fc13dd3851f71620c3ceeafb14" . + "3bea9776f108b4c9c8f5ae23031a310fc3cc55b695206a3c314c23b68aba54a2" . + "6469c7a27a284a00e0de81ed226876973a2fd9acc9852535f759006e0c9b044e" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "45fc1f4ffc614f6b8fc6ad7a43744bf41b4d3e4f80def493775ea31b87ed4987" . + "4b6b3c0d8d47275ed25b55a6b1cc244e54a169d02542f55655fb0e763659abba" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + . + . + . + . + . + . + . + "2f9738888eb57938a98eb54fd81a3dcd6eabd50662ae77e25a18fcdc654c2969" . + "6a62293b6bd7a79c8ec0d7d38efd188ce21b4426e4fcb9ba1c266320537d294b" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "4b798cd3465cd40eb662a4d48c2ce8e3aa78017a0183a80a14da1f4974cf7547" . + "f966959719eeb7b3cc5c682c725b2d00accce8b4ab66e03d921fb0a85ebf2ef1" . + "c3205764f41fda94921c723326d92c2114975789e527ade6f2eb1f11dd767a3f" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "244ad4248e2d0cd4c2dac68cd2ae85cf0b9ae831ac150f8c85ce18cfe78fd9fd" . + "ade7dd0900aeec64dfab70a54190c651dff527b760779451b41d3a1ac712dd00" . + . + "34d7921127d1473d825831fbc6a3f88852be00bdc8e11a412432343cbcc40b3d" . + "71297125812d1a07cff673dae32be2da514f2cb2145749c3499fe7d75d29281f" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + . + "4c79833a240ead50637b47393e55d821dd16992264dce51b5dc4cb77f3417c7c" . + "f013283d752bfd988930064456d6586b3e75124e1dc09a7a345d7a2d6c53470d" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3d3bdc26ee49cda25f7c1c47f82ac433eae27b45e29f689ea381a34e153e0487" . + "3d3bdc26ee49cda25f7c1c47f82ac433eae27b45e29f689ea381a34e153e0487" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "95309f9ae7828f3d09cecc6e73f6008d07e5de12ec8fb27a5f34c11fcca8b521" . + "a7d1bf44a86bbe5e6ddc3bca7b0631328e4a2ef0f4f2b471a6949a0c4324b1b3" . + "2822f5e25939422376fa1cc0d2dd10d0d52628e0205988be014c144647c10a04" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "dafc7315d72330aca684f9e9b6b7f769ca65a26659e68201c83d5c73814baa9c" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "8ea3dc1c9cfdf24fb30a972b3520e31e7e5d9ac457ac25105141b03ee5f0515f" . + "05c9f3fa92672d4c7851ebd580910054f4a71f7b4b0ce0bdef4b804101a3e17d" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + . + . + "5c0787d8cde031130bee96b20f067f82d20ba86082e7cb3a1d8757eaa36be745" . + "afcf9bc9ae5000dffbdfdf9521a8bc28ae1dd6d4dfde9fa7e1d7636e447ef3a5" . + "4e6873a065b51a56958c19ce3975ac1e13f0aed5bb3a43aab51dc7c8d53d4345" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4866df8ffb54bbaae734dcdadd8c1934ca27e9ee49761866265374347547fad3" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "1ab589becbd8a67cc2e8c1166711d0633401150bfeee458a63d156b19138c5b6" . + "1eeac482cb2d24b689a0c2682586996f5a2fbb2c8b966ba390cb48023c03db52" . + "7d345c39e662b26fb42f5b62386cf6196fb62c06566f6dccb590fcbc8208b84c" . + "e6107a37915c94d86aa1dfeb481c7e2192d481a021aea734e95287575f50e117" . + "016a6f2d2d45c3abb36cb844a91a0071fc03e5251d34632811c35fa934b53b06" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "09a24c8ed7f65d1934fd7f9e47bf20a794524a8cde09b53f84a72923df8dda60" . + "6e0f5dc19a4804d49174ba5183b7ca748bcea977217f5a29637100127123501e" . + "0535a6304b0f28774483ee1aaf78e7359af1b75deee2bf2b4fdc3d264d396c70" . + "2d701593cfba7fe0688d55c9bae0af03a312fa02db8418581b160d459923d363" . + . + . + . + . + . + . + . + . + . + . + "8acd0ebce56aa34e998609d9f1b5199d547c1e17a54763eb1a1dd8f38754a25a" . + "092da52860fd269f87b4239b4eab402fdae2daf944ee9be7882733e145a73269" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "60316d50f13600f39dc92d717e09cbfe53856918b90e2fedfd404ba875af0b7b" . + "a06ee050822932e5517ea0a4d0feaf6cd2a51cda935da7c02bc69165f33a2719" . + "ad20dcf7273c1cc2a867405841ff015085fdf05154c833895f380847efd50d81" . + "e753bcbb5b35a9e3ee6dec8f9d8cd32b2116566faecca684b85c2f9170197522" . + "e52256408e379dc4f3d10e7b08ee87f888e5f62491a35443bb05a93dc23e382e" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "0a90e5e6477f0fb3db40d82c789f3e5f744c6cf6563f764101864be78a1fb6b1" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "e55d20f763955cd1479945e64b01f26a85c04ce6e3ddc9ae2e999cfd2802c0bd" . + "acbf47e733e39b28336c57eba1c6e12ba01a05567d1005d44d1d40f0815f662b" . + "b5dbf2b691604a2cf1d9c194349d826de318d585f8c63967a9dd76179c747ede" . + . + "ae02e98d18d9790fd102ceb8609e4f92c54a26b89aa98220150e98dfdc5422f9" . + "e22b5215f75dea2c33f7ffbd417938db33571ed0bb67164b18ec42eb0c43592d" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + . + "b00db98515a2aef0e7280fc99b52abc66457d9f41c0b87f2e323b74fb29ff630" . + "7ba7388f1aa4f19046b7b3b544766ad078880db0b27f2ef57db4cd54c85178c3" . + "433ae8afdce15407a41558d41bfac73b75606fa94ecbbf3fb80e9774085196b6" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3d3aeeea5a9d8955e5cc1c3fcab407571235abee3502c03e2eadf6930740e30d" . + "3d3aeeea5a9d8955e5cc1c3fcab407571235abee3502c03e2eadf6930740e30d" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "e944c0b4187222e65649d5227b774453702ffc5936a55c7eb802fb7bc000e0a1" . + "64ca0a22e003083bd104be1bac7466925e28227e888a61ed6710da4505c571d3" . + "b0b8d6e8c5c245d849c4e0bb187a364063482d75e6f96b245e329a55a119aaa6" . + "d84b90a241aa19ce10e1b4ef7529e210632c5fefd188cd185259b448be67a154" . + "73d89cbbc8d01a16191039743f5c7fe493058a14c337ba5e355ef72e90741afa" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "198c5c89741dccf53c0c88a31ce764be5adb6e97e3fe908f9f95f8d46ccdf9a4" . + "8dfb6254ed259d330768c65ebf2e604835e9c091b25a0f6765e351d84d51a76f" . + . + "ee2a5741b17ff64a542c87d572db0246166cc89a55a9b1128c8be6c709d338f1" . + "50fe84d633eebaf75ed325d35c63692221e033a66b369d77adee6f4ab224fa53" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + . + "ade6d8bf1e3e4f553de917548f05d1cb9e87b36099ad90ecb03d7459dc6d61db" . + "8a1d3972318a2ab190b70e4c05ac8b51b9f3eefb05385f074050eba8c2746a84" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3d3aeeea5a9d8955e5cc1c3fcab407571235abee3502c03e2eadf6930740e30d" . + "3d3aeeea5a9d8955e5cc1c3fcab407571235abee3502c03e2eadf6930740e30d" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "721f420541b183546221d14ca358efc544303296c44fdeba1bd72051582ee939" . + "571977b5536f432e251af94624e106212dc279afa7e1d61514d80b6ae23c9287" . + "816e1230f26fed1895475bd196aeb9330d4295e44dfc9010875f79a0c9a4e79a" . + "7d19c839960f7a7549e982d408c6b1f611a555033ce94d6232463f10e9ed4da8" . + "0da9138df218625768290fe446e6bdb83d0acb9041215be2ac69cefde4ac7258" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "6ac1de21beb17d48282adfccbba8ec88963c7f6c7de06d09bb79276e79331fae" . + "8e9fc5e541fc0a180caada11e2ff4712f4c349c795b0ef4b1d5319942ab6cbcf" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "ca9bcdd6448d53ad56bdd570ab3ca5fd99b05c0e5bca4b67a893c6ed28019078" . + . + "c8e59dc976dca91eba9e33a6ab4139c6cadbc54e28a010c63d728058c2e64716" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2d490a3ac485e37ebfcdb3e793c904b214c5e9f35d19cc0882205af7fba44609" . + "2d490a3ac485e37ebfcdb3e793c904b214c5e9f35d19cc0882205af7fba44609" . + "08cdeab113d093628854c7bcf0c202e15d6440e120366641d0a0846e199442ed" . + "a934bdc292cfd85cea9f764713f3c7621b25960e2e0384974e89b4315016f98e" . + "8e65552b86b70aca87b33daa3e8a4918aa82124547dccaeeb3e9eb2c83eb6eaa" . + "3396b9737ce191b89314034619c5236fae2540b47740db801fa8490814da4c33" . + "abccadd8436040f1453de331bb35bc5044f9e95a85cce5dba4d81206ddd49fa3" . + "7b2f825642cd557aa497797c990549847603716e13878e0e9e88e63685f94868" . + "bafb394d3fca1606a62a4e29ca402802fa23598d06b3e5012dfa99913283c368" . + "7245e91cb0d8794b41e4b133f142f6a97aa23d0e2a09c226ea643ee2ac8c794d" . + "c95a7aacab86c00638e7ee3cf785b14e32dc844d479623663c799b4252b7b725" . + "89d4f824559073a7121cc3709623f6a991042b0d3f734ebedb99b7b7602e1a3c" . + . + "611b2f80fff07e28858fda7fcd629a5fabaed711f89bb6dafcae378ce6767d11" . + "8d1ce46cf2e0ab0932506e79a0d60f7dee108a8818dfad317387935913ee531c" . + "114e0757b0ad0d6bc324ba28bf4b55f64cd6f125d957255002c00927c479234d" . + "2d960e5c1d4c01d169547374ae83d975e9212c5b23e64db0504f36c8367a7cb5" . + . + "352c31d6562bd6e521bd88f2aaeb17c099094d0abad1a8e8343b2ff324457ad6" . + "8011f449081e4542ca6b2803e6440100c162a712ae05a369144bc5d26b4ff8c6" . + "6a155f2cbe92e369bcf8de9168d9e325ce237c4c2943e54ad076455f47a00640" . + "a767fe2cb91044c55143d6f1d28e75d14afc94d54f4e3d25badabe4c86e35baf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "680b805d51112d0649af2c9eb17327f2c9f643b796f54993d4e0fe8db9019de2" . + "27081338d4ae159f7d773519127ff543b0822974a110444a12bc4f3794d775e6" . + "df20b00fc85111e3956bf85d76746ddd91ff308398ca4be2418246dad5f74939" . + "f39175c3884621296d35fc65f2dff9b71b70865dc3208d962af30f8654fdaf96" . + "b46fb6d87b0128117b0bb456537b58981db30924d9f0e6c3cbc41ea0cf0ddbd2" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "1ec59456cdafeb2bc51f3ab8420b00dbf4d8195fcb5c22dfcde9f667c29a50f4" . + "0f2ad3874c2505c6bf6ae2505c2960f6d6bb10baf0ac4e7caa897d540ff5f773" . + . + "30a307a6379129b06deb49887cb77b2c0eec9e07bb8758dbb7c7ab8f84eb5fe7" . + "686e0a27a867769c9db989c6226837a354e814de124067445b9ca6fa50f2d0be" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + . + "833611649bfd47798dead1d8e2ac7c4e67a910d59b1f493d1bf1ff408d8e470f" . + "8e99790e6162e2967af8785db971198afda0d058249ad85c2d971bc700ca35a8" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a790bac83e80c51052e45d10ef386db7c130a32de02f7b5d12a9239a199326ff" . + "a790bac83e80c51052e45d10ef386db7c130a32de02f7b5d12a9239a199326ff" . + "2379d7b0f02dd828cca0d375d404c6a15649a568dfb4c6182530d698b98eab86" . + "2eee969c662b1eb7dda52dbe50cef1ee711369413d9f588fb9eb727a3aff014f" . + "88e8f645f632a8a790f06d151f6e0d0dd241d2899ed715fa48eae36b110325d8" . + "7f34d100f5158ece1131370064a34127cca54b18fa91a1691fed33868199f2ac" . + "129873ee7ff3d1db5108271f71504179512a607fb55298b807ccffde4c8072c8" . + "2fc0b5893c709ee341704b539cf93b292ff5752cc00f81e92cf2dcbf6afdc109" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "43d3e2ecb057c2f6832c1a1a78ddb49038306d0c246994ded9eeae0f9852fbdc" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + . + "3e3572d3214b55ad1b858b0e5b55c3a7087d3361bc1ba99cdafe5e5de2085476" . + "6efb30f6814ff89fd8f4b2a42a3304b72507629c354dbb6e886d2bd8de702fac" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9246450a615e8d6a4596bb05655a5ffbf63a47df75b78901c33432a91114ec14" . + "9246450a615e8d6a4596bb05655a5ffbf63a47df75b78901c33432a91114ec14" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "3f09f2e8b754dca7165da6fe3296d03e4337672591e69f3f8945403549da1c28" . + "77b9a6096192af5a44c42788ec294b2bdd08a98cd05e03d980b162ec65a54cfd" . + "7d331a4cf3c1ec7214d6ffe1f08457707923d1c8ad391bfe6d85c913d0246f11" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "de8458778f768946eb3efb9ec4e2364c83ab61068235231b92b4abc3f18c27d3" . + "e6751a95990b07e79e5a4a916119f9876a700c14fb605a5e463765b3a87b1ee2" . + "a4fbfe6cdd3b1c06694323b259cf9e631fdbc0af5aef2221e593d9cf4618ef6b" . + "2233dbead7e349f4cb6c95e90b0e1253dbc79dbb05b484ad04537ab01514e749" . + . + "f4e52ef58f761e27193933125dba03da7388b54438f22db2ee6abd89e077b38e" . + "7c7a4bf1154c476b5deff05da6968213e7f48a7fa749589bce04ea6ccb24af65" . + "75dcc8df13299a41967060e54056ed71093e127c8d5fbd3ebbbed7c15ff34ba3" . + "b0e9caefe2d7d085b80d9bec3a79d0c0594cc25b5b3a3cdf36ea13afad34bcaf" . + . + "792114ae5506423776582b5e4ad7a2f0e22283ea5005c6786325612771cf862c" . + "f3c84caee4589b5d839f0764c8ff805f4b95894b00388caeb4324413d018c122" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "373829ff9a9a676841cfdff918fa21472aa21511b196b3abcbe8260779b97be4" . + "d805edfb204e7d786bf6f118f983b3f289ecdc7234a960d1324b91807373c7ab" . + "54c93e5f67920242e23163cc6b13b7100bacbfcb1d9b7de56cbf5775d4ff9a5d" . + "4811534154baafb8274b2b7ac8abedca2742297ebff1a6bb3b3582fc13b1228d" . + "100c21c73dc6d32235c672011790b309daca782ad6471c7b017446c96fff0ca0" . + "add8665f9f296c023efc70e57a514f62ebc6d5c5d548a461c7b69696c3832174" . + "a55b83fec86d2f5a936844297ffda5c2d41da7aab0eb0e6e5e379f803b7e2c5a" . + "ac2c5dc8d94785a57bd536a291ff3e6c85a9becdb5171561dda521f03e4f2cd3" . + "9accaa00bd48f344ab668b7aa4a25808280c7eac267d491c5b3d775a86da3996" . + . + "363fc527bd4f3e132a99e7c241c123ef72bef496d25c498f1494f57e0d565b23" . + "8832de8b5116103887be741a4776fdcb44881171a354423ed2f16006d74ea4a5" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + . + . + "513141034f3ac59963b46e2e05974dfb922ff0656118ec0d5839e8091f75c7cf" . + "ac7153624b760af6804819822d849727175f15d827d36c79f9b766817db71e5e" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . diff --git a/compliance/store/src/test/resources/nativestore-testdata/SES-1867/newTriples.nt b/compliance/store/src/test/resources/nativestore-testdata/SES-1867/newTriples.nt new file mode 100755 index 00000000000..efea9d39bc5 --- /dev/null +++ b/compliance/store/src/test/resources/nativestore-testdata/SES-1867/newTriples.nt @@ -0,0 +1,20484 @@ + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "e2dab42a98635606933eafd20df23ff5ebfb9b3804a6b0f8d447ce0182c2f5de" . + "5900cdd48bc0ff3c2a1f7a3b7d1e81227a691877f9a63bcc8f97b2923f364506" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7ab7c8579a4067f71658bcf914b30aae189ae2bc886cf3d285ca6e6225b15db7" . + "01831a984d95e4cd2d86c7337309f6a817adcec358ed6ced303500a78e42269c" . + "dc2759e4dba7bfbf3f7ac6783a5f5f61c71585240a343d65048eaedf39bed20e" . + "ac99ec01a880d2df46f31f0061cd9cc995e622612a10a01e657db1c82e1c5321" . + . + "19bf67b7529461a4463b9ca4840d21008d430519ee41458dd8de7607decf29f8" . + "75788e8bc7fe02c09fab976632e4909e664b6a5bf105ace8f050ab8d4cef8fcc" . + "c32258116fc5820123fed50bff6cc339d905df30fb9474f7cd5b5abf5f7c604c" . + "ef70d1073aa06010579b2e4b5b90f2607fa1d174e5b95644726f170e7232f30a" . + "e67a4390ab6f15feb50b2e8bc0df52196f96fcedef2bf5248de490caff0ce232" . + "8dbc91fa53b417cae9ddc09d6c587bbc42b0f1ebfc34e1917d6d1c01ced2862b" . + "542fae80622159f5d5acb66cb2977a5fdc53ceb3a1a9c239e2a85a11d6dff6b9" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65beadeae6ebcc5329d0ef08b6d356354a37afa2a1fdd8f488f03caa1ec4c04f" . + "5b39575e44415720f5fe44747dd74d8fce23ff8d3bd59d68f255437e5c0a86bc" . + "951293856ad8921a5fd58b3e2959edaac29645bfdf0089166b56521d5d909776" . + "be5b67fe1a489c34921358cd5503b197b5f10385ab6a11460263052cb0409754" . + . + "fb9618b334a62f412916271531910577d9f47c204df7f76281e080a8e341ea56" . + "58ad2504c0147554b8638f9499c410ccace94ece119af458533fe2170acef183" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "7bae3ab544b5113a4b0839e3abf6d4347d4b21dda782d78944160f913577e461" . + "44ba32571a556232435f0afe8ed24bf9e00fa61e2be7222ad24d3e78cbbd1808" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "457b92a79445332741e04b7435efb9f4a2c17833f15669bd6e5eb7590641da8d" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "57fb1cfc720febb0adab43b7ba50523917e5bde4251059bf3159f793532285c9" . + "4c25117375b96405dd51200ad732c120e9f6b584f4199340716f3b6b9b64a25a" . + . + . + . + "24172c1214c4a2bc1fd001035e771b3d9afde0d25823bb57a05d7b2227a54b79" . + "f50cc3bff3d303d9b470cc1f726a5aa1922829448de01141bc125b0beeddc3f1" . + "28e749e50df57cfb890dc103ee0e9a8e88bdba5360d29e79234f62e83de5c41b" . + "6d35a339272e2bfc9f2b1e9398ecc119553408437d09cb21d462d640718d26fa" . + "b649e87600e3f1fa29f18c0c411169a82cfee39c93297dd5827de7b6ac561b40" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "8092b174dae3abd147b335210bc6b099a4b28003b537b39ff4867de7d90c0c87" . + "49030d7468321834fd167f41c26a31929fb197f3cb9414b7cba3fbb7fa7d4bfa" . + "0b58600496b44a42bcb1250bb250a7f895c4521a84b5d356dc525059d379060d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2e9b5cca33b25cf8fe83f513bed2687959854e25cdbfa11c846f511f8c1df152" . + "5feab7a2ee51c3519af0ba75400ec4a0781c95295e866589ffc7ceca488b1c33" . + "073680069bea393545bf82d4a608ec5d64e9413a0c59f3b6a94cba7ccb458d42" . + "aa7f95039d33f9296831709e3418abe452a6cf4401a726b2e0ca1e3f0a34887e" . + . + "e77248200eddac96ad684d246d25edc7e9e3c5000d295a5c31cd357294cfae2a" . + "5f140cc6509da130c71dade0f7f83025d10621704aff658dcb6ac6d6b52961c2" . + "cb0515907f4376a9e21f541085a2073a3beec645d8eb18145770dd816fe81f6f" . + "17745a515426841697251425c9c69b3da00eaa930034e1ed7b1ed9ba7d8bee72" . + "4d3608e950b7acb0ee04fc3abae7766e0464d9410660dcd51679ba62e36ac63b" . + "9cdf8bf3fe70fd1afc7e2a00f221769f839a8fd5c26c7a5ed86ae86676d5ceb8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "982f0e645dc94c6ccb640ef19cd87a3558af94c2cbd64bd12cfce57190456896" . + "faa441b0793344ba2b8272477283344fee48ac6d00dbc6876b487a956f4f200c" . + "57d7bc1b981ebc7d87df38786bb562c0c7541ecf758dae481865cc1407a58b36" . + "ba2141c4dbc188bccf427d1644f782fa8ef06c353edd68466f910f4e754dff90" . + . + "5f7f17e37607ee654e0ef7b319c02d2eac75df9e598e62a4657aba7f2713e598" . + "5ef2e79b5b842eb9c360b3a5435d6eb260b024dd6a560542d1dbb73558dfbb30" . + "0f75f2fe55372db30a898c992cf5ce776e3a9bfd76ffa9d7091ef37d22e4f91c" . + "b03c1b2b5858e716273f554adebe91df200596d0776846fbf7014978acc7b57d" . + "25b295eb3ceabaecf61d0e1f8c74cd284d35c14dc201a3c8e8815dfcbd7e5e31" . + "1277a2036f78ccf4753381eb2fc82ccc9416e06cddffda08d249db7763c0d68b" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "615abd594b5403def7bce46da131eac4c9045069fdf064044fa9f0900a606a90" . + "eb553f38ef5c078de539594daa32541c0981622461ab255187d7111c74927a10" . + "3cd3bb4ab99a3d5aa350a3652fa4c20c8cb9fb24bdca16c1ca9ca9de2fe13c81" . + "7e3fdd886b2160dfb9ddb0d0b1e3e2acd3aca993226e3fbd37ca964068a5376d" . + . + "0146659d61e0f36fb55647ed214a2529990e66603fb058fbdeb2c6e9e27a3c89" . + "c8391d297c550b8678e990854fdc45590ef4e6765d70f607a0e65c1d19351b1d" . + "b0e9caefe2d7d085b80d9bec3a79d0c0594cc25b5b3a3cdf36ea13afad34bcaf" . + "ca8d102a0d958c5e62ca723b250e8d0302914d321bdaa5e15e7b1a7aa1ad2f80" . + "0146659d61e0f36fb55647ed214a2529990e66603fb058fbdeb2c6e9e27a3c89" . + "78bc5beb06ef2b5be15c257a81fdad1f3268168e695b4326762d7bdcd738c1db" . + "097825c064918eb40d9c37de8835a7655b929d80cddf92198ba5226df17983e1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "76ca0166bc1ca969d249075d34df7f8792cec53e6f2186e3d7d97fb2ac2c1a7a" . + "eed3e97df74ed27614214d15f227e4a4c7d4f092b3794d329f2716bf0cd69c40" . + "4a6469869e69378ef40c0ebd371485cfece5c6ca7a415891717cc090dc1f3a0c" . + "1e53f0d1e89287d25bd8d0ceda315e4bde37a8b179bfc0f9a82f89b947f1d671" . + . + "f7305d1e68e0c15023dec8ddf3933f2f9d1a6cea23f79561b90c75d3086b7996" . + "e1f16297186696739932f06df7ac7cf2194c9384ffab7b662d49e6ad161db51c" . + "e7f8e20b953be14f4c60629e35bb2bb98550b449a233cb25285dfd18da4ab071" . + "ede4f36a8a791eb11876ca2dbb66ec73d95b9beaf0bfbb92e05e416874a65b2e" . + . + "22e48e96152303b89e2fa3aeb0c863fdcf6e59e91fb0704c530f7699865a5eb4" . + "f3611d9edafb7ff5d27e3131281bb77e635457e1ea4b847af2fc0e06aa5b1ef7" . + "a653f08a2d3afe432ffe256af52e41c63b2c5232a18f7ac12a7a7bd9164bb0f2" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8d98e7530ce18abbbcdaa3fcfed1e9526e1d0000a03ac3274cd369fcf0b2e0dd" . + "c23ff19e4f58e941f493249d85fc64803d8386518f795b9017c3f8b12a2c60a2" . + "a6dd043620c4442ead1fb3af6a22bf9c739f819efd4e9b2bfae0b5eb8d367cbb" . + "6ca64249ccaaf816c9fb618bf16054246aabdd1f42bcf15a0d367e2eb0e8539b" . + . + "03ab234b6be6946c0a80124e0b6f41c0574108bd88cb271c7db90011f9392ea7" . + "dd62c72b6a5eb8dee9c2687306a35997d42b0152d86598610bd3385b4a1d5132" . + "227cfdd6a9e505f8221d6da019ddf4c747cb54bc16e9d274010a7d0f9b050819" . + "209977a8f062b69f8c4d3c5d84387643d900a76af65854a065cd0622b5e686e5" . + "b3f53b940ecb9a41fbd8779939cc0138e5573508fadddffd4a1da61d06a9040c" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "356104dfe8c4d66797f8de046ce13ebe500d19479485b05ebc20d44410605791" . + "674e531033922539e5bc22f5b16254c6e9a33835932b54f5740c9a7358b69c4e" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eb0b512b21d408528d518fa4ce9ba1c4e651076d639ced23d2a132119ee5edc8" . + "c1e2e6d25c0b920af6f9fad08bb291ece497cada1dcb1aed62ee97c04cf591c2" . + "8f7bcd3f66d1646e83d8f298370bc0b99ed4f06e6fdbefb1fda7a0a086dc751c" . + "f522a91398e9f125f4fd8279dbb44353ee0dbfb8d182e730611807191e9f0e16" . + . + . + . + . + "6a461111a45548c7f2a55fb60746caf502cbf0c8c1f80ccb47dd6a508088118a" . + "7ffbf588d545676ef3714f9c1aadeff098a7cf772abf39f93873f59f1e8531c0" . + "a506ec687f8d54a0891a6034a6c2485ba9776519d39948a619084d8cc9480263" . + "d76d043013dede77f1bfd16714c039de5205fdfed7983e0c0e8badd02ae9e3c7" . + "c821dc4f278ff7de133ced545633fd9da4f261fa57268a49b6fe5ac828ecd69b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7ffbf588d545676ef3714f9c1aadeff098a7cf772abf39f93873f59f1e8531c0" . + "3ef0b08355da09c23c0fdb17edae60b23ff063df671ae3522232f5953c799347" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "62c8f296b6b0cd61cfd3bdcd33029e0067abc9424085f5d55fdde71591203ad5" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "8460681d053c0d10f150181383a721c0c4b59233eb3098b4a53a36da4075f715" . + "c2e8d596408cf3a8c3f1888e4ddeaee335f4a38c7fb1c16c463145f35743968d" . + . + . + . + . + "24fafe30d1b6c8b94e58abd11d2da97ea0a815e46f4ad19ad8f39eda3ea595b0" . + "9b2f7d27b216556c8cd912eb331b18eda39c5e1001891af837673a5bcbf95fe2" . + "8ec4af613df5f0663dcc3b0525afe9140fecc2dc16ad74a2293b0f1194fee571" . + "d5ea83547add32e0b6b0a50cd81014a650710f8d425d9ce0261883b8b1886a61" . + "fb5c03d77e424d7d7bbe0e5015e06c072c87fd63c114e96c13f7850b83c1b7db" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9b2f7d27b216556c8cd912eb331b18eda39c5e1001891af837673a5bcbf95fe2" . + "4115c99d7949635ecd09bc4c2a9cbe1e486b4ed9dfdac60139bf44407e417adf" . + "99d54c80794bdd2a41b1343d251aec41b9ab2048922e0106515d10f9138a5573" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d4f1381f39c6f4d6b3f8809479c83983882cb8cec0e8a2bb48024c8210f060c9" . + "57076eda3401912cee7d47e6060e7de34d47ef486193e0b33cadbeb1aaab0ee7" . + "c7fa6e3e22e50a4400a5cfdd31d4a8cf59f070155edc8fab80cf8f420b94297f" . + "55cb4df4ec87bb42330fff4ccc23ddbbea8abc78def66f9f04c1d763b91ff10d" . + . + . + . + . + "b9813b52ab0b3af0f0c5a70d323c0e3e09b6384a5e93ebd2a7909b7b06e4a4e9" . + "7cd5899cfecea699b65a93eade85e5ef2be9c4429a829e9ab5b533424ef1aab7" . + "201b8ee54a27d836eca8e5825dd13be1eb65f1012f60214d30173755624e4e94" . + "e4ffe4398cc043d8cf4e98755db7795a788bb9ced79984d3e05950a89534b188" . + "3054c10709a898ae81be217951c8146e63ea4c531f4e7812daa2fc92011bcb9b" . + "3fc223fd8152114d548519c24a6958b18635ad78e54bd088fe127fbdc114e4b6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bf2a80760439b52999cab52a74fc4a4da8af9818435f7626f45c0de7ec1a9a52" . + "d2cd41626da6ad2bf545ff723086240951461c948ac6098f483b9a9170db3d08" . + "46f070b3d704f491998ab6cedd68fb6203dc8028dfb8b108075777ee099116c7" . + "652ebf1a185b606263bce123db983134627f9ea7f5ae70187c1c843e21e0e1fb" . + . + "6d024a4f5b55582b8d495b5eeeaab3446e4c33c559aa913ed795282589cd3e04" . + "b05acf3652ccf5985c39d628b5d72034be2cb88fa497d5f9a6f2832dd044dba4" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + "0e045dbac262b8fc1d4e28c1489d0952466ef347fa081194339162c8af51bfc1" . + "efefbdbb3444639cc8f38f519bf92bb759295503d8f895e813bb4f56cfa44180" . + "592564f573a7b7ab80c8f6acc661137bb23a70304fabe5955a8aaa1bdc537d76" . + "1e3483612c8aebdf93ba991e014dc8db384ddd12853b4603ddff220f59102086" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ff49be0af318c5ad2252b5ccbaca647c1571c8776d7cdfa5b8f16a54e85ec3da" . + "822178d98bd792738749082277cd4637891cf31476cb29710011408ec8b4f342" . + "767ff65cf808ad232f70b64d05d882125c3213df666a130f3650ec001f755d43" . + "1f06da7714bfbd03049c27914c045faf1495ff13b693afe5a252439e301980be" . + . + . + "d379dbc4d9482c59c825c758b2fc74a1bf4c92f19813dfd44489f4422a493fae" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c5bf595bbdd6e2064f56d2fa34a5d7c16b368caff4543d7af7a62ea3eab699d9" . + "60b26096e338a0cbfdf7ab5a4afa4968e99c39d4d9c8059f7c14191b8d498ac7" . + "a2cb18133be48777551fbe15f75a5c63d54f3658b45562fec79ce5158cda22cf" . + "0273cb401b03db8a5d0fd55e51ecbc862a374163ceceba93c624a9e222bb903e" . + "2f4856ec0cd348dbda9fbb46aeb1c5b730b29ba05d85dbb68985e1e3336a7723" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "d911cc709490b4775270a1283df96f697972cdb8d3b168a1b975c8b7aaba91aa" . + "7b9914175e7a75e9b5bd4dc7114010df20291fdd8146e1e550cd25302267b8ff" . + "1b401eda3dcc043d1f8ab5d8d38d82e98affd1ed1b6f14f3a685791fd271f0ac" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b8af4ea0273f0e6f75f0f4b3dd0e93375a847bb569698eb8b79dc4630ce93438" . + "e195a981f91fb39957df0f7009271afcbc54faf85659df9ac7e8c3868a72c929" . + "05afcc8a78744f88b4db23fb625f221593e8ef42d9db38e0c3b096c5dc200de6" . + "b6e8adc4f907407d4980697016101c27cf1e8101beacbc553d76bbc7f3e91d34" . + . + "f765e3788a27a991a552eeeb3eb08571b1b96ace304cbed546c92c181f573218" . + "614a31414eef1e5d50ef653b62a073a41ac6e054ecb5108e61a533506029964b" . + "f26a9f384b2aa7e233bc5a29c19cf99664aa890cc8448ce23bf2e0b8fb406d1f" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "99a2e1a3b9a871ce4452cbf0f48512ab5ea16a94349670bb97cfc4ba7fa69cd3" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "11c3d31de1b28a7d7f784ce0521cc32b5aac18d2c2cda67e5cf52a08fe3d12c9" . + "f1406a7f98d085102ffe08fc3aae62411a040160e73377515e2dd1e8836f7d63" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "adbf58d66f02e72a3c3179d6835056d4eae8d4dc11e39a78510fca718add0413" . + "323b9de50985d980cc9e2b18474b5632abfed798123f02aecff74669384c3536" . + "98e85bde0d43e3c302f9355dde9eb4c9880371f702ed8b6e2aee75864b3658ca" . + "a5bdee1c1c46974656f3cdaa35e2ce15d44c78531454738cdc8163d31ce5d7ed" . + . + . + "490efefcec4e7d65ed7b677360f60e0e7cb5feaefa0cbdc4144b8fa2bb3a1505" . + "f242166b5c80f90e2cd0b3421a9ade88e75b6028afc6be5248dc3a80fc482849" . + "7ae73dd18f650dacd17d665a5c06ba64417a234f93514af1a499469c0071bd51" . + "323df71c8909b363da3ece635c07cf203bb30f114f1daa6cfd3a8e5e8a023287" . + . + . + . + "d59812e4a0f67576fa244f69e3c295dd388704a066820372eae574baa8f474ca" . + "42b810b1f4c7f7a7d8cbb1690af0eae45905b8a9fe59772207b490efbcc901cd" . + "9d30ebbea8792cf2bdef718ecc2371a79a8c308b85728411dc7767718f51b0a6" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "080fb7ed809aebe94e3bbc4687d0be21fa7aaf17b37b01f437735f554daef171" . + "8fffe328857e7d235c6562f05ad8eaf4e65131debb495f189d3a3caf3cddf615" . + "45d7664ac87faf4c457f96dec2c75925e5ae3f916b5d466532a9a3a2303e34f8" . + "16614dff813174b133a1579f43b743da821164596420b9ace119e04aa3f4b009" . + . + "d5926d3a6f0c1f9e740b063d1c1f1642be4dd98c417bb155978091cce628ec8d" . + "2c139e913c15401fdce50539c8f51d3c3ea26030c164176a272a172036fa515e" . + "7e5f83461998b9f58f350e325db5ed43d70a20d9ff85fe77db5a5f6c6a1f2b7a" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "18e388123182b5506d8ce1e57d1119a95e82e09a5e57408876580f558cb8167b" . + "efc11faf30d8eeec80871bae2e732a2ff2a18a77ebf4455121082bd550c2ff87" . + "02b35ae708c6a098e6d3eb8bc6b0587fc60405f29b26b17c42cb3f30b94668d0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d6de4c78374cde64ff2c8a37066122c9ef1f9eb3173658e7a3300bbe5d4580fb" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "cd60b6faf93cc3bdf9efb0572e958c312feffd077620728e6188cce83d3cf316" . + "18ab013b7785915beb33a21e39aad704b441bb493529647fa333b3ccb4f49931" . + . + "ffcff215d621a173667c744fe35b3f967d81042250086e8de8bc60c335c0dcb1" . + "c594f161ef71afc57074e198d9cc8287f8964f4683d51291b3415633e476960d" . + "f5ae70afe088cb254d1a580ab328f6d8a137fa1bc8fdab445a08327340f811a5" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "72c462c4a8d6f2f331d6f10ecca9b46bf300635fb461521ec33b0c7671d77a1b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "765631f6897e6bfb5ddabb0b2c1d65d135b467b69cf8067243f90aa965b39a5d" . + "fc3b553a96a39af6663ce01ede3ec11deb6f6d278aeacd3ad88d147a66bd643b" . + "8440f3ef5730102f6ed077b4f195011a0786118ec78ac02b46ab0d5c03d93bcf" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8bedf2139e38f826fc425c08a14e19bef1e324d6c6367e3fc1819af00c5edd3c" . + "86e89049af8f413b7ee54a5f9c652ce0273aba18baabd83050fa74882b17b8a5" . + "e077298b0d608fb5cc30aa2d087d75bb6a0e99a216941c741b442e111379828a" . + "de464364752def3a241e9e6cf8f296df058feebdd50610dc9d354bb8a8e2b76f" . + . + . + . + "f4def80823436e9cee9276b0e7f9c1c0632326c73d8d4135e792230ff5d300aa" . + "85bba15962b60390ef269139db41da575dbfae682bf1ef9c09dac9e556ba04e4" . + "0c1b1d4b42cd6a6a0a68b7c75d1b4153336089de9be52f67dcb7b1cd6e9e1892" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c7a2f1bdbeb009d3bcaf10f83b462d8a7a83d5c311bc0cd00bbb21902ed5d381" . + "2b59f266ad327f68714ca996674ae29ab09c9030bbe83cf520dc0192264ef466" . + "f4379b2ab22a72f8200fbe6dd3ee1303366a6c02649ec94b69b57dbd86aed7b8" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5034b6307269ef298ad922565bd07c5d0a02d0104c1539aea2440fb98f81b2a5" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "a69989b476b76efe094f76ab0faf9da9abc260ce048896a2c97f80eab6e22e5f" . + "5bb32b4f5a1466916816a2b604cc639d632ccbac12000d3f08fb200e3455415f" . + . + . + . + . + . + . + . + "4f9c532c6906783afde7c1a1577ca891f5213efa86bede89a64b2e9b2cff2f4e" . + "f27a2e823155aeac796439698c85ba187896c251f014161028e90a77a8cd9deb" . + "6381fa11a76ad30093eef067c857f00fb899744922824918f28f34eaacac8cf1" . + "979367c1e303df7393630678c7f583fbfbb2f538940bb713ff05d06aeed42edf" . + "53535913557f7ee3f3179adc6f41bc52fa5662db85220941ed4d28c62a6a67fc" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "40dba64ddba8e5ba53693616464372c6dcf94121c1c42a03a0d8870c6a05a8c0" . + "95693d486257d7370c3ffb2cd1d08f8dc5d969dd991291b86870142bb58abe9c" . + "07b0ae59f5e32075045243cf140ba15d0a00b7d9f633bd2172501431f5fe9bf3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "24704e705db8aa532ef11c61599efd7e7928cdc72a1ef03175081891d8c7e912" . + "4b9b1e4bd324754a1e1966d783d4b78eca42d88aee94811b70fe9917603f0f62" . + "0d9e3fd563ce762eba5efdc8ad05f4202f679ea671782a53dd3942928c9c64cc" . + "73a8d614d72cf359dbb3e73589ee90e99359faa94a6d3166db1efa7d70a30c27" . + . + "271e1bae853b3ae481a2338c2a5bd5ee9d6b3ffb63b181126398568ab79b7b11" . + "a8dc3fc13f7a440a31bf4a289db6382d48ae50c0bcc21d11e295a99a3e1e6a54" . + "88ac44d7e73e0b57678ea59718b74102bb7f2f47df6cdec312382e90429be402" . + "155b8ccb7dfccdd275dbd6cef199f12b69f3073efc297dad8674a48697c35934" . + "c1fa2443cdce35786d680f6c3b113e7d798d76ab5fd175bc1ff16dca9619c744" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "5141845caea4d0ac8716efbbfe07d5c688808bcea30c01077114cc055df0a36b" . + "12981536ede8742f02cb92b43c9d66047a6790c1e13de466bde772a97e6b3ebb" . + "80dbf4c1094ee632af2a4946067565c628d14f976ae0de7d29fd23c8881ec35f" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "30f940cf0b005ce00d6f8eec06a3eb1050e61967389d476f30cfe7c5a9ca0550" . + "c404d5a0a0b824e6ecbf4a47cba7dd9308d0e4b258d597e31c2f8c3ff2b8b80c" . + "f5257b4278aa3ebdf05c984861d160d8aae6717abddd49b61316cdf175179e7b" . + "09baa59afb2cea20ab8e55b289661ada3788fc366d145efb78a2a9e55d7587ec" . + . + "719a294c9586686cd0cde29fc96245a370b64713ca256b5b8a3d339d9a3f6029" . + "08c003a71965c8c9a97b4f128b1247666d352b499859542bd7c1f9e575b55b99" . + "da4a0b13d1c939d015e91b924ca0a96f80a56029bfc40b10df3fee261e3a3e6d" . + "af23239920ab81606b813dd6a7023a6ed2d0e8fda17b8042abcacc4ae2cf841b" . + "9fef46afeee0d1c1ca2a354b9bd85f8cb2f8efe172bf48dab8d6d410089acf14" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "672663ec820e1cb8bd5440c40de4fa9aa1ffb0a49641f679284bd60fec01c312" . + "7ff9276c2d56783d8c97f38f1e3829b885dd1ecdd4a0687842772fddd22bcc38" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fdddda7bd343e2dceb0cbfbbca6c3cd61eb14b6e98b721142812d5de3bcefd50" . + "217a0ef018c5c7c6dcbf5baaf630e7a23cc38faf130c760fde703bd4e0c2e6f8" . + "f29cdf6594e9a279a0b681523300026e65b221d27eec84b224f3de008faa4a5e" . + "ba4e2d19b787b6febbe273d2d776253b305a3dadb5c70d7c5f3d090c2ff7bfb4" . + . + "5515b256d905460408dc72a766eaf94934101226c41a3271c90c0d3cb011ae8b" . + "064e944688716171f89e4424e6ea1796fcc94fc4489c898efd69ebacf63a1898" . + "dcf0df9fc414a1272fc692c00357ee200044ec8ff2eb255b3f6387abdf1f7f03" . + "821ba5a1e698ddf5c09ab58c145b6bd454d7b335f797a5c88ce8d829b89e37bb" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "064e944688716171f89e4424e6ea1796fcc94fc4489c898efd69ebacf63a1898" . + "73a9adaaa8a307a85e1eb93204cbd719acc08421d143eff59b21757235723390" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2a594a5eb993640b19209fe8707d1759a6b4310f738502ec8e3feb56ff877916" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "99f2298d1122077ccb7306fca79ff37abfcc5f186209842991c78a23643768b9" . + "160ec1cfecfabc6d9c12cf684698414d1c576cc89d70222a1b33d02095d7a1f4" . + . + "e93e4b05a89bc37d4a605eaec34db96730c10c538ba17c150f86a053275e93ea" . + "e0f6fe6fc88d4604c8fb2e76a183d64f333e511d77d81cba7bfea060071b1462" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "457ba8abca7460250dbb2ded124724e7b5d9d4909160de07fb94d57fccf623bd" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "45e4d98a79fa608dd64b1ee7b94d49461fc3d1560150e96dbc41bf63665aaa53" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "1cdb9194caeebce26cb785f67351e12291b2d2910399def5a0f3e57d121ed9c9" . + "d59f147d3dc9a63b6817130e7c3560464e9c1a2c359e2ac919bc9e975d8f09cb" . + . + . + "5b44fbefb53caac4bef4dafa7252eaab083a36c40c0ac14740b0e63f6b8b61bf" . + "fad7d61b5be86db0b3c5d357911d80ebbba7a257ccda09a842c6ae134ffd9b05" . + "e2bcc98472b4eb3aeeafc7857daf9a7dc3e1e169ea3a463a41c1d74d1d984bf0" . + "4bcd7d16afcb755e22b6e2345fbac90dbee4ce6bfa42424ac309b9b59874ce7c" . + "632402001fd54f94bec554059c8c927ff03b624f6c10aceb656512bc692b9572" . + "c3132d5c3bb34f217772be90ae176b73db1e9d247cc696b40fdce9011522b025" . + "6f069c747cfce205731ed29944456dec411c97e7f690114399f2d8f182613fa5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fcfef4752b92e50e8246e34743b84c135e89a41a3e5f797a460a34813c617be0" . + "0249fbb7f0fa91e66a9fbca876f0f81a69db2054ed0287759fff3be912f1d64d" . + "b39de6d779c3452782abfd9af6c8797085c00e77959224346c310f38695bc62a" . + "a4197687a6dea7a7ac5fa82922c3973da89e42c60f08122dc0a83e733e6d3eb7" . + . + . + "d6ee1d88625a838304e7744ca69a72c7be84a07f967f213736ee56dc8aa99d9a" . + "9fb3b13e2af25564e8bb8ef9ad81ea858fd8db19363e0a82c3b4bbea47e60093" . + "278659b6bba5ad7c9d3c7ceb213768f89eeac09ac44565329593f7bc37d857a3" . + "2f6604a0ed1889e4b110a04c592ade25db3076f78e9338fe5138a426b69060a5" . + "ecd03ef3110287bf0b24acd052c33c1583273f7bec07b7dd5755fc0741574197" . + "86924d3a982934cda9b01832d31480304a70a2f08bd6651aabc9647ac1897c6f" . + "558d408bea4d0e08f56b1106233469b9a65673a9a73de67a75b45a6310ce5504" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4facb59cdf312d944f6d6088bbb372459159d40493b5031fe8563f878b18240b" . + "711c2d8eeabea729206870c307b0dac69d748b997cf3afd9ea1c6194835e3c1b" . + "12c1ec865cbc992b963ef25e34582a641e9832785412771b0cf2f0086af50b3e" . + "c4029f828e15c85ae7ac48326bf4d6acabaffda4c164a318e20217a6ce12c055" . + . + . + "6f5bb6ba98c0d968c7f204a4237ea163f1711ba3a57817810e8a675abd10e17e" . + "1114d6f9732579d65621c499a8e985d97d730ca4f290b76c4f98cd006e101d08" . + "9cdc0c0ac68a154f1fabb593bd636c50447606b005696815ba856c0d57316f69" . + "11eddc5ee5ce400f92f6ff886981b3338840ca1fa6bf6a0d13006915fb28554a" . + . + . + "86e32eee7f51f03d42a14ead994827ee083666cc6db363726e9ce442f083916f" . + "50bfbd7a61388ecbe94c7686b1846c0442c83028f62b3a811264dc1b5d654a4c" . + "66425ff80138771c2aa5a598c4e86dce73ee3c5484eb447deaa2fca8a3cc54ae" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5d455800c6834ccd6bcc828ffe56222c323565329d314108a83510d198852b66" . + "99f8cfeabecc4640a9856c8bf2b8698105a8fc2cd359d8a617b59d671cbe2c39" . + "1c1760e83ef7e58396ec0ac48c6b80e5987131441b3d9c76799810c94296fc32" . + "11e028385d07afe7a4feb0d57cd932b7e4a364ab00d0953a05fe625748a6c340" . + . + "06abd12fc407ddc984eae9fbd626503e2a6e78d87bed22542d5a1f83e2baffcf" . + "b7e14af8a17405cf79747b636ab0b4433a49c78c3cafa57214c5ef7d8ab4470b" . + "916ee1a57de2de9522b2c385a0845da8675e0ff2b26f4ee4910ef9a513fcd6ef" . + "ccdf85515392c092848b328b7dbea256f353408788f50c2c241e720d4af0cb53" . + "23945ce8c9b9ec56176b483e2cebe0be1cc2196a813dbfa47a30d2862e58fc87" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "6ad753e60ab0f92eacaf4492c6e1ddd0e30752521c8cf87f782c457ff1e2755b" . + "da9001d9d0626ef48a45562f69088563345829e91f819e914b0b60f196ffaa83" . + "660a4cb6055f53e803faf47a0acfdd3f40cf8ad402be4c6857f02f1883f221ee" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6f5d486fcebb907e0f67c9170e86ea3cd4b287f1fd1f8d220e12ea8c41f451e6" . + "38a7dc54b25ab3a7e76c69919aaa8e18f157cd959a5cf284a5b5d6c680084525" . + "3f2e14951d74ce5f462a9b95263a4e27274c7dccdfc545a44f1679e088bd3587" . + "c25c58a21bad510cf0bc148533d904fb8b69891cb59fb02888fb7f4c3817edaf" . + . + "0898bb372ee4db064474f00869ea6f2172ea01d5d1ce88c3702e22471c063724" . + "c2b46c0a77ddde5d20357c05616cbac92836bdeb0ddf2739966d9646211ef5df" . + "2e8391b9f7eab281e66adff5ac1efeeeba295a29b62eec35d4f8b5a355d7b0e4" . + "19f5acddfb274fdaa5e2b00364054349b1e0d96a308924f5e53101b7e8c5b78e" . + "c3fad642f9a1ffbf6adefc840cc7f43a3811e43ab24f0c6eda75eeb21c22248b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c2b46c0a77ddde5d20357c05616cbac92836bdeb0ddf2739966d9646211ef5df" . + "63571c25f8496a20355bfeb34a7b622c328f79bdb4c04265ca64c2469514f831" . + "bf508a3718635005490d6ba5e21264af6b0af50aee574d2ffdd0cbd6deb538bf" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7555eaa4cc1ff3e8ee739d2a391dfc1e4d82390077f57b07a02600cc187c41ab" . + "3e742dea9a406f2ccf0389f7333813beff7abbfe2b460e8c746465985e53844c" . + "6a192c3c3dce62459c3dc22c02ff4667c1adfb0fc180718449cdcc798c8a4932" . + "4fab4cb2ff2f90ba833502234752c771d14b277324ad2fffa944a340bfaf117e" . + . + . + "de53ce849b86769feff1f8be0431f7b3978c5c0748fdb9c9ba2f25a9274e227e" . + "742a23d0f9033975c57ab2a9c97bf3ff24f5172566cf4ad7a4db91cb232ccd28" . + "871d125790b034da00f7767225ab50cd9f14e40fc08d112b5d7b6d14815ee44a" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + "3596b040be8d5eb6b393c11ebc85056a16e8edd388e63a10d0be1bf0efdd4de6" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "edcb85a7e2a8a05d4d6764c2f1150bc2e3a3078169d530f354d6f449ffb802ec" . + "eab9a214a37a27552360fc6413a7856ff2bdc048541660ef3fd68d3ea0ded285" . + "89f16f2511f5e8cc212f27859328b20a5fe7a14ed1af6f93dab1c56c3d6d0fc6" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "11f51f1a654891d72cdf7e2a5c156412ce45a919af49462a836c7cab7eea507d" . + "82a265a38aea6b2fab9ed1ce1395594d37d37a0d5b4b06374d4e843ebaa5f3c7" . + "cdfde898d4fe1fdcd3f3a3bcbeda83989b0dafbc02c01ad1f43f03c0dd114851" . + "9d58218b455fc5b0353ef135c1dfc55a79e78b54264b2894b18b57c60803cecc" . + . + "dfa71dc1cdc451530326ce0976bdf7b45c8db1b4e1d29e36f6b999ca87f4520b" . + "beff279029468c0cd12fd6b90d62a5c6666ea0ef62e794a5e16852249029402a" . + "3af7dfd521fbc1455346dc00c7f0c604399697e173b1cc12069b076ac29b32e0" . + "a11c25cc357ade9adf2dbe79bf2176b42a5bb2df217bcde2af6cc9459535d651" . + . + . + "9f0ded95ff756fc8dcb30063e48bb8801d955fcd1e2fdb9c24cbb5e547accdc2" . + "069993006c423fdc15357f009a64cb308a2c6445f42549bd27e08020b77697ff" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "da58e72c5b56aa7c204ef4061c35fa16ee4c305c276884851ee1447b75d52488" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c884176a36fbdf9876e921e903cf210f5d670638d0f7ecbbc10b79231fb664db" . + "d92d7bea2b35aa4fd934066bda0ff3388e04786e767d0148972f60a3b36f9c81" . + "96555bacfb494cf921073dcb6c9c4895612b215b6f45ca227a9ee61f8460efbc" . + "b0bd977993bb1d731ce8ffe0dd12236bbc3fd92ebcbd3b0437ce633fc93c685e" . + "63995df6e6396ff0f25c60e977fb00bd8ac92f570d2138d4a0fac9ba872c7989" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "3d905b3f1bc60f7543b1ead7cf4d2eb3ff5d9ac694a674b6b5cbf07219c9f3f8" . + "6e90e506ee0c6bdeb0a8c2d1f401dd4300d3e11e355832c37f4c8461b3d5dad9" . + "a5393d3727536fc295fd7edf154241cd6ec87ff40a72f56504417bd16f33a9e3" . + "3e827ea306d9e2a806174cf5450b52ef367e39cd535b7ed171ee378d3e5a7408" . + . + . + . + . + "4f9158f8dbd9eff5733cca08abf0fe4df54919cf7932f87e481a6c3b5331a767" . + "0adfcf9ef00e7329629b9e1407e8d711cb343c0bf9743183acb6f7828a8b90e3" . + "a978a320adecbe64f6e93e59812274be1ca533ed35adebd917794b6d851b3c0a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "42614a257acb57ff68648c1392c53efcdf469d66b375663fc4424001b8e4789f" . + "a1bfb3d10ff49f6064727b48bf2773db877301a7692982df9a375e0e95e30d9f" . + "671af84a98f554164deebb50b36ce6f81d9c59b0006e6efbc19aefacedaffcfd" . + "880fe9c18fb55c7f959ab62e1d6d591f6966fd30d489dc1171022157b1a44058" . + . + "14861080fc5cdefe105efa702f172071da98562e1f746499afe9ca078a41a73e" . + "a832b217ba59a111084c9c434712f138ef8c3c6154065ce3191dbd43a2c6dd35" . + "e5ab870ec0e2b5d3665283ba651aa6c566cab0cee74244a1178fc717aa0d7377" . + "706eb143ed3c25d1403abd826af2e0b15d671a4ea05ead5d16fef54e8b5e188c" . + "3658d60999350673516f43053b519d98d46b2c4ec095b02174cbc4fa5c724921" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7275479b944f84af4824da4c0760afd494a8a6edf56c6ef8f2558a2fb078b92c" . + "70b46309b84362d342867e066ad218014e9fbd8d3c9e2d2979044383143d570a" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "794a33c46b93aa64db7871d09c5a8b498c203b67c834e2299fc94055230586eb" . + "a5906cb7390e55ef146bb0b39d82d5787e6df41514f614d004af6b14b85c117c" . + "f78b9c9c3e1b33dcb4334546e72512f70a5e8ac9c8551bd1f2e45eab7d4b682d" . + "0c5a839c6cfcd6dbba3dc91d375b46b926e7712531434ead93963d18e40b3eb7" . + . + "7829da36f498202da0b3bbd2735c1edbb22adca71e39c3da6e8a670b71b707ef" . + "9e2982488e3959f3dd7c1793293a117f3ad68730ad9166521d8a6d2521ec353f" . + "ba2a38c2c7995506a39fc00741d35f16064ed0fd1c9d83a2d6ce97749686e3ff" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "821ba5a1e698ddf5c09ab58c145b6bd454d7b335f797a5c88ce8d829b89e37bb" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "1e820428007f1c81fb641f52763b0659d54bfeae7adaf36feea74a2a00399e74" . + "e3a32954c4d5c5a103e0190a32c8fcf1f509df8b08d0d8ff3dd04eea4550c63b" . + "a7bf2f5f3f8ded1731fc7a69d3cc0e9fdf2c73b741ac1625a27d61bf3ab9fe76" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "801ef175b999fcf5752ccbcf1ab8f4942edc85a30be1ba930a89dec29921ed0d" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "b83eda51d2fccb169d96fdceb838e21e2c3ad824df9c6babc62d27549dc098a5" . + "05069cb727ec020dea6fcee0a6d4089834c2410939e62adbaaaa8f6b0466d6a8" . + . + "d1fe511642e57e3c30ea820a03d3be56d91324000e80381bfa7926ca45ab5317" . + "5e9ead9afa30d1e3883034abfa9b4a0d7bca0357c323fe470333667de52f72f5" . + "b55bb7a3402acbc04a3c6855ba4358158b294b52347f0c863de03ebacb13f2c7" . + "4cf6b5480f3a772a9d68682d10a367f1d5aa797ecbf0d3cc1df210585c1907c8" . + "c543194b8f5a51e9192fbe1fdbc6b1782c34d21123ef604096cb16b6d4890528" . + "5429e8bc0e914d2ee20a6310fb49ae326ca1e6105332b4315e053809c4917a6a" . + "d5c4c8b6ee4e1fe2e963600b869150668038c2c47841fedf4937554827135761" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "268eaf9e6a369ddd3ee3c8c66e7b8bf975350481295a1167973ec944170bd653" . + "ed54859b869e19d57dcf6774659903978c1fbcdc0e9f8438ce53f4dd1d23143f" . + "a26035b67efa248f2bfd4bdf10b7aac53eb35a92137729060d7f37efd9cbf6a5" . + "827874335c1eb770a74179f0c9f25f025576ad11498542177ef9b90f324561ad" . + . + "f75c026856ceb15e219152ac276ff4bd7ebce3dc199abe84c55b643ab7e1f7ea" . + "62cc3774d1801c19e6419b535b074a03ffa42236f08adcf3e73a090c58b9f939" . + "a5906cb7390e55ef146bb0b39d82d5787e6df41514f614d004af6b14b85c117c" . + "5a619b1314028321993fe807477c02c8cd45df5baa61e7a599a96978ee47afa4" . + "d57fe23d14be2952be969a1d0e881c6ef8fbfa82b43e227bf8c3c41e76923eb9" . + "34024be4499d76b8617761d06bbb17241dbf71702abc508ce7fcf10406376795" . + "767d24dbf1bbb07d59f0f1c9ed03b8c21c0de92a6ffd3f6247ab2e248730a18c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "578165e9a8083e7b349f5a579a0adb573b3c578c5fcfbb66d3c22ae8f12716a1" . + "2744bccb59fcf32106b460d4bc533983e80bb8a402e273e0a1cb79ba871f2182" . + "42d39921773df362cb2d9f795e65ad86432f6a1714be016def91f3e204ee4028" . + "5fda013d59895a616b7c162d13c4d1a02a70dbfd4134b64e8def5ccbf8979b86" . + . + "44d38b0cb40e2bbf34605da4fa40f02e7efdcc205c4417dcbaf8249956956157" . + "3af738d109b50ed9256cd4ea49a9ccdddbd2b413302aeffcb22d3c6ac7525239" . + "26e1f24a7fe3459ca09cd6547a0d6dba43a4807482d03b00f92ed16494bee5b1" . + "3a939550f45494d0cdf88dcd8618787dd67b523bb0eb705ca6b52a3a8b6aa2f4" . + "78c7f1c12db904ad372996b1357df7ccd137e82ccfd00a6288da16c1a9f12b70" . + "e861ab8b73ca35d4237001ad361617b810f985236ddba22b9a50ebe3a61c1833" . + "f83a28e6c07b05ff54c5d87150a186632e17376032f27d813076efb2474684fa" . + "44d38b0cb40e2bbf34605da4fa40f02e7efdcc205c4417dcbaf8249956956157" . + "7df257b0019568955744449b3569c0406b640545a69a497efb8bab1d10e5f3b8" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "988d9cc38df5588a3528633e8b9461237a80a652d57a8e4b2bc68425dac4db16" . + "b298d59647c9a8d8e7df3d76bf4d2c010040de4e6e02d92758f552e5c158a6a3" . + "bfc7c8bc2444d3cc829c316bd47ca90fcf56978f46666f37620b31667c4e0f38" . + "bfd02977e60fe90d3c8db0e624256b9845aa27cdf565ea832f0f99a60152926d" . + . + "848b98f2cac5e0315193cff02e848ada1e09a4743792da01e20b5a3f51a63308" . + "af0149c38c8f2acbc890f9359b5aea7f96cb733d6ccd26251429cfc4a766afdf" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + . + . + "9b87e579a9b4f7d1fdb8b8c52362929f5d2c5e731ed529163f7cd571ad76e930" . + "d4473db5105dae59d95f19f8603f0c479344aa2b463ebe0827811175565d9a3a" . + "332e6d9da50ff4f3453b3bff011834c9af2a38578aa2a00483018bd6aee9eb89" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "06a4e33495924d289381d7c32098b5ff641cc6ce2269eb36e7ec1e5cd72454d8" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "552413e9631721d1c69c4569a80197162bbc51821c214535fad4f72304498d53" . + "6561e2fdb733fb45fa8eaf51cc50a53181a3bbed99924a0e5c8718da4967aabb" . + "42731b8706b44c9c97acc2218afb18ae4c6d12184f5dc452f36ad1d1ceefa2e7" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9bd2d961e747f086867f7ec0b599841ee670277cd9113d20f10649e7f2f98911" . + "79561a0af3f32553336da42a61d24ac0d593ae600dce717ecd9ed9cf7d66ff95" . + "0a237cd46bc96ae66295bfa912f9bff64b60e92a176f34b50bf384442c5873ce" . + "5e3c75f78221d52e3968445ede68b17beebc8aa838401586365a2ca121abca5a" . + . + . + . + "6d5a4654f4c34f53b1708653e3575a5efd6a571bfc8877bc1fa105c83076236f" . + "7e82e9697e28c9febbfa373c176646f32779997277ec20fc087af941acd4e490" . + "63446ef864df7e94cd8b04dc8cb8e7d6b84689f6d3c5ab3d5a40cf417295a940" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "820586ec713cab9c83dd1cfd73d1b50a196cf1764f877bfff6468ecd5d5ac448" . + "f6eece07de48fd00336b0782670b90a2ddd255020b306851480205d085702c24" . + "acc00597604aa05d4b7e1896fff1887b37fde0018e962a0633bf0ba1a6598b28" . + "73f43917367b3ce0b298aa4292d404815dcf46c24050939d35d0bd905caabe0d" . + "fc5d86b4ec4dedb4efa189fac08f741792ede37b756452cc007bfdeb452daf5c" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "bd19cc9e2c7b1933de6a97faf4ce92238a9f324d8e5fe99a2f3e954798ede962" . + "7f07467e2d33dbac1deddba2e43c706c1617b8b5b7bd7709ce2ea3c79a7a185e" . + "7c1719b4ac20b6f3e01736f606e080b997ce38ed93ef38aae7d5da82fe3e5b7d" . + "5bc6a2dae68017bfe3d6becc12873ef85f52889d679679b8750a421381f84c6e" . + "bd19cc9e2c7b1933de6a97faf4ce92238a9f324d8e5fe99a2f3e954798ede962" . + "616b5f32a97bf45c8ce0d2607d52eb09710d552e685fce7d6fd386d238c99d9b" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "74d74739672d70f4b35e8cf383fe00e100fecf669af29523fd415e2fa6b2ed2f" . + "19ab1b013de2377ce35a6c8363eb813563623d5f6a4ad001f2009363b99d3d2c" . + "0148d3803ec6269bcf340c834cc78623e76358c3f11782b22a547ae1c91c210e" . + "ab76c6b8979213cffc6d92a7c4257edc56c4500087b6a95b776849734af6d35a" . + . + . + . + . + . + "c5bf91fe7cd9e30fe4ba9b3a4b5a3496311b334558b8ae7e253c0d5199d905cf" . + "2c3d7e4df8c7773099a2e7b58254034f17a831c1de910a93354ec54e320e4132" . + "3c22a9fec6095f58b1d0387fdcb67f0fead14108de247ca6ef267a1eaecb5c2c" . + "6a146f2cc14baca6b8600b7c20fed689342c7e2e4f3cb82e0bbb3d59d87e3d82" . + "9cdc0c0ac68a154f1fabb593bd636c50447606b005696815ba856c0d57316f69" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "a0e69f1d5c38f8ac4ec032c17535bb9f2b405f3c739208ce9c1404e68aa335c2" . + "aeb2234f8a72f79eea49ea9d70f2a6d63133196e60932cbd1a4b1897199d5848" . + "da340d5dd825374cde36ce4abca8ebf0966580c94e07ef8e6abfa1deb28a25b6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "acaf479e736ca00951d4978f2f969b07b378e215cc94d0075deb88ef33aa83dd" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "39232d11b1662b7f79147dc16eca775961d020d3228e0593821a2cfff507c0b0" . + "63209e0ed992715a56011fc6f8a6e670caabaebc844c6e7a28fb23bbecf91356" . + . + "3918b8a701fb9e91db7b87154ce624940fce74f29604048518c4af896f57f26e" . + "07455e2befb7cb374c0d480b007dc71ba31ed12e3f4eb296adbad3828e5bbc15" . + "7c06415421748ac83f58209295205866ab053f82a6448fad0ee7a95f18298c51" . + "715a2e433f355f7037f8424b4778cdf65716f52e8a5640470498de7914493508" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "bf761da4c62b7d88acd021b8cd92bd3187bad740cab4b12d1dd7e9761fabb1a8" . + "0b1e356d0af643f17337917b9b95340b4e5010fc8f9fc0a5cdabdbb367b5f2c2" . + "eb602ab3abfd1a28d3904db335fa33b6e90d7e584819663d79739c14262bfd29" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "87bc2ae77dd59ce677cc079d10f42366ee7d9c4da6f0f792bcbd05bfef555178" . + "dbee3bc293cd2f976b6f543cb465584f9d531fdf1ed8eb5bc4a99d5204bea558" . + "3be0c7f843eb3aae2a14af55d6a7e882db59c4e7c1d0dac5e5967dc3fd65dca6" . + "4f06bba850a2505f972f499382b7f0f87062ec92c3dcf6513a2d3ddf4136213e" . + . + "f7b4260bc80f08842e0303221c703a04241a8ba3a467e9a6a1fde1f0726a583f" . + "311988edc12b5611202c1e30cbddafb07d67ac699d0bf4c058dd7a76e46f73e4" . + "99b1abb4b697ca6fbfdfc0f430f6ac09f903d7e67234e0ed1b29c3c7ad066b6a" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + . + . + . + . + . + . + . + . + . + . + "8d236468ac567fa57e798bb030ce727f7a954e63397b1cb75a9e77752b708ee5" . + "6c42ef0917a8e8afd167129d18faa90f9caa2fbfd5d5a63ce6839bdbe42c38e0" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7f4fe46bfbcf988d501a9b87494fd9febd842b4df214c9c8fdd4ee763a61481e" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "731054d221a570e0ebc88f381a6f1e12ceb7ed0eae8ec865096e6bf26a68aa26" . + "0026b73b3e8091f8e27d5b120a9c3a6734ec654975beaff492f3ba4c09c989a9" . + . + "1d2dba5a3f6e37a215384c0f1c3a71b1a3bdc6666484720b5321cd82f13bfe79" . + "c01110ec5326e527a1a35202877685d37d1ab35b4bce1fd73c8655459c976bb1" . + "dffcc1b124d2268b6b1345166814da796bfe1730630b6aa47998cc414e7998f6" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "6353b26512124efec73f474a5c3d8540644e119732e6b444bb286c1649e25c73" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c01110ec5326e527a1a35202877685d37d1ab35b4bce1fd73c8655459c976bb1" . + "906dfe7948cdde2228d1c806bd0163c1058d4278625ab1e444498cd5ae3df8a0" . + "6dd47f6e8825acfaff90295223b6d11790eace827dae9796bee4bf29a8cc2205" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f8f59ef9f426830af447df83582831ee1c9eb3e86871e417edf4b7ec13cc11c3" . + "107657727b755c714e119e7bb5c88ca8961c3de0e16acf8073976624b45c90ea" . + "1f7800faf0e9701e26493cd0114a92a19dcbc42a8d72dce560df67914129a1f6" . + "9dd4623b282a2d77a794eaf265d19400240d6271a40eb7a42ee0f82f0cfa1866" . + . + "410563af03343578e3a59414cde9a062115b137c292414f54ede4bc91af96364" . + "c70e4ad18d3b462b41c2d7fb804e1311f999766d4ec05c74d0feb7ab04187608" . + "41ab2f52dc32f211a6714a40590956e6e5071a1a96abe8f79ee44c7354b1a299" . + "e881d20ee1cd2c978c6b6ffa96907753cf5d6b2b623af3909ed36e4fd59e0d92" . + "57563ebe9d321a47cf2f44e95ac3498bb11b9bd6e9770169b8c15d46f244ead5" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "0ba9e91d2b98ee982d81f116dd226782ac7f9b506e1ee6da1d3c9c793bfb70b6" . + "5410951cf0705c35d9b500905df85b56295d72e92925ce118f3765ae95ac0f83" . + "fe182069747887cd77cf5209b72a59226bbe9de2e0d9ad570cb98f351d0a100b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a7ec7ebf45b74ef9adb5c8171c40a0aab9a969d707dce20c90963b7d8b8dd8e0" . + "9c200f3f134b5bc51598bf1c880431ddd5b8ad54f0b4f2d0deaf43e54f9af653" . + "4030b34dbabf83dd35eaad3249e00143d310e1f60c195401912e7c84d90468c0" . + "393bd52bc5b1c3844326c85cf69cf55a845ecfc8ed85b3a349e41d4cde04cc72" . + . + "e1947de75a684f8b666eb7c875b552bb9122de10f459d482dba66a9f2803b06d" . + "9f5ed452571b70bb2ec0e8b6d6b2b4ba7a981c992c099d6d4d0a074a398a4582" . + "be4b7a70b85ccded6fbc7f9b99de0f9be7d56a3a51137054c5254f7c034c45d8" . + "58a50b63a096cb71bf4f6f622906cf5beb9599ddbe00eda3456446ce8e072ba5" . + "3e992a8c510ef9e33febe5e6fb8bb17ea3da03d46f3d9be4270b7d6246ae0e7a" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9f5ed452571b70bb2ec0e8b6d6b2b4ba7a981c992c099d6d4d0a074a398a4582" . + "6ef00d46cfddb3a1e66d961627f7e56ccd6f7b1c772e536b248c701c04d284fc" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "482543845dd3676306bfa12fadfcec374de38ad2f6177ce2b2b4784992658a9d" . + "8eff7f228d5c4e4b09cc9b3e11d27ae24a1181368fdca57cb91c9f7e2b605cbf" . + "4a0a8fda66c9f071d8d691bdc693ef6c4bd936099e15568312e675daef9495bf" . + "13179b5b715e66bc3a97e2d6415c91bfee0644b7f6f4d25d2b304dfa5890dfa2" . + . + "58bf2ce12e2b1a64a0e9893ee71a0b16f01b405dd3752317e46b13f6445fad82" . + "128ba02766099117e1ce033ec36b5c773410d2e95b3156455c07cdc2b683ca4d" . + "035d0ded71780cbed8ae6c5785268321c97f717b536dd7b351894e6efac8f34d" . + "c2a846f62140421923e35f449666b365aa0bdc68031dfa861bc3f9ecf2f9dec0" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "55658704611e5eab80e6540d64dc336c1873ea8192e5e5a7e491a567b99485c4" . + "730cb0b0954ac8858a54345bc02efedb2302153e85feb572f1ace34f0bf62876" . + "376cb330e167a66c803b03739d00c8586fef3edab1284ff28d18ab2c4b845068" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e72c683f8f2f4b098668d4c0e3102fe7d3b1afb4b4db140f43b9b9515d8ac121" . + "0ae0eee4fdb65276fc7aba42e0b588cca84d8a85819c004520da9be199382b97" . + "0c6486798b303a99de584fdfaf56f5ea858eba286c0cf4dd27f6f9adb0da603a" . + "798276df582653765d23275b30d931f7c0a42fe26d1087f9fbe251a4f8982aeb" . + . + "2f65b8daceaad1124b3c5612dd5efac9cace62ce4424786422353b562f5bbbf7" . + "791ec73e27087d4386e1747f18f95b2874084116797f9020c13174c49712ead7" . + "c527ad9b39a02e64b5644f67032d18c54bb06d6456909433bcf13db2c5bc561b" . + "daf057c8edb0cfe1caeb373197009a50aafb49c9922ca61de1b4f0348c337494" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "be851719d03d51fa49b2b5747847a5541328fad198e1301d193d825517bf8f39" . + "737fd8e8626b437791590abc8900716ee410dc2337173c211686083dea5576bc" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad374dfa479680b64dd92079b15c65a3d97dd92f25588fc26b7925e4063b1003" . + "d03c2f6b51843511c3804f60a7bfd39bb5db2f8ddaab2a7529b5c441f46e8b9b" . + "49120ab9b6d8c06c3af7b4095c9c13997bd28b4dad9d5bf760d83e3878030515" . + "ed7fbf081a4915edea3b86712f83e3bcd24e758affc260346888323cf90e5c22" . + . + "82837a0a01de55149bf8e552307a69396f8dccb54b2e40bced98439341f5ed3b" . + "36d1375a44b0122ee70f91844060c37d2c8be844c73d1a1881dcd01923681273" . + "6b4187af37a75425fed1f5bc3c7a875fc3d4a8d1ded8687917c6feb90fca3d27" . + "e9daa000b01f3526411cb83949e4892b040681ee095e83c995c7d890972642ef" . + "f8ac7f5635af874c510712678a87aba4ec64de33d42d6060e6ba49235b1902e9" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "36d1375a44b0122ee70f91844060c37d2c8be844c73d1a1881dcd01923681273" . + "a8f3f53f61973d1a2135475ef552b74bdcfb6c64f6ff61e18b3924f55405d143" . + "660a4cb6055f53e803faf47a0acfdd3f40cf8ad402be4c6857f02f1883f221ee" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1ed8814d45be025e5f081e56e421dcd5b71d4b346af6fc92262e6cd344edc24f" . + "8f336e6f0a392807a778db03887da67b0d967d148aa2232391c0f9635cb23dfb" . + "065cc350db20679fdffcebc88519208425a70899665359d540b260a3935f2801" . + "de9ff1cba4299257df1e70dc7c75c21c19456a6ff15a64f4c9d3df9803831660" . + . + "1681af9404422a4797f85a263cb8fc01021d5ee7e0ca3252c82df753eb1a6985" . + "0b89f00adc76e11d93ae5faf532fb248cea31b50d749d7e8de8a382a3901fba5" . + "258d83872eabe446eeb4e26bfe8df18e0fe76114354f65bfbd3880431d7cf732" . + "e0921e1910dbfe7c3c7bfa1ed4df3fc217a678177154bf2ba423c04f85dbedc3" . + "35eb8177a0b03b547f135fc0cb0d4690014c7787bfdea03a28661055f5d1fedc" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "80b1cc30b4e3d4cc95fcaa77b0f8b6b5a94cad6b7f89da9d1c7a079d67c0348a" . + "e8c1e752dce088188cca620bf5d347f27132880c3b16fc9d1d25205e2c7860d4" . + "f24dffa63d305479c3812eb60abaf9e5579d2322d712c013e26eaaaeb3cf911b" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "527dc999eb344f3355d345c30b6dcea818dac5e8d8c85918b931d45681091add" . + "a60be5d0ec629f2a85f9b61b0a6851f07258b6f742c878f7ab7efcb2350dd12a" . + "94c11d776366aea77c6a6854574e4b94834d6613d8074fefe7cf66946ad0b5f2" . + "6d630691c8e8064ed64ba3211aa1c981eb519fdd9dc04a8b5200c0e4b722a710" . + . + "23ed61c019233693ef9c53ae656ac11873319f6d21f9137da3e91c96265e2e7c" . + "33f65859e1e05df6613af3779e68592ef8bea061c2317f35065b2a01d6cf5d36" . + "77cc9f769f46b23660d4f689bf900726bf27ba491582fc03b66fa19f222515ab" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "7c1719b4ac20b6f3e01736f606e080b997ce38ed93ef38aae7d5da82fe3e5b7d" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c2ebe215fb43742b3ed1649775a2b7eacef4027e11fb2f8a91f79ed1d70bffec" . + "e7019a92516da12c62e1536c1329bdfd075a7cd467224169e057b11898da0d0b" . + "89e21f4e07793c735de0bd9f37a4d031dd1d75632201c083ef47b33aef1ac38b" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da8f6a30f36faae87a01e4cb733515fd08364a04470794c87b0c4548122796ed" . + "58e6a1abc06f48070f4001f2eb267dc56d706b672802c57d73ea634f9cdd9c8d" . + "535c265ced445d9da19c7dd3c1effc002575a6d04698e17058f3d06fbb937c1e" . + "fdc3bb63d8ce77d6890971a5a3a1f5cc826f86bb9e62b4df816765c47c9986dd" . + "c06bebe1eb919da7d2b9c06bc4226cbe6767c2f17c2201dc8bf06b87b9492021" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "e6ec92cace61dda9ea80d24b81f6b62a31885ce2596697a227e6772fb6b415f5" . + "576b81ec2a86156106b8c8dd3b7250e84874c4eba13dc0099b80bc315094dc0b" . + "8ccf1e0009d9fc53fdd43dde48a40e1f51b2d738034a2edfb1d8580757021cb5" . + "c84f22e9222680d4ecac3e029ad0ffc5dfc9f1c5b4392f610a7d52684cb6fc7e" . + "acfc7c9a2350e691c432e5cfe74159f79e460da19a23113b887c7d2896d3b1aa" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "fc46e12526503ba27407e70e4e496d88e437f0e61a1231ff93b11916f990d650" . + "c2d7efae8c5b375641e6c965175a5ef906f52977c2387df8804ec35713ea812d" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a763bc2f71f257a4b56b7ec980639ef3d6d75b0206855f445345c46ac312538f" . + "a6f9c429c13d1ed2fd6d70029be6c5377c7ff426e118e331dbbee87079e5644a" . + "5fc9400b977674521bee916e6215ff741461b8cb2efd502b69b8b09fd7522ab5" . + "2d0e26274cdd5074e71d9fdfe578e51df7af2afecba41e8a72d2f6d37190e9ce" . + . + "f3c0926e9feb875ee0a081ec6d1c37c6c409ac89f2a84ad67d575e3002097b98" . + "7689589111f0bd4f5743feb00d57ecfd640d2056914b042856894dd751b9d7f7" . + "5ad7181e314928f65eee913f3bc5058731252f3ecd244cef6f063b8316818e3f" . + "75df9d638e8ff8ad98fb229d041fab5a161f4bf5e2dd5dddc5620540017924c3" . + "106602aa2144f66d0d71f5af40dd87a7605d499351c09454eb8dfefa2e02c093" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "0525a51abef4a9f9efe8ffaaa242f8e9ede77ef8a921513367528fba0e33c57c" . + "54f46e72cfc30738d13d59f0200c3bd2f921a60f400eb9224001002d9951fd48" . + "51648db51d77b8c0c379b77dee2d7108da4baadf89ae31f2bd158e4f4ba99658" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7ade7cbee49b5af9b55a65b9576ddaf8b80e033f44049827c4a7904a9478411" . + "1bd6042e9bc3296f4a513f189f4881e18bb30c807cead7b8ef17ffdc92410ec1" . + "c6f34e6138da789cfdf7cd890efc5df1a078625a89ca5f8c28fe1db15ec2346c" . + "1ad5b8583f769efb77c5d98fceaf1dc0e16d349f47823dc67abae2936afb502c" . + . + "e1c80b154b21d2ff93bb9ce83a4e5c3950eb4c9e013964cf0fdfa60a1be9c6de" . + "e2a4f4b9a11d6ff7174e80cb2577a8b39a2ffae79ad7a4143573307ef37b91ac" . + "207a686cc5cbe6dc081cc115dd94ea70021166130257e6bf3cf1c07e6bc63de8" . + "9a4177cbb00fc4828d83313de2f1f41fb4a164984ca6a4593605022eb9313dae" . + "bb34a56210dab7a76bcea707d9e0898d2aa9e818dbe9e0a4ce7f764c2f0944e4" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "8c498a622ac4da2f2a9a559e29b1d59fb6985afa299d8ce50086a1408512a089" . + "4096143273a2b85cdec4c8b5b1e31326511e5ac82991e409a13e5fd7e6fadb4f" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "973e2f9a52d60e43130bbdf41f5d6651cd7ea09eb0cc6d118d525c0429ee158a" . + "d222b5e3c100802bb23fba40af2c8caa6ab7fb856bb0c2edc3d63e705d1e441c" . + "be5ddf65883716202347b1aa1d73dc1badf7408acb2f82ccac1bc34947d833a9" . + "a46a02ca0d541c173451558ffabcc811dfa9013f236cb2f3df91c5f08035e1c2" . + "ec1ccc14b531572a02323c31b7b136e2b35eb255c199f31c79abcfc842e60607" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "afee71e59752c5739a47157c64aab85b0aa63b2423bd16fb810e82caf64c53ef" . + "49f12fe4dda3ae5f547acde6fa529513605006899f6fa70dd497bf13a443fe07" . + "94ec90f201529de21ef181e189ca7f46b17cb2f8114b3f1f6c133f7a02d55381" . + "0b2d104f967258a041bb02ea358b79d8165856219cab2dca9827f6221278f558" . + "da553ad444c24d893523e4bb69fd416656bfaf33d844a427cdfde3bc3233fe79" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f1c461009ff1af73a0429eeab51a98b9f6ed475942dbbbdd8e874ec1929b3b22" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "408b0c2faa165354ccfa68b6cfa0c3053ec8e61906c11503b2597e4fb72c8f9a" . + "1db3a28a433590059bd6e95fdf9b8acd48257c67d795a00bf050330206c917d9" . + "d1fbe5099d0a05600f4e653ac452301669278592ebc8e87b32e64f895d796e83" . + "757c0cc95a3e77c79f79f5de49483c9c85f9b51dc94190a9b92ae2919533cdd5" . + . + "a138ac2f58fd2e149a38e5d23a678be3ff56ea4735ffe987d51407b09e8adf1a" . + "f4adc65c08218939f8978dcf5a9d17f787a0596293197774493497184faa62cc" . + "3bf1ab000cb089690fc351839de72d287bdbbfe61813d977d8892a7ebd6e1d0a" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "3a565c521d6c49d194f2cd8e015e1c5eb50d8e7f0e32709f62e5968f830cdaf5" . + "2f871d9860fdfd93689607ea25e7e5ad52d647de2ae3e4474cf034c8c595e730" . + "80a8aaa9308052e3beb0473becc1603b9aa7afb7871a6785480cb9d5951344d0" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c27312342f51c404e6d92bb61435c43e38789012797b7105175bf66753b24734" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "2302e9cc283b91b903cb17ad7a0f1e8c2c01ac39a3f1c3ba4a2379a0ae4b1c02" . + "62ce4146289976ad12a6cb1dfe09a49f15fcca4e7c8b95eb20b7057fcb1113d8" . + . + "7d7cbf70faca7a64f7a32d0ba32f114b6a20df38b9a6b4bac094731ccf0f9717" . + "03f8b3f1c2a7de0c4110af25325be543bd2ec87a1d76050fb858af00ee71fb5c" . + "7f133d340f5f91e54d2316873f0944c843b2f963412fc41b41ec309899cb560a" . + "5a84ffb5eb39c03d23c435d423d0ff064881807a607ba3fa6cfae06ab419d868" . + "c91bee449065238860869ec12aa5358298caab010385253c97d285468a892db6" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "507a03025552b0601da1654b0b38a9dc87577c48e0d3787b2cdbfb3e4ee1a305" . + "c5c0be9e33a2bea974ea86767391de672d26c864c23265e111358605e64abfa6" . + "bbd2faaa1f7003577516728cbb9b87b106f02d05173d920fb5fdd024ef051689" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ed22f1d53ae82bfbed368aa742bf548a4327e53d385ce8ecd8d04994dd727ea7" . + "dd9c0ee91abe6893e1f890f8c82cf1537a47096d290806504484c072480c891e" . + "03c8f6b375bddebd1862eff47baa7f0165a8d485c42b63af75a55209c8297014" . + "cac8f9e40355fb42db14ff24d2ad1ccad14b4befbf033f8b06756048a8f81285" . + . + "071943fa1136c2a2f330c19bd9817ca2f68bf9d713f66e4c08a02240d36ba6ec" . + "aae952b6475ae273a9ed4acb231703827adf29f011217bdef3b3e5c2418a9770" . + "a1e49cb15dbc7d9edf0073391fba4c851f2b8f53a21246c41ca98870bee0f4c4" . + "bfb809fd15af3fda6428f355c2f2d97f5077e64a46777b9f494e65fbed1ce9a7" . + "fee2ac3e1f8fc1df251dc375510e93ec2552cd1a2d45a9696cbed47a786d826e" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "7402635ec49256936d94e1574ba69b95e561c29d05c131ee5c9b34bb3017eb74" . + "0414a7ab31f410068f331c8de2f9ce1d78198785fbb2d16790c7f442a771546f" . + "dfdb51745c872af24329acabe46aebfb15bebee202323b5fe5bebca4007ca996" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aaa2b9c857ff89bd45714c566b0daeb314a578eb0fedf6bf0f629bfd8179d5f5" . + "e76fd9b3a401036888287c47fa8aae235efc629a717149a4ae652722348879cb" . + "b625dfe9beb904f52477616d205272975fd781c9be4db1aa695286128b43a372" . + "91fd08ba2282200733c42dbfd06c0f1ba075cd0cdbf90823b8e7e66bdd151cad" . + . + "f8f8e2a7e4f2424ef2d5ccad9e1cd66969fd7afffd87cfb4358cb8d326ad8df9" . + "8b4136c36c9cda127e76c267653f99d970e35c9f4a7f539551596da950e2dd34" . + "3a301cbf2c814706489b0e946aea8f6479202df46e4ef02a027ef131ab71095d" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "add64350b837330ee2ab603e036bb3c9b72f83c26e0181d8901421d69998ec16" . + "445067f266e3a464323be3807b5fe77d0e0eb1e63a601ea9434d36d344023c02" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc572ed843b78c42a38b79f285060505561fa254680572894463271826b44868" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "403af423ad2a669a013ce04df867e663ab17e035dec98ae36abdb406f829a229" . + "c689b8d521e9e7b75dfd606f6d6c4f1a85912068439a61e5ddb2c85351ab6f2a" . + . + "7446018083bdbb704937583754457956633e8a4525245766c387b2bb8192b04d" . + "24b3e95152f0522cd7385cd52de5ef6b8a0bea50d44df7e19c9d642fbfc48034" . + "7f5c29070ccaf57b456cbabeb882340d7b3b71f2bc7435bcb76b4f1313a173b9" . + "4f1852774f1625de6eb3360245cf263a66fa34b660e1245d3b4905e22ace1171" . + "051a7a6db85621a1d5011d536595c39b8c9d54ba249b8423fe846020326db11e" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "24b3e95152f0522cd7385cd52de5ef6b8a0bea50d44df7e19c9d642fbfc48034" . + "32189cdbf1fd2e497eff8b55c614e49e4b1e5c17fbfb7e8f3316b1555cbac46a" . + "1c3bf8741f30f68ee16ee38ff86e63916f7087c316c6f4d4a93219ac7b8b4eb3" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3b40bb68bb1ad8ae6617daa7f5c4a81ed749d6ca89cb649a48f3e5ec0109a339" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "eb74d1d7552da2aa785f2d828a9195d40e3010a7c595d5cb30704f38e380d1de" . + "9a9e77e8d383218b07dae2521f315427530b72a2fad3ff4332fbfe7b08ce3dcb" . + . + "203eb645a953c58ae9a54473af4eed42077549c672094dd7aef366adf18abfc9" . + "e12390e96ac04335bf6294a4be345ff40e320aaa15e5bad780f7e569f4c1f925" . + "2ae99eec07e4dc36c98827896cf8392aad98f1dda535ea7ebc54deef306f01ab" . + "0b2d104f967258a041bb02ea358b79d8165856219cab2dca9827f6221278f558" . + "6297397692e3bdf90d61f3086f261a93d1afb1c5d0c116f440e40a6a64c4f533" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "e12390e96ac04335bf6294a4be345ff40e320aaa15e5bad780f7e569f4c1f925" . + "5176bafa6de416aea1fa6717df4ed9c65002715e5a6fb66df9da111f4ad5d1b1" . + "ee4a376eb62831883285594b5f32c9389368aae416af51cf5e90a9448f752709" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "56471cd0b59cb13ac96ed7339a8629743f60523b87034b53a97066c79d929c6e" . + "53f93241a48932ce4ca93d24667fe7531030eb0351d06e433244e49953ba381b" . + "9886a094e6a3bc55cd5e4a0371eacbd780bc7c4389ea2d2533814b519e4568ea" . + "b4294e07889672d300c702a5bd445a5417a37d2d7466919944964d72f5b74fce" . + . + "cdebfcfa4f2173f1fcff4fc21094e037c4990085bc129f9d6b0844c3b2b93853" . + "cfb5ae15f0f22ba291f3b746975852635a51eec526f94463390a1060f73d5424" . + "a6db64ab85615f9cc57d7e4e4273b17efd78bc620b393e1e4c30dc9d801a0926" . + "09594b7255c1c847d61d899da3070455fb484e9ab56693c75dd302a2215e2ca5" . + . + . + "0100de175ab4576bef5588d272214e201c6f3b5146a3a6d9152d57e84aed0220" . + "7ba53e04b4bd9b7d177f2c98b202d6d4e2de4968ae76bcdbdd2fb9aff64ea24e" . + "b19b83fb6bb0db06cd7a524830e1d2dbc0887d6660c0c260e5cdf827331ab175" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f9169be49d5fb73abd354f6bb79cfbd37e1fd303fb09b77bc805e81ed5848ced" . + "453c2c41de691479c46569f3e1fbf4477d8f8ddfcac2da3d465302aff0194ca3" . + "2956f2859bc7c0b461b2dac95e60e8093293fdffe78b328fb9c1b1df34f62785" . + "e233baca4e042d1642b0e948c92f7e66fe31fed2d74fc5fbf0a0c22a1ceaeb99" . + . + "338cf92f52874418a7e880231f56b291e32161b96c83802e6b5b63f31023b8ef" . + "4d891049c491649ab36fa8276507b1881f4ff5eb61c0525aed958f42abce416e" . + "3a24fab4445a6f93b7e79ddf1937914d426ecb0bdb2d72484dc88af3aa917be7" . + "ba51a36932a472c62ae9d3a8ca7172a879b5ccd5c6b7f710b6f17a05eff39bfe" . + "0ae2202993109204123094aa7faa402bc73b72df9fde67faded118c840f5d6de" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "38c00c4794c38b7debd1355d6197bd946dcb457b1c9b91b860247d5599d17121" . + "5d0913caaec4b793106dc15bf3af48a78cd1b47f9a893c625dd25b18b79b1942" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0df954a5428f0e0680c1d2fcc61fa43f9ef71ca25b4afcff009c5a733da51ef1" . + "7fcb06ba62f119186cfe2c543258756aa83881f80a45ecf79364197f265568ea" . + "b0c7b7382519b18bdf502aa95efcde8a4294031ddac4d3f792f5b2ee2e4f5492" . + "cf77836c452ed027f0344f3b2a9546a1e1a728f852a90f51b8d90863becdf6a5" . + . + "14873ff309472538b22c8346c1cd72c59a175466021624f70dceab6c768ff031" . + "9b64e3960d4cc4b23e68e68c30b9a05f87f81e92761bb7af154026432e4f52de" . + "1f5466f8188372c3752d2a8289bedf7b61e81657cccdbf8caeccca2e49b188f1" . + "a3e35cf6411133196712c1b822810ce448e513c488b4fee2da25d67ff15e31b0" . + "d0aa34fb47f58e6d8bc27b18e5e0a0b6e2e8e1f3d38fe88e34551bc15ce3fbb4" . + "47badf7ac6437b46568544f335d311622c494ac436970d1d9ffa88427ca92073" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8d6c1396baf51b77618d60d0c610c0fbb4bbc324dd190a38d86eea93b81923c1" . + "e0611e9a785412e64d72be14d63ae7091845d4f3077cc4a606b111bd49b93151" . + "480d1394dedc7e33b74b8dfea9834a56953db08b460698c412c228b417e072b5" . + "dadab4aee25036dbf7471ec564268d87338ef4f0e33dc97b9eaf1a2659105098" . + . + "789b90921aa5894a6e5fdf3d2d2701f4e3f93c2efe73132b88600d24718d67b5" . + "311283edc18b29e1acf5a9b2daeca3fc4283e09dc5ac9261d8d0a338b8d52d33" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + "c67d1d947d63b8cd98852ecb9a455489916c52290c56e8602aebcaf007ba5503" . + "eff81797e68a96826523ed28920b5f6d918fd61fa9cb1a0a0822ac573309dc14" . + "4fcdd8ab780538ecec2edb636f163467fe6ce09cc9b27bec7057d99a040605c7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9775f956395d5439c4c432ef47c9df555e00cdfdfccea536d58ae7e0525fc28f" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + "676314f75f4519d80462059ff7ca09a0c91586741a5326dfdc1d989cc115cab2" . + "6a1b6fed6d3636c1dbc4f09a17e8e9322543d5f609060b555bd6cd274e9b9cc7" . + . + "f99ddf6ba40a689e2565a963612c9d180761c71f382891e16f1ca7bdbed2833e" . + "4811306552526463bd880d25dc675c31b6dbaf029df9e62f14077fdae513c116" . + "f3ed393b90957f3a99a5adad03e83acfe9d5488fe046c3797517de46c53f3506" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + . + . + . + . + . + . + . + . + "523f8c21e29d2228cf9b68f08c2422b7d5f31aac3c9c671aa320eb428af6ca0e" . + "707cff4ccb4b3e6cdbe19a67c3080d5d150b7d39dedd63117abc42c39af5a209" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a710dd051334f11713b0f53b0ccf2163dee8488e70e565033a5381657031e841" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + "d6044109c18020567eb49dbe68f121d337686f429a765ce0ab0bd594c122c97e" . + "9c241c33357f0a5324b1c0616eb79a601995f2c06d38e9ae343ad6e626b5d6e9" . + . + "9de00e82c7f4f7ffed864addea1b8c800053801db07db042231295498f320af7" . + "5ca1fafd32083d2399698487ae09bb456df095ee4a3fa5eba94e2fe8f09f1b11" . + "7fa2c3ce077335e7131d36d7379751dec5b07c4528e45b93ece62bbced2ab1cb" . + "ab499222d02d9fd3284033a489fe2044090ca1d3edc2ff5afdda22f8fe4be8dc" . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c675e832ca9c6b3a9f9004b8d00df6dd8b9e639a7f3cb6cf8f949d02b0258099" . + "bd1ebd26f1f081e7ef3d68bfa14378790af3f99de57da5b8645ab4696ed7ed26" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd2e0f0e6f8ecb6e4ce9af19a0c5bca61b8ca48ed590f8b27608e8725166efa5" . + "a1007f1387258a2ca4b04c621830e4dae253331865bb92b35c862d7d01180c7a" . + "00e7bca067476c46a4d45f0aad6f5778a30c77284568032edd656ac6e34f9de6" . + "5d8289ee9d9f11081ce79162b681200eb8209c7ce672b0b7b34e66ae9ec18e8b" . + . + "4e6516c2a3e0d6585e5a056652d25cbf2d71add34a311fb0d9335666c5d61e5a" . + "c3c6213b153869e9600cdf008eebb95e60ee51231dd1b786c390f071649e7486" . + "5ce9d32141357a113c154f9092bf134305e9640e824bbc56f8aa0aa67af23e29" . + "4f1852774f1625de6eb3360245cf263a66fa34b660e1245d3b4905e22ace1171" . + . + . + . + . + . + . + . + . + "b143283e6cc9a31272600c87e16dfff3f7ebc2504d78c685d1b6a65400cc511c" . + "85195f681f992dd085b2d098646b05bbdc259658e029b53605fe2b054248def8" . + "b88ebe2087399f871d40338743dd75695375198c00c4131baa155f3131bf9c05" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8c559598f5fd663ac7a8765da142c2642a8cf8ee4c697d5d8667113060c04fd7" . + "114e0757b0ad0d6bc324ba28bf4b55f64cd6f125d957255002c00927c479234d" . + "cd199358d9004b1e20c438389b561ebce3658134d248153595bf1c6b496fef56" . + "4ea709bd5774e3b09332d3dc1f561bd74af1035b571b9128866c4ea7f002d903" . + . + "d19b99d7095deef96619e59fe7c7a7a02ebb562d9e9e86fa74c1e68e98627b13" . + "c14913d8c8ed5e5513e463e7a71b9c1673c6341a70fca8f3ce903f973d1d6a93" . + "9aa746b085295be78c8737f0fbc9be4f9282e7ab6a60d1461a1fc52937bfdda1" . + "c14261f606fc688af7d7eaa3a5839115d4a98487b82f2667bb685e7a5fd62cb4" . + . + "9f6a59dae00610099e570250e8ad4e8c250ed2c82a602dbb2711164db6f1714d" . + "ec30410c680b52958d0852fb23a464a64ece2b1bba2d16acfb602ef7cfbf5ed4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c6231bc0282ddb40a89647c242669c99e35c89343d6837803ac38aceccaf7d02" . + "555d414fba57b827542dc434cb1eadb3a28009ba3de9dd3cc038f1f79442e516" . + "f09afd6e0265c0f6cfc108856f68fa5093dffe5f35ee0a7f9f706d5f7b7b78bc" . + "d1cfac81d35617787389a3ffb13dce1a1298c18a61788ddfea7e1ec636c997e4" . + . + . + . + . + "f799f5239bc36c371c42ca1ebe47e7e56b590a5b1c3b86d988b3e971ac453d48" . + "cf2102f2817f4d85427cbf882de6786802d65d451318f9a1644305cb642041a4" . + "12778af8c8ccddd423e6aedf916b1f79eac87cba3cac76008ccacc38e6a00485" . + "b3f226147c4b9272043a35fc04e84b7bd3cf869815de1ec52041652474531ab9" . + "669cbe81ed356c134ce185e8eb3bd36b0875899f2de8811cb8500377a0e4a011" . + "51870301924dada24012c75d13a31334848c671aefb3fe9e92a9841f9d5f0eb9" . + "5abc7f9d21d96c152d6d4cde2b3113f43191b5b4bb289844321f6d46d6ba34ba" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1ad3a23de7068e10b9a5656a1828074ba2c6616b8fb7ce9f0f213b7aaa8421ba" . + "bc341da4ab91514832f15049e7361c5d545b37e53496804868459f22a22d0e3a" . + "610942aadc7af8960faf5e9ab71cd33b51fe34dd91faf7b6edd7f00cb0ce5f81" . + "57619ea96fcd48126e12c2ab40f77c9d2da815a7385d4cb05b7ab6a9f334e7a5" . + . + "036a9ffe0781495d9912edd1cd2b44a710ec10a43f0d7a1985934870f50390c5" . + "216c23670fc55d9b716baf1e672fe661b753837c4d171cc2593cee5188128cb8" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "33a606a6de394124e24fd1df21b58c90ca84921295edd24895c8520e37537741" . + "376876905504f61b1ec0c18c58eb8a7eb98e0de69e444ddc4b9c8b5c91185bf2" . + "944f7b3ae696c6c7285cf99701ab0ed406e92fb7333e3396159212c250c7cdac" . + "e23d08b8159da97320002e9ea2ceb13769d0a646a249fc2695a45ded8d7c7af9" . + "b7c1ccb5006c7aa09a8be98f15e35cd1039da812b04224194c60899958afc112" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0c8e81979a638b386cfc551f57e3b3a2fd1fb88e115e534d702e636b7401ceb5" . + "7d28bcec63a524022540858bfbeee104787d525dee9bfdd4e86427ae18e220ca" . + "2688edbf3d0e6d50949f244acc736613f7313b76fa0eb9fbea8026f0bfea86d9" . + "e2e985d5acee4db950b295eb5b21d175c479adf848122106a631f0f97dc1033c" . + . + . + . + . + "93197ce89ebcfdd656ec3ed470509bd924929f251ad0f4a0a45270088e88c6b8" . + "cc289fdd2ed9c828c5746fcd2f7529da563a3700b12916882b430c15a7d1eb27" . + "0b215f33a4782e72455c0400543392ebf159a708532ccdd5ee1861a481534eb8" . + "9c798d31d9d1aae5ab6933f3a010aff73ac5458461a09b7d59e46b7a896f19fa" . + "89154ba170779aea2a46fad1c0672b6edb583e84f38e7fb33241524c4afce7e5" . + "ae5b0dec900e1869e8163bf8dacdfa04b92c1583c11228596c4c946b16b9ff60" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0ef480b98ab413ad0d9a948cac69500ebf75fa6a91f6226d849c719fe609e38a" . + "12c0b80d6388aad8b5c24501d10abb4f837a87586fe4d84918630568fab17fbb" . + "b809990b02878e8e063aa701f888d0c8da51ee53736e68dd4e7abeec60a782ee" . + "011a9baf8dc995be97226564d1d69efd8eb547b5ae9f6a51f1591bf101a61c93" . + . + "9f79ff4ff36e75fbf52afa84bad8e52b1f04a5191cbf21d9fdbbb0642d51cd9f" . + "81e6b354599469f5a8f687111693677010cbb356f4b06a9692e8e7a1bb207094" . + "8b0fd381e11a2c33fb7418697f9e00689e4c496ec5acb37222bf2e17219824c8" . + "59b172f7ef3312bbc17c89a19107bd69a7df3df162a605e0d4fdadd99b2cd8b6" . + "aa8becfe58c7aa97a4ef7ba6eb4d88cccd77e06e34aa58d2a797c90669fb505d" . + "648e0e52a23ae02c2b08a10c13e04a68185131f660a3a44df12477ae28729bc1" . + "3ddcef84f7b43b9a62ea33332ddeb87e27153ec267d3f02e328b0f1813e72310" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "e4402cdc8e7417072a8eabe9a3a662fa37814d7f540890ac3a0bba975a233ba7" . + "2906c48d29909b00cc91d5edbd3e0155e5fdae071783e3197f466470bb5c0e07" . + "9ed80e86f23ab364126c2c5046c58305fb01d84477514e9f96693d32717cef31" . + "39dc8a5897f8ae5764b1fa03b747821eadf474a203137a4b94c6d8f13a0090af" . + . + "69bd0135ba751902941107f89fb222c7cfada87bc1712a19ca7958e120d86389" . + "a20d975791a2eb9d588f9eb38bcd78b164fa09d0feda645d7d2006615071ecb8" . + "d3006fcdb4654832d72ae96ba33e61cb97dfca6d7fcfcbb90ab9fec552bb966e" . + "d7dab32bbe2c2e6747f92f4497cd8fe07cb5b435d5cf415ee41ce9e92bb49240" . + "a303a335c1910f109db74a0ef9c0ad24c5839de9a28950d13eb92b6f9905d476" . + "e3dd534b3d0784057576226e0f0bc21c1a7893512f93152b162a607d32a1b408" . + "49d1473128511b295bce6ed2008149660c7d3c9ed43ea31efd3fbe590ab639aa" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "daa0a86a570de88e12142d8d138f2aa71de3d1148fa750cdf2d58ef671122bb0" . + "2727540e83f753ed59b2d0b42280f6f972b8de17ce83fd6cb61e3ac3fc365cb7" . + "e10e24e3b6f239332c1b87ad447fbf1599d69b07d7238cab68102e2b3ba5f2fe" . + "305f4db869c81403232f2324f1ca1cc32555f3480ab43388bf45b2384c24996a" . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c153a6d75cf4c17ddf1b0793d75f9b2cdf7b21b8cec389c4789740d8f5ccb984" . + "8f23d4b20880d891da617faa5df7c7a190568b2bef2b8acac813bbfa3d5f8a94" . + "1d29744562592179db558db58f6261a59e7f4e004100e34d0300ecf188d36017" . + "e2db02bbab2fb07af33462db21b34eeb874ac050287231ce151ef82040154412" . + . + . + . + "229c3d8350fc1ab15b56451903e9f48b9621086785e8bd6ae3736d196d26eec1" . + "57942d23e6ac24d8e6127c0ffd6914186849cb85cac85cd70cbaaa2525803b03" . + "dce331dfc9dd9336cc446858163f67752b68083623ae6ea569d4f59c1f84e539" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "984f38ccf89b77449ff816a4597434aca7d8aed7a108f310ea0747e42e0cb492" . + "d596f93727d6faab5f51a4021764c726bb57ec0b6b9b52508ad3cd056b4d0167" . + "c918d8d503b629f4dbf3a789f6f575a552dec9e8f780971ef63938b0fdb05522" . + "ef005cd184c81a49c0854d721c6e4c67a824dda113ce74c774523831f4c352c6" . + . + . + "7d4323f751b684470055392c524ed684139adc6a314c1c8c3e5aa45d7682b184" . + "80f2d782218b339cfc0763d41f45def3be0bcbbd1f65ebc6372e74eae9a5d498" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + . + "cd35a2a6710445b8ee339f21c3c78f35ece3b4b6298cf496f018e79a80a24653" . + "768c79fb1762bc86ce29e446ef358e78c35cd3d9b96773a92f62e54c289ad505" . + "3b6f6d260da4ad3ebc2f1de7cd2307d614375dae599e754fed26c2b1a5e48fe3" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "a100ebec462afafb47be4078fc8a3009916a6fe2e2e8d760f69e4ce8a7d1e34a" . + "86f304ab84c71f7222dbaa2b079d0092a11ea4632a9577cdfa9d40f971d89e3f" . + "c57df9353ccc173419338e2dc2fb5541b4310b0b55bdea5b824b6b38657fa48f" . + "93cfcc837e4530cf5e11ce2a6ce58c34541e5809f21898623347e58d34d2fa2d" . + . + "22bd5144f088da8991c255674e3ebef0210c3e34d945c34cafa582d418c334a7" . + "680043ed1e1f19b97368277fdaa801bda01ca076ae38546deb25c4b10ee854f7" . + "1e15ea8baa86e85627790a9e0431f3d8b110a7e7415ea30d662bab7283209744" . + "d412d48853acd781a413fcf308f248b4fe3dfcadc11a54e72b9138a67c867c4d" . + "67f5d69a336a577e2425e0a6654fdc82dbd425e7b3c727bf97ef435e589b2856" . + "48e682bc2b4339423c57e6c48f465c586f2c33408a668c56aa3e5ad8704d7095" . + "63446ef864df7e94cd8b04dc8cb8e7d6b84689f6d3c5ab3d5a40cf417295a940" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e6c7fbf2a01efd1ea536f45b590be3a5ac1a4b80c2c6eb147a0d18164537fb51" . + "f9043217dba0bb0dfc2e175df3a091ebdd4143fd22c5ebe9b11af1d687e64d2b" . + "83ceae5bfbfa4cf1be8c8b0ee1ddbf38a4d916f47bee96ed434f4c2b4323c506" . + "ae3313a8d09129863dedd205924d2d8f31a2d1b0b9c42493228742637247fc6d" . + . + "49822b5755689404a91fb4b7b22d18cfa77b5afacccb2ce5c4af57adc54b3ca3" . + "1f3070428100817a640dec63c13d424c78ae31e367a7d6230140e284ce576040" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + . + . + "f02fc0d37969ddb928e06924bd3ce275bebb9a87e03e67180a603008152b0503" . + "12c28c4aa28b4e1d0544402a8f52e61fbaa54129cd32a9a14cb8fdccc9f065bf" . + "0907e66e31d5b1daa1274a0f8c77c956af19d948796d321708f85a50e4ff406b" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "6a96b3f957974e5aeba09022d62aa62f86ff8be2ec6919a2c148ecf049bc0822" . + "78086e86ee14abb36d43f0e5a5eb00babdefdba1ba624bca97e776e4f23dcc84" . + "bd997daa13c2034e17d75231115b252d0224d91d97b3286610c1cecf9f00af5a" . + "2040c7509d4000f8df31e35e7faffd3f7e858c490b1b8d076dadd9d29dd04c11" . + . + "7d571b282931b0dc9199818aa4a9e83bcc6f2df722440d398a12664ea74684f7" . + "3e8f7438f252665133005ec629d9b2602decc2fe5750ccd669dd058ff49fe0f4" . + "c27916a4480790a0de7c09b4eb0623d67c82538118c4af2e2db004cfae2b4dc7" . + "35aaaaa61250fd310204b27a0d526073cc80260f7c2a58293aa24757188a7b56" . + . + "7d571b282931b0dc9199818aa4a9e83bcc6f2df722440d398a12664ea74684f7" . + "3b1990670b6ea15b47de6614c145d66873e4b03648c31e6b076e8954512c03f1" . + "d323fc1f4eae7e384f1b45ce3061970e7a4e5a6900570428d632a0f17a984223" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a7f721bad02d13a961b77c6b088490278bcaad8d31e0c723f910832b7d93885" . + "911868bc31ac937d22b5662f58421fba885af301c75e79b98745f576c6b38784" . + "200a1c4b232c5fe45939c5cd2e3c7043e6b5d1897e37993f27737a6aedde65b1" . + "2d557ecba90a7a8f3ab61d15a03632abb82d186de55cb187f08c31b70c6633c8" . + . + "936eb2fee865e1d72f327216e2682d3a3b245178de7cebc98b0f543b6c3a4b60" . + "c66f03d9ba55251f06f9db9db3929f052f4fdafb107fbd3dfd95fcc42b123dad" . + "f8eb9fcfd8b9b0e62026120c375171c5d6097d0a138e516b82f171d161c02899" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + . + "7a695c6dd0b968b0e79873e30a1da06a01e1d9cd10760b138e4a3fef459b1d76" . + "e21937ae53c16c631480a41ece34ab3e68f2b6ab6852eb9770206a2ed41ef81b" . + "3202407b3cb7b8a67ecb79a891f47fa6940588c7fa7475ff15c3e2387d760f12" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bf5abac24a9810c9eb0f7e40d29ac958a3f39689fbf593405df974cb8b61c2e7" . + "add95ef8acf05c64239b997ced90d53680e9e4b3d07875178da2378c0b170675" . + . + "f6d13399aa7afc66e6659b213f0d00d79b412042601b89368f01d753364bc6a3" . + "54d051f9135f446efa2602167cf78f1438e0a94a94d1283be6f460001e04d1e2" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "f7e50435eb24a81089a895b86f252d306ba94338d42b8f88369d3bc04a92f879" . + "f0d447bcf59d6836cc7b010b058ae78d9809afdf296d7c7ecb7ab310d907eaff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cf70ba30a85b0109f9f149ef88e1a19bf0bdb6852ad2bbc8ee5f3cc81026fa00" . + "a9630fb437046faf1d2c807693fc8cedf68dc65f8bf14936451b4e6007df7c9c" . + "2914f01481bcf445c7f19021a0c214b52022bc5684bee8f5755543e26e1753fa" . + "9e8146e66fc205dce4ee5def4177a6708f85999ee59d0bcb13f2f4be5a1406ac" . + . + "871baf37888e2af5f041b5b671ca3ef31221a19d99d4e30b09f6062847a475f8" . + "5dc6f377b64eac2626b742ee1cd83978e0925147281dc92b9db1998a3be352a8" . + "45f84e810335b4d369e564d10738eeebf8fa66618dd273a27b79120ed855d566" . + "de393b3f21f4713df683dbf9fff738d1f841409a033811253d93f310f227718a" . + "7255dd0bc107e1c682c620b6e7b87db0cbda79060136c28907853ab12a2f7e0a" . + "52d0ada5c75d3a6c9ceb81a26efab7c0179d147643a7b5bd5b14664cae44bb38" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "86efbe30570c079555a97e6f15d844a68d1af8cbb48eab756beeb2f79f372321" . + "a1367698e0bbebd4da55c5ebc65421ff183b41d7d667c5976dc27093eadc5c60" . + "ed49cfa002412f1d69fc70f0910eee81fc821e1a8647e9a72e4591a7bb8dc9dd" . + "96de73a3ae9b05a73493fe79323747989121f90e94411222c8bac9f9c331777f" . + . + "edd63bce528210f3afdbb9594d7f26b9e57e372d30277c6c2f279409c75cd60b" . + "0bc24ecf32007e6df69135d5aafdb8cd3c4398c51f01cae29395fd8d139601d0" . + "9ea03b14983f054a1033742415b25dbc69d7ae889ac55a5e7007775373432303" . + "9225a23aa6be80c622adec59849614f2a13ae85327d3b17a260e52a14b012e0e" . + "5674b248c961157a9d81697f3f0b0f1033c3058498bec748fad15392c7ee9b41" . + "b835dfa8ee967bf93b76fcd33e1466418b3e6554b7ed0308e3e952fac3e923c7" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4bc2e88736cd293dc1f1c44feff9c783e8d58a7c301c4d97fb02451ac4caafcd" . + "a276799340a668192042c718f6cd3cb0169b5026da188d77f417eed00c442368" . + "ceaacf951f0727785b6a963677589fecdc92e4234613b27fbc6d3b287e00bbbe" . + "d20dd1eb71a6b06a829c04f1859e3ee13f44e04502903e789a4c94cb60d41410" . + . + "bd54a32962a796f622c9f35c7635f78b72930190f8728a0569cae851ba3988fc" . + "b12576f3c6966cd21fb6da2b43d992c6c1cfbba4eaca1f86a6e857081a65800f" . + "d8ff900de629f800e9a69e4e25612449c8bc93edcaee5847ad97fd539a90c083" . + "5ef52b542c45fc42def656e7b8f24a702b7f5e849655d766bda26a95fc39eefd" . + "5888396fb6bfcaa39a22ef7791d5ac79806a792ac42447cc3e5034f817241d87" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "b66063e61c82311a70c5c4969651714156cbd3b8eec657b96787a9b0152e476c" . + "9cf0732ab8990ccbc27e9cef1c64ef24d211e3f915a213bbf743beca3947669f" . + "414541643f34b23497bcb6620f5412bfc2d21473b95e74c1d17cb5d6793da9ce" . + "8e9afd87bc70136ddb463ffea46d3ddf2c1eee8188447a0fcd582d66d70070f6" . + . + "48ef2cec7f38ac952481f72fd7949cb16b4ce43a3cb9f77af8be829705043548" . + "4ff14d319414309107aeb362d7c8a846f016eb60660c86eef1407748c4de9f16" . + "1ddeee3902f210cc2a2aafa798e473df3134799e3e7486247f0a271fc8677c51" . + "6a0db4931c34a3c0b8c6c33c29c10c1c312da7e62041d974442ab851f372bd21" . + "870f6200167b6e0fe077ccde04e26b2b0501bff6155b4b04fe4c9d794cbd4264" . + "57e32cf4bc00e670d6787ac23a90d326b45354de5856679133e8c3773d5ae636" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "93b4f971604ca682915940cfa351b8a425dc20b23147f500d1a2bbd9ca19be02" . + "ab56be07fd69a9c0399370eabdf8f01a7b361b7d6194c9b51b3f70ac7f649245" . + "684ed78289c2f2bae00ee28014fa91184365bca2a5d19725a64939dceba9dd15" . + "8802e8d2eef7116399792b48dbf1ddf1211f1d4ff77183c12a25a1b47bc03198" . + . + "e71bc845abb704a7173e34fb0dc98b8fe214985fb2c323e65814636c567585f0" . + "b96d127fb17c5a5bdfee7129de170ab0ae80ac7f877e05870558b0332bbba3f7" . + "5cf40774b4dd5aa34c8e1f8e908e53a9d279dbf7c1ea28367604393788aaa061" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "193072aea64723384115d309bf65c9130ca9141981bbbe7bf820f68a23a13939" . + "d2cf789697fc3c3ad75e4b64a7ec0040ad5d1bfed482b224d5d7892231978ea3" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "faa30e598bc7e55436f12af9f4f6643a5507b6ab59a3b94bbc75784c63ef103f" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "6101d7ba11819e12e16fd0d15886660ff4a89f495529a0a59e444b22c09894bf" . + "fb4d0e681be09da52255fc66b46560ff87bbe74bb185e6b4835407d4c5ec888e" . + . + "17ce58faeaa0a912a62f0896be02a2e73c0c0f17b1afcae062a2c287d9cf40d1" . + "c3c0e7c7b76eabcbaacb1e80547da546b7800c3c8bf97327a0372dc3569c94e5" . + "f10f7d1aa7a2dda172df3d36dea925016db9e6edfb3b7d85507a87ae52d57603" . + "941137395400c03450cf0681d431b1e644947fbfc672b95051d44772ab3ff546" . + "17ce58faeaa0a912a62f0896be02a2e73c0c0f17b1afcae062a2c287d9cf40d1" . + "19dc02d1a2cc1704ad61b49980ed502b00b58cde405b671c398f4bd5cada2fae" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a1d9f139b0c057b4019360f31816d989caac06428722ce028ea386972e6c84f7" . + "f59c1c4dd7861c0597dc966f21f3307d5e443700fef780b735c2acaf766b6bdf" . + "1bdac0ab674ece2eab76fd859d9204d648d5941035be7e9c4bb831a41aee0aed" . + "f50626d31b187569178ee45c2c6a197373d41c948330865cb63e836c08c5e37b" . + . + "476ffbc6483093fe20cfc603709cfa2ba90367ee73f7035932b21a464c84dc7e" . + "6d5065598c5389e27d0bcf61e77ef9e0fb78c4dbf0fbeae95c5dd76f7bd4b812" . + "e899aefa2530ea16ad7fa755e0d7a2cab56b188e1ed54aed9b5ccc9788e5a8df" . + "9dea4ced73fb4ab115f651ec019874204876c45c5934a34447c6d60f96da668e" . + "6ae68936f5f9b8690d8eec8e297696b7a8b51c745124aad2d4901b8df0d23514" . + "bbfd917283ea2d2f7036c49264e506b2a4cc9fb91a7e732a468f86d7e2de461a" . + "03d991442d36c8970dd4fc3e26a9eb8fa07ebcaa8909be7944c61e53694a6235" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cf73ea4095067d573a726d37272b1fcd8a52c258babca2fc38e31d234cb34b4b" . + "400defb65edf7f5b569f8e54081b624e227401a15740def16c8ec43225b221ae" . + "d840cac2766786e1c1c7c68b7ef77cead1e8be80a58b14ad64134ba6e7c49f4d" . + "482075b38fee03da1d6b14d9d8f6709e8392c8b39213335f0d8092edfa896f13" . + . + "162979e0730bfb1bd9a67b0c88719db59bb566dd77734c6150bc8d89af3e3dfd" . + "321f13c610532afd2d9555b3a05deca9e7204803ca3c059bbb3dc9c531fa6c5e" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "7a4161493cbe1f9f9c7fab1c8a21efc0f1a6f6730382c0a253019e4b7b03a8dd" . + "4d9cb668bbffbf103ebe127265d54612e76e5d6faf20a6fcd3301563946725c7" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fd2fcd9d5b062ecc1156a0b4dc1de32a8a018f84ccc5c0cbab8a6eb5c978abeb" . + "c1122f24eaf74ddfbdc24eedc472598136629882d1bb5a211d702b67fea15e72" . + "bd8681404bfbde98d16b3605e11097738a36296539c9450449eb98704b53e698" . + "0b151ecc0dc9534895aff22ccf3c7b319f8c7eb219016c705906044e878547fe" . + . + "b9a7781849f42f3b32ff6fafc936bb5dc277b8504bce040081ad2a5429369177" . + "95ade005147a533d72024a43b2e493cc6a7d7b7f7744144f7bb1848f562ff825" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "9cf2aa62235885c1016aa11d160267ce812a1579a973d10f793141db0dc180fb" . + "076ae414961c48c434874e58d234a0e88393f725117aab84d4309a243eb732fa" . + "962280e0993f8c047b523546a19d36223954fb94b1f4281cab3d538ad792607e" . + "00ced3653912436ccd56f65e76b1a49d9a6b7668af8b98fcead8745491194aa4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e5704d31a2ae1771696b93156a829b0b6cd09c59cce451aedb276e912ab77f4a" . + "5013e0453185a74d4246fcbe366b5535b190da2f9cbe5dae51e54a5bf0955f30" . + "cd1510720ae0a1bbddafbe2160ac3e9d49be88610bdb553295ed656635eba4b7" . + "42e53a9e5e4f3a6e5d09037d44c76c6af5cab078f82ee66b4c6b5dcbfa6c3d22" . + . + "da886f774ab221d123c931692ead5332e13f80e15197a122def0b261d61e49fd" . + "dce18afe92d98d4c4412c345fd37c15690708589ae1da21dba95a954ab6d7251" . + "3a939550f45494d0cdf88dcd8618787dd67b523bb0eb705ca6b52a3a8b6aa2f4" . + "d6b2a262748cb4bc88707ec78e94e853fc85b341af781b9636edb5c85bf41cc6" . + "81abadaaa2ba9570b8b114f53a14fb72fcc2eb6d78a4d2643c57a4adab896e1a" . + "fb232fa581fb011940110ddd2bd60273fd8f6b443237f3ead9b48979cf4cbea1" . + "d6a07f2240b9d4f42560cea6ad2960bd8bb613cd6a59d7fd4f3bc22a3cd79c27" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "28528f845a14012051fb18a0d93c9caebbb160d16f2414047e3d349adeb20302" . + "e59c841c57bfe863aa8e258f54c3741596a944b0b8fd79f42ff344c41cac68ef" . + "f5573aa2221f06bd107fff9a51ddc5a4d49e67b0cde1949ee55c9ca57dceb022" . + "17620322d00dc24ed5ed53633ee60417cc5af7e3a20e294e1269d749e69e50bf" . + . + "13e88a0e633bde07ecb4bc02e628e2588173506a1f0ef69ce2a8a97490cc2fe7" . + "407f0b012d9937fdf71b6d971698a6d4005d36d1124138617b95e834a0e72894" . + "f3ed393b90957f3a99a5adad03e83acfe9d5488fe046c3797517de46c53f3506" . + "87802c00d609da89baef2ed2eb7e674096940aa32d04114839a2f95dc9b2d134" . + "3bd0bed63f6b171d15ba3cfdc537aff4e4b9e691ff675e28df28ee6f17dc7648" . + "f0ebe958fbf355345228720030d8075dbca0c274892aca99b4502587771048d3" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "981f40feea032a411c1097bc662d1fc638a78e067afbb0f3d276f1b7ff6e3df2" . + "14bc50d1e7a421ee875e8ef5d0ed2b05ef5bd082674c29425dcdca05af510a29" . + "5b834c41decf1da5ef94c4959eeb48244dd0e240d4d48615541e6d6f21a1d11f" . + "c01f6d4da074881200e762e66777aca3606ce47b284f45e830a61280a7388d34" . + . + "1d269eda6e3b745836f330c3c894b9645348367075635d7b0f275d0d9b9a91f1" . + "76158647d788743a06486883393626bede9f0ea333053d894733de2afc502ebc" . + "fbf019a58589ed0642c314291bbbf4555274cbe810d80f1665c3b4b6d7a6b9c3" . + "214965bca2c51dbe2ac9dd53f90e6dff816bd9db379795cd37e2f63a69965b11" . + . + "81f1d1e66d9e6f50232d2d2c8890fbe500c6defadf17a449fa4d0609b22f3a39" . + "a48e0c6f648b6aee6490290c397cd0839f8a4308a436e2b3a1457c9fb9ab19f3" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c18566a49f7b352571f9d431de79e79e094f3da1f288b52544487496aed1e268" . + "58803709bd4287711223e4a3e432f9f897abc0d7c4546ba78dec8d7131b58ed1" . + "b7a14e3a116336f9f6d7793f28f43895ba9232617a475a36060ef3055c1f762e" . + "71b48bbe780c6dbcb20ffe9660704952cc7bd5c31b858ffc9eac1d5b97b84acb" . + . + "622f83c9dd3194f43af2d3f90bacfa7730329f83592d0f0a370ebdf1d685e85f" . + "87841e54977b317dc6dfa675b2ed3cc02705f56b31699a95923a1e7c508299d2" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "19f6be1b8c687319ae49c326bffa1d2dfa866fe3092a84674cb5847f34f72b7e" . + "f9e96f9a84c9a30dd0ba90a6307bc46d6ace69ba3193f05ee26c91c894708bf8" . + "52008747429936dad05f12a4dd422d1a7c3e5aa3e2b780d3abc8028f29c942cf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e8306f55561ca38930394b106392a30aeb7a140a8664a8658e4723e18963421c" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "f8478c29af3f146144d0c5ef4a205d16072b06adb668a9fbf9ff178949eea0a8" . + "12d585110bc0eb6fec5a3e4cb5d703df19c55b50845f7a51dc7df069af3a4937" . + . + "25d5e0cd9e26f47edeb80268cc4c7ad222ed5752e7ce9e7f924820675ece393b" . + "910bb4c828514cf7f3f5b86f3168d5319d54e978b89a033fa1871ad6cf2d3b4d" . + "106274d5389310b9a7b0476fa586b59ee509f722bcd62147dc182bb528f1c0fd" . + "3293d3efbc5496c50f6c409d988b05e371c99166fe64d7531f414225e4d501fe" . + "2558534ab95be1241310ae37b1da4963820f9edd8b96d91ed864b9eca8ef4950" . + "103b3290872b59bffc59a1422c4e9d45b25f1c418161ee3bfd18d2d631f07160" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95605c5e1baf97ffd2bc096a6583055d39ecacc5abe3e7e794b8bf8d092f9a54" . + "7128e5210743b092cb7c0446bfd8f7ceea9b1859f5698437a8ef7bee5595d473" . + "d85c75c564768fb6ca97abb72b9436ca8a9d04123bbcbab3f4ccd5fafbe160e1" . + "339525b55d4c4bd2306360ae83e143da738660b97c7cd4ce3c6b117df129488a" . + . + "f5f44f167ffd85569547288b95f34341b326d96e7a3e5d80ae91700bcc8dd09c" . + "37447415c1a770c6984e04ea4c47c4effebba03e786c558dd657e5f58240125a" . + "73db25f8182b6928d00f0b1fac882c8d4bb3c81e35afb4c751bdd10d264e3043" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "6e290a8c689267a1721665722943a51ce791f04a4f37fc58ddc0b6080ad7d1ef" . + "0724423fe626b43972a305549e6744d13f1937f9a1e2ea0e2b915a38a0e39b6e" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0ffb4239059ce79e2dc25e58d0de3069e373f72928a7e02284ee716fb1850dc" . + "6c03987a8b35e51edcf449b7d1b7408e998f7acd9041298192850b0865090c38" . + "7b24ccc3141b0aa794969040a2c9418d0e938c289eeb015735f171f712dd4713" . + "05a8359a76b7b2b2b1e8c8085b22ae44ac1405952d73ae82615e46da632a4b32" . + . + "db9a8b32235777516f52a5fa6e3dad24dd07434da4f551365bd05ed4cf764692" . + "bc270c52660932a364befa4d74940b2b833a066cdd0970bcd8946181a02c8c4c" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "0b57cd77279c5da2078eaee7f576bbb8a64c69811b6fdf8e92ac99b84837f5cc" . + "1e5662393bb89d72d436a3f84e37192964c1aa353544a5554b694bc782e4464f" . + "af76f797d68c12c50bd5bc32e3ed486f638808e09a30d2a1cb74388f3052e60c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4744e727be4aa9257b019c44e034b208cc74e4bea57727ab03b2df43cbc4dcb3" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "848e3498d07db569617eae75ee574a7c325a1cfa6c6bce31e6e6c1293d75fa15" . + "15665cfd36da0c4c8cb140b068836885a01a27e7cdaa40265e11fd9986e212af" . + . + "d25711ca6480868f611fb0de44ca388e043986b10848fccb235a3b60557ea9a8" . + "426c9c564ad07edc6e71042fe825f34fd6f1979a34d5d5e06bdb89eedaf46df9" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "d895bebb04cd012d596c7f3571078a6369833d4624c048c61f30a7967033f730" . + . + "b19ad13a1996dc71420eb140e363f43e7c58773346e174473b24fe887be737d7" . + "ce0187d072283db5839bdbc4686eccedd8c7db20be2fd06d6b35bcde7872d2b8" . + "bc94fde1aab26dad9a0b73199800095bbcd43741dd354be171fad5df9510a466" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "90ea7304c39b75b6c15184a987bf211eb4b80f7b2d3615a2fdeeca0f938af885" . + "bd38c95324568abbcfbb7b82e20b704f4aff967fc3f7501099e2d39dc32ee607" . + "ff33f3f91b208ab803c315650323f536ad4a56e0a3bdd6d98dfb6d87e74f34ea" . + "de12eb9b06393b56fa1c6dd428dd9d02de2fa700384aff3b0ca58523eb09a57e" . + . + "792c4fe419817ebd107511ab7e41b4473131bce7c4344c7ac9ef5366f4b64720" . + "9b05af8586c65e446ac7adb5692aa64900dd3c7079aec4bf0afcc54966a90e9b" . + "72c462c4a8d6f2f331d6f10ecca9b46bf300635fb461521ec33b0c7671d77a1b" . + "3602bbd67c989c61d2be7a7199244ce0c11eeff25eefade0eaa1b630e6f554d8" . + "d51fdc2e7afef0a2d51419b184d92bbe4448b5c689146886a1e84f4dee54a786" . + "9bfe2d82a9b534ad1f8608fafd06288099fc248f4c72276cc82099be1b204857" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c735fd850b5fd9067c5f7dd78f5cce67990e57abcaa4d6f1a3ab836533439da7" . + "07ecbe2be18872599fc6b8ba36648ca8837c011e610fefac91ef6502a4ad4cf4" . + "3b1c713f3ee297187b4c2c0b5695ce68c8c8a9074456b91ab2b23443f9e5f1cb" . + "6bdcd5e8f3409952e919982bf2fd88b75e46b10f32db703fa83552b4d60ebc60" . + . + "f5a3b92a48683436bdc2a738ae472fab92b7eef7b20edbf9918ee4ee04b312d8" . + "4459fb7609c8b016e80d2e852c6bb5b48a8996906a3bd818d5b804c098e854e7" . + "ba8f11118438bcf612af3ad41f925365a633ce1d9713bdf1dbbc760d3e3d2c72" . + "a99fbf614ee9ae3f84814d6255ba4da3c327acee31cdbe64ae3626fe16f1623d" . + "9ba0bad05dcfa9dfb9a7a8b215f455709963b0667f9c2ebaebc295e828561e1a" . + "d44acabf6834c3ace63ac7ec776f17582f77b0ac6e205b7968dacbcd870ee7ce" . + "fabe89210e43b545728f12c38cfc927efe24790fefe1522ccd352a6b16efb4eb" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "46e0738cc5a9a8c0cc49d043ab5a131e7ac4502eeb0cc9df1bf9b9580bf54cbb" . + "85955bb27eb52947d1de5a00d6c7f3a3418cfd646851ea6308a3c86ae4001b54" . + "48e4a01b73befbd53ebff5fcc94e32f0c28e3471c0b2386853df830f16deec88" . + "96c6fe95ddc0015ed6c4036efc1dfde1b9ea507987a43b29fae13a1ffafc5bdb" . + . + "6c1b9dee055555cfb9ba22c5cec1e57a8c6e935c430d0e72d77dd2800a3428dc" . + "d1cec85619fc2965ed087f7a262381d49b372d8a7d20eea2173db53d09c0841a" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "e03fcdbd1bb0d88259693d516389bb24a16d104f654f7cbea22ba997d3d9def8" . + "7c61ffb48310079444f5a3afc7c7614e00968cbb95e5066bf79f9c113af1168d" . + "e242a81171e51bd722e024e52e74a6ba695327064d6531f31d66a3473cd52767" . + "b8c3e5de9ae1f3bb7a8be5ff9e9e4b45c26b68e58fbeffb7d0d2129f0710fa78" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "eb85daa3e856931972d926d3521e421ba3193953b8ac51bdf21b2952b3c32414" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "dc1a3a2293b8067fea8e17d1799d063857f0dfa05be97e60f49634b0cf314190" . + "f0f2f032139bc711c31f9f1adffc703a3e40f40224ec0ff1ff6b5b2b5560c077" . + . + "77e26d7ce8c64b81424f9e96448af6f35cf9f7ff46d3b3cda147aa2d07f0dd4a" . + "fa692f17ef0de1fda572e3c12756e21c5704aeb7080c2281721ca48c68de22b2" . + "ea86f60ef63a3a8a52fa92109bd46e26c3531593f9fc378d389e981cd84b5528" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "e17a0caaf67c8c7318947404fff2ef9edb9e84d29472bdc7b6b18cdda8dc523a" . + "67837f84e8086ff9a72c864f7a6dc9faf5e9f3d070fcbd9ced1cc59c06e0f0a0" . + "0328cdc0ada22e242859eab37b8a0aad0711caeb2180fe0f5a0c21de353b6bd2" . + "a767fe2cb91044c55143d6f1d28e75d14afc94d54f4e3d25badabe4c86e35baf" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "d0a571f11dbadf27aefe66a1742845e7f4fc17bdf37f02b0df21a2bd26c9a99b" . + "8a1d3cf6ac3eb8674d58a2929c16d8d8d9916e4d226774fedc16b4702ac54d71" . + "27fc545f6449666ef3da98815f2a545d4bbe61cfc6072978fcc6f89f6ba71577" . + "b7fedc90d21d3567cbc99f4d0492ec432ececc3d42252433d6715eca7b7bb7c2" . + . + "60c2af7ec0c2ac867784364a2c8e18cf198da7a9f609c8cd6ed27f26412583f8" . + "ed9bebabe1601ce369f0648586af64a6f0160cec410983f4d7dd5556bf6ae382" . + "89b6baf2dddbace10bad2c222322a595d7f3649aee99b526abb50f2a555a46a6" . + "552ad85d960175fff1a1960a4ec8163480c2f5cefd6dc9537cbee277c50a7588" . + "10d500dd453a8d329468a32621c4603e2bba2247c919e3301e66cbf0727f6a86" . + "647d7e9c667a4928bde40035caff5ba14519555a409d1607067e786ca4d9d49c" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "464680c10b19fa4f149f8830727c9c4d32eb76391cb4716890b950650e68c978" . + "8e4db3ef290fedc932257d2acf6c5ae7029ac84bbc743c104758ad9d8eb29571" . + "32ee6db74f18ef59f68a2573a1ad540118ec236407a58b35412dd00126160927" . + "af1d7ad86dd70ec4e636d6d457d5ba24874cfb389b8a8d6e9c7d749a0f0fb861" . + . + "a861d5af4d63159e4ac69492b79e5f2feceb59cf310095ffef21efa9326c1060" . + "d5bad695ff873c400472baf838d6696c4e1235d5cdf45c130e378ab657a4566d" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "c919bb135c64c53d662b92713b7515da3724254bd6e4590efed7120104b8b7dd" . + "52008747429936dad05f12a4dd422d1a7c3e5aa3e2b780d3abc8028f29c942cf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0743a249be7c30d7a8ebec59313c3c940d74b3879c4bbd56c0e0cdfed464f962" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + "bb0b6d1a126140709b276cd1f2a50481c8a08f5a09d03275e3bd5925aa303ee8" . + "e291fa352a9aa5c3ba0ebc8355bde564dbc74dc0a72083e74a81e627e7890843" . + . + "2cf7772c3d81d6aa2c2bf19aa44e8793352703c195eaa99e18570db5c6fdf8d2" . + "3f23afa81131ece3113a28d0eb5299664b91d23f6efe81445546a6d90f359dce" . + "9377b0cd1ccb7f12204ec96970eb88c5b4b212d2e231ae41c556fd591c4cda08" . + "de0c0a9e497d02951ac678edadc9ef38e34bc75527438e19abce3753791b3752" . + "716f560990158dc2773b837f04d1664a39b9251f84b84d865a8207b042923e31" . + "d38e1571c496aa2a31d65cae2a931ead86295d411c494feb953d861dc22bd5e3" . + "1498d0019e02bfa4504119098a71728e8ffaa70241c847deeea6e2697694ebb3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f11d1ed4ee553572d69042bdf92419999b98bf4ff6293b01d6aba440a76fe8a9" . + "0683b207c09963d64875a6a53d9b29651125a9e16d95f1bb8f28cc886e1804ce" . + "c4c7d2e375e42cce06358476e344077e9700a1b5470dd6f99ac757bd75bafe19" . + "9f10c5bf449007920f04dadc38d42dc9cac73efcd40109b5c436fe41ecc91192" . + . + "406551c5e83fe23c26b1c37b1f5d625c64b2175178885fb84592a1183a988693" . + "2f5e23b58f22a8b2d6d8a6599e2594f3f78e86a98efe0d7c95ccabe44f04b64c" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + "d81c2da142bca67a663e81fb6eaa69f6185c8e651728bcb1c04a470baccc7af9" . + "09a22ab15fe091534f8035a93cb284122d3991844c45050528d62eaa7ea5c878" . + "fb05264f753849484b28fcdb5adc121b303f223098be700c6379edfcfd817208" . + "c6b14d1de9b6331c15a8ead755e1b6b4b45ad3003629d9fc3963e982793f6ad4" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "78c66c0a2b5fdf28453959b0ed2f94c5afc5754ee0ba9541dba6218d674cecd6" . + "82e7585995ee5f4e0b6e55400518bc8aeae4d67262ec8306fe59005b7419c8b0" . + "ea9eb2b88ade2325c6f1e6e9506a5e4a698959ed5425efe604cb64e4e3b12c57" . + "e499e909496b2b49b739b17fae959872bf5775ea3fca57c480c8523b3aec03a5" . + . + "6bc04ef4e35256baae4aaa73a23273bf335b0ffcdac3b7ec6b40bc5976c5f8d2" . + "ba3049398a508ce94ce78d1b2186966299d471f26a420451701f2d8fc3d9fced" . + "3e992a8c510ef9e33febe5e6fb8bb17ea3da03d46f3d9be4270b7d6246ae0e7a" . + "56d3d3f2e3fd1999de142b054ce915e4a39a7a5ba027d0b641b6250b90ee3257" . + "9163b0b7cfff491bbe3d305e12e441901b4f46e1932989967c32c3aa4117a8f8" . + "224bba68735df463026f642b7d9d773be2ce17f2f1e73e85ba94980b54478556" . + "92c4e5d3811e41dfeca49f1c03e466b922a082236fe10a99fc2f697b4204d67f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1800149063b97c222d2819369d31c336a2d4d744eb256421452f1bb5a19929d3" . + "a33756ba595ef3cbc7adf6942eeff10393a9e4fc195716f250360cdd0f02a326" . + "5c57dde48d79a2cd6436600183fb146318a19017492295b64a0914fccffaa686" . + "2870e0ce7b5c87cdc84fb70425a02bf148ad1297c1ec08e7b662ebee1bddcf10" . + . + "c8c2b3a714f5b539b090e06b75186334fecb3ac64036ce6df99e7f3eb8a15fba" . + "d036a7f00261e332e887b94d37626b23aa82c6501e49e48f18f8a509903f887a" . + "90e066af0d50ee82fe1820f171c984fb9c324d4f0b10b4b1180c7e8cd5ff50dd" . + "89ba78fcbe0da4259bf00c3b41e2556644eb148438c353a0aaf8a337c587c2c0" . + "bea5ab871e79a37f0896fb54b97b530d5781e69bef6d0764a771b769c97869cc" . + "ccc0de3dad292ed395f94db5bc681475701736e2380d2a25b86afe397c3f0c12" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c5de7738e47f15eb6f2bcc14906f1736dbd5545ea7d173d8673d3cf0b5e7c151" . + "67de8d4e4c96cf78bfd49019b30ea1191e2cb1260c72a2d356e2f71e5426de96" . + . + "3468d1abec79b1dcff8ec2863c5119856f3f3fb834f37084ef34bdfb06d6053a" . + "11baca8041e27389588439b9796e74b670c7b40e335c568d39e2cba99edf98da" . + "9e16690d06dc729b371bc0a1cd8212c013f2fc8aab73369349f96207987daf48" . + "eaa180e59a35f6420d617db1958de65afa491c8f040d4d17faf2767921fa4c57" . + "f187b8acc4274407e503b9a55e3d68fd1f4c8ed3011e5bc68598e1c59f56a8bd" . + "af47b8052d53f5b70c758cdbf90fad8d341889ce2a1f9959e4d04e1b7b3fe698" . + "ca0c3c830912f1f724c5e8bee3cd3b3ca4e197eda2620ac6ba270e532293630e" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c9a04975b3514f494b7f2b667d99567f748b7f892ad1affb25843613083d5548" . + "360922447e0d02cae72a2a9add6d0f93f402b72a3b317dc7755ff79df5710833" . + "de162930fda9d880329998a01e715327e8c996fef04519ef515071364e693b4c" . + "1b80f65768b370a214e5235fa95b0f4f9da213b09a16d1038fd22879ef48206c" . + . + "b674f43ac6e4516f26cc77b4dd7c2bb6496a4516597fb87f56a875638de32983" . + "b47478a19681194c0971c1bdee7d9077bd98f01ed651a04d294d924af639bfec" . + "33e139c31f2a1a1b5a20ee2c560dd9e3b27c3c0fdfa2d12155fed5a3786cff4a" . + "a2e7e622d9a670ff4b49b56f9a75786dc560dc601551c1c18497332f2757ce64" . + "542477aa9ea5deb2496cd57e28f85de09a293875650c73bc28be5974b28d3002" . + "47d9c7e5352f75ca7a1ad88e911d220db7810bcfa9636e154eb015a123843f81" . + "99d54c80794bdd2a41b1343d251aec41b9ab2048922e0106515d10f9138a5573" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f1a9395c445a2e0c595636625a5eadb17b108ebb420f887a99fc01a42d9256f5" . + "a90526e8cdc8b295be33de5fcf35e032370a367baa6e01c7965c2b68641c207f" . + "5b48bebf016af32cbfbe9f9d54a23b6cd159c344275d5d4f7fefe411b8d74a31" . + "db337025c95d43972946c7563efb497270253d98000b2edf77562bc5c107b0ef" . + . + "09813099f7800cb40766eb0359e84c6f5439c745092c984e9c76dc8f40aed7ac" . + "c2f2f79cef2d6fddfd97e98116575de56312a800a3c7848147632434fba32a24" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "d1d713b43dea90b69a6bd3c28fff56a35d9ea1ffe182f57a3956836c408a1635" . + "09813099f7800cb40766eb0359e84c6f5439c745092c984e9c76dc8f40aed7ac" . + "9a2d34ebc9830443ad9e9d9f17faabd2918bb98137f766e6d2b35b6c25ca7bdb" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8fa40f702f0982ba7f51dcccc4c9cf0d00bc59cb702a8a75b841b1abe00af87f" . + "a7fe2edf7a05aeeef1a4ee01d2141ca5b967cc4bc3ecf00ddd464119b41e9394" . + "003ba0edc94a5ac95ca6a43d44290efa24504d6adcd6b3d7c2f5ed61239dbf06" . + "1c4c3e0d1196dd98c70a7be581040408ef4f13f798b28b5a949678478919fa7d" . + . + "7e8b5c2c27345bccc8b0583ffa813d4b4ec7e0e2a13ec01510317cc2dd9a5002" . + "328d8d854614f90d4a66d41488b91d01799444eb96344b8facbff40d44f2a7ef" . + "b940b8039c14e2fd123457c14e359102cbba8a9e2d56971afa606d50a2b72c15" . + "961269721c3bf78fc4e1d06a916a5e48a428aba5e140d4903da8bbc68cd48441" . + "7ca74cabc3055a61b85b872772fd187907d8234dcadf6a295dc13810690c809f" . + "b8cb4a130fa3d802c03a95d038f6fced090476f56ed9756633d5ca69f6ae0672" . + "432b5c61c1c1beafdd562325ad524544e8782a760c2346b25d70e46e2ec30d99" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "241fbfb23750d2878035db3e2aa577c7ee3fe3027e1ba6fa330a18e19f603069" . + "6ed31cc1f0e201926650fc0c2974256b744b813991d0040f6d43127253655d01" . + "b53ddf478d9410da61b815c5bb413955d52d086b441aac89319301c7c4b63487" . + "a2d63086170e6d5956300ed0eab7332d0498e760403fc97c0ef3ac26867299b5" . + . + "781c050edac4a45f9b70c6cbc5d602e01902f66f260ec79d3fcb9dc1fc08e6a7" . + "8caa8ea96773020a47cf9c23c7e0a6c00252f44084605cad2333d00d383824fd" . + "815e1153981d38e21bda5a426a16f95b14a51b32433b9b27606aecaffd7aa23e" . + "d42e01f57894c48b1da46579801b823cd5af82d0803a65b0f6641209e34f8e13" . + "cbedc2819a25243b9872ce749bc97e42838f07b3a5af82e74da24c605e7ba460" . + "3eb37cb31338804f43d911c5651b5811c60d5b0d7e3b09c2c2dc86ba1ddbe82c" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d03a0a75bdaff232e7b599a6dc09aceb2d67c25512fdaea9ccbfa19c38903c9b" . + "5f5559693456faff03d519ebbd26143adedf617b055631514c17a757e05d8aa2" . + "325cee6246f6ff6b31dd16dadf24bdc808a5358d28ac4396fcf9310681bae600" . + "979b1b9a9f58db1bf7eb54b8ba00eb965df5f38e9dc73c1079a45ad01383e265" . + . + "96ad0e7cfabe79fe02ac672a55f8c0310849ba788a9a781c30fe2245e8a5be19" . + "498efa520f70101e2101a7ba3a62da64de6874b5c021374cbfef2e7ebd035d1c" . + "88ec9634a7a54b17a7e612b852fe8bfc60932f621b3923e5bb576d61136467fc" . + "efa6988b498aaabcb1a4fda6431a15f5c4dc2de10925ec8c89fcaafd2f78b57e" . + "f03d0ef30acda815056fd979ee5515b82b475a0d7ff830ec5c4fdd4aeee19251" . + "471adf19ed509846606b49c63d0376a6f44692e9d8ceabf7abe3b7e6072795dc" . + "a0a69181b56e1fc2863a98258a58484ca9642cc2158749293e9e1a5f01a7a9a9" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "01a48fd4664635557bcfb5f1bc54381e818eb0ded8a749fcfe8384b6e5049805" . + "3e992a8c510ef9e33febe5e6fb8bb17ea3da03d46f3d9be4270b7d6246ae0e7a" . + "1d8c1a1854b70ee254715210b27c5760583a200aeadfea9bf001dd3110341442" . + "7f05b7eb385e313c21da614c7d0edeea2013e311114d0cc29c6879da1768d5cd" . + . + "3e4c99b455344c0929172be7e95fa6a5271ac21ef203e6895f7f8da4152ba071" . + "27c5be211827c291ba78b9da0d733b65498e7986508c67cc0a7d88b49203df12" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "f053166bcc377bb409f951a535199536cb8064a735fb900b7ead8bfce182aaf2" . + "dc5d1768e5639fbca3ebfdf19dc724df0737a02fc6388c0fc4a0b53d6e7d9d52" . + "65f4d3de36884827c588e8ddaba992fb5f6a4cd0c2d6a3960c4c18d4d4419b3d" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "41be6ca75c6fa94710dcec7f46e851d8bf4a22e4658b739a1aa23d8498acefd1" . + "f77ca1531bbd91fe72731f3b168df3fe6050e236acf134409caabeba60c23bf4" . + "2e58b046ad1e5577d392d61f3ca94219524f1a18c638ad15ab19d603c0aeb845" . + "59e50a1aadd78fb2fc43fd524e934b8f9892e47b50de2f4d909c137a46a388e5" . + . + "10f4b43952c51d1491dbcbf3e5fb3a9cd2d1d41a2ceb0b4ccc3a28af2df43ac5" . + "a937efb2edca5e45f9971bab13f674ec14aaf6a3a67a27c34967b253b24b6836" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + "1212dab1b107e82a2af497bbf029d4a3c378585a31bc4a084d935c605cee70cc" . + "2afa2491c8dfcda17a267b78f07d8beb045880dc22dbf8f0477d63b8b9d04ef5" . + "566e4def3fe370816ff4ef2bc8b4c13a5a53e06d795fa2c5865539dbda3d0bad" . + "168a0a0d4515e231fb8220a4c9d25876d1c56045572f7a444db736c49338f1dc" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21371a0cef360437640fb9b34a58010e3076cb6f6583912ed926231ae1d4eaff" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + "5feeb10e5c7cf7b052f946ed51a27aa7e14f95c8d2d8e8c157dc10927ceb2b99" . + "2ab1b2bcd411dbb6a09968b65f05d58892fffa4a2f6ef102fc886d7f25377434" . + . + "bbc17a2c8a2cb367e3185b1e45e913b209be8d40e319f48c4744773fccb4cfe6" . + "8c9f4c2fa552ce0793c3c20100580d3082f9819ff9c99d541fbbc26ded124851" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "fe30bf1d8bd3d853042ec49b0950e008d90b1258e497139831e91d0cbba354f3" . + "e40568333bf0efd6b4b28843c366f7ce48eae167049b32e8ea2daefa312182df" . + "10c7007949b2ea2c570e5f6049b6b7f59074e4075388ba0baec1a4bc20b87d89" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fdb7728c909462c106d4875d66d263489c9eed7ee0e73c5c1fbd7122b0cc0d19" . + "857d8b0a2f227cb343200ddd6aa78b62269b014920c96a0fd2b2853622d95a31" . + "0f79f747086525aaf8b98a8c5ac14c86f971d925be5ec38ad54e9ecf8549bf0f" . + "33f5ed4f4e3c89d54e8dd2f230a0d621ccaa28670daba6caa62abe7ad71bb0c9" . + . + "d74b8ca63eb76bdfb1c11a38588597c9f841e7d89567d2592369ce9e8d3cac24" . + "caf5eefc744b6fc11d2cf7a8cdfa73962188d19951d09ad0201d33665bb8c662" . + "9a4177cbb00fc4828d83313de2f1f41fb4a164984ca6a4593605022eb9313dae" . + "768bc869f2cfc3e24ce1a106febf2e85737f6bab18417f13b0fd59db0f284f4a" . + . + "9297a9b39ae4dd3bd0efba2142176ec06e2554072cece37eb83a8719037d5d56" . + "bc822ad608e0678271065690081e7b94c80eb5905db8612267014eacd68d2a93" . + "6bdefe9cf42f1efa0821aaddc06acb84037a14918a51c17224430a9483471897" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "85be578519de0e7c784e0d8ee2c540354f5e6edce47c71713c047404793a2de6" . + "e7fc3873ef78cd2eebeebd2181a602e533acc341ab690f8e6b2c7156ecf0dca6" . + "d62a0a9f067da5db7575a27d7515fe696e7ef5df0a076d542d131579ce003fc1" . + "35fa830d7ff6f402bd1396a8e059c0a47088238c1b806b32c5a9f184425e9c2a" . + . + "11a36612551c3fe37f8c0033733d7372517e21fe01359cd84195b3e04c6e4e28" . + "6f36b1f368a5005b78b989bde5006fd02f88be3ecd0dd9023be15f38c4d4294e" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "d4480d8db9af1e588e4b6313311c5c6818c80452d60c675fd5af9a59ffaca922" . + "e17542f5f498d41ca939c3e33fcab4916c8e08d4904381d9bd81f5c93563da8d" . + "7c2e1efe13a502fb8dbd25ab377bd195b3ac9d7646b956c284a9ba00dc8358b9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b34a51ce1e4eeef65a6e9436b6095b7303995f5676bd29df98bc45f9dd83129c" . + "a8a2727880b40a9592d8b935d082e841302cd8b4f0c67cdc8d5e545a1ccd4e87" . + "cfb4f7302ebe720a245bd9ec9da2ae4aaece957a5c09cdc64c318742881f38b5" . + "521e1041ee273212b29a16a0ad39a9baebe99d20a7bb9a08b06423903d8d2043" . + . + "fa994461629596841da918345da850bc459beaf708ef7c709e008392921175c4" . + "d4189b8dfc2d7084500c466c1277fefef79fd936f66848f0eba823e92c3c2964" . + "2d960e5c1d4c01d169547374ae83d975e9212c5b23e64db0504f36c8367a7cb5" . + "b0d86e92dae4406c599754b16c8a0fa6877d50aef19c500a5d3b6039782a6358" . + "8e31715ce05f9acf2d52adb86f9d1d9f39925d234d30425904d8ab4dc7fb38a3" . + "8004d2395a46c0538ff5a720662344df1bfb903c1034ace3fd12399832235f4e" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c52f667107fc6d3b9fadcfb9d81fc9f7ae0e6c1bd6b6ac3fa66ba8027e9b498b" . + "c79954f907d30b00369b5fe1c5c6552450d7a8a548afcc46ef073585f558f5ba" . + "030fc02de84f9c993bb0fa61ba75454b95ccba856acb7b5a79f993c2f350fd08" . + "5b895d5947291a39f5186b3ec8298685a567de03f976d94a5768da333841ce36" . + . + "82560236ee96c1ccc74b5a48933b32c54d85f99dd6c6f163a0ce4795396b1fb8" . + "c2467e3376acace5d71c9ffd685e44c31370b74d8fe3336a06cf0c3763b25065" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "0fc8ddedefdfe243571fb1cd4b86530d71161e55de9caa7b91aa1ec3dc802471" . + "db834545fa35480bb320ef63833c4c3e6f3b50c60021a0d5fe51d94380863b0a" . + "7a7c3e1a7186fdcb0ef9670cea3901f4a0764142824c7c311a6be01023043c24" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ff6548b7bbf2721bc73f50cb48e0186d63e7faa7ffb05abbb68114d3d949c21d" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "2948c87c596b08fcf5272c6e9e0c6c5b34a28c5c288c6c7e0e9276947ff87560" . + "4f245fc6549e3fe33fe862a4dbb6afd3637d79f3195c5fe7240d7bf3f4530b32" . + . + "c23ecbb87fe0ce6abd87f0b42ae210487085b22931be175bbc1f8db87c89cb03" . + "6c6252949c6d60ea378727356455c607cba45d04b826c7ff3e8829601ece0f3a" . + "815e1153981d38e21bda5a426a16f95b14a51b32433b9b27606aecaffd7aa23e" . + "c1122f24eaf74ddfbdc24eedc472598136629882d1bb5a211d702b67fea15e72" . + "5c133cf6fac6a60d3317623d12072feba42bd8d780013ca652a5040695deb5d7" . + "9d921c3ee4fbf03ea3fd952befe97c6e9fc3a2491e6cfd8a01a493a47821edfb" . + "bc92067bdbff1a97c164bf4cf73a50f34649c53a0e311c6696234cb1e2f52011" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ac1422e96e258581503dda59345321816657235ed539c89f7550ffa2f1d170ed" . + "ce5cdc507e34e47a86110f11b9e2bedc4c178f5cc2c7bd47a9723c4ef5ac002e" . + "19d7074c3273cd18ff81b6945504e5eafe13d88681b45080331ee2ad2ca970f6" . + "644146d86a58a14ff4741d3e03f5fa87ca79e386f34b2c7353c134985db623ae" . + . + "c7834a8c543f168efa1e7c75304157be2e42452f626f5a8b822f4c20af9c68f8" . + "87599b4d733d70355d88d7608e3513e4e2ffe06146a9c8bc39c7e3261fa31502" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "fdb49399b3ec6d7d59db33d702768bac6b2e5f11d88b56cd76aa1e3b6d36233a" . + "3aa8795fe9002736f03d9a6aa02fc9ad3489814745e213d31b6a25b3b1afca33" . + "71d608e6db453019d2bac482703a3328e40d6b29766c3dec5a3349a656eea4bc" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "903ac5971448ee99849a1ac674df60a51d69627dd7f8994d1f0b73479f5296b5" . + "3568b792a8802725971bd6fc07a94982069785f1769b66aabf1b7b73674f95c2" . + "88ca0c839ed065ab3313fa39dd102d40db4ce8d54809503b6ffaad6175015f57" . + "76937b64feb5295063a8a4626b16011ab899d503c12dc8a5c3af3a2f33afdc0c" . + . + "49ab0a4b321c585a7ea5ded237179932b6c264a6f8ab4b9bbf36ee1a6a547ea2" . + "e06098e2f2e20cf6016649f683117c7de454ad73c1f245081a798d9159377b28" . + "6f69ca8735970133a3753aa18d7e0ade36922866cceec6cce04234dce7b7b095" . + "3c1f399c9f26db2324ae5757395af3e7325431dde0149543f9fc33f1e63a845c" . + "b116a82a2a283406902a9402f6eebebd91adb7e78a6173cfb6c54237facb1832" . + "3f66b748ea286c7114bd145ac1173c093e69ef1199da900cb7651403a4dd9b6e" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "76d6fea32e7df403a509f7f74dc97785cfd251cfe3898f111a60b8f91877990e" . + "9741dd32683742d6c4a5c4951ee28de0cfd1fe29190c330c5f0c30d99f8d8b26" . + "33a05278c0c64bcd0d53d21b4e66e45127fd5dac62cd88f926d64af4cb800146" . + "fa755d2a57c0137bafdab6317840fb36ac1cad2cea6c5c00c960bde8fe55bc18" . + . + "50a2dc4918d31b8015011a9c567de70183a38749217a2ec82f6e7cd7e0e3aed6" . + "ab2e1965dd2e55167deb861fa0fa26b918fe3852cb211eb282a8b9c7ed19127f" . + "5b16126f8da59ab516f1dbdbd5a7a04f9355baa6bbc82d8a62d160b725089fa7" . + "1067dd9b5b8322580df7f427f0bc52cd73882c9fc8d2577b52d38129111c39c9" . + "ac531e1748276a421a9c01b0b6408848b12aa2dddb33b1e39c3116d310dd1eca" . + "d4bf3f229d4ea4677c4a487b6df28c3ee9cf4f689894675eb83684c250fd2aab" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b279940431379b894d5695a15ff1e691b15c09f813fe8cd98396248dbcc9e1ea" . + "09594b7255c1c847d61d899da3070455fb484e9ab56693c75dd302a2215e2ca5" . + "f796b071b7e5ff1cc19a2b447eb996a17abb23f301a5873c1147a89cef7a05b6" . + "366281be4b933f1db31c69e46cc611cde1af99f22be5d273fa5b5d2c0b968b18" . + . + "d62f2dc444df634c7206f5bc0e134bb70d10f40d4004a899226712e8535ef241" . + "c3a7a30f65d5466a47513ab0a3645beb6b4870d770554a80ef641cf80ae88261" . + "91e6ed0e7e8061b3d8df981205a3652a4ea5e7eddd9e95d5690d1f62385fec79" . + "70a6469853438f2f39020fce13c6531ca9f8357b8533ba94133b45809cc91c3c" . + "49a6c8ac756626cb10e32d8f6e10793b2d119db02909ebfb6e68e31ba048f98a" . + "8a7faa1b9e3f4d81f91803347630e7dcd595eea30efdc27c870877f8c361f201" . + "0b3a9d9328c06ac1a1770caf7afd8231ba9c5b537163162be7d22ad96b795a2a" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "602fec6ae983f31df178a0d01f713d37bf2fb40a1377db0062e6e935f02b76df" . + "54bf2c7bdecc2414a7203a5986cf13093e6367e92d9a6e3abc6e01df0170e5bf" . + "a4b342d300678b1e8e31c18488f0242192f747debeade3a9f396f407a0ae8c43" . + "211a7356c5f8593d8c17c0f081bd63e7a3bc065cee22761a47c80556bdf5fdd5" . + . + "c3a7cc1b9a265fbe89071cac840528b0a2121a8ebe20ba74c402bb5cbb656e93" . + "dee0c1c5a7111177820160e54a872ac632ae2a475489b998f5b4b5163d0482d1" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "c3030184b84c55c6ea4c1edf9fa094a75c2e65e06c07c79f9f7613add3da9fb1" . + "3a2e651acce19f228632f4e89622843ae984236a64ba26268725aea2c4fec214" . + "f4294970cd5c8fd0b6a81b8b2b34a3c60225079e944fad8d7b9b93e01fd76007" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6856190c503ef16a8c549964ba948c6cf6f533c51278e8b4e61366bf6f97eb7b" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "776e05d766821d0fbdfb7e66c919826851c603be7f865490e1a9d6a8a4483573" . + "cef89648a0bb219b282bffc9939c037ce9ac954b9c5b99438778a75debee9a84" . + . + "575f9c9adbd24b05d43bee49d15741f6295553981a8cd2fa762efed70522e399" . + "8abd9937319702ce2182341855301ed5b1a9d15539bd66998be5476e0155eac9" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "78086e86ee14abb36d43f0e5a5eb00babdefdba1ba624bca97e776e4f23dcc84" . + "b9d6b95dcc0a0076715065681e36290859e2f3d01cafc3d537a9ead1c1ffb4f4" . + "e1a57cb0b3781cbf767b44f402d954121700cda557f9b3f6298e6a5419e023f1" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c813299687e1f6220f486797786fbb4310fd0b920e2a9844070dd41a6df7fdb0" . + "a44baed6849f7f188bd4039e1b5d6cd557b22c5104318f68d3c741215273bf10" . + "8ed36b710bbc8ee001cf0be8fc2833669740c621d66264ddbadc3f304500871e" . + "25669a052c19389c741d72836d26f6dada6247591e0a8a733b428706719db191" . + . + "d11ccad2a9482f7fdca5eaba0d5f24fe4c52012400081715bfdc9c385ea0fe01" . + "107f41b024973c060e21bdf2252a865fa41e49be8e90e9872991779fc5fed518" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + "035b0342334035b40269ac37f858945fee4317d3d55c06270a423fd16e648531" . + "16326ce33c16f5e447083551226e933bdb1d1002467e0be661b30adde668a2ba" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c9d3494ce6af41ff02eb5891e5b3aeb3432f131edd395d9249a76e49f2b5e1ca" . + "9cf2aa62235885c1016aa11d160267ce812a1579a973d10f793141db0dc180fb" . + "c90356573806923331899651a70917dd026d4f59028dc035bdd374102fa0697a" . + "4c4b8e04fdf238f10bb7e150437e7590fb9213ed4853d977babb6c567366b8e0" . + . + "7807fb2f527eb3f952e2f5d0da673bb5c5c8a01233ca83ed7cb85a0980c3f0df" . + "bdf4d457e2449b877a47e9f73da6c259b340822ccbb47e7442ae2936d79d4932" . + "8df5bedd52c46b9396e6aec1b2c93f2eb866acde39662d3d6db0b12508db6f8b" . + "7ea578b66cd6012994feba4eaa439e9139c359c1362b53a54e84b5bc7a6f6432" . + "2e928e4612f523f34c52a79eb3d8e3b9c50a6f54eb48f4536eba2c4df29129ba" . + "8047f5c2605c148f014e4e10e6b3f11f1007db6c0414f2ad3c4317593a58fa3c" . + "20c87f53723b619a2a0ca29f518795b09e4cd9d57a0d6bb5acb4bdc644b62780" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ff1e6909d7c9c141540b9e20b9bbd9ddd9a383fd267f84d004d613c6e53e9c94" . + "f3d13b296d00ff9327d838eaa49ffd6bc684411c570aedf7ae6d0941149b2e76" . + "1398b250260f27a3b4e6f1d68c58a67519857f3806231e301a4ce239f792c24d" . + "8c276c9a09a356588d7b1fb72fc0295aa939d2206b15cf651ede4b81f39cc134" . + . + "a9026378f871d30dd45803b64ed0b0c7cf00dbc8cfe693539fac03351e0919cc" . + "57ffabbd9e20ee36ae60c7023fc62caeff1fee003944ed64cdcc0e25c6074657" . + "ed11904a5ec814782c8aafc5dca1340de8b544d7fbf599825a5d28b581e600d9" . + "47c60daa3c62125513fda5c94675cf752cc28d63d82526c619ba47bb3fd03078" . + "0183106e4b0362ebce031ab3c91d78f1b25ef4d5b371e8faae61a21806db9c92" . + "f9edbab4c0cc47033bb1f895559621519feb3c8b78c3f7093968bf79f40f910f" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "77f7fba584abb89d34c28b32be4f096614aeabc3c14ebb5697df5c519fc455ae" . + "5f5559693456faff03d519ebbd26143adedf617b055631514c17a757e05d8aa2" . + "d2a55756e1e61ad4ea15824cee84329fd798fb811c778f4a1c1865dbcf10241c" . + "fd4e8747f6252256baaed61ec42d13a6145dc9422392823f6df513695898fd10" . + . + "d1fcacb49516a829cff663aed62149e3c84968ba45ce1c0227a294df4186870f" . + "b6a6a0b768ba3d4671625ed5ae6f4e73e1f64350f841b70fb5dd118f5b4b9abe" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "d981f665e2cbcb7c7385fbc06ac3c769d5c1bde300950dd49b35f740f9f041cb" . + "248e1e82206dfb8a803b65c297e8cbffc7bdd93657b349a1f1dab560f5afd565" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f48561f1f048f55f416ac557dc4548ae7543e42fab12d9f67e336552b902b23f" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "f7534bb3f2dbc8bea52f9d277208b58364d5680e4481f17b85a6309dae3b17f8" . + "67c74b2894100034736291c66364d4b2562084a2df9af00ccfae8a35e7fa501a" . + . + "825715cadef27c121c9dedba4806c42cef56a1c3678b9836c57f79e5d7e95b2b" . + "0adbabfb46e185891df2cbc8101ae2e09cb3f019459018b7313b85d55feb50f5" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "e2f456e7371571bd2b825aadfcb149ddfd7ca2a7c4c088aee8027ed5e21ad092" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "75c72b65346c3f45a5be59d27655f3559fc17b7ea11fe6a8ab7edadccca5f0a7" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "7e9a06e6d55bb5665c5446b2e31cce8fe3efa3e8328be859c1f90abdfbdd5381" . + "3edabeece1f42ad4375487b6ea3a850b32495ede749486bf4bf008b9f1ec0d0a" . + . + "147b7b9565ae7a8e012c40b8e1117c45b180e98429d439c6e063af523d1d1cc7" . + "233623e1a57abb5b99b352576383d949ac35a3a3ae88b5d3245265e7f0ea6ccf" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "90cfcefa0cf5cc53d4b20465ceb3e6850f06ac0fda8a12057d61b56259edec05" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "17982055c10ea6df8528742169bcd80848b6d034ee74f60b6339c6b1cd83cb74" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "5866b09291e180cdefbb5134409b993b019f5bb0edf1f8601c9f99c0dd30676e" . + "d303f0d547584e7a498df2dc4b02cfb1fe6add311ebb2b3052a1ad5ce5601824" . + . + "7a60dcb1c1f6b106e111e7962b56b5042a6e4af83f53561c9d4a2efd20df2ff5" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "31956c3dbeac0e9d42d572d5cf74f48679574ca10835cfaba99e0e13e0f57ea7" . + "31956c3dbeac0e9d42d572d5cf74f48679574ca10835cfaba99e0e13e0f57ea7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a20cf7e8e4a6996e78bc7cc16bb98989a106fe5d78a975612ee45b84180cf922" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "5bbe7cab8177d83bee8c8843a2a3dd1db85f49a80bc78a8395e4610b1fbc9914" . + "10c2d9c89f679f156afbba9cb814742970d57c2275ccac614cf78637d30295bb" . + . + "893ad0bee41dd6ca35ea203af2dc23bb04668a018cc01fbb7cd8b3cad97631dc" . + "c139fa89e7ccd2fc74d6d4c4bfb513c399c1469cf6418e945cfc8b21c9ea069c" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "701d84ffa119502a64b54d2b1b401d12c5bc2491428c546d65e1d5b6414842d0" . + "701d84ffa119502a64b54d2b1b401d12c5bc2491428c546d65e1d5b6414842d0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c89784cb543a1121903987be497254a66656aeee8ea57d88a903d9d34a95f8e1" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + "916f621b0e585a60b5a07ee5463186c0ad874662f3ed79d03f99f404bb166f13" . + "f06f1301282cc345bc5bb71fd963b2a5f91e6245fb381aaa8a9ba5ff00fe1a1c" . + . + "0b8208c412ee8ea100647b9f9a4e307aebe9eab0bd98083bc4245da19cd33622" . + "222c5017d636e44ebcc61bc8078eebaaabd3f1e50e4bfb2ae001b11a0219e9e2" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "e87621a4b9a607326a2999fbdbf7116bfff73aab5f1190533cec620a53cf6fcd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dc3b75c15e1901bafd11e2f2687fe810291535242f1e01f90aa05a93d535765e" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "58f3456437217a86b785255880ab1bf8a5f3aab109b40e09e77087bc1b26fa29" . + "e0ee8b6ffeaf341e66e159d154bd2bc21266b06aabd819d0b5ec90b84a49c263" . + . + "a79693613a97838415284cd6403287a20e9d30ad4b3fec83042795e437b9e70e" . + "e8e0d77fc3a4dc6d541e3021851fe24e757d68b70474508707a0d4e0715769ee" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "cec3d7be8403271b5821bf42b5557f53c6caf53182295e77040bb71a67bf0d34" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d897b4f1c56d18050affe9a6dc06431e283f7ebe3326f2578bcee295aa46b08e" . + "6ede6c474419f0e7ae270a5951033c41d7855d47129c701187b95632bc0be221" . + "db3102b2441c7bf88518d7f5c597b1e16f412d25a5a4e23a9b0aa9f54d596e12" . + "3248a3cf360ddebd704f4dc616bbb98157f8e15c85d6c31f0ec2389a4c5b56f5" . + . + "304bb0f7d13286cb2b6295f54e2c171ea67bacce7380885282213833b8ed4b0c" . + "9622b43d1db6d260b5b16329128ffaa8cb32aee309c43256331a4389e16ef847" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "7813e941363c13d1f633d332cbc6c1170d917a86f83669beb3a92bf6f71c8cb4" . + "7813e941363c13d1f633d332cbc6c1170d917a86f83669beb3a92bf6f71c8cb4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be726d16a8a1f8a57d700d505bbcdfb5c7f652955ebe6226d0bdc74018fb8ce9" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "496302d2e1fb4744340fa242280e557351b3999b1d54f6ef32e40261f7dccf27" . + "a3bd1ed65169b231a83f5aa896c22dc71030ea3d64a20164ed2432697419011d" . + . + "3d82a8e030faf089d1934e7806d15d7d4698fef12b22268a378a53c87e59d33f" . + "b8bd46a82fdab621f121585a93388d6c46dce5e459e76929ea475fd5dc36d19d" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "ce62b05efc710ef4375fef093b3d28922461c25522f530affd16924d4b7c9558" . + "a8a3b05f140212cd6b12793c3fbe2d8cff1f47eebe175d817a3841d7f43a0995" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "508347d7733f0b34290ae3830ae9965b46b5a378ab7fa67ced0d87b900e2dd02" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "bd0d39c993d1abd517a29aca75f07e81d08f69a758164813c390e02b65e5a376" . + "d5c35efeac8b876f9158dcf1bc8e7bf55c4a51486cf3b744b350afb7ee8ec359" . + . + "7e042b6573b13e08fcfaddf5bb73daa34f552eea1587b58490dc4ae8d727edd1" . + "2d138d80433d41266c8dd33b9105a12848afd7f00a7e2e489424b864493e15e2" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "2608dcdbd61a7e73160aa79c5c5d3616f7ec42f8d7fbfe13fd1666d4c012c5bf" . + "25fa5c79e78b8e16e1a66de8ef5ae65b218c05beeebd91775e7b70818b155ac9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d2b01642ba536627ba092d35e45f39f4b35c02993293a93739585280fd3f34b9" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "e6d22c5c8f691a1f6deb15547492bdc44ed62fa55ef6b6122f1b0744c0a6400e" . + "e366043ae105cd3572b6751ff0367a2efda8330ff2cda6dba038393f0ab5ea15" . + . + "dc9876b113fe862cf9d04fbd295225eb4d21c97c418dc215f2a84bcf12c9f142" . + "c41e1b044bb3855c17e15e11a653a753a49e585a65c9b6851bc3414c51e3bfa3" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "053f6c288751101fb61d10edf3a8a5e2088f95d9988ad6772ba9a465e5b1ca8c" . + "0e1bea9fd86de991037b6ac67c127a0a1bd00c88c75fd2f3193844507e2226ee" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc9a488fcc5dc07efaa9b8c37f42d53aed6f3c67009327c175fc541be893b492" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "c0e30b64a6c7b324fd68315c93fbb8252cc86e12d09f5b32282c5a8e7337cdf8" . + "8ff5fc7c83ba5d9b6c25d0ba68b8ca8e9bec95a5a111113d1829488fad4d579c" . + . + "998f04c2b98c3f1e08ae36526533758f2f4e0f27810225e0f4b685380bbc29f2" . + "2bcc183901495aa17d55c1cee53b8afaa8239dd8aeec32616910b5df58582aaa" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "bffb1ec72b161d54d5a428fbd3ed0f52ada45ab1f9f1943cb68fee41ed7bc249" . + "6baa4a8307bc6083d9d59f291cb2a94444ac29e771a9bb9ab5ab6f8b099cc1af" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a44a21c06e9d46e72fd2f1db6bd95b946516a24221742ea83dd3413c70afff13" . + "edc74bb1df36118f152a351d15edb1da87e06599ad9bfc5c2f51c7194cd4229b" . + "c32fc9b3609af7128ce494cf93d9c1364b38d30bf1b2c509c6552ce5eaa5ab12" . + "fdeefd5579358819420fd11953d5c6a35530b72901aa4ee8ad656280b092069b" . + . + "0809f24727228cdaaa371af26f95d6beeca4d5a2650d0e5304ceb1a8f2dbc06c" . + "0ac8abc0c893153ab6505e730039a276ee3fd639e1ef4e5cdaf6ebe1f66f3598" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "fa74cdebc3f3c843377753b9e1750890d1d68170ee25ba53fc10f4ae5b5a601a" . + "b72fd04878e4e72200f53a339a2c1264de355d3ec5e03d3182b8160e744768bd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "386ed334a4814fccdee9fc41e7a461e4714d05bbb72c9e45f536e79b61b46319" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "77d9d9651a0f77eb97f795388d64ba0519f0bf04383863f3f6d7838d80242de7" . + "7d2fb23ccacffe1a03aa237e1937c9d0a606bfa1c548727eaba4710f79a052f5" . + . + "b62fb9a21145d944f81114ff5f0d17ae54d9d339c41d5e10e380dfbefe65678e" . + "d550e68658136aeb424bfb04678022c9af20ed09f7939739eba5a433514174ab" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "97f299ac4299886a6761360b371d7748f1380a408e6af3e9016fc2022b548ce8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "47c7b84534cca83464d4732be50c3eb885302a73d862cff00c640557ba0823a6" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "6d1d622ae2cb4e7ca696c916b43e0aa6bd35d8dac4d203df05d957255683cff0" . + "e62362000c4af96796b81f0a7e4c63ee9d6aed1e66624e2278fc2fc62a4f3d4a" . + . + "3f8f51cca10d2c54f31d1cbd62c0a3fdb41492385dc6e2b10c94b06354791230" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "80cddc98c6d72bcca3149b6df38fca60d41f34d1455412aee191689e9f9b9c7a" . + "4d876f8193243d49f273507c91975ec675488136e4d9ea3b6e47ae4cd1f800a0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a6bf553c4e557d77f9ee9487918833b6c1c6a48a5278a199db5b0efaeb854ee4" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + "a9296250a1c4cae3569d71f96dba92eb172546556b0541154c627ee703e72d59" . + "1a408b9f6bc7bd20f229bc4c22412e271b7a008970a66bd12083e6ce56ac07ea" . + . + "a7e76f03336afc1a72c81e31e104c2226f1b1b2bdb89b2b57b735e24e7e17a25" . + "fddf7f034136c936e4000366153c64d486ce461259a3497a8ba33f851af5f7c0" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "c8b4a049779cfe35148643720fb5b4eec87b246326ace7031685b1b01b145454" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "69c9c7c6d2b6589f7a59efaaa606d2634cfb27aa9560d34425333013c3b51830" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "8e2866f867717bffcfe54a65277603563b7ac81169a0d8800285e4d32d2c13c2" . + "e1db9253c67522b43a34306f603e24acc6a06b6caca084dd514c76364f3061de" . + . + "1fbfe63a80143055429b35a71fecf6c7a29dad310cb7f1d5a95a4b7cd9d88a13" . + "b6a6a0b768ba3d4671625ed5ae6f4e73e1f64350f841b70fb5dd118f5b4b9abe" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "8c0c1ddde9f1e43763aa404e259c6fdbc8c914056578e5e397e7a235009f0e31" . + "a61bc598cda0b0cf38c848b5950a90f8ffd6394e4e5fca114311a8b306e6aded" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7040bc9478f4b5dfc54b2b38090be3f6a51c1d23b2972c6673c50ebba8144793" . + "0f94ce473060e7c5503d6bc14495551118663605be875c111b20ae9f9a3080b9" . + "b53f937d57bf232ea09acb55e5c31566f814685ac9342f7ebd77c9f22f06f9d0" . + "d712db620a27391600c1d39d611f17b4789557a0bfad04ea84b2747f7132596c" . + . + "6f46c7445faf70c47af49bb9372a30be4a624ad0cb26ce59186d7a39dc991117" . + "314fcc35dcd334da50f371878178e742d7d5c5daa20475c73b23242dcc175377" . + "17b51194b3ffb93ef854ed393e2469c3f9aade6db89752032f42dc4123dbe254" . + "cde2bd069b5e9772dd4b75e943c2d4429d85eaa7c4987f8862a16ca3ed5d033e" . + . + . + . + "6f46c7445faf70c47af49bb9372a30be4a624ad0cb26ce59186d7a39dc991117" . + "4e7ae3b6d6e2edaacc51788c7ce3a613744da97711244f9ff91644e2bdaea987" . + "af29535d15c8c877bbfa75e41fd96b052a460b94d4891a40ab697a6d2a3601b7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5cab6ccde5b5018dcb9d496d686c64f86c724434c43a818132811b8c5dad8ffd" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "7fb91963004d3f15418ff400c22b6d729689c740b588b76b76977a90832857a4" . + "dd94eaa8481251fcf45752fa7bd33d32e90fd677477abd898b8b433508d12d3a" . + . + "f4c6a3860f928d4b3e5cde7d777a6b21b491bbc996b4673d2b7f25c678cc409a" . + "05caff22570ea122ba447374f8749df44d569098ed06f570d7916343c142bf7d" . + "6396804246644698c1f7656990436ef69f1f2ce1a784e49658e1188d4afc4dd8" . + "731e11e2179dbdc6149997e302053f4eeea7ca3ef8da98574abc4c87dce97578" . + "b2ab1ba4691a25ad76a74172d2cf43b4539b256fa0b3668f80f0a97bb55de2dd" . + "d7491c923b7b9f219351e01d5145b3166d3671cebe95820fee08c12f0abf6562" . + "6ef2051fae0d097c79d1a273f0a633963718ae2b49a70191b5fcd422f57f5001" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b525b8a9856228a2b8f0b261ed2cc3174ac019df542ec0fade8f01dcf1b91f4e" . + "0ccf618706d00a2fcff5519c2e908b5a86657bc29a60b402de24ba498be4b484" . + "a43e3f2c971b2b47719bfeed29561889b0eb099ef167376fa015ce9463f7cfbb" . + "247b25b8be5bf051771c371982339fd6be1023d4083958f31d021a2c7d380fff" . + . + "42da03d90deb7080ea443179c5bcd5bd96bf25c4371d3770ab699d070fb578dd" . + "956c62d430f3342564e35f462213bd2ebef978ba14dd2a6b36699ef9a4e33389" . + "84b470041cb64bf93f76c41810fe2d013a5afd893b4a2690ba05aca7fc41421a" . + "dc5c757dec3618a31813269d312d32de1a67d672bc6edc7293effbf9df98285f" . + "eb9581a696052f5e850f0a6256fc83b8ca571e3490dffb4607f6eb11f7648d33" . + "02f15a61ec1f98a4fe77a2785fbf028234b714a9dd1077e33c276084bdd8952a" . + "fbf4e657294924acca4862173ee31b86b300ec94f8c3e0cbf291c1c1921f35a8" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "5f51f029b889676b83295670f370933e4fc1c3efc98607305262746598ffc302" . + "cd0e48ba309f49cf8fce4bb93d11c7044f65959863b85ba7c46dbd7556b1f59f" . + "a049a75603787e760ff338f3f4899ee7cf4bfe9220029a73aeb2bc4b4b179eba" . + "75e74f9cc3eec93ce60d78e7d25d697a0e929cbec40206b105ff7c72df46f454" . + . + . + . + . + . + . + . + . + "5864c23053ded641a3333290e46087e1bc7b64ae97946331dfb988f0159e32ea" . + "fb0e98de2bc8f7f7258cead75d465495173005495d53233d9eb6b584d98d9d4a" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "3d93c608d308921ce09819efd4f64a2b66e103ac010e547cfe9864527fb5722f" . + "06e885b8495e91721ed886b60c2ec93ca87415dc73a5bea25efd11f6bfa01654" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "e9898892cd56e6a576826054b623ed57a6faa65f8c57fe0a67c13338b34639d3" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "107ecd322a3ec6622a46d908a516c9b640ca9aa1b6b37a9f5ed6a27d25cd681a" . + "0e698aa9b8c689e955973d8455c7365c7e9791fb4c0896babc26e2b97dd4eeb6" . + . + "0d6580caed17350417b7f06219effe03d0dfe14c29d123e7bd842ca1e9ad32fe" . + "f9a559468aea0968830cba98a9723d6dd2a88903f02336353ed8b532e76cd631" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "a06f7013a4f94f3186748ed3184cceada6014447f1d9563bc4663155b6603a5e" . + "72f4ff7293f43252664b461c4ad3307eebed45f7fc0022d1e0304e4cbeddf847" . + "ad8397f15d86db58db19447adcbffe967428e78f8e9e070b83f26fa04ac0a4ca" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b70c132303c4859a3e4fe145c46acff926f2aa572075d950c0c342f6dc42e794" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "7c9ea26d5861f35169e4becf8098a2e4bfa856da5f227eae60a081a734a57d7c" . + "79ce38ca74c6766ab2382454c342920ce219912b84cfa2b52059a7f81b236ca4" . + . + "d5bd861b3fe0ce35540fbbf512b80273c79365ae12fdadf4955d1700c7d6b9b1" . + "6ab45ce1168ce50c1a968e1b2a4a16c65a462f4ef259b7ee09633fbd89ad998e" . + "a8a2727880b40a9592d8b935d082e841302cd8b4f0c67cdc8d5e545a1ccd4e87" . + "e7462eb051fd7badcea625894913679ddfa66071a4b1a669f07a0fff4aa10ea8" . + . + "483d89d110c6373a0ff31c133f46dabfb87a236a8039e5a0586a34386c879e63" . + "9a62000be9bc8fac7cf88ab51cac7a72551f94fddcf7d5c2c89924896ad742dd" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c1e7c626dd7d814f6572f1a71bb526e566237965d32398e41972f40ad01e721c" . + "3f7929232d7356290d3da502ab7b3f7718036a4d930c0984077fee71a27256c0" . + "0fc8dccfc0cfb132cd4fb795d0ef5b1fa36d582c2c2d63faf6eabc2c34cd2a24" . + "0e26a83b32e4b1b9f0e912a5d1d39d5b3c9003eb65d7c1953d5e7610eabd10cd" . + . + "4aedca74ea07f284f2aade279abef0e1ff90f4cec27ba8e906ab04a1edbd2807" . + "3836e30a207688ccf94862e70a072ed3133593a77d5a63ad3d265131a8aa71ac" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "bf5aa404c90cc5583cf3a3f24a2c7a8def9e89cbd0830b88ef292f769378879a" . + "4aedca74ea07f284f2aade279abef0e1ff90f4cec27ba8e906ab04a1edbd2807" . + "cacd84b0ce8c7ba9e3fabe6e606728cd704c6378f719bcc96d01ca70ffc8ddd4" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "031b834816014f774d4417bf245a2fffc31315d01d3e3d8890fd08d8a2cae95b" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "a983f4ad689111b98e86ae918e2be2a39a7a5a2b69d8935d63aa337a902eeb6e" . + "7bf42bfd035253f1b0f4e31a5424db8e8666ddc76803b440d3dd782d97acf525" . + . + "8c1424bee9ea6d5c09cdee2225ef9baac3ca6f995749e4d7841e59520dbbd925" . + "fe9358e1dcc93ffe62970fc195691758c6e42c36876dd01c3bb68b817d715e65" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "67528d6aae70cbc1fe7cc740fb3720d13c060f22499148323caaa31ec1670e94" . + "5f1e55ed9e8053d1fb1c79be50892da421e64405b0bbbf54a3ecfa1dae7da1c5" . + "885e602591a2f774af0841fd349f5d2093bdce68d822692d797fdf042d4e328f" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c52362753de3ccf0e56f4451d9f3320d19a66ab57029e91c198097022467622f" . + "f75701893ce1722083bf062f127a524dbb86e3abde5c917831a2f484cdcbd343" . + "bfc9ff1512e61c35915b6e465db1cb6390f47ee26ff337230ecb7769589374fc" . + "737cc4d165b3faef02f66daca9ffcd2b94376e3f5fb3d972c228e110390f6e79" . + . + "5c43412d4b4c7a6bc490f745f2548eb8033f7fba5f5f7f0f18f86e5de78d95fb" . + "023240ef6105a02caf7ad8610b792052df7daae6dac02f44b161c013e28c27d0" . + "de5662745b3ae1aa0bcf056f0033c724a5425551f616a82e8a7571950c33b747" . + "9768e0083ec1a88848d75eb0fe02f30e2cb531f6c3ecb55ccc7fa284236b9efc" . + "e6606fef2b33b7dfb9ce25a7a2bc55ad01bedab74cf0ea048b96f0501592f5bd" . + "88fe71843f052c12b28f7762b69b61293fda441276df2ec5530359bd3e7869c4" . + "193effc886ed73ee6dc911f30a8815948da529952a9f96826fadf2e8f6aeadd8" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2b2cf66a9e9c5f2cf2d3c6b9048cc50dee0cd388c686b84ae482bcebceedeec6" . + "7fb396d993ad2f53edb81938b7ed7ecfaac4bda1cdf7af8bd9ef3804e7d6be5b" . + "910c9274d55d70746d9dc4e73d35d645ca9d4a1d68f12f10dd8450263809591d" . + "9135a4ba474160880eb6b54007a1bc6e971ec0023b2efe92aee34cc2e28938d3" . + . + "2c79f55906f91012599f270579bc4cce6ed8de3bdf2f978a04c0d0a7543d8961" . + "f34aa7a5e9117d1779b9796ba9f85453cf4d21bb45a645c627f110af45e0655a" . + "da7c60928ed0f5ae3751e05a98bfc9f2373630953ab24755715707e2df7b2dbb" . + "5e6daee77afe38e403312690f95be61e774b2da1913bc056ec95d10347b15eea" . + "24d70bd9be9227952924baac11772ffd94bc5bba5088ebd04b51119b2e198ff4" . + "914713aec57f48a4e70dbf0e676fc63e7a85f19ff6420ea674fc4b769d01a6eb" . + "391955044565fff11747ec3c3c98b2b37fd698c777bdd00ac379b5ea4181b2b3" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a3031679a57af718bbe6bf8ffb2c9704b8438c81932ec7bb3b1b36a1c8e9423" . + "68f56a47b78077fd816025a51d3e28278a81a5d94bbd25249bc6d981a81ef0ec" . + "90f5eb67282852378e6008cfbd6f3531a4439d9ea2e168478edc82cc4c5341b7" . + "34dc6a26ed3369dd29bc1ac5bdec6844750b53648b8f379538bb98665fc20fab" . + . + "1b5438f0135a8cccb8d269ea721d1e48f1033ad56d3cb98fc69df74d871f7026" . + "d0c68ca3d707cf4cfd00fd3cbc19f7eef617fd8e0108c0202efaec3d8a52fcfb" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + "2b222450a3cb2a55bd9f7451fdf2f9eaa45075b8925b838acc545f270576951a" . + "7f5083b7f6bbd4e88691e58fe64763dedf568ad5f09166794ab088f525ac27a4" . + "0f68a4b6c33577cc959288ba08e28cd12dfec9923b40e2b00cd0130b76dcf343" . + "d46c2f949cb11ef3bb4812e2afd04155ca333335c180e112d6d7ec2777bfffb7" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d507e93d3514f0b785ef3665af5a019d8072cc4aac7c15f2740138a9a5a70331" . + "4631b01a0fa80d0a825bca4ac4928f646618363068e62786bf211008179a5837" . + "70f24238c26bb15711e3b7d70beb6329363275c66f8f5c49592943db784de4f5" . + "0ef580eb86bf3aa35151ed94eda0cc7fd7f782023493f581f9836660bc7dcb66" . + . + "7d0174fc306a63689f0918bebce26a072cb5844633b518f8d1f24cd11b3b8401" . + "f0f918342e1d5dc4bd025906c49ab753fd80d34e21edca43fe1b003e30c0d4cf" . + "ea388de3ef832b4e55efa33634dc963f0b54bf1f4eb20da73107a309ef1abe9f" . + "5694b41b18a3e3ecb8f046da5890a4790898f9cdd61d777901bd421ffe6c6588" . + . + . + "7d0174fc306a63689f0918bebce26a072cb5844633b518f8d1f24cd11b3b8401" . + "edd8f67f8273d7aa06b13e2e4488e9dd8d8d6b81586fc074e3fd821d892696fa" . + "e40ff634bab33e83e09182f53beaa85ece83bcc2b54090566f20f41791836492" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e75731385af5393f06351c8d7cdb339324c90dc6dcb7d386b5d9c853641ab258" . + "8b88613fe892720c7c76ab29cbc09692cf996e8e25b0b508750a4d48a8189889" . + "1744ffd70040f3a4540e83604e48ec0053784e1c5b49d63bfdb7ee0227354e29" . + "96cbb209b19db4144618d6b3c70ac3938f683dd266729857584a220e82ad0d46" . + . + "c1e1890d11783a57f2fc24ab3926dc878cfcd89db62259d0565a1e7c178ca994" . + "4f0cd6e2681e9964a6c2cb7a66e6c83da93ce6c79bca198165eb001b87b83fe6" . + "1b8cf2ba37092a442491ed70e22da1ed06a2f7c13ca44b279bcef042db32dcdc" . + "1fcf4e2803cd0420c0e8c69f3476077039d4b99642f411a70c59f1884c30233b" . + "c491a2f44b779c1cb47d13f5167cb91d8ee6033fe235acac4eeb7b8bd9d34b47" . + "e50dc62d9fee0ae12a51a9e63fd5c4640c37f1b75c631cf44f068d0d3ae900f3" . + "dd33affa8a41dc7e7cf6e5141256e14c40928436b9dc4907d9e6ad0bcdbeefe4" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8ea3f4fdc83b49b7fffad7f6a8da259c5134d128dc5c3fe9841dc74af19625f2" . + "c9f9d6669fa548d8ea08c979426b88ce75c752fc8c720eed640332ae3f1be09d" . + "9d9fe0e2cc53c425768250d36440342f63194f5206f1df56cbe2f8075cc25fb4" . + "dca27afbbc020556e54898680be7fee099c563d92a0dc5941a06bd9980fa72e6" . + . + "67ed45c5f93ee8b2246b20b1f76ae53ebde18f23aecd1eebffaa373e251e08fe" . + "c27bd2a226528114b4b3a9c9c1f026910d3f1aad7bf2e88a1b94c80e07f92d2d" . + "bd63b9de7d7dc16e75f04b81902c807cd7731f8e743031b6aa11e2462e7365bd" . + "dcd5ead43054e3f1ee4b8b12a46f9def588c67123153de2d3fb830397809ab74" . + "2de1d565bc5361f660f72fcd570cab736fc68c9b85c8094ddbf550ee6b1ded4a" . + "214d671a1b2a82293dd18824e156aac3489e1a99cbad4aba98f444e9ad7d994f" . + "5c194eddc1f3182f39b49ecf1a55f6dcc52b59fb2086a2909e88432c3918c300" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7a8265f35b014411066e6aade98b776e916d53bfed767424dc82af06d1192eb0" . + "6c9edd06cdf866334f65fc6df6ff01662fd82b72174bb3c3f5a108a332c38413" . + "f64e9af89043a26acac08df167656fcd410eaac65868aeb6ca89c08e5f27dc96" . + "008cb7931394cc6935f34ed0b51432ef6517d710449582ef7ee3c6040c5043e9" . + . + "fb1d9fb2966f04f054a29659ae7ecd2505a48e452cefda52fdf9748505dfc1e5" . + "3df95a927d9770dde995b2afa5bd3bcc4f59f0b900c612af31de1e0bde888152" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "49c33c744b6f97de00a3c01f12563e405bbb0cde2367ee0288a4dc96cd3e705a" . + "9edf30592d6f1d3e3ef3b93c13eef55d16d109bec416ad8804f0569c9c9b85c3" . + "b3d4bbb695015c46907ee9f3eb4b820b9cb76f5c77199907a2e6ab9ff7faf47c" . + "949486cdc02a553c218ea114274a9e9d336d0c4010214638c24e20620fde25d9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44fa1e506fa3d7f171dd40b018ae033a4bc400060b281fac39c6d6e021d10335" . + "0d58a6c752bace76104f66e38abee9c11cf8a6c098a725d53913e76b2a595197" . + "cb7edd1e46004725790608a69f7f348e2ccf6d790c857a73dccc51c110559377" . + "93d6a54ddf016abec295391fd0e75368bd97d8be0151177a7759e300002f241a" . + . + "f82c53ccde4a6ce5cd5abc973eb6eed5f618314142b331bd783fddbf61ead58d" . + "0678cd0b57cf47f2c26eb802cf97fd21764f75d04408cca9d5d3c380c96cb011" . + "9a8b5fac2c52e43b83390210c1fc4ff65f95314b749d28efb5c4f2be02739fcd" . + "85955bb27eb52947d1de5a00d6c7f3a3418cfd646851ea6308a3c86ae4001b54" . + "955b9055b1ec01ace3c5c6dbe4b24c3c3cf1e2d4be7678f6907d65097f569e4c" . + "597fdce2836aa5b7231f5a2331dc9a4ef520fb1ff42a5f17c11fbe560b4d7e5e" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2bdc6c94f22ee48a54bee06fd715c12018bec5e5abacfc30589d14139e39a3c3" . + "f14926c6a6c11be3ea244d39c8af793312ce9e4b2f639210740528b18edfc619" . + "ea881f9bb1a84bd85ff78aa18f98b255c9b3fa2a494285cb3188a493d6b6f218" . + "1fb0c8ab61b05d2baeb9397caec9d9884284293ea68c9cb5501e02de533e45b2" . + . + "2783a7e2887f156d369c5768d450a250fa41f3b637e675104c4a59adf26711e4" . + "3a466ea30c670ecd7a458149145e627e78a3fd078d23924678f26bdfa0077789" . + "547cd28e9372fcac15f9fe093e075b6d00f0fff658185aafd3fa788fe5e7b780" . + "10ac3e2860f6d273af7abbe5a5a3b106fca5c83ba3a9e124c2dd54fa62bf762f" . + . + "3aa6247d5216dd513617418249bc1210819d56a2215a8f23af60046862527503" . + "5c085141926199a9de98da2dec8e1b8d32ec0753f53f2a8d4234f537498ac76c" . + "27d01464313761a25675f4e6b30804ca720a208100f5eaf669ca55babc94b8a7" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1291b9d63bf64299004da16f551e954c63e00897e81cc083b0f430a01887ac60" . + "769800f6a7836bf513b64c63fd9bdd8364027d75b3dd07cbb44bc77599c407f6" . + "b9725eb5698e47ffa92ab56add50e86aac44e87828c13f6919ad9de742b00084" . + "56ba12bb0a7c291319d887896bc72c9e9e6b5a58a0188dd9cdd9946fd8fccbd0" . + . + "4e3ea321e823364ef6d9e39204eaa9b3fcf8efb7b8a1cfe2a5cb5dded8fee49e" . + "65b08cfbbed668aeebb5e12f274bb5bdc6f9ee5ced6cbd10c061ce5718e222f2" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "995208541b6f1675b2e6e876764a2ff8133babe10c7e6b4213aa833c17d00aff" . + "368cb030b4871bb9b928f0df94b0177094bd83b714517a012b1c4c4c9bfb5458" . + "c39d4378141bbeb00d12c6ed28b2c9df65760f92506f38eac8921084e9fa9853" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "260bef0b59ff6cbdd290b83130a6a56b0999a04c9c7176c69faeddfa99eda5f3" . + "70ef2e30db0b07e0b29d691839863cbd241ecf28521e50e0b7bf637a61bc7a9e" . + "d7794ada3ea8df62fa9c5f7e8fcd3b084dcd6eea35fe9a3fce438fc38985fef9" . + "3199df55e4350e0151194847ba627da9a58cdd7a9d688d61a77dfe5b349704d4" . + . + "262ad985a2c8cceb4ccdbf4ef46ba58a069fedd080c3d73de3b95e608ec16dee" . + "6e558128ea39c2ca9198dc9ef8eac67b946432912595bb1b7be42673c3821b43" . + "944cf39c20bdb22fac82470133008a98c0507659cb3ef8b3744bf09ecb974e2d" . + "b5fc3b5ec044fc79deba86c5167b150700453987203779e46a669839f893479e" . + . + . + "3aee83f6328b62eb2dfa8802636b7c82d2422af5d40f985a2ecbda08129bd52b" . + "0df2f18d10f20c1df95222a923902540728ba4a4a54f0b4edd73330b93890a60" . + "60349bef3326e640ca730c31a320b4dabb6cc5b842d48212f4448785dde72035" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4111cf8fd659394d1979a300046be15d5fe796d8c1e50aa2ca9d10722b035760" . + "beeba8df5dac59a45706bee09c1b3781e0b97976de1905fabe6adf8035e3ad3d" . + "8a14db07b269cb71e0baf12c43fdda6ad591c15c257ff451167d99576f109bf7" . + "ed2e54a16119e8b545dd980fd7c22e8aceede787c0d3bb09e045263d297a30e5" . + . + "ca3317cdab9ff0029762504d326397fdb3ab5ecfffbcef6794fc70eb2cd7d0ec" . + "61267d3dbe706d34e40852d87f784d44aa09c55a00fe6dc389a6d29b0b2879bb" . + "045daa014617aab6d64110a83080c52c62f2c8b025e7a6607942253819a8eae4" . + "e400df8c78355fb1a97e2dcdde48d777e5c07af8caebf24cd2a28271805e60d6" . + "79cfb1ee39639b66e3e1ff9f3540f2b0a98428feddaad0209556c715ef643d74" . + "1fcb486db0be86262b0bb22e23ef7cfec62304481bf31530c9c2998177773779" . + "e5e7f001dd2b273f9075393795f712d70dfe260e29d730775c51ae4f3880e880" . + "6cfd1cf48c9bae2d0222907f413c01f8d99a601efd487292b49691ce7043e521" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9abc7e327b3396a10e29e2a49e9c5fa4d89d0163e883591f77ce381b66cfc4c4" . + "5ee5099e7e3197d4153fd1f4627731f4f74811ac60f59f4647de6106def5bdd0" . + "1cbdb529e96def1205dbfb5182018042b269abee117ff2632409cb6c7276afc9" . + "f5d7f5bc60aa78dd3771888cab8eb1f7db684d7255367b3887cc151227c4bdf5" . + . + "801c98b5830c89ab3fff9e2e592cb731c68358b57c086454cfcd74f1682cb90b" . + "002eceb3d69ad6abb9b511fafec76a510c093ecf4f61dc84fc9af901374fe925" . + "c642cbe7224447b157b496b6eed5d08cb37b77d59c0447dd0336360d281592fe" . + "28b3e7b35b0a485e82c6d2d01971e097716c17f75bdbc351120cd5ae214ec814" . + "c5d1952972ab1daf10a0081db08dd16cb30f5168a319abe33e406780bc4136a1" . + "8afe078f8d11679a52ab14a54944349c7c52b41395b320e91b70b5ba0dae3e97" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "395f972b5a1ee4abeb8d3c3f110fc38e5bf226d7d150739ee16ace56cc44889b" . + "4ab030f3fa60582dcb2b1c0c3ea29f8817f76bf762e3b89a9f0bf4f3f8cb80bd" . + "2c9aef3be6ae65cc212a0d62b79d26c37d005a275e5592b73c2d54c0584d3892" . + "4fb55874134422396291d9a1d42f3d0109c8a963ab884268d3fd2b68aa381dda" . + . + "f1dd3b457b3a0a18485f89420b8341af5ab4017d7eadec4d7667ad172eb9aa7c" . + "8fe393f18a7d03ad68bc23e9de0e92fd62ec8b9ff62402b4a0aafec74052f27d" . + "5fc91fa3fdaf46f406a9777c75eed41c69ce8719a1dd6ec1fe35c2f4f6a938f2" . + "fdcdb6904edcbcc0310356a73287499c6b95d26010e436d8da68562094d3dce2" . + "02a5c5683074cd99df904fef8439e55c887f72d4ea4701bcc7a36109bb1c2d48" . + "125c2d2e21bdf77e4b361a31137b81de614aa374299c76685f562376ca5574eb" . + "329c2576ceb13969f2ed06679b878e7a72c313d3a7eac562b7f2db7b4cf3825c" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7cb4c23c55aa7d9bfbca530e38eb02e3e1674b8aef517e5dd2f28364c9f29173" . + "7f881b20fbe2bf30e3977a0d2f377b247fc0d4d119cc635b569cb240aedd93ad" . + "1c9e5dd7f3eca8ce7a197224f7c6ea0c99a31d599191ecfe675ea0ea439120e9" . + "3aec60234bc7fd5ada42c80acd9b812d476952edccc68dcdb8b034f16f460cc1" . + . + "175ba94b22960f91c1595cbc2cdac58364f14efb6e919da36bf42b7aa4a1b7ae" . + "39b895b5900c0aa8ac23739fd98ddf97dd02bf687532a2ed1caa3a42c02d9b73" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "3aae6587d2f96546a4fe53b732686162280707aebf986018a5761cd0f244626a" . + "74297d1544703954e5241af3b2bc73cca998294fc52eb1dbd7ca9a249f24a74b" . + "763fadf89ae63d9b727778491030a3673d03f18dbe42a6c0f659190a57c4bf59" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "01c9a3019db3f4ee49320992cb523741726a221c4a1466fb62cd2bfc08c9ab3d" . + "40d932df0af06dfe520d57c5e9b9f717b869f12fa8ea3941c154105c0b10ef37" . + "f3a8c5d3e152e623a6d176511e9bb2abe5d89f20850a887df27b78c57c05ff98" . + "60926d39ce8b465e6b048f9e4f1abb417df4b0d4f759f97441970925e2621c48" . + . + "c7b61d59f7d848219585f079f18aed9d605557d7ebacacf132deca2d51930848" . + "fbc54c23f0cf82713fc693ea0d245f430bd734a597db2f1272a610125a6f456c" . + "cc8dc4d67f20fd1942aaa61b1a26cce8d511e697cb8f7680f65b572fab9c1c92" . + "ccabfadd4498eaa1c9518b7c1f87217fa5f27861339ed1eb84f201d9deb213c0" . + "b7e0dcf187498e1a14c112a7a437f957b9d6800a248af425786f2b8e6c5b0ab6" . + "d7e49cf5d83a331771949fa81ea1d585c072e973949ff3877eca2b9593c1deb2" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1139503dc70172a8a40186ceca0447e1571f391ab92ee458c4173e5c501f5c29" . + "4ad0effc1620c57aeaa6ff039ac827490d8c8b248e07aee4e7d341d5c478777d" . + "73fa784aeab2b63f4ebc813e0817c823ef0c076dc9bb6c8324c94f8d6d4cf471" . + "05772f50cdb3886fe80fca4774c67e175438ed46c1e9fdc6a9a534cb7b0ba2fd" . + . + "efce7f6cb5694e33996d62485d996dc5aa1691045b85519da23bcf8434b135d1" . + "7d511312dde24f6d1386ed99210a3c0083d1743564e8230d0ad52b83386e83a1" . + "8b2c6bf4866c27cf068ccc8f52107c06b79d66cb53801b7c51b6e282ac439426" . + "0acbf2d73483a740cc3db137820fa72b01936b5f00deb9016e316e54fb933b67" . + . + . + "c72e9a6cad7d19f8109a559d609c088df32c6c8eb3d2630f91fea90e8881d27f" . + "b4d9ef37fa809514d9a3b9fdb82544a33b5db0283f0f0d1ec0baeae43e6c6104" . + "8891ce494da277ad8d2528d704b9cfc82bae5a10363836f2e1dce58f35d79618" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7beabaf30a8772a19e452c045801ec590f43316e90a38511147c03bed5b915e" . + "17eda503e49d59284bdcccee294561cfd081d1e507cb7269cae984051f3784bd" . + "a6e7f314a96a1d340894e9806105d2c96b59df1ca77cfcca6041d36d505adb58" . + "e6d13eea4e7b8bd9b256dc5cd85fa19e0f80ccc0dfe99ee34ce5eace3ccd2f0e" . + . + "a15bf491caff99beae8736a9029424e5c1bb0bd76b8d4bd0a3464ef411957e7b" . + "bdb49bf2e149617a2752023fdd113804078db98ac21c2ad50fc9f305e0bdb9b3" . + "f89072e789198119af60f67da4496b6b7d6e5c1a733583e989ea9d4d2cc14c70" . + "4ab030f3fa60582dcb2b1c0c3ea29f8817f76bf762e3b89a9f0bf4f3f8cb80bd" . + . + "6ba3d48fcd12d4342fbc4d0edfc8981375ae9efb509e6772bd99df4b9d90357c" . + "e84c67744c8eec8e209a9d0c8f250d43eb6382f50e6db79bf69096f852c53de1" . + "47ffe97c9e345a52abb453e524c91eeef3cea3407d85f7ae6dc6cf847e1910e8" . + "92c28fbfb617f8be48835b67ff75cde2dec058dc6d784121c0732fd5e0f7bff4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "febf73b58a5a04ca7f4bddcdd9a5bde7d8a830722e0a64c448519d3f6b8d4a07" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "dfaa7dd35d1cf42286d1d5eb4da9e3497abe6e5381bba2f35bc4b7c8d1b93ce1" . + "ef448e6823b7753fcc2e02ac9206fe1ad29a093cc0c4c3581f7dd23b4faacec3" . + . + "8242121bddc577fbf05ce6da402935a726e3d0ae8cd0b00e04f27446233a6f3e" . + "557641b28e5a331d6e85a10eedd1278bc9a61b7cbf65846bbd6f7d3de9f0307b" . + "594a2dc9bcfc327fb74c5ff329debe77fcc2464c7d2a9bbc2f94b2656f46c4be" . + "bd4f3b315b8e7f0f0fd2cd2486b1b67004d8f12133141b6ee1f21c4a8f474ca0" . + . + . + "116a6a0bb39d449c1cef943cf242b58e61cf82d204abfe12421ec2f59d1c18a0" . + "c36c283bca66af4de2dba4aca657738305c44e23904dd3bea5fb631a2028687e" . + "3bbe71f60356e7c417862638372c0b76c0d874e11c77dec4cbfbd86803d97eff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7dc453648decdf3e5ba6703e35d437242ded1694d08ed48f9ab7c6e3f3783fc" . + "b190b6e87f035d5bd8406daa2b814882997d9226f511df963fa3ce11531629d5" . + "54304f296feca0a283e2b607f2d520ab0d9588d7794c92c473f1be81f2e48161" . + "0f7ada96bdbd661dd4eb58566ad084ced3ce2934a0f05e88781e15037dc47fdf" . + . + "676a8790204bf74db030d65daae66afd4d04d7bd315749ffecedb75abdfa71bf" . + "1b289a3456d98d8f824075aade7b47e528da0ebc78bc7a30a5ed58dbea29d8c2" . + "57e476262d6a5e92c2cdd09b246cc1d013da4fc731efb1ba18f5a9db3832c8bd" . + "3300866e7cf632375aba746630824088e938bd6dd3b78c033c07e8123de9cb46" . + "cc69b6849b9835bb264ce2ec00d92b97f5b09a98fcf7417e5dd4973f6ef93f8d" . + "bfd6ee09752cd445904ee5868d5f1e255267fb1217c0be8d251376ba9f8302ba" . + "fe4065160205e617317ce317a86b044ca4476471b4c4ad912e5ec30604a42b70" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fd687f60d404e167c15d0858f12a3cafa0f8955e379e2cf9e80cf33cced8dc12" . + "88ec9634a7a54b17a7e612b852fe8bfc60932f621b3923e5bb576d61136467fc" . + "76524a9696514ce5849fa1e125e2c89d3edfc5d9aa21b8472528965c39da4977" . + "b53b57575f1f3fd87cd911cfcae3a68fc7d474044d306b98cdf619ab5a979906" . + . + "f9792a69f1b77f0a6ddc69cb398d0ffea4e4a3f10a399f2d2574bf7050f86299" . + "b43ed8392003ef4531abd4f0e584e020932e859c104efed3b000aa85255db6d0" . + "9429a124933dd7b20fd9f88474afda11067c580ddfbb38b286573859a3e17a52" . + "f039000993cc05fea6752e906fd88782dbb9c1da5675686359303918a26d32a2" . + . + . + . + . + . + . + . + "6c40ebf558c97a6407504ecb83972f1b04dbd6c076eb112f000bdb275b6c216d" . + "55298c30d98b3be54f29d7208d5031d72a07fe3312902aaacad542b6c862e4dd" . + "304d5f905a0495e9008776f8e75a9f0320910e58d3e94c75143e650b2f3f619c" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "644c9268e7a26edaeed128a2fa2b02ecf5d4c2a7eb10531828943c2b7ff3048e" . + "6a7153e352452d9fea0716af42959ef77a9171b02b98af48b76c0ba9a49a4c10" . + "7e8d93f5d503601f017d71ed9b57cd18595153def1a59e6884294c2c0afc1007" . + "ef66dfa1dd37640f8ad01eff9ed4e59369a9f09efbb01955b00605ae60f8f3d9" . + . + "245c98f8860185812e069b341e46a20ff5c603b0a3b602dc790baa9f2c14fcf7" . + "bdfee344cc42a26cc6fbfe649a2d6290ed64a5ffc610789042ef1ee7710dbcf8" . + "17b92a1db208a45b4f9d06dc3da3cbd74025cbe92ab8e3e826244fca9f7d8a8b" . + "3307833424b98d4f253916f98dac728881976092f60dcdbe768dab52918fc9d4" . + "1338a60ef042f1a5a2374602ffee9a0901facb55943fe6bc27382ce5a989632b" . + "05f31f1c8f6f86c54bed654829b3bd3f1099fd1a499dfd830d9d0cd32da437af" . + "5615fbbd3f75077ca4da2786a794bd18d1fa3a58daf06ada11e7dc689fdd75a5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a2850225d7f6b258dfb6a8c645f47c0a484751f2b0d0627b6a7d489a0023bcca" . + "1512b655c585bf9e844ffbe620da30e4189e9db710a745030c1daf7007c12bfa" . + "9a5ef7382db5c485a8dc5acbad6076f12767c3b697a2b4738bad145c735d6e71" . + "83b273fe40dcc72fe403459371f8eb422f5ddf0cb46390c53726e6eb115ee2c7" . + . + "92da3d5c37308d64dc3fa8d4ffa3c6925f700e44c9ee153c3e0797c6128cb6cb" . + "0ef1c5898f63f2e8b5ad59317c0b3dd71985c0b7a87e1785856f1a692a28fbea" . + "c759b624f13fb436160b8f1096bfb4f687cc00f94430de2aa9f0a67a276eebf3" . + "ef31a8a6e3d4a684d1272a5ee8c1af1a6beba1eda12d1048ba5e6af92a75c0ab" . + "5bfb0d6d8edc6c605ee3b47d7b928f74d92b0dca05d454949c78c6199f33d133" . + "484bc41e3dc80a104e87e51db34190c79f380467c9d8f77810e507b5c3a25601" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9786ef8ed0b4a17d5306df3f77a69d120586a74811e03a6af62b5572e4ff3683" . + "37e430462e33b498a4b08311ef6ce6525b07c7fbdb71c164734a13b644a85682" . + "2cfb9916cf77a0f03c3e2473503f7ba15a5d987187840a8bd6304300397ac66d" . + "83ed127bdd9a0ebdedeb111cc0a29d20b6a878c0cbd4761d97b6500dc9e80982" . + . + "d6bd39c0120fe0f6413f67ba573c2f2646ec5fac437111d4eb22f9b60e6fb27e" . + "a7e1c6ea13722322b897909ee7ef06cccee0dca5226e4cd1378a427dcc1e6dba" . + "2a32631b0ee9103a1288ac279d597837beff6c51b219c71da6db5a569cae1065" . + "599ac20888db63fbdffeac630eb7c2d8c79e44370a330bf2035cf25c5f378eaa" . + "3184c21227385fd2dc7a6cccfd24a2d41d1e9c581aee0a4407120caeb150f4c6" . + "81b8c711caedcb0db7059b1c8a63350e41f05fbf9a55fdd9896e9095fcc287bd" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0f8a6659bf28418fdc3e2802c4c46ec6ec74ccb1e34791da14a9258501bc09c" . + "b41adcace24346d40e3cbc0ce6248e9bac73a8922b359d97fa1367b5384f0e81" . + "1812a1c6823a196697cd2a1741915ed2afcc2fd43cfd51217e895fe66656b71d" . + "e6e24cbad537135c4caa16ac9ceedeb75ea772d5c28b5f2b9f7a3fd0491d88bd" . + . + "c55cf94dc8889cbed819272bd06d377db382fd5a593ea0dd3002cf1890d0cf0c" . + "7f525ab3e7b839eaa4ffddc92d78b1a9e2e4f2a39ea92f69dcbba290e0e0794a" . + "8e44cfaa19551211cd4eff6cae9d0af0804a81f5069c7bd665e5b1d110802e2e" . + "a9790d5292228118ef48d781fd01893203b46e9c3ad61426f39fa944d1bd8b92" . + "b58fc41f97a055efdf857cadefcc868991e339a93c21a8976359421b37a2d03d" . + "0ac070a7a67f342867e6a510705d7fd4ad0b880d853a959b339f339252f62f90" . + "60b5a8e544653be6ac8b6e3ce998d825f1a5bc4b197a569007c3bc0c97d05322" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fa26eaa071642c51fe5dd4077bc1a6e07c8e98abbf82b18e2dedc9bb798a61d4" . + "2db6d9554d7707c5ccfaf9c977d9925417dd52c20839c270698e589998040049" . + "1c78b566ff6988daf940ae820d9403b35c48aac30a46eabd90f6cec2a56348f4" . + "7495539cc82245f0773919a4c18b41133b76a033f8be01a110aae3636da0e375" . + . + "941579ccc4b7d7dd425d35a307221428b8883867f2ba071b8f9f22b4e1b956a8" . + "acb0ec1e7dcb62a34e7cbcde33482486c9185054877f0e23879e64a9c91a3292" . + "6a7153e352452d9fea0716af42959ef77a9171b02b98af48b76c0ba9a49a4c10" . + "b3fb1a095aa904a1f2b7f98510feb7e6153b7093b4d8c80291caacf4b618a193" . + "bcd12605ba108380b7791de28a1ee78fac49e6719d722622f0f62ac75bdc2f7c" . + "0a33432c4816de1492c1d1cb471cdc5029292beca8e5b0366b0522d1a457832b" . + "3bbe71f60356e7c417862638372c0b76c0d874e11c77dec4cbfbd86803d97eff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dd0baf14797ecd5ed004fe577241fa76c72765e54fcae2914b5c1f59cf392721" . + "eae0442e17b89fc05567496611debb81841a9550fe1d9d818552cffd30072f68" . + "c3e31069d2936c04bf08998c4081750b61e73cce8aa088ded7877f9124210505" . + "133690202181298f6a2d10f2221f1fb47593df266c3c17b92a588bd539c40628" . + . + "fa103b2e56cd3955cf454afed3a810b05edaac1bb038ab203c78d138625b9c11" . + "b48fb1638b32bc4a8d32c26a77380c6b41471d33e0d35cac11ee8e6529074603" . + "2f8cb696e7b4c50b3dba54c7c0f297b7ab3605233d5e4c0f8a18fc24c755e9a7" . + "95fef341fffcdad725194dcb993b507bd81af2568859bc29468186c4f67d435e" . + "b1867f77ebeb25f0f186694dc32e6063e01e5bcd5d3137bd3a3929e85ae9c6bd" . + "09ad963a00b32bc5d167b76f62a8f2c54b0792fd40cc2059e5b7034bd65730cc" . + "82932ddce217e2199c3cd9ba126ab94c5a0bca7f820ad501ad2f39d4dd9d90cd" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5f1bfe2658a9af19b80456f91d0072e368b4e8de448d434ea9b45873a9729602" . + "55e10e2979c154a96633112dc80eb1225f656f9ed65ae502c6689543061c3152" . + "d128cfccb1220eb1041f92cbba96da2dd918ec39bc9234377c5660b65e484115" . + "59935d8abcbe4d560bfbe9e3e971fbedc6c86adc6f312c88f796d950ef02e388" . + . + "185c092c3369388cbb40d144082ba959cf479b7975e10532963f22fc676f029f" . + "8df18bc8f4dc8ee0802fdd7ba291f39b57cee9d3e1d35e1ce4fee85ebaf16956" . + "06552071ea6a5f8efa252ffa62545c82c4236d502e35a8b372ed6cac136b7f28" . + "7db3a15edc097f49a0a80bf5236993b86c684f50054bba9c92fc69145c92a872" . + "4e19e1966ebfb73ec13117d3357c7f8730df2611f2a16649e4667253d0533b77" . + "bf430e32ccb548de0303ca846fab3f68865db6ff5596897e1cca5b64d7aedc9e" . + "608585738998e6cd5755ca55074d66e8f61179a95af217a67c377adf5c7c001d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7026d3a0d6a7150117129d36e4768dce491740936fa52b8b35badd6b07781f93" . + "edffb34810561c4e597762b62c415d7a41d8f0b2bf792f6ed9c3dff261c85800" . + "8e045dc8e65aa3e7dfc058b296ef49cf917d87be4a92635d2378c7d810695087" . + "c06e377fb48c201f1a8855652ecd7bc440d2756ded0231bf57ecaac1fef58d60" . + . + "7bd113be439037447be2b1c8da146b968ed78a63acffe5e7100b277552f8189d" . + "7c187808e8fe33786f5775653bd5becb3f6d26fb9780f0b8ae10b5418e4e0266" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "e0921e1910dbfe7c3c7bfa1ed4df3fc217a678177154bf2ba423c04f85dbedc3" . + "c4d7d9ae2d92ecce1c09bd8575f87125ce1959e55542a1c90ea9e34f447d8bc7" . + "cac8ba3273034712e6b5f1c1e8be0a684024531c8dc016a3bf76d1ef93d1ef64" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc9e41f58a8e46862db7a852e933f0ce0df7945b9523171b327a2e1ef04e98c3" . + "2d960e5c1d4c01d169547374ae83d975e9212c5b23e64db0504f36c8367a7cb5" . + "2c7a21050e250f00d00977b0768e0b4893d23ab95b03af7339de6288027bc087" . + "8ae642206bfcc0b39672270b12c3116a5d16447d072e669127a98cc0b072048b" . + . + "20af2e875c28723044f78edfc66b46c5ce4b90370184af522992d3ff0ef7281f" . + "2b55347c3cd7cb3b2eefff443167852e8827c140a211f315a729acaa2dbe96f1" . + "69a2077960df86512555e22aef48d93174665e73d9e49f7cc077347ab7a9407d" . + "e0862bcdd1381bc01820ab8e34c796b7abd5d6fbeae40025351a3df3db478b95" . + "33a302a28801e12eceb4fe287d1c6254863f356e803da0c6e35c8e6ce26ee0db" . + "1b3291d4f8faa4b4c4a8535350996c0ce1a5a3b5c7f32f29fcc9b6edc5f44f3e" . + "66425ff80138771c2aa5a598c4e86dce73ee3c5484eb447deaa2fca8a3cc54ae" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "38be3f699892dbcb020144acff33cf3e2a3e9e069a87e87b68f063010c662812" . + "f2cb357af24c13ff8bcb8197b4dcbef4c666c706418a80aa5dd68159e9157e6f" . + "7e739e2270711a0974602f1315d55bfea779b24d2c6f10131b5d9526ddd7ed6f" . + "e127369c6bd9a47ed99b32fb70fc7336bb7bbf67a3f6f7f4628e417a63dcb528" . + . + "41d306f92facd1bff714fa76439c7204747ca39ca7745bee751c19429957ae6e" . + "5308e14a06df78ada56c12ba8585a42fa37883557294daab60c065b7ea0ec003" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "12778af8c8ccddd423e6aedf916b1f79eac87cba3cac76008ccacc38e6a00485" . + "aa1868d41346884881ecd8676b18e0b8bc298c67c89bd783f33f3ccb2c282bee" . + "60c3855c8b3b374e6148bd6e4a288128a4659180b936ede4d5c80e56b20c9900" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "25c2049123bbc8eaf3a5de5a61b288e7a4e71a1c6f3883bb0a4d89430d24545e" . + "e9050fdba47ffeb9dacfe7692af10ebb29bf689aac1b19acdbfbf2c5269437ea" . + "068b7256c0c235aaedf02a6a69d1855ba71d91976fc2afff1f6810b800af8399" . + "0fd67a29f9a5737851be8d3cbe89affc3564ae5e561383f0d66573f1ba2927e7" . + . + "c661b0a9b297cef4e1f2d32ddf1e70bcb28a5a1414a099ac5fb49e32139a928a" . + "6804fa9f19f5eb4e0ed2bf9ee8414fbc19dd1b127ce74a059d08a8590b129fd1" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "112ebbe930d8923b57cfdd2c649aa194a403ca6db0561c7d4bf69452cc4a4e20" . + "0d4bd8a883b460754fc5a859c84a3b1a2710d69d3fb2d63769fa69f750579c16" . + "5e2c2d380dbff2090abc09db12defdf50329004652b3adc8a91465aefe447dac" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0a059ab7b5028e0808fec67592028c616e62c118a3f91712291f9f886ea5081" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "d9a00dfef926c70c4fa4cd08b9affa600709dc84fb7b0319c72e3be09886c853" . + "dd4c9c4bb71d0fa25ab1796c6958f244e48e49843fc1d1509ecb840beb046f72" . + . + "dc49b5ccb6644fbd14dd462a0944f19dafa8785595fd696871eecce92511cd63" . + "c71d293d5760eccd569eb3ee81035b5035367357ca55b8382790c8e0e3710f7c" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "bf4ff78b10880659ef94195ab9a6972c5146a9a52c8be2158bc9ad57cce002da" . + "07faee744f0a80567cf8c7e1b9bc156049b6efd587322a9600e24551a52c2530" . + "5c79e701addb4270e8111aeba5cb0350107cb93b736208f3fe6bfbbe5a0d6c39" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1eae9dabf62c746c53d8ee995f2efcfd12bfc3614b44b13607d9768e22777514" . + "18af155413776f483a491c6deda34523126b33c7a41f3d6edbf16c8f57a149d7" . + "3be698bc5d9de9c28b5ff3f3b4f325d45a0fa8ff0614329f3196575d01f14ad1" . + "84a55695bdd44a26a6bc4ea0f318edde04f8f11032c28a0d4c0d82c72e0a12d7" . + . + "f4a71234555ad3547af8d8bdb91446db506b953554941d42c1adaf016729e2e8" . + "8cf62c33bbe807e1437b3287107144ecb4b15bab2fb1f9036097f2a0eab8084b" . + "968259ab436feab20f9afaded8992503c43f8f4d17c6fd0006d3761bac267de5" . + "60030e450906e95f0f20af0a0433338472cf2f31460348b0e82bda378d156c40" . + . + "3444e3b817e892a9016516627da7ae62c69335298c3c2aca771f40d42bf6ab20" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5d7a8163fe6e7ec5bfc3214b7557892c063a5d9d44931354fd62530cad07ce55" . + "8b88613fe892720c7c76ab29cbc09692cf996e8e25b0b508750a4d48a8189889" . + "8320aeac8b5466b4cacba6172815505562f3eb2edff27297183221cd52ddeb9d" . + "12020dc21de802c6ae30691b02303dbe6b515c9fee315c15c7f4c63869e6d58d" . + . + "950e9f4dcd2a06d48872389c98a406477488c1e4b52c5b4d73ae35ae8fd253bf" . + "be5f8a0a6d60efd98a1a5335f8a2c4f2fca494be46cec55a70f1f54759e3c3a8" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "e2db02bbab2fb07af33462db21b34eeb874ac050287231ce151ef82040154412" . + "5870a9b3654d4418442c3bc6ed60346893848dca26fe1428fe78b2ce57422099" . + "e5538e37ce823e42a9a9b835e0c10a5f90a12df01c2a88f5a5f5798430a0b9c1" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "76a9093232fd41e69305bb7239238a8897468d3cca73d87a034aa411bafabd9e" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "d4e7c9174fdc29f7c69779e47b00f067d2d9a548a7c0d3db0e46b63c3bd711de" . + "cebb2a23f672adbfdf126d4f3e0c5db35ee026de98953de07c1984a9cdfc356b" . + . + "8d63114a586eb4bdf4bece8b5ab052c51ae17f86a744cd93004c66e0a6c3d216" . + "75c0d82c7b384f7c09489b54d6e49b26c4fa11c5b739174e7d52487a406dc7f7" . + "bf4ff78b10880659ef94195ab9a6972c5146a9a52c8be2158bc9ad57cce002da" . + "e79736ad3242441a9d24c68dbfff75f37baa7c19b7ef5ebc5f8bce61ff196dfd" . + "018e28945c6df5ed6aa57219e4a1c5a23fbaf106fbb72fe4617eb7bd6fae25b0" . + "b524d456e46fe61ed4ccf732961185e324618e0c9c84687086328a969b445a02" . + "bc82427d55908b497666f21ae28d903a9f4641c62e433b7f2064352a5dae5d61" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b1ddddd0bb61699bbe96673521563ad909a7d5af2a031997accf8781d0b3d0c2" . + "7dd2b19a8e2ae86284e6aaad1050d230b8239b234d0abf862edb711c29b6e24a" . + "63c9436f337c126b4677b37ece0ab067339ccec7e3f9f909e0c66008cb092f62" . + "cab3b7e27458e9e2f6952cc7691d6e78df2f70eec53b1bd7e892ab288d392292" . + . + "6ae95fce475c6f52c888404a0fbbe71ab7eaeaeca32ae3b9752b9607c18fff67" . + "0132d6e9395f1b9254ba5a3df1d715ce2e28bafdbc1ad50343519fb6aaf5d49c" . + "bf4ff78b10880659ef94195ab9a6972c5146a9a52c8be2158bc9ad57cce002da" . + "4d6b1845431991a74c43855cd191290ce722f1b26f1e0e385d38bdcad09acae4" . + "4bdea30e26f716860e5bf6b9d452a98f441c69a6ba4cb190d994c9da1ee8671d" . + "461de723845006e7a885c137bcc99bad9877add4e4b9ef0d3cd51d9c0b22a494" . + "ea768d3a9a83de773d634a7ddb4060fa61927d8760ea7c738b357852497f3e6a" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "180643e64c178df60ee7db428ba9e534149b257a20afa8c54064ceb875ef83d2" . + "fa7e259fe58a8d82e2b571e2ed434b9058feecd66e116ed47b5a2ae8c1c9fe82" . + . + "0c5124673693fe516bf60395158efeb7e66dba25a61b0dcea6ac42c56283e0a2" . + "fa97e43684aa4b798eea3e638d0f41368b6a5408083ff3afe303fac941843294" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "882ee8c16e1a8787edf51b7f131117cf9b24c16d34050b384a7ffb71cf2977ca" . + "1af795a781b4068e62c480923b25aed4d425f64870b18bf8dd21ddb16bb191d2" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5c6d6f082ffa5d2190c67d1aa546a3bbfa436b820aeb56992d079947268a53b8" . + "537ff9a6c545f03864fff7b3e2a835b9fad9bd0c2049e28f977050755d4b7474" . + "a0efc75dc4b773a2092dcc158ba3e685e59bdf57f80e125f614732951ba5ef72" . + "03856cfe43c63ca39ed1a8fa1891ee9edbe6571fda1d572ed8e9ad4c4c1c9ddd" . + . + "60c11c0cb8c79124728cf2558992ea6b3e465311eec6379686af2d415690047c" . + "84d1607deb85f9a29ce1877d825d330065d3e0f77f79fa7ce1ad24561b114b9f" . + "335221c4d0d949a73fbf099c505b78bbe23700a423c7907d7d6c8886b7bbe08f" . + "be3fe7fb878e0ab67787227cc4368994dbc92e0300eee23c11b76230b6caa923" . + "ef84502fb97eab54b0623e4e85b4186391706878f449fecbcc1262bdd79b7849" . + "0e254b460c3af99e09f795375219749ff7b2141eecf62351ab68e25204081562" . + "b534aaa1d2af707bf93248c2b9aca0ced7ef2fbca2cf7402e64840c53875122f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6194444a5d1d4533fb8631b93c1fc656ba7ee5a9fa3e28c7877b134d4a0e2644" . + "8628d473c4a48cd83e27c3944640867fa38a34c583bbcb23fc9712cf22e1c3bf" . + "ef321d10b0f7271efe045d23c34c64401e6d5010e20bc3adeea919b37b871727" . + "846ec25062981b1475c96b3aa9e7d3c360a9de01eebd7325eaf7c4510dddd753" . + . + "b6f50ed1a1e5cc39fbd31bb792daac98b7a906f2d843b655380efbffa3af63aa" . + "da2440abd455c05c5dc222eab7c030f6ff6fc5386819d7b71effe0bd7e7bcb0a" . + "5f3d8dc16e98ee2ae4126552fef42cc7a06c50f1b1eb6dec83b8062df081fb0d" . + "29e86c783f6feab6b678bba4f6a695751bdff9b8ed3a4c1a1ea365eef2f2bc52" . + "b6f50ed1a1e5cc39fbd31bb792daac98b7a906f2d843b655380efbffa3af63aa" . + "c98bdb2f6216240923edd404c87aaedb32145ba26ab397f959e83f7b1497c8a2" . + "ee9151500120a816c80137d250c4ac673fe27e13347abc43bb7198440ec36b99" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "58cb166c909d9bcd711363f155dbe1c62d4504d9eed457c1689f5c3ffaa856c8" . + "36d9260b7859ee921c1b4d943e30dfffe1a658d461d6ba2abfb1108679c27b05" . + "bb59fe6301986a48c878a557cd17660e3acbcba626c48f4d9b5f76ac51047efe" . + "5166f89583d6174cd209973182e3f009fcf525fb37f57cc3a97e6ace9ca17166" . + . + "6029506b8b92d031eb76d050f63f84ee5ecababbe2f0d420fae76994ac311fb1" . + "8e691d0c6acf35cc038d380fe640daeee84ec0278cc3ae23c45f04098b7a0ac5" . + "4d5c9d932bc8c4a6850b7c38b78b1f395420ad314fb37b75488aee1975bf2dea" . + "f9c78823ef36f7040756c023cbfdbcd95d42dd205ab6bca6561835f4af9b4a49" . + "f1c9cff6780a45cd4b1e6ce68b1ffd7a52df9b417ad6619ff40f82c316119275" . + "4fba802c4c6c6bf149290cebca4fce1b03518b308df5a1c105dbcc8b94b500ae" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "017f497d1f71d8f8f126dfecac0883b3784ea2e5b82698150ee53569beb7f78c" . + "6ab4597913a5d82bc7785264c65cd5c9b44e69831c9916bc50baa0358be749d4" . + "ce3c38dcf137320d1fde2aa13e7e2a8145f2d9f894b49cf20dc9a944b9a542df" . + "dc985ad94703c3242f1a4bdcbaf248a2959ffa71bf2911e8fea5f9578205c7f8" . + . + "27d7e6b699fa00e83f99952a6537b1a19bf9847915d12fa2a2ff1dd847f312e0" . + "862f06252765654ed1cae7a5c8fdfdfeea2e67c72dbed47cbf116e7fd369c4f7" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + . + . + "2378aca6ea6c41fe0e56d97f76dc017774cff0b65a4231a18c9bf6f5502d0ca4" . + "59d4f4ae1fe89937b4d009d27e2abe914b1c801d943ba4c61b5c0241b04294d6" . + "bc038f8a1fc5599b9e3d0931c3eab4fdd18b97d4707acda8739abc95ae055bdf" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "87cdc9963ff0c4fa63e09091bb6c87fa488baf23b9917a85f366315e59b1fcd1" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "bf5d5bb89f6b45a59e27b45d67fe411b603555c856735b315ee8fea7b1e52c34" . + "f2943d088fe4fecca1202cc3e1068646d814e29941b7dbe9a131e9a83cae4500" . + . + "2d6c8f94a20c994f252e402b32a9ce554c6ce7e6ae34f8d78352d94931a01766" . + "3c7668b01cddfa0a27929162d57d5601ffd9945591a58885bfa8de58b665ce3c" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "bec78e2f9d537fe0b7d42a1bb7144eb9f038e09e0c05b4a3ea655a3b1a34ffdf" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "145f805f6feb260c4154193f894525f43af82f566e78cf923dab37364be658dd" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "f42c110894d377d9238599c7798f3671f5f8c3fe5b3e583a733fa00027515736" . + "e058085ce9da3ad5b711c2e070b01bc8c1f9a68f12af85e3ccec0f00bce9e6f6" . + . + "9d742d4fa5c1e452795e879fe8f94d49c569e4b6c3d5cb03c6675f48da1d3840" . + "675495449f0a53ce95857738a547ee5b0039237ded7a6cb65a4c78786f7e5f69" . + "18a919c3149d059d47d177039a15c13d5c74325e69964e958c20bbe26e8029d3" . + "4bf8fe05b49a2c689515b1218e3fdbf6df58d77c5a4eea32efec00845c6a9b9f" . + "1147f13d83de2cc756c9d22bb2c9b329ed1ca9bd9842e65a3ff5fd68ee797fa0" . + "9f49b3bcf40a5481f6e92a74f3d189f82ed03c1bba30c276917c550c440ba74f" . + "86eb6bebfb5d95ebaee6a24caf372fa927d76c5484529be790670afb82bf5d4f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95db40db1e6d717a53b8eb9094ba9587f0dbf80256eeb0501e64f5c7cac45874" . + "cb20de4e7972666294eb013e3161059da635fe91c0351bbd26d656d791417c7d" . + "8ca3df17f9d9db190a9d5247874c14019a51da4db4000c3ae5042aff86a30559" . + "1ef7f0d85cd8034f8a03473779fba24ea8929044bce3bd36ba50ca6e71008066" . + . + "6e70fbb6ed277963eed656f26e3e1e7276fb102531b67153c3e6cba461a3606d" . + "494c264950a6d30ae91065d51f9197524f7d9b676b8f76472389298be3fd02e6" . + "2ab32e2537f4b24b19c7648d7dcc23f48605b9c0adfe75687c15cee13d18259f" . + "0f9f30f18e40ca82a655d94f51f8924f6bebcc2e2fbfbbe557242827fa6cab0c" . + . + "b8de494a362fb6d5b19250ceedef7ff0085b664721836180881c834dfdc2b5ca" . + "7ac1823d15d39f3c07207f3dd14f6dcf0ec9410e2794246ff02ae99b3133e672" . + "53c325871afb452fd57910d334da9b4e8664c1904f0888af819ea534a67c6b08" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d5229cca8619f9ff1379c058737f927d307ed3037f03b79ea476039a4786a9b5" . + "c7d99537f94f73b46e174c36b6691d4b938ca2485fc37d63131c45f8756fa2fd" . + "c44fab7e3942d9435fcfa7a5285bafbb2c7d5894b6dc9d57186bb9aaf9184727" . + "99a7ff08ccd7ac953d82ff1684bb6b069062b3598217d60779b463aa880c475b" . + . + "904f060099b7454c34a6ebf52608301cfe9d23623fb5729183fbbc292a429443" . + "be18ff20cbf416375f774772c338e98ceb1ed7875fafb1c8193a50e746cd78f7" . + "d9ce8f30c36c3bec2971e44f03a7daac74eb6e4824f9ecbceaa75716fefd85a2" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + . + "fde0a49932e1303431896653620579407c59fd3ada891d5efc57f0b61b06a0dc" . + "1f2740bc67c7ee1a20a7e53f30025cd6a9f728a3bf6328713646502f0b135bd0" . + "f800f29e49ed7805a138d3652340de865b763dfd1484aa13750587674fb824df" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "db2e3982261d5ee6a84b95681bec5b043c90f7efca17ea0b3f64562fa22e5340" . + "2b7c38d3d1d5776a220f8d4757476b87e1a630f28d1abe8ac33ec6998514566d" . + "c8f3a53ca11f757e7a12337f7ec67db4e391d28b9f7117ac5137423c3e6fdc13" . + "e1b3bd23bf8252f7357a090b4d103910b32f30cab31cc2e76fe4076f5b50cfc6" . + . + "b1620071cc587c44225aef8141f11cb0315507abc22a9a56dec22e2ec27490e7" . + "f4e44a2435012168248252181f44e72457cfed5121cbd81c09d30285f5f51997" . + "ce5cdc507e34e47a86110f11b9e2bedc4c178f5cc2c7bd47a9723c4ef5ac002e" . + "65ad60d76f74a3dd19ad2fae0b83e08c6cd8c0d01ee1287477dca8e13688bdb6" . + "c1e4ed9410f06b65b1687a5b4f934608a4166175d4dd8fca9f12dab69e2a05b8" . + "33d5ff5e1b9e2f71b5a99777b01b7a0310427845da8ca3f0c6b68f751c18ec49" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "66e8244d1c1dfd74d8e19c94afaae0132e3a1fef51cd0df4024483fdd0957aaf" . + "8b65ef8a277d9c1af60a12f4b10608e1e65ff24e60efabfd7010143e3a22be30" . + "5769a60330788f53cb122310135962c1597e45034f72a9e2b915127850c235c5" . + "dfff90f328c84d30141d8805177aa99150d69ac4a49aa3655c4e9bee54a348a0" . + . + "6f7c7da31b610a4db0a233630abbed991e350af3a389b9ccb65f579f1cd5030f" . + "adb21c3d2b02373e6aadcf3cd5737e3c30eea08ae52dfde5bffe64b04429a1f8" . + "2567110cb06e83571f3462c7ca69b7df4ec5fa2671b8070754e237d3df13ca39" . + "9ea03b14983f054a1033742415b25dbc69d7ae889ac55a5e7007775373432303" . + . + "027ecdd3352184bb177d60b37cd42f105638b6c39eead831b247eb6e444c611c" . + "9309c9ce7312172dd14b6a70abfedd87f1f45784cc6c3b13357ca40ad6bf628a" . + "3ce77596a9c69ccefb9ad2ce431cf3acbe39b53282021edf9612c2e0a6787dcf" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eaf93fbe65a45bb590022b1ffb910955379a01ecc218bf0340907ab46f6bab23" . + "74e7be917e71bcd13f488bf56fced4668b6d0ad283aa3463dcb8d8030b438da7" . + "dd4ccfbfb180ed7ff5d8dd0d4e17f97dddd88bc60e46065963b0c94b3f8a366c" . + "5b349df2da75aad6bf6eb9c5a7884d738000aa1acf413a4efd0f7d36e7e2ce9a" . + . + "ac1c72508234c888ba07d978fdcd966c1565e6f61d422c978b0c025e0ac32753" . + "7737c72f2edcb271398b64c1973dc39515438af7fb7090d9f5520c0b4ad76bed" . + "7e2f259e2f27d3b87170c9e3d9270c2c3b842a418da5fa3f6ab486d73a69e4ba" . + "5859536b6dfd0b3b2c334e2b7f9bc7a247aed7a06144d3769ea60e0ba1b076c0" . + . + "9880e1f971637e1766c53214f9a6e56a36d0e4bf1f2267efe513ebb6aebc57e7" . + "c4da55854937998bff27ee74a2cda99dca3ab1e348bc79b5832feee11f3b5b8f" . + "92ba9a20d4f4888030fdcc97ac185687f7a64227b75211402fc5f5d063a68b54" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95be804e109eb5585c294b222e9fe238274c907d46ddf11f8c531cdb64c34627" . + "b9db31b3bcf836679621351c7688b4341d7c5fc275d669ac1e9f5d6edbd85900" . + "d71303c269adfdb5a0b226074ba0ee242fe247ba199f35f13e645dafb4fd40b7" . + "1c3f1c5f8d2a355afdc3628ce87f0f2b9add77e31d625831dfd5b48602588453" . + . + "3c3184132ca53c83c301baee5fb4232cbff834c264d2d4b5e200944a6adeb1a3" . + "300ff3b37fc16618826cfed29225d57a0158dacf30cd1499db9d09965cf68a80" . + "c52e6f513b13f965cc8cfdb921e1024708147ed2461bc35754619d4d883ba5fc" . + "aaec19d0985e172d92de1bdd4e108cb5692aded3b3f598c18c824d142c27e3ed" . + . + "08c20fb1a93d27e60bb21db95b1bc1d7363edf77eb223a932523d5fa0f7f00e8" . + "8babe717077486d811459c38a21b6787b78cea3c296ba79dc060332b542a89c5" . + "792e723d28e8a013030d20ed3fca075de02a301270c536cf476bcf14082c4f35" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a59ea8dfb731dbfa213c5c08eead83c43d87a0cb91a9787f2a2e572332d5b61" . + "e0a325baa4223ee40b6a4ee8b1d35c27b951a7cd10d28c44a00bd6cc59b68473" . + "ee0153406365e1a3007f057cfccb3b4306cd456062a8ad49765a0a4257f094ec" . + "7e4997717575151b717f68d4d731ebb9fb72a724b528775313ab0ffa8bd2f072" . + . + "388f870545dd6243e0e9f33575c350ae7ed31565e6ce831127d26db1db16de8c" . + "b8276e10b072271fa968680119edf0cf98631cf905c05ab5af48f79f3816a522" . + "95bd6339157e328fad8829d49c4771cbb3d60588ebf0dbf84c015f794933dea9" . + "ba61d58901d6559e0023a7740aec0115888e352114e4161a45fee4c3072e77e3" . + "e16082af5d704629786f0f36835590c6a5eb2f2608c88df36e0ac173cb7c391d" . + "c25f2bb02e12388d5cbb9b456b6a0e613fab226ca985aa7bac8e80878bb8fbae" . + "dd5c478b1455739d7c054993d2d679b9e690cb3f535e4808faf5d2008da15deb" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "20c5f4320dfe75773752c58dc88f5c0d9607c5cf020bbe9d4e7ff8c3ff8a4fb7" . + "aa008b418b7d5553a7614aa6b2aaf51ead88ef1145976ba358c1b41a0ee164a4" . + "111b4fb38fcb1dfde330848e9d0518785599456cdd7c807ea3d9bd36c4d2aa2f" . + "9edfec033503a186eb5627f61e62f9a21a35c4e9ce91d0c82373ce7991baff85" . + . + "99a2d2849290288c027e84ade5e9e89c26de7fc50f8395602b6b7ee13d915749" . + "019c962ecce4173b526e0fd138534694166c40e7c565ff19388d2d2801a8cd37" . + "f1da07179731f3e5e1c12cfc3ba27a3833372363c966914a60fa6cbb69e75b2b" . + "c0e75f20c4726d792a603a53889bb706cb9e0c09042016afdc679bb4b8e0e777" . + . + . + . + . + "c3ab4393ceb791b718ebc32b896518ddfa7d2fd8dc2e773db71057b84d9d72a7" . + "7a2fec0cded01a41ed101e2f086ff0eee816f6a77fe49dcf999e2fe4ef485878" . + "14ccfb2e01091075acad7674e6c5385d2ec51d0113c68d3153444dcad2662973" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "03766c70219ecf5c7bdb4202d70a998da5475b2fa3fc6d4c0aebd816a4e92cb8" . + "4f28aaa17eb4a80ae5f2ae052c9c5c9f260cec255322510ee7681b4465c8d4c4" . + "1985007dd473ab0bcf610d83aaf04f4aa7536e30cac63552b5ffff2ca2398160" . + "4bc1e988844272a23a270247db664354e946be969f93a0628ae5e6e90ca84126" . + . + "511ac996130563cfb9121da38dd8da0d978101b314754b17361f6a4006260dcf" . + "aef7ec0af27d960c9f7f8351144b4dc37f074d3b920522fd93920d7ea131c49c" . + "695d91c44aa499c4e2226a16a860a773c5531cac34613124f5cfabea25345cf4" . + "e3cd9c560be5d8532a97f100dc00021263cb7e17b0e46247ea0fb48d1bf857ae" . + "916749832fb74da637d7431197abb39d0b6e74324a5becc17c5fc37da059c3bf" . + "7f88fe30a51b845f978d63e3d183f0a77c623e006214e7d2714a9183a12b68a6" . + "4a3742825fcddb038a450c6064a60e92be71a70ecc14a61430fdc231fd2359a8" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7d4abc68a4f6959d1fafc6b81af24b91fbd39945159db209fec5bd4c370c969" . + "10972bde62d7296e7699305b76b6f2f7473330703b8238265abfb8855ddb8378" . + "7268c14a0c4333e84a440725e8db2091422cfa5e02caeb9892a3bb591ce52079" . + "d9db631ecf236b4228e394717b374016ad3fcc4f3be5becd3bdd01097a7c5225" . + . + "b817a11c6e8e0d2897768dd3131ec6e91899995a9cfb5e3c58ed788094142b4f" . + "1db720ad1ba89d03d3e2a378e772234a7c5f688c270b6f23d3a45b6dabe4eb76" . + "d3bed16ee3ee3f6cf278e08f52658e2b1d04cc1dd1c181463a1e9bd75b4d235e" . + "e9947c6581d9fe57d888702d90ba02ca277b39774902fba08b691b82a7646b49" . + "b817a11c6e8e0d2897768dd3131ec6e91899995a9cfb5e3c58ed788094142b4f" . + "223c70af59b2c0eeaade860bd35e07b017ebc25b59d43d40ea833d8fbbd8cfa0" . + "271aea8a4a53bd388c14b9519d7eecabc4d8f3b632a78527777339c9520a1a65" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "67746d6eeb70c01d46c736286434fbcda4a654ad2c1be4c7baa7d3714191eb79" . + "cc080cbdddac41c08456c42841304c6bbb7b677975b4f750f14fe8eb4e455d53" . + "618ca66511d322991ca7d74b09054ce617b7e6e0af1b2c6dbfb4ea447735226d" . + "3e09f4a580fb27c3a72ded8191b33e8364a2030a08a0a886fcc46ec694b0de76" . + . + "4cf37cbbe0c3cde15e26bfb089256985290bbcc10e5ade0f9e85fcff3356906c" . + "a7e29f6d7dc721bcf1cc80bd76201ef5f11a05f101f6852cf14d772ebb0ef4db" . + "8cd5b5d84a572dbd76a7f5bcf164240e3f77a524f4f96b57a005849c2cd2e373" . + "0e6adb90d2bbe14ab056cb3a32d5d6b4071abd53301ed544a3197c69a2ac24f1" . + "8f9c7afed2d77eb2d24bc346434127720f292a45ef0a45947b9aa69c460e1eb5" . + "bb866abc226e0a96b6abe3ca01687bcb5df0a63ed05662a95872ed2969b45ede" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7174cb8dd219dfe375bcdf48e364ae58e26c38a32f4f87f99d4631c2da31538e" . + "99a2e1a3b9a871ce4452cbf0f48512ab5ea16a94349670bb97cfc4ba7fa69cd3" . + "fd1c3e025922ce3c6d92c107b0c0580f16ac4441ad88fbaac1060d594d1d7b41" . + "859cadef6e03a592a294ed5650925764b68399c9775118f60ebe9b9fa4e60eb0" . + . + "66e9a3d24cb40666a43bd153e93d342097dd30f24aec6ec134e64e406023b993" . + "925a72be9b1a25fadf0cebbafe76c3abb8fc4bf1d893183d880d5d4e399ce37e" . + "4d8e1067cd0434bc8111102f7a76975d353bf7f419d110df0e64c6cd1bfe2c50" . + "4aa9538cbdac1e73b3204b55267f844e61b10712888162c43ab2e51c8ed38648" . + . + . + "94b8cdd5bc20087faf56928d862e2f27fc4b1b401b3824d2718a70b8780320b9" . + "af507c4278743942d9f4985ce1b38fa391f3f1c3694b8122e7a00d26707ae201" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a643f6e9d5baa574ff4518897fb4ee3b3800a18c688a27b39c206ae9c5674256" . + "6a865ae60059ff6652d483218423364622fdf667dc79cef82e76f4b16b2eeb04" . + "4f5a5940f73ea287140f633dee027092742393a5954e1f9c1650b437d6c76e7c" . + "627ee487e6fc24b6e754a3e6910d18f68abcb1c7a69a5c1053cbcefb377336cf" . + . + "c736eb3238b3c3a3c315d44ae10af6fafd317d8ace444084d38cdcb50fc2c211" . + "70c5c3bbbd064dba8c5e84924cff01c72598ce52e997149bfc77a5506c9e63ed" . + "fcad24214a9a20dd18429d14a82b53a487372886355828be3e3f372f16c5fc84" . + "a53d6bec93184c69261e2363c64e37f18a3f111e2bc73d081694854769615a77" . + "b89904ecc29a6bfa34d87df946cee4b3d168ae4bfb9c17f751312d08d77b7657" . + "fed1ec55d54748eac1eab7738f0cb9e0643713888ab0374c0a8bb10342ae5444" . + "bd0c9c55651989d84137f7d9ae5365955f7b60e2d4bed2224ccb64a41c96309c" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "538ae9b074f088460392b88be09b1c950258e23ad3dfd1e97b8f1016d7aa3a4c" . + "79f56e897eaf2215b645b49027119fd416cc2dde7ad25d34d2ac2ef142e6d750" . + "28c9da3d1e380ae0cab159147b778b350840fe6c438167a1f2ec505f092f58fc" . + "5ef2195500fa6aeb161eef97e3edeebbbef1c98d965146ccae5534ad16035420" . + . + "e729da3a518aa871da3bb60a4a85f6b9d0fe92214ed77f38fa7ec13aef3813a2" . + "8b8be377ae88664c2e6b3fcb253b907bc38af8db5f0a2c81f310de0afcb1a38e" . + "968259ab436feab20f9afaded8992503c43f8f4d17c6fd0006d3761bac267de5" . + "66fde7836c07bc13f568d627bc035288461e0298b4326493d313b78532661cef" . + "e729da3a518aa871da3bb60a4a85f6b9d0fe92214ed77f38fa7ec13aef3813a2" . + "6f0d9a17877833ec84e100f855d8daf8ebd01d5d7fae8cff96c952b721d21d1c" . + "7d6e905c210a46b8ced0fc2032f66ce8a922cf0edb5f8ddbd71cffa591831f2e" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9fddac05966297fe9db24b4e46649bfbb2e96359533f9a0bea8334ead3e447f9" . + "3e741eaf635d8024240eb73ac67f9f6b844fee0576ca2c60fc084951a174b2fc" . + "f3a58a47b1f4581c3aa69cf581ea32681cbfd07a2f1df879e8faca6f3a8d93dc" . + "c15ab2067f5a088707260523231774b8dd496e6268f576cd9d4d60c4107e360b" . + . + "6d48b9975ac1056087ef32a34eb8469928121f7f55dc8ffa1a1d66023f1bfef6" . + "35d072d258c773abb7176bb5efc2402b660001ba355f6cb0c33a223e3da8809f" . + "46e88afe5b6f1c3c1e13e3c1d11ee2646707ceed8ecbc2c4aac68fa17f8fd6ba" . + "73546fec7fb87e1e7e341651d8885ca8ede0806aa40a242d9b385543f6040d6f" . + "39f8ad38b5ece1ec8ed7c34ab2505a534c456f9a76e5632429f2836168ab5637" . + "0183808d9ef63e364264cf056c2f03a5473ebbfec6a819b6a4da2741abfe1722" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f9bb99a98ee57c1fd065ef5cd49254434698248770ec44db0ab03e1034fafb33" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "ab143741b8b6f7e7498ba1e48dac8d7bcf2ebfd2ac2ab5f3458c41ad0832431c" . + "e1a3e79fa4b1390e05b9e4145b8aafae1716be723ec98a0165e89c8454a625d6" . + . + "8a12b1506575f7027f23401b3221c555bafe837b816482fd481d20f85c5f7424" . + "129441df1d199ca617ec0de38bc8b2861a338676831dbc19e89a2bd081c1e573" . + "97099bff065775b14723148d70180a18fcd17c410f6a82db09b7452de59a57ac" . + "70725c5bfc7d1911e67012f0287806a9e0a9d47be2bf45442f79d1caa4ff2442" . + "2e928e4612f523f34c52a79eb3d8e3b9c50a6f54eb48f4536eba2c4df29129ba" . + "89d3cc20f01fde6ad44c19a15c774285ad7fdb01f089684d797304e325d5d89f" . + "e2347123010e1784c704019887e805ac8129b8c6f324eece40b6d681943913aa" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6784be0952908a10a61730fe56f4270b27c5f8e1bdd4653a5c7cc8d137b3ce43" . + "e7f75000880ba9426340d09cab41765555e9d83a0fb091c238e0aa5b7f654880" . + "b0519c546dfcfb5f68d974f665bf610eb9a56b583fe269a21d595c217c632151" . + "ed3242bf739a5bf53c771c4fa99f4df658801074ac4fca18a860bc00ac13f230" . + . + "4a55a8405865a227640eb9a2bbf7e37d83fd5affaa5249b074150900f3492220" . + "e4518fbe33d59110b5a7fab48876876af385af64881a4fcf0feb93b3df794fa4" . + "5ebdd6eefdcd8e80ab7168a548221d390c2be00f0576e3e65406464ba7a4d642" . + "8f4db0489538b4628307cc66ccaa4f277091b0603832dda3f00e9bfcd5b08ec2" . + "53ee53bdf587e9b87292ec6c980f2231860775d44a09dd39a2168f65bb446ee4" . + "ebba54c654be1366c5bd29029d209b975b3c651073f32d6cee7444459805ee2e" . + "568b6501d56a4900efc966f62d61a675101bca757d4f985cd513f04409b7b9e5" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "769ca91ea45aea1f37ce73ea0796c08e4c97758623dc2c09f95b6d0e228818f4" . + "283a51e76038d96cf4831ad3fb4e43433227e83cc35d5badbabcc814276ac1c6" . + "dccb0c05359cc949f4fac1136a806715d96157f254bb2cd6a82ff08dbdf02a57" . + "1bf1b06fe6f027bbb4031ce99af54ab31a720574c640da278e37130efab5d4fe" . + . + "7909c5a677a1d66a8960d8a700d5ccfaf29e1b5be1a801ef5a8caf5bd4b54e08" . + "fc4a3b663e5af615fbb91c6884beda3867035d3a246515261dd7c565d4b252d2" . + "0bdcbc705e945c5bd5de78bede1e23411360741f1a26a4d4b3dbb2aa2e1c9fa0" . + "82ef415545d171a15f6a891c49cc070b3270a1971e814488515947af29556b8f" . + "58c74cad8d811ff2f1a0f1d75d32286a2fcb3c197f43a8b47375faa2b04c926f" . + "8ea2fdfd10de99f0bd7341d115da029231a6aaf1a0545f1649d6ad35e8519ba3" . + "b010d6cd7fb854e565a36f1426f7154346f6d76dbc6f0c1f86a6ce79ea7c5f90" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "8988fa85aa728163ffb02340e752dc494bc182cb49a08751ed11fdf1998876ac" . + "917ee9f0ee9fea4cd329b8d1a4d194b5ca10e1e693fab7ae13ea0c383b78eea0" . + "a50ef4e651d919c42f8c89d6fb0aee2ce3fbcd912bce2d2edd24217648372e89" . + "0a0407c18d3d672f69144b40ff6bddfe2d5142fd19bb4baad84bcc4dcf698582" . + . + "7c405d40264a69b73792cb7c809d606eda8ef822bcf26164776d1a2c6abd673f" . + "330d1a23c89af2f9d4757e7615ffc1da3b656026712b9bf389cbd5abc1108066" . + "a2cabda81d87b31c6976ca218f68b4cf2c11f4d6b7e7f293db88a332be775b67" . + "1fcf4e2803cd0420c0e8c69f3476077039d4b99642f411a70c59f1884c30233b" . + "b404c9dc1925fefbf3a8b7f6bfcec6df601cf9879829b1499ebbd223734573bd" . + "9aa07c7b5b031e09f7198313dd25bfb9ff38e25a79ba774d286233c5ad8ff520" . + "ee6e6b94ee269d5a1d2bd2084164dafcc6168d94337492d11dd02422d8751e20" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "78df79e64be2c3c2c9f9e052d80b841680e5a781934181448ad0125879a94da3" . + "4543eea0ceda26f3d3f807f10bf5ee5cbb8f81356ba22e45e7e251f0fe1babe4" . + "d1fb603c9e5dd1c0a8d978197b8c3d49ac3819ef5fa2e584c9b25d653f88fa5a" . + "61fd66e01fbdf8a07029dcb20b3bd900a76f29a6bcadae3788b6516fde074393" . + . + "87cf07475081a0533744d3b5533dd0c27a9d0a100263b3ac995e0e7872bc7dc3" . + "3465b50326f47f1cfe26a19999f235062660fe68ed4a23b678ece033e78ce4bf" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + "3e741eaf635d8024240eb73ac67f9f6b844fee0576ca2c60fc084951a174b2fc" . + "63b19986be877cdc847ca5898112f8e9e3586c32d9bf2c17266ed573742a3121" . + "805c06a477482d2beb56606a04711cb34f9a75a62e55160aaca1ca49e9594fda" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "09a42d51aa19023a2d0bef6611adbd4b2f42d790d3c3ab6d0ee925c07f1e866d" . + "3f33b4128a18e06ed3c3615e3c56d9972fdab3d476b8ee7be4d0224a336b89d5" . + "f585b71f98305608e99ef9c5e83e05e085610d53354c11558dcdafdd48c86efe" . + "72bc826e4d0735711891fe3a284ba4fcadbbf59e8b6d6cbbb028c47cdbd6c766" . + . + "0a385887bdbace49266ed953e8596cb03eecf323da8b2712b09b1263f22feffc" . + "2d96dd148599c9b7f23cb770efcc7e4b2c3a49c1e69fd6850c47a55484527114" . + "e593f5662db7ff660a0a96e3fb1d22a70d8e041ab7eb22957bf2335685264322" . + "7ae06e664a0f47fba9b43a42485faa19f3b3ca1072784cfe2a0f3dc45ac84779" . + "e623fa1ec720e3ac31bab5a6187a14f26fab7961b4ba92178790ddd2199e0e55" . + "745dfdd98cd5c9136bcf195ea63db350c5079b39059e8791e9cdc0a4ee95fe33" . + "2586c19a354d09959bf49c81d8679e3ee48278b2ec81c70f335bde4398b19ef2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3a880229e07f20846d8ab697ce4c7cfc6fda0262e5ac2bcbd8af71c66ff33d69" . + "a7d27e0fc8dc80fb20558d07df11291d1c1c2508fd065cd44f249151062e4b66" . + "b69b335224c9f59b6a7d265fe358f86de66a2b6103ed7eb3a8b84578f0b04190" . + "2a827ff87cd0e18394cebac5c44b0113282ffb523355d37d2045fc568f7757fa" . + . + "e1ed54d359d867e9cccc4f5340063e9f144bb4642ac72fa2e532fed76e65d526" . + "e939902eb7e07ef682952e30f3a6ec19ac1659779b9affd3385974184003e54f" . + "0a00df3568f527e91fda29c31b06bf84acf63fc16f6fe77258fabbe34082923b" . + "0dfe1a8cc0e4dddda837d84fd907656be4ae730474d4eb6e588ae3eec33342df" . + "3bb749c0d69c30db505340adc23318ff3959cf313ffc0bb7dea72cc825ddb4e5" . + "f2f43f5f7d694b39955f67480bb89e25f6bf6a482a1a98286090935225c26333" . + "d23fb09be69efde69caf4e84d5d5bddabcb32f2cae55d7f3708ce8a939d15527" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b51ca1264d2556b76cd7250b99b52aa1e74b18aca5a4bc960ed54cbfb7766933" . + "aecfa7580cf9475714fa4a49f59bffdafa0953d0efab159178892b46285e6821" . + "fae1b217c5dbd013689663b6e491b88e5e06a91770b8fb00c2800bdad80432d5" . + "5251d70e09fd586e2c7fbf770c7fe438333dc5f7e8ceb926c5676a269cc00a57" . + . + "dc2874e02257571010200e12a73541c7ffef640c556d4183a6dd8d374edb1975" . + "d7e205efb1a4cdf74ed26c4c2c83cc767f60fbd07265714e638d390dcf027cc8" . + "3a795a2558b956482d0c5a9fc9bd3372b7d8f9833526a6ccfdf0cf0391d7a9b0" . + "4d6b1845431991a74c43855cd191290ce722f1b26f1e0e385d38bdcad09acae4" . + . + "dc3c4d9fc11d595c9542613a42220c27b84258ee1dfc66031f56206a11d98806" . + "aa766ba453abc0b8907b3b4c5372ffc6657622a0f0a4f0b0e6c7fef759f9ca8f" . + "091da9667877a3a56a0f857f0ebec93114f10fcb901bc73945b57f67b6d9501e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "91aeef0f6da1bb4f006acf73db2459b766826ffaee23f29228b1329d7cbd5652" . + "7ddbb387a295d71e921ee59c66e7e2892031fb42bf9a89abfa03f4fd2a1ba90e" . + "248c3c98b1b96e1b133e2e753e45c2395150ba375ea651f0361d07bb9d40d0f0" . + "6e0b1d7d2433ef5c59f291a3fdaea9f9c3901c95408075a5bcb38ce70d07380a" . + . + "60c2ce0404845008e0ba3d4e3714743c749ae5f1a167689bb66e5f73cae88998" . + "d0b6b7e432fba38336457b7d2e0bcfab639baf9d89239ae67cb1b0698ccfa389" . + "6163381ba6718a9e87e30ee933a0c564f2fbaabde1a26eca10a364caf5f624d1" . + "94af0475c2afbf29bf1a72509487bc64502efb7f8ec5ec9756622fcc8ce39ebe" . + . + "c2a497749a84ca0e13a51788e9a68f247da8d81316b0633aab732f7e8d76a719" . + "971f38d1aed6fced76a78eed220169881b67fee52f08c79eff1dd62a0038fd7a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dd6ca8523bab86760574a6c984b9430e3c3bf32eb615b3a0bda84e0f0dd74c74" . + "616e126bc5afc43318514b81e24b9f4dd61e91226ed61a4653af107000a544c2" . + "e0ca8ccfc22b718ad58a94a4295e363213ee88707bb3a4813754ccdf00984b3e" . + "d6f3bd40a79218cd1422ed9744235aeb04c3c74df0f057cb6a004149a6375226" . + . + "91e269a1223980ddbb35741ddf606244e958dcd4f6c5e34f2e50ea7ddb965ee2" . + "5d47bb9d7b64363b230139857d5c3d4f8368a65453393708deceecf75f9e54d8" . + "c91117cc447e8ade7406e6dac0840e60fab7d5f61066d0c956288c1216e6e8b3" . + "9203d12692a9aad1439e63affcd0d64b878ccf3eed0213ebd112881152a1c719" . + . + "9a0db5c91a9f47ba6ac13c7689f6cf7e803185a9c8b71976c24fadd4284f689f" . + "33338d465aaea470fc042e14de9e4aef590bd3a7df16983b8947a2432cb1cdfe" . + "c33c1f957b68afd4be594f50acb76a3fbeb73cb315bb01ba595982de7578f2da" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "64533047bd93a3f46679aeef6ac0b87e68df5249f108afac93c61364d9a8a29e" . + "ce7f098af34cd3678ed8511ed3392c594f54a1cc92c37c656028edc0b42b6f92" . + "fcd94138db7d604db26deca03fd8dcea6a9acbc62e2cd3ad901a09728d359136" . + "52c020e45291cbc3035f7e00a00c6ce855833daaf060b0d0a47fa4c71b634495" . + . + "2f566030104250b9ce07319f789a0b5c2acb61b282afaab145cefcd4b2180efe" . + "2438e1823b50c282539721243112a9066a79dd6fafbd5652bd5525c271415ba5" . + "44a298c0c8a028626e5688e2b39e80947dbfcca7a3a883282289bbcf5ee455a9" . + "9149ce811fb29cc68ffca3bc08efffb0ebeb47f010395b7abeaa90cf878d22d0" . + "8473216f0f9e515829e3e93815c684300afe70ae0b5328284e93d9c8f3009b94" . + "a79d1018e8d10ecd08e8c247ae0bc0a121547175bbb3aa1d76801b63d78e6b9e" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d931f63bf63dc11e023119b7763b4ac45756e8b03bb5e9e0e61a77ba1d6c8ba8" . + "0d2fb88aa50641bff7bafe58cd0f9086762995a267bf3cf9ebf4a076267026ba" . + "4f3b588aaa9335a22cb57b20b9efcf539b4843f3d74c81cd7f630543dbedf6ba" . + "3fea71d016d714e7b607cec1f2ed60931cc1fc7c2dd2b191c4915c62a3a365ce" . + . + "430a4261dd830e13c8c6264b8ebd0bb41eb98faa81233c26568acb9e58bf4077" . + "be71b085693f87be4c815e67c50a20d0bc48842f6fc473a07ec288b515569fd1" . + "0b215b66447d5014114e80b0c64fa52d7305306a75799e4241368e1176884cca" . + "a9ea247751a9afcc0a601e780b7ab3114b7a215713fc76f94bd83aaea50cdb27" . + . + . + . + "430a4261dd830e13c8c6264b8ebd0bb41eb98faa81233c26568acb9e58bf4077" . + "864548b2d2de4046acacd59558083d955733c7c4e5f56233cf3d0596a93818a6" . + "ef2078ce0bcb91779d42eef32a760c4f9fb6dad0aec0600c5035692ce5584797" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2820498981379ece0a8579c042fa7880426de50d7858c5826d55063ba0024c9d" . + "ce707fd3738b15bf1d7baafdfbc88504464214ff7618122797c9a7aef7e14338" . + "1790a406491216dbc70678e2ffc9b68e050de93e3df166d2f0f7bd464313b9d8" . + "c9d4fdf2bb2dc9073d1ecfa28613c600a511d34707c3109061a166d9bd4d31a6" . + . + "3c41202a5dd01de04a655ec39f4eb114b036e79505b1d6735caebd9f9ef7562c" . + "63fa6dce005750ce4438324ea09ff52d105db23fcdb34485ace0e76adcb3d10d" . + "2567110cb06e83571f3462c7ca69b7df4ec5fa2671b8070754e237d3df13ca39" . + "5e4a314f5bb6a18226c567c9cef9bf24a5616947cb69ca4aadacef7943b95cff" . + "5c9d9fb0ce195435ef1c48e7951e16e16c5904961f70653dbe8fb13bd0402e39" . + "37647b12129d95833ac8cc5ee322511d2573f0d89766fd6fdfc13c8d36fd5ce6" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7f8d52232b09c215601e0ab6aeb23fb653fd23f5bcfe249bb20f24daca548327" . + "61f3e73f38dc9b67a162c5ca062c36db2d97a6e2646eaf595e92bbac285ca340" . + "602343bd2c970793d7495bad4338d5587ec32e80cea82743b29dee2afad972aa" . + "404f46abec9181a511136dc17b145d1e6a88e841af24817ef3e2e0e99d443593" . + . + "7eb62394eef43ebf4f6034564489f37c95e59c8fd3f6ad63967cd6ba444c78ac" . + "042a10d51a8f5d157129ed6ad744fcc7b54dab554cc05776e620788d10be9a04" . + "51340421b835bb0713f473205fcd727c1f9931f181ea9895e674ec83f01f945b" . + "eada246249f70976fe63e1d131e1aa4d5e395e6812f9ad860c54a790bded69af" . + "000ca700e0750ba1fba360d7cadcd8e0557843c4f49210e8da12a7d6b5d19471" . + "fa784d15b134ac988f6789d9a4684c85ef9aba2318e8dcfd98bdb6a06e031a0a" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "58b971251314ea4df67486f770cb9068a5ea0f48da43a00a61fadf1356758708" . + "174358090126c46523e76a7249005d837fc8dfe761bfab2fd4a984c811d07a8c" . + "b7e855252633f9b84f768481dfaf85428864aa0d8994e3fa9253a12deea2a7b1" . + "eac5f097cd44c069274676291b9190f7e1f61eac7c509fa1cf0c3c7c9cf328b6" . + . + "98e32aa5eb941e5ce3fdd334c2a3bab40e11d854c64b371faca0bf37ed6d953c" . + "eb3c5ffce9707c9f7ec4f2b92ca544335fc4bc0f0837f810870ca3709fbb5f51" . + "c8512fd7c18374867604d88d1e61e17b2b37e09a5428036e52b082788c0d6e29" . + "e3d5b1d40ae5a3579a5561ce5f127e14c6598d303a06db516cfc64f29621bdbc" . + "4ec3656a3e61e8360dab7e154f4bf6cca1f8fac3018e13ad25853e2162d63865" . + "c08048b531de5723cdc4f12c2aeba1e24597cf7741ed28aecf091c56a2be5b24" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3c1854617ab59bb9f4c96ce91fed3be882d3a7e9eabbcc0f8f02f74d31d259b4" . + "174ba1079549feb4e13e0033c2f328080b5bfaa7f401946fdf0e2f97c3ddd823" . + "2fd14c76d7f4aa68c6450f66a33030b2e8b959ffc515daefb9b111f3f5e018fb" . + "3819b99d4af188027e49f32b302f22e4d240dbbcca6572829e784c0cf1892217" . + . + "b2239313bb253234ee0444bb6f1f7599fe4259f6e1eb6383cc50b1312e6e2963" . + "6b1c50425badb446e6305d1effb3166ac84e9055175fcc13813a3bdc6004a6f6" . + "425166ad64ebf10ae291ade77c9cd9f7e8d1f084f6fe42e5d0d9ef6697620d7d" . + "77c6985d4b46ff3cc7bd6e888aabfb387bbf741047089a00e1a22973f3ab2af5" . + . + "d747a876d1fa0756327708b8859b76b0c889f6898f319dcb27bd473ca2ec482c" . + "85ee43cc2cad8ad638b44ca6e764dfbd008f8c0857a7545b6c98033a641dea4c" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f58dbcdf8cdc09565b9ae861282518032948cb8b640cabafd80e9ce93ba0afad" . + "7790185e997f18d85175c75b0852b10557d5a60a6d15335691ee244298cc2a52" . + "dc6ac7f7a7325d480157436c16a1ec83fe8eaad77606f46bc63f1cb6233d21bc" . + "77e381627d687af14a5bc85219719cdfd3d0d50995fd98d588329040f4282bbe" . + . + "d841593ec083775935085cca89f7d2ae994d92835b60b255f21ed79d76d9dcb8" . + "3714c028438ba3755baaf37c544d35f935dec060dc9c7d41564c57accffbea42" . + "b781b62f5b1f1967226e72cea5da7bebf41f90c9e9f2f87bdc3107dd966e47aa" . + "90a7c4202c3a25eda3f1e6f746fe7368496b302a6a389be86894e4d4f29970ee" . + "82d580b861ae32a0d804f419f5dc17caddae87d7d896e8b25ad0f6ecf81522be" . + "be70a5d9491936f916373c990b0fa4a79554568bd555388817428951354240f7" . + "6ae5c137c2b50ee272395631700c2c0f6233ef29cbc7b34659a3c50928748fa2" . + "51648db51d77b8c0c379b77dee2d7108da4baadf89ae31f2bd158e4f4ba99658" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "999f4809729c5b9446b6df861a071d7bef40dcf0c3a35c854ad11b21dff9354d" . + "026ef8ce86ba8711aacc738b7cea9f5bbc1ddf5320d59f3d68888ec24106c399" . + "0c0e02ac9fca386d1e66af3df6c91c57227b7f1caf0fae94652a552b022de0ae" . + "326ab7bfcbedfa2badc5f15a9f6ff4b93dbae27e5c042dca27a6919c46e06b07" . + . + "f41cf583708144abba6aeb881f45dcb787602623f41dfb13502ad3d7ac20cba2" . + "01d43040cf231b6076722652c24945ce3a70c00da8a265f3989ba2956657f149" . + "c23c830cd2b423c42ca56b32d590e2e44d30413981b81fa38b0a04ece40e8c58" . + "750e866abb9ec0abfe41e157c6b4a69d3f9fd07181d480b75bb6a05f38c20968" . + . + . + "fe8a6ab94f1c37ae8eeb2eea8d45027f796361c6eadd8fb718b872842bae6741" . + "f3e945f6e831e459d5027f0ef5ff35238ca632eb38efcb250df295d5ae7eddca" . + "c011896e250368bac8101a7ee4ba767725e46c40b64df22007c358498c9fe587" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9355b07acec1b27b84cacd887dc15cb4d8ffc6f7a53679bd01df26d5943e7649" . + "5b9fdb530f286b1bc089aaf2b16cbbdab6c6636120197f5e63233f4989fa2d5f" . + "73db35122dd8bb7e41a07a5afcc25ea66b71df0dd6b6eb7925c078311627fa61" . + "a3e91ff97bcd2a7353be5558aec1667319e9146fb21971ea6792e9e175511099" . + . + "9fa2690ea6146831f9738947577d5d876a3cd735ffdf6d06620c6807274ab3d4" . + "a2156570f9ea5ca1304e33c9c0183b144f8a268763f31af7954ea11ba1609554" . + "27d7c61819002d137fffe479a8a42a5782d535b9b3e609f44e613fdf67fe6ef8" . + "f41d90f58bcd124d114ff5308a3dcef36df803444ce434545b38a3e51cb259ac" . + "9fa2690ea6146831f9738947577d5d876a3cd735ffdf6d06620c6807274ab3d4" . + "b5c4ba218624abe89d9d2ec1ad6436763bf7ba43eb584852957899cf8c02e67a" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "72f82376c643f50a2d83000d3ab0072f739b1d9eb9efc6c3b2ce8717f85eb72b" . + "b80fee7903e74068970d0e954ae7e0d282fd2758864fbe47fc34c5ced1092ee0" . + "6d0c291649fcf48d6b4a50dfb0d7f6f496bd453cd84eebb1a75f26b8102d9d96" . + "d75c876d39e0076ef3d633248cf7aaf65a734489e13f3384d72c7b8b5381696d" . + . + "1c5e79ada0a7490c465dd7d4a953b4c8fccfe2d38c42cb7b29712ae992bff342" . + "21cb26b7f0dd851ab9758f8683d625116710a0989b01f204867082e8b06b80d1" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "78c7f1c12db904ad372996b1357df7ccd137e82ccfd00a6288da16c1a9f12b70" . + "73b6c8a17942448a9c50c3a5bafcafcd119de91d4bb1ce24787e9f352f37da0a" . + "44236bfd4b70efd3c7981f9816c9aba6079e51ddf655f7d8b713526e8931795d" . + "5bec8ed2b536bc1a55dbb229ac8f5cea91222af8a929e08687de26daec838f85" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dd34e83633af5376472d69592cf72a0b03e9b8c1bf0b31a2986790ee8f9988a2" . + "20b9be7807fe9750a6e36951f2dc43eb16dc1613cfced3e62ea0b0a17c791619" . + "6f26441b68ff38b2a950fa3014dedb4f0f89a684e751e869adbf7dbae827e365" . + "93fa8b959ae6bc9cef2d3871afec6c77af1930d8b53ab4e9664da69e8d09d450" . + . + "324e3c8e570c49549af1de2ee9cbed3c53bf583986ce520c5cae42b942104d92" . + "73d066b5b7193405a5406580f96c3652dbf62bda43d79afdd81954638dc7b0b9" . + "7d090b1d7ca951538dcbe500404e1ea9f0acd11475cf709f85198aed1169d39d" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + . + "a205cfdf8548a076e9ef5ed686d179aaabc61f85b198bcd576775250fbcab0c4" . + "ce53497543f777349dd1cc4b5491459c5b168cfc66c4e9b0fcc4bdb76b73ca68" . + "41103506cb87090f403ed8efe0129d247138ee24eb7f0aef740bc2fc16096b8c" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f6553e692860a09a20144b20ca5b8cffa25dceb6cf05d66afb9fdd120b61cd77" . + "fa8b63fa2406a82f316d4d60f79f8291ae78c83a4a4997fa4bfd82aeb92f7b52" . + "542685708f3f3dd0fe731b69602408a51497bbb9597d216c3a30cc874019aaba" . + "5ab485d1e01e2834f7bb52c2baa7ac877a137ef0fc677464000c356d59782cb1" . + . + "826dfc21122364fd8d0c0259a1d3ef6f0f84fe800eebded40935855c2893c7ee" . + "258280ed7ae4823d4b940f43acb14c30c726ac669080fc7d26b9a6b3ee2c6448" . + "871043f36c9e4c425db28509d8ddcf051260e69fa1638476843d0efa554c0fbd" . + "135f7f483822d0a8c6b2c8bade5e02d870ad4a0a9337cbce897797d43ca8abde" . + . + "a8ad52026ac2a897667675cb28b83a51f4dc73cde6139bacd853e9cdf2d32927" . + "aedf26e737801685c9eed31c14e5321b4e03cfe233d079b6d79e960eba8349c1" . + "e899f29364461dd9db1cbaa0756954f48406ae8f04ad4633c26e96120e5a74f8" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "39667e09acd41f8070e012ae4530db31704daa5dd495e830767f9e05009c3840" . + "477804b8c631a79663d643dd29be09bfd0b574a292fa461aa2908fe3cd40538c" . + "4bf311259fcdd6e8d2caf7c84c94c475f4e668c15afdcf1c4b8e065c15a06a82" . + "66344bcbc52e737da1aa5d3f9778fac8d305535f0c3489cd6513851700acfb32" . + . + "309294216a4fcfff7f2e4a5bc15dba6cdf697c496e16ec8ff417e6d1adf2875f" . + "212a378a27c05b4befdd2199765a8dcc44af70bc3c620d484d120771817cccc4" . + "89cfcde24f7bf11b37070a03edd8a4b79282ee645551f6c2767bfd342f9bc37f" . + "e7462eb051fd7badcea625894913679ddfa66071a4b1a669f07a0fff4aa10ea8" . + "309294216a4fcfff7f2e4a5bc15dba6cdf697c496e16ec8ff417e6d1adf2875f" . + "ef544d48a02d88506a9711e87ae6f30712c47adccb461ed86d0aa214fdb9427a" . + "b8c4da464ed2b944d42171c5fb9c51d0ac24a307375c983aea5c6e0ec7d9d9f3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "032e18ff73023a4158f3a2e407696b0f98ff207b5c51876d680d6aa09b1d56d7" . + "b45eb4a3b9f0b58cf4fc4dab558798ff0623ff04a605004c422bf53a88659f47" . + "5fff3524971d8e4a310f7efa3820f00ce84c437197a6645928bbde5031abb996" . + "95c75b27d24cd38e08d2643736833324300966c6e963e5479d80b52a62366d18" . + . + "b176b00132da3bea2885da1c1b83e4bceca5c9dd117d3b547c2cab7dc2d9f4d4" . + "68fff71a50ddace04b8893cc927c9b677ecfaa0bf5deb31fed417c90192e890b" . + "571fef046b5221c66852243f622178305996c1d6469550997cd5ccc97047a389" . + "31026d686221cb775654c86ecdf77c0b43c262069581182e67e10bf42aedf3fc" . + "ad32a91825e9670a524369779667b86a4ad114daf51bacc141afc96aba3bbbed" . + "7beedbb34325e0e5f41f616292349747c018711757f90bfe477200c70333bda6" . + "47ca7dd8e4cd2703295af98818b48e9384e076673ed89040bdd420acf0e95fc1" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da54d2b128de5343d7b98d2bcd012a872d57ea5cd3607269386fcbc0149789a0" . + "653d4b688ef06e71ae56a1bbe1e091eddb1ece285a84e712d3b865a10cee5035" . + "8db1be53e2f6c471d22eddef8e770f58c58d940e5777a270ec4bbf1fc68ecc01" . + "df5242a6fa59ff8a61a3f94e8ac72252ececa41083570b824720d021ece3730a" . + . + "a1169b6028c34e8c41fdea09f0e579da33939d8d9647138cd4b1ff6a3e26392d" . + "7c78641bc66d2c19245b69b113f9a5ca35b05c1ecd7468f172214fffacfeea11" . + "fdf2a7ba84030f74258631dccc859548af074636b8fccd0159b6e3d37e8f6cb6" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + . + . + . + . + . + . + . + . + "1cc83ebdfb72257d401c6cfe1517b1662dbafca9e19defcef45e0f3f5cd6e32e" . + "d418531896cbf86e4826707eba120eedcf13edd0de1ada00312bf0e7cd080015" . + "77daa11419a7c5dbc496d33cc65bf23b25abba7481b4bf56589fe438444e0bef" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44d522e00d361adcf07c31972426edb33345a1144b02c9575611a9c2c3f55f24" . + "f66f9aeb7e2fb1165aab92f1fc5b6a311b7f345803b38d64d6f5d395ed082dcb" . + "949ae97db49b24083b67a3ff3e4bd079917fc54768b7bc89ca9d6b1c1cdc6ae9" . + "2306cb39650bac1926eb2e95147400788a2945d328db52d7abe2c73306798fae" . + . + "1ca53ce8cb51d61d33deb65627a6a53e31acae1331bd5abf14f3eed7c7a21819" . + "f5baca1108c8f327805676b7af77da9f5c015aefbfb764436d2ace8e4eaec145" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + "cf671f94334faa1550bee3acde146efd0801878ee315e55d9709ffbe16422e71" . + "239bf635e78ca226f20624422189dff836e53bf1384fd57665aa221faf0671bd" . + "6cef1257190052c43ba9aa0899ef7355e18b2bc4e3632657934d7cd243bfcfdb" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5b22fcc119b98db291f87f41c3d89e15dbab82f97dd32a32fc792a47a0808fe8" . + "ac5577d14e5669931d53a38e72a738102ff31b0940e0d1496829da6bf384fb73" . + "28bd8de6589d4a60558abbc63e7cf5df48c7ae8fe5de72f41dfcf3257cdfe723" . + "38cd87fb2949b706a83fa6686f3a0d6011b3e70347614d628a97f637fe39568a" . + . + "7b9a7c35b4baf0a3fb955c20a15754e40ab1e15c62d38bbd345dc225697a0c52" . + "b2c9c4e51a429bf36ff9b7b4dc92549626b5cd1fbe9ef07ffa1f7c5740072720" . + "821ba5a1e698ddf5c09ab58c145b6bd454d7b335f797a5c88ce8d829b89e37bb" . + "f3ed393b90957f3a99a5adad03e83acfe9d5488fe046c3797517de46c53f3506" . + "f9d3c24e3ad8c11546bcf1209c2188aebe6d0d6e02214626eaea5d8325e0769a" . + "03cc02d8fbac98e6db527cb82bb360dae58a1f5c63efaaca854366f1082ac7ad" . + "9d92e39f495017efc46693c68ea487b612f7d138bb30dc0b262bf0d941255519" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d79fdd689e982bb33c90914964475440adebee9621660fdc286c06eb278fccef" . + "fd059280689e02e9008ac88a76805177100b9d0161f2a4163e9431c2632c3be2" . + "3f78ec41ec77b7767da11c2b192ced510d9d2e67cf9981b42483d0d27cce21a3" . + "dee967e45c20d20f703452f51b0929b72a1a12dc61a5c7aadf9f52cafd48aea8" . + . + "a62f95450e7089f87737509130bfe63a710c988ef526e0312fc62051592e9b36" . + "c58d1f496fcfed146c6bff2bf9a479973b61b6385d5c3d3bbfe42dad8b6cd5ef" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "8922f270f71a0468c02e9b498430e50f1a2b2eb16d875ba9bb4683153000e28d" . + "fa7190c15eae6bf451be2c6155fec3ad0683d1b07ddcb76fd009ff80d0074030" . + "52835f314218a63df783110e81c455145faeb99a407bc1ace5ea5fe400476c05" . + "a600896d3296f7674e570a19065762d9052ef860e8eac5137bcb859408c349f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3695192306507885e121e87c4f78af1061a3969b70dbbec9e61c3fde10f825cb" . + "fcad24214a9a20dd18429d14a82b53a487372886355828be3e3f372f16c5fc84" . + "e6528af805d2ee7934fc1c9181e355e9a93289d573c6b4f64ae86e3c56a53ffb" . + "da6733de0e33b2ff04b2a85b312836c7b9dee1a60053aff9ea12ea83d3a6b4c2" . + . + "37d46c5213a1a195d99751cc7629702ba5015b2d56c6210db098cd0444131048" . + "a6629cc2739f3cc8bca937a688fce90d55806b20e581dea1220d285ad3e1266b" . + "7b06acb4e96263bf4e0a1b21846da069e6ca9db827a83e24969be831be422e56" . + "2fa62db37491d7228cab8ab7b5ff0d1d163b7115b8c46384d0f1d93460c1a390" . + . + . + . + . + . + . + . + . + . + . + "03b8e48f8ac9115baed4b3155665dd350dc54cc9848cf3c513e7dbd6b0e85244" . + "afaf58b00430e7b2f866ac18c2ef07d21d9c7e87bb13db74736d1600942d4174" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fa799b0ce4b9ad9d34e7961348a0abaaf7903fb5c57044cbb25a375540c1faed" . + "35ee3e2fdc7bc4021812892cb582d65e787f9a4a4012733953ea7f9bd0a0943c" . + "6271e3e33ea2b759f0218b5f23627358d8c5a81c034badd85b1224d9d5997235" . + "732b9e0ac9e1088883b3c917081c961f09050a7b4dcb419d6c24aed820f836c5" . + . + "95d8f84aa718e542127bab1f7367b46286955d5d8fbc88ae1c5402ec3bbc0d2c" . + "63238c470a068370378f998ec1aaa16548d18d77f7ba6d5975ddd37300ba3078" . + "7274d95c7a559991c2d894da47944dae404797644c01769e6c75cef0977e98a2" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "2a25cb2f0f636d3e76b3518ef6a99f3ad9c212e16f0a73b29ff8bb1945a1ee3b" . + "31d90be74b05526c7ef14df063632b2e3b634f3cfd3418f8734073ee345cc0f5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f34f66df4ae3121639084e3815069fb581748bf16a769afbdaf12365996c37f7" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "672dbcbaffaf85774d5a0161732743df9276bee0b50d5c0d0fb0aa7d625422a3" . + "fe721f167288499d7eb3332c525b6c7eb0d7956510c4fd50864fbb28f97d16b7" . + . + "c8d80ab87a513b051e5002de68dfa7ad43af110da8b011de540c8c4e284f970a" . + "e0470436c3ebc2ff0a370a7372f3994a177f5630fb9b2c3621a1fa466c2f7e02" . + "6c8a3e9cb5dd62b780312f28b9bab298e953281eb72952879327957f9666461d" . + "d7bc7203123b56bbeb1c0b082e7ba0941d9ef46adec4163416e52b27f9c83672" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "956878a581107310d995556839331f04d21014958ed9b05269094d14430c1eb5" . + "fe482109c9f5d93336dfd1f5206bd2e85b3a40ac350e6395cacf44b06486f687" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "10641d64ad0262417b8956b07ae2d03cbc734d9a97acc4f1590e9c5247cc09e2" . + "360922447e0d02cae72a2a9add6d0f93f402b72a3b317dc7755ff79df5710833" . + "4dbb1ad90f6c4ae4a8181334dd0abe798112a622a1afe4999dadb3571dddb7dd" . + "37289e3f6aa459b1b5109ba8ffae27b6db5adbf9189efcebdce16f2dc59f1baf" . + . + "51ed1a734ea2fcc6f3afcd953fe3c320189524002dc406208b19c2d6ea217750" . + "45a15dc5a9d8e0179e99bcac115f9ce2db164f58d837e060a6b0f92262643efe" . + "e68990e1068c144bd1157e5f2d52a791349dc7c8c810a1de80afea522bf613a6" . + "138173d8289e855bff066829ea9862c3f5f28d45dbed0b4f2b0cae6c1c8494cd" . + "17eda503e49d59284bdcccee294561cfd081d1e507cb7269cae984051f3784bd" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "45a15dc5a9d8e0179e99bcac115f9ce2db164f58d837e060a6b0f92262643efe" . + "764cc31c297eb39732afe9557f72d0214f2ef3a0e1f8e66b1ff1cedb8a1059f2" . + "fa834533fed5d1689bc97caf01f77c930f7bc8a4531890f490ba746f1006a171" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "def3b99306faea9ed192586db1dc7d28dc49b75faa030b2811c5969872d5b4c1" . + "4631b01a0fa80d0a825bca4ac4928f646618363068e62786bf211008179a5837" . + "116ac7ff4b3f03c99290168eed44748931ba48799706a79216c978f247002d60" . + "0c0bebe846249901637c2c9afbd0abf023a9da0f6454bcf31b378ff90f942a40" . + . + "2f302d740b7a2d97deae67d9c65f065ae3f074d176f489339483f20f07b185ca" . + "7ced64d16ed0adfa34d4d78caf72322ce71fe6f8d319427508dcde09d21ed69c" . + "5a914724fe755ad113b5436d825797b0ce18a25f3d97944af7463243dffdcf06" . + "0d956e3d91047b07dc1c132ce35a2fdd881180878f80a60620f8a24b5fbfc771" . + "2b40486bfbadccdd6ea3448bfbd37d77dbf66dfbe6cbbcb452e26b267d6c9cb6" . + "54b53861f270ca9b13c096a867a715fd5e7abdf048d4a8fd91bdf4b980073b41" . + "365844ed5fe357bb340c0404c23140b98859a941cc66878ffb9fb905e04729d5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "55395fa5000fab1f54ea38ce4c8a9790a60ab6d6b93e4d84861c3c61e332f3b9" . + "fa61ace0859362eaed3999d10999ed45bda97040f113c65552a3de68f9ed30dd" . + "7ec68c3f39db2ac2abf8d56c52f5a1c64b9f08587eb284f8e93e2896a4ef1d92" . + "3885a88900d341ea192eb73272647b57fdb501717cc7fac8048196061b7fdcec" . + . + "8cb16bfe35467bab19096a9af0dfe596d1ed15c6904ac6234f2f23883c82127d" . + "1d19b3e0d58ea288f664315a45b247765e784bad1aedbd7a4fc6811e8251fb56" . + "777be93175bc9f38ba776d15f2858e8618a9a6c5d277d421179ca533da4b0866" . + "f90650e33208f4ad39b6cbfa69ae45b40ae10d356863d42fd9eac37e80569daa" . + "af500860ef81866022d72a7adb5b80076ce09f245384d1932f7248d5524d9efd" . + "60f4d555a37998fb60287a0e03b37eafb967743e04978ccfc3f0d4a48e619eb7" . + "5649bd23a39d1f5bb9b09ddeb83aed05a96e879ec79d918af243802604efa126" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a445c9aeb241ca3db2f7439c624f5f16e064154194f20df1b360bedb8f025fa7" . + "5f071f8bf069a92588607dc365a5e1a8c492666b8faed82c60d70cc64203adc8" . + "a815a54a757ab02dbbc5b7e75539468c5318dc7afbf4bde135b577d468eeecd4" . + "b9c6b1307f91d0f0c699bc11e42f83104e1196cdf2df77bced6187e561ad454d" . + . + "f1bea9e96d7aabcfb8bcd8898ba7e94189d239358debf37fa9ede11f3ff6c8ca" . + "59076bf1e6bdc3b543c140a4746126a7b94cf13cf224a4d215e254be7fea5bde" . + "c4e8da17725247b855c4a814fc40f08c544674a262b2067ee148331e209aee7e" . + "e96b966e2987760f16657fb22132ca5185544ae6061497ce7672bc675c73b731" . + "f1bea9e96d7aabcfb8bcd8898ba7e94189d239358debf37fa9ede11f3ff6c8ca" . + "a6ac89c7d9b5fcd79de04d603b50a77ea37fe0460a9364e08f59046a5e609425" . + "28b0b0890cc69ba7b1d91db4a6dc12cc8d1fcc78c05c141f5d96f04edb31f531" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cf200de4225964b16871046052c564a878b672da471cb64ce26b7ada0dbfad30" . + "44b69080b764f07e3ee70c8de656f8a241618a36ff67824fa635d10a213a0525" . + "532f881bd0d001104594640413002479f6a897beda6011014f20df9fd6d71d81" . + "30612057d7967db9b9771f5b30a2b9cb2d1528e4cf5c6d33927dbde1bda850fd" . + . + . + . + . + . + . + . + "2211121d5c550abaeb8a15ca0bed516f752b6df9ea433565b2ae4e70a7912055" . + "989ca7b287b4de20e9c0c6f04fe19d8d6c1cae39b0c269402756fca13bc51303" . + "046609023ebf7ab8fa80e36d1793b7a82f035cacfdb3ed2a5f21f415e90c4cf5" . + "c2a389745ab23f9a9f12f99d35fe98c71557371bf46630c115cc483d6f506f72" . + "8446ea33c3cb0c2402f9abeb71ce59e05cee9e8d66fad102fdda22465e4b2ba1" . + "61c2c5af461aa0104492c894a72fef3022a552f98974242530df8a582dd9c48a" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cee029118d0d283554d1f12179310b28e87193a5bb962a1ab42ebbbd6f29a34c" . + "837af5d00ff9367b0850c35eaaa8bffea772dc2402e71b61969dfbd802168080" . + "e4c3c2169739d206d970458cac04100ee9728082866c09d226621d033852bfb3" . + "cd10512e148d6f6715c340847202a7b225a1518d948fb37a9d5086cdbf07b03b" . + . + "5f36da7ea5ea5cb0d1a225df19f425111ecff8d86277962b0704ea12eb2f5374" . + "6840a7dfaf0e6306a9737958243f89e63e2b88675e773a6eee955715eec156e1" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + . + "59e26f71b041e2ce6abb872d506827b4cdbd459a75b04a4565feaa8b7c64c985" . + "dabcab9589c156cb33548fc063edd1ca256c22a02b9097330fdfe60576e8cbcd" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c082176ccc498a9378f6983f85ac1ed37626321ee1ee687d0202fcdbb62ffdd0" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "3674ae80f9f7ca07881b6f97a58e3b9c065e8cb7f57c3f6548b5592ce9972f23" . + "e594cde2b661b7043dc1750c930af7d34fecd0a5a7bc30fed0b758b21db5496d" . + . + "926a308e3494e35fd30ba8b8e5cf835e1c4c0242d14f6420efda7c623d2213ae" . + "aa6e04ee7bf74d19244d64a28799fad76744c02c200796d98a65a9183fbe6330" . + "f6f550c1f196ed8ebf8ad744365bfa245179e65a3cac7aaa3d014e176f3edb57" . + "403f2100b5bdcc375d641e10c6375babcff4a6df6d556f6558a1dc3bad5f5973" . + . + . + . + "5217c0e6245b1cde6e3e9c9db1b3cc713d105b90c9deda22d95bb9d04ad75bf3" . + "7bcfe3d17f87916271c629dd759b694835e1f29f7d1c8d798c51761dbb1dcb06" . + "bd15ddb151fb1547aa8f6e3bdf952440b4ac489b4ac1f6eca3d28934c745a7a2" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aea055e65bf20bd42cb7bada9457ab354d2cfee1992624d8cf02ebd287f0a87c" . + "83aa8a3e5cf8941d93b7e80859a4c7d19f96ab4f32d150436312ca40b3bb48fb" . + "734f2af9d84f3de115a9e666bb0b7310c095c5b038e29438093d7c0dea9493bd" . + "6dfe760248a40ce13169633a16c5b9cb7dc65435d7798ca22e00ed1e18658361" . + . + "574959c59932198dfd6a0af6603884220852c57c5db96d7fd5d4e53ff158681a" . + "45c920fdaf2a5108e5870ff1b1a260b66a1e1c56e67aec7d5bcfdc38f481ca86" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "47a7a9d0a634bad9b003cecaefcf27878791d1d79f8b1b9f78ab65b1d0025711" . + "574959c59932198dfd6a0af6603884220852c57c5db96d7fd5d4e53ff158681a" . + "75cef94a9d9e1d194b210b3e20d981b75e4cceff22967bb5f5ada7ebdfa098e8" . + "1b55b26122b9f0bb1d72f2506b96c20ac4e1aba5e486c5297522df8de1da87b1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "abbbf6b39a798522922417082e8397cd6d20eff5c3a9824cd3eb4fbcb9b06a41" . + "b39a766ca6437fca9e0c6e04e9b02f4b852879145af0442f72a2c47ae02a992a" . + "e9923492d75ab856ac8c39dd51c78b568418c1cdedf295af599cb378711ff64b" . + "720a0bbd50fea267bdfb716d2bbf471686224d2f25c81862b834c37bc2f1b1e4" . + . + "ae453e3faea9fbba031ea28aa93c76cff8edbca5f3b66ee4ec68e9a4cb1c373d" . + "9d8f9c4f3e3d1c31fbe656f321f40fecee96e8caac40c136e1a2d99b1ba2b5cb" . + "afce873d7f207ab19461f1ae9e2499006d112bd9aa4cd63b953cf2d1fab7f2bb" . + "384fdea2b04acdb618d53a1075aefabc950fd23b9aa1b7fcabd3d354301ed4a6" . + . + . + "c2d7846924549ce7658fdebe9d37851c2a1039405552727135393e283e2a8c66" . + "f632461558dd61b33c498e40c716950a4809eadc2fdfbc53529ac59b9c2cfe15" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "06cbf99b78a63b5554fd3d1d059bdb752cd8f04dee3491fede4c2843a732e81c" . + "67528d6aae70cbc1fe7cc740fb3720d13c060f22499148323caaa31ec1670e94" . + "dfcc32f505c698b1df862d8a31c711b920aee0551b7d820c44dce8283366eab7" . + "7f6a227ba15b13567ef31a0d55f8833aba0666f6b8e69e7415c000109f9eb692" . + . + "b97803181a92a8d55f4b2e5475307cdbee18a702614e5363fc238c636b58cd52" . + "c721da7e4393351d5e0d84fb59ae5702362327b7c70d254eca7203b146897c1f" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + . + . + "b6c24cef2fe488c634e21da58c2fca1279042c4368157a0ec3921df05207643c" . + "dfaa04b3276e2ebc9544d07e477895633e3ad8c225e8f472fa4c72a63cc16593" . + "bc5f71fb6dc0745b9aa5bea891db52990abde28f8320905c954f49d29f1090aa" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "32a97bdbb037d9fd21a9056f4d5b1b9f8f90e12e75dd4b28a4e6887c57b41b06" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "913f52e112cf088b93d76e7dcf9cee5f9eb399e3a7416d53270f0cf43ed749e6" . + "a2c808991a802768fd8de54c7d93e000fcfdec78c52fd33c0a3ddece23cf39af" . + . + "de0cb8721735c1dc6d071a2e10f147534ea41efec0a11305eeda3fe1bea12f39" . + "d7fdcf372f96ce87df3d4d182798559ea503e25a91808286c1fc7b90fed75422" . + "f56f88ac9b86692ec9114883ea83b2b7ac75c9f2e4362b328ac945a3c41b5d4b" . + "0b431da068680bd412fd8eecee7067d10ef529def76937acaa3216f947cbb227" . + "dc02a91eba1fdfe282fc25a8b5c657c7c9c4fb88a7c661744959de1438ba5bb5" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f02a7deb80162751fca015dd5f48f4a72e82ea3b62b3044b4fbc18c44eb0a529" . + "f68497c78d919f5f9b07f51b8b35d4d4d3c6bfa57c8b9b0554632dc56d8905c7" . + "9c4a6a95607394baab04ab3aa7c771e6aaf0e20616cc1c5a5e56406e8917005d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "71df436740e314ab5d9d34d5b777775b72eba76b932d7fd5bd1d0a7284e9365c" . + "a4737788cbe782f4855764969210f0fece7821857e8538ead41b059af526cde8" . + "14ec41f8891644f33c71adcf46d8693310c88d8f9082a677003d2a4e16699b41" . + "2b0e2e33abe72e4b061c30cd2ee5e05050bc4b59390c4a4657073db4d45b98e6" . + . + "d04415ca70674830ef86393778a0b434bef05b188c901c7119365ca2a034efc2" . + "932b2a580c6df0fa6edb1c0588b465ef874298e57698c2860176e06e21a2b702" . + "473c9b41273439562bdb46f8036560e0801042366d14bd8fbe67c816b1bc9159" . + "d2be66257a086c09c76a9e1fe6a0f6d55b1bd887e4b97831c9316ec55641892a" . + . + . + "af052ee8e5e862a9218125d58348e4b7b7b69fe49fa2f1ed6a336cf3c9713232" . + "5d399850e62e6a0d7b4e019cc2e665b8f8a181502ce5db8eeceabcbe36dba0e3" . + "a6b714fcd190bb8a2a0b8f5d31b42e5a230a98223f509bbfa8f532f2ec8cc67e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0c9714212e97978f443aac4b54bccaba135457779d059a01f39fb9abeac04e65" . + "6eb6460b5415326f6325a223973fee5953d3d5458ef6490d7048adb958b2ffb1" . + "baad83f5ad64d97eedc395ba6acd4337588488ab98af5f07770992e543ef3a0b" . + "ec62b202b50440b559cc3981cea308894f1cbadbe547d3bfd696b0c6a019f633" . + . + "8866c436553ee98c2a51857283a7a504dcca2f3a69d8de5e005f99dcc0e17ed3" . + "ced71dda49465fb52d8a2b4162166343a034509c5df70ec52a29c6101ab010d6" . + "f5b98bae1cc2e293f4259181611db1ab5c39d09a4a39c2ac8af1f9277092ced9" . + "980674906345fbdaf4f3591983f8ce3562872aafc7b97266185317d7f9f7be39" . + . + "7839016f3a4d6aa25f519959950d9ee7ec09bf0884f7cf6ee73ea070267d8695" . + "7150b477e13e4fa8df3524ddd033511cacdcad92a156a60fa5f3b5510012273e" . + "03d991442d36c8970dd4fc3e26a9eb8fa07ebcaa8909be7944c61e53694a6235" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd1efff3777d04c1b103576141932cc2d958c3546009e7944601baea33ccb5a6" . + "477804b8c631a79663d643dd29be09bfd0b574a292fa461aa2908fe3cd40538c" . + "4ef49ce8068cd86fedcfec031a62254c76e4a28dd579b8af503f48e36387728f" . + "2eef390df64924b9fdf05df0824f6675a4cf23a0831e1dd79b15484b79abf7ea" . + . + "0359c2b178797fd825d5a75739f5586701ba09171177a3c7d699d6bbe2af9b95" . + "55c8e1c6735aa8863a5cf46d401e73dec09946bd342318a6f1ed509c75cb62e2" . + "bc90cd3a568d440fd0706f77b1399ebd848016dd5852fdcf41203eaa587de582" . + "783e6a04c7965fd9ef54fa349aad9a9f48b18cb211e8e5703f63dc35289428b8" . + . + . + "6cc5372c31aac297f7f6480217b300d319a8433a5095d40e5f221aceb28c73f8" . + "3982c7d8a60ef950b06572cc934a4d1ade51a65234550f39617f925baeb49291" . + "5a27623f87094e918ec6e03dd8e182d2da6a610585da768b127173d293b00e4d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc8b5103c98f8575079f369e5d6301b6213570b7d5556cdb25b8cb657bbd9ab2" . + "19479f0f711b8ac58745199de4e01a22e7ee00d73ae238bf0c53d1e46f55e4ab" . + "ae6742ae7e35e11b1c12e9e1be593f9ca60eee0f0b6301b8292ae73d3997c787" . + "588c74686130f4e344979961712c691806ac69eebe87fe07501e689825a32629" . + . + "f1c54fbf98c47df0d67c880fa90125c675fc891a4e062b66062721d633f6fc0f" . + "76b31719c891d9b2cffba5aaa9026b17b12dc80851734d656e15e468c0088a5c" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "e30262c6dd556c127f1ccbf69fab4dc34e487370cd6e932da50b6fd64ea6c646" . + "bd27ce3dc7fe31ed7f4cd5ba6a594f6596a37fa9a5eb3cc405f4fc03216c15e0" . + "1ba25749b0d993968a5f733793a2afc324873e9c0fbd794878f115499552b5ba" . + "492d688706313fb6c9527082bb5fbf95a2435c7d09394638dc509c2b916392dd" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3496825c78facc5795dd612b5044c6d1845626a965bcdf674dccc37a71e6194d" . + "54526585d156586c00b4ff0fabc216027b47bacd36f63f33e81bc701558144d8" . + "9389f34fb2441f41ed749fefce83b315b6dcc7b1f2880112e469060b609ef3b2" . + "e20655f03f7511df98c4227e8492f020df000c5327bd03a5c5994f2172a4ee0c" . + . + "85b85d2a2ec5e2dc5e4e0e385fbb5a12ded701975272a66457c8728ef4355516" . + "544eac02e3eae83296be702e2c0a98983f92cf47a6a6fa8e3f908967fcbad432" . + "575f7600a918d28ddf9b85bf8b1b404c1fedbbe5de44d637437da5deecfd76ec" . + "a4b06101d3228ffff24eab4d232d2e50cca9b0f06f58d9beebc3de512dbe8b1a" . + . + . + . + . + . + "85b85d2a2ec5e2dc5e4e0e385fbb5a12ded701975272a66457c8728ef4355516" . + "805a18cb86dd347dafe38a6ab1580a6181c7e03db6f04191ee35c8882739f52a" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1ca62a7a00bff84ae63a6663dbe26c66e949f666f843508c08a32ad6e52eef5c" . + "e183e4ad227c3a79512ebb7fb4a4745040b96317db39462270f55a705e7b7e4c" . + "577c73e45f3a56a89038251bbdc0ee522d598b5c9c3be3cb1148a5b0f6fc34ed" . + "36d8aaccddce78424de117e2e77c149abbf9aaea44eb5ff625bcb0e0f3939d5b" . + . + "05dc44e6d6abee3195cc3a00dad8e6895a6967b62d08c576b0b427b20c3facdc" . + "6c6da19d20f80dcb4fd54802297bf1d96069a213da410587e8139cd6926871f2" . + "a9630fb437046faf1d2c807693fc8cedf68dc65f8bf14936451b4e6007df7c9c" . + "b8b7f2e544265fdff39ae6bd5c3b7c2d63d452c94a63ba6d82a0145b89a0130f" . + . + "af63e977438d1cccfec814291261b4c518493290014e5d8efcc2c733e15e3c75" . + "0f168c5cf83ba2a2a4b88c914154d300f66ab9bac0e232efab01672131fc4267" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0877c262f96ea9420e63c28512a54a5136b53a5ad50dfe80d81103b1c0260e8e" . + "7abe6b77f0edc102d58c30113a0ce1588c5ea8ee4035dedf33718319430237e7" . + "181623c1ddd79e5667a4300eeb83815337db9d5b99935cd72b730cc3fbea759e" . + "4a18c07acea66a5682a1c1865f77a60793c25079bc7dd14ea7803992ada8b2f2" . + . + "7cbd1453a329f7e96e149e72ef10834ef092faaeeb3b2dd6b9fa6ab6bc94226e" . + "da75f746715fcb0915d15825f10e31a7c9c635b774c0abdc4ab91d935ef10f4b" . + "05dc82a60bfb04d0194164443c3f83bc8210abdf213b98f82afa4ac6ccce7b8c" . + "fee2ac3e1f8fc1df251dc375510e93ec2552cd1a2d45a9696cbed47a786d826e" . + "547d3efac2897935da812fb345af5d19d661228f5c786fd39e72b211f7f2543f" . + "9c787cab58b0834a227b19643a625d4861ec9730cbe462b66fb7220a0dd60bb0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d6cdacc20f89f987b04429f0261d69d788af16c6278c25ffb8bcb18e1f9ffa6" . + "e6392c3860839d6334e57a5b735fbc16e34c0ff96e7880c62e08625989b80306" . + "6304bc0e23d35f7cf4dc1b394e895cda280953ec1c6c3ba5a2bf53d93b6cd895" . + "d391651add08236c220d3a395e7b3b5e297dea5781277471d4bed7500bd86568" . + . + "0a550ed0e2671adcd3ef7ebaa865ce0758ee1bd9c661aa331f4a471aa48e0867" . + "8fb06a69e6833646a641caa25bbaf8fd50fa5df019e65246ff039d01b11203fb" . + "e9050fdba47ffeb9dacfe7692af10ebb29bf689aac1b19acdbfbf2c5269437ea" . + "3c7d6a0af1e2ff0a38fd5012466d8e76328ae2b85f313b4c16fee0f70df46354" . + "a49939de8cd3bb1a02df6a608e8e53c6f93b5771a57773afd49b799c9b25ea17" . + "8807751d5ffdc0a6e57d350ce8d21797ed36cd4afc0c9c87e7cacd728f94f9d0" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e1dec935913625b082e201d520eb9daa532c5faa19066a4c556dfdeaa595aea8" . + "5a48283c960c11da51528ba1b68af4ef3add85e83fca5ed5280dcae8d61f7354" . + "1dad0cf507cc6e9b98f0e60ad3b8f6a9a5a382599c29d29dec65500eab40eb0d" . + "39dfffe182e4d106d02037331346da0c3f0a17895ec66a99f71cf5c39a664b09" . + . + "3bd40873a74c68a9d87c35a2ee656e0f9c5baf6ecfc74c3be87fe00c724b90ae" . + "63fed2dae5a2e13f543b073ca654a2a92941c2a51c5b0692c114d3fa142d90e4" . + "a578f00c9b4c8e5c863f99c93aef900246113b1ad1d037d6e29dfb0228cd76dd" . + "d8fd11425b096a14662a314fa299fdbf2285c7e3fb2fa32cc8089fbc15c3121f" . + . + . + "c8a9d2a5a8564e76500e0f7d1d3c1d1c063f1ddefb21e2d515b4c4b61e30a710" . + "b1266710e0ac6f99a6b46b43fd0f798b08856fd63cb9244ce1dd0f1a12905000" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4432c918be02701314a906879c88d8d30bb1da1623cf877298a9ef9997724e4f" . + "0ae0eee4fdb65276fc7aba42e0b588cca84d8a85819c004520da9be199382b97" . + "3eb07687cc8c4bb7b4d0e63b6afa47a09feed1aac6da3fd697866cdfbcc18c99" . + "9ed2522bb265c2c6953faeb915fb6fb3836a2d2883bda2f0b2af8e727acb2a15" . + . + "0e4546039a2c42552f25ac3a330198e33e79161d1fe9f29a6440bf6a924d6cd7" . + "41ad12f03cf4d4d4cdf45f46124f16698b1d4d87b0bff9fa79e09d68d90b029b" . + "b3f226147c4b9272043a35fc04e84b7bd3cf869815de1ec52041652474531ab9" . + "ea088b9765a0bae104902994b80efabb58e5c73a1bac39270ac2f6fdd8ff4f1f" . + "fb91ad1b6b43e35fe9c18e46e67ec69e3ddda7390f680d4d1339a1c3bbf40734" . + "2a657b60c4e8499284b3344776775c9a17793fbfa6bdafa46374ab748c1e3f01" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "44eca0d3a67fbcf22f7973025e3e095390ba142066d8feeeb796cccc7aac5dc8" . + "1d29744562592179db558db58f6261a59e7f4e004100e34d0300ecf188d36017" . + "563af0233527fe66920141acb341f0a7932807fe37e5e9cdc7b5b5b096b9ed77" . + "bcb9372b2535c9b466269385d97f719109c338e3dbf6a2a0d17d1afb9df5ab49" . + . + "3d50e8dfbd6e9d98d503dbdd371f0896b67b6f98884de6b1bbc711bff2508994" . + "3f446e27e3f4499a5f3dd967c7d2411d8473ef47e53d3ca9fbd83a3364039a86" . + "2a0303df99074833613f4a1a59b92e1d5bebcb51a527f3f115a14c8107a358e4" . + "6eb8a0c3fce3ee720ea65786bce45487dd535417d84994efd144b3fc5c5d8328" . + . + "b6b2a753947af185df42cb187ba828c9b58831aa5249e965fc8b6b0edd8938e3" . + "1fc92f2c4d8303d866de54556f2470c335764569c2de0e5cf6bfd186bc456cc5" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5717790cef846983f0c8323bc7770a86c492e810d0751f7ef66ba523de8cebbc" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "48af8b33ac17330d3ea1e7c04b968ac148aa03fc9f266ab61a0185a8413e0108" . + "1ffa2fdb5be30fed10d354941706dca507d2ca45e0022b2fc91b2e4a2c12e715" . + . + "c076a43310a8a755e12338d8755a422c90db09a9a2744584259a15213ae145da" . + "dfecb0da64570bc32478c0dcb703e61c1786ec6b6c210171096df09034654119" . + "b0d86e92dae4406c599754b16c8a0fa6877d50aef19c500a5d3b6039782a6358" . + "b55bb7a3402acbc04a3c6855ba4358158b294b52347f0c863de03ebacb13f2c7" . + "9c9d99a64f985d0744737b9119a0cc1d52a4404dc855071d018f63d4355640c2" . + "a8bd30e71bacc97b12e8d8b75f8e10823e86f3047d7e41ea138425580295a1bb" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "07e13f7dc0bad864b28e5b1d7dab5fe533bf845aa8888be89e19a66eae5bd3d7" . + "5e61af98f8f14a58c5827f6b411e1718b1381fc3f482eb6ab5d4b7eabebee58c" . + "83ab108794c5ece8c191c16fb93158423975a2416a7859d29b87178b3b640ccb" . + "cad26d80d2b4c832609315760b25f53ad869e8a55e4e6c92acf3d6b703036380" . + . + "850ac0dc6814ef9fa574d360ccc84c816933234ad52a69746770b4dea2ee242e" . + "366f3c867a1255410a422ba772b01c3f068a41bcb25543f3890fd5ff918d7d7f" . + "3322af7d3b9fed43de42c37551d7db25537d8932e21b3855bc172db834b4340f" . + "7034e5484f28e7cd21b2d925653713a7867f1fee5c80757af76d16b481994b7a" . + . + . + . + . + . + . + . + . + . + "a9c32c411b7ff8c8be5415004d9c7b9d8a00ff573ce0696ecf0496bee35e768a" . + "d06ca5f3c88da7675c0fc619c279030a1ea974ab4b65e3c16ffdc89dc1ac9ccd" . + "65b378b0fe38dbf550ee1d0cee79e719d01e20835caaff155a09a6cfd0f389a1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1a8bda322f0581b018d80a501319851d1f05686b8d947662bf16e435efa6c379" . + "907bd32a6e05d3c0e4ddcb50bba45653c2d76411e323502046edf07163baaf4c" . + "a00f8fc9b59d5a33d39fe2a4a23d20626833114b2ef48745bc8e67a31b8fa797" . + "4156160f4ade38f56c6ca456bd5a66ef5b1514b273e9bb0abbb3fd1ce1b46504" . + . + "2ab6900e12202e8ddf716a6bac4944c485161fd83ec821d019fbe111e1f0c487" . + "e21ace1d84ee7cefcce459f80cf696e8e51ee91074c4e84240a7860a0f79a167" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "e3ac7152a4d58e15de8d215f780aa5d52534948b196c08600cc9140da25a3310" . + "ce6735d836bf8be9f3134001a695486a90b98ad41561e3f014eb51698e90b46b" . + "e73872d2c471b02d945fe3800f7a6e70381a349343307df60920de4a1ac0cadb" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a08853d6bce93c5875d93c42b85e0e3b05da03da926c99d546dec2984b4dc329" . + "2ab32e2537f4b24b19c7648d7dcc23f48605b9c0adfe75687c15cee13d18259f" . + "b7af9f20eb7c614dd834794ab5f35743d26003b6fea4547739181b5a642f685a" . + "8da0a128fb6d708a2b85ab00aaeba217831af24358e4549b1bb5183f8b7c1227" . + . + "59eb495ab48b0a2ffa5b860f75de0ae5653f8139fe8d4e330015d29a6201366e" . + "c2d94bdb5a3786bf6390ae5a719fc85aa6cdbe98969f0840d3f6a94757f5179a" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + "c91117cc447e8ade7406e6dac0840e60fab7d5f61066d0c956288c1216e6e8b3" . + "59eb495ab48b0a2ffa5b860f75de0ae5653f8139fe8d4e330015d29a6201366e" . + "72613acf4541ad04ef8d42fce3fe26a05ae01418453d153cb3b80bf6af92f44a" . + "9f18f191a5114f56f107f8c2d32bff7f59d71c34253e98f6b6cfbc94722de6cb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7517bb63fe05ad023246e436a8487fdaa7f53f1545bb85f3f0f4745c85ebdceb" . + "f24ce0c7935a8c7e4daf2bb04447a1c88309bd48037c97c8bc66bda277bd52f0" . + "d78fd592b26f184950822c7464cb83903d708ef88245667b048876a24c2a2218" . + "4bd58fa636498f9f11ce0eb1d147c44d1d261faeba45faea885858ef57f18c28" . + . + "3b09b38702d3567259efa50330fc606979620a95a9be9477c7f14576d0d4e026" . + "4f4c394743e136320a68185b7521e23f2280155553a60ddf2399825d34747347" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "3b09b38702d3567259efa50330fc606979620a95a9be9477c7f14576d0d4e026" . + "baa31249bf3b14b4d2673c9c939c1583abe162566c99edbb327a074fadc05206" . + "4050fcb9dc5fa91d771dd3073ca043f76997e5b42618c09d5d932c9ffbc1fbdd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "971c1d0d05e93d42ced9e538008dec6a0ecf77d370efb357dfa3975f024bfde4" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "6ed0d45f7227e01452fcbaabadc317e73134670e42c741024107a491aa00a5d9" . + "b27b7297537d245df7e088fce27d9df4d293b3c6f5fef5b5a0550d0c555bcd9c" . + . + "64b8a40016ce3088e345895fb87c080b9bdbb5f0e8f297eb70c08f8e7532ce45" . + "cbd91e22af1cb3316cfd91c16f91a089dff4ceb375ce10c5c48dcb59c93422b3" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + "bdc94e1a2def8524561974911c59888ee6eab19279d197d8efa3f9f5a018d957" . + "8e086a0b7a351bbfbf12e4f81445343543b71823575ad36b568c1e680f8b27c8" . + "c52bf65af3d1f64691d7a59e5d81cb25c75b9319ea918791e2a8f59c449f9880" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5d8f8428cbb8ff955f7b6b62322e1e0c59b0a39e07744690ec6c3c8d33b7b077" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "76dd0cd1ca300d8fc617ee1edfdaa29b6e582766b5fe630e0d18b28ec0006f0a" . + "ebbf5341bfb166fb7acd3482f20a2fdb3799c68179de2075df43e2d66b43fede" . + . + "d9dfd94ed3965c47899f501cbdb5fa4f1d9dd40d861c1424c609c40297cd27ef" . + "fa7556eb5b584c7e45a2a815f83fba2c32a094ad853d4b73373392b9334599da" . + "4a844a2257c9ac26139e641ea17b3bebf2feb3f49ee77a5e092715629a4de1df" . + "12e45a55704212fc4868f9277895fa119ff7d60e8718a45d18074d3604ac9244" . + . + "97c1b00a76102e916ff3c9759619047a05f637bca4f7154ee8276fdf87972507" . + "3deb5b241ac3a23bd555c2759882cf42a6f0ef7e7733ddcf5f6398728ef21358" . + "adc640e60b333d86e42efb69a184c873d39717b010a0e6fc1351e0df0c24dd01" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a19e9f901a0818a1f49a35638ba0ad6a34c574d348ccab4aaad63e7dd63c4ad3" . + "914beae475e561fdb7ab3c395279679ccd68a57ef1f21f18efd498538ddd9246" . + "22f7aa86c35d86d0be74c1a9f666806ed7fbf528f7314b6d921c9630e2b520fa" . + "515ba65a45cd946ef69ccc774a513ef13fbbc302c4bddc111ce1774badeee898" . + . + "ba286827b5b3a28f856e57686673db58b94138414644917da7c0cbf6e2e670c1" . + "0244bcb1436487357e5b418b23a2a75b548ac8748d58c155ef9c64466176c335" . + "f388ade5c80205d90d1109cc8d897fd16a13b74b0cd992ed47313c4091620035" . + "22d3ddcf65b90ee58344074ee3af7e26b794df122ee6ca5a5d193a839a28e038" . + "7d536fdab0acafc4b1938ce20769d3f925666d94617d6dfef6ad833f7bf9f754" . + "d170e6ff6420e4df934497b873a74f1bfb20ef3fda92ed7351a5fb4f224f7798" . + "28f7c5ac47414516678ff2012b03ce699207f8b0709cced870bf683ca7752598" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b1e14317a6391ef28ce7f60edfeaab62dfcfc17b7da3239b8ca10757d818d825" . + "9aea0dba72e7cf28c02bded3223814ae646c7d03c515946a37f6fcc8ce2ab686" . + "221292f7f916b23e1e03a9808d9583bd86520b5c74f83d92ae0d37a6a991de02" . + "506256968f0a0ac3e98c3022f2123d61b77b2f7b6d90b707dd516f7f00ce6dc3" . + . + "7609beb7c2730d61d30a4e7eb16ac6fabdc16a6da5a72877dbd8051ea952ec92" . + "9bc45150d4fae55da9b0d70f03cfa298440ce8998209b11ba64186b5215c93d5" . + "3aa432cc19fada9c5c25c2b6a17541074effc542da63fdd4f05ac56f69f6ef9a" . + "03102e7a1b076b34dfc4ba35675e0c59a8ed373298a4e27220d51f14dd431889" . + "bc8594f41d5518932bd3439d519112b53215dc302d99eda8ceaa98275b1a1aae" . + "d93cef2324ca5e39184ed582dcda00001f7391b98f4d0c5a2f9ac11e4c75675e" . + "e95a74faebda2379a1723e30e7d80d7ea2e953a46853febcddbf13372fb63398" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f5eb415f5f2757fb6edb67abb7072a0b337a827db182df92043297f50cc1f1a9" . + "6ba11ec951f4b399b7660683d6e1726399f2e0051b3b22ff2107304147cdebd3" . + "d707a26e6ab572c45d5209be34627de3cf3def3815bc749a6abcce110bfa23ad" . + "3991b60df3ebcb6d1f921883d656a3df966b8dd4e38d3b3b718293bdc99bbe07" . + . + "c97d9dc5740a7353a193fcbbad0d7078d68956094dcff4dfa6e9fb5f9954a120" . + "db7e66611ba00237d6592f5a1a9e32876611b7ae58f471e27edc4cca6fc1e1aa" . + "928de5e15c88b01a90d9adbfc4bf51014c49bc48c5a718d52ef29effeabb5c3b" . + "fb9519e6074d5d27fd529e11a778bf22fc117dc780f207b18b25bd04d1e21f3d" . + "c97d9dc5740a7353a193fcbbad0d7078d68956094dcff4dfa6e9fb5f9954a120" . + "9987f51aba584f81c349d0a84da0c13d4f5ea7c5dd6c87d67dd7605d69db9164" . + "62a053567aa960969b94765a6f024aad8e3f9199e465997e0cb41a5abf94b0c0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d0af02d22935a452a05c1be9d12a04938d94f6cca6c08ec926c640487ab7a6e9" . + "d88408decad29a4b1d3c2d68ed95c11e9f3c6b12b1c3532f14bbbff69db7784d" . + "d13c2ae2b183a192c7258d01312ecf360d3f083e0e927366909203d1d3554f51" . + "15060c21f8e0aed9a9645943d89aa5787b5ff4d6f7028f4f3beaa27b9e7466dc" . + . + "4384908356dd47f151db32b9beefc57a2d2767ae8b60556afabbcf416bb8526c" . + "a83059d5eca162e4aed394a9ad5eb9e2b6df4e751e5da744ef6c68fc1d480b03" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "be7f6dc27352cee8bf0460de0c86183f236e116b7000b67559bff8e5ccb2da9c" . + "b2e428dda652f255822e335204995c586cc3db94f01dee21da2d46af81ad64e5" . + "3ceb971bfb593914c2cc6fea280d4f859be749c28d35edfaeb17f047eb36de2a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f39c0a282a17153aa6fefb3c08d5796857fa0c0b73c7fb7160af689cee53a900" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "0d6d9d8cf26118c0a85c1052c49be9bc0ccba974adb337c434fce7e0a58b6a08" . + "0f6e144b997b2ab707deed8293496b8e1de797e9d41d91c3f8cb50dbc676aa81" . + . + "c426fea0e8a3ae248c8d3b75d6c1c49990d215b8fcc5be3b29d283ed40decc6a" . + "2ef47db783a37a39bbee59207cd6c572c7a2b9f5a646f1b37834f7e49604ef9e" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + "c8e2cfb19046a97811e45631c5188038fe390642e219511888ff725b3d5314e6" . + "48ebc1715f5192f3e9449b0be62ce449579e49380eee4217f063c8ee61cf7aef" . + "d50024c11194606c3f4493d89ac59cbc9550bfe57d61d65dd6d6d4e48556e397" . + "fd9abc89b20cba4f7836078ffb81d28d7652493226c7e021b71c931e465adbd0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e8e31d07a34208aff45a247429a1ab5bdb18735cb85e7adb0dfc8595b988e94e" . + "83420e9fc964e58d8394e3eb990a1ef08a5f683c21526df05bbdf784942a792f" . + "d4d1919568bbdcb7a9331331dd7433268668919cef74ff508af7d14849af9bb1" . + "ae51a08c382e968cf1592769fabe1fe75038d479b7559c19b3b53d05eb26e871" . + . + "c7ca27249c660da3feeac2477cf00e24d256f57c8660a051377675e351c733a3" . + "cbef6e9dd59c4926253876045dc38c462f0a2d1db2bcad0796117ead8aeead26" . + "76f48c971f231c7b48b6103f67c1ad1a309e1482d40406b262d26d6cf0d7aafd" . + "3c2c3138ebe4ed7f02a347d8fcc8afcbc14720ca45925b49fcff6616b5f84b83" . + "be97ab447a186f80de3ad90a9b72b39a7c4579cea844ccd84a44cda4ea7dcf46" . + "acc09abb7d8baed5317a17bd78639fcc6ed1d81927197b6d17d0344f064e2a73" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5897bd79f5cd98cb6cefd400089dba746efa64e7d171a2427377535bdca5c33f" . + "00ac58d5a56446a3ee3c802b45f12484985beafd063f1d43a8cc30b771f1dfff" . + "43f9ccb7bd522642cc64a09151d2b424d446cd8f0cf6ce9dc39d439b382c821f" . + "5d98b6a3d20969774cbd255ee49868eb6edbc27795ed8f78e33ce999269c9512" . + . + "c8d286707d15c2c054666b58e161713cc271a76b2437a96152ae4ab0aec5b7b4" . + "239dc584b58da87b8e771a9bf5d8bdf373bba483006d8e8090aa13114ede4d22" . + "ea86f60ef63a3a8a52fa92109bd46e26c3531593f9fc378d389e981cd84b5528" . + "0a237cd46bc96ae66295bfa912f9bff64b60e92a176f34b50bf384442c5873ce" . + "6fb6f1c3cc52658897af99cffcf8fdfbf7794d586642de4155bd4e0b7c40d28b" . + "8080922c03eae080e88e9a827313791a0c3b451c4f347e3b4bf11ab205c3a1f6" . + "80a8aaa9308052e3beb0473becc1603b9aa7afb7871a6785480cb9d5951344d0" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "04249f1ab1019fe51337806b7905b89e0cc28fc4103c6ed736a07967aafee187" . + "af6506ae204db5ea48babb2dd3d2138ca8781dea4dda98ecaefeb50b40b07a56" . + "98dae323a6216a9f3067e787fe8cb8c288b31644fe1801847d84ea6f92bc4613" . + "f32e8874d74d4a0f8b19103dfc99ffb469b2f096f2427c9cb52597afbd9ab769" . + . + "ddaa01130344235656e6973ff0db3f7d837dc651c584094ec131484f4ae401d2" . + "388c84dca846e2edc9248fe67538153df5342f43b7b339aa883c2cd1ceb16508" . + "73db25f8182b6928d00f0b1fac882c8d4bb3c81e35afb4c751bdd10d264e3043" . + "18a919c3149d059d47d177039a15c13d5c74325e69964e958c20bbe26e8029d3" . + . + "d63ce628c8e7794c900c0c2b1068470c493eb2ab84b353f8bc6f2c16c6153a80" . + "c27ae498915d4712e7ab8078c84fe5bfbaddfcae5336f18ebc1383e4823565d1" . + "edaa91b66d053307b3b6ba29ea10d8aa781158b1a9a383cecd86dc5941335e38" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0f682eeac475d6819148a99781d936d02a06251382e41216482cd643ad27a547" . + "b825a05f925d646361afbd06cdff48175f4aff91e3307342bb619631305ecce8" . + "6812a1a4be8d18be55c2930d6b7e94925d6f319d547b684acb4faf7111b51024" . + "23f34f626d3042585e9465c2fee64d5d645770c3b2a0d7f788434c5acfa43ca6" . + . + "a3be2c669a13424fef77b6238a6b8faf440c56ea01c5a0e8528cfd31a576775e" . + "bdfd04f2a07c189cfb7994b39ddee207fc6ffd3c7469e41b84be7334abf92dd2" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "fea89c9ee611aa3b349c85f6ef4f1f70c80bed0653c0139516ca8f0930be5da1" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e196158c169d0fe63a21da236e10a9c8aa4da1bd7cc7c693faf449908c9cf1c7" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "841abd1c8f65c1d499711f885a5f0276da9fab8571efcfa194811e2c990fcee4" . + "0a615ec11588ffcceea50543cb50d8a6f6a7b2df23a843713d8ca73a210751b4" . + . + "0296ee500e2b980190d6e0af459bd8b6b6abc168d11a05b4d197fe5d99e7fb85" . + "8790b6d770cae3ae4f7b58f09319a81b2d2372901030de2885428bf6c7a2789c" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + . + "2187d340999a6598e0c0dd29bbe45c6b5cebb0a5c6456106004420d6b6c364a4" . + "5a9b8b177ae66554221c914e907124f068c088cfe6649fe8d2862fa8a23cdb71" . + "b8efe6bb61117913c77afba64453182ee036ebf0ecfacc2d3b6d8934cddb23b5" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7b53784f6689de27411453e96da74be09877e323b1253c090d7a437ac673073" . + "6570740fc4f1bffe24712924214ae8d4d27eaccd9f4a0b6a7b783667cd484ff0" . + "983b91b4515b0ae65aec2a61bad99d5083e7a9f3ab5dcc84d65d51debc03cce9" . + "b977e6cdc05df91f0c81a0865c599586926fd8bcb32609fdc44667fd8e5190f7" . + . + "224c2f2a1bbbc1e3695b2d468d52f176355129f2e9628983c7e07242b6196188" . + "fa4de5e7000073f38d136b4d5f0c42ad46b2b0f91f39160f512eac125da30045" . + "c32258116fc5820123fed50bff6cc339d905df30fb9474f7cd5b5abf5f7c604c" . + "d6e418f003c7192b59c28d6dae9ee43216ad0857020e2c2ece7378593972f0be" . + "458fb91997ad41a231eb1dd3fd4dff4d5bc17c5a89d1c9da2c5a09f90de1cdc4" . + "9cc6e9795a0ce8d2ba8c21e522a94582919194bd9b3cb2266b1106ce3f7a72d6" . + "c43efcb5640e4aec86f5470e327e20fb56f4f389199ca750c8e8872909ebfac0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44e5fc518616da6f9c6bead634cb06b916bccf46eaea53429f4fcf358a017403" . + "0b215f33a4782e72455c0400543392ebf159a708532ccdd5ee1861a481534eb8" . + "5fa5faf505054809a74899c8933bd0665b0a2c870650f16fd926bbbabb72ac6a" . + "f1e0ec01ef640c687a86015ce788aaa5c83c15cd8866219eab776e85065f25a6" . + . + "15de77033a9f0b6765524518aa5d24dc2be3700d72455d737268edac8e87d222" . + "fa997ede7d5164543299835f673276ce9df459f85730900d091ca874d7617020" . + "bbaf699987824c322fe65c8d6ed4ca0c3829751beb4df4744843840df92fa76a" . + "64d11543dbe44e34e8721740fb933cca58fe235d8bb4516d0b666d3b38e04b27" . + "9f130b40cae8851aa7f4e9bf0366132442ae78d5793a28a2cac58f807fe4a0a2" . + "752d5eec5581190bb30af169a2844305998c6a43690b7927b2fff115ece58de1" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4faffa20accc6231966c2c4e3759be3f8112a5b56affaa847e9ead776af875ec" . + "7a34f348d0cc19aa303fcf94f5eb31268a6d7919c34e7d8b6dad21c50c3d0fb0" . + "c72f1a3f356afd04c31ad929eb1f438515507c45d3a6124b6127f572853c4a3e" . + "2d04a5154a4da8bdaa67cace3894916d9576daa53a9c12bfd0ae3c8fa0bc4032" . + . + "1b123b54eec1e7d9e4ce0310f847b6c99052aa8f50cb7aea7072e163b73bb739" . + "3bf6f50a308ee666a1245f91f287bfa7efd055ad8a1583be42a1c703c10982a9" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "2d0ba9b40836c4041af16c0ab3f31c9eb52333d6d18fcbe4d1ee2638ba7a9a9a" . + "43981a1966c95d8c6d87e6989a3d16cfe8faaeab7168a70db0c73e48f7ec084f" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1eed5677cfe5a33c91d7a6a9105037a1b6635ff5a55de0bcdae147e73a018a3e" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "9727bd82da9af5d5e6203f5a77fe8c7f0d9d0f756f8d678014366a21d2fe18c8" . + "94aa68e97aeeec614cee06c05d48f94e55fde9ed2d26451b7b561e917fd26b82" . + . + "104267c6f7f9f9cdc02114f1a1092495804c57b146616ba9c50274944b75a006" . + "f75afd1f5016af3aad706414fde28430ca9e24362c2b8968fd966f07ff582788" . + "1e6f94f3cc7d9fdba906791e5f85b605164b3fb9f9ce45c6ae46d37a34902809" . + "ef48532444b498701b765bdf5612b38b96dd3d68d37120762f2d2515dd4ab77c" . + "6265aa4b4d89b92e059ee3d9db62ffb4dd7483c254b38fe9ef61f63bb62a0cd4" . + "12bc4f56458f0adc36fc38d038b01acbebe14041f65efa7c6a38929407988128" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "09b7ece918a62c8dfc5e2c3d1e56e98749e17a256cc0aa8455264551edae2752" . + "0077c260e006417be7469c74d2f7474670459e72eb5196be1a14d767e95ec5d6" . + "43d8f12f3e21f7d2077772450a4021a6bfbf2560cfc4a11ec6926d0662c032d4" . + "43f765b99b997710c8411dcdfe4e253ff1dd8783e286d98356dbbd8ac2fbbd53" . + . + "9c9f14dca231b69efa1bceb53af1976892acb4690d5a4f1999a0f01ff370733a" . + "312f32b014c24b5e6380d00b244f3291e545a569456ca9a14d550a4c364c4fac" . + "278659b6bba5ad7c9d3c7ceb213768f89eeac09ac44565329593f7bc37d857a3" . + "841951424363366698143331a0af0acf3eebab804b9942976436328edc0f0859" . + "d86edb233e49856dc833d963b0da46a28f3ea4f1eda98e48a63dbcdcf214de03" . + "dee077a5797ad7b3e5713b588a483d3cf0ab87cf24f96f85934266980ca6ecb2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "684c0003787069745921e59360a07b90e62d852c8ed8391d08c7290d595a9a1b" . + "2be0d4965d2c38b62a4d86c364b2b9f87a9e9e842e87a7e8400a80cf21e33cdc" . + "dce79c2d3d05226cabfa3c16e1f8ed9aae4374e1eeae9af4c7d91a64da267e62" . + "31d6b113ca7a0d63724151e5810c14cec98ac12d6d03df13ab3ef03842e45a77" . + . + "4ae888285d4461e96006b7064153f71afc539b54aeb40f85fc6efc2879008507" . + "5bade83b5fc2edc2587b2887fe5eff4300cae04c1bb8ac84cdca3ef71eedca68" . + "e03fcdbd1bb0d88259693d516389bb24a16d104f654f7cbea22ba997d3d9def8" . + "caef7f8939854b5f95e2c6519f7b5d857fd853c051ee8e839e115005ca2ec226" . + "4ae0564817c2b954318ff930c6a53a206d01b5b427163ea9d97042d1953c94a7" . + "ee2fc374d0f81325bfbcc16f8a016331e4e8b8d9c81b9d244a4ca37c8f1898db" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5645e773ea758ca5f6499e9e2055235f9dfc78fb4c4211cbf7fccb832497b291" . + "77b9c4da073ea5a969ec15addfb7fe131553c5823e44de973cd9da331a0be31d" . + "d2dbe49f4f4069657ea80022cacbbac0c0e94e2e0eefef9335fc961e15574f7d" . + "f93b6926e897169867259d7d5e83badbf5956afac8990c8d5301612f2569a840" . + . + "41cfd211c24c990c971ad3001d71ecc6dc500ad7924660571aea78ef0e0f1106" . + "53862af88960634bba3b83b44d64da5f6770cd0b3871837784c2cb3d5bc99fc8" . + "ed99858befcf857caee6b3a9183a68077c85cff5e0c0ef92737fa7315f142ce4" . + "39cb6341a9782bb577ba867f16889d0a75df361cc4ff3e5c66f43ab6b0abc6e5" . + "a9c511e57b74e66eea4782a32fab335a6d512ec8523cbf05c5c8b6fca42fb8f9" . + "9b1a4b6855147e91106c6a6447845a092db2c5452f8ad7c96d0a955204c7cd63" . + "439753969221dd9dfe8873e0c7893a44426463b2d4b55ba641156169b66f6801" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a3f350bee532f918d851dc55ca61bb0d2ca3e806073841fb1ac7434ebdbd745" . + "011165498eef1440bfd00a0858327871d54b9d3aa087a955a0ee1e3a49260e95" . + . + "b62c0edc7e0d9a4ddf7eb155adc7e3f17187262a51a242aceb6c1be1d87a48cd" . + "889e1af51dd7860152e6ae30df181fc1e7544105a3fe353dbbfd076da8849d0b" . + "a99fbf614ee9ae3f84814d6255ba4da3c327acee31cdbe64ae3626fe16f1623d" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + . + . + "d4324c9bf8e0905078f18e20b431eb66f4f251ab495aad48970a0bc315555fdf" . + "6c51e5625fe36ac8b1638e105f61902f8ca2b1793ab98a06eb57dffc4b33e239" . + "24170f5927c8fd937fd786101c75448b1c18bb7c42bcac54017a170bef97b138" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "09792631029a6275212a0a0d73c8d70c13699724227512525c9c84faa4cec7b8" . + "1721664760fff8571cd1bcdde4d33bfa13c7f42e8e8f404e42d2064ac5a0829b" . + "f8bd588429c06ae7e0bc33a0a6013b03a13ef72a49662056c5f98fa4370200ae" . + "9be1a762cd055c0e917b3260fee4bf5847927de259220ec45c4b4d6186440610" . + . + "9b7a2c146bb932553849e0c8967add272463fc75b4cb6f392610991824f8176d" . + "720af37c1ef811ee5c2081d4bd6f283ff476f07259c079a12e5601b0fca45b2a" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "4f7b234bb842369fa39f19161e812277e247f2d4561c89e149f84ee79e608e6b" . + "ac9b7b7a3cee306ec41ed4551814ab34941aa5caddd82d7f3209a36174b74c78" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee1e061240d79720984d88bb1f38440c3f3fc8e442394bf9e02d6fa9cfcab913" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "b7581ad263d1afae247e80877c1a55d7a1ccc0db7e8a888efab55e68652a1b15" . + "ca0cef9747e8c6a3c53415a34252670795d4fd295b2ec22bf997076eeae153dc" . + . + "62a5fc4a356407a51976532bcd205ba4ec467b0104f97949d74299be81e40eb1" . + "a8fc50a8a3f11d4c5413f4b3a25008c1f2d1d77c7d40ff4e49e8f4f95fc074a6" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "ea3a327da37f62c16f0a89996bd3415a037a80b75f67a332b31056b5215178ba" . + "2aeb687d6150d99d14ac9eb8e5e44eee4587f5325bd8733bf753a57ae3bf49b1" . + "d6cb4faab950b70377acae52e91530bc8cf0bdc4cb993edc2cae0e3dcae28121" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6e92cbfd0c37fe999e46f89c5b30e6d443acaa8756580612ce6c691f48b278a6" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "cdd2b38b9023946bca3e502f70f0e2a7cb764efaf9d586339726f170b6f8391a" . + "d2699ce84e69683ade08fb5b71fe3dbe63c1e36f0089018c60f1351bdf65a494" . + . + "823fe0f10be3403c6448b1a31b12a3d04e2bbd85a0438082f2d77a1d1b736b02" . + "3fdff11bd99eb5dfae0189409df8a7336e41b32bc297e410e0c72ba17079a924" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "a850c11b6e09e46665efc634bb2570b514fb5c30538838cad467d314e2b9cc71" . + "9b33c04e473062a48c013c71313e8eafb84c1b10eb2ef50b1d298e66ee07b1ce" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bc57b6e83496b4d0035f22322aa356499aa1a1e5ab5cd8bb33a119123cb9621e" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "c6c0c83a46370ddc5c68706fe302c05f7c514593fa9dda350b79e4089c1a3770" . + "ad8402678e3dbe3980a3afe25a673182c0982a97b60ff3fc62a90bc7bb0bd44d" . + . + "552fc586e4431a2b94909fd2648d785dd4d25c4ec59bb7111edc292f33f05fb4" . + "bf922d126895efa0a93a906f35bfbb0d7b6122de3888dedeb125d09ec147d801" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "1814ba5a9c92651c25a770b1b47dcf847300a3ad730d7b15a181c358942bd96e" . + "21507f7f44be6afa8347a966885f313a0aaf7474ab72cf1a074ae6f3e53bcabf" . + "36f5a63b54a9bfeb487d6ee9d8526c6c4820abe3d65014e348c93478970f8239" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "516635915f5cafcf67447bf99b61ec8b5555d5ab4379f9c6ce186c867056ea51" . + "112ebbe930d8923b57cfdd2c649aa194a403ca6db0561c7d4bf69452cc4a4e20" . + "842bff402c659ab7ef3747e2b25f1209a46305126f9940fc6f87a6e20798ab06" . + "e2c725bd102d1dcec042fb9bee5d4e3a5b1161d58b4b16ef0c5c557fcb9a8bb2" . + . + "3f3a9ef8f3db5a2e250c1e726360d140c36fa2d28daa2067130ea167543073ac" . + "e189a9e42b169b1f6388986b80f567feab5a2a45bf742a8b0d26f02c6f4b25ab" . + "28b9594f0122b844b37896ec9d3cd3d9cfd858fd9485f704489dfed55a4d53ab" . + "821e9d034b3d11db8ba2da877e20de01053529a10757093c2fbc3ccfac4816c2" . + "b0bc2b722cd28e330ec6c83ef4701007617ecf721c3e992da12b6129dcf4f211" . + "f42fc916fca186a07cf4eb3982a64517906ce1f020e0319493c0783c6155355f" . + "99d54c80794bdd2a41b1343d251aec41b9ab2048922e0106515d10f9138a5573" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "239521bcdefc3caa38b52981d1e43ea217cebae8c4246876082622764ab3862b" . + "d6c7baf7fe2336e528ccf317b0cc32de3820e3a732849f47a539fced39d1e1b3" . + "0ccc9271e8801d941e24828547a084bc0e36b2d03d60c674a5d47c1526e1d868" . + "8cfbd078d812d7b461d941140b65f2f529967a63e82b6bf51d08c26a5ef63e6b" . + . + "b5b66a975a47b1d337440f813d6025f84c0cb56e06109aa37b13498f3a315067" . + "e66daf7a82b1da29820ca23425ee6af707f38b09cc2aa17b029cd21ce4d696c4" . + "56b341278d8602a6c4173f59160bed66e923d04c68abf2ca41347d52e5618fe9" . + "d6f52605ea40f900227ae805c18f2145bd3e52b19972ec0ce0e8af69c7231adb" . + "7fecf4dba62aaf2fbe888ed0845bca3144cee3a51e7babb9a4278d0e561856a6" . + "5e4ef02bbafc5171f04065cb3b609cbcdb5555852b60b07670889aa601ed42db" . + "32a4b823d3fe2dea290e1df3d4020a69cad8e20e167b2da6ced3c0ea5e8c350c" . + "486dcb1ebade1349a71c73a4f584442909c690d26251f72d0c4089316768d8e5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6597ec75071760b8edc02f52beba86dbbd60d7fbbc4392ee58342b8e5e4de4ff" . + "2a8f01402587239b8dfbeee1be04159b7b23fb3a802396875095f2cfed4dc221" . + "b99c0a891cec4f5fc55082b62e27bc190e6e7f6710b13a363761dcf652f7bcd7" . + "41f0f16112e28c69fe5922c96c4ff2dfcdbf3c67fbe707f5b4c820c1f71044b3" . + . + "793961ca4999d83d0d8fd2246ac4f474e3820ea153ad7df328823cc95158668e" . + "66cec7765e2e367e7e799aa10480b9c2858fbc7d3ef1eec89aafb097fb58779f" . + "056a04ee2f7ba67124a0e7070addac176bce3cce7be54a165735fa1dc58b2ef2" . + "962fad6cf1b2c58f2617b784200b07626e7b956d064bf2ce93f349f213d476b5" . + "d8fa4ce94c106bf89d2c1bd3fa6b1fc7846f336f76455949f09d324f285847a6" . + "4041b014578dd3af011557a5c570ed501ee2280c4c590326fc66e22c39666226" . + "a7b23fc78c0b97fe0ec723e737a95f975fa55b102bc26554a29717de9e810e22" . + "1aa6252bae37926536ce56c83104358bc14caf33ff6b20c9bd7b97afefb62f25" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21a05a3e13a9864fd95dc10ec5772acf6e82aa1e5087a739f6a38484c40d4b26" . + "6f8f50d5856694d314db6c78512032e750fc9eea1b4ee99ac876f8a8d98d3312" . + "8047b584492854d8faa44a86f52f1eb880a037b536661551e6ef26c476b6aaa3" . + "4a55dc8c6510c1a5e18ed4500e097ffb172ca3b152c17fedef8f1e2f1342c3b1" . + . + "b6bdf391ec1ead4f0206d9ae48789d9f43df04c18f08ed08689cc176aa12b199" . + "47ed7c2a339dfa3d916e0a70fa6e5406b29a5dc4c8543620371e5abd4291e140" . + "ada6624c34cba0bf403eb1f278c516c25b8b098a3ebb25b400b9282852d044ce" . + "52383e3509b81f2fa56969daf84d035170be666b50d1e791ebdd22e89ef24577" . + . + . + . + . + . + . + . + . + . + . + "9511686e09e1e7e8b4f3eb9059c310b8153a04adfbd50125df05ca776f0703fb" . + "34e6b1fb8dd85b8c0798d918962a6cbf2799c558d8a9e689a5843078adce53e6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8ff849d677ee2c683d75c85ba24d547f46ec862219016da1ff07a5ea8b8e2fc4" . + "51340421b835bb0713f473205fcd727c1f9931f181ea9895e674ec83f01f945b" . + "f973c19367506c5aeed49929039674b0aaa0e58d2cceb0190ee8db74c35bc15a" . + "1bb73ef0abb49d86731272358abb2dde935926d4c329b286b413a29cc5bbd753" . + . + "8acd0ff262628089ecdfe02bd734af86686aad20b4ea6cd7293500350c895c49" . + "51e636906ddfdbf340b22c29ec7bf0fea58006589b38987ba56c8ab8fba7f3bb" . + "244ffccbc7103f800a4061b4d0b30c356730560419f6e959307c5ee6c298a2a5" . + "5d119a42419341e7a9a24d5189c13ab3d649183c9a9a8c2df517a0130a4185a9" . + "b13bdfe0db050f83afc25a629692fa15206c606528a409f66eaf91fb8128c7e7" . + "637c87aa3d6e6f69bb2110304b2d02bd988f4396b727ed5b990d3dfaf2d2c329" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "989942322ce6ad0f1f0fdf49b23ca09a5f854b043b284c6df78236044e2684df" . + "14eb0398e3aca79d37c27b2ce5de3baf54142b1370cd6582b1b741f146048518" . + "e73e53ba27c09ff3ec7b9e2147efe4f6ff34d010ca8b9f43e31e531d6b493e85" . + "61ac325c4682728732be543b775757e650f172e081ee73af308f486bc80f79f7" . + . + "ed7f7c5c719e23876e5e597bde56f914494e89634f6d4f2e69880586b75e528f" . + "dd5420de56d5f13e3533ed56deb7f750d2f2959c9e94070581e655a2e0dc4792" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "72ca580519d446c2fac7f21cfd34ef1d83bb4d6ed0a98ff4d22455a5946e9672" . + "7cc4141903afeb9b50cc5c4771b67c89d4e3921acc82bd17d7065996fe26f320" . + "3009a3c8d997e8d60521c1795f5cc346fc7fa0e3e35f91f9c9d0d49c042976fb" . + "ec98aed34a901a0ec8f725716591554e7042e7176c596a3dc101e7d1b4463886" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b845afe528a6bf2bb462faaccee7ae60ae63cf8f8a0246505b74c7030238f71b" . + "907d492a532cdab962f52fdf1b10d821858fd017afb5a633ba04e07938371fc8" . + "7168e834164001cd20656ae5f1e12ddaf979c619e946d25ae2dfcbfa6a969a9d" . + "9940df6a906ef58264b59bcdaf1442ef419c72c66069b64b6af40a0c58bf4bdc" . + . + "2f00014f17bb53500fd7fa675f9f66898df0e62eb62f28142c6de6d65b839b22" . + "9bab2f04466078fcec557f5e7fbd3e534f0555faa0d09268091c602d0572b8f7" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "b3d0b0ccdd4e4352af68d43b5066d00858efec5f5ba4ccae308c7d0f47c5dbbb" . + "1943fa85a8143953e6adbeaa6c69038b6b1b3e9c7358e3cd0e3bbf2bfc83d034" . + "be36b2097db487df49ae0413e7b20affadd4afcfdc19893b402471579dddd362" . + "03515482620338df2d398c6bf29fbd393e2ce010ba295935b59e683ef8ab090a" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "daaefaf0239fc81a4d54712be9ed02d0be3d582c967d6e6aea0ac36825ea328b" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "8de13a410d3b268ff036d3bbe2777d0c7a7c5dd1fd938532dc880cf0c152ac29" . + "6fa7457561485a7c896d56549e29232877db1348165424704a949845066d2977" . + . + "c15dcf61a26a5853a4de998b89d84b79221617a546b4d4a84d5067d3e7121ee4" . + "b92da3fdcb3b610b8649e0914ce4783d2e222ada476b5cb2a9c53eb6265ecd1c" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "8656cfe3f168f253655cdae74e50ec7b537a927887cf77a5c49770bfe93b244e" . + "6ae29279336a7565bd33d027c94ab004182954aaece732c892d4d1b494f51b22" . + "234f76d812b8a4505d4b338e12acb832155bc5ef7f54078fa521786eb2c5a084" . + "e83a3e9ab1830fe0116ba1fa7251cd4085a4a5b157261f8726f902c50e65a391" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e120d6b5ab4697a4a2c6491576d03c6ccc4fee3e5b9485f1d0d319245e5fc417" . + "e3ac7152a4d58e15de8d215f780aa5d52534948b196c08600cc9140da25a3310" . + "d733576522f97de6af153809e21047966a792751c955c5998f6abd02c33e4c10" . + "71a9eb2ca62abcd2b872d9dfa2a2e95873ca9c1dcc097662a5c1da4cb62181c6" . + . + "17b69e2b8d8055a6703c8de35ae9fc8276640ded7f987172c0b797eaf1175daa" . + "4a960c5d52d4e9d70a14dc6c3d057ec5802ed162c41457efc4036c7648e27a99" . + "b35a9a20f133a4aeb0717fcfb3dac944e5da5429e5a23f3d8bbb267f474319d4" . + "5d19f13cf17ee38d2342de7d70e0c36a69a2a91c776e4cd85e29bfea9d50bbec" . + "34eb673b4f60b060120f0cd382eb9a102084ca3d46b77fa2ff83fab987905cfb" . + "3d72f88e304cf9d58b04072c12e09ee43d152a7b8d06b06398df744154861861" . + "5f33e42a4e6bf2743bea4f758ed28e7a37f6001eb603bda92a02da4c84b7f19d" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "62f3d70872a7de603c02007a28cf95a7fe2782f1e8b3c4634931a697046b633d" . + "c623c91f26f0612ae585f0f95401fa150e848d8911163dfebcfc29e135cc3d3a" . + "057659a42648d48ef2b9bf0964ed463b4775b1fff7b57f5ef4efc117e346ccd1" . + "f7f9795a38b9919dc57bd89cf96221bf93cc037b3b34520b02702608fd544e71" . + . + "a16c7b020d25b27efa041838654ac52334e2902b7cf4a7e890dfdd07701c2ff4" . + "8667b483892f901286bfe878c793987b4009eb357c4e6d7f86d7de35af738bdb" . + "ab9657b7d74ea3cd31894ce5eb651eb8e20073b1a1b1c9dc77f3c233bde70264" . + "0920411430d5b357c5b32156d7b805b42f66351bf326f15dcc49d3487dd0354a" . + "a16c7b020d25b27efa041838654ac52334e2902b7cf4a7e890dfdd07701c2ff4" . + "1903bd9e4cd3e5bd330fdcc7a4fc0865b3cbbf05956f87b3673447ecc445203a" . + "91a44e20e7f4605b8c4ac19bb12ba76f454f4318cd81db6e356baef480bca1c8" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "fe77d2fdde0d016c8ff3582ca2b0ab6d232f35faf4bc038fb6da8119c6abc30c" . + "6f2206c9c0455da64e480d2a551f35770f5455b0286bfdc6d5ec9b78df69f8bc" . + "66b9c3aa9f95c63b9042b9687b4939e82f5455d4b261736f3d004c401dde353a" . + "de40fa67c74ce2ea250bf3e16a840058dc48a618c391f3ec0c1512f56ed2cde5" . + . + "83588e290f44b372a92cf64282c838810f97a171727709c9243475cf93e489e1" . + "fdb093a2770b9bbe573db621a0743802ba2f938ce5d76096c942c9292f849242" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "3651e5b49871afd5a1112023faeb31584ae983313887ab5656742c60a845c133" . + "da5827faa0937965e0ed4857a8a7187fee527b498740d20cf7bf4b73b54c0809" . + "6424cb0f66151d84bb905c285cd84d96aae08091425fe0a75240d6a9b88e83a7" . + "5ead61d3151c67832cc310bd19ba3a22a7a8c74f2f66dfef5d6a7956c9413d72" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21f3dbff01908644badbe93cbe55afd21445773c981a90ae1b858b1e6d0b76e5" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "0103110998ba188bafcfc65a7d7bc4a8ac0c8975283535e0a0dc43d66a18616b" . + "166798c018632475c339ccd0ff9c23c5b0d05ac5f21c34895621a31a79098269" . + . + "73d1e1faee7be10ccd0424daaf67eb166124daceddfcd71a170c3cc5677da8d6" . + "6d6e829fee707879a85b8202d632e4ac5be73787ff5b7ffe8c3f4caf3834938e" . + "a60be5d0ec629f2a85f9b61b0a6851f07258b6f742c878f7ab7efcb2350dd12a" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "8139e4edff9d2d79268c8c98e876dc505efcd12251897b732693e74d68c40b65" . + "4987ed8d6426a736337bfd1a162bc516e9850bb48b71e232b0611696353dc6d3" . + "757d7e0a1c04ef7b04e9b9d75da90a130fab271301a71dcf470040e5b731f262" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2fba13930f6b8a2840accdbd442be2d4b20caa8c0bdac21765d7bea40e33a70c" . + "e03fcdbd1bb0d88259693d516389bb24a16d104f654f7cbea22ba997d3d9def8" . + "8cb4e9670d514ee9fcd0df0ae482e7e0936062db840a51bd1168fc74fa4f7446" . + "cb2af22f0953d0420803d2631b47e4582cee6fbac43e0e602ad1137c3ee56985" . + . + "4b88b81e32c9e2cd2db69819bd6a9aa8142443342e41162d6e715add52c4fefe" . + "c1068b203958dcc5923f3751fc0896b5d96aca4a3ad69cf397e6359d341eee69" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "f37f763959548f87b52d9ef3d98eacf18eaafcf23779e205f0e2bc982cd42617" . + "c4776a3bc5eeefe8bf1958810203106b3e43d253e5dc19984b03a793e253baf8" . + "0344eba644a44c2229b526cccf210dd38da77221db2a7610135c2be75b6069c8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad6873c9ae309bb835d2e8b4bd53566a3fcc04dc35f10d86c491a637b4e3008b" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "f9d7cb3a1ebbfc3e6cd7d8484c509b30ba03d2b329eed30de2c6fec179b17ee9" . + "5b29aa4b80547170065f7f31e71f1f3e44b2f5bb7c9eed926373e5476d50dd7b" . + . + "99f7bfa9fa356a3772dfce515a9c4081317fbf44353feae02361b9991a8b770e" . + "c623766adc9e5d6793dd04d3448a84da7891d78811efcddfde15df8b6c7deb95" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "815e1153981d38e21bda5a426a16f95b14a51b32433b9b27606aecaffd7aa23e" . + "08e6837862ad39866de7c32e32fc1229690db4d15ff57b10239d84d8aeba7900" . + "0a93011c5aa9da1a5bd7216d940fe6a804cc08c0b1b6c5bc14b4091631436f8b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "41e9ff69f6b0544cdab0b4120433654de9e25d0d7dc8f466adb9a84f5b911d4a" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "f4b9a997a981082e239dcf5bf4127d6e208854be525173e30f98442f20e84cc8" . + "937e2ab7e659878c14fdb1fc772c74cecc3d0da2c7657622853257757f311d55" . + . + "7f20167ec64c42eccdc931a66b9ab0905a962cc741b7a5cb77d61506f95d8ad7" . + "25ea7de80bf14613a1a4e50f4a1a297ce1bd0e1d2517b986486ad025a94c8b96" . + "bde387396220fc3da3b4f682e92f62253d6a405611d4d4c20097eb067af9d7f8" . + "a97d72ae42b9a9a959866a5988cde1bc414a84505465f589c143b0254467d9fd" . + "7f20167ec64c42eccdc931a66b9ab0905a962cc741b7a5cb77d61506f95d8ad7" . + "9f8be4714a618c7bede2b9232bbba5147e306c5870f59627fd2126e0dcb260cc" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5cd5ec79eb1bc0e4e1e5b091d0fa358f643d002e451a25ff5761c07a369bf148" . + "1aa45dc0ecd3638bb726f207ce2ddb5238c5711cfb53f611d2faa752fe95f16d" . + "24dc56686b72592ce5358d8fa196a1f9ddb89db8b3586dd4f02bb4cf71b375b6" . + "55520bf1e149f69dd4209a47d52b8ff8762f8e1498052b92fbe044be7a53dfcb" . + . + "998ad46822f7985328ac9be742c941b36f5a7aea0604395e3250ef8b5d498892" . + "4f8c77eda71409f7b4811b413d553b751c9c70fc5b99bd478f17c6d36301b6bb" . + "a8d22cf2e10206f36596f5bcb90f959e4ebcaad9c8fb8d820175a0dba57d68cb" . + "0249fbb7f0fa91e66a9fbca876f0f81a69db2054ed0287759fff3be912f1d64d" . + "608184355a93712e21726c5e434c4d65f12343299a4e2fc6e3c33df763497ef9" . + "393d5fddba70e636f3482856e4e2f52e57c539abc07c56b2f823eb64dac2940d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65838f653958c9d8e2debb29c63cb16b6f3390dcd949b2f45698869820a4fd61" . + "7bae3ab544b5113a4b0839e3abf6d4347d4b21dda782d78944160f913577e461" . + "b695bb23c40161e20803885b0b7cd25ed6d4606f7f8835731b49365c956f9400" . + "e9437db7589a2bdf4ed6b27358467892551a833f94a2fd45a9d4aaf7fcd1cda5" . + . + "61703f97634ba44eb95ea0edb289f03a2cd81c5179a780caff19861a28486d70" . + "27061fa0e2c58ed30c78699249afd64e774d2eaf3c853d1a4a29a1046ec83110" . + "93863dd15860de1c31b34e239aa901bcd5d210d037ac6368289f534dc313bce6" . + "01508bcc115c0da28d7316f34cbd0d95aced0a378854467250aa32935ab7c14c" . + "61703f97634ba44eb95ea0edb289f03a2cd81c5179a780caff19861a28486d70" . + "59e81e3d4b7ae9d9a1545f00081b3d11360779f5f044e51a2fc67a91986837b6" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a409fa8191afa64da149e926e79c4fcbf6b3356c5ab299db435c8dd56a3696de" . + "b98c4ebe8b3a93764ba21877f7e8d784808dfeb6064914600d3f6090a1616bde" . + "09ed5977ca496ee148c23014bb422e493c93ab1d81acccadc9d712dc6fa43162" . + "5342055931283f09d2c6a9fac5ec14b71e44ca4d8214ae45f8288237a979dda7" . + . + "2ce4a408a1a19cc8b56b4cee6f0ac95b4e7cc91d7d539c3fe1a56f71ae523bf7" . + "d71e033a494475b9184519e462acae19b1e8b8bae07cda469b86c4ebd56f6d55" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "e5c2e788d6aa1289b8f2f9cf38b912c486054161c779f4ae187d84b90f8315be" . + "07f1dadcfe88bd1faba3ddaf580b3186068fc6f9fdb75266803d29f486174d75" . + "e13f53168afa276532ad89c9f4e897e657871678b0deb4e543571ede4b8cdae4" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "75967aadc9e2142b0cff517d4bb697a7530e0ce7e188fa5ca04d9d365515d429" . + "0573769400c68eb6f1b816e8dc76e3173b58e7549f26a5511b4b5fa10f95b65b" . + "42c5b9f4746323182515631b09b43b2e6cc87a0f406bf1dd1f8c2ca63df2cde3" . + "42be482201939ca29c4508846493a14cf6784ca5aab950690193562b2f394131" . + . + "2dbbb1b2c5e827b4f2b1ea566fa90f2da8db9f011d5832bcc02273c43514736e" . + "1182d9d1e35d1bafaf1bab50c365f1f80d96d883bfd9b828366fabae59a0c57d" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "fc0d72ee21d1e4764d445b3de4ae88e0d9a66b09e65379a597e5021842af68c9" . + "f3ee2cc026b6f8cbacbfee371be504c79ae718fbb17a00eb9f5d406b4c336d96" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4260e304eca71c15f39e44142238cffb2d08b020b1a99e31fb91500f43b1557e" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + "d2bb2b991fa70abc39ea9acbb47d9aadee1044ccfa516f62f4171ec779da60e3" . + "e87076c5a36cd4819af05cbd33ce77988a06bdaed8b84c83cf175cb2643033a0" . + . + "0868d868f62a8ac3217890e1ff381e20050baf5b17a17dd5a526fbd4b824a22f" . + "95cfca038f5e81b46843b613be77fd12a14f8f5458aaf5ffa4b82602168a18cc" . + "3e594cd0d4d63ac7175993cdf944cc4229d6a8aec7658516537afb3c9f87eb0f" . + "3acfbd27bf64b8e63919d011507403ba22550cf1306f4e59a9f71e1c0441f8b6" . + . + . + "81cdde3fed79b246be7b56a228d8d64bea5e1ab5f7e49fbe52e0f274411cbfec" . + "b987c2803442426ab5cdaed038a03bf445e6200e78b9e1491ade690334ce5a33" . + "80d3bf8aaf84cc7636d02ac1aa8ad46f9b0bc9ad99b932012bee1d71d7fefeed" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7036941c9e813a665e6809fcfb29ceb13ad3ce7d172da6a4de817e8095d9bb52" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + "ab0a8d77fafa7146eb5cb694454fd4e73782255542fed925142ac5575e0f1372" . + "bdd2c0ae105799bffac2aff65c3e0cd9af59b99e916dc53a2af2b7ceeb85f5c7" . + . + "ef7d122bc4953b97430f353cda60d1198180c8343c853a4f14ba47da406526c1" . + "74a3c4eaf49ef3f057662f812ad489281c88f65c8450a68db2a84f6a148fd724" . + "b2cdf69e9019dc28045b091335962de150dbaea6917e57470f6a439b3469269f" . + "a901f34271a8af2533c0b98a090e527c0adf887645f9c6cffaabb6716f80220e" . + . + "28b0db3978f8cd3c7a6f40688a71442eed46497ffb64464da5d14e19e276fb74" . + "e8075b4586c96dea6e2c843946461a531548e2c8bfff79568be697a21bbad1a9" . + "597317a5c62f22c77e433d0072028a1d40ecbc9a69a1c985821e16cdc73b9307" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "84db50f84ebe2a90b875276a8b9caf650c4b5a8b175b6695f36e4bf844c37d02" . + "7cf890985926e39337120be0a2110fe116e5dc2f2514b6af62cb25c6c9012665" . + "1eceb50c71f22bd07c5029f281083acc52c10d03c99ffeb0fcf9b90ce5b587db" . + "81a22f1ccc890eb51285958db9bdc56e5c5dc17f0cfe87b390e70a1baa4c58f7" . + . + "2dbf7a005b73a1553dbbbd1f71a2f5154067b9a378eb6fc5cf8c2243772c6363" . + "d9b441f06fb2178fea79a294c3b5073be8b17950fbdd0cc0498060bd3702edf8" . + "24bb2c7f06c9760496afdf12e7e25fa7ae8ed18b108775cd9ec79f0fda5ca6c2" . + "708d462acd45b8c45a147ebd9a99cb404ac4c8e5be064d97d16bc620ca8e3418" . + "4e81691c593245fbfd57d1c9ffcaeb0c94ddd6d18455013b72f36d22c6eb5d74" . + "a7f18f921fb5269e54d8761c5ae20fb57805e40fce741e1ca84dfd68ba0653a1" . + "17362aac4e7c49c2a4ae46dfff82f4af721a34c9eb2837bfb02b9bf09dda468d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "03dd95e0c7efa34c6fc3850c9c8020bf784603b268f8c79d244104a92053cd56" . + "520bc165a3086723094ab37f35953962a609b4ef3fe38ac4d38622ff48834366" . + "36277ad906b8833a5e67d907c9966cc5f686ef92af7ae5c2e392dfb658d7148d" . + "626ce317c34488b57906a3a0354f363be28bece248453695da350bf2d29acc63" . + . + "5c4b0e2f9ffb2274842b1b8ef559870581357f0f16c446f5615e0657437291be" . + "fcf82a3a15aa29180f4a156019617e1dd8f02c30d5bc504e60755d53449fbc9f" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "af23239920ab81606b813dd6a7023a6ed2d0e8fda17b8042abcacc4ae2cf841b" . + "7b9e195ce2cf60526a183f0810fc6b05c78fd7274d90fe926b9c155f22866ea4" . + "45a00693f2b2eef4cc04a2542d46aa316c0260b8d36358115ce14ccd470d06e1" . + "c129816f941689715a725cb82caa4b650a55fc6fa3d76b01012d62141c1d1f44" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1c3a25d4b384a1ea2b84ddba988fca85eaa11ce0ff59bdf7ce2e814f5f85d14d" . + "c306a383f0883b60f603b3b2cf318ddb02d90266a701ffcd3f90e471c0434c8b" . + "3c33ea06877259e5601098e4ca5880e6a618ab21bb764e1df723904b90cbaa77" . + "672b1091f95daf1c797296db21eb4c91b63a00b556cc3663c42c764144164bf9" . + . + "55c4f0fc9de2d89c18c0850ce48c00a2651da25c7c8ad2a65b7b86cdd82b3342" . + "da5ce615ea64a5c5826cc26d85aba444672c07503d604f0d9ec19966ad7446a5" . + "27d7c61819002d137fffe479a8a42a5782d535b9b3e609f44e613fdf67fe6ef8" . + "cc8dc4d67f20fd1942aaa61b1a26cce8d511e697cb8f7680f65b572fab9c1c92" . + "611e66ba7316164189b26ad82beb72906ef26bfcb5c619a18a50c950375a212f" . + "b69693bbcef3b0d2362edb3bd917f80b5821390d6e3c6ff4c1ddd6b40698fd27" . + "d7167d0af42a5128978269a58000d21ff02ff5f7811ffbdc562d52b0fd34d02b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a39877ebc3aa1548980e0bdd76543ad47af5aabc0f981eef4aebaff88dbf189c" . + "65f515cc210ddded79bbf98630848382b7c6503d82bdf280bdf75991c6af497e" . + "32af8b22cc81148f5a27d0cd3c51111ed3d97e10e1f2c14bca3790f263bbf3fa" . + "d32adab1dddd6e0f7f2cf2b31e994c46b3bfe653655770b3a506e1d2b894fcd9" . + . + "7b719d5a52598aa9da8975f6468188f7144ef31c353891c61eb9ff9790b23dbc" . + "a33130935af697a3a0cf3315e9d3f43cb0b1676015494fc0f75ca175922c3fb6" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "f89072e789198119af60f67da4496b6b7d6e5c1a733583e989ea9d4d2cc14c70" . + "30ae2337e7550a79099c526a8d59d55c1172cb831dcac71da3253e966c4b9076" . + "ffcf909934d1105177e1036ba28a1f5ce2f6f08219bc676cc959430bd85b7882" . + "9acf0442068f2724042dd1ddcedaecb2be0aab7f71523f049d805c117368987b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc88193951c515a55ec9844416af03afe1bbaba5d6ef63cf685b12abb50f9728" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "357775208fe840f772d24a10f0a11b70fef370ed5f1e56e1fd70717135fc34f2" . + "d3450e8235ed26aa540842ff00b4e38ebb747549889221b13af92ee2631d9865" . + . + "29cd08190e381c73815e11ae37b0fe27dedad1f92baa48e222f47204491df79d" . + "a8201888e55d0cf2bfeb994172e139bb7e62fb64efa2c84b75c909dd4653cfc1" . + "96c35cc982595f373eec85a1254bcd4b93ea8043420b1ca57ed3154304ef85ea" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "620c8f9d91888c78e893d08fe4599d5cd317acdeced6465bafedb940a8fec0f9" . + "506632d01f757bc3ca0b80b13fef318b4336cbaf2fd56c769ba508c8cb4a720c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "88dd071cd672cd444451f4d10097777b1205d4aec249d52f98502674360b858e" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + "71c85054edcadb05938ea78f8f464d51048d792e061ca760da48e8b95f57066c" . + "1fd4afd53759f0119595c501b83f72eb47d09312e234125933411bc02d1ce7f6" . + . + "9406f5f49bd1b8e4fe6bcedeed6027457b12b5293658a63e2a474a7677c5e460" . + "19f0b7220f858d5b7290dfc22d0ac4b45d8d21fe7c001643f6b721074cc8d985" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "338b68f9a6b8550950cf201de3ca72cae3fd9503b6f02ff2ce317a0e97ae22f2" . + "904fc95a107b72d82d6337c27a80c49d14cfaed8ca6152603f783ebd3c95fbcf" . + "b728a657a8abb353929ef44bdd2be35d6f9db3b1fa5ca61edc00cd5d712e7641" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ba4e43e3dc6ff1ee80de8d3c9c50fe0696168934082804c5b44839049e014605" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + "3f81bd93fddd5555d9ba8e40ae40462d93a189472b1452680e667bb6963bb7b0" . + "c050a608e16382cecb038b0c4c4895e9138cafea2a41ac7dde97fc36fbbac85d" . + . + "7999fbc53b3979cb3774ab15d79b60fc1ac6e1eeb961a2de27931cbb6c509849" . + "181137da6b30e8faa2533383b0a9af118e77816362b56159001baabfce8d6863" . + "774b2276440b5d3796d27c6a6612d7190df580c82bc53d603f736b1fe312bca7" . + "2a8a651877fc08767b0abc06b4802bb36b19861880d692d1fb5db8e5c730c8c4" . + . + "2107d5878847712663756c457fcaed1431deb07ece1ccf797969207cd4b25cb4" . + "fac87347e6e73a26f93e4eb48151e8cbe0e20d2e29ab0d9d9d475b215b60ec5a" . + "0979f48aa827f20532c002e14ac4f7e6c26feb9281e89dc061d63c61a6ad4ec0" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4237182b135cb41f6aefea5b401022d28fc09f0d92b59360856a3121dda4f691" . + "d946c3d92080328ba422b0b2e2a6641265853d41e33a9391b5c7ff1169261331" . + "29e8dd1bfb2bb483de6d2ee8b5f02795fc764e79d397c0a51e02057ff348106c" . + "943de77fce3bfbf6a96595ad1d6b2bf9b98067fa3ca5d7787341bc640dbd8290" . + . + "ac6a1bea7691618a3f5e0be292397efba71d54f1cd3bd4d5c506c43862e2ef52" . + "82358779fd0fead3eca6a50193a32690ad69ab6bec88dd27ddd4942ccd581af2" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "4dbcf6785f479ac57ab4f02742aa8acb0ab3a534a67a3e70c64e0067b66630ea" . + "cd0dbdda246c630bd408165b47888ca60162f4f761451dec1e96d17fc14a4a93" . + "43b53f491083e7ec52bb62eb3dbc90b7ebcd2b596c901e158c2919f47828b963" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "75a3ac4e2434485d793bcb99df77d9fbce71fcaab6f698c62a1ec2f51d619952" . + "b1d386adc0168d017cec4addc6f2e773b0c91e7762c5ffe41c150bccc24e3dff" . + "0f141333a088ba1d48672829323a510af2d07d9fc86eabca4be43d35d9a6d26d" . + "1788494af3a9fceb73c71111db8bd2cb9cdeb091a6f862105ac5beb438b54efe" . + . + "e72d3655193fad0e05029fba37c95cca629be13733057a38448786b1171b70d9" . + "c88fb3378929dbb22091320bd367fe35331fafb80a6b2c7b0ecd5950eb3773b8" . + "b3d0b0ccdd4e4352af68d43b5066d00858efec5f5ba4ccae308c7d0f47c5dbbb" . + "40198f48ac0a1fff2c19e1c97bd3f7aeaf0ea939ea1ed3e0421757092257cb42" . + "878a868eb9a9dd88b0822238b2165028586060f5151024ca1318682fccd37e78" . + "2f1ebd83b717500992e10f32ca3194b52148451a619ba9617c9423a8c9485890" . + "ec7674300537f7080610a03abf9c420a2c262a3c7361b77fbc4cf6b24fcd4006" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "725c34de2c1a399abb782c16ddcd90ba183968680755af8002fe5b0be4f599d4" . + "953f923de72fe791261c989470b4a5916bd699672380b4ee27cc4e4933a5861e" . + "d705bf837eb38577f82b727dd1ef65bc788902c4f5f981e6b94d1533db9f8b8d" . + "b78f1dc8a331277f5ffc4e84029753e29453ab2fbc8e837b1727b7a6c87733dc" . + . + "a68991974c5ea38df4d0a2864a5f4e3ca43f1cbe4860b70cf658ebac35bfaf87" . + "7ccdbb80826950c0f83a19a10f11917cd60560dc3f2adf5b1ef2a9356e61a2ff" . + "58dda1a90f1969937f69bcf6a06391fb2d7253744f35efceb609a1b16c54696e" . + "36de581302ad9771c27e689c8a2660b657138cee873fcbee2d96a31c3966f1bc" . + "bcb25a3993c4a688b22b58fd4e67dc9858776d6cba7b1758716900152ce66afb" . + "6bcfad18fbda08b3574f007fb2ebb6fd5605d3fe4304a8d834b7ea6f0fe9e521" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0da2a11069ab7f38e0016ce0cba45dc7a0ecd304519f4cb871c7056d841e4f7b" . + "28826b0ed600d6fc7c0e4418b936c99a6833039b235bb45207f1a942cb45193a" . + "01d10f6c46fe5d4a6f0222ba250ec999c689a2cecd18a5fc998ad17269d4ba9c" . + "e76ac92749aaf3d02eaa8c2216135293ded5376959b0bfac1061fa9f7cbffc79" . + . + "318dd9826c59c76d262a5d149fa1391fe4283629695aa45e864d8aa86f596c1c" . + "fe2dbaaca3f8b027b3e0631091f04d591f81cef556bda94bf08cb37cd435c009" . + "2218d04d47d5167bace77fdd27cf1e663b12f4fa08f2801004cbe35d17ab1c9b" . + "68f7b9b7b86255f70984eadef797450eec561d677c155ff101f113898faeeac8" . + "bd18879f93d252ec86ea8575eea1c30a3b74be32f6286a1971e9802d202baa34" . + "4ee3f26c812181f2277ef41b63385136a06c974d02b0501e80ecd1e7d64615fa" . + "b19e8a94d02fcf3ba39e74de45856e0ba7a21f79a92d44a3d58878e9d8a662e6" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6c6b96d6676695acd7bc873ed2b8979361b5886dc35c25053212f9ced9465943" . + "7f3721bc913033d7f016947c85e698bbfa240dce1e43c755f0990ceb142552fe" . + "2583db9cf67393fc6254b72cd3c2049d6ab5666dd6efd21e30f85ce107a5bd27" . + "08a50591f6030ac44cbdf9d5c84d7f56ab383652978d68f00cc067a8e1002627" . + . + "ebdd45f7b85433f8a90870c6e6c8d0241ccbaa287165efff76353399dfe6edc9" . + "75d6e98b891504e3add60942e0ec0b78300bf58a25a66bc9b2a4338cc1550e0e" . + "20fe5012bb3730d4fcece058bf9723efbc6c6146bbf4caaadb3273bd1b130109" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "95a0e0031dc8fb049a4fb954223daaef5ca354475e04cbe69c7c3d2eafd921cb" . + "1ef968426cd29a9e54a2c7e1cab1bdd5f3b3125ea92aea136a90b75f33ca2035" . + "fe669f671129dbabbad33c6d1266ab471b33b23cc4fc0d7fdeb5807b18d5b60d" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44fb9bed4e193c40d0ae65c7ad0446ef42ac108d1b0b77f6e3207d7239fc32eb" . + "89b6baf2dddbace10bad2c222322a595d7f3649aee99b526abb50f2a555a46a6" . + "98b5d6877c78b4686f6e1c57cb053e519b7331ae341b9e08996c79630f815e40" . + "28eb4cd0cd91f3bcedb0a1bc3a68926dad6e6f0e047f9ccb526dae05c3a22e64" . + . + "a7687e42634dbc46184cc25445a002dd459b0265b593be77ab12c626376eefaf" . + "620636b72d79ce73abcfffbc1c1deb17255508b22c881cc03bac952c3e14d02f" . + "d0a3a1ba651a744b4ead7438183162372bf6c3b7a71e65d4845de2d24487452c" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "3f8db07f361d7439fca063ca031cf8b23ba311358149e5b49ad94475a85b64fc" . + "19d04670f8ff2327a96de46c8b7353988ade713d1140c9e277b4370a4e39c960" . + "ceff435a35e0da603723f3961340fda61bc542c8f5a58700b5e4394674a2a14c" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f61407bec3069cd727cad60403ba970d7d93daa041649825831bd99e5791b100" . + "8290d50f036307bc3b52cf80db7748f06301385cb9eb83db156571ab5d8b9cb2" . + . + "52fb4a0ae161b445f38ba9e04c4b667941639624c6381e85b283163b40e9fdfd" . + "621d0f3395939b89f53fac48b6be9a360742899eb1b292c9b756e6d8001af665" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + "846bc82f1d6106dcd8448edf03647faaf6b007d928527bd1cf1114dbcdb08ee5" . + "2977772886e1a548f47eb92d51d1b7a0c01c872bdb0b78bf86f0bffeacb847c7" . + "b563ba507ebe2aef66f7397e80455aa0c6351b06c12175cf15923c9f34e23b9c" . + "bf813056a98b1ecd8cfa68a86652f11f9d9b52fb70dd6524ef5185269c63077a" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "590fa9d973caa6ee652e2b50d324ee4bfb3b090bc7f4d48f85614d06117f636f" . + "97faeb6bf698903f226e492342e3fa4e0681c0edb004005174eaeb8f53d8bbaf" . + "f98a942789f087a5672d1180787f9e5e71082ab4fbeda63bac15b2dc6f59800b" . + "28ce1dbe100f3f46bb7f728d4349210e617727d06a4227c4520c8f164494ea1a" . + . + "3e80c4f8e33880d88ab449c84517c4e2bdee5d4a9c4a2d68d316d7215a48b6f5" . + "d093524efa3dd5acd7adbb3cad526087584e4a1eee878b3371b1ea1a6080b53b" . + "3104a48e4212d0eff2da51d6e8bb08f3b8ba43558c6461f01c3540bdb391dc3b" . + "02ab32f24c24a4d0f408da8d5806ce9b1605191b50a8e8075328261bcde532dd" . + "7279fa6f276ef595decac7f9d206c2c8508632fcf4620985284400bf374a1ecd" . + "d3dc654041bdcab3273e041bd140db428150684afe9271ab163a6bde816c6ac1" . + "7d88436f379a6bdb215a55005aea74ddaa4b52795874d0c1d519fb23a2f4b7ca" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2af82ca3c64c51ad9f928d40e577bf8adc785cec67935792146107e0a7d4ab67" . + "82f4287c2478ccc072fc759950ce7c3ffde510bf5959aad00a2146166a935d9f" . + "fc9214f0c037e5b4da9da05638c6050da707eaefac4e4cbc4b9661d861b3cef4" . + "e76498c4ce82caa53d5bdf9454e748808fd5a1dc9f730dffe4691d3e96988250" . + . + "1b1d9b8e2848edb7712adb3baea54b5f25d6015550c76321bd956894bb66b685" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "6996fae59714f0a0365e23409e9a5056a141c5954bed3a961bfbe8bbdbd0c611" . + "9c077e166e7cf879e578ded5a5cb7783f23e43f86287ac0928959fc63f63e73f" . + "79bfdd59a7a0557a19a5b3bd91ff1fa85155ad96a62923aa5c12b3e76d5a5b7b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53dbc1064dbbd0181ca1cd18f55b923044ca1127cefe98be2391479a271f06c7" . + "4b51432ca5cf7904d01346b4903a7c674062611f0dacf6786b5143e2ce86446d" . + . + "99f8a712dcc9000e85916889dd6c84f4f99b10f1b9ed583ac60a020fdedef102" . + "235d2a4f5ebe3b66f2e714f29946e011a987ef9749240b6846ecc6d9b93750f2" . + "5bf6e3be012784687a5cb18a3afdde5a4fc6e85f7d05bde3ff13bc689236e801" . + "028a084ea5cb638c3df5aaa1c0f65a5297f8cc4abbdc8879da470f1c5d98d618" . + "2f34501b9430bed9fa47ce1cfbff7a159bedeb2fa02b150872d79c9a87e701c6" . + "2389d37dfa05036df2644c3a9458110922d0c5bf242a1364198cde1b1673fe3a" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "55c2b0d8b6f43e5d474930ce88ba0a60de65ed0d6fedf41e3610f3de401aacc2" . + "b86a532a496d2410251cafa7054c601fbc9ba1b0382cc379639ce3b9e7049319" . + "6bcfc5d14f2495a5a9f1e878a7e01ec209733b42f17cd418f01a3ee6d8900148" . + "8d2939f75c2a6b43fa08a98e4bd874fb57c2c40c0833816f09c35633e42f81ba" . + . + "84d980dbcaae1f52ecedad798304c96890997f5a8239e9e37a7646bd6af82c71" . + "a8b9ee5673926118e43166f8e21f319c7ba17bcb23b88c05768fe5e351424c9a" . + "f89072e789198119af60f67da4496b6b7d6e5c1a733583e989ea9d4d2cc14c70" . + "8443370a1bad3751b9a3c42e8cef2b42ce5b4f288c8dad950e4ba1e085ccf16e" . + "e1cf5d74694e1be7b9e2f94bdfb1dc87b45cb5d1002f464c856a0179ff029ef4" . + "e317784f7d3186d9d958e3fc9e01653000b5404971642d7628f7716db6e0bd09" . + "9acf0442068f2724042dd1ddcedaecb2be0aab7f71523f049d805c117368987b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1fa1c3fee924248c3ca0eb723dcda3ad23a632ce74af78f736824413bc703022" . + "5a5a9658f4301fad791b3e1fc3e5dd73f37a2019c72adbea75e5838d0cf7e1c2" . + "ce583cad5b3ce5c723da27b6329e096c5a8c410ba358e442526d4d94c7804af9" . + "0f7966ab50963b61bc5dd7b20224670c7580413f4363a076026445b1e8e03fee" . + . + "1ec69428ac2c12d79594becef5c01d1021b85669d9c97442ab7b7ba2d90e95f8" . + "93f3db54a2393667bc497cf7dc81326fd8347a692e3623cd0504471fb15b5e95" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "e221af795e3d619313cc0c6c8343d3ef38fac0f5bc66fd62a0bdafe0356462e2" . + "65156f6b161007522ba0a514f307844bc48272799485bacb0ecbb88dbf277616" . + "f6e6bb59acafad28f3785183776e542e1c0201c4b57981ada9085d2e09caecd4" . + "3c9524c1682cdb91358a2f0c80cba4c34f8cd975c77ed55a831b5162043354b6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f383f2f09368c3a17f0da1a6325d69100e10e934a22cc01c03ba5244bcb087ef" . + "afce873d7f207ab19461f1ae9e2499006d112bd9aa4cd63b953cf2d1fab7f2bb" . + "c541c5c2e84e45d2ee620cc91078e52cb8be7a3900c97614bad05bbc085019e4" . + "5078deb7fa3d85a4a83ece7fbd37618dfa550d8de2fdb74a77769a2b692fd943" . + . + "a3d80c8dcba7fbfb067f44b94d1c85f3309cc30902dc254fdd13d209a27e8cf3" . + "ad1cda8e88087ce22432524338f78bfcfcab84324f8cfd8d7774d6fdadbaf69f" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "323df71c8909b363da3ece635c07cf203bb30f114f1daa6cfd3a8e5e8a023287" . + "7aba1f37dfde6750b416da0900467b13e2370d6d9275828ae0fe08ed89830cb0" . + "978374970f0bfa58ebdceaba3721170fd5e713405fcb3aa13c1f0709dd2699d3" . + "6f09e2b7e48146415ca44ef39f0f88c6a2d61f5bf7ad543e220626879aecc16c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "43fdd09067f52905e8edbf207a1f126d71bc8a739b7c8ef49b4e1e13176dda89" . + "cde83d6c72c8247850857d37fb01fdad66d5071ebff8d49be328c028bbcf94a7" . + "d891023e9c842837d4e4984ed5d2bad25263e4ef204805037cd63b232604f52a" . + "d262a3dceb301a636c09c87d1c9d1f8c9f9de5b1dd27aa931953857cf05c0a96" . + . + "675d82d009312b6551b5591c484ec291dfc114da245793a38e740a7037ce402d" . + "0dfaf02f50f904c3d70f33e45bde2307b3282ccfd386f35dd7e92dae765f8989" . + "da3bbd81c8025a238f4905d1cb6301c0080fec6856b4ed9d92b94f40f90e6521" . + "cd28c05b5567ffa739d1a0c6f6ea7bb0b8abf16908bfbe3442e111f881d229ec" . + "a57767b0fbec36be8f807dbb9ca933cf97e47788b67e925140aad04ec7704cd3" . + "8bd60db2f53c40ce2ccda1ee7900bb364baf890a9569ff20e9aae5f92f9a250a" . + "943ce123d0e38135efcbc5977a87ef29382e3bfa2c8c7040aa04538f4ba5e230" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4958d002cd41d2e4d8a1ca1dca57dcf806c3f9f47d96207a80922dd0a199db9e" . + "fccf8bf3b7f496b8dd5ce458068461281d7d522a8d9519c3ad77fad111193acf" . + "c7d19003afe889d797dad2bbcb507fa8200c3176b0d9ef89e9c829e5a097b50b" . + "c1a044be27aa139f67fa0d2f1aefa4d45dd137730a6307fa20bfe3fe17c48ac0" . + . + "b6e2bc8c40928d9c877c4ec1197812813bb662da2c89ab808e55f875700a818b" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "bcac6e7563f21395386588722a3d80a8e71927f23ce0499e3a8178e461d4e9f0" . + "928266cff8a72a6ac0e67513b043b340a05322108bd41fbf527bfed1e8ccb739" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d10a53fe373f13b9427a04366f2563640b3da25728a34b0f32e6aaf6e9e9540d" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "7d9c44e18d0a41e41184fd60392af24822fed4e6c096b1d3ac6886923cde2359" . + "711365fade8b8b2139f74c9582125b616f44cabc1462fed08b6babb2e3cc6a29" . + . + "24f057395c4efd8e249261fff95a65e7836a5d76743c7d5c9e4b86be70dc7ae0" . + "7e65c846049d8ececf6bb2b0c7a47040b811eda42e6ac1b2928d8d023129ba6a" . + "3af7dfd521fbc1455346dc00c7f0c604399697e173b1cc12069b076ac29b32e0" . + "e3f60b970c2cb7174d2302417369e0da6654f5e44ab89de1ac08e8db831233ac" . + "7622194904f5e67a55200e22755a646ca4d232a642919d7154cc854cf1e82648" . + "532a2d4e7e3e84714dfb5973c2c53e27844d8e1332f39b16805659f33842cc7b" . + "8cb53f946072ce1615e3533c56a4ededbbabb376a178b25efb73896816aadb30" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ceb58c2638fb04eec5cf55ba47fd9a373febdbc7e68ac05faf307b033bd6b999" . + "5be40203bac78a6f81ba7f21a9a0fec5011de49092c48faeec34730a74c7d369" . + "0d66eb5b09150592b659439f1e4b13b2ee84667a5ff8722b6fbc69ff125af05c" . + "45874434c28652d21fad5b788a4ae704081bed93efc979493b982736ca8a9491" . + . + "81e6a8ac2e389b1ca5f6dfb523817b8938809c219287d0836a4d546e6ace3a45" . + "466ffddd1604f7eac04b3b1ce458a1ce26afb7a7ed4d2c92b0f74bd813b9d306" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "946e17b6483d3f6107b9ea91124459ba8c90a60d433113d3757165b624bbb3cb" . + "2e1734e71413769e20b3d73fa387b6f00d2d1f419e9d872caddd75d63c66b451" . + "fb5da3230a3d36e41bbd3049758a6d722fe0921caf5ef0e4b1c09f9504a1c735" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "38b5a9ba573d013cea9ab605a317ff26bafba83c3d0461a763e4faa694eb9686" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "2f6aecd8a5cd839a8d244e4c38fa6a3d5685f0af7e9b26fd5ce2fe235e4dc5e3" . + "32b358991b6b7948f440f2eb49f90e7531a2ed07b6f96c12a284c2315aa69d12" . + . + "c76a4435c3b583224ab8343493b47079433fa488973386bfce72b5b42fe8d8e2" . + "3d4126065f30edbb3ffb3f412bee4b62b1c8c0d1812db65b06e760b3eee4f28e" . + "2bf9c1c7b679ad681fc1466bd4c63cfc9f1315a791ad3bf86e080a7586c1db7e" . + "08b3a5a096e587359598da24f6ccb2bf168b8ad29ae4982b10769466b3f6113f" . + "cf745524a8a432cd117acfaeffe5957da4c0f9a3a5be0e313dd31f43e31e03d1" . + "2d786db023de5bb06fd216b4a6933840f6d5750bb50aaa7d9998db1395e26b49" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ecaa89bc4586a8451789aa27d679ad48540a9695937423b5be21144de6b49b72" . + "b72c87839dfc4861233cc291324df74292c32a1a1c23aa2159b886af9ea2d930" . + "65f23494798bac14a26618fc7ea594be5bf2bc65b9125b1951df5a33475a1381" . + "a703d4179b555d814c3b6d2589781aba05d6e920c8166e14b0c0d8b041d2c946" . + . + "a3d057b56fb829bcc8dd3869926371b57094265d33b274ca9f3334fbfe13dd2b" . + "6bf86b5709d2258e9b6db6b5701077ec11d302e5256509f50c34275e9c59d942" . + "6231c555ab29c38e22462beaa07a47072bf7da0db971d661cc7af67bdd880681" . + "c8a07d1704b76186e12f016fa3b12299829d542c050bfb4d962d9e3f55cada2b" . + "f6d12e2b329c8d07e393a1583d7680adf8405fa13dc570895b9997066168d1e9" . + "6e25ae02b137135d56df4ab777feb6d4a147d15bcc2341730f94bdecedf219c3" . + "0eb6639a96d588742afc77ec991fbd467047857dcb05586af81d60285d08931d" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2ac8df13ff060b38982dd65ba13d855eb211d0d5182e95a671124e631cecf785" . + "590e43bd6e0a5a1f50bf2622a79918a1ccdcdabc654787dceb23bf295d5d09db" . + "60280662aa59117be3f2a0a779a7da3219134532d9b231f64582dfd9da18c377" . + "b205c1dae4f05d39c2676f235408375e31681dbab29c3f4477c8588d1625633e" . + . + "143d69eece118e53c28f86f99d669879bbc213ea02217a5c60398873a524e95e" . + "008fd866bb2c7f4ea475869ad0fe3b3da97333006e7345b4ef79adfa88453aa2" . + "cd99cea8b7d7ccaeb7f60872418fa42972f0459314adebf2645b22a1d306b087" . + "9c7117005a047013712f6eff470b3bfa3ffa834200b92bb072bd37a496ee4952" . + "d605c7824a276beb12a8e95ace7d12d5c9d6290c3143ec6fe457874301d18bc0" . + "d6d5c6bd53c7792b17b740413bda001e69ecc693b5aa7f19a89c3e83480b83fb" . + "8137a0cda7691202861b637798caed84e570b08f88e1c219d6765a7520323a68" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad4d0bbd102e44a147c659bab2abc360cc5dc87f6a9b5a3ce627effeceffc9e4" . + "69ee91c1a4065df22cec6532c0616185d24244abb4606803be498df927b2504d" . + "c3a9407fc58db0c8ff8ec8168561c1b998714aaec46e89fb3a2c297b52ca75b1" . + "8757ecc54e574d1ff2e9ceb2030a80fe34f98a545d3a57cafb7e53bcdb71f424" . + . + "35012f4310ba4972ae35b83f13139f559f37f5f41317fd2730dde10dffbad3f0" . + "d1589053557b5d407b4da96f7f05d67a29f2ee29692baade4908d80d70cd5a61" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + "87566fc4186e90b4ebbe2aad3594953296dde1f60d516314ece52422f2c2fc15" . + "401cc74bb238ae5b62199c89ef5c0036966e7ebf84ea5530b6ce241196c4a213" . + "c563c46ec59a7bff5b78426b7fd83e316e9894777c1d614800b1421df6bb2af6" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4402cbf1f05c7f89328d0b5b63815484262ce919d3ffa7fd4eb8d89125cce958" . + "4d0f119fd6adb425760681d8fa6459e5d665690183a0ab04efc2d647ad16a9c9" . + "a8c57bfa0955a6b4a20ff0012f1f864242bee68b3630104f06c3dee417e588f9" . + "236c889f7452715fb9ef0863dfbfbd76f9a2f7b4a4dbc652dd5dcd07a93c39df" . + . + "6c0f063c7b58e3c8cd9c8ddbc116f869047549fb1e489e7bd1b9b8c522948fda" . + "f73392a0051a1e4dc602f3f9dcba0ffc05dad1341f7a34df2880d6568f7a0863" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "214fef0f8749616653e545e859a701c29b90f5dac96afa1e05b8dce41d50bf63" . + "5067af339fc3e0590959139db61d29b0d7500afc86ec9d02607b64f410220fc1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6404ee7259d791a75dd348c648bf68c9844f16b94a004e510eaa1f5df364f525" . + "6ddb17a81e6dbf16ab235922eb6ec03fc40bc781d88243789443d19b0d31c619" . + "461df5c7d74eb4a3e4809be75114029546376b82d1a299e06370df5e53c88402" . + "fc7ad26518377fe4bd690ec87fac9a942d7fbb4f37c34eb6a824003c1d4e8ccb" . + . + "52e8258219652c85f52e774b31490ce52b11511190553988ae96011c493806f8" . + "98cecdf9241545d43634154050d8ea5c44a1e61b3f979cba320acaad4d359fa7" . + "83866e5241c93c5f747c98798b0b4a82e8e79aed3dd66f6374e0d9596560fe96" . + "3e75edd678b4832d5581046e71d3b9a5bba34b1a84b35dcd927ae664872f35f4" . + "5a3ab973ea6038e3dbfff743fdac0643e85aee291713c3a7eee1e36bfb9a2c29" . + "d6f31c9278880493573984ad9f11cc0487cfb3783993d7182c2f2913668d28b5" . + "d753d3341905c9d5e55c4c66995b73f8eecb4965c9ca5ef242331fa12b6c3e3e" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7a7eea16442bdcb8f405407a722aabbd8132af344f94bdb7890c79892595b15a" . + "86607239c30d3cc1e659b1491d07ac18bc490fab4d83917ce4abe6f6b0e010d5" . + "b02a113cdea75264e4fafbab765caa92ce27be9484103ad1ede83336c3832f7b" . + "64f78aa39e12b1ec5d5bd2bbfcacd7da8e6322d007917910398e39194816ae75" . + . + "099efeee0fb96ef241f499e1bc416ef45eed777f5f0dee3d1ee4420fecfdf2a6" . + "6795ec8a76ede8340af6f162c2951ad15ecbec3918cec985909b7c16fa24ee51" . + "e44ae713f3b34e612ef31438a077455f5c8ec5dfdc9f1d236e96731a02fbd24a" . + "4d6b1845431991a74c43855cd191290ce722f1b26f1e0e385d38bdcad09acae4" . + . + "37520f8df92a03cb91b373a269c2f425f53baa3759433e04fe3bfef725e805ca" . + "cb3cda0b037472586fe9046c0cee90c89d22a8e46e2c5a4b7a9c35c87d8e8ea8" . + "ce527e5719f5d81270d4445602040380770e131ce2d57f6fa7c04defd0861594" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bc5f9db97b994303fa3c208aa2682d4c46ed10ec42db279e433607160b029f02" . + "fe4672b40a4e907abf1f9e208522cd630841d68ece0bc82c4a9cfd51bf8696b0" . + "570c2f6d591fff1c0eb80de0b4378f3a630f299327b45315c65c2641341c7d55" . + "8c1dd65f670967028740849a7adc9d80dac13d755297533a1727e026efefd6d8" . + . + "7c3fc56805f9bd85de6196e522f6eada540a29b9c325da2a68d4a24598b26386" . + "60b068182aed5941a7b0cc52e959ca32721fabdb8fa9a955cb2a8515e59dd970" . + "d81c2da142bca67a663e81fb6eaa69f6185c8e651728bcb1c04a470baccc7af9" . + "7ce05616c7e3b03c63385da6c68ca96996b9cd5b65bb9195ac63de635cc9f209" . + "5d2dcdd88569f0258ab155ea80f9056216512141c1adb86b533910d7e4de1ba9" . + "0939aadd3f30988f5ecc37d7d55b565412dbcb92eb7940cb5b659710018201b4" . + "4e75dfadeecc294ffbbd950cdb8fe1780c261df4112eccdfc943822c40baa122" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e2779a529855405e2b778a4a549d635aa222233553cc37512631d7c13acbc44c" . + "56996efd8500e9cfa253031563affd7492cfb61c17854490609d1b9870d2078c" . + "ee28bcd318b885490af566f92cef3f619945d87e31d17c394885229cb1ea7b1b" . + "4c0aea857609af92e3f5a5ad9bcd622d0be68611069976f27d163ae41da8d7d3" . + . + "619f696d663fa6ef0e4e12af2196eeace7b59df31f80d79fbb42c2826f02552e" . + "5e1e315188c7f6a506b354b9d6a079faadac24932ccb2a1b1290373fd836b47a" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "f9c78823ef36f7040756c023cbfdbcd95d42dd205ab6bca6561835f4af9b4a49" . + "3124486c8aa1823b91fce55366dbf035617a8d69dfef46f9bb36e46f33f5cbe6" . + "4c82b4bf7fdea81c1d6cb591845d1e12c155b0defc9d99da953cf9c49daee229" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c4d535ea681a650946a8de9578761e1b00fc3e8c84da6ca0f55b0318fb982ffc" . + "c1893a02f3b685f1f35081ac7038601a3adab551ac627c71bf12126c547c7fc3" . + "f7ef9759d4a6cbe10d0aa145cf053c688d306a1ce2d6cb47fe8762fe4de541fe" . + "5f96c042517d2e9abab09cab143d1ae52feaeb87a903951610b30ef74fe7bd47" . + . + "f3a31e972b8146bba4d9fc623cc9ae313892acfe8f585c907a850cbe8e29b1b4" . + "003554961b4489c368ddec945534918cf700c71b406280b2d747d4530312d1f6" . + "e26b27528a9b12d958731ef0d32360e3a6f1a9b723b5fccad495a28d7342eb31" . + "edf2a0c924fc489734b1032f0ee2ba91beda6d1ebc573ac92f0515485a44e1e0" . + . + . + . + "65dc82001ee4548f675fd6b883e21783d8efee8ef09c6666fe7a4d55ca406e26" . + "768cf26677397a792ab5edefacb8f9dadeb1cef95283185c9bbf8aa9c3a61227" . + "95694396f5b760f2780928d77e4db1bfc0c3dceb33debb0d7614804e3dac6c09" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f52350e8ea642bad6efd168cccf62237c53f771c3241ad16c10786125ad270b0" . + "338b68f9a6b8550950cf201de3ca72cae3fd9503b6f02ff2ce317a0e97ae22f2" . + "f16f1b69559e8c43d6dbe1f52b0858402f58e3cba9c71b18547dfd0d56e5705e" . + "a935830ce50bb62c1957877fbdc6c07f5e108d860e9a32f32a76b72fe563e19d" . + . + "f736e20c6df4e217036a4582521fc203e5a561311ea0e4bd60b7668e30f4240f" . + "be526456bb79da93cebbd8514d0f8e21c85ca5c1caecd1cfcd53bbf661b0269f" . + "a44f3d41823b1e9ea5cf26b98e9bde24b46b545fe5f67c94033f190460b8280c" . + "6ee5770ddd98015efa6b416d31a2d742330e1df0db259800489f2acb5a7f046a" . + . + "789ae597c362fef0466539046eecb4155ffbe2fc32619d84b5a2f228e6609c09" . + "5368e6bb52c7d7b08e9e16bda7c5a277252692e6607bcc945d75564855d0707e" . + "22741e49da91659721b78fc06c132a4672bf64942dc907fc350bfe03ea3bab75" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b886a5a663d0f81d38e80f2d037f784fdbe4de05fd63c8e0c499b306e8ddc68c" . + "b0f0d3d61ded3918bc29bd4d4bba039116b8f3ea3cbc05693c670b534ee27327" . + "b957395bcd83eb7dcdc89169d59e62aa9d686cb1549f4a2b67322f3a4444ad7b" . + "22daf30d2174ec16a6f7631e54c7af5d88580eaa60503a89f84b62c0ce073355" . + . + "ab7943d251b010931bceb074cd5bbe9bbf0576738038183fb4daad1ae007da7c" . + "1acc83920a40b5c2b84451f2ca9da6a808f13e416a74babb45a04e8b156d5f2b" . + "2ccbaa9f1cd96fdadad41b139297d91480420ee9ae49b99f8498cd067319fea9" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "e9885e2026a8d87dc69afa362425e6adfb9056b3d4216bfc6132e775ee1c9614" . + "618d24cf710126fe74fbc67c6dc28aa2feb454543464477dae12f915a2da300d" . + "e7bf5a6f4ae40adf6525a771f8d6c5aa64c6f4f2e1a57c21acfe0bc50636694d" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7fae882df9ce6f950c45d2087c34bb481499733db1795a1694e17142695b694b" . + "a99fbf614ee9ae3f84814d6255ba4da3c327acee31cdbe64ae3626fe16f1623d" . + "457ac78ca45f46597c40bb18d73bace3d0beb79437feeb66f1f4233e2c7f4f5d" . + "e070d3b43fd1071f99b384fcc0fd3c5ad4bdb6e5f73a23d9347734ca08075553" . + . + "e10f735f702100d4571b004843dd8a6b7562d880934be9d075335f23aa6f7dcf" . + "a83e388e36f6c72dfcc43557d3d08264702c32f68d83608ec78362d39cad2685" . + "a37ff197b7eae203d41ba8a5220dc50d374b106b57aff2f952bc113e83000e94" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "a302509f6723c714895334defff4cf25054aaa402b8f8322c857f80fd58b0a8c" . + "e4db3ff4d72cf4e93033a05b24458da775d80ffe3ae9f3453e4eb2952df97814" . + "d05fd3cc8b8b0cb4638bdec8990ebdf5b2e60bf7a57d25b42364de6ee7d575d2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "90cb771bbb302cb40356b0e95571d987c8ac4e7c42d8f588243d950ade87a774" . + "615a9db56f8588738db0236cee996613293f9be2bc3514e809e979bad6c25b30" . + "90260dbae8575851fe4a322623bf3623b14c5b1f624015c21d43cc301335af2a" . + "586d1bdeb5c78dddb93be5c0db1b06e3293ecfef0c9f91a19e8c733e2e52f27e" . + . + . + . + . + . + "2cd3ee1382adf34b352f790584814c6042cf48cc688cd31e7b040aee03159895" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "ddfdcdbc2144ed876d344fb5e7076bf64960e5db2c0888e6347b0005da3473e1" . + "265c873946f27d77e54500cd321cec22db45aa1e3a084f243b7a6da0c2bf7bac" . + "1518720c6a3e1e1762b39ada6bd9663c28e63fe0b8d1e40728fb8d89a4cbdc70" . + "fe8ecc5a976cc6327246adb126a98991abc6aa962aa23f039a29f281fbf5dcc7" . + "ddfdcdbc2144ed876d344fb5e7076bf64960e5db2c0888e6347b0005da3473e1" . + "cfa0e82cc6c8dc336f33b4b8123f5b99b40c171f0248282eeb2f6c4318edd774" . + "47fca8307d323e48c1d26b060fb235fed55ba8ec2981c45ed9167e786af6a1f3" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "34cc7291d98df39359d51ba76fb1b7e81dc9db7f975969e598340f6398d0af74" . + "3300866e7cf632375aba746630824088e938bd6dd3b78c033c07e8123de9cb46" . + "508c2d819bbcfc6e9e6a5b9fa84373689961b4eae523246e7c87dca8aee58329" . + "8aa917534d57418411db72a4baf641ab5054e5b228bb3a350b1178992cf79df9" . + . + "3d15f20a544fa086574c7125227bd32f2a4c93f9278d6142eae8c8f26b95079b" . + "311f2c7797fb6fb8ee071f7bc930bb23d1aa21e171a63374eed06f49a737aa60" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "67259976e3ce1c595e57905c95d27260de1dce9771553e1f04919610702a944d" . + "41ffafd874e4439e4d4b98104b4c8a44da02263e2f2a06a42a84d8a3454d7bc1" . + "a26a0575172da0ce41e6a69e115d18c4547810ce00d149cd1d2293bf0fbcd990" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "123f6af71ff89f7037ebc3a3a9aa35e09ca4451b518422f3e6597f36e12591ee" . + "d6b2a262748cb4bc88707ec78e94e853fc85b341af781b9636edb5c85bf41cc6" . + "6e6db53cc9f418d58888a2a855db3e802a4e6b612620a1a3f2e59683e8a837fb" . + "ecc34ee94d07f542e1b6df9cefa0a2862e11096dd76100c632e6405d0da38d69" . + . + "ca6ed1fed65a1bd721fbe93d846fb4f88a766812d7748f34df34313d5a298a03" . + "2128a43ddabd72ed0fb955ec3195906c6fe24f070883f860ae22228a1519b91e" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "3338dd192b29bcbd0df4801b017cf7ecdc07b31c57497e99d464e3bf88fb2f8d" . + "4cdb0ff695be5c165ade213949a61aa0f3cfd18db2f0c33915df486ef80e5f66" . + "874c72a7d3c6284a3f22727568bfc533f44bb747a1946a1138b0f5335be46ddf" . + "a6d4dc422262ff37ac1ee52f1c12f2da7acd5d309b1eb33efe8f7f23ca5e8c04" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5971288e13ad40b9cc029f91d3f0be0238f0835a22ad9aaefe3a2ba777b7287f" . + "47723cf8489982abdf0fbc3d84c35626cf89c7effa8926039333d189ec7e0474" . + "fdc745822dfd2ef65ab40aeca6ec5e0385da0a61e6de20086e4c11d8c4960d9e" . + "47777654727dff0f1efbaf32f476d976a5f18151656870b2489515e5c6ca0694" . + . + "94c8357ef4daab21ae7d3b5df76be68715adf720a23d305bbd667e2c83506ebf" . + "1123552c8a98822caceb258d437424329c01f5b1bb47bf23314b5e828fe229f2" . + "cc3ab9f34ccc79951d61bfffaebc79cfdec7cf9c84575f45db495e235cdadc00" . + "7309066d76a422dede360d680b64ac567d747f7f0a3e8130c35281ac2d3b7b65" . + . + . + . + . + . + . + . + . + . + . + . + "b45b20ef215e507e4cc94dd0da8ddddc8c85cf612999a5e27cc490ddf9545b09" . + "cef6dd851fb19f2219c183b3e22094f9400260dc4a0752f0e20dce3171fe129d" . + "33194de76afd36dc77d8614c7e8e83633b31ea97272d9fd732b7bca374c75066" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "63e9db32019de69bf3bebc74b313b600f37da03b8ac3253c593793ac30e11ed3" . + "a0697221a7110ea9df36226ec90988ee8bf47a849da967a1796046dddd263ceb" . + "52395b90c79a3a9fb0df47d17b3b8db880fbb8ffaa6be7ce345766405c93ef28" . + "67ff35380e0d906c6ba0a786654ca16cad8e3ea4b0538bdb3d5ed207ebfecada" . + . + "a532568377fe79b72d07c9c4e7e4f290e99b7b33994b532fad7c12fd8a91e856" . + "4c6f1f835c8720ced75d09e33596560dbe495cc27570ca7e24e2adfa46693265" . + "ec9625d5cbbf3ff69e97b528e1fc17483a25d1df8dcfdd5145db42361076c827" . + "ce5cdc507e34e47a86110f11b9e2bedc4c178f5cc2c7bd47a9723c4ef5ac002e" . + "b5bd47b26b071a084e26cde25bebec268e60f16296de379089419fc0942723a9" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "efab03e1a6e3f66404b39442c6d44092770b4253408a8b24ddcf9cb4997dd9af" . + "a1559bc690b71a13b01c4f12232ed3eaf0436149be516bebe4375379080c73bc" . + "af16272ac8a9f4b197bf08d38982e78e35f1d58328c8b922955a4efac6db13f9" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "df3bb7dbb61da233bf60cb506c2b8fef49d2f19519981b2cc6d9bc5393b01784" . + "6297397692e3bdf90d61f3086f261a93d1afb1c5d0c116f440e40a6a64c4f533" . + "e07ac5b72eaa8948418263e0da7e9b3782d401d73431d659c2aeed79e5230a82" . + "df14cb726841114063be64abbd4b4b621179e566f16e565f2ddb73e3df0d4dc5" . + "115f59891eefdaf6676ab19cc6ec9b77579f792f0781842c7407cbea186a89c7" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f8b1599dc11091b061841a04fb607b1dfd3375d761fe3f198575924278dff640" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "d3d22675132df71870c9c5d81968682440505d2091c66d19503550ad36bec510" . + "8e54d2467abec7c721614165b7fdc372b300629d60a694e577778aaccca15a94" . + "b9bf7319f5d5ad2b5fb6006a99b7410e8fb0f4e89dacb10b1ee17812dd6dc2a9" . + "7131d3cf4e55afad35a0dcc5d0d96d4aab2b966ccd99fa07beff22e82f7de5d9" . + "00b622a0b7bf768e82cc140ed074aaaf4752fec749005be0d454c7cbf467711e" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "8e54d2467abec7c721614165b7fdc372b300629d60a694e577778aaccca15a94" . + "421080a51ed7619dac0485c5e179f0b9b16c7a67910d2c3aeec3238bb4f6a362" . + "5030f9fed3e01903eaf8b65c6482fb2c439d5df6bc9206ade64036fd38248cb1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "119173673bf3410d82f6e07ee5a124bbaa3421fbb561839c86bcb964efe2a9c7" . + "a464deaac0cc0618733eab1aa6cf264da1fd406c570b43d7494ec14f3c022932" . + "48c805f745616238c251961a1c012913328517b5b745de2f56db10fdb1fa9292" . + "d939c193095f48670966c88d1aa1934050afa08ecb6cfe40ad3a2cdf58a73254" . + . + "39fe37bbb9eb775d751c0ce7e4cd4b18a447062dd8f6d31abffbecb60604f328" . + "9ece66b1ff627ebff782a3e4ffe4e1f2076906771baac31bb100ef1987eb3865" . + "2001071b904b6ce6cd639b7d09018d748aed96175d82641d6c86e0b5ae0a7d7b" . + "0f7b124798fb0609521a103893a44b30cfe258a46de22dab6b19c3f58adbd461" . + "90df63f283230b227e677a6f542bfc9b7bc08a0ab676c989190b91cd7fbf78f4" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9ece66b1ff627ebff782a3e4ffe4e1f2076906771baac31bb100ef1987eb3865" . + "3d3063100ad1bc719f24455a6a5d7130a2ca1db0365054753a4b8b14203aaf1b" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a248d4841357a277da0a39087fb46e99ddc5aefafc3e47dfcdab067f041c9808" . + "0dfb3fbc3b9d309827789a04bab9557d5a15168db5a56acfef28922dac4103c2" . + "71577ac488128cb5e0ba6f216919776a2e7bcd86d73640bc5f326512da51a5d0" . + "85483c03fe9f140392121288139bbd360dd8c68c9b32b6f57d53eeb6e3e85b06" . + . + "20784cd296552251d68497981b3f633c4a22d45c48e82ea2f326be9623d7161c" . + "0e52ad3532ea3e30be7c92892e2ebb8f8c59c7c3c2b3f45613eb60ad211d69bb" . + "3b1b095368f34b815c58ce173b4ca7db3b5ccedb1924e218c55a23bcd0955bbe" . + "8d4077e7a697866d311c0c1c6766720cb6b6e91d1a53a53d818fb23f7dcff194" . + "1b8cf2ba37092a442491ed70e22da1ed06a2f7c13ca44b279bcef042db32dcdc" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "1b978e1dd40e60d53a8228bcc522d6b3809af767ccdfe7ca81590e5aa2b5a1e0" . + "dfd826e8c80236c1b8a8aba8d26cfb0f0e0b0c4023e9cf6d4fa5f6d24ebff616" . + "1946f08f7ae8ade3318d9419109966c8822bbfb7a2342db58e82fe634310b5f1" . + "51648db51d77b8c0c379b77dee2d7108da4baadf89ae31f2bd158e4f4ba99658" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "08b4a3e25e94a3c9cfc21a8f8dc6dac2a3ce44d0c316896082d290e58e1ca604" . + "82303950736d869108968e6ce28687787fcb51f9c2dc83373e99d4d7b332585b" . + "ee9f93c3917777f918487ca2d68dd7bd7e8e3d9b3e3bbe785097bf9219729199" . + "de274fd7fe15331b2f5ef84b846a3c017b5851d6e7ec33bafa1092fa71debc44" . + . + . + . + . + . + . + . + "3e52311c4deb2ee874defcd44527c24ae11cad12dc773b315113f42a84320847" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "52a076d76c5c3410107782a977d3bf9545029428d1f1477129116e1db113e67b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "a6211b8e4463bbe7cc1d2088d0f24290271cf513662cca78e29b42c402f2410d" . + "47195fe9e065fb242bd2294f42a63c74ae430cb69a96ed0a2dad8fccea10d5e0" . + "1b2f5ba84a92bc301fc1b9f40d9e2fd0185df022c41276e54c0d2ce8b2a44585" . + "2c9a43420be719dcafc65566ba685312585030c07573598fe660e902d37888da" . + "1ef08035f4e1cbf73aa1a78362d43a6acd87e871b965a81fc527626755e5ad8e" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f7f3aa3dcc85a93d457f3b490560f69efa602bc755c23b98d148de7ae335dd27" . + "2b8020263b53202709fe0909ab57c51981e1f3ebe4b2df71c105a2db9090802f" . + "fe1f4acc9beb842be0a81dfefa11e651db54484b387f7eef65ad5a52913a3954" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3e58a1c2cdc7b47e231c06531f3dcfedbcbb80a16be10b4eddcc846998ed237d" . + "51bcdafcf433202a4fe2b08c05ed47efb06b95c7bad29d57912382ee8bd2e65b" . + "64cf3cb77b39f68dfcb381bf84954b0504ca94d987440368cb41df86ecf0f1e7" . + "84d0632513aed31df1726f1ac7177faca2475c4f279f171acf925483d9921d49" . + . + "f84fb1749c760a7ad50975b40f4c24e9c21f487476fcd4f09e33e93183f6309c" . + "133fe37ba5bbb289bcd9eb1ad9b42ce02608c97d84ebf7358621714423f1c23a" . + "cd231cb5edcc72e05c9d73f0cbd5541590026040f6b19e95f84648478688ecd3" . + "1bf2c9a9ac509db4b66b33236df0fe223b2a1484e6389ba0d096a9d389d6420d" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "78e68b7896c2b3e0d90de39ea7bcee9c509b467a9232bca1229aa58b95eeb6e1" . + "ed5ff45864eb025acca934bd1eaf6113d79c8a4d4b4f85df137f2abe01b6a6c6" . + "f8f225ffb1ee898c7755e509023eb2ccff5b4beed048a1bea1bf0103e8af415c" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "57762b6634a714c90d51f63b2d7053e24af786033e2797c080e219a5753e2d5e" . + "5a5a9658f4301fad791b3e1fc3e5dd73f37a2019c72adbea75e5838d0cf7e1c2" . + "94c5cb8edd8391325c28594332a801a3e005648decadd889c0e9a624bde942bb" . + "e3af0c5dd8d4e620f244bbfe326b75acdf6b66b3714b3c021572084c2465e661" . + . + "fac3e7c2e77865db5ee32e139fea1cb4bf1dd561ce98c53208fbf90f5f9ad760" . + "6a2a5afdb1d820c83720c9b614d9fedbdaaaeaa52dbf87475f16473fc6d34c3d" . + "5bf6e3be012784687a5cb18a3afdde5a4fc6e85f7d05bde3ff13bc689236e801" . + "b8202b1f7f1852f24df6b47116ca7f45fdaaa87bf0ba7e4481d188de3be6ec4a" . + . + "f43d830f0ee6991f24ab9c5479eda3ba4a8ec51f1c60aed1b8a19751eb7da7d1" . + "bcb7181503232572ef558b0280c6089ac70bdb199352e6396e71bbaea79db904" . + "75ad31b0831e1ded16ac12fa061dc1c1b7682e598ab901ece4e6c16eaeeeed84" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1bedd7be8908832fb0b16d33dda5aececc20100a930598745c0132abe47ebc02" . + "d16da8c24cf08a1c970d1e9f5d00fe82ea79bdc6201f79791035f1649ee7ec16" . + "24dc62c1c43668cae7cdf779e331643366d7bb64d4aab7a8e9f48903ba355242" . + "8637aa096bfbb235c5130dec2eeea32f221fcbe1da826121c7384d4f821b5db6" . + . + "2a1cbadd15c3a26098b8cc13c73dc0305f518fbc8075754da96633497efea2e6" . + "b310473c53fb4d6585197719a006e7b88d48df8c054b4b5548696965cdc97028" . + "4fdd8ae1f952b8be4229343b109b3a1bed9d55235a2d0a55d607efd4561fd7ac" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "b310473c53fb4d6585197719a006e7b88d48df8c054b4b5548696965cdc97028" . + "84289e95037e6f746c8604e850bdf57ed138883bb5040c40b942f65c1c4c1055" . + "80a8aaa9308052e3beb0473becc1603b9aa7afb7871a6785480cb9d5951344d0" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fce013142bc0d78d1fe3509dfa2014a878083d5c4e3409db7469e7f25bc8db88" . + "112ebbe930d8923b57cfdd2c649aa194a403ca6db0561c7d4bf69452cc4a4e20" . + "b4170977b297b2af438a9ad72a2837ba342d7c1a33728a1637d9d2790ef2358f" . + "f16c35917363e51c1a86b9912b0a1a916536778f452f0f7e1b545aeaa5715bd0" . + . + "fae82cfc0410f56f96df4684e523695904c9e78bc525f4588ab6714682758ce6" . + "b91aeba7277f527017380ea59be8456550429d7f14b4aad7c4ed0469c7dbe2c0" . + "30f95b068683552aa6f81cf9f7b4bcd6dbbb9d4d5af982421db5e775b1f27455" . + "420b1d8493dce3681d5566a40d783e2e8c317038b90c17de62be46f4eb47b270" . + . + "e9a8fa0601d082d6c70cd7f8e24c29fef9d5e0ad662fca41cdb7a967e9052108" . + "9c607a976668e7cef55f7d850e486dd2f691b5fa0f9d3e047f5b5140d44c53c4" . + "8acee96aabe4437462e5bc05fe9843128ea2c14c2e891013a0eac794b4d772a1" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d58517ec07da7d562d06f5812dde8b1cfa0d7f73b618d6016bb9f6e741c6792" . + "38236c74976ffcf0390da249841790af22ed339bd55ffcbebe10294b7f5c46c0" . + "40f8b5c1d1f5249c052502eb2d37f5b67ef60cb66f1b726163c40e1f150b7abc" . + "8d5cab96ffafafe69853e777b7c3b7dfcc047a9dcfe5a55c3b3ce9d1b49ec72c" . + . + . + . + "7a6f02d59049f221ef6264ef9e335dd8d1ef19f1f8f4d39809687ea19aa63558" . + "58c8a74d5e500c86d063ab086c6a72d68a64b11eb69dab2090f0c4b846c4b60e" . + "a03e1883d279a2503ea62aab575f643b1c1261b93772725a7509bd5160931f3d" . + "0948c1851bbc149f96239962bcc8db38cd074f820aaab3bae8bbe86fcefbafc9" . + "dfefe49a1d5403117cc7f7e0c24ebe7b47c7c4d5ba89e01714262156912099ef" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "91ee78890ff5fea7b387def47785f28ce571795584da8dccf7c46b07a40862a4" . + "f1ef336e3776f74882ba46001c1edeb5b55818551d77e197320a48b9dc8db436" . + "c7b2221cd6b9ad0d7e272a8e6b6dd2e6ff85c1baffd92e2f2516046c8dcc5200" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "45cc6463dd19cc5e51670b10f4592dd32e958533a2da0beef4ae70563befe49d" . + "ef0bd3518cd1cfc91cdb1caa08371baba6dd53f11af05c3cc52dbbfe5cd9a5e7" . + "a566917ce8bfe4b83468d7d31841fb2e424927a00d4d91cb69b835ec3cfe2150" . + "8c461dbc3aceae48e81a902955981706f415387e0914d93b076a7c462c43f222" . + . + "e31dfa6b0191a12d4ec671501ddab11e132293bfc4ed9f421787f5b2167b40a4" . + "ac78c3e5217d724ef7c7039959c758f025d76a32be96274676f307302b55dbfd" . + "009b4d9e2fdf19adc2f6dca6bab779e55ee6de32111e60e170c824367297802a" . + "d964759e32499d69d4aa476059fa9c55e06259ce97b33d0001f8b6ff339c5c15" . + . + . + "9f78a59aba3cff1cd69895184568d7768677f6b74263d688343c0d8e77c2cb7a" . + "9759458a5f5d59407c35d992f48d06aeb1b7d4c25a1c3984da424065c0fab8f6" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7abbdf7ef4a5a736c70061d8f02176984818e256d0ca5735407a6617450feb10" . + "0fcc19c9f32b7d0ad5220c6637efaf430c6a792e84685925b0f62931e0341aaf" . + "d2da3b5b9650e82f4d751a9ceee93c4a7b2ff57843b0a8690e1c17b3b9a10777" . + "a10f5f1f54210b6547603efa53d4e611ffaa44a397d9a2e98b0122233166d718" . + . + "6fa5a6c5173208873be88a18828761e84e0b6fab2ff58190d3a9ee39374a902a" . + "066d7952db709062dd902446b663523a6a7a4ac0dded61294bf98ef5a31ecc71" . + "8c8333c0d1b6e834457650dacac6c4f94b215c3ba963660cb38a03dfb3f93be4" . + "463418b8aa7201ca1a6883a6452ac9a32779cc072688b29e002bced50e6db04c" . + "6592350206fd2a907d36271b044d3f6af1b7681164ac680750057a0c78ade9da" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "066d7952db709062dd902446b663523a6a7a4ac0dded61294bf98ef5a31ecc71" . + "ee310c5d4139343c4ad737ead9cf55c7f20b691a52baeff4d5ba2fcb82c70d66" . + "423f6e66ba6188dc3dea317d012beac0374938ebd3490c9fa8f38a87dbf252b9" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7287159112003d31cec5d310248da2e7e63fa0acd2610ea58a5d0b5eff244f9b" . + "616e126bc5afc43318514b81e24b9f4dd61e91226ed61a4653af107000a544c2" . + "66561cbd7a009de74ab556f90cda9eec8c4e47c271bd30f2762b3c2c35032531" . + "ad3b5adc70e403b1045dd2919a08d13b82042c311c83cd01b6cc2d020e2df356" . + . + "8a0e0e511f43990a5ae047e129d49e77463d3c137706947632e57cc1368cddc7" . + "88333e969135b76a3fee642eaaff837afee7df4c5417f7dfcec3a2b1559be9dc" . + "f464cd14fc43c86fde02e2120e225c8a4397b766c48dc18a94033791466f0255" . + "91e6ed0e7e8061b3d8df981205a3652a4ea5e7eddd9e95d5690d1f62385fec79" . + . + . + . + "bd919afb651128fae1821f9c4e9ea1aac8d4ebd4b1c1b366145e4f845911b5cf" . + "28699a71fdd9b724db773def7a3481aea2542132a1d8bac63c3f3230c28647ad" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "91e30daac544c256026d2cd067ad3613187d1e3d57434755dfd5221e2eb037e7" . + "66764329ae8331bfbc1666fae4f69b1dd72f0377e1e5bdd20df0c8c16e7aca31" . + "93b0a2fd91e153195b5ce57d55176ab1ae308addf9690537c160cb9012ee56f5" . + "c322627e24f2af9e0644ccc27d48c5bf29947da02b80c24e4d7209c1f56cac83" . + . + . + . + . + "c045a555fd51abe130a8f94518bd15491ba1c5b2bb652ba03707cde63dc072da" . + "52957c3fd2c214018371d7420ca17dcba6b88921841f0d43bd2f9546b979c021" . + "495ea9a6b592b1e98afafe09ac71b9e11112aca42d7e0f56e1a5d1a0957081fb" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + . + . + "44058d75dffeabb8840bcdb8c6b80d6142f6e68a68b5dd098870c0d05a4033c8" . + "8c66c6bc3f4a88fea727b747f1e95dd28dc994d4dd618f24046ad4eb067171a9" . + "9edcb84e7cbff537fde4721484853399330460e23e6a86d5e1aff7892de5175c" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "260e5a8ca4032b5d916cb8040c257096d2bdfedc976aeaeb80aa338fe20afb1f" . + "4a673e34f4b60e20305dd081358a3b85b106e465201a44c2bd82a5dcbbdf1434" . + "2c21346c3718992111b26ab5ec51a6607dfaf0fd1a9bbda85948001c35e91727" . + "6f7a3d36963988d863e261ae211374a58c24d470e2e8bbffc0ad593f7a24963e" . + . + "320448dbca835a75dffa9a332627d67696ec23801c0089d7dc295d37585b413d" . + "c7d1ea52d5ba69ac2e5149e1b886318e3dbccf1b73c5cd2b9c0528a033e4103d" . + "976580da84964e711737301ab51410705a48bf7efa24fd2bce06e4f55f6de412" . + "a49869fa5dd88235578f0a5c65bfc1abf1831222c7a939e54b40354adcf88127" . + "80f84969df614afe51f568ea55cb2c63b2d2fded375528f1359e4658b4c8465f" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c7d1ea52d5ba69ac2e5149e1b886318e3dbccf1b73c5cd2b9c0528a033e4103d" . + "9928ff73c9cc6c94e8eef6fa643da0b26367f1a9df615d2af52ac6d91e8cf076" . + "3bbe71f60356e7c417862638372c0b76c0d874e11c77dec4cbfbd86803d97eff" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "78d9cfcc2f6e91b186e7c4302cc43627ce776792eee491131d226f3f91261723" . + "dc2f00df510feaa9b7867e0d533eba7b554cdbae91d599e99140c25d8e7fd76a" . + "22339d8caed5bade1025bac66e6fc3dbb9953ba72cdea82b05bca25fc532e0ca" . + "ab9a8ea049179f215691bf84ad9597129472ad6d063ec7ec56e67159e431d6a3" . + . + "ec4eb9fe7e67f28f4a592cf043b2945a052120f0ef7fc29e85ebbf13b8de7f26" . + "6bec7a48d5083afc12489d327cf39b1ac33a9eae32fad0badc6d433010b732e0" . + "35b5799f3914a48026f7365c2beda06c0b0ac5f5b88784a64652da30b704b98c" . + "984a55271d780bfc8785f899f79cdb539883ddf63779d68a48ef5f8858db6eb8" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "24ba752bc4c45e628e9aa75bce585ac5d85ded158f19d887282b8f16563ebce9" . + "f79c5b0bec36a5d49157e64fae10ec1d86c8d2edd0a3ebbe6ac9639b152afbe7" . + "dbae9e5a636d2a87fe44f6e01118cf2b64053ceea260ff4b65325d9700df08bf" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7ee7d9f3c0aec8a2ec33c651d3a3e836aec512b3780d503501b1366f37077b7" . + "17b51194b3ffb93ef854ed393e2469c3f9aade6db89752032f42dc4123dbe254" . + "ab2fad38bb0f1e03c3c579b8b2d0dc38cc883ef2fcfe0d312f87cf626dad4fda" . + "7028dcfa38ee4af7a446ac9239fd0aac8ee55e9a91dd3e7a9e6dc8096bdbf705" . + "ce9732feba18d1c0f78f5cbc4aa87b242413c1cc3b0ccc8bfdd95071b28f0cac" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "09b5f027618cab3b7b5adc01903e55fa31eca89a8a2f65ba0eb92c200b2694a7" . + "88700bdbe592652e6ed940acb483cdd1f1ecf9cd1e0500d9786a62118c18628d" . + "112b84e389cccde2110ffba1f9c6804f260b5cb9add513d0f50e3f288d24d371" . + "739d5688b68f50a81823440da19b4c0dbbadcbd49766903eae5f3841a0fa8ee7" . + "ae7d2ff483a99ab3fa85be0ca8fe0881269fd573990efff9457517aec3381543" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "261faf607049751b1e8f33e87438bbd2bb77f58d9b84bc2bf3a1beec8dce4771" . + "7d4cdd3d3ceb1cc32a9b939a5c3bf153c3a7954d8d332b9d3422ec91587aabe1" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "60c5f5e2524df0856f401db47251e417fe3e04f808c29faf09a5a8cb3c8bde0d" . + "05c7fb51b11f5b0272a1762ad58a3353a7baabbd843b4f47d6ce14ac797feccd" . + "07010d29e55dfb602c447bb12adfb22c7a5c021e6263ccbc8680e386cfbc86dc" . + "6da2e779a06e55be8520def815fc9dfdf00bd60081c850e11ecc325bceb9c5ca" . + . + "c96f545c8a4e89f177b034e5510775918ca8157428091249059446cd21ee5aa7" . + "9f46f7bf9ad5ddc2b95b08a2cb413baedb04c4f191c238258771a1c975fa88e5" . + "6b18167a2a603241c08f7b94983bb694201145a226fa9549ebe485b8df8185ca" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "7ed0cec8cc0acefbff172bd9f53c86c4ee381b770e81026cafcde27cd750d5db" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "9d410b77582498a582bd12f7d9ce666e74f206e0e8d6ca9fc416a016544a530e" . + "c2c2496aaa688da2e5eb43bd81433e11b4ed13b59292a8dedf1f5f45b5e70b49" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b31f3cbf38cf1c4bb7d86c78da5c2a1ac0125108358a4cfd1a981c3eef051cab" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "192ac5b3b6a2248ec2b97c7057ff32468bb28d3a642fce5ca5ec47a209d0863e" . + "30b9e39fe82ea4e91407831736744416d0bc8f5129e8ffbcffee81e007589241" . + "5ec9f5a79138541bd21d9fb8f991cbb675cf201aeb7c0f93328fbcf60ef59884" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "e9faf730391cd8c2f7bece593d8bf0f2acd31919ca6c8497cf261623f14bdc66" . + "c7b3df096686502812ede4badf85b93293e04a03e924649370c764a0b6b652ff" . + "9f31a4664ca850c3e19fc986800971fe2e476da62b776f9dbfe0acdc8982dfa0" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + . + . + . + . + . + . + . + . + . + . + . + . + "50d54e1cc62aeeac35587c9ae3aa825f21aa448a690ad9c6df426d6872da6cb5" . + "fc6d16760c779cd0b84c71333b060689f8506c795110f89c91f8e3f4632fcded" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fe1004dc2644b73e9892405755c0dca720307be84ac56287c4a191c0caf95e31" . + "11598226d6ab575b96e17a00b7b8f8e743c10c863e74d5635952de3baf175f80" . + "ee1408d811fb6cb323c82174a2979b32830d1fea413b9ad823d277241e0fe1ea" . + "4c4b3a29e885e8b78889330df9c110f727d20bc9a365a072ab7ef0c1f458d866" . + . + "0fbb14e134e04259b64ad3162c92dcbc18f6d5dc166e26783454092cb6ef8e0b" . + "8838829c4bc630661ce35d291edfb84bbad716e2e4d24771a573a61ac7837ca7" . + "d5ee1d44d6d5fbdead8de3b65f8b284b1e5607a14291426b5dcfe68b1cd6b766" . + "6ddb17a81e6dbf16ab235922eb6ec03fc40bc781d88243789443d19b0d31c619" . + . + . + . + . + . + "e8a791f140a7f99ee392e38fab8327a69491d0eda37c1ef2b7d2ad052430ef00" . + "d19bf0402228c98c78e085ab744fe5c3f2a36df20fc269e1bf09759607fc647a" . + "85c3f7b45307321450805c74750d2a41cc9f4aa9427c7ec023bee06cec7d36be" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c7888d82c89566f3e8c9eb52475463d0e4de2c19721e8dfad351f7d39cfb3e46" . + "cbab58d86d0e1eb284160a24b906d54408a51a2d830aedf4ba9056338cd4bab8" . + "8ec3d5eddf96592337379decef00a4b8569ee42f46a78f9fd81c76e396aa7288" . + "42296aaaad76b85981aa57d28901c34c0dfe6591c86eacd3073fe9e8c98bab4b" . + . + "5c60ca48585e6b2e417c33a750066633a6f3e20e55ede365caecd129f14ef5e7" . + "c9919f8cf89ece59de1ce99d4994153200533606bf73c2b8a295947e5b681875" . + "dc90c0a63ae1e868770513c1a3c0dfbd4c0107c4429cb8add7f84891846a484d" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c9919f8cf89ece59de1ce99d4994153200533606bf73c2b8a295947e5b681875" . + "5e37f2edf64e8e470a9bc4494f6c7495fb31d53eb1054905d4567a3286c24dfc" . + "dbae9e5a636d2a87fe44f6e01118cf2b64053ceea260ff4b65325d9700df08bf" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7551b215bd599d7d245edec4a2c3a01703f41a960d3cc0b1fb13e73b41dc8049" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "5c4472b88fa0aad9183df9a76136fb30b5c3cb2cb93413a529bbc047521ae1e6" . + "c0dbd30b52b6597f751451369cf4842dad0bdcdc6998c16491c3f9c5f7f3d2c5" . + . + "e9da22226a3c56465fa782cc6fef76914c16bddcc077741e4a90246e7caef785" . + "0d6c279a46eb2598ac8d5cc698af8a8cef637e859a0a6d27f7e86ab14f0f7070" . + "3f025d22ee5cb480e21b75b48826d057cbbe9ca2d5390a1e441837ff3854e83a" . + "dec34e88e7399155286a07596b00f05b416e466b6fb1b1c823bf86fb27fa7eb3" . + "ca6a0d6b4f2845d9f18d2d639bcfde49323d4e68ad523d9a4cc5f912db30daa1" . + "90535344565caf889217e49c7436f155b9aef905d77003c47706880a9a6091bd" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "aa85f0503553124de16bfda71e245e1699fa7c1425a285264c5f3602127e02c0" . + "e0ec93365f9a6343f168a62ad73e0d624d09751925f4230fa68d5b2b69ea2674" . + "7b5c2d301674c095c1b77f6c353b2b429d474c8866dd41b0522fa8507e7b1973" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "df0715971f046a9513670cfa0075df5d7ce8dc0b1d9bc3bf4b4816ca8f30c508" . + "e775edde0136382f2058ee316c6f78b6b81fc7fd37f71590649c25d5a8297d05" . + "a5a7df96563d3bc3c6d00471b28597840f326a0a0a9d0e35e4f1caed2142127f" . + "d2aeac52191c758872afa5a4d35282cb22fe00539052c95415493373e769841a" . + "44dceefd7df5488c7ce75f0b4928c7ce39814f5ac89d6ad4c4849c3433eafaad" . + . + "8aec9731dae31910c0f84029e656b208ee1786deda6626b62ea13293e90e749c" . + "982023e99a480ab63dc43530307e8b0abde5f0c3c00aab1f7e95ddead08781f9" . + "1c23dd7adbe032072d5dd5c378161e50577864c4f8e413eeb0997cf4367977d6" . + "d577404527e14e67577603c9279812d5e59bd6ba4017d1f5b3f59cfec2e1afe3" . + . + . + "4ff5b7b0893b78169768941e04f0759d791e03411c3231477845c4bf73adcb2a" . + "96a906d6258a5763894d4b1344f95368612ae87c82f71176222ce71148a3b5d1" . + "259856997542c089aa890d5f0a8e5dcff6b7152bbd58f5308f64a12287002c8b" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1695cdb954cc003476e56c16cd3cecad6bad3208909d427590bcc76a60d8184a" . + "1f5466f8188372c3752d2a8289bedf7b61e81657cccdbf8caeccca2e49b188f1" . + "ceb0a057882db536a54e6b1f39453919873a7d14cf1dadff0c6c7892a5a74137" . + "38c90d9d9e72e10f159bc8475356c68665711105335a497bdbe99474b4e9594c" . + . + "774fe6a30abdfdf15b4c1eb00ff48a87f76f817dbb37f942c89b6b7b22f79b1e" . + "dc3e79a7227bf612ddd2d17814a9f0562d42f9765f3cf9030e45005aa9b57c93" . + "9f8aee6e05a0c2a3573ff2f2cab2c609e0c66b727dc8d752c3368276b666f9c5" . + "012901f7d4ebf54b82aa4e3346034fce0d1edca78cf853e93fe26d4b319d1cf4" . + . + . + . + . + "774fe6a30abdfdf15b4c1eb00ff48a87f76f817dbb37f942c89b6b7b22f79b1e" . + "262dbcb72b27d4601303761dcf999df77d99a68c9d50d60d539936a31b3e4f44" . + "3e356a00cddefd1873e96840e6caca01db8c258f6ddef9b511dae23edec3b699" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a71f9c6318a02e42e70947bab16b63623de009d0bc0b710691a92aa0d074b4fe" . + "64aa4070bc3c729b42fedfb2ecd86492958c95003f8f2612e05b6009f38b76a9" . + "cf1191ff79130d5811fa29d6a7b7e74f4345f6f74db21dcb25606ac3edb7f4d6" . + "0543508b5b900891c1999f21a3111b1515c04371f0e68e4d6b4ccb08b11dfeb7" . + . + "0d024244f59fda94db3e35ae3e17fa117be39e734919c5dcf2219662f81f930b" . + "4d1773f003701ee86cf5dbb0b6323b88ad39594eb5f874fcf6aa3ebdcf1f0eac" . + "42a7e17c5445424b0baaf216f213d6f76b97d1ffa5798f646a46530e0459fecc" . + "76f48c971f231c7b48b6103f67c1ad1a309e1482d40406b262d26d6cf0d7aafd" . + . + . + . + "13f349912ea08afc7deb228bf526a96723b97738f09bf1581469124ba2e596a2" . + "3f48de4284560f53dbb3ca92d40b440c96ccfcab0e1a7017c557df96be1d6bfb" . + "74e8ebe5bdfbff5b76ce4600cf73275ddd10fdc33db4b7aced0a5f09257566d5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9ff9c4fe8d4aa9f8fc5469de80f1f6ffb00d48b0ba0dc60712785242424a61fd" . + "5d11c7fbcb9f50cfd49d8042553eccbb55d05a20bc701e774d8aafb513340022" . + "d95ddec4dab8273c3b24243a8a23c945a0e5d1541c4a7b71ae26d5fe8fd47e62" . + "6eb3e94ab27fef045aad9ef4920de2a1547e2468ff5c308d6d34784d625fe20d" . + . + "b2ddc59cd4b6e3c7e7a4268a3cb74f51861734c642d47110d2337a94e79aaff0" . + "75d7b83553071018f764186a9ab4d5fdf688939eb1cf0c75a8d912038600f776" . + "a91dad2e631b75b945d827cdc590ba953d43386f1f42f1baac1bc03250551645" . + "75a0518f9f75d2de17aa30e59668358c8b764512d38b85c8410902d2b935980e" . + "4117b139691f8568c7088551aa1821d3829f8655a656e67a1643096d1790cca8" . + "799555b6e301eddc18578ce7f52c884a422b7826ee76cb2c54e4a3a90c83804d" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "88b0d937aee913871a949b25986dd212839e05d6384afd84feb8c01a7172bb72" . + "853af52b083aec88ede579cdc69013e285a444faa7aa8524c46d5871795b3711" . + "11cdb6916a029531a343928fa3fb882492aa029596dbec29dbaa15e5efe9df5d" . + "387e6ff0d6a07a109e25741438d4d70103453458eaeb5b2eb20ff06f73a24b6e" . + . + "24e0373fddb9ff3006f573094774dbdbd9be748ef32442981f0f5bbb26a71fba" . + "de9398302105cad0fdfd2fd2a8e7cf395227277a5c45c3880e4e171688bda1d3" . + "67e69029334883cd24c078494b921bed2c6ae422001cc04d1e5dd04b62b78bac" . + "061c780ee97558d912961803f85758ccdca485d68ebf42a2aefc8275607b4ad6" . + "1ef8d4c3581883c9fdc2d1355d5f5024e4da3b72b763596cb403186cd9026e69" . + "b6955b0337b2d712b643f88b875744663c74c841372067eb6052d15cd08210de" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "58048116eac93ea3b7d0e561cc8e055a451199775b437b5bf96c72c82c959159" . + "94d6ccb55cbaaea43b90cf19cdece24965c18ea9cdbd950551177d9369ca0d67" . + "d23c96e902d05b7b353fab241957498f5ed9899e55520334fe70ac6fcfae6b00" . + "9a102efdeaecb4a4ee57fe732069aa0b777874087679c21d190721b45f250853" . + . + "81b0abe5f1f683c9fed88e31cc57df1e70bd3b4608af4491c481e221f50c8dff" . + "26d49c47d873d10800751bce236b24f372f10a99f1d697a3bf8d1f50b72cfed6" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "559134c86aca986535242ef39e235c6be2b2117ecc1a37b35611ad168b99e6f2" . + "37ccc24d0314cf15717465c33e7c364ca86c36428b5ac1480eaf208db13d6604" . + "ca1e2d45caed772ff1912a2b6e691d65c5fa00c708cb5f7c40e9c5a621f69e2f" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dcfb8510f1567ccb08af4c5cd0d2d2f3378ea093da1877255353eadb4360e8d5" . + "78c7f1c12db904ad372996b1357df7ccd137e82ccfd00a6288da16c1a9f12b70" . + "e7f4dd6a6057924bcf0648d4e1a624c3cb8142b7a4c3009bc1e31b9eeb6322f3" . + "417412e2ee4bd6dd5856043df7acb856ec0adcdeb6ff280f2fb3cbfd1bf78ca3" . + . + "8c74b831dca0c9f6df66061182edf1e1e988fb0dc2fc3fc4237cc9d1ee401537" . + "3c2d8953891fea02ac04661849039467a1cc7ae17240ec0421e0ac5b4eb4b5fc" . + "6964adc15507503e561c977d74ef9dd6c3db4d840b7c2113c7c19226d5a763dc" . + "c2316c9bde76c00b57051ba68dbf87ccad7aadca31fead4fdf4c91ae9f7655e1" . + "2bacc6e2a1491882bdeaf20155249096f180da9431073cad537d130a55213846" . + "a73416ee445a00ca0249fecb0d58377f4fb96292598750b986eb1866a704c57c" . + "018dc890e3a4f724c602c0a68736eda3afb6bcc55f5199e751cc421eac3628c0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e5b7ed8a27eb293bed165adb7bad9ae5905e1a265564df74811e9d2161f2228e" . + "f635ac02e4b873a9f159d0b9b91c99ea2bcf2cf9552db558dfb7e665bc2ede1e" . + . + "da836f530db55b44054ae59c640773958761f9da64a1e1c0143355de7964d449" . + "697960b2cb6401d13f1bacbf1cebafa6875004abe28c9ce0e4fb5e836126316f" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + "0573769400c68eb6f1b816e8dc76e3173b58e7549f26a5511b4b5fa10f95b65b" . + "b5512533d6462e363cac9f35db39aef86a6c70d9f03d62a3aab4c93f98623eb5" . + "4055ba342a3c4d47fd24832f0856d054a35bb375dd54200d2f13db2ddffaf4f6" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fe6ed5e52c608c4d6d4c2378a030a1e9aaba8c7903cf32952982817d30c54277" . + "eda50bea4712a4c052c451510bbfac7e00383dce33209c0ceda5ec9571d9a6aa" . + "4fb9e6aca98423cd576d69ff70a9c64974b35c47a516191629c35cd1ddcad5dc" . + "bffaf22c1ea13450c5d4d086c570dfdd8b58d5d8437277843d6c48c4f6726684" . + . + "01ced0b94bbc7b87573b8635954ef911b512f3a8179606f0076aa99bc4651958" . + "fb7a54b5a57855bfe3972e481eba023cce075154ce5c7cb27453e4a7ac06fb43" . + "bf89455b33df1752aeb7bc60d8fc5a229a59a834ee564578fff8c1322d07c200" . + "ca79a7ae19d694497529bd4a7647c54d262885be9a82306f2219ad12db4003ba" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "c2af37c6b08eee29fa00d5fd3d1f4fc1eed1b432c76cdae2e493c5e051dafffc" . + "e7d3bb07258d2b0fa5bf7d40becea0fc95f39fd211e17c3c2530c601ed8221d3" . + "936a8807c6c84da9db6074df16842a442cba03c87feacb646897c3d5e9091a05" . + "1f05ef0c766f1d781ee845b7b3cba9a78c97ad271dffd791e6bcc43e245d241d" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cecf6d04757ca63a4a2afa58e7cf465f5871489847af4cff59852321c1ba3db2" . + "8b8515e2db3d24bc364a6bf7a3dc296d44de93cf1379e466afda92e47a5fc53f" . + "d628c311c9388a7ffb4671948d33efc10ecc9e1753669f0e73b7a005cb950f9e" . + "ff191aefb7149f531e545b547c7ff8ab9d7072bffd99838d616270650d8445ce" . + . + "98a1ddf64ec6304513d83d9a66cbe2c40e34b11bdfc1c4bf11d2be145368e34c" . + "c5772953eb097ad9b5ba2d3a158f286410f4167d607d9a93f0b361ff283bc813" . + "61d7740577304d9b7fc3d47774e320425e87b13343625d00343bf4a302c83a64" . + "3f8a3413035fea3b9befe5aa12fcb11712abce9ea4288987da6f7da10eb5218f" . + "a9df01b36151101890e9376ba0d6d91a8932714988e4aebcabd2c748c5ae04fd" . + "266c6aee86e53873fa3ba11497c06d829e1480833fab2cebb8d376c61d090b47" . + "4250c3c4d69ae59dada9bc4d5dea6248e10edf7c859a1ccd18516698e6353f0d" . + "ef9778e1a89b48cf40d8c9b697992854c7db35f67c6867898d45d047bf90a4c6" . + "23084b274236b478fd83abb47b2837b62df51cfa4636e2705174270eced87127" . + "01282d573ef277af811355aff4d0ec203cb1ddf2d3cd485bade418fe717eda67" . + "f9e27369b2efc646d1c36884508f3885e8df97d7a9a7b9c8a3735bda43130869" . + "34bc5aa92ed1ba5917d9a07e20e436f3582c08fc263eb81e974b904a33f5b371" . + "4f4120685601762a16b86d37da9c14a195f40dfdb1594c88f247c01f5613475e" . + . + "3014b05636121b8fdfc493073300b9c1e4fe1af3f5bb159db8a21d723119250a" . + "5a9df922e92fcf5b772ca57bbb562cd4ad28992401a9e383070f47d43fbd4b08" . + "35eb8177a0b03b547f135fc0cb0d4690014c7787bfdea03a28661055f5d1fedc" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "83ddb458e76505d3fd4d90660d184184fd9a6f11ed3738fc768f2d9a1c6f9c01" . + "1e40c093baff8f1b48025daa5b94ad9fef4acb5ba58e5cc46892eb3378176c08" . + "240b4c3c8fad2d1687eff1ce66c810f7ea1852af5447796230213526e8f7c055" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "af2c9bc338d80866547199a8ef6f3a16f0cd3b362e803b1b5f429e8f90a6f000" . + "1c3e7ae592f5e1a90b8d869b4ba178ebeb720fb4f4a3518b90904a779e445b1d" . + "cfcd613f3dec709518b7deab8311da34a2a9735dd4e24aaa83f3b3259eb4dbbd" . + "c54cfb38b50d3750464c2b61cdf71b0d9fc2ca20670933561436dee1e91efa56" . + . + "0b85b89ca3b8fb36665ce95712d301290f0e6ed2950d0d148a799665130d62ad" . + "f18aa7b59dbd0249bb426d0c93bc8c92922a3e6e5573133daf4e2862f71cb484" . + "27d7c61819002d137fffe479a8a42a5782d535b9b3e609f44e613fdf67fe6ef8" . + "4d71a227a27bbee34c174fb418356edb690b58f2a5f1a801379a258701cfc4fa" . + "2b6266ce2b78f553a6094ad78acd7c1bac5bacfa82a98d1d0a3073eab7ae4272" . + "9a638d930e8e64ec91311c812361c4a2a313a44a81bbeace36606af776a2a8da" . + "0f7cee29348c4f8e5ff3780c200c96f0ae15fc4cacabb848a3e6eca56f90c744" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "736f344f8cb8c9f5683daddabf06932b3013db4108f060ecf43653435a4ad5ed" . + "538d008961fc98bb6bed01ac14df9231ef4df245466a94b1dbfb3b9d22a6af76" . + . + "d21114995f86b73c20ed1cd0eecd814f7da4b11f0235455e77f41821f887602c" . + "f383e02934ca169feab8a5cb5a63901abb4c46b0ec4efd5bbbd8fdb14f0044fb" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "e2d56cadb250327496b142fa4f60c3e1a3e8342772d3f0a602c1f6146c0a7d89" . + "e590a167cbf0cdaf54e89982ff4f0e5a6d4aac887db77274ae0b317c66640c55" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0efebddc27117a3bcea16272778e9af86727a8d9102d6245144b3fc925da59ba" . + "46059d28bf12855a55f2b961880db94cf82f5a8689015a91d4b6a48664e40acc" . + "f186d91c7e64484457b0a4f7f5c042ac911210c9b047b3c5f898193664174ec4" . + "d5edcd2f369f7ccd981a2137dafd04888ca76071243ce1e00dba781923ed9e63" . + . + "dcd46bd9dce5e33ba2116db10e71db7dc44c817e5fdc023624ca44d357518aff" . + "ade0ff7ded486d1cbdc8f331b10c5a89a4ad9bb7972e443b0046452de32bf090" . + "0c322a8fe3aa0904f3ab49f65317d8d020dda46e9a482ebae51b8df972e11e65" . + "980674906345fbdaf4f3591983f8ce3562872aafc7b97266185317d7f9f7be39" . + "54d0d29f36b09017802885696d9c306576511457dce6903424b3063db93d2843" . + "6c4ef45bf1a2e9878d144a1c3088be58e498ed2795c7009fb8d1d58009256d55" . + "975576dbcabdb9ff196af2bd020feb10618dc600989741d01a9cba666564f164" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "324310887dd91dee00167d4d71a0034a71b754c37f708e2790a9625aedde07a9" . + "8b2f9068a70f4af7ad6388bb84fa906e841dca0c21867a597b1afeb38fe1ce04" . + "fd19ba2952dba55c6808c71806dafb9a9e363635907300145dfb1b9ffe147212" . + "ec4c6743127379d328637f868d3582d9a74697d41e5b23d07a1fb9dd24c197e3" . + . + "a5a3328800b9af284ec9fc4dfcb607448acb588f862fa498b00268befc5d34e0" . + "44628ee89bfa6ec1d81282763efde4183efd830c26f2c7a5f92d2b62e61fc73c" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + "4108efe180aebd33738f9ed8c048cf3d7d11a24967fc51b65a5929ffdd149006" . + "02799e38c010824541ecdc4a915d9fe5a136e9f648d9df4bd9a9cd3e6370332c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f13a53ff91652c830ae73a4d7d604413cea47474df1de31ca8b6df8980a9ce2b" . + "a19c4b809b83af5ef71b70dd27898a3210719e238a20e91a0d7e3eede3136a2a" . + "f2519683ad5f7b846c562b955ecd50da5663796733398250094f428aa95bd96b" . + "4a274c057d00035e3543cb69bbf568cec1c180071fb6a1c87fca8a2c0da48ddf" . + . + "61aa4eed0cb3372f0fede67aa1cd50c4971be766c2d1d896bd1ad2645b6b0037" . + "04ea0f0b9125cfddd19c96edf499a412663795ca407af34bd4d5d98f90023252" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "c02087e9d039d252400771bd78e8f4eb66a246537fd1dcf6947504c6cc7a4296" . + "bf5530a92d1fbf9d5a17b5fc4dbce9fb18a8fceb65b2f9745f9b5303f8bf9fd8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "650437681d537ad5c6a6de87a65caa3631bca1382836fa4fa981aa935adea318" . + "b0a7d32965508b1ed546ba507bd8d33a3deb8bc3ae8b883c375537c3089322e8" . + "3dd71abf5f301bcb59ad00376fbbcb827c3515fa7a8a4133e7e72564e3a00563" . + "3b8125798a652d730d04659366a098ed0f0583cc8b7801a263fa119c5c9bc7c1" . + . + "4e6d6cae96d42c4a414d899d3e5fe294526d7d12e94b2c57515978aef00c63bc" . + "559ee2229354ec29ace6da6690c39332e2f16d207d3e144f1d6cfaac8d575e45" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "bd19cc9e2c7b1933de6a97faf4ce92238a9f324d8e5fe99a2f3e954798ede962" . + "6e0acdf4233750fbff4c8d851b6077bd51b929dada2d3cc76e3c17458047d26a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d8a249683480ae155d8091c127186899431f278672e172a24c03998d15792806" . + "7169d9d121266a853fa999ef048b7181d8c400181c380142b103a8571cff842e" . + "e46ff1219ef985b5f0d81c2cdad0bcc8b6fafd41409ee6e6a74327ef8eae4140" . + "9860bf5ec9f0b9c2851443feeba2df891263ae0760993c3727636ff102973c7d" . + . + "44f84b226ba73a0d44ce94eaa1892e9f68178141059d27df314aa1209f7dc53b" . + "cc1636f16758c1d11931b59d2dccfe0cdab8ea5072b7088abc2b369a82d551ec" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "7658df422f0323e7b9d67a440b465f016bd1191ed90b1f1d78bd93bce9941116" . + "2e1b46c877585852391af3f64d8daa5c9e4ae1345d573b259a33641cc1328c9f" . + "c2366584430134347549e70ea59f2a8acd5185a0587a0794f80da19b224375e9" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "94e598ba6012724e7ae9304499d008ed3e043dd75269f058248f52aad368730f" . + "8f4f20b1c51c5440beb6d412abf11ea17e3f74009d425cf752b15c24341bb063" . + "5aa532bd8656eaf88e192fcc2d35af34ece6fca0d7f8535426b94d1dbf140eba" . + "82e41ef1674ead0a08a09d9b45f9ba0906f9646193179c1b952525817118be98" . + . + "1b818152cbf0c87dc9610215b79e8c32d7ee3051d6e4b5ccda4e96903c0bd3ff" . + "a5c4a70061e60b525fba41155fbdf19df843de3ac862509ab7fd283b1990b23b" . + "0e8ada6473f82c354f5654458e357a1e769a27e0f8f06eb68fe252c6947eb036" . + "33e139c31f2a1a1b5a20ee2c560dd9e3b27c3c0fdfa2d12155fed5a3786cff4a" . + "5f96de9085430e3c26a99a6787b53cf3c5fe76013a02c39b24d327bf0a69e5f8" . + "73740e347a02ad45b5b47bbdf7b293e4619a8a1437a62a62c6170563e764f850" . + "f68733449b3cd524fe0b3d848c7dda32349021c742103348e8e9749b478d3418" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d7582bfb30939c39a3992d527da8cfe9df47de741ddd438c1bf1706ac70b14da" . + "76f48c971f231c7b48b6103f67c1ad1a309e1482d40406b262d26d6cf0d7aafd" . + "223522fafc49756641d8eb9abdbf11618ac3fc114cfb888c2f760451b3a49cc8" . + "7973b98835dff1463d9f3fe13472fdd2525e19e744635b69011a094bae5a2838" . + . + "4936785b8d05defce943244a3f23c0708095f2e7e66f70a114d84722192550e3" . + "3afe7b386664ed6eec64a0caadd2bbf8b8c936b4e0538609cc525047bc907fdf" . + "e2bcc98472b4eb3aeeafc7857daf9a7dc3e1e169ea3a463a41c1d74d1d984bf0" . + "75dcc8df13299a41967060e54056ed71093e127c8d5fbd3ebbbed7c15ff34ba3" . + "5be30e642d654428abbde43e7708a2cd32b471c6dd172a354a4c3887755b9f0c" . + "402ddaa379f872efad063ba2b80ab1ccc24b4ee0e7aa3f9a51bee3036224b548" . + "ca826a01d1c0c46da716cbf6f07ebce4d3e94a5df87c2ac5e334c1f0037368d3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "347e825a55439959c180fe8382c2d29a27efaadddcdc32410cec442174670907" . + "8f8ef5885d414dfc07abf1a8894c33c3b200e5bfa5e8a22d215afe1dd80a8ba9" . + "574d1dfa533da3186cf322087a0b00a08e60568986f0629780e1f3bec78a7ee7" . + "ee889386c2b62dc4f8295336d9ea031c59b1c91665f600b926e942c4a974cc02" . + . + "cfb0d2a671eaac474a87e3fb33354339ada68adf26f94fbbbd78daa7b53cc252" . + "382f6f1278f3775f7f46def9887bfa8074e34a59358e94052317c445f6c285f3" . + "96c35cc982595f373eec85a1254bcd4b93ea8043420b1ca57ed3154304ef85ea" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "6149335e49f0c0966b8c652f95ebb7326add5abf2b7a69a521066095b73ede70" . + "b55194aa18e297038a1ef1c6f9c7dfa23339f73bcb3e8324e20d38f97ee99731" . + "40f832116cbbcb4eb0d07515cff0d0bfb6e4f7fa0b035d86204d89f2f834c97e" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "bea499394e679982a141c2e24a9fa3fd643cd206685e72606f7d9d042b0eed2b" . + "01862916a7378c7171be10e8e42a2c8fe83d2e8343306cf70b3ac95a72d2752b" . + "a1eb521358e79df561de6d6031eb4de61404155a14b4fa765e5b619dcd3a9150" . + "0d23f8479ec4a5d27a98670ea3443cd1dc25e9b8ec3fa524d3b07e5c3d4cd7ad" . + . + "5c719e8287ea131c2b74f01c57eeb5d0873f47f4549a9eb65ea2ed4de1307c9f" . + "c07d45f51b6ad52b96a4af207e4b6d1f468a2f1a9757f511b3057695f45c25c2" . + "be542d9fda2eab3fef617c26b256ee969b7c697fea5962b818867f04dc1276db" . + "f26251ad363bea9542998f3d2e4d111ee224119e3161c97e7369d87f9d1769d1" . + "a93a11f267f92084ec2b1ecf7e0199a4d7a568457b64247c65235aa60e5dd646" . + "782c64f36df6241681d62f5fcd0e452477250f05b36fbb3f78cf736bcb164a56" . + "9f3f8e317508fe1ac49b5a5cce6075a73b6faee2a604d15f0a36a74aaf812637" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "f1fa22657ee2639fe683d931d6415233622d1bf95b78e07a41d56089305ff34d" . + "d225109f9b77c078c1a7c33bb2136267ebc41df292dd2c056f2e3957ec7b2da0" . + "15d34a8885e4b37101edf7a3bae83ecb33826f6ffa6529f62da4873f20ad62ce" . + "1791ea9da6d79613c03845f3abc63a7257694d044dca194ae95f29bd4bcf29fe" . + . + "7c1a115a759c9f1b0367106411e542d6de2ae3215ce28e24db4006812f1b3b68" . + "e554a1420046e2da316c2bc2fff0ad2d0c8cbcdfe9199f276a50018e52058210" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "1d5475c98d7f2d0a72c079cd7f8487e7ef9835c6d82accd9318bb0a6e5cabe47" . + "10ba609fab32083604e151ed9f4b96895b8ff63af2f25dd68c1a9c3b05da8ca5" . + "5af34a571af3da20f2591fdedcba18831aebd3818d6baff93c156d4eb601f42c" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ca2c3ef42da39561649722a190c6d91052122513bf7c8014cca8af1696926484" . + "4be683760c571155c942134cd90ad344c8e2af45e1f34170608548ef2a3816ea" . + "336599bbe358f828d1b9f481ce9f721240300fa89e2f1ad75e46854bfb6f66e5" . + "2f318d1db168b9a26183feeba6228302f86bd26807c8a52c703735fd7f159e7c" . + . + "f641b720d747f6482f19b15a409fb04b3f4764c426cc5795f79d94c15425e927" . + "ee5039a3508fd5145e09603935e800489d46c0269fe8088b2e1be0f43ac1c6ca" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "78fe9b33cafe58c172914578844edb2fd35543ea84f346b4fc6969012eb915e3" . + "f6dc55138b928f3408924f7523b44cf90d80a2119ca4a909a79e70d2aaf5d54e" . + "4d1eedefa671a2d866f32e32b8ef6730e732de355bb58b1b8b0e0ec66eeb9665" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c4feb5601b88fd24e7d43bb0cab2eff3a152ade9b753d24b310dc7ac1b21e2bf" . + "da7c60928ed0f5ae3751e05a98bfc9f2373630953ab24755715707e2df7b2dbb" . + "5ef309fff5f463844a335350859bcf0402d31ee2bdd4fe1ddfbcda717adefc8e" . + "8d8739b518ee6132a1a8c0277face34819963d20089713b2b5ce4ad49fe7cc02" . + . + "c8bb4b8452c0c4a6c583c8d4b9746907e90d901cae6c95db3401081047ba7e55" . + "9149cf0be2738e8678e15f2cdb38434608ac0a7c2d8e70dfb0ed5e8234ded6ba" . + "244d8489f4457f39bc3857b831629b1e69291c286dd80eb711b6e2ad75653a8a" . + "0db1e663179b1ecadd333b0e873dd8daf752385484c252042bb59e9a68f8f386" . + "fd14105b47521e708f9606d138e68d9b6da9f130c4b40eb897a25a348fb53c19" . + "19456cca67afddbf06110813deaf7ceed632752ea3bcce0dd480deee802925c1" . + "58dd5028dd4f2268250a39f08ae6a55f2776c30b6c8116aabe48068d20a7fd11" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ca0f55749e3e36f93c887afb0fa28ead2ac5ca99fbe9235c41a03e7eb70f8564" . + "2bff339f4f3811c4c00c15fd37142a6adfd65e9aad96c2ad6e9bbb28021c07e9" . + "ed69c370674c9c9d291443b7ef5a891185400dd0bfe8908dd3fc96449da34d24" . + "5c2c8fbfd3109574b89d9d9a5c902f5d8cd26ac723ed210d8243dfa498b88ed6" . + . + "bc7a57d8338d6899799a541709371b54cb4f4c7f22291fa447e55ed7d93d8bfc" . + "978e227bdad6802a645b4054ac8fadec8d61c71ba11bd35008e5c63700c10ea0" . + "02ab32f24c24a4d0f408da8d5806ce9b1605191b50a8e8075328261bcde532dd" . + "5e2aeadb587dc88db24a593c90de8f30590e972f42f0d52f86f4d5b120038cc4" . + "620bd6bfa6f11c5e5a877d93440f6dfeb1cca36ee0ca0f9df0e64e7c0fe28e7e" . + "db4074493e0c70a83070962543ffbce510d3f6fbf365adea2273ab620ed0eb73" . + "0826fb9bd33ce43c400f51cb87c4936764392b50b03fb659f5fb4d8117dc34a5" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a73186b86ec489dbd888659579710a47cc260c3ec93b49f673ae77b7061b025" . + "58e6a1abc06f48070f4001f2eb267dc56d706b672802c57d73ea634f9cdd9c8d" . + "8b3726c4c1317bf4e22f1bd0147f5d5b76fbc6bfd643c5e4757b6408985a5eb7" . + "712b97d703af7f770be49c4170d48cef7fcffa5e6e04649d99a4cfcfe56f4511" . + . + "77753dd6a1a37d16f2266356a7b8193eecb8338195af371b3e19e4c58cc6f30a" . + "76056c1396ae98982227c0297a4a624169ba3e64266ffb74d3e06edef7230cce" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + . + "0805974db7c6e8e0242271eb732f710aa39f9ed15cd9e296c08246a22ae091ec" . + "12caae101b78ad49be1b95b878b8c3873310550c12d19359137531b3f291e338" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d3443c70ca7aa5547587da5bd88316abc518cd758faa4f21b63476ed904723b2" . + "dd22264480f401ea192df22e8c980ce1936e39da435b976d0054a149bbec48af" . + . + "4cb6017cd29cd5915ddf206f537731cad81f4e43bcd5b1cbae1ed4b0686f2a72" . + "073ad4aab3e7f37edc5dd7b29b1e47fb6555de5f1887e5bc8fe7aa88014852c8" . + "24bb2c7f06c9760496afdf12e7e25fa7ae8ed18b108775cd9ec79f0fda5ca6c2" . + "d3d24769a2f2f7d03c84e7685115a1f3fe4c906b23e98b68fe3f77c5754a1a20" . + "f1b6d79b2db81de9920a75ac34592c26bcb53361de960fe15e22d252abb233a1" . + "84928c58af33989b1d4c106cfdfa2e12d0624a3d3970fd2755d9a7937fa787d6" . + "ab8133c70b708c5adc548bacbead80495b06f63e7b0bb83f6bcc77b77c02e8bc" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "899f08792be53ed606cdff746b2c20d758d2bac9edc8854ab0d001e9dd4c80a0" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "aa7dd807dc2024e8786a3d25426e8d32bed2580eb1da980779dd848767ba242a" . + "2083582b998a264ed3958d242e92fd611fb07aca05758240b22c548bc6010800" . + . + "d461d7b8dbefa215e4801ffa9f11e9d5b5db3a9f4dd8a2c62d62a70ecd35a020" . + "3d0a9d8de5925599c2b95843516f95f094237f08ae7e9e8696ea929e0f7ba7d9" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "22568efc19be76d2c9513f632799cb8718820c4697b184bf577ef834fa5f9cdc" . + "768750fa4ba4e5252e900f77f0fa43edec92d9f9d7a5bd85a624808e2a9e97eb" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "4b798cd3465cd40eb662a4d48c2ce8e3aa78017a0183a80a14da1f4974cf7547" . + "cb637585f30c8ca50053feb1b471871fbc6de1f54d9ca2b1ab1652d2084e178d" . + "a890e75f0e57cbfd07520dfbc3febe662244fd0c48cdbec48f7579f63eb22610" . + "b2e51a6077199655788dcb7fb05a1fd69c2513d309d0e864addd9fa2e6f92d27" . + "e6e0c62ec0990a5487c08f12d398668b0fb3b102cb5a7a5e8257287966168566" . + . + "fb2783270ceb95b5f1d539cc69aff8f61db6f100d61e23b4491ef7bba0edfa9c" . + "e8d2ee04090581e5d459228b8baa00f92669972b1652ac3238264e45284cb127" . + "0b215f33a4782e72455c0400543392ebf159a708532ccdd5ee1861a481534eb8" . + "e44106445113c9816ebb15969d270e8cf5f0315eda5dad875a62e54f4098adf4" . + "481ae4f5856aef150341ca4770399abd822d705bb82559d6d8f6b397a53123d1" . + "24a82f7f50326c240b59cbf237a10d3876ebcfba64e8fdef2cfa2a583db6d292" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd72ce7ae2ec4e18f4fb238b9bf5383d7fab1f25fb9ec2d78639bbe5e1c61a3a" . + "01862916a7378c7171be10e8e42a2c8fe83d2e8343306cf70b3ac95a72d2752b" . + "730e0e595d7cf2883bb7a1cdfdaefc6dfcdeb2759675cdeab6c17ec85a608667" . + "4ee4611a5e8a57dc13b3efaf9c5ccfe6d4ae7e64770c63df92c02869318166bf" . + . + "4090a489ba4ea1238dda923c3a7c8ee2e2ade6310c15f7b76853f5d5c4c65eef" . + "1364a9a8382cc782a285144e0aca3545afbfae9d04fa49be6c729ad82884958a" . + "73730b2bb0aead24790c4d64a461e44f584bb50cb1f818185860a15d5b32c6fd" . + "c11ebb80aa5e811a0bfac3d222beb94bb9a8b816456b73117bedb06456d4bf3e" . + . + "481ae4f5856aef150341ca4770399abd822d705bb82559d6d8f6b397a53123d1" . + "fd4118251d1446849fc3d8cd2b4b1d2eb7e890f778719a93ba9e423328c5a61e" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b37844347037104e5bda4e2ff110c4c09e5018b88c823a9a04fa61647db9be0a" . + "6368ed9392b839fa3f31b375a414ca7b944f695bc8316fd9c17e8d03dad50b84" . + "5245e5cb91458ba2b3c63795a1fb40bda74e4cc6d4d965ad6ee2cb02d5f5ce85" . + "d9c895b387d6c8a5808a35cc2f75d1d6f585f6a9016ba89e555cb1e97f2833dc" . + . + "88260def63ff9aa8281562877881c504585e36f16492b9109be8c433be921824" . + "7e0086352a18183bf68f863a6fc719ed5a64c4a03c437ad6325213cde8b19818" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "e3ac7152a4d58e15de8d215f780aa5d52534948b196c08600cc9140da25a3310" . + "be48b45e831195735e90c7826f16ee0d66f9b4248214d4d74f2328cbf3da0555" . + "11c0d1e471fe93c6db1bc1c26b2adc38ff5e3584666690d1d7c5c85241dbfab0" . + "904517e27c833b07ab825c617539163638854072fb6b53049912798c047602a8" . + "901f069930e873a24923c2b22388b2cca4edb1e21393898421f94837d5e2562f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5fb131517dcac320eb96eeb549811188e57578ee11cd0ff371fa26eec3f89ae6" . + "735f2f341e1f6125dd058a00d7988851a8d7f72b45ce5070c2e499ae37326661" . + "aefa0d25334f30bf1e7bb0381d6aa43326e12156df3414ccf712977ba101e7f0" . + "03fb5eddc03f2a64514ede84c5580108a04ef650b8be3fd1ea18f4cb8910c74f" . + . + "d6b71f92ff213d2e887d365b7c97de1a62dc5a21e93540dbb633716efd25adfd" . + "23162572efdf1e70cc86ff9f64a280c768c3381daf16cbfdbf08ed427b76e2f6" . + "2f90e7d651a611dffe7a36d0bec7cae392162203b0d190809ba8d7a540f49024" . + "6fc42bc70817b5a86c9be6982dd12e0d31a2f005b6bb61b249b196f91cfb6901" . + "847ae1de2895e0fc57d566944cabe7e33c7c61282bb8bd26f3ceff7a5b718205" . + "16d5c4cb8cc05b8f83de6a416be4fbd18ff6e835b4c9d53baf5a39ac69b1493d" . + "4b349abcd23cf570152b1c75b656dc79a1a6e9afb700f20b2f2edcd9b54d5a9f" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9607ececcd0ae1ee99614c7bdba13327711a6f723732c95950a62b5f43b3eb1a" . + "3c6f7efda453569f0871d90a8676f2cd2e98e40489667d9cf1894f28ac7ba6c7" . + "eac349e69bb10f32058bc03913dbdfdb8cf2717b5b1703c6c7535b3c9a058748" . + "19b7e2d1100e0b5355f4ffb93b4b3a11ae22719327480ac8b70917c7e86ff6f2" . + . + "8cd3dc0070345ad193ea150cc88aa4676df02521751898ac38a569d8b1672ceb" . + "4bfe9a4630dfa0db26664bba9ad938bc2cd04f655990b500331c5a133d0d3f01" . + "643b9b72a4067674d8441d074a3ff8bc87dda4c7dc5ed39a4e54f8de29de45ea" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "cd8912a4ebddc10da0b94ae1d7c49424b0489cc27172bd3643c0471458cebfb9" . + "54411664e1ad86bdabe3519b4ff364cf33d8e780e59d217db4e96d6028a913d5" . + "6e9e52dba05c06429449ab96eee9c409188bcf04d949f072afa3aa068df3e277" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0b453890f6d107f1e21480216122ee1ee7e7ef375fdd49cfe6b372c8633886f4" . + "1572791ee2e6845a7e1beda62bd2a200b9c9c401c543ccd7e72fa4d9d7c1ae7c" . + "657220c384efe11f62ff4d093cfe4e6aeea433509dbc40cda79c050207b50e65" . + "dd4028500698213c4ed7b98313df322987692c2ce13cab811c567e82d6964745" . + . + "b1bc7bcaad97245500e2a8f95571ba3915bc3afcd24fe1a6137e5cb49fa3f3b6" . + "f9418008a7c245c1667a24e6cd343871c70dcf24b07639c7fe1156f63c725a84" . + "0c4a81e30afb8ff53cd237bba8704f62fc458d95529f8ded120c8849d123259a" . + "51263000e4c11ecc95a462a8071274751cca21c0324df397fa9bba5b3097b4b7" . + "92b6343f175f39935e5532218087e6dda05dc674105fbbcfc176e973761bf422" . + "35ffbe8aaf438b111d9dc83deae5874711ffe10427e76555997ceff46c347fbf" . + "803f3082746aa63defca2e99bce6ec5966cafcc8f23c501895ba6934e0bff851" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3c0f98274adea540ee689eef7516944da9ba7a4f987272f012f36608ee00711d" . + "29bf7250fd687c41542557245baa5a0ea36172f0f7cc8a025e4a71a02c775337" . + "15b338845389d9edde9ccbc4023687a71ebd99b8c66b258df6199c901728527e" . + "99930683ff28e71b7ea9fbb8fae58e8635c1f77d74670708be221e7b63a8bbc8" . + . + "f1dd6ae770dc4a5f4991f6ed878a5e4213e563a61a624d307786c631073e4ffc" . + "70903d1173832e6ba8c26bbeea535f7f91ef86c4495e9205e501fe5472291ed1" . + "0a1d0202761615469f2f1c5b7601e9e5444dc6a703640da217609f67f8add44b" . + "a8ca84174b2891cc52be27f68ef475d515feda8915301d0489e5e6d2c52f5680" . + "49e758250b1714c352d71cc881d0d7b719128e82896014937e20d8bb80c5590e" . + "c313bc4eb390f8d954a8aee2038067afa63dade6f98af80fca64cd860c8c5334" . + "b1f1fc2ee574a783a1063f1fbe6ce6a4d4bb90ea2b7d6a238481a55b7812485a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a06fd9748f8b16b188407fac8515ea58166a2b679fb54e4c8faac5c994633408" . + "7d06eb9835b6c6dce0e8d1fe09d1d85733eafac2d49830ffa355bb9a5235250a" . + "1a18cfd553ef3e22aff7249a7c04d2133e36a16c1e82c91b7363029ff34a2c27" . + "3f0af0573b2cf9ad2a1da90bc439d79032ebd414de1c66b79c7f30c18576a3de" . + . + "78172f9ea98b5f2e4ea1642fb342227f8e890a89f3bbfd368f1d606476c3114f" . + "a4de483fe5208fa099931a2ae2ccb2a322410c5113718127790b96ed0b15846c" . + "44db225f66a360ecd83bcfc157bcb5d0bb6bfe4b9b7e441d3b52dd998546ebd2" . + "9a450bd66fadbbf37706719bc303b55100db3f60b9983b2bb4f99e46b2fd9e6b" . + "062461fd6ee5a99c955646c38bbdd8fb8b1471c43f21574841e9028ec1fee273" . + "6c960927223b13dbf29f1c8733e5a167f3a28d2f09fb5802c3ccf075322580b5" . + "dfd15d8659c0dae63589df13f06d2f7843ef7a2d98ad39f1cec6ae70b6952c18" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "eb6df709b9f967859999d05427643f07f6ed9309cb12404a6c241e6196bd32e5" . + "eda32dd69e1a98b8108bddab5c019471f8ed3477aab78886a2e8b9d1cf16fa0d" . + "929317d9e1196da0e764503069fcee1e1d8b409665bd0be9a994bd8879ba91e8" . + "59e27cb455897e71a0fbeef3c1c9a8b18fdd708a96b2d151121e5dd7375db9ae" . + . + "ad51953113cc34c5206e04464408e24fb3b4c964154f98692dfbc9ab24af0345" . + "72f6d36afe0ff5269e1d60cc8f7c9446429bb19466d4c4f5d42b149608957152" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "3e8b56907c9bff1d49b7034c8e616b4788cb38c11d0064813e20beecf23511eb" . + "f4e7ce9e581a44a83986b6ecd28bce8bbdad6dccc93d8d7433dcfd440cc42bc5" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26e583639975385b5f7fe04b442e7ef0e7ef9ea1504acd9fbbf1cb712c6db21b" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "432fa4ef2307a0622b7eb2c695f24b6ad3faf3385a982c941032ab5377c7f081" . + "a1f49a69a0cdd7f9ff95b0230e7308d4bf598ec5d50df423bdd7abb46c648fd5" . + . + "96b64fc506a398b355de4e300e2b490e2ff2157addd93de63b8fcf70a6017974" . + "384b2a705bdeddfa5ad37e9f2572d2089df41ab42beefcc3c8f4f51a186f327a" . + "88ec9634a7a54b17a7e612b852fe8bfc60932f621b3923e5bb576d61136467fc" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "4fb924d08563213784fd03a0659a111269728f3fd793a223cfffb17e15dfbbf1" . + "de5c2cf53cc5777dde14175085c27f81ae1c07bc5c6d31c0f456c3d60154fba0" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b8227737a529a58052508785c0bf16a5dfc27ed5d882a5081fdf24999deda42c" . + "3fa9cb2825077d6a024cf1470d59b659086cba9a244d03e61c651a1ab44caabb" . + "3d143233d6f81ef279f2deb594033951ae0ff677aa182cc71e12c7c574326de3" . + "ded5826d430f21594eec755067d1e190078402f9f0bc9c62bd18c96096a877ea" . + . + "8d0d3bbf8bececc06dcc5806e66d9a922c086f4a891ecc6b2d79c63d1498f5da" . + "490e8d9c6bf101ca2d1e662b6735e270eb195e694ac3952141a624e1adeead14" . + "188e0d2c8bd98e90d47b7ab116aa5d6c0140863c90231fc25b70ff6e25338ec4" . + "bb10ac23deedee64d71db2eb12c9d0abec7008392ad35ffff806ab948fffcdc2" . + "9a3c4aa76463b02aca055207d778fb20b5f67776fee8e2830f4efc07af39a4db" . + "ff110e789e1bc6e66288a09f7833fbbf3f31594cb3ef7ecf8cd2419c96c7a9ca" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5d455837ae22ff7e97a2bd2928111276c802a8ede60c957aa0f09680d29d12cd" . + "6905cae3fe76fbff89643e3b92f8461d68a5bbbaf055aec2a1bd990a28142a3b" . + "8419f810ca25449c05b5aae172d82ead7242a41837ea93d203120e8b55e49b47" . + "734e14d139ce55f3e9197ff8717d2ae68fcd78cfbd25a36879aad52579c6d0b6" . + . + "117b17b63884f55511bd83402235a6a9cf95ebea39a4c43b535140dc79731e8b" . + "62c249c7914f524320bcc5226796006d43bd8f3455350c466e5b130138c2256c" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + "21ea415e97f213b608b0416406f3c913d1878927fc99a4ca8896efe2be271f89" . + "141411658c0384f32ce49c2d4bf9c518df99ae4529bde95c0d4bed38617b3f4c" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "15cbae5d2ebc6469d8774082d911d8c33ccb8309c78e032152e6b15c356752cc" . + "9c72708e1391a61aa9272a4bb15d3d229bbf6eb5e9ec7a99086f23288d7193e9" . + "fecd1f75f25e6352b904679ba26d5c369fed37b43844a50cc7c43d00886dedbc" . + "705e8ef374aa4e4a6a6b8eb96ce31d29d5f1584f7a93196de45eeea3a1d9b878" . + . + "4b777330471666314de3e1344ee7e01d48044016b5ad71e2e736401964a78d27" . + "77560da95e2c452dac20c767f1438a0b91cc71132aed7063b6296b372a9d73ad" . + "6996fae59714f0a0365e23409e9a5056a141c5954bed3a961bfbe8bbdbd0c611" . + "c46f92a5d3fc157df70029e24c6b8bdf27279cb878dadc3cf689e92d429ad404" . + "0cbf1b7c989a9cac35d1c9fc0ad844f6be47bf6edb5ea4b9d3194e897961f77d" . + "f7961e4470b62aa6aa8c1b293dd01e7d2140182be12913d74b797b9263491447" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "21a77a412d4d31eab2b607fc80201c0a93f50294790c51a5d47e33d66f6ab242" . + "da8839b5563c6eefe7398183ec47ff452fe475be102c453bfaeb03f6959c1ba0" . + "6b3899335003816b51f13c82d2b9c24d25873a8ee919040f7210e1a4c8634899" . + "4897709e3cd0c44ae6c549b51755116b31edb7dd71af2283ca3fc40e355df5f0" . + . + "cfc639aa4adac0345cf58966e057857804fa4ed440d32dddd3db55bc4ab6b118" . + "e07316f69244f340998d89e7036463ec637538f4e1d7eb8d881b715b8dda6e34" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "4e7397722118d827d0f132f5fc415896efa1591397865c83fd3909af9cd9f19f" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "956333481797dea3be7e388bcc6ecc41a0927c919b37617f00edd4a20ff4dade" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "64cfeef7a84129f476ff3b0c14fb37b4d3216735b4159ab7b4d18c5f27611ff1" . + "a309c65cd9e9e3324bf229cdffcaf86338a552c392fb8871927e63ae6f3de32a" . + . + "35c3bb9b5333477fd5521487df3f6c465e04bb704ef6c6070efb79fc88950bc1" . + "657c3a15a8e1e4abac8b67b605bc0f8c7f49ed29c524e9ee3348178648946488" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "ac235391bf878ed012c8ed241faf68dc016e0ea83b410351bf9510106ef39a32" . + "35c3bb9b5333477fd5521487df3f6c465e04bb704ef6c6070efb79fc88950bc1" . + "061cebec983050b9a5e8b89f1cb1c1b6cd60c25eaae7f5a4e0826615309093f7" . + "efa2ddfcef1603906a4a4a345c4df5f02292619dfe10145d8cba75732efe6d23" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8d854968aad696991fa62d445e1ec690f4881800e00e6061d626e606830d59c2" . + "43859937a785fabc965276b4fc8c7e715470201cd62c51ff55f7519a54cc6885" . + "ed90717738a5bc3dc17554f5a4b0c72ef102fb3082db53b63f0078ab62221816" . + "9eb0fc6be7abb74e6039491064ac3266689383762a4eaea0e06fcb328cd9cb74" . + . + "6a45d05433a2472462201b4a5c85b5d44817640adcb1eb9a31fc118f55ed396a" . + "c642313ecc58fab504a0a5caa7c96e56ed319037d1ff3e24f33c15dcb9767a1f" . + "2f202d1a93b3a1c21417b7b4e9e6c00fc330985ef14070ad7f5433e1dc4ac5c2" . + "19f5acddfb274fdaa5e2b00364054349b1e0d96a308924f5e53101b7e8c5b78e" . + "036087ea5412358f0d756b20ee303d9e84f96698413e73486a1108d29b4ce37f" . + "1f17b1e56ce9f02f410eae466a7ff58a92b2dbf5f749c47a668071a215b19976" . + "c308dd1bc83b5f3bab92485e0f64055caf6ad581a37f183cce93d002671741f3" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "832546e680c63a0d344f7fd1c84c68d9acbcb095aef3f2d8944b02f493e29c79" . + "77b9c4da073ea5a969ec15addfb7fe131553c5823e44de973cd9da331a0be31d" . + "8a41d49b47937a7786d9ac24cc32bee4b8211457d87d5cebb5a44637e9acdbc3" . + "834da6fae84411afa5316fe281e3803b89919c47e5c3890edf617cceb857c10c" . + . + "95f950cb63580aff1e1d87757ba22491c14322c61c5191a6dc9fd0a2ae0d143d" . + "849f48adceec07956b06bb83c80affe4caaf7f6745b4e5d6f061aa09a2a20343" . + "5edec4f05188e6f28cc682c0da743f787392640555a280d0dd4131b52b608681" . + "a3467c754d364c69d821c19779beffc7009f8828a3e318d259e99c3f2eab2962" . + "80a182587700a211968e7460abb717499ac3558c497e4bcfe00c3c8659cceca3" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c568a29d3638541323e7af1def87ee559b14a9898617095423ab94ed4364f761" . + "195656cf5fc6d8110198485fba1dfe27edf5dab33b4e2b9003811e3755d2e3c9" . + "0edc8cc19747ffbb65a9db08fa6b569b45860d67fc953a12b2be1ab28b186152" . + "ef6eb55ab1939c30b61b35927e1f5cdb75379272a301689afebe4518e993f60c" . + . + "3443043acc73c609ed746bc9c622f1dcb92fb30c0602ad937a8746aa84e50c7f" . + "868bb582dd023d925665e8478a62f90652a5ac0de0607209113b1a3d841fd2ff" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + "f67dc23393b3a1fc24576508734a08a3ce23a022732d53d6c3fb012ec0cfb822" . + "659d9465e02796269cde54ada530d2092ed06c1ce519431df1f0f46d905729a6" . + "0581f11e831a1ecea5b624816ac6336064d0725dff29db88c6b582e9b3f0a1da" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65027b27a882800187a5aaf8f1f6e9ae1ba2b913aec0113b336097472af11daa" . + "3061206595ed107f28802e9557012c776a6c5b1ff29ec07a824e8fd7d57993e1" . + "5bfc83e613e48a9b202739bb4d28b4d1005aac964b0d218b42b11a9375d539b6" . + "30cd33e607f2e5459096f4ff521a595fb7576339519a00ca41ca92192467c658" . + . + "2c9600aa5c868a39461a83fe0a2f4f3aaf5315412e06f458d7bfe9db0ef178df" . + "42d479d30217ca9ec7079339b31e7914d1a6bb761a47e0511992335594cf16e5" . + "890bef6277e989961212b6ae69d76040fd3c5bb314d5dabf56f8ea2356cd8bbb" . + "995208541b6f1675b2e6e876764a2ff8133babe10c7e6b4213aa833c17d00aff" . + "2c9600aa5c868a39461a83fe0a2f4f3aaf5315412e06f458d7bfe9db0ef178df" . + "4c4c2eca8cb60cc6a10493d6e909387d0a77cad35b0679be267ece725c081676" . + "a165430fbf389a662ddd16eb93a754ac131511d856f51baafce2a8da9fb1743e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "bdfc17a8ddff67a7508348c203b8d9738eba91248b651a363725b097c5a3a026" . + "a875f4411f038991ceac5f09c895268d17e61d340fd3f23ddd28d41ed9491219" . + "66f6181badb56b220024f0a2713fbcc4e23ba6217c2962c9125b7715fbbbfaa3" . + "d50938dda023de34cdb95f433beaaa6d2a9608dcc96b6484aad5c7c28a6fc5b3" . + . + "6376352367366b5a48a81ad39e47b9f174ee76b606ecd470ec0106ea53a94a7b" . + "693f96cc3b80e6cfe626381d6131227e70c37118044ad41d4b614978a6afc34c" . + "e03fcdbd1bb0d88259693d516389bb24a16d104f654f7cbea22ba997d3d9def8" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + "1d58d5bddf32fab0035cf7d9cf32809a956983c493097a023e35711dd972cf2c" . + "ee0d7da254fcf51d8b9e7324f4e132e1b9b58f5a93acee76dc6813c25a9eb79f" . + "b1b19ba5fc34d06c453ee206ce844d3aac92f9131792dd14c4dd1ba0095c34c2" . + "10a53c5c8e6b1702cc0db87f882a6e22bcb4b6349322315d8f7e76f74b299ad2" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0fdcbe50e259fc9a6aa9f9cf190c5654a3d92d3a072ae94e27e693afca4876f7" . + "b7c0dfda890ed1d2a8c5a78191e945b3086675938369458836e4e68362eb6ec8" . + "22b1f6f3d35121490d4860ec6ee2cd91881b0f15e3de6461ffb103d3af969b63" . + "759eee244579843e9b909b5378e86b4d591fbfae34f2ea074b33e39e4d2fc583" . + . + "515d963ce1a310935f498e5ab52f5afb6d8275902ca7d594f0297891d8e6783b" . + "43ffc6f2f3f78399ad306a728c63dde747ed1ced6d8c3d0c9bc3f878a8252ef6" . + "3061206595ed107f28802e9557012c776a6c5b1ff29ec07a824e8fd7d57993e1" . + "4aa9538cbdac1e73b3204b55267f844e61b10712888162c43ab2e51c8ed38648" . + . + "050e9dbf31b19806417f5cd3cebfdd6bdb89ccc26d23e085bf379d721e9a9b5d" . + "b01b6d1c057b423e20e7da780899068dbfbbe38ceee847d845e208d971f26dfd" . + "38aced240343f4d84d19f02f694938384f4d3ced8569ae726cea1424bee976d5" . + "d918e21e6845359780b08a47926dff2cd90a8b0622178681b9886e1f6d4c342b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7bff17e7d3a33dd063218e11b7ae43d717a1572b97d86e5aa032f0cbec8f9f75" . + "baa85c87f746b25cdd35cdc4d36ed561b371264010d2ff7cda818db6a2198ad4" . + "dc2ae0be8835cd368e76851aa83969fd4ee623c8c0e53ebc6a79678613562307" . + "0c1e723dcedae72c4768d07e7a1eaacef7a8af77096e151f0824f648557802c4" . + . + "12f14b7b26392a4e9a3266b3075a1da0269f2cabb28638e65493ddc779c1bad5" . + "6d6bcb24dc737c821801c1a2a27fb017de42848f2092c03b3cea9277e5014ffc" . + "d19e0ee6ce9dea5e74104063987632b179b47d1979b34e7aef5824536eb1f294" . + "5b7bec0a7de50082e677c6839b7deaf90bd26eff30a3947bfff1cdd912e9aaa8" . + "bfdf129f795aad4d33edae63cd2466368d5cb2a6df1699dc2f2898514bec707f" . + "cf5c6d71059434f53cb3aa4c2fc5dcacad0fe5dd87c83ed85153c88952f8fcfd" . + "5c536251fe3346f7d39ff153c968f8a2cc57d76a7b59fc1bcd8ef968e028e03f" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a5ea2bb4a366abaa68feaaae3d064a0df29b06a15884bdc3393581ec2dea110e" . + "20660a8e764922c1113dfdf50bb7edc7e5eb39b4e87f56dc44d9c78b3fb82483" . + "cab5fff7746ba7e4ed22568c9c3810ccb19c2e846b7b1ec51508c05273ac0536" . + "02b4edd9a4abf4a92b28f1940ef85d1af2d39db9128df2c188976f7ccf6d0688" . + . + "bfcf1ef4e988e6ba4dcc75304b56e9171bb16f5fcca31569c916376ebc6738ed" . + "d47239ca380c1b75b5bdc3cf437e5cea1384dd0ea68d97d20407ef1911be8200" . + "7223e171bc393a27019f00209e80c4022528d023e339b337645c8cffe564fcca" . + "5f737d75bd88b8c40b0ce6204dcee752314cb9bad7385d651c40f66f5361c0a4" . + "78d9f6e559a1d17f694e9f404d7931e9fadb78c58b056d16997bec60207c3436" . + "e57236f6782b442b4c3efd2f581a92bdff5b2c5b8991d5fa820847c0e7069f60" . + "13dba608d47d7c3bff8b82631741d1cc0ce7e361ee7ecadaf35754dba87d17ee" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f87a34e98460b0ff01b90522d9585f48a4e478fcb356e2b976d45a465edeca99" . + "258c967f52bf894aedd8e28e0ce9ba3cc3cf5eb89a9119d5192eb218c10e8c36" . + "c6406927fe916f339fc84770894f4486e2f8b1ec2d867cdf0c92c86d455223eb" . + "18e8170d5014e6f9720a516e170aca443a7eb20f85383d200b55f896a2e47ba8" . + . + "66c2d82b61c7bb5b01fe11c137460d487d37f334fdf1e8a4dd33d0b57b77cbf7" . + "8a153bcf4c8b31597a0062ae0271bf417ab4b237f9af89f941d4235a4242bf44" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "80fb005aae3a9c0e9a39d6d2aee9b7be155a8fd6e0ee206f4b833bc01da5899e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a14d2be86310df7f35a469de236af8ab370e08bd04b40e274441606816762112" . + "4cf6b5480f3a772a9d68682d10a367f1d5aa797ecbf0d3cc1df210585c1907c8" . + "cf80ee4b9bce3864b54af533536d6fb17673017b22bed05aef964d54aee36854" . + "1ebb5ae03479d9733e026f42209ce7c68eb4d5bd85fb83d7aa93f39147566390" . + . + "289ebff16d6cb69af6265838632240bb3d66912491040a85ab1d3d3e3e56269f" . + "6f1b1f27ab05fb0a9876e42f7d3e76aaf82fcf2148dbf22139833d041722f1ac" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "1d6c36bd21c34c9e22c018d723b71c27ef352c44ac3e8908de03349b66ebdf3b" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f54a39dcd6f4f5990e2789e184a37154cc199d881c60c96ee6634befc49a8869" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + "e0f5c0066da24b5e0a04db4a13deeefa331b9ff85019eae815fbf707a29fa9ee" . + "06cd91192e351332fd436cf9174884c15bbbfa5612a179bd912c6d5d40f35a2a" . + . + "95ba24c1e0bb545255a6d8010ae34536d03063b5600c1b2b0ca5194e5e032f22" . + "587a9b49ec5664791e2dd10865654d1f7bab7b167ea057693088fcb0d242cafb" . + "0b431da068680bd412fd8eecee7067d10ef529def76937acaa3216f947cbb227" . + "51ab61ea69ae598238bff6a26d853b846036b9cd1f284b9faf39f2e970b92785" . + "e18c50c8631a6b5e2ff035f61f33210e9a2f83ddc8900f2e114bf6e000824c46" . + "84e29a14123aa1fc5ec44cb32e2358d31e89e025ae47dfe821e338cfa1ac5797" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e1f3e96eafe21b59e0f83979810e81c41ad3b399cca8fdfaa2ad79160dd5e9e" . + "4e2075c2232704f7c866e4c05a3e0caa9304bab4b39bae371f197e01a90e78b7" . + "bd07f06410cfc67aba2c0dba30ad6e023cd406ba02d74ce92c1c713132133d14" . + "72fe88126d2a147b3cfb4f9d0a8ed9c3b8c82758f071a2e73bfc51f191b1bdef" . + . + "91a56efa92359a183ccc110f478ca92f5f27a42a2451e0086d920ee1c6f95ee8" . + "e01b6ea84f66cc4b7a299df20c170dd45a143361d4c03b8983b2f51bd56d9117" . + "4d71a227a27bbee34c174fb418356edb690b58f2a5f1a801379a258701cfc4fa" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "31763cff70c576d3a51c83f3a991e4e290dfe08aafee52d545c8062024f6a5aa" . + "08eeb2e899c8fdcacf6423dbbd5bcd2710bcd8c53843a70f36e434b2c12dee73" . + "6b2118ba2a5ce720c94448d788c3ffde6f3b52f52f4e7cd47aef8740a0a55c4a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2343a030d8b0e23666e7cc9a61068974101744b5c9257ab50f7c2105ebe4d57a" . + "fb1870184a75234be64103f20230702b34050413a0a3d44408966ddb31ad9e98" . + "2dd4501f65db214c3c92894e28cb12de9e216655a3827a1799ae80e7d626e092" . + "bb81db904a8c050eb524d5a6afe39d44c820aceb850d00f4a8b10cb1da407028" . + . + "ecc1b9fc45182814194ac7af4de73d63a1d8a73fe058b8ea2f7e7e5d2f59c06b" . + "1e85de555e2c5fa7007d0ac8ab957aeadd661ca08702a73bfa1d2ca9b2f1ab8d" . + "ac41f1d6870896e39c4c9c2580defc92c8a259ba598fe077a1e0971924cc5df3" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "aaeef613a21909091f5c0ad5988d3f006c7ad835ed0d9f438a8fd1667da63731" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1bf8353bd06cae5a51577d6ad33000e75b95b2eb37d02b0458cc893dcdb07a28" . + "aa17a237a8f5171a78569d8deb130258cf74a778b128e279aebf14c319da2f84" . + "fdb95a9d5a6da10b80f346836e7c132a0f01549ab4f982147a34cb7590657b0e" . + "01aaf4732d6b82ad926fbe3c1b96862d69eaf0729e2c7606be5f708dbfba991c" . + . + "8ad4b42f4f306e8e099ea62011e3079d2b0da69504111a27f873e671a0504364" . + "d3284e24bef8ddac6f54dbea5ca19d462266c552e16c00994cbefa085d669222" . + "403f2100b5bdcc375d641e10c6375babcff4a6df6d556f6558a1dc3bad5f5973" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + . + "8c64d775a32d3f6ac8ac0078fa5a9f232f9eaa4bdd95c5dfb6da4e7d90ec3d59" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4a376dc7aca56139306382a8a1753d4e34af970f790da83b8833c2b77962115a" . + "fd4cc8799e987c7de57c2d885586631a8b3eee50aca1f57f4dbdcad7adf1cd34" . + "219240f0d03d75e7b101658652763a785c0211eda6f79762f411d0159b4cb2ce" . + "35e68976b029f4fc740b97dcb2204c48ea83f7665e97c6782cbc905d0348307b" . + . + "3f7dd8328e370ed0915f76a4ee72f3209d0a5ef809451c51e6ec33f7884d33a2" . + "9185d7a57055a69fc90fbff86c0c937ac27dc4d821ada0f3423b17d5be8f90f5" . + "881043800dede38e3b0a881de317a86909f2e74f1264597477d7488740e0261c" . + "361c9ef96f95a473d5bcc00d0bfbd4ddcfa11f8dda4f5183d0137433a2da83b1" . + "739e1ace66805e10898dfa6535409b1189c759a0338fee8c7fbaa66db2b155b1" . + "eed352c3d1c94a01823506af6863497bc2cc76000d4c5958bff8f73c3ac33eb7" . + "f1c0d739ee4b35e46789cb5f280b3d2b43abc56f867a61c828628b4fda47e7b2" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "72c3330a3dd6382af08f0170f4bc7fb5ce96c9bdb83d263723b75fba021216b8" . + "7344f26bbfe64996b78476191e6a3bbd5ceeda5c4dc8f7092d84edc6b052ecf7" . + "4eaefe3b7858e1278c172f48a2b90bba1dc82020dce74172c77f1d7c64a06d71" . + "cfb7affe4c793cd48322c262f4d6c702ad64a310b09dfbd5a50ad5c1ed23e102" . + . + "d53eaf4ce0a215855f4f4d9e48ff7f3ec376e0af2f82cf5f9db5d812870973d9" . + "b5e887eab8046485bb6ebb726acd6bf5c4058d2edefa453643a0c426649c4c38" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "f3a9c9deb156b209eb7c7e137ee96d75e322cc69090dd2a36e40459235444b1b" . + "325786d1e02543e128759095c9ebb531f990526b01b367a3a4bb14f00d14cd48" . + "f498f9bc8179f37cb6858078602e08ac457ec36e6856445531b158924ad8d59d" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e8171a448c002376e4ad261f34ed1af6124d6ec430e823764fdaa397befe0684" . + "00880386ae7718a31e23e4b7a22672cf1346414416b2819892157d65a75ee3e9" . + "ac1e5f50bda879e164b8f7d11559cff9be4d4007c0c03c9daa8652104520f198" . + "6cf46618745d7de0bfa60eb7ee5a62a75da804f5b8f0ea73b632ae4de4b672e2" . + . + "be27c76ba22591b576908bfadd028ec2a2866e6eaa30e04b3d84827554433c0b" . + "218df5515a9d889d7ffb96ca7b5f832582dd750630e84cca5537c946d7013d92" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "a33b42a342b6a43d32d59c90da0a49cdc68a27ede6f5d473572357bfccd602fe" . + "3d289a33c5793bcc342472c8b77f0e99e4622d396f8da9a99a645244f3832ed7" . + "1a8d65ef688cda533fff0ba8a3b09907b468c2a603703e8b416e30522efdbb1e" . + "4362f7842bbf8c1eaa50ccded0df1202ca39e2f254121ea95f6b8e5551829895" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "01fc74616a9e7fb30e80932053647d4acd41174d154e3bb9692e74e494ccaf54" . + "1c0467817d839239286a9500898e62c6700e2c424d3b936210f3c08b941e3864" . + "9640bc8009531a8164dcde168af43b397ac35bf53a3b166e7e75331e2a00d773" . + "f95c276294ff4101f37fbbbc152021132b3bb2f1f62f6493d13a0bda3fac6503" . + . + "b438dda51e8fbe080605290e62094614c68b9e84b2a0a9fe0b90b695eaddb3cd" . + "de6fe8a6ad1b31e433f0f7033c8c7176ffe379f791784cc5680afc3bc275e541" . + "33a606a6de394124e24fd1df21b58c90ca84921295edd24895c8520e37537741" . + "b953c7ba4621566d05e7559aea5b01e37bf4fba7051c04f4ed9c99fea832f831" . + "fa3da9368d586669152c25af33f4bb3897f807dacf470a8c18c4b0d4daa35d48" . + "6e357ee1802e83182fe6764fa76ef6b6a0d3c7acaf19138625cd51904a7a76c8" . + "01d31839d34a22ea04cc49e6a0a16d4e1dd990ec68e76abad19cd812e63070f4" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c9c726090ad08a8f4be3ef0746362285d12341351ed9793e885f28a3a45d188a" . + "da5f2e18239ddb2cf90915a84088091932041dbfbb593467d8cae85fbe0ce655" . + "8e0a13c79dd5c2733de6afb492ff99e2b5134aa61c40c31de4933816ba4bcd16" . + "c70273db8ae778e8b75d523ece3e244b2c232d7bddcfd82dded6356f9ccd43fd" . + . + "b70b3435d59d7f721152e80d89ddaf0c26d120565461018481aec0f3fce1d833" . + "97b0bcaf209118e98fa498add554fcb29390d3f821f3d1ec9264beed09a3b6b8" . + "c6824509e14c1cd5f42e0c3c3211e424961509b1d239aa71980755ea6bd48143" . + "510de2643ed4c29dffa850e8da158a9f347e4a9dbf0d1c7127796a82b510edd5" . + "c45ab4f9b5b1797a4fd4a74b720aff73a96c259aeb4a66a77394849f2b15564a" . + "36fe9343c7237952f75c8360d817683593a2b247648c8e6f37c9c2651b7c07c5" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9520dae0dc9e9ec6deadecbe251cbbf5c8ff88ee53f4f4c2e678e0b000b16476" . + "bb10ac23deedee64d71db2eb12c9d0abec7008392ad35ffff806ab948fffcdc2" . + "3512b8c3ba7ae51d5401c85913a0ee16baa745f8502f7fa72d599a2409afd7c8" . + "e13670cd56b133ff8846d4bb06c1b27ba2848acbd7aaefda1f40c9bbedf61d22" . + . + "2f09a16713a02f1dd35988711088827dffbe11fb9493e2041b5eb74d4215aeec" . + "f206f4ff45911130b59e670a8f74cc0c75eaa7833de6669ef04ea8264c82d070" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + "30f95b068683552aa6f81cf9f7b4bcd6dbbb9d4d5af982421db5e775b1f27455" . + "21ef321adb3953bf318404a6ece99c23a7ab23a5b88d0169e0cbe9f51a3690cb" . + "81cedde620b645470163a85f6fcdac4979742f43b4846b69b6e3ab46d5970854" . + "79071115d5984bfa0ed72c32a7ddad2d45a7b883eb7ea4c9c65443dc9a61c922" . + "79071115d5984bfa0ed72c32a7ddad2d45a7b883eb7ea4c9c65443dc9a61c922" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "30071f8ee7a38c55512878c502b2a0cf5abe0ebf9cf7bcf53e28af22278998cd" . + "28662a47cad1fccc86bddfcc92128112084738e91b82d0a276ab0c9a8cdb530c" . + "d798e7e015a86f202abe2bc44c9aa8ac3aa0305d1959eab79058e7451bbcb4d6" . + "f6a05df414e8fc1d1fd0eab66856710f151ad19c99d65af4928ff4e00b50dca2" . + . + "4c3fdbc846bac8119d32adff96173742608db36e05fbb376d11a80b954b1d3b0" . + "2a9c4d258afcd59594c74dd24c62414d758099e87cb7ae046fda4653d54ca022" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "3c2c3138ebe4ed7f02a347d8fcc8afcbc14720ca45925b49fcff6616b5f84b83" . + "f948bb2d7ba2e9cf100e21b50185717d71b631f3bd9613d374bae954392eea67" . + "66f40f94e0d32bb583473cc47529b29fcba6a9b69383df0780fa5da69913bf72" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c7a89938e4fe109793e5d537963e4dad6d1db5a559962ca8640b1d8c83f2700c" . + "d0d5c414acec77c52edc55fd62f0d5413e664d39513b774e54cc1c610b6a6d22" . + "0fbd390a40330c37088a85d658a29e00be0543fa8f705532e0bac72b1f9f28e1" . + "b36fb69b0d023884bc9cb39a8b2ba9a54a0477e1217c7d09d0f80dc11e5f50ed" . + . + "e59eac856f14f3fbb7a1ad13748904c7eeaff090dd01a874881565a22416b2eb" . + "a6cbd61f4bf39776d1b2656cfed9363393e8a6180c8e2d8c39c9ab58e55d3e2d" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + "6607d2affc34101bf25fdde70860d7f1e9dd5f7bc4f3ffd6b50d3734dbb87507" . + "3373f3921692baeacd3b9fd71974797c6f95e37d0ad4f378518bf07954903306" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "69e9083892c5e4a215305d0fac73c4f19a29ae2bc38527e3cf33057366e9650a" . + "0273cb401b03db8a5d0fd55e51ecbc862a374163ceceba93c624a9e222bb903e" . + "14be3991c7e464c001acb58edb307980e695f1efd6675ab0ee072cab4df4970d" . + "610f0012483d865141c44597bf858f2da0415819fd13d248238beb43b57a0c2c" . + . + "19b25827e4e84cfe562021fffbfb141e5b703a5a9e9aafba393bc5427885e26a" . + "acc95185972870f16b03a4c7da18360d58f8245d963456f7402378b91ad60a2e" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "65f515cc210ddded79bbf98630848382b7c6503d82bdf280bdf75991c6af497e" . + "4e303b19c834c4259707967c43e8cd83b3807f9e5380a5cb524678d828cf2d78" . + "ada9a487b01e2df231dbc0477d640e8ead95399ec82aada781fc3c1288ce86de" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ed30e7d815dcdfd8a5552aa9fc4680e2c6dde722ebf04c565392174a31a1156c" . + "47a9b8b16df6573b9edfd8d0a9fc1d464f3f41f2a1169683e983ad20fa88cf04" . + "7de549aecaf73e9691950eb9b886b4a42e931731ef06d614cad0a584b357e430" . + "bec5f78bc57b5d496890cc0cedea96c98c72002729e8bdae1b0f1ed96ed1df30" . + . + "1ce730056601cdeb7f8dd5978248518d49467757017e678f55b2ec763e756f1b" . + "948f6cfdaa865fb36dcc0ec1a515aa1a8b0e82bc41dab2d1e51bd6bda2a8038f" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "e15adfd24ba5aaa1ded8f3d006de6094fd23e6f0364918a97c2fdb4d80ead691" . + "ca71d3dd281bc532294637a4ef084189ef96fd49aeb3a514ac259a0a3d077efc" . + "e802a26c576149e2cf97a877c7a696381071385998e64603a43bd6535265e742" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b5a7128dc803c7678fe18f4094a7f8694f078e7966633f10e565b185a0d9e003" . + "ddb858f15fa4c25be6c56fba18aeb7f0c3db7fd048eebc60949127d6a0fb1a51" . + "ee55a748a57a3a2643969c0ccb0b13e865ee3d3ce9532c02537218da6014efe5" . + "1aee809917bd9a3878f884109b79bcbf6de0e3929a8e9e801070912ffae5fd11" . + . + "af5945b66dd5412fe2a5c7f0f8df6186e905b2e4999906ee4d2769128e85ea4f" . + "cbd1e77592da12f2149dd424ff54a0f3a362904bc05a7cbb0be3c68ed4242332" . + "28f0712e0467e7de5435c0cd3a479655bd07319fb9e997ad45b00cacbd1fcc40" . + "50cdaf0a0edeb1e0bb089fdf151c7e70085aaf18dc1c29de4096b19c56c300c5" . + "fad74dd8b88fd5d4a05784d4774d1a79ff3b8b8ad5509ca077e842d176a79365" . + "b84a2763cb4fcfc0c4fd2f591bd78d3987a3f43410d0d58183ba452f9231e49b" . + "ce942f8b97d64919cf3cf0377db44386ecf6ef7d840498d215a1d3da0ecdf997" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ea6e4e43c7b0aa60198ee8b832cc6809f8c35e6f6292697985a11fe519c57265" . + "b7c5d54c10ae496a85ccf212dc1706a55dfcc7ad01c5358ba28fb2357cb99ad9" . + "521ff313d87c678469793989a0cdd9ef6ea2769168b2fc619c4a2384e8aa869c" . + "506d7a3072b0d451083fbf4056f9881c56611365ae87136bb0cf6652a301f36f" . + . + "90ae86d80738fbf32124f037f1296a23f52a14e567b762fae2c741a9a945e069" . + "98661ad6c0956f7705291ae26df390cc2f4d3a2162bdd68acf7e21ab9f527e82" . + "c21bf0e0ce8d945dcd785424ad87b322d9b9aef8c0181bc95983b008efe27766" . + "59b172f7ef3312bbc17c89a19107bd69a7df3df162a605e0d4fdadd99b2cd8b6" . + "730e1c2c9ae5134cdccf1d28e4d2771b99f8f70d1449783ee7d506dc10c7cb8e" . + "054e94e4689a9a2684c290233e314e21d7ba67bf4c601c128d9626a3bb557913" . + "b754fa140a453993a6f2fee03d6e42dce08546396aac2650c36f6831d3c61918" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee1c0abc535027cf815b5b5fd876f42d78f43aee99259f7b989c6f1fb1407186" . + "1196d780355c7f9a05c251e0d9149c4d572862c46a7a7ffadeb13d18e70c1d32" . + "ca76db044111bb54870da39e82db52f6fe177bed357008b772aacef8f9d91a8b" . + "3f8128b594d67c68937727f23e6798b011781419c53d2865288b079f4296056f" . + . + "c4678204dabe8584d81c0f15334f6a7edb4f4fab84b1697e8116030cf634fdb0" . + "671106af6f567013dc8286784e0ccb80d3224cc9254090ed1c2ce768427c46d0" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "0d54bc3818d44994b97d7fc8040d3036f48ff6b036712dd200afd4d474a2cea4" . + . + "30ce1d5a6c33d4ecbf4ac7ce87f505b9a88f054533be77e53991127f680b773e" . + "c3afa16890c4a6a3291a6cd066089e0f292137281cf66caa339f2237c8096f41" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9daf94cdb2558b60da692dc1a8a914d13ebb94400c2fc902a3dee36e09b45622" . + "948a020ebae922cb61e65c157bf9b0a35b3c206858da653913970190f8f12edc" . + "1f8d017487b665c1694d79689431231b9eb7de371fec68790ad8b2c72f7ed3bc" . + "49a4c09ce3b208424fdd9f4733f869df42d28e356d92e5fc5a0beaeb19491e61" . + . + "def472bd567b7f64f3a54f997676a80c12d11566c2ce0dcede95acae64c6f090" . + "065a8e2d72c5efe0b78c70d61bb3b31e71018bf0a4b342b1b445ab448763356f" . + "e8c4f586ac28e93f3b4f7edcd2c98b41859bad919bc6ab1be36b0a439d00703f" . + "32a8b94c3334801141e96149aabe9345c035b285da8852822e227bc083813493" . + "9b4378b62fdf2f3594737c72b600f10edd4f1826ae1254ab4120c1923e39e62b" . + "43181b3ba3bd5823acdf36ed96948339a6e4d5d967912e9f3444a0009a6a33bd" . + "d4728a4bf28e17156a05243359236bfc916eeb545fbc26581238ac9a05ff0eb5" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "224ece7835c9b03c0c140da3858c320afbbe1f3517a5f2123fb21b93551c96fa" . + "9bfeecac058950ee62dc39430eada7a5c10c0390c9adea6e86b5fcd199601e5a" . + "c0f17682bfa793ea643e30e15582d99473badd6b5338ec6193460470341363a8" . + "8f43683d3c666a8273ef633e3bcd30e016f01d0d9ac4f35a9c327cf7e09e0669" . + . + "da31b7f95a5e67087f2c419564e5e2a3811419acc58389e46a68d8db7038e110" . + "08f547d85ffe30ac3caf9ed073ea7f2d6bbbf69ed781b09d4850ef37326ed729" . + "9d4ee0961be2da7d6b3f7b3040a477d50ac73378711932257d80da2a6b0c98da" . + "6a2fa202cb0675843912cd7a41a8d8451d2cd22c94e2b6c902a580004d70c4c8" . + "59727db61252fd88aa6b35afeb857fb420541a600270065f044c0ded17b272f7" . + "c91331041e0128c91d39e926768f5e2a4aa00319e63e9c603c2f89515f7e8713" . + "0826fb9bd33ce43c400f51cb87c4936764392b50b03fb659f5fb4d8117dc34a5" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5106e51ea6111e8a9ce5c9b91ce56c6df6145e0b7535193c97cfa0af6a9af4bd" . + "51128a38de65c5a3181a2dff4dc8649201767ae1bffac2f1c52b842bebf9ffab" . + "802d219dded923d459f9f128b54da0ab4d379d7c0a9c0c14f8de16e802cf980f" . + "46634ed58ddc9534f1d0e37908e6f96fcc97255a7cdf96140d153a15e1bdbdc8" . + . + "4bca05ba1ed1364940704cde659a908fecdd9378ea0337454e536691dc12d627" . + "2cc0036b8c261fc224f1bc9d3016583cbc4d3170fb213fcd72c8699b287f899e" . + "cd99cea8b7d7ccaeb7f60872418fa42972f0459314adebf2645b22a1d306b087" . + "feb405f2e071491302ed6082622d36b65024259b61686f66d27cb0f6d8ebfb30" . + "e9e00a26441b4090070f5303a8e3f50bea1203da105ce7d85f5a5eb912190041" . + "92007d4246fb73153f9af00c272f2aa5841b382745d514836dbdff013d44565f" . + "0826fb9bd33ce43c400f51cb87c4936764392b50b03fb659f5fb4d8117dc34a5" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c610942934e45f207942c47d534990173a7cdeaea173aa2b565da35687751a49" . + "62df394a095ba5cfbc0689b1134b11008f96d0f754429724e1c50a3a76b266e9" . + "dc3c44894f41ecd2c7a0d138bc152df3a76418701dc28762a78ed37a626a06cb" . + "b66b9a5820a4c72ebf8ff5c89cfad91468c2b729895d439494c18c4c869647e6" . + . + "408f6040377b24c54e18be9aea75334b8465f89d76115fbc9c4a7daa9cd416d4" . + "ab4657748f2f4b9334f0ec93b6b1c9fa809a5cdc37aaa9c505f1ad53bdb86e6a" . + "051a7a6db85621a1d5011d536595c39b8c9d54ba249b8423fe846020326db11e" . + "caca1c14c72cf039936f51758b0fdd6c03fdc0d3da4ad5827e8efe445272b10e" . + "179147ad9c1b387d2cdff5b3921a559a7f1c75ca20258aa73e9499b2aaf07083" . + "d5cbd8676135663acff5ba24e4708a8645fad913e091aff46ea09edbdc69bc6d" . + "9a638d930e8e64ec91311c812361c4a2a313a44a81bbeace36606af776a2a8da" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ee39c8a338f4f0963d4e23ff5996d514b511761a5d56481a16bd117ab7fc58dc" . + "84df77b3dbdff684b5488be2aecb6900c81ac3ee2b4065fefce389a47645ea13" . + "5cb194a43c95413f3e7bda08d8b87ff72e5e59f91541f57c289d6bfbbf479fa4" . + "68ae41a8c56610562f0686c939b8bcbda81f15a338845e13425ad16c7f465b8a" . + . + "61cf2d8a2a18a6400ec0ebc467d0d783938a6c5711122f98aaba0e46bbdae380" . + "05fa5653de948ce71224e2e9fca9837e12bc2ff8543ac144c44b3ef0c29c3c44" . + "beff4063c0a01abb240de64bc58b7f2af7a3f63c467f4a5d5a866d2511c59b23" . + "4380e54b573c56d5ddc9237cdfcefaaebfd21262e625d6d5762e047d9a7d7a7f" . + "736e170470469eb98f69983f0022a7f5f5208f9f97e03fbd89b600a783030f51" . + "89b02d5a1b7347020a91fac088abba1fc237c6ca7280159f72f551ca2db8d380" . + "93dda85a343159be34736fdb83e7c97ee95187a87015fc557ed9876fdac13f3b" . + "02113f4a5aad3f8869dfb47c582d985ccba2c7b548d8c8e51a12df05a0db6036" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3b98dd929421fe2769fa578aef95c832d583370191631fb7d2ce4346a86383e2" . + "d99b1c097281b63bc687678fc0830e32cab32fd131bc88a0e165680097e29376" . + "5456bbf5855f9a2ae0d1cbee2a947f754de55b75af3bd2ff742bcf56cb91f675" . + "3dc727ee21c7c495962608927ce23e173e695b97871663ea11e7df7cc7680e17" . + . + "8d6f359ad552d92b7e7f671e5264b78712a7a380c52f25fd94b0b33b07c61fb0" . + "37c38dbd020e6b70e015e511c27a2c61eb368f01689cd43a22433565918ca539" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + "f640b3a7da52de9f89778eb6162b478b8ead5794b33dc10fbd208b25648c47de" . + "d2b40d23a98f3a7228e19694fcf88573f069f4549d022f33b642c8d0e086293c" . + "c6bc852e0360a492763526fc247d40433ddae4b29b591555c82dc60351293a9c" . + "14840cefb7441cb5f249a1b35a1cf85ddd1c1d95b90b7892ccc0af59090c8c44" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "54ff40567fc5217f3b4cf4ab055e00b76c6a27a1462310200fe9f27c39b9e7f2" . + "29de6d3b75eb95842a693e8b7decc817d52e93553fb24dda2273458ff023aa57" . + "e36667223c0234ae0069e1e98d1a04f5c7780e3416f8c82184468c4ec051ccfc" . + "fe0fb61f8d8ecfe8014d483804a589a755619148292e82be59b4dcc724e1a15a" . + . + "45bfa4b9b651af2f513a47be25a5c13d7cad8bfb5ea3d8a925c8324fed874628" . + "9289b1f9bf7da99cea76c4050124a4aae36e329c9a779c8f5b61a3650622f409" . + "bcf11acfe54b36dcef20b8e497be7b6a582ad3cefb1f9ed2e54161f6e1264801" . + "6db8b00f3a88f0c1cbe094c569914f5bde07ec1366e68d4f3388cee1055b7f6c" . + "f5790984d4079699f2d7de8e48fd5d62b88d5c5f8e3f09ab8e1cf81ca7b73631" . + "284dc5c24d90bad6e34346b2a7cd8d75bc3f30119ab0c21299c6c3d29c21bedb" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dbc5236a35a5bf4079f984ed982352ddaa384535258a90e384bb4db6e51b4514" . + "b83cd10ea04171819fef4bf2b87243e74c0d769e967310f2dab1b6aa88b8a8f5" . + "e30c5a991d22e79ddab6df3b0fb534008c731b40499ac06a0472ca4c52840d8b" . + "ad0faa670f0bd172b63f6216c3acd62d3bc8400758b4f817f9f3586a846dcad4" . + . + "d22fa04a98d6e4bbf86a60adc21b50ed7eb29c01ae5e08408ad70b4c94a9b6a4" . + "07de5859864fe556ec1726c901e2a6f32a0456c5e9128cb5e178e6db1912a0c4" . + "9a8b5fac2c52e43b83390210c1fc4ff65f95314b749d28efb5c4f2be02739fcd" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "c83d9097336551876731e72ba3bf42d6d69e0852e008f70898076dbd460e8361" . + "eba7499a830688f44378be02916dfa2f1e242e69967cacbc208ef574503098f5" . + "d92733cc48ea47164b9c53d864e50c19ffbfb00ea4e69a284b3e7750544a5562" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "02f4894c551c6f5ffed3f4af8dceaad5d30d233d125d8fe4f4e0e36d0aa1357e" . + "bb1e6a7e2aed004a12a264bff6a8bf852a5922136e4b11d90bad4cd7da812ab9" . + "4e52ecb3e5aea8a60837c7480980a67441a050d43598d51c721286ed27407279" . + "3224e2cac6f52835db0dac3598fd3df0f9972e8803da9ecf44e47626d2c44529" . + . + "99818be6d1383d1b8aff8f4fb191a5bae96dcbf4cec155e24ee5ad8ebff2d8fe" . + "53081c12f7a758a061365d272c5dd0c1de82a15a367a769313a2860fb5dba4a2" . + "b298d59647c9a8d8e7df3d76bf4d2c010040de4e6e02d92758f552e5c158a6a3" . + "c766ee2906c4715bf3e3e2f3f789c11c319a93a9d85b0fe0bebae87b51f59bfc" . + "99818be6d1383d1b8aff8f4fb191a5bae96dcbf4cec155e24ee5ad8ebff2d8fe" . + "deb618444d17f489ff0fdef883d51b35a3833ba2fc00aad4161b6caa92555dd9" . + "022b77f62738c7b92f4244c9669e6b917f6fce48da4ca7fa53c1751d499de6cb" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "671f165c81533c4742c74f4158ded79d16f2a881dedf2395a7134a46e0fe11f1" . + "8c0699cd042d1cb487b307b8790847762500e9e3312db51ab960fe5a8f67537d" . + "92448dee9aee5b58a556859ebf35e022959bed325337c33561cc4aa3c1569623" . + "15ef7b07973f8938c18c1786812afb6f936dc01b4554f740960713cc5f253d02" . + . + "2676b0d5602382f5803c21e5d21b35408e94d67cbbcdc92c46abc6ae9ee4927b" . + "0e4b5d8353a4710b8380e41bc3fe042cd7714dc7ad97a6f70d6ed2ab78e7ec96" . + "351a1c6bf2c233790ec343e63aca9d37d5425abb86d41b7dfe7075ebf5d91652" . + "c21bf0e0ce8d945dcd785424ad87b322d9b9aef8c0181bc95983b008efe27766" . + . + "825a138d7a4be6622f42e078a5156d192e2c521275cbad93a626723c6f4f3df9" . + "59081a86ae44ed984e989ac7b4e586acb5d87e2af6f023d8ac876ead33746b62" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53849a29ce293d361114ce8f8e5cab1cf917b85e816e7dd2079986d5d55f73e0" . + "e2c03221a1c0e6f79b1b936244f33468e05fb9a99468d47258b3c34995d71c99" . + . + "6a3d4a96c717aff7b388bc719637373002b8676fb52112df15bc1a529ca3e77e" . + "212c6c4946bc743a9f44c096f8e97b550e1d437076966974c1a2c238c54c4932" . + "c821dc4f278ff7de133ced545633fd9da4f261fa57268a49b6fe5ac828ecd69b" . + "566d1bd5cfdcd9a4826277abc752c39917e1fc20a1d3ea0b254cec48b99f1f64" . + "a08180dd438ca1a2f0638712113c42c3d6b1af4d15e6d5d5d6a91a8ca8809ea2" . + "5f79ee31d29e45b98cbb517a4d5ed73f58960002841787b5d84757a07a95952b" . + "ae97e11ea80f96919867601b01f2546bcda7a6a080c636eab36b3f9f0c89f404" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "04fa731b2fd2cd75e34cefefaac73f546c9bef7b8604c0fdc21e8ef9a6bff7e7" . + "d4de55112b01afd12a178ef0fe3981f70f914999edcefe8728ae98c18e913879" . + "4fa2a5c96bd07ab5e38ec2673617cee045be19b49c23afe76ed8e300eb1357eb" . + . + "b7df6f7a4cb4707c5399a6893c12686d9a953fd3bc53010f392564b0b742c701" . + "276460682ba9d67633901eb347679ad4da481774b92b3b56fc39b13eaa20fbf5" . + "26e1f24a7fe3459ca09cd6547a0d6dba43a4807482d03b00f92ed16494bee5b1" . + "66f1c9ed6856bc51158da27509ece6bceab2880792e3db6123f864d40ff0caf8" . + . + . + . + "4f7ad65f6e4351cd7efea13df6dd471bbfa1260bd388165e74c531d8b82c3d52" . + "b510a0a1b7f73f410de9ee65f19d5d2c99736eef479ce4b694dc7ed072a94513" . + "039cb24b58664e50358416111cda491bc7c34715d5c98938c4f4137812ba1010" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "04fa731b2fd2cd75e34cefefaac73f546c9bef7b8604c0fdc21e8ef9a6bff7e7" . + "b6e4acce906c8db474640ecece7cc32f52a8ddd19454b8c6f2a2ea920c5149d4" . + "046791cd06818e74f08d93d7396b4be5f5d9c6350d549bd9ace67667ac35a893" . + "5831b793ed1ce56c664df0e76f479df1395b023dcf2c32122de26da5148c6ab9" . + "adcde5cd00a276c5b3da27969ba2010f6d37efeb7c93e82e52a0253954a5f86b" . + . + "820ed775022c917cc90e406f73202baee00319f4eb879f132ea5c31d77c3d12e" . + "9b3c3fa73419f276ae0e26404dcac79a4f34cb267323bad3814d4ee7328a1ac7" . + "6926d5c67b71f639b54b490e79efe22e6a6c926bdf21e09e6c0f6d74803bb532" . + "efc794d1ba523b275e3362159dae129cec8a6cd32bd01a4514e27f7f6136ba71" . + "399d392de8127dad5e6b01cfea96c97b171c4fcef5cfb4839f60676f86682a84" . + "9d74076b56753b6cdfd6373d94807d66c2da70d66442ab838a9dc73089c274db" . + "08359b28c0b14d5d09a46bdeb5295cad51128e6e7fba686f8790c63fb136aa5c" . + "9b9c6467cbef28e35893ba0692a6e966f19c2b014c14bbbeea8b34152fff4d10" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "705e04c018d3eda83206ef415557b24e12b577a30838a0c7bf9b79a15b95b523" . + "854aab4a65c2b7987c75f9f5ba6d9786712d8a9e37851ee9617bc0399d04ddf9" . + "50b42767992635ff638dda549c5bacc4c6f224a177c0498c840e5b86698c83ec" . + "e82889753b54884b3c0d593fbdf50275e0b3ccd2fc632a01a999e1c5992d6301" . + . + "8a8f73a2b3a9bece75bf2e92d2e0a08bc7114678e118526740cba8b4158b085c" . + "1f132bb7a159f3a207f51b453947859ff077d0bf20fc07da8aef04e7a205f267" . + "d8f4b0dcf80a481cd502af93001819357f52f23b800c245807bc4866596a0f00" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + "69ca7a57daf6f4fbc16f928c78d6e29fb4661dbce52125e18364789c029f4514" . + "995ce7f43781814a2a74cdf40b3e0d8d3b3fa362114f21ed996d1eb27e1afc4e" . + "17a93fad52cbf85c469fb70dac071a7bc62d873309b97bf3f24b3fdfe7e891ca" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1ee116a5168c09735c86c235e0ca6ef6e9d72a4538110ddb0f76e36d0baf8cb0" . + "a53d6bec93184c69261e2363c64e37f18a3f111e2bc73d081694854769615a77" . + "8b44e78e35b6822c631c297240a51076af12106952edd9d758ed28346294a7e2" . + "c57f35803334e1e16017a77ff964aced40f430b8042d6a53d1d76e8c20eb643e" . + . + "566750cff3a56fa234cd1994216467d7477de36c6511772f81cd6832dd643575" . + "8b8bc6dfde4c5beb92786834956e4b99606c5ce1a8a799117365baecc3839eb1" . + "4a2b505e1cb3a9b76837cd66cbc27cd6c0a13e1d69389ffcabf87ba599572a50" . + "b33df5621ae85d5b91a576179f655c2fcc0ea32b58202135ed9bb621f6d327b3" . + "ef6d6783325332c85a951718535b664249df6820cd121cd57d1275395622900b" . + "70938613d4faa75cf97113a9d14aa9c54a33158efd66f0ad3db4e5b205fcafd7" . + "17a93fad52cbf85c469fb70dac071a7bc62d873309b97bf3f24b3fdfe7e891ca" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bd39c29876d1b9adf84747b36a78453c17e64de226c9775927ef2b1245d3fa51" . + "19f7f3dd777bbcaf0cc491f6f8adf119a8710a210e81f08fc548bd0567060da4" . + "00722731965dad60a48ffd7346c932b3d8bf7bf115657d7d5e662969390f1124" . + "d304e52c5f5590e2e90802dff66248224282dc04975a51dfc474cbfb8c8e6562" . + . + "1deadbfbacec1c94f6f442aefeb5a4755fbf7a087e90ec682ca0ca8b5e796486" . + "fe153886310063327e39cd311269d7b9560089b93324e62e5576c7b8444c183b" . + "106158aa38428c0f34d0c8bc979f356f99d1c3453600d9abd4e9a7903d40b324" . + "94af0475c2afbf29bf1a72509487bc64502efb7f8ec5ec9756622fcc8ce39ebe" . + . + "b3e42873e320692fda8d6d44f38734c0f75be3c03e0e219a7c5925d064204039" . + "8d70006c8ad3a265cf37b5889e933021cb0afa4d265b095c2eb67fe5c6576e04" . + "1210d6b910dc06c803cfa64c652b32eacd7e139daffab49f43d558a54039c6b8" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "f8f1371582bc6c17b007709ddf647d8d495eab523b69d3a5e96bc3fe1c634eab" . + "b8c8bcc14bbb296c9f96adb085f5c2cf47d366aa657e6801e0f2be2ed8244850" . + "4e08f4c244ec5ca669caacceeb1f2ca29b2f1b2bc7371d0a739917aa8e8e6075" . + "a4475a395a6f146c7603a1c00aebfdc61ebf31cee245b1f6282e1d55fa33feb0" . + . + "63d11dfa275f8444a032ac11a3714b7f489c886cbe6c0aa8edc87e58038bf5fd" . + "d034ba54cac592b14e3fc4fc6f9dc7a3622bafbb1e133efe8501d2443550f914" . + "cafde1829e95eb5e12ffd9c40c3bf43f9e4db6c09b2e593118784ee88727a331" . + "74ec08292cd42001748fa46a719abdbe7c26c0fbe55787d02181086af96128a1" . + "0df85b6e91223302330960541102432beee167c7aa6066451c86eea7fc4d5e67" . + "3f2f69269af55f254cfd1b8a8c8fd8dc337650cc0a257dc592af4f54bb83eab3" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f8f23b6367cb6a0a62bbefc26602ed0e2b8bb93a4faa0838c3c735808ea796be" . + "b8cdddcdaa4bc1dd03e857debf67bd67077ff01ae8e705b91fd0da21e21c3bc3" . + "cd568cf591bc65bd787d80e23bb6314cb0d56d848eed197744efd9807d7a3e3f" . + "f072fc7fccd2af19ace841102d8254d62c2e5fd769a143d7f6f6dbb2a5038068" . + . + "19ace03cb9f7d1fa188694869dfe013ade11313d7c6afb9f490515110c5378fd" . + "17d4cd05af397089caf27126a8fa83c7ae34ec1f546752e9152211f78bd897fc" . + "4d13a152b99f54ac8893a41a8b73ea17b832f8bf4111715972db805ff293d13f" . + "7515cc0946a6789f71762fc9bb30f59d44fddd19ee3f582162cd850b2e3f422c" . + . + . + . + . + "85a34c24f71526ba25fd4f49bb9acd42452629d2f2931d4e5acd7a1dab3e3235" . + "80288c29136c8b22b766c4c989c9cdda4bb7e2f8752e6e60d21f59aac8347ecc" . + "ca31488685137a0cd291bb565df85003a9fe0ea345b1bcb1e218c13881a4f515" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "38a8256fa7d93b0c7f082e61e8d0450a787eb958ea01c22f73914d38148170ca" . + "c11ebb80aa5e811a0bfac3d222beb94bb9a8b816456b73117bedb06456d4bf3e" . + "84ef5f73b3eeacab75c543ad7e7e231b207450e7c6a061935b124e2370f5540a" . + "f7a76c902d3f56654c707e2e65bf79851db37092b5ad2b52642b355d035c324a" . + . + "cfac6b49a0837bc8b8920b48e197693faab987262aa3c661a05db4b789092e28" . + "af7a6e71a02d8df30a2847039746a136c6656ef37789dc89fb3d7068fd3e27dd" . + "67e7fe14dc03a9d02131e8331244e72e9e12362a2df10679b7f28a7aacd9b030" . + "607279ddbfd65c99452c29e6ebf72bfcdc83ca2c2a50dd593cc81344e40b41b3" . + "31fa11ae0ab0ff4cdf02b13f18103b9956ac1552dd81e3c890fb37e5a185d9b5" . + "8051d18f57ddefba2cd89620c4b0c71fef2321a13706e061225e204685ba05c3" . + "cfd9d12367c9f6d0f98c2bc785119a0c5190fe9e59b16ecfcf57b388e2f9a48a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b5c49eb7d3d35c0dbf6f7ccbeba5a94b597b4d876f201357ec73f32530e9a491" . + "054e2448ebeb55db930517776c38ddb2547a8bec596dec44f336641b47b2704d" . + "a320420896b6d4d1595880561f2430abde048816c325aff57df41b75e55d9704" . + "2f425f5928d6813a2835fba2301b95190de069c9d0325b4fd1b81e68f224d986" . + . + "bfc01f0aa47f57a5cc7e88dee7e54aa136197dfe75fb2494737d5dd3ec3aad44" . + "b259247bc3295cecb058a4c8878e0db960a2416661dad0719399b7cf933409cb" . + "23c2a356eb7a9a1e7983bfa9c85697dea983fffdf34f03ff605be4676365d0e7" . + "f75701893ce1722083bf062f127a524dbb86e3abde5c917831a2f484cdcbd343" . + "bfc01f0aa47f57a5cc7e88dee7e54aa136197dfe75fb2494737d5dd3ec3aad44" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "168a21f71e950bff80b50ff9ce27e0c9763dc78046cb26b512a12394c58dbe9b" . + "4390dbe2ec6d1a72a384c4e57ddb7d444efd3d4ab0fedad916416cfd3cf0d93c" . + "1220215f6dfb227cc25a7a832c1979c32bd26e44cc41799243cd3077e334d080" . + "d2867d6e71de091e3a1bc392364ab786f297e464e1a66d0d3aa7f924105741e3" . + . + "68383a52d83c02156e9f3d3be87e6ff1c314a29b18502818054b5c4f56bdacfb" . + "780bcd395e09dd245e5234e8aeaeeb21e3c875e807460790f7b87f7494c91ba8" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "952ce3c29ab7c1037266f4dee0387165d8492bd1ffda9f3f8a69332e1129a7a1" . + "3ce801afe9422332d0f6f2863afef131a2b7014be1550f2fdd7bf8693e8a510d" . + "410073537f01dc33359a1e5b8bc6d4345e1e1edf60b5442f855d5026a796ee3b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "38ea00f8fc484460712bcf03340104e79eaed14e28a192015768b4b24090eacd" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "17a79de2ebd66764c9a115e1c9eb5fb34a05fcbb050ca6cd26012a5d5caae97d" . + "f82a8c200c3cec19b0241a357c14053d49f26852086cf321eb6c66eff5f35264" . + . + "96584474d12b09737e42c0764d08ecd61b1283df24e15799cf602f8f30465ad1" . + "4250eb2783f7b973325fdbfc5caf2c5fe2918f3de69cd2bfe5606b4186c79a95" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "45640839700d5e7a9ef3bad6b15cab0266ac34eaffff5a1950bc43d9658b7678" . + "e9e957650fd9e5f1906bbe2be68951d900b3309587e43614a0c0fb79fa93794f" . + "40543bdd118487507a037b05349cfe86e0d9b26dfc8b99b503199a42bfa27df3" . + "7aad667d631c87ab992a528e67c85be9493d15f02c279163caa843d792166a92" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0eb2889ee97d10d4ae7b384f2e74ac437639ddbfc33d07eabcf51f18ce03e387" . + "0ad65c5f771df0db5814c54a30533a58f7a40df84879a3abbff5debbbd56c1f0" . + "d9e24e32dbacf0e4a5f589bdd3ce239837764cfdd0aaeda09f290fc08e38f627" . + "19e21f0d80c24fb69f42b5857997eb53a196baf71a430c0adf35742503e265b2" . + . + "266c1c4b5fbb5c249c73370c17a97d01ea579679a56192084db4342c500e2ad7" . + "17ed3d4d7a6af368918b8a2cb3754b64344c7f925ca73709f61d35a91edf3b6e" . + "c21070837b6bcd5502fda098fc63a6552b264136f3646987485a8195aa5fe5ed" . + "d32d871f4c641767ba094e83ed9d2754cf6cc640946d1abbca6105b2e2feee98" . + "5f8519029fcd4cea013bd4edf72ffa090596c009d0a0391cf9d795d2c4b71022" . + "4afae97475bc55cc377595483e98f64d5d705e31a7f1a47a99d185032c77c2ea" . + "054b99533d4c0175cae7bd7c7ae1ddfdd8e521ec641f0783c284f2e12e653027" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "abc39df7281064037a2199c52d8a708fe2da5775f8596dc5eca791edc50f991f" . + "a6ca0c99e6b1821a3205ca8221d9a146a8f90c9c977a9d878c64f30395e2658f" . + "f12fe205ed0e4cbd79c625372df07f361c4c6dbea6b13fce42cb538e561e5812" . + "218f2c5cefbc3b3560c25621164edcc394b09bc72b53665d4514c2da6783d959" . + . + "3aecde3db8dd1c69e3117f63b55ea5ae847e27057f5232c09840617308890617" . + "57f69d7484d50bf97d31948db079aef45621b49579e224ddc878bedffa98f6a8" . + "2517797299122631d59877b40026bdfc22310034087ceff53efe6ae0770b397c" . + "007d5cc49a6a1eb7cc3cc46012a91896607dcb8633d5f360201ba7bb24a7c0a5" . + "de8f90fa8d2a913d03506316452cc05f3fbcec641e0427016fe5b862c612451c" . + "4e0e4fb8d458de640f4e55051ad0159833cd068f1ef18f3e243ea4fa25181b55" . + "0252d8707837cafd6467612a0ec41d469f41e91e0b7111577a0d45e2d47c6205" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9aab50478c609f99e8721c3f2cfdd12ba14d044814fbd85e5daf917423f812df" . + "479a3b752df55d080c3e4dab3639c35c436858b143dd7073456bb824d36d401a" . + "2bbe57adffc461f6a756f883eb39980acdd391a552ac085b88cb7ceb993c6001" . + "30b142bf824c75f96e746143c47c78db482665b0966c65856dd931a4d14dae81" . + . + "e3a775b4147bc8634351e2de624b4d3b39ca0e6ece25a1f05b0f41cc7214f414" . + "b79f728050fbe1e344b2a8bd7e19ea75b95d7b2cf0ed439c01b5ad489ff3da45" . + "19f5acddfb274fdaa5e2b00364054349b1e0d96a308924f5e53101b7e8c5b78e" . + "a624d68eccc80d9584303db9b3534b9e86a54f471db8061c11bf8f7b6727ccc3" . + "7926ff76c575e1ff88417e22c04ae7f3065eca59694ca99cb1f1e86140eaf5ec" . + "c34c30888ea5f2f730429ca586e10891bbf99edf832239d6b15b9ffddeb6d20d" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "691f85ad1f519ca2fff41a79030e55535813cad778daa6a48903281702b52a4d" . + "d9eb6e7da4c63f48191a61b91a948edfc289f64cf2ed62f950184c77983e44ab" . + "ba4e4b1957fc1184904412e65a715ba9ec74da08a431743b9abe1846780f66aa" . + "444ebac77f371885e8575e35cc0c3d843bc2f6d66550cdbe251e795bdc051689" . + . + "898b47623585ac4ee4dd8181e4f3934a112badf6f226a052ed36b8f18621659b" . + "713c2b6fd43079103815f5b3f75cb191afab2272154a066526b98f65f8e62e08" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + "cbedad8f3842434427362a437d7111efd38a79edcb766e8eed53097692442928" . + "c11cf35100fed6765467873f6e65bf2a15c820a87597bb36ed562d1c419fd26d" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7de3c48b24e54d5d9d50a2ea1a467713b385e60215c397441cbaad4acd7a2a92" . + "249a6fefbc12b1dcfbd2a0c59c1b3ec7af796556bf7459233b5ab737581fff31" . + "70a45f6e3dcf66642882f89eaf3bf72a9f52a696add54daeaf7f82086e836a05" . + "492185e2cb639e56a24cff4037c870bf24fbd5826c4821b1385a6a245a114c8a" . + . + "668581dbfe7b3f03c721992d0dd2583b6a3c8448ad86da65853e648d9c431aca" . + "e9679c4f33bd7a5c92a128b5c2052bfb5433e780f547e46bd9760d272595381a" . + "c6e8528ddd26a59346be31bf5add911d6785fa35f5c434029cc7edbb0be4b0c3" . + "d76d043013dede77f1bfd16714c039de5205fdfed7983e0c0e8badd02ae9e3c7" . + . + "8cd664875125745f4a4ded998de2d62f852b34323d621bb7964231ec6fdddc54" . + "3cbd837ce8ada12d6124013106159afc920114a5ed41e52912b640cdbda4d041" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9e3618531de76026bf9a1dc96dc85c6124b010315dfdecdc141cb0c8d0a49534" . + "e7462eb051fd7badcea625894913679ddfa66071a4b1a669f07a0fff4aa10ea8" . + "d2295b8f1370e9d5f7b7633ff72e268fe57ed0fcbd791ba177db241e9e074f36" . + "45cbe7925b3194390a86257317563c260186470fa7b75f58f27c83d8863845c6" . + . + "69a95ea7a5896720a1647190b630305502dee55837fe55c9bf0b804f7c018dfc" . + "b779d3dbfd008632ac1fa097170593d27e2ebf6b06f0e0a70273ca797c7992bd" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "2159067d1d232ec908f89fcfb3d49ce8f93bf78c937d41d96c916168e426241c" . + "78bf415b073f6f4f5f84ec8bf84c5cbdd81f5384aaed10a814b26fedaf54af5a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d81b80c6483f32d5c28005c30a1af9a59be8591c34e036997443dd919cf4bdca" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "54491c641ebf841e626efb64d94616fc07b3965219832f6941b207708a2e211e" . + "9da25b993837efb04a251ed16f9782519325fbe9cca0da2e4dcae5da742d618c" . + . + "3cfe58b8a950c363d382165e1c978dc8f5ba2e6c4b5e41db5054caca2447c2e6" . + "a07f1064de8ec756387d5bd0144660367e196a38d330862e713f468bcfb5c5bd" . + "5e6daee77afe38e403312690f95be61e774b2da1913bc056ec95d10347b15eea" . + "4bb586473904a7bf5974e4f5df8434203ac5439e990298b334a3a1d4481c7190" . + "99c83f472f0ea45c5f455904e9766725b1a0af84fc1c1a9f2fd4f267f7b2209b" . + "516bd17152317f54fd2ebd18903f75b230052270192cc4e1ad83f842df575864" . + "97e53464fdc63cede53ae12551cb9e25bc4149088ea70827213a37d22fd4cba8" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "ac97361dd4c8cece46c57e3c9822aa72a1c561dbc73a36140ff45afb0ca7a502" . + "4ccb5572ce5ea010f009eca6ae2154b18827d38e8ffde89b753f885bb7c201f1" . + "6fdff91ea10ca5c684c2b967640aebdd852120add3b1f3bcfeb156c2c5d74411" . + "c93acced359d7068dc7117769ae84123c8926375adccf2335a1794ccc4b676ba" . + . + "9826480f33b4cf941991cba2556051b328dfd7f199e3a28957ff8941f63d099a" . + "0bf7802eb6079d56185388d8b0e54df423e424b3a21b1fd302743234f9ad0654" . + "0739d46cba60c1bcb6b3cff3916b4529475ebd9f695da3bbecd9784027e38497" . + "68867e5fcd8dc622fe1b395c89bc862dfe3f45605ba506029bedef59596b673b" . + . + . + . + . + . + . + "cc10f7dea1d627138b80306d76ac114b8d2ec6030fc097b0dc3dd37b1ac9b9b0" . + "0295c0ff58824ae2335ec854652870de2f8ffc22ef40f75e9ccb6686a8c47b92" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26e939d59eb68dabdc7b19f275b5a2e52716dabfd70cfcaad64286a469415b2a" . + "2b415d6c84c67f565f59fa81bf218e70550cc0189e911aa4e593de3a101fd43a" . + "fef0bc3b246a4541ec62416c5eced110011e5af87723850fbf225fd70b3572e5" . + "f17c8155c0cf221cc533b64a38beef250ee4af212856068dd51bd09fb2f6b3d9" . + . + "7b2c68e7a03a354235a7ce412ef9d5246d0f11fb288394dc43adc197e48a7609" . + "7cdf7c58354da9da14623d3a0904c71db07bfa0d24a4c41c2e7038f2a2bfc9ed" . + "48a7ebd8d4832542e67d5796357ac70fa52b937cb2c102bc8dadeef465ab31c1" . + "fcbed72acfd853d8df61064a2e72bc4a5364058a7e56b0529baa455e78c86ded" . + . + "07c7a6d3a13eea5fd808008c7d9fc1ce141094ac3cd6ed918558e2856114a40b" . + "cba52a94068a833dafa21308898471817fee596891511e7a5fce84ad85e6966b" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4e3fc37bb6d1f7982caf692a87b95d0cb011d1cebd66468c858a0a9d53398f59" . + "5f737d75bd88b8c40b0ce6204dcee752314cb9bad7385d651c40f66f5361c0a4" . + "ce6cd91e2dd4092f6a547be942ed33a01647d377903bf1ee44893a3eb6768ee1" . + "6a0ae1bd8dcb3af6c86e9cc578c3445afe9c277539a180fc0016bc196529761a" . + . + "edfc5ef75b65aa8310dec101592a3dba63f25d094afbe4978224a942175d23a2" . + "2efde55c58ef6897bcf0970fd6a0d93dd4aef25b6dd31a9e1ac6b6c46ec41074" . + "9626002ec0701b6f8607ad9015384322c1aac1edc455dd38b42fe909a1e106ac" . + "4a5bc19dcea6699de0179abf19ac038cd828b471640f717201a267a12c25cb72" . + "27632732ab96b899ac77657e6830b9e5712e051bf4fe5b498b349bf1ad9a8c7c" . + "be7e4ab446e270232d241140fa3ee7e9f6c5f8247dee0a345481c7bc35818c9f" . + "621556ad3d2aae50433795b8f8d0d0f1c389028d5f78c75a650c2dd3a836db47" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7377bba23242c4682e7445da21c4e19a15810f54a82cdb39b3d8a861ba917281" . + "5b47cfb35008a267ba3817ec448af1104bc05ac9de7092c4f4c3da98d25d6e45" . + "6e9e71e06f7e9305fcb367cd910d32f44e96b7ae5fa63b67f510cf5bc7147a21" . + "f2974894d274b385ce84dfa549aa1dc2521ad45b8d1037dca29ddc6d1805e86a" . + . + "4b59f223187e8a315ec50dc95fba0786b206d570cc1bd9dcf99e760f2a24f960" . + "7affce056137b6b2c58a3a1c6f9c696d967b6ca14c3d20de8dbe76781333d3d9" . + "9d21270ddb54f1e7f3d16f18c72890d61af66151c8320a76fd662fa5a1ce5ab8" . + "9198cc339f2875ad9e08fde7c60b7f122b47c5021130cf530be3041daeb7e24d" . + "df647611aa2838b0ac497ef9b066d30a72bcd8bbb101758c27dc732ce4a11b38" . + "50fe7aecd996bbca3ced76335e331ba1fa57b55239491365d232cb8a04dae2e2" . + "6e08a6dc143e510daaad63b0aeb0eaaf083beb8abc690814015d1b40a3164d6b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4af147cff50c6e25663eb22c54249cd94f185f65b6248e2a9c5889aa1b0120d9" . + "e863decb7403e6109b704567d6571c9c9bfd426f7136de612a71569ceed0eb96" . + "e7eba29bcaeff8bcc787f0a8aa323b8748ad0d57d7f222437832b4c6dcbc9318" . + "d97f1fc935b00e5b25d8407434a7bfaaeb5035734433a280d8fc567a087b2fd0" . + . + "9fcd8e1b0387cde2d1783a98ebd850903bf3960647a51cf5229c3fa186284b3e" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "05c89ba7a425a64f1d5ece7fd08434a761f1318bc6be1f9e36e991fa49ada5b9" . + "4ea3a73420cbd0fd150ac4d450ff63d2c1e46e3d37a2fa62b60b3965e4c17bc4" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7e3e517334333b5c66a1b3309b0d488b5d392476c116f3f37ef975befbeb3323" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + "be221a5023a9cab6e81acb71345142d9d7658980c87746ba01ba0a7f979a1741" . + "1d4e3108119b52397e6d626bf7bb9b7d4c61e728369e96b1081334bbda3d2fc9" . + . + "3b656e8fcccc94a7182dc9e78743c041062f9206edee0985e257ff00b6ed2b5c" . + "c3ef173626a1df133e80f2262be70c178048008e7e4e724783e411f885ae136f" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "9c4fa637b9243e6b29b2a635014df0fbdc2e5cce4abe00c971d6787211ae6874" . + . + "ba0b887f122abe515b83cc59538e0250550050c652b4decd170ad6b0c91b9c74" . + "0b7a1516bee19c6cba1a83bde260c1f98bac32ab4657f1ea632d8e1bc8f32364" . + "61bf64ccba3329eca4752808ccb9a3146e42c74d483f646354b9e10ad001987b" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "32498acea030770004e2e7348a0f77b07edafc0d9e2b5d2a8ffd25a1b7e4836f" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "d708c525cdc62fd7fd2e5129bba943ff94bedf50b51110579e2c7276e8b492a0" . + "ca90f6ccf4ad6a81b1eb4a338a9f96f27e5cc9594036ec7a18cd93087ba2970f" . + . + "fd801d39d4c84641b5376044343315cd3eac7be852f4e24d3b75862905c376f7" . + "dd140c04f728bac5c55f78d47b3f5397f77bc39c7d43dc85e17750ac8bc55123" . + "75f81925a9193cf74ae991ea13d0a06b9bfd1e9a55ba536a88d4d469885dcb49" . + "01ab6808881ec3d5eeba596472f088c102b68ecb651b9eec3171f811f26707de" . + . + . + "be00262606482387890fe26f84a371ab0dffe5c9fb5010977fb3bda839634c88" . + "ad34ff2734d3f5c8eb798f6e709b6f6a6980d61253940b3407474f3f621bfd7c" . + "3964f9c1b4e0f5547494a42e6481c565bcdab9b7a5313815ef273e95b3c7a2ab" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "150ef3a628ac2f74aada0d14953cea01076aead969919691fa4751d581d9a362" . + "e94764191cc9d0e00a438aa52565eecbca9877092584e2e2b5510df1189d4a07" . + "54e5ff5980e548b9a7e059623aa596e28888b9fd589b35a64ee05974fdfec947" . + "e86fa140ad58f937aa0db8657498a80dbb2b8b1cb1fcffeb49cd3df637883614" . + . + "842b34e5e86c99116239c96b1839ca76fedd25ca8048ff2e34e8d2fd8633f6c5" . + "163e8f7765d5d0cf69568ad50446e3300e19de9aca8f28fe7098f5c8450d9466" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "a7bfe5559f092e309af2b2d283bfb73b5d81e9c8eba2db1c2735d72b7871a4f2" . + "0d04ac025adc6b7a30aab757d10d5b896084f86765def101b9cf5c026051d85a" . + "b7a43449d7e3c69976eefef12f7f4275bbc82e72df22fbbd6f67a9a3416345e8" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b1bc0ce9e684b93dc3190871be9b08be5196ae5b1a293779e6f57477b42a1efd" . + "ea088b9765a0bae104902994b80efabb58e5c73a1bac39270ac2f6fdd8ff4f1f" . + "337b58d5239d2aa0f6610f22bf67a50ff3a897f7688067b631bd92e02a04551f" . + "33a838564831dbfa98078398233ef832699329e21c1e239de15b405cb9155a0c" . + . + "c37c318270ef932927daf50e0097e97f796cb872c5a5491112ca411211475818" . + "77b703b24a925821df4d8af985f2aaa026944df2648b86262ddb700300ea17e6" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "f6fc96bebbb50364de93187753a85da100c771de2783ea450bd696f3fa6f547b" . + "4ca7369ffbf4d9dd215cf453bf2fc4c6cdc7d811672f6b251b99fea03b1cab63" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d6bfa8de8ee20f40bf4918cd80ddf4f763ce5bcc71a9959b0d799f994332281" . + "7d090b1d7ca951538dcbe500404e1ea9f0acd11475cf709f85198aed1169d39d" . + "dcae4425d8e37ca62e5045098828b56a28191a8c36f0a702dde080299fd073cb" . + "935dbde76e25c93cf37cc459bfeba248b00bb478be8477bb39d7bd79c83fca5d" . + . + "2dc4011c96ac338b3b064dec577c5585b348bd1727f5282a378d8350e8c7c33f" . + "5625c0fc47a9197cdb22cb9407cdf472ce923187f8ad623083528e69356a850c" . + "a7fcc8f86e85140aa0b39685346c58b87c22b4f6b1485a80e9378ba9237704b8" . + "00880386ae7718a31e23e4b7a22672cf1346414416b2819892157d65a75ee3e9" . + . + "6f8959cef9ce6ee7594ab80feaf5799397f4a8dc1de8a85c3c99a9423ebc3230" . + "42e9a0639848a9b254b09832f2f7c2738b4d07b81254e76072278c1372650cce" . + "395146c2443739e02447e9a675ed445b2a9e5dba9a3cb65f30b82b3631f53f64" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fd1b5c186585031d5cf8b680cd74a3745ef5bd10b23e6ee4a1275598d3a6f1b0" . + "9c9b9f6c7c5d29e9a21c9a932434058cd19fa618e4e5c83bd125cfa97998cb03" . + "a7d510156a4f3245219b8096451439f3028280ade256707ec942040263dc4f17" . + "c337350ae69ff470d786a10cfd29fb7ed4375d3b7f83bf268f026e9844fef070" . + . + "3a46ef890fd5c550d2544ad70670378bc8b5d84bf9e8c8262cee723900257bfe" . + "f150897d415758e7cf6d79c0f497fa3c69f1220fef79fdddccc04bd61ca69594" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "3a46ef890fd5c550d2544ad70670378bc8b5d84bf9e8c8262cee723900257bfe" . + "ba897b17d3e9d417a8363acc6ef6b25f9d0f11c4f6b3316916c2baf235bd69e5" . + "33676e33a4a9ccdae573a3918aad0f91cc43b6f8da9f856c8ceb9698b9fcaf65" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4894482690e5bcb38617a7d4f514bf66acd74e0460775e7a2ff57bc9589b8f6b" . + "82f4287c2478ccc072fc759950ce7c3ffde510bf5959aad00a2146166a935d9f" . + "367a005bbf64a0c1562d4605f27719298588a21433d789ca30ebb41d1795bc46" . + "948123ddc4aadad625044f118865544b356d49a7e5e93f8fd83c725435d09f48" . + . + "e0304932d0e93a81034fc7bd29e5a005178e186b7191d5ceb5d4df24c337de9f" . + "7401ea00102a95c0685dc9c5735f8b22cb2e04b20ac76837aa6dee77721d6e30" . + "6b9b78e4e5c87912fdd70cb9a41b9108f3e461318c5ecf8976fdfdf928893cc2" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + "8b1131066b6863a534d0fddff2688ab645398f07b3058311f0f54739678af1bd" . + "a6331482bc35fd4e7ef4ad091b1132b2e5cef227b0b9e2c3cb8ec3cd29c20d43" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "91f57bbb007c926de92a50964c838cc251c8b09377fd91640935af8384a42839" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + "b333567ed517b1b35f1a5380052ee8c0879f200fb811efbce0ece1083dccb5d6" . + "bc907747189468bfc6fba592a9a9c364cb6caa23f1cbce2ac832c04a807709de" . + . + "2fc43ce65a3081e77126cc27494543f4d4dce71ee7da97d86d23203f7a79e43f" . + "199931eb224ca6fe99b7a74f04f68c13f675d5b15353ffb3753790f300b31954" . + "6a146f2cc14baca6b8600b7c20fed689342c7e2e4f3cb82e0bbb3d59d87e3d82" . + "e2db02bbab2fb07af33462db21b34eeb874ac050287231ce151ef82040154412" . + "568b503bddad9b2f3b85f433cd9db1d5083e69384c0e87e888426f257782f72b" . + "67c8f6d083aae97887798190d67556b2d8ec4f718cc12f32670edd18846d73ec" . + "8514101ff6d04c27888ddb2c90e72033c3256e0332303783ffc386331138fecc" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d310cce9cb1a4c4f0d9eb7d3b8883c44592d71ec20595e9d4ecf3571ee53798" . + "914f658ded2243a6c830da92f0e387c660f9981cb59eed00e7a3c7e0f3fefc15" . + "50e60b8259f8a18aea3a3e69adffbb3221d8f8530f481729034d1c429ec650a4" . + "20a04311d8ab4311a0147858fd9d59c960d63620e18a44b2728bc74a40afe6d3" . + . + "109d998943bc81cca8bce9d3934dc431874f1e6aba28c947ec00801d645fb404" . + "39b2f251a9a8132af7b0130639fc36d8f1230564d75571c5645c939f54632da7" . + "b953c7ba4621566d05e7559aea5b01e37bf4fba7051c04f4ed9c99fea832f831" . + "a7644808cd884d37e1a716cdfb5b43172829bedf081b3e873f3e041129dfa83a" . + "7b8e569ad8b81198fefdd901c9292a3b109244e75220a2c19bcd79ffa26c29e0" . + "9cb6d708752b5ab0120ee643f08bf71ffabd26e581b86353e5fd901fd830c237" . + "680547e26cf55727a1c08780a6c608526876aed05f2eeb9397a597c54614aaf7" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0f8f32f3f40e8a8ea420ffdc10fefd03d2090470cfe37325f8035cd5f7620d95" . + "5a2c4d3d21a459784f7d8dab5433523ef0efd168d84ea171ba767569e751c92c" . + "41144ea1338084351dda3725462cca352b1a4b3eba4ef55cc2b8c40f52ea3707" . + "5184ae9584977bd8b5dfbc083d3ca0459ee7e91c1fefbbf72eda328b8a7c34e2" . + . + "71c0e1557c1374ba59070d3b590b10452014dc479d248337195ec6da0a96f633" . + "d1416e7cb81cdb32d3c7ebd9c726e19bb10c4b4374ca967d75f309e873291d22" . + "49c26ed06c543b71573914fadc4a80dbbc3bda1913b7b64b97a7c2f902080dac" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + . + "846d552179fdf68f1b4a52bdee3ac0d6a93e72fa9899f6e9356db8c2d6ef478a" . + "f9ebd09bb91c98e1bfea570976c79694030b047f0a5fdd01cde937ad21605284" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d5fd8e52cb2ca1cb47235ee94c494af8a18ee77cde9b23d3b199c9a1c9ed0831" . + "eca4b5576693681476d2742e8cc3c2a3ddc574f807bd01e197e5bdd6c86bff09" . + "96c6624bb831d05d2f9c05bcf9e129d9b36cbbae20fd96bbaf34ed4b5e5b1ad6" . + "2d58ed9e458583b0b1c46370c33ea9c833fc371db8e464fe9c21a49dd521b0c4" . + . + "2695829989e82e557abe9e0ddfe2641a0ca4fd8304435f54cdf65f18e0dc1631" . + "95075f969e8a28a1e011ec03d0f9b85a273d422f482d1658cc4fa305f7f05e47" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + "faa441b0793344ba2b8272477283344fee48ac6d00dbc6876b487a956f4f200c" . + "5042001ca613b9b12ed319966e4eafb6223059ed43b6940bd02e5a7b07a7e7fb" . + "343185e4ffe2e4ad39f3d76e61a31c301f745a17b4f6b7dbf51db6fddd5cee01" . + "9e89586a202b11abf4852eafa257f84efe658bf3c4b30ff94439e6f3856e3f1b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "872d01af385e1a5dfa47cd721adfd75a3cca4c56469533c7994e2f8bbae51a27" . + "7515cc0946a6789f71762fc9bb30f59d44fddd19ee3f582162cd850b2e3f422c" . + "50c01b3c8c033a5048b1a837e040bf3754a117f3eef8ba853299f012348411b9" . + "5ac8231a78ac870f4452df435bd2f6f1559ac04cd17feb717ef8185aeb2bd7ae" . + . + "619959ca793fa46342a648189be1b8b03bd51ed95923218b291bcb54848fe821" . + "08ec74db39eef60c30b0918810e35c5c75b159241eb7c1ba51edff6bc88973df" . + "9e16690d06dc729b371bc0a1cd8212c013f2fc8aab73369349f96207987daf48" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "39cafdde3df21c062d8c3e5c47934cc4f8df305541fff35c6515213d38968090" . + "5d44c99ad3fb03bf0dff56362c3866c499347695f5d4affe17f8649e3268a747" . + "2ad336399c482ab9a7cc5b80eb80b48e2851b5d7ae7472d2a7cf3ac185f8ec81" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4e50a8ed9b3613d76de6e0eaf8a2fbb1190d453db4440d019dcea3f01d06ed14" . + "bfa9d0dae50eb4f97cbc9996254fe7d1d91810dc1470dbedde798a3f982aac2c" . + "50081e6fd71ea831958a6ea7b518f0c66dae38ec22f82568488159444236f1eb" . + "454478f0154d2ff39e39d2390c739a6eb4bfdbd664a51f6306c47d38f678bd39" . + . + "b5dd8a9dbd3397f357a6690da71e9bc6f3f07cadce17e8f73a93e987965970ed" . + "9299aff6446e238ef9534b5ca13235447efe6211a2e318398cdf7accf53b44f5" . + "027765b8eb7ea94fd71dce0984204350c4e96bb9a58f6a5ebde1b3dfeaa44a79" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "0305a40af0c08a7db13053db1b232baf817d617182462c72a852de6f2f58b750" . + "61bf64ccba3329eca4752808ccb9a3146e42c74d483f646354b9e10ad001987b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b37c15cc08aa01c54b7cde3dde16098be79b53d74a105fe01ca6fec8bd1fb230" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "c57216dce5bf5e04edc13272d875d4f243e997e8a40bef336461d7ac36023231" . + "f96e04d842bac0f3cdeb71ce81a4258af0dd950f46a0566a92c1a1dfb485ef4b" . + . + "8cfd914ab11b9b73ce3f7575f29382eb72ec41a01a57b84525f690494f502468" . + "c23b4f8e390ac1af1db8f1feb382dee73f963dbafa025f1830da24811b082bea" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "e3c43683d8ffb5e2817327ffae2549bea0aea0f2474f2c2865d35f50a2e2504c" . + "620b439bda283be2774201542a4415800e1a7ae3de47bc04aa31772bc17b6de8" . + "bdc5b87bcf8d7ea81a0a37c391dba5019f4a69c0d4933cf2d591ddbcb487db5a" . + "72982b6860179dccfb92d781d471c8cd0e2a96c3c5920ab855fcfb9b4517c42f" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dec439ec71864e2a6cbf5d194ca126c364e650caa8d8beb27213a1daec21f096" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "ef6aff4d4522a0c876664043d2f0242e4da574f1f720652fdfed9241798264c2" . + "32f6c745c006e6add645e147e724760e5e7d08d7b99ecf8000f9e9b00032c60d" . + . + "57d6f9387780ff4a4bb80f06520885ac7b22185ac49bf0d87eb1c15072b5dfa2" . + "969a289969c3b626791114237708ece9bf2724015d1bdcc1e6abae39555d5522" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "3e16209c772050179ae65e499891066eb10a90a2b26ba8a4b55b825afe028d37" . + "8bb6be0a222b49082d048bce7850f4124aff34c285563292fba0d749be8724dd" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "030c24384fa62b1a86a750eaaefeacb3529e826a5e63f38d9087fe1af9da7364" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "7af6d9ca128a17a20346e05603638453e3cca2df2b8171e856665cc940b0c60f" . + "04f8834850aa15e506eb91a35729166ace546eab227d4099a96c4d61ed9bc3c2" . + . + "8e8cb6f716bf5f601ea7df7d0b7a704f52955ca993871076379b250e7b06efe0" . + "d7c6ba2045d944a35c11544c07afb3a667f879b71737051c8458a60dd951fe62" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "aba1a53edc45a9a4ed9a7301f581474f7d030c61c6e1666c618042d79150fff0" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f9b4288f03db68480e0d4127d7d5658666cb14e6aae77b0d3bfdafafe7b241e6" . + "99223a632ed8b8346074cf9c734e2196fe9dbfca597e69959fea7565d542b6d3" . + . + "263526b87b77b1b6d41a4a8beb62ac7c16ac81b67e5125bec4d9af22a69f7e1f" . + "4bb715388f5368b6df9eba668c1673ddd51dc53974186374644a410749af4655" . + "c21bf0e0ce8d945dcd785424ad87b322d9b9aef8c0181bc95983b008efe27766" . + "77b9c4da073ea5a969ec15addfb7fe131553c5823e44de973cd9da331a0be31d" . + "962a1277b7cd7adefbeaf0d43b83f85cb7cc175dde7ca0eb92bd07f6f0297634" . + "24a2e5a39d816660934126fba09c5bcc2d0b17c28490302aeef4218a4d626116" . + "f2f1995cccd823a31e86df238da06fe25a21f6ed048c39605501d430edad85a2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "30abd0668413c546f21f0b478408602bef4f1f8644585f957af8df3ca17a5838" . + "af782eb665fed82de7adb9f96653eef5c556d51c49476cbe810f4367137607a5" . + "6f9464919f79d723b31220a4e41a9f2bff09022fc9c93308db44c9401bf4bc5d" . + "5053e8b0cb6458a7e9d4fd7b1eb5767a43cdc9861e91238316a23596fb95393c" . + . + "da971e522095332bf632e279d72b02e8aea9bda3b00c8a3c24d5c9798e9587b6" . + "bf8e3b4bf0af1e10883386ca8169cc1a71358749dce8ceebdd863b7ccffc8b30" . + "840680d6a49263690ebe09642372c48a10b046a99856b1253ccb3d5f7e145dc8" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + . + "7c538cf8c4accf27797a7c0ab28af1e776c7a3651081904bd7a2c3bf608e8d20" . + "7fa1972b11d31d1b4970d24137f95e9db8646d3438924306a3e5026aedfdb066" . + "930ad076dd2e0d3a2d44dc1ce85cf3cfb21a65a68e4137df975897ae594efa54" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "92b36fcd31d7d88e3e89e946b9d5f823afbd124b24c116784aa22e80ce39c1ac" . + "18edf29a277c1fd577055b7b226b38c839c6b06ddff6e843088f85f81c691f21" . + "233d557fc1635e4ee216d606ae3481adca871c60077143d47cb2f531eea6b8f2" . + "a348dcc33dc60f36ad8836ab97b56b6434f8bf32ede32972c67f6bb57b25af82" . + . + "8c9dad716197b73e65fee814d51ac06c0d6f7557d9a44211f4173fe18673986f" . + "145398921b060994a31d4b5ccaf6f574cb8158fd923b544a2c93ecef172dbda8" . + "f83a28e6c07b05ff54c5d87150a186632e17376032f27d813076efb2474684fa" . + "51c9e20956d60c78f52d860201fa7610c44a77ec5f8de8853a04a3659559250d" . + . + "22a2e8fb69d917681d451f7adf0cce0e604346825890846073c02948de58cb80" . + "4afccf06f466c68e5ef81d0ca5eed397abf03df9ee5bf0a1c9d739c13e872c39" . + "dd6d0e3a59b09fb791139723305deeb9c0a0ca348ac989c91f69d12ac9b7c1cb" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e01faf8290288b8cd4bbc94b0649b7f0cf8c3d507fd4e544c08226c2a799a56" . + "2a499328477aa11aae0133085a7265be07967637b5b6d8277b508a4cd95704c1" . + "62a404cb6ac15284a1708f9c7ec63123c75cc93214772fc0c11948ae7303646b" . + "9626352e1d30e18959ad6d3824b7ef0747512d94005139134b7f187182c23b44" . + . + "a8f0c01a090e189e4eb58a49f0767efe412d6ef063c71952f91a1a3793d4e377" . + "036a74a5185be5e13d4f767e93735b29a885e04ccfb1e7e931cede414acbc4b5" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "ee354bc06499dea85bd80b0b0061507fdef54d561ec380089c21294edcfaeea2" . + "c7c75ae3313c6caeaffeaf748d4812107daa483d2bd72bce7ffe0f284a91ee6d" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "486dcb1ebade1349a71c73a4f584442909c690d26251f72d0c4089316768d8e5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5bdc60f4c08d1785acf1d31fc568a80e535a13ffda39b253c76885fd8f6f4cae" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "fbfaa97850c976e9a5dbdcde4d2cf6e10b3727884adc4c8c4d37e4ddd5f26d33" . + "20ef774c2c322c3312b1b95d3e3fee9af0fe37ebc0a6e55eaa911e826fa0e603" . + . + "391e662c9ac2d26e26b4bb4607d0748b787d45d5170082ebdfffed5fa20eb65e" . + "02bbbf1ec9aed6927bc16c1746c6549804777528965aa382b9a21a725b6478a5" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "2432c889bd86c141553758ac492c27d97ce9b73852b677b6a66ac8a772ab1b70" . + "964e88827ec759d88d215cc108171d09dea18d25e6d3ab6c54ccced045bc9319" . + "82d46754599c80424ec8ff5d412f8a619de2d64350fbddd612123b4a02c54c9c" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "895b385afa587c51ce726fea9bc6ae628570dfce342d3af48afac41347919929" . + "63f54b82af7d6a06fc3659c388602d62faa6c64e46ed2e4f8f3b002202fc1f3f" . + "c1b6c25e8a00db80183618fc88b087d254ce5a3cf70cf041011aef64885208f3" . + "aaf4273c67e932aa1907d2691284aced93ad55a1e598cc6f240ec9cf465a565d" . + . + "fe8f5571c40edd6acba429af06b31bdec408f1f195d85a7dbe4ae4f386c2fa99" . + "577397488307dd5df0110bbab95fd79f54cab24ed17ead3fe1f1cfb73e9b8d9f" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "05468049d3a715efcac214ddabd805a8a4da8d67b35326f9d27464bc7b4dbb31" . + "e7f0d2c2f7eb94c9eef80d1d880ad997f9af7b1ac3b4814e71169d26479a46d4" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc52ef2e72eb2f32e3640bf7e5d8e7b8a2f924e1b27ae192554fe8f1d44267d6" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "1661bd160df7780e807b21b4b44e6554c4a29ded904b67232fac6db44bd106c6" . + "4cba4e3760a3d4adf102fa96325803722097124b71899448d7c6745373073826" . + . + "bb82883f92046db294684778f37e97e0080fa48ce097be015f3530644d4081a8" . + "e4922aaca4cedbcd5c28f5a9fd42ed935c62529bb2c95f2512d1ad7e7db5a4f4" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + "b42cbc4e8b7ace409dcf948c2aed12db73bef7db8e691495624ea31cb975609a" . + "3f86b13927781bfdcb40352235bb5a69727cfd868cb5d7b8572784980213f908" . + "c5986b352d8ae7a3f569202bf62e544910244ce406a7010b2465c6a1b916055d" . + "7bf0d6aef51489464b4b84dd1a4bb91677e73ef59f6057d77adb2a64076f8826" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e15d67517bee368cfc1f7bf20096b9f48e9f335507681459aaa763e327ce7c6f" . + "f7e8f1cdd2a79988be03602f8a8e08c96a7405ab6ea712ae4c4854809531ed3f" . + "f4c22cfdc7b1ed6ec018846d2d277b9394e89de1ee5e12a9d95ca94125166402" . + "6bf9aaf55a114cdb8aa222688f454049a9a42c465336c2aa1c727f3bd59b33f6" . + . + "2eabf73eae60640e10114bc454f18aeaf84508960a45156c1d88ebf5a516ff4a" . + "6c6448f80a1178f7ce56f878fade6df5f02b76431dbb78070ad94f6c85764538" . + "89cfcde24f7bf11b37070a03edd8a4b79282ee645551f6c2767bfd342f9bc37f" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "48fb390424fcf6f710cc2264f826ff571faa80d929210b2382e69eceba0b2955" . + "856f259d8304c0852d3a76f1914594bb2d1e68f7aa98bede468cccc340b849de" . + "779fa350db16a25b473ffbfdaaaedafdf45810c5e9d1410fe1a69ec8edad979e" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4c2220f8e53ffb961bca175b18ca52918d763574f5bc7982a63fb4d1c0d1eb33" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "c6f635a4c5bb9debe0f510a54feff967039aa08c68b758bc2789c03a299da32e" . + "3b32323f01fc47401201bbeeb541af5aeb92f9b74b4d26fbf9fa5f696bf88002" . + . + "4bfdc93e7f6ed8ab47f25349e3122a974af3f43678d09e4274be61c3bb61e6ec" . + "49927ee84a74c242296bc46b415bc38a94904574f819da8951298e4e8e5e248b" . + "c04ecb39182dc99ae04ec864636738e2a6d9e99f01ab4eda3271fd3cc329a7e8" . + "fd4cc8799e987c7de57c2d885586631a8b3eee50aca1f57f4dbdcad7adf1cd34" . + "c317c3c6533535fa37c78c526449cc11d83c65d4b90130c9ee8d8302058ea428" . + "564c98f2c5864720b0a4406329d9ded6309d6107a3f1831fe000ab83a639f12f" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d23b998182fe421c4938d11b1c2b0ccf483c838f53afed2dc43e215f6666508f" . + "1f72250527fa8372f6b9f2196f5689c5dab61ab335488e521469e95327c0e2de" . + "485ad40ebf635c33858158ae0950cf41423f25ef1b7e4caf31731eaa3322023e" . + "c302d5c2d2dea1f6aec55425da3bc91525dff8f3b44132cfeecf0639afd2c1fe" . + . + "b1891798196f5f83ee2c65af36d8d6ecdec03ff3317dd7c1e6e3ac57414c590c" . + "5ca641d0ada8aa368565dca7be973f22e0d6972b545f41039040cff8a77bfb98" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + "79d88833058183da924c88a3ec614cf739d2caa08db09e6e482e62bdfd3efb26" . + "251af49c6f5de7d725b6fa2de979d49786be83e02f719ac93a4f7e397e3a075f" . + "65580228049a9bd0315c93bdeb0c398dd09626b9b5ff08aabbd2e95851728998" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "48b60524cebf6a2e001531d10778bed55439d99a72c618879f5bb60da911ff3e" . + "86f304ab84c71f7222dbaa2b079d0092a11ea4632a9577cdfa9d40f971d89e3f" . + "989fbbdc1f813ffe668ae27e585748e15fc6c63ef0d080c8cf9b323f7f765bf6" . + "83e730733534070b22c551d82068395856a6274ec8ee277acc00ea6b285636b7" . + . + "921d4750d8092333a60cd9d05c34f30cf90cc4f411f571d304cb3d5de49026af" . + "2a29f9963be29fdd1dfdcb9a5ba4a1c2a87a617653ac8b4b26087ac2b34aa930" . + "893bd24a1ecef0b8b7efb225a18c97e0c20788802cccbeabbf9338ddc990e2fe" . + "ca9bcdd6448d53ad56bdd570ab3ca5fd99b05c0e5bca4b67a893c6ed28019078" . + . + . + "29ce4002fc11fa6ff7edbbd464c91e8c79d01d37f9d1a44c3c2b9458dcc0aa3a" . + "eb78fd7c53b6b8b1413306ab32048672c7d62f9fdbb7c7b6965ebcd202b73acd" . + "e9952b6ed2105d12b3595c6c5d69b8ddaf3f5d6be7e834f13394a929abbf75d6" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be944dc74bb485e344b7c09493ca07b690944a9b52f8e6d4d4e2f6f5c1d0239a" . + "5694b41b18a3e3ecb8f046da5890a4790898f9cdd61d777901bd421ffe6c6588" . + "6686176fc79391db007a48e3bc66a648fa724bd31ced77a29cc8388507ef2836" . + "2ff64189fdf3909635fea8b77271dcc486938f1310949f42fa9c064dc1991325" . + . + "8766e4a9543603c346f6a9b11ee62a1e24fd61a0e1fe91ed2cb0a85b66f71b0d" . + "0225f715134f53f09783817bdde8cfdd740f0595456cc84e4d4ed909e75f2295" . + "5665231b8b74bd03b3c90ffda29f2cd4305a15b79d3cf8f44002ed39ed9c0c5a" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + . + "9001233b3c43c3881f05339d7e2ef2c3cf8efc2d2dc50cbc7e9317d2832ae8b2" . + "3549d08828ed3c4de94da50d128bc95d06dbf6170eae2801bbb43596f06e1201" . + "68554a20a13938c7f1fb09f90b52c8ef500e489f82f99995c7a4e114c991de58" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1988c5a5ee99b6f4c00f37715150f432668522209f65b7a5142203279301274b" . + "efa6988b498aaabcb1a4fda6431a15f5c4dc2de10925ec8c89fcaafd2f78b57e" . + "9117b08dc3f7dd9248c556cc16bcb2b5259769ed00bf30ebd2b2b3f77f71bd74" . + "92d5b37d5785dd530eeeb8e38ed9ed98dfc305771aac13955dfd84b64ceddf5c" . + . + "987a4205f61734712121ef34658b49f883e13ea346e6c2ebc731a9827924c36b" . + "059890d81748cb2644dbeb1817fdb6dfdd847c5435198b479136b18c1194ae74" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "2ce571ae38eaeb1e536a776c2e4421cb95b8040076981f6d831fd116c841dba7" . + . + "987a4205f61734712121ef34658b49f883e13ea346e6c2ebc731a9827924c36b" . + "49580c7f4577e43cbca4897bae4ddc8a3ea7119c8d30ff0ee4df08f588d3dd4f" . + "7bf0d6aef51489464b4b84dd1a4bb91677e73ef59f6057d77adb2a64076f8826" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a186f841a791e817ed30b6fd9aa1ae5c7717cf7de04732248d77f9578d7bd280" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "b3f9059ff0637dc82e53074993b80427fdadaaebb2986adff83b9ce035d8ab94" . + "cdcbea022b965934d80a5eaf144851d6518bf3846f30cd9f9dc298eb44d611ed" . + . + "ec099fc2aecb565cb669f9e8cd8b085f5d34de40fae9bd4c2c89c4eeeef62952" . + "c7c2da3458f2f1f5516764146febd29a2ba1d6f46ae395fdc3bc6208f4b8944b" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "46e88afe5b6f1c3c1e13e3c1d11ee2646707ceed8ecbc2c4aac68fa17f8fd6ba" . + . + "5950ea3893d00bf178fe8b0baaf5500c5e0b7872317090d028de60200195df0c" . + "2cc16b23182682a7598d0934e045663f444b843ed2305f2efa1afb254e245323" . + "fe578fa642014169b90988dfe1c79bbff71176b790a67d6dcb13ce3a49b64cf1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8b31cd06600925a393443477cd50b1186e1d2675376f50a1deca402e7adce217" . + "01cb26c0564d11913707d67613b09774c75c133c0dd865c2bc6484c3b9542e12" . + "67b91146e0b1f2a2738191823eb964bba670c2d109773f6b3f4aa96ffbfe2e38" . + "aa799eb60d591a127519c0db93d34c89dbefd838f6d0860937a7d0c7759d5d23" . + . + "5eed27d4df75ab537938c6f94fb5e4bae591a9bd7154a24adfec9f8832d88f0e" . + "7b1135818e3656861eda318c82cf799e8a02014cb941129c4abc2a6260be09a0" . + "46e88afe5b6f1c3c1e13e3c1d11ee2646707ceed8ecbc2c4aac68fa17f8fd6ba" . + "a9630fb437046faf1d2c807693fc8cedf68dc65f8bf14936451b4e6007df7c9c" . + . + . + "5eed27d4df75ab537938c6f94fb5e4bae591a9bd7154a24adfec9f8832d88f0e" . + "2b14d779412648265ebc52e206a871390ad426697928081d8ece07bb8150ac53" . + "5a1e3afe88b544aa91caf6f260efd3b542b4a7c062caebd5b6ec3df3f13fe37b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b54dfbff5c21fa3cd3b752c77614f15202ad662fcc81609e6d6780c82d727b3a" . + "0b215b66447d5014114e80b0c64fa52d7305306a75799e4241368e1176884cca" . + "5d6644e22189528a7f67896523e7f71ccedcb08d35d863010767a6a515c56d83" . + "f66ffb5b8d571dfbd4cdb459818d875023ecbea512b515a4608f967437a0c3fa" . + . + "559626d3c368eb28636b37b580cc89535485245611f96dea32b0b0747012653c" . + "d66edf8c478e102724fc760eca2baf9c25ed88d76f74bc2fa95e5ffe01a2962e" . + "cde2bd069b5e9772dd4b75e943c2d4429d85eaa7c4987f8862a16ca3ed5d033e" . + "b050691eb2cef384dc00660ffd5f33d51251d1f815b4f83565b60e4cbbe37860" . + "160399dbc9787afe6f6e18e635dddb76ad82e13a81acdb9ec719e1df3db44201" . + "0774b30bd258f146bc2a3392ffdf9e86ed7eb0843c709948255f76e0c36058b1" . + "6bdefe9cf42f1efa0821aaddc06acb84037a14918a51c17224430a9483471897" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "00cdfdb2a1f8fcf28cd4f59ded3993e366961cc1d7610f5aab36c880c85641bb" . + "6d359d96387a281d940046308746a4d7b82569ba922849c83a9871813592ff3c" . + "e6f0a9eac9f7a56e1533e0528ee0f5722f169b5b8dfc95463153657fcb8aaf44" . + "14979bfb656ccfe819686650c73420de29e2fc2d234da8d503644440218a2ddd" . + . + "46ab3c9bf05fdb1b772f8c5c3b06fa97bbeb3af4957a69c07413efe5500c6017" . + "65bbbb147383c7e7e396a44ece68947fd7fc2e4d55fd545d563872053a8dec30" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + "ad6d85223d2fecf2a728e710cd0c84ec6eb54f14c04657b98372b550a5be6b58" . + . + "2a520b1fe523bfaa8db18723a4a142c6ec9e5ba7b9b82c957a1b4f51c04fdcaf" . + "48cf9d7ad94e4f3cba77fe0744fd2f7345abd714dfe547246afdb1dd8e3f4a52" . + "b442025d5132ec40747c29aebdc12916cf009a47fc13942e6d35948355626cc7" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "65c70c5e9e4381646a0355d8103a13d16cfd9139fe429d827a9322ce639f64ec" . + "461aedc1c8cb6eb3844a3d95dec1ac9b7e172564076e1f3f533403fdfaaaa49d" . + "b79141b78047a8bc2de9f5ed1758a4f09b3afd53e24d8d215bf74ad8e4e9fe02" . + "5e828fe09b20f79479a16a14fcc8a0a8983992e6c788ac48bd63cbf90943a66d" . + . + "bfa15bf40de2365b21a2642fdbf24b059211486a5fac9151ccb6e1fb05c66d80" . + "27246f8192b47a549efb4e4f1516f6c3a13c8ea0fe49c1c3bf56c6efb670d419" . + "9e4c2bbbdff78dc4d3c58e9787975bb36aa609e108a03bbde8fc89b78a4cfdc4" . + "91593aabf9063476f9e2c210a00679b4c2efd1e92b12306ab9e67e2183f5cc49" . + . + . + "3cbe1cec2a6bf1f80a377882423c1cc920c361f97b74197a448e37f45a437cb7" . + "f4507f4415d6d79031a4a8ecd0e6e0b41d93d7547086e7d71a8a36c414659574" . + "2586c19a354d09959bf49c81d8679e3ee48278b2ec81c70f335bde4398b19ef2" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7137e64cfed3de3ff21b4fa5ace961510ac3e62511aa3afd9ac4a87fa35ea53" . + "40b20e422ccc01a57ce88f8d23258ac836745c0f008373f6513f642e58a880b9" . + "f8f635af8713cb3978398f00fc4e668ff744bf5829a785e6d67b325a4404d53b" . + "0ece0e42ec0d002cb5f4aa53f9835b1f3f69118ad9fd6069e9e6d27c45e6f9ff" . + . + "962da9bd653cc0631acdf2634333b2388022fca535c9c8322d32936d4fb0a9b5" . + "420bb0733b2b2e91d79bec54f05e92377ae6157acbb21b552a21dc4d9a7b9875" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "c9144c2edb951273e0d90ae7299e476c8fb5065dbd55b2f02d4aedbc641998d6" . + "962da9bd653cc0631acdf2634333b2388022fca535c9c8322d32936d4fb0a9b5" . + "11e1fb03ed97f5faffafa6aca3e22826c84a9ca1043ba11ce9050387fb750110" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3f5a823e6135506a7a2e2517fc28015623f93652f78a7fbee60edfec3a2dfd0a" . + "c32258116fc5820123fed50bff6cc339d905df30fb9474f7cd5b5abf5f7c604c" . + "bef5a6bcb22c37c0f4183da20d5ac40b2008366731fda34eb22d24d33227e952" . + "fdf8197675b5801f03059a3280bbe4c006393a3fa6da6dfd005098598c3b6e51" . + . + "9a24f114e1cdb8eb8b6d6813c11dbed1aa4e82182252f0535d92a41e8718df36" . + "4fc62612e99d84c68df27d095eaca4c8e16a8820aae588f5471c3815abb8f2ea" . + "03dec51dfbd92b5ed118251a6c68d3f31d6cd2fe486edf5be64447563a42e02b" . + "8eeabf6dca13412bab051f2bdc465197809e9917f0a85fe3da039c15e9536ff3" . + "e9f9d3477bd4a1da46c03305c961126bab73b6896c2ae22d948862a8b8f8e8cf" . + "632c867ada0a6977ce4d71b06ac05516715c7ac1164a2b44c2a17b569a8181b0" . + "b5e86cefc9cfb8c972b2ede02131e8a270e7fbc4216e7be80bf800aea5de029b" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ec0e679f9a4539091dec7d7c60583b4aaa997794a17529eb197d23bd06dc8413" . + "652683217b6a7f2e3d8cd12a1506b3fbff1d1f12eeddefba689bc9f01183073a" . + "bf0e6fe940e6c4d90c4adc68c0b806084fab74be63519a34396c630c0f60f0f2" . + "8b088adcb51a1920dfd6c64867b5e765175981537cd40b7a6e3bc1014220441b" . + . + "f94b65664723fc0ef798f1746475ccb451e3f1cdeb91fe97f8d9929f6e6a8bac" . + "c26687c79cf4ff309478e285b9faf66b581be1ec1873396287178a87828efec2" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "d895bebb04cd012d596c7f3571078a6369833d4624c048c61f30a7967033f730" . + "0f86e74f23791a8369ed58196c456b42ac931dd85762cb9838dd6f9ea1c49553" . + "eb64c169523878e7790612a4cfd2bfafb12bb302bded6a28687b039e26bea05e" . + "ffd5fe7962e3de478152de11be4aeaa86c20c6c8be80f1cf1da3e126e407820f" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "389476059d1e9ce4c97aff4c730bfc708c84e2dd37486dfeacef001beccf6223" . + "d6e3df261a3b71c66659387489e7887f7738bdedfc29ba5bc1e32a73cde18c9a" . + "27c36122a32a317aa79ede8615ce81555a574527f69a9e037c81fd4213e0ca92" . + "8a0e37f513ac5c25b3f6ac6290cb5f1aff303e2e554b5a0e20b4d4ddae0858b2" . + . + "14c2c31588f412ed4d5c03e7ede5e690b71222cc944853bc219869de83d20557" . + "13e35753455445062108cb08d7be5fe0befba2f011aeaea2ec13d9bdab17cc95" . + "03b7d8c94fd575508ffcfa9b3950a1bdccf65b507bcceb001ced5b6f1dbb6063" . + "bbacfcf65b801fcebd2d0db2c09f64027641457fbe7e89a7100f4bc543c4205f" . + "14c2c31588f412ed4d5c03e7ede5e690b71222cc944853bc219869de83d20557" . + "8c5802a6a4f4e04c48a60bf4e2c047c5952a8ffb2257cfbe3791c4bbc8e86b5e" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2a36f5a606ec6048aac43b1e128925797699a3c38df5cff02306345fc04c9676" . + "ce7f098af34cd3678ed8511ed3392c594f54a1cc92c37c656028edc0b42b6f92" . + "572b99abd37b99999918b6ce098289ec2b69e1ed6df8c8338fbef14b8d5c963f" . + "d755f41f5cdce3dec45aafd3c243a03c35cf849f620019a6100e710fac44e90c" . + . + "80a8f13cfad76cab45a15d6f0b6124b2bb66f6e0c186fa71ca51d0328cadd02e" . + "134e22782f930cc608bbfb42822c7925bbb4d57f3ba28180b00dbfdcd4c1e3fd" . + "5665231b8b74bd03b3c90ffda29f2cd4305a15b79d3cf8f44002ed39ed9c0c5a" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + . + "b27b93bdee96779cadb05b3e2a5893c751a3916e74f2f5e69800a519a9f03d3f" . + "68e68248a6c423387d8a1c651c5f142c700bb1353eee6c8302a671938db463cb" . + "54814cca62046c4a31d5b9763dadbc69657cb9e39ca16d76ff4beecfdbb79fab" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3da39e2fee60521488a4d2203f1ba20d09023f5a95921f081a75ea45db35c6d4" . + "78fe9b33cafe58c172914578844edb2fd35543ea84f346b4fc6969012eb915e3" . + "61764fe6e274bb861e181c7b6973dfce79a145742f2a042cc0053b6d5d4f3aee" . + "fd1d9bef559201d1f51a39e7cd3ee616db5e2f69198f822780802404798c4738" . + . + "81055db35157a6d14343142d3bcad03c78f8bffada5d6d798d3bb27b401b5d5b" . + "d18a18f6f31602c64217f5ed00e187b6b7172abcd27e6d3d3b46d04de2ed6a92" . + "bfbdf5f1bdfe8257ef02b90ca0807c9f0c8e1c5b588a58a84288930223d5016c" . + "a1ecbf1a0e419b1aa9f6b6125ae0477257bb294a58a6698a3f59de3555a854f5" . + "9dbaa145fdc05d951e42a4a34df6aad15e961486173588263428889c929a8991" . + "f79f22281bedfc12ea756bb17d67d6cd2581c9c6596a16ddf76dd398509b8e85" . + "556fc6437866aa8ce4533c0986508f49cceb772632580e7e2ac8e2323ac79eed" . + "b61f72611f85d5d16e75d10240d79bcc3bace79daba87e0e40b52bce6e2632dd" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1fdc5e3dc8a7ffba05b148bea383ae9de8b618335185c80db705a186ebd74b63" . + "0f913faaa97e842fa3618da544601fad2a8db4c5028473b4fbca28bd474cd481" . + "0e278af4fe12e0f8216937aa4b5cddb60f126dc3861308d1fe485d055948bfce" . + "20011061425d24838b66422beb2f5836a53d8aa98a96274bdb633a7272cc89e1" . + . + "a16847369123ca7f4d8003cdb02e2f99c34fcb12498f20877cbf4b6e57235f82" . + "89d5732262800eeaf03c2e9c44b42381f205b8f13b4e44e9ebd54945b24fbadb" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "0c322a8fe3aa0904f3ab49f65317d8d020dda46e9a482ebae51b8df972e11e65" . + "a16847369123ca7f4d8003cdb02e2f99c34fcb12498f20877cbf4b6e57235f82" . + "2a09e26fb2e20c65b6043cfdca132ab26a263f482604c9a4567908fb2398af50" . + "89f16f2511f5e8cc212f27859328b20a5fe7a14ed1af6f93dab1c56c3d6d0fc6" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "948eeac4ee5319d2915d6d1cc46e8e268b79214e71490082cf02912aa02bbd16" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + "83ba88b6d2addb1f3110d285d05479610cfdbccbbbc1d75f50f1534006aa271d" . + "7f021d70db4dd080eca5928b9521ec37ac29750527d30a70a636039220b6c4f5" . + . + "f033a81754a668f8e6d4105c37f4a6f6d30f64a481b4424fd36dc4aa982e40f8" . + "42ef6efda44cb6274335a270d88d0066e97f7bf52378782672778e0fc880fd64" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + "49c26ed06c543b71573914fadc4a80dbbc3bda1913b7b64b97a7c2f902080dac" . + "d3c92ed7cf8bae1337dbe2207c19614c2e5aa7f0a25f162a1250126ab6d4fc1d" . + "a7fb4646a2969269de424a7f34171e25a58c37d5d524590598411d7de61294c1" . + "f91d80a2b96de4e67651ae845528ce5c39c004c5ee6fa409c35d258dbd21224a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0b0e1f40e81d51494debaede44f8f5353549fead117f0716e68179d75ef02fb7" . + "f6beb321ce589bddd74c40eff5855fdc38cb276a70c057d06bef507fcdb5bcdc" . + "8d50e5e65644c2b94e9434d116545b629d0d31a80d0dc3f85947565894410a4d" . + "2a5c9f08757a50a4c314b0002cd9a9a98f7743d2b8baa3afc85ddd1b20deb095" . + . + "84bfdfaf503bc460671d40b6fe350a7ad06b836a617f81619c3bdbdd4f6cb9e6" . + "6e9a1db949ed5e7ebb6dc7cb38e6228fc19b826910f0021f2e97dc8711108ca0" . + "ff045805136a1d471483cd5245306990d4b3e466be9e082dc383abd350ec8698" . + "64c0695567812997cdcb35797557b5490b86eae30fd2a773faa27feb04a2a491" . + "eb652f043457a21ffd25dd939bcc0ddd9919361b88cf88b909ee8b5ea9119eb3" . + "c26c67c874a9271be8718936009df32eaf05d5e10056edc276cba9d6fc59ec44" . + "dd6f0d4eff993f50f83d6f8291ce45e5db9b7f9720ea9e38598d8643832831d0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "04fb12488d706cb9317592b20ed37b94ac0e208d51b4d5b9e11b201cafa3f982" . + "d2c31da6fd18ff3448c2fc47d3097376265f1e2e215eac0e0bd45b674ef54602" . + "533fb939f03204caeef635f2e32cbc2f8a4a50a800b36488fadec9ef30d4f00a" . + "c9269b5b54dc4a7206459c95cb0c8ff27a3ab268bf5d67fb782de979be939537" . + . + "2df199a58bd3f6cc751ac002fdc3bd9a05749ad38069a4c8edce969e4f277bd7" . + "e51079ec610bc256f6353d4bd95496abd752bdf08b6c6d9266bd6aa8b2787390" . + "5859536b6dfd0b3b2c334e2b7f9bc7a247aed7a06144d3769ea60e0ba1b076c0" . + "300e710438b7b1e25ba243d92a07f63a3e4f9ae8320868d9076271750e855f71" . + . + . + "bbf9becd063fa6f6bafbd114611d40b97433fff3fe5f7ab2600c2b98ea0d3b6a" . + "3a2c7fec281c8c9b69bef3390ffa7bc49fde463cd7f3364e19bbd4437814bd0c" . + "61bf64ccba3329eca4752808ccb9a3146e42c74d483f646354b9e10ad001987b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c64a72b2f1a52ceb1a57c4deeb85ae45a58e37c28a0fa243dc9fd8fadadb5ef5" . + "a5d4a240cdfd40b74673729ebaa241e558e9883b8e7375ef58b84729ad6e54e1" . + "85d4afa072151af8e184a575d80ce1f4a267d76d5f381294e368e6295d04a8dd" . + "380b0bae5b0c45dd66d70654520bbe2178d9e83f294314a441d428c8b46cf342" . + . + "b99939c5cb01e0544667f4d740bafb745737978f7f0ddbf654bbc0cd7f091d8b" . + "0e09e0a7180dc2b19fd64abc826fb126411656a805eabbb339d502c354920d9d" . + "8779724321f9659a702760a7391691d00aee38cc4c581a695d7a5a96e0b3ba71" . + "cca5b40a332e7ddbaa0a16f94b9e37bcd5ac77c5a414083da239e03d4908c35d" . + . + . + . + "264023dec8368c9619882239872f90676cef4adcb3c5d43f5f3a2c6e0ff689ad" . + "230c1ee65bf7b51e3098884fdcbc6829a3429830d00ccb7adc2e51d25ecc09bc" . + "61bf64ccba3329eca4752808ccb9a3146e42c74d483f646354b9e10ad001987b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "42b816b9e9f49bae724d2188330de327768ec0032442c4d5f5e80ead23032e5f" . + "a47a6e747738c7617f88b800182e56aded71a6575c0f8b8ae6ecec82557472a7" . + "2fe520f221775872ad04b1cb28427c4f6feae6cfe55a03f899d0606c6d9666fa" . + "ef4a387ac6de622dac327bbd93cec9d2ca923a189a40e10cfa40d95628d3a750" . + . + "4b1613fe3aa4e69508b0ad76d9f17016bbd7bb4c304ebcd9b6a5a1298b950ed3" . + "8be0fea29160563d70029bd82791b1cc483a49fb6511a76ee1c87d9565868088" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "a168aea6cba76a59d54ef38b1a9b45340a7900e7edc350c1c46e01bb06a3c542" . + "e69c28dd1a620bfcac8f3f6071b80882c15fb1bc775000966ee3259323e1dffd" . + "c14a90fd7562c216b9ba5eb4ae51a2ea2eefbaf53d242b708fedd86482cfb73e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "03184ce7a0eb0a5eef6845f50f54bb3d857b31dcf7c5f651e871b7745b2c2981" . + "ca9bcdd6448d53ad56bdd570ab3ca5fd99b05c0e5bca4b67a893c6ed28019078" . + "f053d1e5baf36fcfccf642caf5f96b05d890db518cdec2bd7f166cab449ea8af" . + "212448d0520c0c4490aa5bed68d0a8d8f8f4385fd8a98662551a08598414bf55" . + . + "351f8b7692f3c3194150c286bde22dd2136c22c5f25f7fe62f68de0214a956b0" . + "9b5ab2023d70f4bd56be1761a66a5f98a58297926dd33525dca091c8084ddc46" . + "7d090b1d7ca951538dcbe500404e1ea9f0acd11475cf709f85198aed1169d39d" . + "daa4e14920eb2f029899a8ca96571e1f2ee358d79e9de588fb02759857665eb0" . + "01c818467e64ff96073a56b4de076e28347a714aec35676fcafbc18549ba7fac" . + "4af942902bc399760215de049cc558c6bd117ebd017fe40eade332beb4403292" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c6d015356cba013db54ec2efc36fd8184134a8de586f9382e1bff45abfe5a609" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "ae3019d17637c0ae2cfd2a1967661a45f02d9f31f8a682cb8e64713aada98d42" . + "597d708fb087750e784fb62654100d3f65062241b16ce96cee4c9fa7441b9c05" . + . + "d3ea6e2373259fb05dc5d138dabbbe8af2f6b9acfcccadad508c6f5900f2e2ea" . + "62b90d3c5db52ce1b6d681283d0c64417fbe1c37e246b92ec355924908597736" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "3d2801338181b8bf15fa8c62780a597f10f3531e697aafba9fe31cf38c2ba76f" . + "690a9946e755b3516efe67df0ed1fa326fddf166ab72f56bd8e49f49bf801714" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0e48ad993b26db8d3f397d7c755f695b9ea2df066ccce30abb1c10277836cd0" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "11290d35bc0cf2ce65a4d017685ec569affcb54e45c70e146edc4d5931b31ac0" . + "c0e416fe232b2d29605cf1642a6e0e5089c059243347164fed4505b67b2bca86" . + . + "3babc37a46fc5fc438256d2f686d961d00281957eb923909753116eb59f930e7" . + "2da2c573c3b4e1c666f8aa4955ba1d46f9ff01e8ba7fb6a12861b9153c446263" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + "320e950a64c810d55934b949a586050e6dd065220d351c64d973e5076c295538" . + "106345f9568a3f80d0040dcaf73bac238fae30a85dfcc630c25235b6cdee78c1" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "31228ab04027720fde36af392fee6eedb2806eda587857ecf0ac3126256358f9" . + "f388ade5c80205d90d1109cc8d897fd16a13b74b0cd992ed47313c4091620035" . + "8b0b317fd6e28195a3b1532caef1afb1503265d5eb213b9002ae1aff512421c9" . + "feba4543120e2403ccc6f1e29549878d0e1deca1996717d4e1cfc0a2ab73e841" . + . + "b8d93bb35f09864c67b09637aceec479b03adc8ad152b17b578f6681a9e523e0" . + "7ebb0607c4179b1422d897be12e9d9d2fa6807c761d7f46533db063e469d0d8d" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "3f5c7c229d3fac179b4899c9041c2adfa7f9291ebcd566706517971e40bfa3a3" . + "1cb3b4e81a663444d4860f07796885cf52f891b55c255c19b605a4b0801140e0" . + "0bfa532f687324de4418de0fccdde14ddc611ef08fa59a2216b8173a30084b00" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eab146a8c17330708de1ebf45b78fa60aec3bfcde163cc2a913b270debd005af" . + "b8ea923542675a42ff8dbd567405b5c4720137c0e0366adb447e8b4fac73ca8d" . + . + "3b6a39602d19f6d1f73924cb70b609a1837d8cac5687b86ade1cfdb334b15c03" . + "973f6e78f7073f2ffa5dac05f7a00a9bb1e5f16b27dab1f4f8a45fcc6f6db97b" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "d5ccbdbd283225eb58cb3ab86b99682659c2aac198232da415dda26370ac4b8a" . + "0deac5d0628ff30ea72156b70661cc7de41833b75fa3dab459df1f05292f6ae7" . + "2ad336399c482ab9a7cc5b80eb80b48e2851b5d7ae7472d2a7cf3ac185f8ec81" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a5d889779dca42d42de65d2ac116ed6c405a041a35abd0865d574f08d9581d9e" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "d4b0f748cfe5e73a50dd326e53db8026302a67232b08b14b98f13b0e7c47f9b5" . + "436b6572448623d24b07d5b40963b071270df45ea9f33b4059cdd0c344996520" . + . + "3a0b546e2801a5a9774f9d9f8e829a846be8ce1742d770e48b955964c3630125" . + "7038a3ed96b31a16a33a82443059f4578e893c0c3ceba8647c90520643f82533" . + "20166b30dd3d68b688197184fc40c9523f10f7d66c23faa013c5f8cc62fc7ba1" . + "7ddbb387a295d71e921ee59c66e7e2892031fb42bf9a89abfa03f4fd2a1ba90e" . + "ec18c4f867a67057974dea73cb6971d27f6b1dbdfe4258c00a28af144e2bea4a" . + "4a8bac6243f7e0f640aa9fb121c5db60f633ac38dcf9595181b7531478f0ac76" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7ee129d4c311375d60d49bbc3c3cc6d4df2502c67e88561ff5a1d0e1f2fbe3e" . + "fce5ea48e2ae7b6808e76aa5d4d770e65ebe96103aec5603727cc84f0bb372c7" . + "7876ae8b168828aef712e8828d268a81a2001d2ed986fc8b35026735070c6004" . + "a7ea0210d6f86dd285dfb8bbb9de20764e8889ddc6cc12748321d767ba64260b" . + . + "c5f91f2977f3bea1114b917d44c27a43af87dffe4aaa5e3fae5765f82841559a" . + "042f55eba02fbdaabbd9a6887cb6435be4112c079fdeb7bc09ae4c3b3adaf04b" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + . + . + "caabe3f6abb0b8d4f91f9817ab528d7265048526d7976e91ade56149689f9f3e" . + "9061bcffe6ced2e6a1af0460dc7f88927ad9d99c5c827c340e703bbc8c8e55be" . + "3dbfd1fd173f16965f2998bfb1265d2bcfd5b32ffdb18bf7fe606827261b3bed" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0b4c15717f91f8b390d8e45e766e1646e03d562d7bfe2c397db3596e210ad9c9" . + "66764329ae8331bfbc1666fae4f69b1dd72f0377e1e5bdd20df0c8c16e7aca31" . + "a614766670bb629c7b7e2ba133cabcb1f76f13861e6bd783520ba979bdcd31bd" . + "ffa105b5f7af275e4cc49c6975cb697a077455556a43626bc3b19dd573f7afd2" . + . + "720be008680f4439f97d23c7b5e94a184eed825b5b3586590768c119846d8e4e" . + "4af985757efc46f5436788c8fb6472f8df7bb67999a572b0057f5e48f8d84712" . + "c2ce16ceca0f446a416175bc7a27fd315bb794bcb57d4a574ff8f9bd92660a61" . + "768bc869f2cfc3e24ce1a106febf2e85737f6bab18417f13b0fd59db0f284f4a" . + "69b821b81c53a8cf2f975c876dd0a4c899fde65206f0ef71acf9dac712e71418" . + "966eaac117ee20343b05b6b77cd238d69033b08c23642f595e261088c63d81ca" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "62e3e6aec751c7f4b3e1309c34a1ded59c56f0d067f4c3c50fe8a9eadb268f6b" . + "bf07bef018b7f81360bbf15e5b7acaf3616c0e5febc00d81b9c3928a98288346" . + "94b3cc398ff6631694c966c57e77ff621684ea4dc6e2800f146d6b91f3ffa6c2" . + "0972b02738071f3dc5f4d920ea380f3d7ec329efea9bd0655357ab31161388a9" . + . + "0541a6d4fb03350180d63ee62947dcd88b91f31d17f57997ff1a11abf6f831f3" . + "3cefc38600c9e189a663f9d0d94ed2a7f03e4aef57e868ae87c385bf091ead6a" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "e0060bf4a1ede4f5bd2afcb56d33ccebd7e4a3e49297383bb70a8ddb714c761e" . + "d4c6ce94768133cb460571695909e9c53c7ebf25d8a44b9d4b3535e4720aa94e" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4fbd8fb7b76e463173a75d2cbed8a10ce22fe7b45f8be0ddded03741ce04d49b" . + "0bc1a3b4b9a82fd7acd3aea657bfa5ead39a69121d02e756801a62e850b2d93f" . + "9496a033cccfdc4321dba7afd663133ce604bfc7e5d635b3a6f2b03801db061a" . + "9c5f1e3d15f35eaf92600ea2306daa239b0a85e8924b902926bda1a8e2899a3e" . + . + "c82dee26be978a1032adfa30399b4d48a13cfd60ae5f061ec26edb545224aa91" . + "93a24cdaa68d990765168cd5c011b530dc80f41d8356173133b8c88ebdd13b7d" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "2f3d62e273e4121d5d921e12d76569b9c84f9fafb470bcf690c4a30a731d9f61" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5024d74ddd657fbbddf935434b1140666cf3044572cf30013b58ab531026b81e" . + "413ee27c59888ed7d62b7e050154789ee78161800db211a8c9bd43c66f824ed2" . + . + "993508046191308f32e30c010401231dcda208077944a42009689f00f870cf6c" . + "e1ead5814a1f9ef2e2256ea4ad06270d20153a50401fd74649f2dd8f583ca8f1" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + "9010c0b824a082fc5874134ec485c2b5be971c5ba6ba4d2f2833ce9e8ef092ab" . + "e3abc53e948b73c8a2da24c43903878f42720618a3d2051f7c071a1a126d3e00" . + "95a430422e70cc25e658d5507b15bc67fda4b3e2417fe505193156db4c63cbe6" . + "d3357bd610c6f3a7dabfe0950fb7213e75b61f82f46e32c3339d224538a2dc5f" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e92d09c7167b37aa8babae398e4489b6a6900c8a885c9d4a7309e9df890d2f0" . + "96dca0e070b809d4d8c2a8b3d48fe92796055f9674416ab81e34ac20acc411f0" . + "b016788ad30ddfa1c9db918f722bcf72ebbf9941745d6e746933b0e7b5b0ee5d" . + "d9380adf8c315ec1ce6d56cad872d1bf183bd9542d195139c350e5478e5c43e4" . + . + "907125f4a66f159fc815bfa0a83a129c34fa07506cb1e7973cb4e30205dbbc8f" . + "1fc38f0548bec159a70ce4dd24d6448d4251517d701f8ba0815373dfb0f6b357" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + "278659b6bba5ad7c9d3c7ceb213768f89eeac09ac44565329593f7bc37d857a3" . + "9d164d80e4d36ae76a3aeac2233aa2b5286dd17f5d28f25aef9568a021810574" . + "18843e6b88751a6f83592d9d3de1c9980ce091c75695343f006c50a2ed84f4c3" . + "ed58d78b367e67b40d14fa834a0b5c5b97bbc3243c73636e9cfa0534f12880a8" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "af6ee2c97dc055d88474e732e99cfd3c2db32419276961aa33973329a69f8e6c" . + "26d77660454226e5684b428df12fb6ea98ea60874dc1c94fef5bb1315a9fcb29" . + "233ca24ebb02a2690b4c7a0b324b8707ced29b5278206c1d5c0c3b6cbde1aae7" . + "ebe36cdbc1de767b73876a320991de7ffcad5b30539c79801c3416381da4b4a9" . + . + "5e792dcd38343bfe1d8b6e865c74d24b5af043d1f250dc64c90824d50c0ec042" . + "bd04cd52266888214e3114a0dd3d561fbba5b0a1c2df09ab2232299ad4e3d3fe" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "69a2077960df86512555e22aef48d93174665e73d9e49f7cc077347ab7a9407d" . + "b14d231f235a098ddb38eff3f55a3d781ad45bac46984bdde4820520323c4df3" . + "f0c9b40f4e4e9bb86fceb04fc51838d9f241de6723f2c6b00ebb9c1a0f8a2846" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8367465bc0bf1b79b41575e2411c492cdee58d05c384d8a399f4c1e2fe213452" . + "8ca2adba45493ca8eb3368e57b8818a3876dba2633600667596404c83f951dde" . + "c97d45cba483cc05f3ad2e0aa71ff76d7a994af39347bbdb73e0149e7718c407" . + "f76c544473677e731a552e82ff5935c8e6d8ba9272fb516ab19966388f9e7319" . + . + "5f701ce6b53f47210afccf9cc84d9b3e0184a4154cccff4828951157d27a9fe2" . + "16b09b450405d1ef6657da405e414bbd733d8f2f07e79a93a50cf693b303e5ad" . + "ae17be26003d0c4eec4d541173096a87ccc642e38e2d344649bb7686382335f4" . + "eda50bea4712a4c052c451510bbfac7e00383dce33209c0ceda5ec9571d9a6aa" . + . + . + . + "0c2b711e77b2ec1b8102891d14fa520553fabcec701d9d4db83576e138241d76" . + "28217b48f6f0b6d4c3988f439c356a621c77ae591207c778873090dfa93831cb" . + "f8f225ffb1ee898c7755e509023eb2ccff5b4beed048a1bea1bf0103e8af415c" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "de029adce00c6d757948a85ca7de959e554958ba89981806c67bafdb55c61530" . + "81a86fe2eb07cd9254cefdba514ce2fb8d4997d2abfb7b056c817e4fabd752e9" . + "daf30b525451f08f9d9d64e8a9c2cc74d7a403b1479e065d3e053d459f9e3f43" . + "ddd744bd2985e6dcdaf5a5c9e9d3097b33ad20c5fb3d0e9eb25fd6b17584318c" . + . + "70156da15152d10a0072c4c039b9eeb4908d703d683b3359c436aa9002f5e2af" . + "7d53861b44bd1b00962a4e94a223790bd74802140464b9fe91b98c4f4f66703c" . + "51277d09fe5231598ed4fe1563de730d67f98676d2797a8986a1cf3f077f5ca9" . + "2fda7de22578be2f56054d8a7c733ed0f532c09258936be973e2849c49b0aea9" . + . + "8969ee6182b2ef6b2bb43f7ba284b697782476df2031b2bdfb133b45a1fad355" . + "8ebc4dee3ddc523b748dfe2208ffb7adaf7713c3cc620c16a151514fb0bd8093" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7f98debf55e3ed222454fd6fa0b5f2d49cb76dca4f4466f8b78c970595d13b24" . + "df0fe71bae54920c7451ddc7534350e834ebb0b724784d42ef6357f5292fb1a6" . + "f9388fad4b85227f60502773e790e39ddd5cc9aa8ac488571bb5e99dceaec705" . + "457b8148dba144190b290586473bb31fc2621ec1d4c9026854515bed34435c9f" . + . + "7bc753e271071aff9619cba2a0378e28faefba3aff90e815861c43bc40416def" . + "74dfe051d6567e786fce8ee6b58095ce6341dc1db37a73bb66f4fd7d216763ec" . + "8d4077e7a697866d311c0c1c6766720cb6b6e91d1a53a53d818fb23f7dcff194" . + "4ae69c8a9d4ffabd16c72020c9a09f3d7c51167903c399eaf3be7b3e1f72bd1d" . + . + "11b7b11d1a70c8c6c09929d4abc1166dd25e0f96f5dfe6b09380ff88a351f397" . + "73bede4d08a946eaca8c56123c898bee908b954b5545e8f6ee5c706269fbb2ad" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "17f30dfc8d089248ae0cafe3273962b70131b7fa462ed6846be8a452e5657dd0" . + "19f5acddfb274fdaa5e2b00364054349b1e0d96a308924f5e53101b7e8c5b78e" . + "51e0395f696e2390d4aea2911d4d0dae1b19061495e96a1b0f921fecd8a987a5" . + "896e9ab400741781cdea86c266baf07211b46678c09d561fc074f5d899c1381b" . + . + "70121e2dab5738d027714b5768196962b140e35c78340adeca0206ed8b10b35c" . + "e3ae66c50e69949428b7bafe901aa296837322cae1d3ad9a2f06466e537bc629" . + "881043800dede38e3b0a881de317a86909f2e74f1264597477d7488740e0261c" . + "e16581407cf0b5e90823f583ab87ea02b5907ffd894726277e01e2ef240b45f2" . + "70121e2dab5738d027714b5768196962b140e35c78340adeca0206ed8b10b35c" . + "297abddd75441554aa6c8fa3df119b356dcf46e4f822982908946d8a63d11cec" . + "d95cd2ab7a0c3d7442d769addc8278adf1a1b196dfa55c5e30acd0d417d1b7d1" . + "fbf4e657294924acca4862173ee31b86b300ec94f8c3e0cbf291c1c1921f35a8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "229997062dba8cdb6fecef69283e975c72038413434d4014afe259d18832870e" . + "e80e85c742e140563cd190a68b120f9e96d6c115e8a6159446c2b5703a978b81" . + "56d01c8b2bce0bb86b0f75f28faf378ff62711f4c720ce43eae0876a5bd73e4f" . + "3abbef813b68e579ece64f9e22fd605a3edb2b1ed216697cc2cc363a08214772" . + . + "ec4d17bdf0601baf870d9f642c7bf02d8add497e1bb5bf31b13d82e3e2e682c8" . + "e494f54249737915b7aec0d00b4461e8bb751ec65024e9ea58620ee13b67b880" . + "932bf52cf333815b5eab68b7d94f5498473feccd96c06283fd2329eb5ecec592" . + "788fd86474783db4805ed5b021d28c51b0a68550074b74812f593d623852842c" . + "abc871d90c7ac252e00551b58fe711b3b49ea745e7d3544a711ad1cf7494a487" . + "f3f0d37754865303593ca042aa374a0367e9a3650c052387ab6058103941056f" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ab3a4189c842d93bd937719385e466cfa870e0dbab5fadf3ef4c828917f9ff70" . + "f69694a440d081890aed1b01a47f95625cb146c159c0e45154cb4b0350b5ef39" . + "d97e1fd659f72cc3ad9a556141adffa236fc3439a86d727d56dade366a024dd3" . + "a74012d20ed2b59037dfdf3987d0bd8f39dfbc2d384536990c02ca19302cdff1" . + . + "6fdc11ef2bf933563930c949ad7855f1d399f503b262d70c51cffd147ed034ed" . + "abeead2fd77a1640df2f48126627ae603d8eff65b9236031a0782215ac794e78" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "818316e981dae6bda63609085cd46b766e6ddb0ec8b2ce398f5a8ffbc017e371" . + "8b50df34afdde074298e752466dced06358faa72572921ef175d3531da135d9b" . + "4b349abcd23cf570152b1c75b656dc79a1a6e9afb700f20b2f2edcd9b54d5a9f" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "816255c78a6fda4752a4e158e016f1e5ed0c27529e4528669cef5b4949434e04" . + "16ea7535427424e2465245ef7079398a0f3f4df1485d0d6f9a4a38f77814299e" . + "d19563cc56290d50f2932290a7c3b4172315fb67ba20deefb59d4c42ea7508c0" . + "9a8a09c245ed5690e2feef6c626b8fb97b03b3f2b729592c7ece38bcc9ae32b1" . + . + "8319576f4f61c4be298f83910c78de972c7d4d80ce592dab9e01a4043b11db21" . + "0b1aaa359cb534edfc90fd21d9189aaf1888671438ceff19f6aefc1799641065" . + "6d857d6a840b50221c15320740792e03a12280fdf69c40312b4f49ff39b5a0d8" . + "36404f433c116c18553eb71d136a9255a13aa73319a2f218e3f97c4828de7739" . + "5f10b035bc3a34795535eb2606a8b95ad9b636de20c4916717bc316fba9db3f4" . + "421301a909a8f7855116dbafc3d8c1fe07d6da052d75269fb09a32e2737ad174" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a4a91619b0c853c9d5ac7ee1126dabc06bee28648b127d54963b142e05c53ca8" . + "20a4cd5f456d7207ab73a3d382d8b2aa49dd48c21b0de4976a96667e048946f9" . + "8dd176d27313acc36d987e4e35b7a4748b72777a6b4edb1d9acb7845db2d3cdb" . + "e3bcbfbdc93bc03b209985097d9c07598321f8fe3989b5c17cf1ad495e0fcf2b" . + . + "60884ed5ce3aa21a3270ad2fd60214371f396cd4c5b1e80250194a6505f1cac1" . + "253dc29c4848ce90dc6071ac8091c4fb481feef42a8e332a53c9a411f70ae6f8" . + "5413c0f0bcc929a892fe97191dd88ee09c72ab083edb6904bcdc4f041b20cbb7" . + "206e310ecaa6349aea372e7988d0efbb0bbd9e259381a1e9aa1588e91d77fd5b" . + . + "9d05d9e7acb38bf566594a148f99cbba3f57748cd2449bb5da2d1401081cb88b" . + "1a023d8e0bba4c164bd2a181611814cf07a80746c7a67d2f14cd2243d6bc414e" . + "8551e40e221d69d49139d11b7ff703b9b18a12935c890d1781c4b62ec67d2e0b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3583b5ac100f80da0012b8e9cafcb60d31745e1f9356153089d7c3a318f06662" . + "640f9144dca2e1afeae0eb1b84361f27543c0251d136c489f65fbe2f3a0a4efc" . + "366fcd34ea16d44dcfd262cb9267e74afccbfd1efac2ddfcd750757247353f5f" . + "1a29fac2afe7504db63e5f4f8274dfbc5236a5d568b52363a097d8a58d1e8c9b" . + . + "b455bc396ffcc9f768a83972923ad5a1f7454fec3ac162d623933e34d8ff733c" . + "39ab4ac2a70a4ac0fe0e1f53bd6bc5b783cd842c613d940d1f624b1cb302caa9" . + "dc2f00df510feaa9b7867e0d533eba7b554cdbae91d599e99140c25d8e7fd76a" . + "c048b987e50b9725ca34a347ebfd17b7aca07f1a8b78f1bb92af86c4dd5efb16" . + . + . + . + "f6763473e9d40fa6db493150eb81b6c138f94f93ff787918321ec57512911e42" . + "274241fb8da022b31a0cd73d0bb271229c6f839cf8400a756443f6e5abdb1090" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4684942258a8518a4e6a3d29792499af47d111a447f62296c8efe954f4b11b46" . + "7f103e61c754d1ac0fb54470b2780067ae176054866ef19912a6d1fc5d523615" . + "494f792d3643e9c3c3c17d733267e7440cda5676e6e9bd0b0f96b3cbd3728599" . + "95868c53d51a0b248390a4dfa38e372c5c1405ff3a7733165c23534e2fde2d18" . + . + "6af4a40b9486d8c98eeb5b97652032eb300628e6fae605fb1eef238ee9c9dad1" . + "840e87e16a9d1557242859d211fdfeeb0bbf01f94ab9ec42645ff3845c7983b8" . + "52a4c1f97f8526fb03ffef19775c5eaefe352e1ea1482c23561d31a07b25505c" . + "84df77b3dbdff684b5488be2aecb6900c81ac3ee2b4065fefce389a47645ea13" . + . + . + "b2e1feb1af6d1cdd89fbba3a955ed84f6d8ab57d038861ff85f830a6d8cf1b33" . + "9750860baa2d4a842f862ceacdce539f2c19af22ca25c605c2d9bac2b3dbcc83" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4e854bf475d057945a92e6b1669a0fae6193403f410bc9adff075d958f04b398" . + "f6269c03037f2f500442afabb2b9c91c67d53efcfd708d743a4f8ba21cee4c1d" . + "c1def984a85a8e22afd6fab3456b7c06d178b5a0881aaf441f999569cd0628ac" . + "8071bf59e67bc5de5b6fac1f7f6900a968b33127ce444335e6cb524381344307" . + . + "d337feb0d5e56b533fb097489a1bd6786e2a459936aba5d8592a36ff02274a4c" . + "b6b2f54844a2217fce0a4cb2a674f0766fe1fe307375dc5443a46917b7349b61" . + "6a66e914ce09cec5c9469797f268097fac75957d4030b48fe99e6e7050fbfa53" . + "0e2ff46cb585b98b67d1f2589b91493983eaef1c59a7bd0a067111cbc78edb75" . + . + "87927e600faa1b52acb8a58e7d66ca25e8e2315c84ba18b77c502cf74126f2ef" . + "b0caf1c46c73810e59d3a4d3b08deb6f6e7d18f49242b398930c32b47151bbdd" . + "c0f82515531553900432b3b4126d335c6d02681f0d36ef84fdb9869ffbe568a3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ff8c3620fd16a437d65720cb14f8aa643606cd4fa7b49b45843a599b3287132c" . + "0131644822e6efea206bbe2ff302398b6d17d1664f9d7d1a04b04f4ab2caa303" . + "84297225cb706a5e2d4c7ed015ee5c5ca03fbabf6c22f1ee524e7e41347ab762" . + "a1004c6e33b5a7bcd1fdef81cfa7e91634174352c5d48947e428ddbb562ee2a1" . + . + "d6b49c4f9b6f667ae96069938f0fa0242ac3896067d75d302238bff7b67e3cf2" . + "e9ada566adf41759bdf038b5b0b0bfa2227e7745cefed3c6d82d38ab27210829" . + "97e7441cf5cabaf41a86f814ee4a2d022bd9558b449e34217f055c0d5bb33c00" . + "2100861d3e418c15ab6795426e8914b41a9ce696e30cdcdd9db29484abe9b042" . + . + . + "baa7eb415649a4fa995586afc7237e99005a4db04c1a25b54ca21d8e2f8e8b73" . + "52fec181fde65de0fd0ef9526a009e2192877cc6ab87a06aeee39601c80c7be9" . + "3dfe93d26b51920b5ed15b2baf2ffc5b61609665d0674d8c927dd57db6b288c3" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a733424a63985540a1ce70241ef3049386c6c3c0534a9c3905850421204e2fff" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "4edd25cfda0877496c99c46cdac0d683297632c8b9c6c7c3fab1851b8a2d61e8" . + "cafa6bec17551333b98575562ec88d2003de1aba4a38c8e3eb376130b409b76d" . + . + "a1629d9ec5c5f68c2937644ac4f0ff4e484da2000f34887a3b525c70590455ea" . + "9f3c36f1425cf7295776f8992520cb278300ce6e54f74188432bc84163261488" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + . + "d59c2ee504a59edfbab0d9f1e33ad3ea1f1d7cdaa2a8eafc93bb6aeeb346f3a1" . + "6f9907f851455c12ed0f3d0dbd081ad9f6c5dcda7036002db4d4bed774f424d1" . + "6bd0926dfd15946bc9aba8eb759e15dbd64f8ae50f04e0720e6f956e50a32cc4" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f783738bb765314ff82a75cd4fd7604b01e23d2559e29942b40c43b8f4139cdd" . + "cd0e48ba309f49cf8fce4bb93d11c7044f65959863b85ba7c46dbd7556b1f59f" . + "237bd1b1be46fbfe584bb37886259dddcec2bac442b3046fd668fc1a106eb4ce" . + "3e1623b59e6172b4d832df5cb9f79eab1e629cdb67237bfe76d5c66aaf494fb7" . + . + "4c225911cb5521eea7b4ba00bc52f07468bf6634a8d58cc34313c981f69b35b5" . + "0a2619c951569e7c424ee79df848b05f6b10882cfe561d408c810191da7536d5" . + "d3006fcdb4654832d72ae96ba33e61cb97dfca6d7fcfcbb90ab9fec552bb966e" . + "7bae3ab544b5113a4b0839e3abf6d4347d4b21dda782d78944160f913577e461" . + "cd421a372ae1037cdc7cef40b5c053160910b29ffd477e310953ea67974436ef" . + "1a43279ae2fc6dc01948c91fb19d78fba66b344e2b2a8e098952795966700b93" . + "62a053567aa960969b94765a6f024aad8e3f9199e465997e0cb41a5abf94b0c0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "189815f5936c9bae830776a035b9ca19806f2d0a31a5bf8f722372139a5e7069" . + "bf46be7f003ba8566249e040b197a1fb069ac9c10739645d9dbdd18a3368c805" . + "ecb21a90f60e2a5dfd677dbc216b064b00899df6696e83965b523819359bda66" . + "25a30e9c3899dbcd359bd580b78e408c10867bc37aec12935892a040408556d1" . + . + "45ff962645cfce746ca9d6422b52ffb62b3749b613fcee8c133b674e4ece35d8" . + "6959be871748f3f1c78cc560cfb4e7c229cd24060bd3475ae1a9a1aac5d5b1b9" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "ef8c5f90e2a529b3516a1f57dc5ad8e2c384898aee82714e90f03b9a23fd71d4" . + "89dea563e48341738e2f68ef08382a2c963a0e978d415a52eabe6c5593c0fef6" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a296157db8c33b1e54cf241efae53a59986f7dac4488c9766c40fb3cfcf9c6f4" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + "df5daca3ace3ef14589fc05f222f86ac0cb2b2e8fbc0aa5f8e98b48c0f0a4797" . + "7feeb648bbac0fc6d1af5903110e50af8fe519497b2f125ffdf32f60b33c8773" . + . + "66a2c266083d3c7e117eeb83a7b4a6389b5b6ae2f370762cd94b28fed6d18bfd" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "e5c2e788d6aa1289b8f2f9cf38b912c486054161c779f4ae187d84b90f8315be" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "9c55b18879d31eca0693e696f36a41c4504c8c2a98ef1501caddf8b5cf78d611" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "04c7a38b3d4332555f17a480a345f8f1bd9cd5c1e0b5f29dc59f21aa911d9aa3" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "a1ed3ccc6390b79364012055994b3950ff602876335f7916de735f3806a06d52" . + "1e7a626ce333dc1b54fff2f598903ba814efefc914879f6f172852038cd89b43" . + . + "b7abdd5865da96e6a04303f24143b58dc792aabd5e0427c787780cf0900545c5" . + "1a0feb4c34881199d6e67145b7f55c594141e509cf8e6675db2a390f89c757cd" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + . + "73e422f03eeb0b70c3b08c097398afdd12b4da7a3125ace6e8ca46e63d208f2c" . + "c1080b60c2646a838362a0f984f7f12d35691603f7a5641bbd5be3ec8610fe4f" . + "f3cf99964b3cba8004cfbeec187a06f02867d3340c2d43d0b17dda1763bc4485" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c46e6f9d78546be7f5c0200bb32a1b4fc646fbccfb3c3c4e800640b5f5f876ca" . + "97e7441cf5cabaf41a86f814ee4a2d022bd9558b449e34217f055c0d5bb33c00" . + "7fe442e61c4b0bf612855bcb389223523721a1dea50a95d50e80a0813697b8a0" . + "3a66415d073ef9abd85953e5e2d063d964f5e2094dee823c6a34d6637986ba35" . + . + "1b8b48f3ce529af6e94118b7a50adc14d404eb86a909204681e9576ee9b9760a" . + "c9fff76401c3799a97e93bf848b31b6e6ccaf2ff155ee1aec84e5651cf7670d1" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "c9ec0e458c93e8ecb8463fbd4377f166b81a997ed7bedc3c83c2a860810af45e" . + "9a41a87184bc3f22fe06041b0dc62b2c007580f88db0e5c75381ffc7b68ebe33" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2745924f29d6abd7581a65f6dc692eed0f2e2604b8c76d1c2e88b1a9469d7d01" . + "d01424664c998d5e5356b8569fe667c4ff4cc882f336016970589f6105144561" . + "6181d32177a6a00ba606fbfdb63b54589a6e4172ccbd84971c68126ad14d6e6d" . + "56dea180ce0128b6623ccec6f3bdbbe53661c233022ed3f987a87073b2d805b2" . + . + "5be8899671dcf38c581982d56595e576a9a9bb5bdf0ae657de409becae8f7e2f" . + "c9e6e78d27a19c5456fd1e74c1006a84ac547e18b28de0b3583ea580b3bcf569" . + "d7bc7203123b56bbeb1c0b082e7ba0941d9ef46adec4163416e52b27f9c83672" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "c72ac3034c7b8244e481579a72cdda62f446c6fda088fb6f6cea63b9d4298e72" . + "491937bf97bc4d7332090409828635dc1a9a576c6e54865ae8ebf1ecf5ab7199" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "4b798cd3465cd40eb662a4d48c2ce8e3aa78017a0183a80a14da1f4974cf7547" . + "5c7be7d6db781ec0a9c7c70f9810ae492080f21deb51b36486d8ee3db80fb7ab" . + "e177ad71c45df818d583457ab12c5df88788aa3e0509e0c5be36a7febe89c15e" . + "4334ccb310b2616fc62dc96a8ae4c4d3a2bc0b6f70bd140eaaa0ac378dd50ace" . + "30e990a961da0756e2115348fc769a9aa32e825fc9cdb9bbfc22f0503270800f" . + . + "75113d7f99443807e2a1f29c876d7d85e5a9b8bbecdc0c7960715e40e507b4a3" . + "c93cac2ae2f4414f8f4ba64fa2e9542a5370413f18c6d12e1475c683417b533d" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "528e092cdd2be43496846b5f378fcb146d125d81a1c777f6b4138dc0ef787187" . + "104565b50c1621e44982c8248b986fef97f4cf13d4273546d9059652aa5a55b0" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6c66ac08c47e48f8ea3427fafb9f90c3c2b0fb33d2bead39e2f0e8dcdd6fd019" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "54d4521e6195cbd4d59a0e47f461fe345091b8d7c1f0ff6ca8b218554a28c423" . + "43c50e7a6eedd4507ec70462da1dc39c032fc8084f147e01ddd7e846eacc43d8" . + . + "dddf8658e0680a8d82f008fec6931249906022bef168f26e1b712d197c2a1ec7" . + "1d03f96b7fe468fa507dd4d82dc7db69bdd872b4414634c528bcae6d45960cb0" . + "75f81925a9193cf74ae991ea13d0a06b9bfd1e9a55ba536a88d4d469885dcb49" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "9ede853c08709660b532faaf37dfda4612f6ed7d00ad72882fd5c488ec9ebf94" . + "2e361e392658eecb31243430ae64e8a3ee41600afea9925897bef7565ac93634" . + "8035eb9d479a21b3bfdbde9f64273599d5b5e53d63de6699e810d9dc59287d4b" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b75a60b0d7b20caba59a485668c68b9c5c72038307606409012a81317842205f" . + "4189fa2d076a3b871bc9444f0dda81ee5f705b27d1a50aaaedb0964890788a0f" . + "93f096d07f62926b3f801af9e5b0b29c6049475becdc40ce16500dc4246e9080" . + "12fac50c942070da0cc80009755d2ef8cf1e5d80fdef74121c091bd4d722b9c1" . + . + "6983285b5affe9ec3081cdd84c4ead39ddfb4d6ed0e55aac0a9d049f4cc598f2" . + "dcae5d791bd0e2091a1de29f2fb8101079fa413d007e4372c22a5aaf0ed5821e" . + "f640b3a7da52de9f89778eb6162b478b8ead5794b33dc10fbd208b25648c47de" . + "e3b4b2a6181580c56a9cefc31144aa67c86e94834b0bff372ac44294f147db7f" . + "ea4eba0a50b1c4a08bca299cc88638b171f0500ee72d7cea147904e7f4c22692" . + "64ec052eb264844f8ec97de466fcccae7449c836fe66b7696d8701ca16c27a09" . + "a97c1d2514d37ba573c2fe30a80cda429316fbeaa2023ef5e04403c9a66c0c83" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2f3f09697fc543f6c7f92b358faa53ca71ffd7fde06c9ad374236c63790c47fe" . + "57076e351b4e463e6b838f5631defbbda24514cd0b34f84e329583821d1968e6" . + "5516a3e6ed1f3107e601325aba06a06ff8e72c15c60f4c5546698d86fd6f0745" . + "222ddf9898caa85b0e4d15bfd87763fd5d5addd4b8f03ede5a910caaf44f33a1" . + . + "2ac0c4a6ef88b5dde93acd5697f9122e3ce9aa10d1d9b093b889da714a00734c" . + "3d8fcfcfb6bd762b99d1e355a57664481c663aba6d2f3dfdec14b1f73d82802c" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + . + "18f0213c2df610ab1a26535698df57d1345316191b6f9e2bcccbd782bb8cb945" . + "47a740bb308c927c6e69f639d86f3ef686949c825cec158eb4e62c6e733a9359" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "478b4fafbac9908750b08a0ab8799bf537c81334fd0aa04bc3cb5eed6ed975dd" . + "bfa9d0dae50eb4f97cbc9996254fe7d1d91810dc1470dbedde798a3f982aac2c" . + "9b6eae59cd0263373e3cf2c6cef50f1768869b92d697a1b1fdeed6ad616ac144" . + "6108789a9022a7443d8998429f9c2ef5de9502d755e5b0800048e328071acefe" . + . + "f316b92d973a38075bfa7b1fdd66398e12a42888c29410a9e5a5c0e5e59adad9" . + "b68b6dde97fe3e9cb0349e28cf80c48970198c2e1d0503c4960e9f4f1dbeddfc" . + "79a9d6efdb85c7f86e4a7007f9a082cf07adbe9820c0163e8893b4290a00a5f7" . + "bf07bef018b7f81360bbf15e5b7acaf3616c0e5febc00d81b9c3928a98288346" . + "d098f6446bb48ec9d864a290d02a09e29811d4eef8641566af9296f02d993281" . + "bc7c7bc0a4bfc020d28778c8d1b059cef831d8bd3acf6da12c500ffdefc12c35" . + "b883a02b502512b0bb27f06cba332db618ee92c410af940f7eea24027a236661" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0f73802c4b18df314f4c0a362a6ec63750e8369d2799ccf4bcefbea4049bb378" . + "0a30948304c74a5e61ec20afb1e29bd6d59f3be2f42999f543c86e98e2f017c3" . + "06b327947327bfcf9eb206379b23bde0757811dad9c13544ba57c2b5a462a622" . + "207066916177336dae26c7652c962d5743066c2b2cbbebead95d91357e17312a" . + . + "ecbabf68e07fa40ca3e72c3436bfb512f430e0d0c81130a785755bf34ee73025" . + "d2a1fae05ca42be984f6ad124b59415ab1f48c9b87f7732a2729da3309b714ba" . + "20de977e6912d60f321142413c1d440cdcddc0d4c1500fd724785fc5bf6010a1" . + "96ececbc347d7b3c2657533b305c8165104dcf1bfffa38c76c9ab9ff4b403ced" . + . + "e15837aed2da6cf712e437006462d5b97b3d380134d530ad577b087f25176b8b" . + "3ac6281e623b637ba4133e920dbc1a573e43ad3f12e96142b3da3294e1284f42" . + "f7028dc9054d1227b4ca2f9a1956c722c106d985a72b68698c67c3a5964a9435" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e156ea134f05fff6b33f4c5eae8818f6a181edf6fc55a227d9409a75b1348c00" . + "78d342df4b813a59b68fbdb7f2b565ce690fdea47ad307459d3193da85833423" . + "eb0c5f613af52d78b26ce937df45db3dd3dd5942b68f0a50dd2f74dd177c8851" . + "27af9f0075706fafcdf94815f36e6153c36dd88b20aa0d5d17bbc0785932ea67" . + . + "094b3e8596c0a7094936c3d2e34db8a28c52566edd3bc2d4e07ebe4ec30880a6" . + "cacb49156f059688f865854208052003886d230cf24f4a32307274624941a3df" . + "f83a28e6c07b05ff54c5d87150a186632e17376032f27d813076efb2474684fa" . + "da7c60928ed0f5ae3751e05a98bfc9f2373630953ab24755715707e2df7b2dbb" . + "59f98da9012e6c1da364fe0c1010bed39e3f361794931252bf1ba9ac4b4c9c36" . + "dd0317962251f945c737bc71a1e3a4011c8f7b390250fb23035951b371b532f8" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2d2f080b63ba1751cbcda117cfcc3f54f0ff9f50e4a04aca09277f5262a81c65" . + "d88408decad29a4b1d3c2d68ed95c11e9f3c6b12b1c3532f14bbbff69db7784d" . + "4710ef33aa653e7be4d5b0672b8221696e04f4b8c17f29403897f11f12d553ed" . + "af02f6e0b65f1d97c48205c6e56230dd9c7f796c760be5fd16f7a407d1bb8855" . + . + "a33770450a17b658f690fb4ce72817e08c1f61b3192bf45cf385d8951ae4a59a" . + "49b61c46508e7b4b3d4f70f37dba04bb604aa7ac4dd68a8679af2a58e137834d" . + "6db8b00f3a88f0c1cbe094c569914f5bde07ec1366e68d4f3388cee1055b7f6c" . + "49c26ed06c543b71573914fadc4a80dbbc3bda1913b7b64b97a7c2f902080dac" . + . + . + "2f6093ad40e0d49128964f14a8e26f5160c8fc6f815f58ba83df34fac01d4867" . + "d5abf219f6f1924b939aa1d6f3aff0c7626a22f0697240c34e280cbdc4fe05df" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0f87e66ab6e33260ef7a50f47a71f504d540b38a600f59b272b368a7fe3f8d84" . + "5ed2c7ace8a785bdfd9e5a1b459f7fa40cff3e5182a62f74b7337b73f393fdab" . + "12a6c8934168ed9a16ae8eb8189a2c5351216a1387c0791e62b296d276fb4c98" . + "56d6dfa6673084ed8eaf55973c008bacdc86bcdd273b9c8d4e5fbdd25ba51005" . + . + "081ece6ce2c3ac244272f93b4a69bcc487642d66a019fbfe7a5f24550a7f3c55" . + "9f79fcb856e49bf22068afe76786d4ed5651fc7e4fbe29894fb8d00ba7b8344d" . + "78086e86ee14abb36d43f0e5a5eb00babdefdba1ba624bca97e776e4f23dcc84" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + "620c40f28eb53fe99aa005205e0b081872cff37d77f6aa2f1b9f2c9d755ff03d" . + "f84f50187d1944bb7d1f576454387c326891b62103c9850399345c6e52e7e8fc" . + "66383c65fab158306412889c6bba374583ccaa9fdeeb86107b44f5071add3c41" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d109a9441b2c44abeb09cc3475f8e4225b50826dcf085730484539d2959e7210" . + "a7fa4fc556aac955fd89a46f2f355d01316912cee1d7c31d0f6bd9e349886b79" . + "34f875aab802876cc99663e6298b78b974457e7cd81193b457baf8aa46344a2d" . + "bd020f767df72fa80926667212b74b5caca5e071c936e82b095d87c5770cc46d" . + . + "708608a177b7c868a1f2531bf77607d9b37fe5fee836ee4813b262e01cc55e53" . + "4a7b9c2b47fc1fcbf7f844f2ccc94f58fff43e0a9e9a90bb5e3a95a4a81ce4dc" . + "e7540ed45f18ebab30c81c892bda228ff9363c3f0c6c1d61e70c0915ef55d5b2" . + "3c064fddb27bedd42b9bf1dff562e74a155158437d3749a8b2a3cdc9f307b5d8" . + "d74c7358f4d18f73f83c9828e699bf667a379cc096d2c9d975d3ec5d8bc1015f" . + "586e9c04d9f53139d80792a1fc95d8d8746488b614601c0b67c15eee2bcc3e73" . + "27c554184daf3097679dd0a9ec6994450ce5048b23b2c4659fb1ad86e525bcf3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e73d91c26593eacac33df685bd8a193267b65bac1d3d89037c38f2ebfd029041" . + "9377b0cd1ccb7f12204ec96970eb88c5b4b212d2e231ae41c556fd591c4cda08" . + "ec9524786ffab08feed379c7e96d002d15dc769aa1633a7fb235eabf36a04291" . + "3b69b3ff7b84141b1f7d55bdde7996644e2631daaad6d1c3058428cc917b5ee5" . + . + "41216bf5c3065444e4bbc6535da0ac1da7096b9d8210ef9ba3669e6d67cf19cd" . + "92bd0b44e26c25f89ea1824381f9972cec1c69df7f91b86f3cabf2175f2abd07" . + "477804b8c631a79663d643dd29be09bfd0b574a292fa461aa2908fe3cd40538c" . + "272d48f07b1a465f707d0c2e61f193b7f5c44d9f3266c55b8050727417967d8d" . + "8ad35e717dbe1ef4de1692bfdea0438fcee6b4dbfc507df8cc8e23186fc29c35" . + "f4af1526cab1e6e60acf4fd7e0248e1ce07093e02d58ddb705db81837cc3ab8b" . + "423f6e66ba6188dc3dea317d012beac0374938ebd3490c9fa8f38a87dbf252b9" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "12e9f2cb08bb0c12d1a27f09e819838b6beaf6acc1df7b9ac27f32a5ddccb863" . + "3128d54f27d000b6d8e00894342704529972e959f6b97514b3fa8b3977d81195" . + "12739c3ed2843db739a7bbe5ea704a3cabffd964da662ceb84332b197fe537e3" . + "ce7e93adababf18672be1b148f5e858c9460f45b74661fe6cbe7f184043ee97d" . + . + "8c3c360c829aaec23ba5e1717d83a31e519b00f226a21b500b124e829df0e040" . + "9b618e101cd0bea9f3f2bdb53305f79a710ffd14c72c2d245dbdd02924e4324e" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + . + "9b95039841e8c20b7daebc38e3e60d9fa3760aaa957c9ced88e11771c02984cb" . + "d7581eb39c0184ed3a5bc5c951da5e53248ee949316f608d4f97c9e0d2f673d1" . + "953818e063ef48610d46b5ada880b056d7420b0f246e0d502a55afdf76a8620e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d3c1cde42ad89f738680e996dfc3986f5b7c1ad9240b225f859b714f4153a6ab" . + "472368b2723c6b84a2482ce86bddd703135b95a111af2ab14e96bf253a305c33" . + "905f7e654624dfcd7b6dc21f349135c2b968cb90c40d36269c9be0740989b987" . + "29b3e3626265901d3cac4e6dd62c056b8640e6eb5c23b03300ad83acdce1dc17" . + . + "9cd25f507f87dd9aed39d1e06b9632b2faf47ed509583a36b36f800a3c685ab3" . + "e60b8e7556dc776e6bce19360a1bf6609283e5d26ce4057b4f942681c4626e40" . + "4cf6b5480f3a772a9d68682d10a367f1d5aa797ecbf0d3cc1df210585c1907c8" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + "4ad7d02e89e0148778d9ca1518790e155bf0d42892b177434c810eb49d9d98e2" . + "f48c596fd1c83ffb4a12520ad65fba443a16c6943c7cf5682b0e8252796fce69" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "e14029f9559bab9f242735435bba227c9bb1edb9220a8293fb480f1d790b087e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "28555bb14a31a0b6c76e5f59dffd917bf71ff4c7ee1cc4be6a5a45abae085fd4" . + "f71fd5b761cc410a2d2e410d8a7445603ec124745c365799a8f39525f5337c66" . + "28dd15c94d73549d37361ef54670bd7f866d8aad1691c3fe384b84554d4757b0" . + "d1b56637e52ca83890d2da495e92031c583ed9e551465f23ae35678c0d99cb5b" . + . + "c9f2f30bdcfe3356d0124f6620d100376d98dd9ca5b0628c092b97a7f4870bee" . + "902dcfc37607225debaacece9be6d057b582ca1c91149e53f58cf43172635220" . + "dbdfd7f10cebaae71d266219d1eba2a3a049bb40a2ba27d798249cf53dee5fa7" . + "0cc6a5ccb75e8192ae8413783e66dd7c7e5c0f521e2ccad1704a055cad1c51e3" . + "21d1a1a5d1c7019086807891ae54cdec6cfb152cb9a448eef1767847c9c53a10" . + "d822433f054c47befbfe0f959c8b8fc63ab2ae3165d64b67396763349e12bf59" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "492fdf706b477e51a4a44c6f0e7168a3843f32667a787aed387e300f24c9bcea" . + "5e1c82a355b7ca98b7892ad57fda051f519cf5386b2c9c6ec321b8d466bf7bae" . + "dd66c15fb95d1d46d4c754f11b5d2562f6b972cd1f254dcef593704eee63fab1" . + "22ff976e694385ac3618518b12e41448b5b24f96c72572b2f70ee79459a2ee49" . + . + "8780bf9185eb32b2b8b8721278832cbb54276a92354d60d7e6b54309173ce004" . + "796f2c7b5e522db97ded89fc39b1af57a82cf34c6d954f7ffaa3a5335879ce6c" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + "73db25f8182b6928d00f0b1fac882c8d4bb3c81e35afb4c751bdd10d264e3043" . + "ef4eee070fda2a2162e712d7e65ae4821c768de1ec0bd6e29cf915684cadd6b4" . + "74ef0cab2291654633afa93a71faa738325038721056611717fce8044855da75" . + "54814cca62046c4a31d5b9763dadbc69657cb9e39ca16d76ff4beecfdbb79fab" . + "70bc6d4ceceb1ee29d647c3db5440785a39c374e1a190b4563d30ebde90c62c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "458a7cc11cfac1b75340883be66f3ecf9cdd8435fa8a6d1c35babcee61cbd14e" . + "f4b953e614087bc04251bfaa0125b710d2cdb7f698836a5a8dc3fdb58c73789a" . + "1a1c3b1e87d192c1cb466469b9f16906a04e935a696735f80719d48beae31702" . + "fc350ab6ac569da526a0948ba99fe34d6471cbaf6d6417f080f1270f01aa0f5c" . + . + "5e0aa72fc5fcd41a0b5b500d5b6fa1db11ee165fb2431b04eafa4363ee7137f5" . + "0deecd23c2f46be625510af4b3a6fb00c4fed771977441ef6f31c3f0fe616243" . + "482e99b44affdcfcd08d2ed4912e44c53931d051bb6fe9207a586aed4f3f16d8" . + "b8e2824d705c7830ffee6b2c4f3df53cfa1810122afa1080d344bf2a9e82fb24" . + "4da1e007a945dff0af39ce772e311f8c068e2d777df56886ba6192f5b9d2e828" . + "e5ae68732ff4fccb5aeaf7d6b9860fe57dc8187b0b56565082e0e8a54df58ce0" . + "ca75816c06a44c3c1d9a14ef1129f8e532ef44e254a1af3c235e666889c61761" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "458d4c83c19ad27c3a61f4a3059ba5929dafcfd807d6759c44f3d5c071dff624" . + "c7c9e2b3749c95a8df26a7c879a65d61ce193f5f69e72f32d6cf43ae43a15d04" . + "60b8a2a73d673d9ff1ba9b7a90e602ef2146eee4e8e97f3f8f971c1b996ae925" . + "63d02bc774b845eb6a3fe4e8c128bedaf8d8f46340d3da12f67aee39a54e8eae" . + . + "efedc7bb1dfa7a947e81e29194595820c18e8047ba8393ac06a2f74b610b964d" . + "a6b508d2490341121e9f3d94b5a3c49ee9ebf78c6c3fd3218680f973fe1dfdb3" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "04f768abcc5cca8b9f9cbd0876fb29a7a875fab7566a0136e82a4d25336a00a1" . + "f84d78fa194e6c74e6b57fa6ea8a940798fa09ad72b522b99bde1a9c9be7e41e" . + "d83b7512aa69a81fe0e9113e26db2d0a1b17df08d4b91e29d9b291e6fe6c6263" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7bcdf3c3d13d776cf0ba74b49c474b0f88c61b38b2ef0d370b72008b7fe7b18e" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "5543eb5d5c33aeaf9ed3f497f133bc809a960bfb16ce89b75aca31546f74b146" . + "601cd89f0bfbe02be0612a4f16167f9af3b9fdad673cdbc7cd45d8eb5cecaa00" . + . + "3531c5d6ef24bd03bdb0e694476cad335f0cbf5f643ee488963f60eb73c0725b" . + "04e93d489aa74edf627a5cdf3defaa4df63d311786030c22f32102d263232eea" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "fe18d19b23496f9ad76bd24316a2a88e33a19dc6b00d7caab79934e5cf7787f3" . + "75faa28e6c5e45b71756a7571c7d52d8da76849bba708b89c04ded240289323a" . + "c19d207311aaf3fd13e086f9bf3b8dd621f16bbce41df6b42474ac1d7c887be2" . + "1f76a3b7a380d1599da419c64004d9a98197a568f68a9f5d093b9645f26ea9b3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "613a3fe1f24b6b59bce384893ccd92dbdc163ee653e9d602a346fea774c53e2e" . + "2d251dea49a6c40008157393900170eb62e979fb9cd0f91c12c3b26bcf9de3d4" . + . + "5bd06795b7b72b65fac32952c0ad7da16281665d661f926de11947eff5e9b337" . + "ee0fd6cd179a38a249640033297d9611314bf8b50dbd88015fe1592f9da186a7" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "be7f6dc27352cee8bf0460de0c86183f236e116b7000b67559bff8e5ccb2da9c" . + "dd60075103f47856a72914b218b43001e8d91087537bbfa1cdbcb90317ffe3d3" . + "b81ffe126d03176ac229913498bb6dda32f185a9f1d9eec6e70ddae753c9bc11" . + "410073537f01dc33359a1e5b8bc6d4345e1e1edf60b5442f855d5026a796ee3b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f832b0ecc7200635888bd92f506febda363d9eefb84d0d6eba6164f70d6d5a4a" . + "a8ef8cee615d6f841d2b42a7b6da88aab2fe91e8fea9e894277712c5eb9a5b04" . + "804392f87becfaec4838c6d4a550a92bc5b09b0866a1391c38cc7b31057c05bd" . + "3c41b08d68884709e14e45e8db4626907ba8c8558f109902ffcdb3d1b45bba76" . + . + "ba620dc93cbb14ca85c80b929d0d2ed87568d6f16610f7498ba7d5840624b0b5" . + "6ac0117b3aa69623adf5038d3f45e1e4609b5db42dbd3208836b292250b2f66b" . + "744b79f180687a976be4f98c6a65f0f10056d3494091dc506734e86e4e891661" . + "2dfb4967d65d7182f5ec48d9046ddd8437f3ec988330c02068de74b64c084bb8" . + "72226057870a47b24b19a3bc1416bea7ab9914c705e2b0c713c74806c71223f0" . + "e7285dd113ff1e322789928911cea741d911976271700c4193cae5a3f34030cd" . + "410073537f01dc33359a1e5b8bc6d4345e1e1edf60b5442f855d5026a796ee3b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f91a53182eaa73fb6ddbc07f6aa2e40fedc744b3bf0baeadd249e2397e3b2693" . + "95e82c7860ebdc32d3961385c843749c1688a7dc403a8d554cc14d34b375423b" . + "9dea5db42f8ba903bf9ca6f78ec77da7f8919b9e37b4a9c6eef2a03810805ba2" . + "fa3e3a00fd06e5b06e7df3fbad3c18c05723c12c7c876f6d691a5f6950cde943" . + . + "bbfe2d7bce7132ac8dd5ffe537a7452e4ba312fd224f7a860ec497c733961fcb" . + "5d060e783a67d26295d67ed9daec84ab50e000e7e707f4a90472c49100ae8d6d" . + "0573769400c68eb6f1b816e8dc76e3173b58e7549f26a5511b4b5fa10f95b65b" . + "f96b364db91aa1e659efd835d8e48e991fb43e8bfdf4158acf23c9b8b7d997e0" . + "72a0c89354c663b9d0a0da05a68745c641b99e6d813fcb05c73e07e9635bc1ff" . + "0243e8308a2c73bc79994f3ac61178b53a2e8620ce2096aa92d1bf60da91ef48" . + "b883a02b502512b0bb27f06cba332db618ee92c410af940f7eea24027a236661" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fc7c104000d615663ac3d6883ee30f192fe35d641c4281dda23da8deb81ab233" . + "1aa60c3507d6f591856c12131f5eb3b28eed039d94b5e7d20160e06a5d355ca0" . + "e1dd613f825633038b9007faa37586411ea4af7d67fe4e4944e8f67fdbbc05d5" . + "08049d7e73b18a769fe051c6045225d6f2782271506971a4f933e770035a3b7a" . + . + "5b6b333b21b8422a1ae69afa520ec2d9faa79fef4621fba083e2f77a0f206534" . + "2000676f16c3a9b06922b608de48c1343538c504f0ff48186a1db4a325998301" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "2517797299122631d59877b40026bdfc22310034087ceff53efe6ae0770b397c" . + "7bae97e56326a70be01d85e7065cfa4239c6c62a193f4989b51d419256cb6d5b" . + "5d3b1840084a289bd7fea1c397a95f3a0a47b95c3e33549673efd404828dfdcd" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fd1244222923fcab03e696f5be1c383591fcc21a6acac154fbfe3ea23bab8612" . + "d05d01a081fb8faa4c94816dd64a11f6bd4928a5bf2ff55b4c25f8d707eb76ef" . + "226c2095af58fcdba3b855ee433d745361cfaaa9c0e0de9c3867eaf4613fedba" . + "679b8687c96bc228ad733c0525cba3b5547d46060f722e6cced4cc6d8b951913" . + . + "9e560816a907d2924471c863372e89253e17be39dce4cd9acfe7e2ed73bb4c79" . + "766f1c6d6d3d73635f5aa6bfad02f03e7749fd6540dbb2c42ee3e8ff98e20cb2" . + "ca97a7943a09f8db0f0a57d9aa15f5aafa4a6af61654ca9d131d9d03b7f928c8" . + "94abf6bf8e45935c5cac4953f43a1167c4f588a9a2b23baeca5e8a0c9cbbcfc8" . + "5d16c17d81639f452a186db790a6f54dd3b135acbae8258906387dca22a30266" . + "a1acddb38542317e25116c8d91484134822814dad59d83f0062e6a954de9df43" . + "d848134fe21cb9db0eceeee7c85707b6a28d170cd288c78326d9045b4d562c96" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1bada8bca8f4342529a3e3068a348d93915f1cc2164caf4baf4f0caae0ef0873" . + "a31a1e3ab2eb2674fdaddb6bdd25e6819007790eeefd85f245b89b99c3ffdbfc" . + "6a9156e4c013062aab9354f81b3b5e147e5e824b6df4de780a4f3824d2ee464e" . + "bcc26765c1aaed79782671a6cdcddc3adee1abcf6fdea394423b2f64b5b51242" . + . + "652258ae608c5d0abf8a7d57700c639ad83dad0af04836bdcfd34cd0ffe389fa" . + "0802f9d7bcf473f7e6aadaa8bd29087518ba9184ac94fbd851b4d6c988595ad5" . + "74229443c97fe127264672487c9ab3aec437e8bbc1cd46771d5882a8c68b7d13" . + "16216d2fc4d093ef4690316e84eae65f792263f8e41eee049e39440cc596c60d" . + . + . + . + . + "559db6a13ba19fbe19278850a5bdfff046ce83ea5ff880ca3068cbd0a5f60a25" . + "0d377a8e78b5e6765ddc77c816796d6686557314de8d80e107a27657c8541857" . + "d848134fe21cb9db0eceeee7c85707b6a28d170cd288c78326d9045b4d562c96" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "823de5fdca17a62b412ccf2091374506a4de77d5d95775065e113f1936714333" . + "4de22d79ccd10ef686492121bcb07904e49ae9b47dac2516c9beefd5309ed24f" . + "02711e58ba9357cdb66bfabd05154187b5f8982c8df9fa6a32e1d5b22a73f14c" . + "55b5b904618c518c89e5e7b33c8066a9a32672d4da6c2b3a1cc3d1efd9b5d0ae" . + . + "fe7ead98c8168d5601544c251561dcf4436c25774f4d864f3dc6bde8a60fee97" . + "e64c48905e6459cc55056642c946af0d6151b5e27a10912e0bc4c7a5a59b8b7c" . + "ac59370b9ea079b24b8dace3e340c68754245e8490fcfd7af8d9456115cf81b7" . + "8ab84d3c57fe1f368915feb70685f5a52ca002801c5468951d11fc3cd0facb03" . + "fe7ead98c8168d5601544c251561dcf4436c25774f4d864f3dc6bde8a60fee97" . + "00239eb5112469ff6187686058e4a1718d0dd9d4e4faf6e01914cd368b658c96" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0d93315423df2560f2eb08567d234940de9440caff65622c7f677791042696d6" . + "c1b29cddbc670b61c78e275ab89c81b70e8641f9428e534fa433c18148a91af2" . + "2f30447fb8fed15d72237ac0ff1022728dd7a71d3e99e156824734b6b6f3a19b" . + "07605fc051273fee81743171e6f575dfd21e66992e2c27f6027195c6af67f309" . + . + "b321f5b5c610f57160de074659fc03a828255eb76305a4aa8e77d65399e82b63" . + "a67c56afc6d4f8d73c6d54fb03e8f670f16642057b46c37119439884a9d5b054" . + "3a939550f45494d0cdf88dcd8618787dd67b523bb0eb705ca6b52a3a8b6aa2f4" . + "cd99cea8b7d7ccaeb7f60872418fa42972f0459314adebf2645b22a1d306b087" . + "3257500b31d728a2a1ec1343db2034dd1d870c860abf9bed6be119df9a76b2f1" . + "be2311e639cfbd8c9f56caf184522599af09fb54fd59c6f8f6918ecf1021d005" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f41debf2d692e0d469426e4daa26d11d03e4a9eb9cf21c6dfc41457405e0c0bd" . + "e35afae152901ee987695b3c2d1912e1e600c940632d158a31677a5a6dd76a9f" . + "45ab1c76367618a41690efcf606e7f3f2e3d0b5f2c3f41753f68164b23b4c334" . + "d8bad3616e0bdb7c16a561b0c676ad061a3676a47f773d4f89fca0db939c506b" . + . + "30e4ca170cdf69d415c5abf29447d61287997daf2fc23119078dbfa72cef7485" . + "d626333806802874eafea89e161c4b0073d7a1da9a4392d568ac1267d3ebfccc" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "e461c9793b26a4e76905fb8e18f7f1dcbac6bb6781e32d18baf01ea68b10ad3c" . + "a50c1cf936c3d46ff555d64cee51ecea9e040287c63d8da49005dc8f9929dc9b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d92c1a7591b1ef7bc1c54f7f08537d5116d8a186b218725d5f3e14f3952e493c" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + "60c3b0e0d60229633360145330c6930f980ada06dd08c167174fc280bb34c8f8" . + "e5703495891f8fa20d7dd59ccb9d03e9e513902e7f219b4853b1d8993bf32b03" . + . + "6b9dbfe08ac14a25dad6181c4989f8b34fccb5af3f3bcaf746b4620804e45324" . + "8061c636e63727d3a28c79131dfcf8d11c6122441d7a82eaccaf31fd18218c76" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + "ec5013a5c492be36a284182cbf346672fe7dabeb591e5d98829a162f4dea5927" . + "f689d3950c03f4fea86b9291e4e594718c569f8ed095fffba9e0aae12cf65ff2" . + "38f2ec814540100f9904970375f68ebf8e3af7a0504a3f4e6d69603c37ca1fc1" . + "13dba608d47d7c3bff8b82631741d1cc0ce7e361ee7ecadaf35754dba87d17ee" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7d2d33e1944e503497d8524c9ea87d9fb12634a3c1a95c7008a2ff98300595aa" . + "c404d5a0a0b824e6ecbf4a47cba7dd9308d0e4b258d597e31c2f8c3ff2b8b80c" . + "8d48db4c6ce9cb7903f59435f1649e1ea35f52fa769db878cd20b0b4e601480e" . + "35df8b7c99c2be74565f007f52ee06c6bdfa90244de0e93dd82fad63010824c9" . + . + "a730afd22963d661862c41d4f8d6edf6689feafcacad9acb3c4527c796e96e94" . + "5a8a8e2b9009fdcbdd543082df050865d72555fee5d729f73ccfb16b6c7170bc" . + "36cbf80f9e47041ab3e20cbce0468f91bed91b9373270305e35ba66c8d0426b1" . + "3267d7dfcd1da0629873c0754c5a465a47ccdbac41e951263a2c8dd4721945f3" . + "de7d114fe10a543d49c0eea8e4ebde2588ac7aa31a3ca656028dd346253d140e" . + "e77645d6c389a67e72a0186f8c7c9feba7a69765a80fd957d782474c2e384f0f" . + "4f88bf35f2db14066cff60874aba912196bd3d5ab2e369a8f757d2170d3c35a4" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "84629c9ce122706c998ad3834c529fc65b86604417bc9a30bf0686b5acdf9270" . + "cca5b40a332e7ddbaa0a16f94b9e37bcd5ac77c5a414083da239e03d4908c35d" . + "c1a43666f7457970f48b55de076aa4d2d28655fddb77f919641e9381224c0830" . + "bbd12d7c17be22e6ce748bd99556a3a9e79aeb40d3f618764e76f20321174cbe" . + . + "a95880c5e3fe2553454d60f264d4c7ea86f1db01b17a4c17d0508390bd35faca" . + "7e525db938a2d18a5928a569ae68d8d76b6f39b185a5384ecd0d85b95d4a470b" . + "7ad8932f0435d075a99e3a42f7a5901286d7707ff8ee6ad581034f47c6925880" . + "fd7f1b6a8c62c55f6b31155a870ea8b7ce0afa89772eca2cdc6eeb3a58a625b2" . + "457c6a4f2c7fcd8abd39f0ade3de97c37029de942b2b9cc92e3214ce47e84a63" . + "64d0e21f86c1edd5ae71d0e63279ead85a948c6b86ee216045d1243ca2960a74" . + "6947506ab38653bba0d2df152478bd6ef9e8bbfed4fb22e0dbd35ee252f5b5ad" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9e5a93ede81fa138f10cf0df9948919fb5735e2f98456d0de34c2c5905abd1ac" . + "9ac87486c892e78569e7082ccee0560d05adda16e90031bfa46df3b320dfdd30" . + "b119259f5b18db93dbe9b6eb551c66ea210801960a28c6d15764f32b82e72820" . + "b3669e80252ec8daefd8af1beffd5e528fa2d50e9fae021dc7dbc34767bc6b72" . + . + "70386116bc5f799c863428e91fdd8abae17336a585f6436c7d2cc6c25b706818" . + "f60da0ca1fb2513fed33275486064034a929b8db9ca6eddd090bb4ba6d3f02cf" . + "fc64d33397e8d4890700b6d8aadb9f58d4ebeae0f17be8f500c6bd35ee6714bb" . + "02802c63fecf8a8123352d5b6aaff2942d77cc43a0b8ccae7e20c0fc4ea292ec" . + "9dad3a1a223bfa9575a9f1de0b4713b8e6e394797d61a4522d66e07c515c1204" . + "b15a69f1615327f35f8b8f8f98ad7bd65a02fbd774721943a620b742c84ca477" . + "79071115d5984bfa0ed72c32a7ddad2d45a7b883eb7ea4c9c65443dc9a61c922" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2ebb04222de15890d288e188d3c63f341f70605a01bdb4595d7740c57f0e8528" . + "a83b32e7886b9474881d5616e0b2e038bf98920eac5110c4c6cf2c645d278519" . + "1fa4b99b0cdbf79c828f66e99cd1c183c7fff9abc99635a212c9a4991ccecb26" . + "1d815f666e8a745e5dfbfe82a4ce85f37842900cd5e8bfcf95311402768f469e" . + . + "dba778158ee830cf8d1119a1cb2cabe9dcbe4b54275f32c06001563501099c44" . + "675150e0611c28f40878c4322fe86efe8d7807d67672210916133e2d79095b2c" . + "7b46c496f852fc899df1a72813ea6842ffbf43966ed814850e86b6f0af182daa" . + "448f67f82a82c8a8c53aa41d6835b1652c5109c84a5588822beec6ad2ae65cba" . + "310ce2aa36f2c4e8d73f5890d1a5dc862bfa03f3f7d5e301dd723418d7ff85f6" . + "d5d201a283dd8617e80a3e07a57147101f0262164b9d6617309987ca9e03a78f" . + "b3ccaeaa4b4a8400b896ae614f8385dd7c757889cd31ea0aad910037b97b1b4b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c8ca28574dae16182cac178ba6575b5685f74c8e2ce96f560d6b63fddf51e3ea" . + "9822cfafd387cd2c9dd630e19a6d634d21c79b6d7b4e0b2a877880a868c25a92" . + "ff1ff05bd18ba70d454a93508e731ddc41c73c7b2ac9b81be143f858e07db4af" . + "eed46649ab4af7108e2b5a32a24e9bd7ca9a293f69fd26ae226ee0dd2ff9ca9a" . + . + "7fdc74af2a5201cd415e6b339bb815a850be3832fbee7c9ffb6fffff64d9432e" . + "66785e4899a3ffe86409b03d672b68a4a72a86d972c775d4c93dc0b281a4682b" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "ce5cdc507e34e47a86110f11b9e2bedc4c178f5cc2c7bd47a9723c4ef5ac002e" . + "6e6548448c950b60930f2639242bd2a85ee14e152d6a5e16ea31ab77b290fe64" . + "b48c90802939d07b132f140a5367052f8cb8c2647cb172a890238a5557b42914" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "253c2e978e50a4daffedc8e0db771e08f36cb86bb951508bc40ae78431850a4f" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "68e49542f3f185b5206949f76be5887fd911c29d8d72646fce0db836112d34f4" . + "d4eeff63038863af49287ca9e0b3d956d602e721085dc8a5afdf6e1e42e433d1" . + . + "49a921fc336fb0ed90fa56a2257ad4e258772aa65196dff76e26f0173009447d" . + "921745f409c954a3826f1397273c2f85629637c2cde7f6d4e2ea1c47082f06c7" . + "3af7dfd521fbc1455346dc00c7f0c604399697e173b1cc12069b076ac29b32e0" . + "9d29ccdec4cc5a66f1daadc146548d930d1a6fa5aeae036ec6fc24efb3b06343" . + "016e9eb7d9f1a267678338eca425b4ae54e8df517ddae955f6fbf0ea2cc4476d" . + "9c6cb1115e576081a448303e532b4e3293214d7f22a2a600c17e75a933dd6978" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c8cb47bf11d500f117e60ac06674338ebbbe9efce170e806a914fc1991019686" . + "385f00efe7ff680279132437a6a5fa91a2070d11edf8782ab26db6e99c6f18e5" . + "78ca875d7630267544f447722d4a721ac735d737e1fc5580543cc87466f5ef1c" . + "b1cd7c3f8cb06bb09876a0249d66a03d40811955bc457e36d9fffb2eaf152387" . + . + "26e4c08600bc9625564ef5a6477ec2f35f45ae3a9ac85dd9da1d2b10b402cd2d" . + "901a40b34c164a0f12fed59b641f7103c23ea3e92a5e6af054c6df884f2dcc29" . + "f75701893ce1722083bf062f127a524dbb86e3abde5c917831a2f484cdcbd343" . + "2aaf1314820c233e7afb806b71d54886cb14bc38a5eb45eafb925ec714e67bb7" . + "ffc76bd83d2cd77adc302ff7d7edc297a4d66bff4f27433fde903f5d02c5bc50" . + "f9961f296523f65231d79693ab20f6e0d87126604b43534a16cc29113448100d" . + "dd7a2091057bc8c0025cacc964811b7b5dfa1280eb18ac38315b53318df0bad8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da6d0227bf032c25b86561c2f53bcf222c417b03d7ef6c11a03deaa7ee2a4b55" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "462422bd62b905c43b537215bb4f48f32651a01d18400e1abbf8ce397ce19222" . + "5a6fa8b72fb7213af6bcc68c939f5de7badb1d67dd56e2a0fc5198fa56299cb2" . + . + "1acf233d4d7a3faa09775c569f51f5840c0809ad1a1e30c1a9f25b1a8788e495" . + "d0e616ed1a0a83a316a99669b52448ddbd675ec59ee8f55b4532418084eee997" . + "75caf5e8056a2125ba9febc225d36e11c7bdf557476f28d25a68bb623784ece5" . + "1257d1137ff075035df93e3b9954c7b5fd08567eb1e348a1a8d7f58db5848127" . + . + "b5b671b6e080d72e8d6963fbb4f8143831ca597210f01d2e673cc682b459e43d" . + "0a14aec62d02523a9a8e09326e05b328b2397264297f63e0b41429b82ea56015" . + "13b99e627bd5ee0cdd8b66281bc85c92a648898a0e450978bc6f996f50748f92" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "abbb1693ee2e37a522e39207672802736c824a8fda1bf501f664193d12ab2b8e" . + "04097e6c7c76bb45dfd7eddf70ed59af0e740d7d44b70e67d1d1fd20d2e58591" . + "af447ed2effdd248fcb62cb0817a798d63438f1f5cbccc7e2ff660fedf3fe28b" . + "6dda760938245b4b6b93972d04b76fd676e625dda3752725d69c141f403d7560" . + . + "1a741ebc600fab23987f979b6bda3b23212ccf84d5f438f7c004c55032af5642" . + "6be0bb92dab980628f1f3e840b1de03fbf8b1ef95a8a7bf9dff0e40463bfa645" . + "9c8edccba4b832503608faac29f3b80daa9aa4500012fbfaa95c4145009cc9fd" . + "a0e2f9419e4b9c98d1fb63ae62db8ed0317bbea157056d51ba89309d1c817b51" . + "0fb2d96149e2c6ac2f5423bfc262d2635a357c7a356059576e3768e9e9d1f231" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "6be0bb92dab980628f1f3e840b1de03fbf8b1ef95a8a7bf9dff0e40463bfa645" . + "83015fa5755d76f8f01af41de36432e831d47b302c5c2d8412ab303e158d5049" . + "4e75dfadeecc294ffbbd950cdb8fe1780c261df4112eccdfc943822c40baa122" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ebdaccc2b77a2013dcb3734415fae2bca36916d457baf4da552a3be6e4380368" . + "90a7c4202c3a25eda3f1e6f746fe7368496b302a6a389be86894e4d4f29970ee" . + "870e1a2fc369a0a7e15792a8000e56172c65d963f6689f909b74382593ded85e" . + "8b5531c25eb63ab5651b7426773c4197beb7dade2dbe4b2709eecd995adfd1fc" . + . + "792e93cf0ae0a58afac6644587aac38c011d6f5619d34c8c0e76465f0bf96605" . + "f8215e8ed96ccdbb8fd31b1b9f6cfa97e45d3277448cd26918a83d24a7307cb1" . + "461aa16493cd0bc39705d9b0b6b3dcc18654696b8fbe8f1ad2d4c7fbd0c25b00" . + "7099b15ffb212cf640fd6795da745ee115858e498553a29241f3b2e3d56d6a01" . + . + . + . + . + . + "0dbbf3d87217dc72118c3a28e8b7ccef89411802c53abe1d9459d251e256f612" . + "fcb909ef88e3282920151dbf436433ccc06699e95bfb6cb156b20d8891d9e135" . + "96d0b1d5ae610f274b85c0579674a9db8bc57e8c7c2d060b0bf9b73f85fc8665" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6b6605c8e79a774a669ec432b7497161c53d31530e1721fe0cfb4d5c991a123d" . + "0b215b66447d5014114e80b0c64fa52d7305306a75799e4241368e1176884cca" . + "feebc315edeb278315e5b5f52316ac91cdc8eb69b86836747bf0708663cda4f4" . + "d6a7e9cd0d3110185b14bd6d12cdb90a24818ca71cee4ef8a4d91faf5d3cb1da" . + . + "fdd2e47c5fdb5012435ef54fda29283ccc8ce5583abcfee7266c399532b73b64" . + "f48f4dc73ef60420ad92d5202dd3df877d6ef2eb06b0151f625bf2952bf108eb" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + . + "b34ce6523817d2a36353ed3c699b707fdab82e46432e17d145e1fd076fae339e" . + "24823258a7bb6e41de9a9ce8df8156b472bc13614548486bd36c746ea62b4cbf" . + "f2cf54a48e63021ca1d325a7885c5f2909c3067240741e6e8008dd3195419e11" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "4fcf2952ba9cbb9a84bb1b3fbd99cee3445eb8c9fd9cb83d1a807d03a97b08c9" . + "e274ddbe4e12754df50a5ff31949034473d072d7f07c9ecf2e41c25c94472a59" . + "f6c13ee84efa13b60a8011e739bec212460782dfd62c3c8b062b9642d329ee57" . + . + "8a14d322c11125fa3233acf7a1ed6f067db7673d88b76c197f793173df637014" . + "c4a2f6aa1f35e5d5d4d52cd3ae1d454f1e20bfcd257841ca44155328abb90718" . + "26687a68e88ac833ad52ec624a5b490d6a27f0e53fa5a22f92d7c55bc80d007f" . + "ed3699078d24b4c7b63fe65f9fb468a70d183217c0dc75519f2f027deab507e7" . + . + "0d009cee7b77c9c67d9338449921efafacd5fe37419fcd3e64df7fd66d364fba" . + "611b7c8579adf7f9e464bf76532ed02255449a0fa581d1f796f9e57ba43e85f9" . + "4a8833e0e81ca7a59680e6f52fd7bd6325be05c671c6ec71711355193bf08846" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be8c494b3e94aa2a1fb46c9b01fd45d48884f106543db901d9a48cfc3b0c221d" . + "2068e957c5f9fdd4fd06759a3033fe2a849acaaa05fb6d3949df4ffe0be881db" . + . + "79a8ec1fd04c905fd092d6e2f335a7958850aaeded1df2d9b41fad6a4bd5d0ad" . + "6290fd599652d46423b4fb2bd95b7d3f50ea4bd89670dac88cf0edaed128182a" . + "1a332936d4f459ed4fb1bad993a6d62196a0cd270ca2942a1fdb99dea521ffac" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + . + . + . + . + "67ff780f3498d1bbccd427000b5e1704b8a1b7989164a04623b78827d9f1e59b" . + "81c3385157ac5ac3182ef9c9dfa1f6f2540779d07afdd7dfaeed47e5414b75fe" . + "05101fa0c4ad5971fa3d95108450163846ab332f5d6a87e13e8f5cbc14998461" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a321aefb67a327df70a5898a90eb1ed562e3efaa37f2f653e85962a8a111f0e3" . + "cab1655d0d8d41a2f1fbd8a409e087de4d2bfc57e42cd513f733daed73d3b4aa" . + . + "b94e33368fe50393c2828e105f34d4b5291ed3693d4304f57334e776ff995e71" . + "f1af9ba1773a18008b7319355064920f62847042d783fc696264ddd79160d206" . + "55b8f22ceaa0fc69d4c80c88c8d256f80eab1433ab55f231bcff6c5f9d79e9e3" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + . + "ec57227934b488cb7a0be050a2365f40c5d96cc848f99fcef1e0c62eb0bd52c3" . + "b4c301253756170f14924a6aa9d47d7b26a76ac909b156ec5caac62cb3454da4" . + "3a198a4272d97d95a4cedc59541dc17198af91367b3054252c92ee8bd41c8c85" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "63a96e94bbb616f134c7e2c28b53cb05ca60e4a289a84f1fdabbe2c3e96fb280" . + "4adedc60d45e4ab636612706ce057287bf91e040d282ffc6820acb623467cec4" . + . + "893649add2ebd45891a132d81783c0dda8035f1edad0f9dbaab3ba5157e526a0" . + "31fcf37b7d3815c95cac14b6f8031288dd07544bf1b0c100da054138a6f9d3ec" . + "18664547f5fd200af440aedb48913233ef5dd703bd3c04b6214fa755ed9c8d0b" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + . + "56850f37ec21b38d378d39c27722d68e83930727f1f1fb2c61ed3439280bbe23" . + "adc7e19487b50aca9290adf06dfafe770578de0e7879c6cdbc749669f8c6ce40" . + "48ef8acc63774913b48f321854693f5bc6d9f67fd044e58ab9bd1873ae56b5d7" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b2d4abc12976d0c14bfba143559c92c1b7e7b7892863817deed229367dff8951" . + "0c67e4759626867502f913d7b4f92df1984bc1aa7f3902d0e8514a9b3e6e3c57" . + . + "ea9c9c2a299e2a1b38468f0ad91baa181d8a9f46b6ba0afedb5961cb8434bb82" . + "128981386b379ed4ef9e80dac82be8fb8c05e436885ab3bb028fc4bc7e0b0221" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + . + "e5e964bae1209eb990b658c44965d96362c0ec33ad1b75d36c60d8c4b2359dea" . + "3a2cb0494f6aab539bb54c1aedc216d83cae955754f5dd5cd2bd4be689f24c73" . + "c2d3f1025f9da7ec085684c1cd72a5df399c07397305d4079868b44f728a118f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a88a02a252f2631c7b4e13a302d317dc2083fa01651063b46d448fb9083675a" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "54a34aef567fc5e22c376c0ecb083815fb9049d9dd27dabcbb7bb8a07881f90c" . + "bbf5f872ac5c3a1b746da18f1b91fac4eeb0d42ad2df731e309bab108ee64775" . + . + "1d3738431efdfb907ec2a851dea94ae67be7522953fe1b0e47edb24451587def" . + "8a83240991cfbcedc65e33e14434f018809b429efc1d4307c39a576502f354e2" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + . + "f46cde752aeaaba6b95902783bf5f59e723998e6deabdff1227203938e1bcbd5" . + "313294b2a9836c86b61549b211a1343d02c25577c92f52e226acb2bcc28a3638" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7602c64ffba9465b8d6000d064394d28c0bdc5558643f010fa43328501c3f8ca" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + "8c37f434c4e94e9f9aeae4058b783640b4286792643ed34a0c5b01671ea4ca88" . + "5eacd0dd857176dcdef522d678016e3b79d22037d9eeb1755870f995b64b7259" . + . + "c9345c7754911e431410011a401be2d1785e7940163c319f07886ad75ec9ea34" . + "14d321c01cf16ab5a080326033e57a8686f0892715dd78061ac11fa7c48cea28" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "1230865e29fe4f201da450437646cde58834f90c69380fd4227b927cf285e758" . + "85abfe66c7ccc559bb5442dd2b967aaf57afa3269432b263b0e7a996e44c438a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "06872e644c331d3c9cd86d8c4fc259e38d63d4ea6cf65aea9e01182d353a2833" . + "69c6a571e543eee17c2f5c59c509b44a920459412a1c69e235544e2ee8c50e74" . + . + "a5a240a4e5fabbaf522f34f6f0809a4ad38e26ce8713ef1fe40695197d49dd09" . + "a838e93e38493f722735b9600e3a24ddaa43764f12456f188cabfe53ea6dce70" . + "3108ea50e351957bf4fb5eb0a66011a824403be783bc16002cfe151ebd011b77" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "89e5b0df6e43974e98ded53b113d7b4d5383f2138a662495326fe87d7e469e3d" . + "8374be73c8c087878f08f53eab5c0226cb41b5408617e665f81b2607476cc0c5" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "75e11844fae6444ba6c7814ac789c61a9fd828d0c98a2c6e7b509861f3841135" . + "25668e3af47d2754488c16641504c9887f40549355308350c4a4335dae1c89c8" . + . + "5108e0e77c6dc64eceaf06d28a311e14561f686855bde6d1874ba337f0309f4f" . + "c4e8ee0166dc9faad50747f58a0aeefabc9e827673743ff6ef610fde12140499" . + "75f81925a9193cf74ae991ea13d0a06b9bfd1e9a55ba536a88d4d469885dcb49" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "c59156bb27a60be18819acd786dfdf5418309449e42a6b33124576084fcce3be" . + "2c56e88bb50c77369e7d6054e6d6fe69050079b8c2e62f6f7fc608317cc63849" . + "f9be1a54227a055bf4d8ca6e7a7a0795d961127cd5aec179566900fe9db9478a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c54cb29b88034c2dadb48d1952ad0275f7b8b66c554964ad716391d1c3e0964f" . + "ba45773077ea2d3f1c749bbaf5d7bfc69e5accc873ef44a27808c3d7c703e923" . + . + "de43b8be1176f9124571f2087d2f4ed45e90269334c772017e33c2237f89bb7c" . + "9d0a0e65f9da2537cbc58305a04f712835f0bb72a10842018e37111a6d87aa07" . + "f54bceb459d7ac7693dbab729d3e303f06c082a77ff74aa54d28451577887c69" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + "43f7692c3efb2917db25e9a36d350a84af711a6959c6f715ba21a88b8bc1e766" . + "a570d322e6e6e63bbd2f292858cb43f810801d7e3ee873aff8221f26cb8e7b8f" . + "60754d8071992edd9350a94f47edd309469ae31126df5845b38478e6f477b572" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9ae4d07785550bda57e854116847dc3b58aab96686f30bf8505b293b241ba905" . + "e131eeec978de9e0c4932dc7957639a27be66072e0bc48c1e1766cbc61fb17f8" . + . + "71dd31891fd426757953a981f2c136a1708255ed6012ee16fad2a428d57f42c0" . + "c868ece28525e32d493cacc1e606fd4712f4163e28ee8f101ed27ec90589c2e9" . + "01d60597b28656850786641377d5b98eac00f67c725452c3d2d130be1fbd7215" . + "4d5c9d932bc8c4a6850b7c38b78b1f395420ad314fb37b75488aee1975bf2dea" . + "6540a1caa32bb56ca11a766130c059ca7fa343552d0e282d0fae204a61df7bbb" . + "c3ce6ba459becd7dfbee5cbee74b3e10287f28326c1813c307469dd990bd20b3" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dfe72821d7d8e74ef2fb9d488aebef3a437302d03a81cf0047f2edc712cf50ac" . + "66764329ae8331bfbc1666fae4f69b1dd72f0377e1e5bdd20df0c8c16e7aca31" . + "2fe7d6f87b5ecbae56e5ee28f5db619476984af8e7d8be6d4be026c8b6fc6018" . + "6cb627bf936873132d1efba0b68b140e200db309eb48f295f54fcfa1a4507236" . + . + "eac7b2428464b65445a91e5e5df2b358b412020ec85a97136330921034579bf3" . + "d79a7cbbdd7cc8dd7e2deee8739fe659727b0367148cc25beb2364335b7a50f6" . + "ac41f1d6870896e39c4c9c2580defc92c8a259ba598fe077a1e0971924cc5df3" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "a090269b7350aa758a40a27c0dbfb79b4022409d8eb731ad665fa05fbdab7cf5" . + "18211786d3b8faa1f77ac58bcd26a664f2de6e3c5a5c150bbed2395fccfbfb5a" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f482f7c4ceec5cc188febffc130d80cbc21a29174be7121baa8430707005256b" . + "b904676230c68fcafa8e118ba7a21437e5060f19ad0ee938fe5a9d45e5495c31" . + . + "8991cfd5dad5cfeadc698d93f2adce9ca7d1eb901dcb638414c2d3b72bb3df75" . + "e868fd80f23642b912e3668be1ba116fb175f90c566b8b3e8671968c11c25eef" . + "caef7f8939854b5f95e2c6519f7b5d857fd853c051ee8e839e115005ca2ec226" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "7502c1c2bdc344e34076c218c60650c01cb552bd186ccf6bc3a90cc9378ffcf4" . + "f76e1872b7590a4fd39f04a3cf59c0f26ea60e367fea544e937676973c5d871e" . + "6fb5d3928fb01b0b46d84bf68582c6ff6c1d5ca98a048e08dc5c9405c2f671ff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3396f0b5b8df2aa1ec54f4681233231105bbc1c0e41231e5e949a50466ee5234" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "8fa33ddda00e37857f3b071e919d98138df1fe35ddd5f4479ad3e5de03cf2a7e" . + "9e18078884df6dc7af9882bd72800a7c939423d003f08378b8fd99818fda3a00" . + . + "429425d16109bee1801f5d71c379271e967740676f0a61d4a4a4e93d747f06cb" . + "55e1eb2fb59c8ba63e619af5022f27727a99eeb078bdd7a398278b4b1e3d56c4" . + "cde2bd069b5e9772dd4b75e943c2d4429d85eaa7c4987f8862a16ca3ed5d033e" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "ce5be8ed3fe51a50a78362426d06ab5e5e23ede614b4d2f538f87b1513ead614" . + "026ffce88ec573cf515eb228cf0307e7e5e62ba6376d6d8f53f7d753cdac097a" . + "001ef6f849d833ab5965fe0e3e10d559f2740e0184d008870e4436ded77bb7a5" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7ce057ec19a0fadc602e87eaa7e368476eab88a0e337c1092d6ed7a617634021" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "2781cc63b4709a68aff8620cb7cb38a0c2d7cfdfa5b343e8f2d4f9f22a95d5ab" . + "845924dabdc8066570928d1dad96cf1ddefb6a1dc79fbba76d4558b4b48e05f0" . + . + "746ec6752dfe07297e75831b1494025b87e61f143afff82efef4b8b05d658cc6" . + "d113b99472668f230dc2cecb829a5dd40a17874a3dcb81dcfcd4b53b6b2c9abd" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "b613cbf8dada20eff4308a5be63118c29db4878d2a08e1d7a6cc935dfd9c5e20" . + "3a19b8f97a03f5d68a500661750eb5e921ae22e15936c19dac8bbfcdff611bda" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4fc993443dcb1d14c0a48188a89c6b021c55b70cf73193c69ff73982894321aa" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + "ff259cc6c63df3246aee3d289337cd0a7605088b98d3e81dfd103aced1b328ff" . + "da185e5e203bf9bcdd5dc7bebb9ce5c0f75ae176956793f22bf4032e5b90f79f" . + . + "283d1853ebbdb34764dc7fe4c1b15b985929d044f1a682f71a3e5e9e4d46d0ad" . + "af8cc5dac5ae41db437f14dd0fcf0af0acc71eab24ad8479d7c0cd05273666ab" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "0f525d3e1ac6e07ff58a848d04cf8ce35c00ccb4c27fbfbb9a2e55a04279ca98" . + "887f14fca524291c8298e5aed3be93567c3ddb745d6baf0abc17922b2a417a39" . + "a6dc0b613c2c75a060533ba718050468ff2ad90cdb0f888b31f34e37de773491" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1398a928981336c16c28c38a5a93d38a859aa92a0178166b818dd3349acc7359" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "5f11dab3554379b4135dbdbb9ff572d3c27a672567774da34f848ab41667bcd1" . + "796d5115879b00f5af6d1846b1da3a1b63f277e83161af45ababa32fe7b94b70" . + . + "f4c946dccd50e904241a73b48077b5b58b63a83c74a45554faa145d867d7f713" . + "e395cf829d5bd3783e0c3b1828d791aa249451cfe7ea2bdc5392ae3eb551c570" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "a58773a303f5945f32c1dc84f828f9e0760c524dc94d4c3dbe6ec4697ef48971" . + "ccef176d4ee2821ef1fbc49ee7ed7f15d9ca2f4cb96e7b20b55d456d364248d6" . + "8b3aea45b9e8e7ccd7221fdaf40465271ad50d3702fa81c78a732acf6147d24f" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40d39f5210be56574e58743918437c01832ece6c2dd5584f583a4ee9b6d3e621" . + "5b0c2b577489dbfe92061dddad55b8cc397c1df66fa15cb22a1df7d7ec953161" . + "9ca87c0393cca2ecc974790e886ecf561b371e0e5db37c4784b8dac2bb7bf30f" . + "4d51997d112aefaaa568407f5d4427051460c6f8c4e8fcbb8ee0fd4ca606d480" . + . + "bae0083722e5fcf570a9435874254d3b067c7cea006767819f2b45d7b46be391" . + "595898f09865cd879e3caa3f658e166275bd827cfb9395f71acd0988238dc45e" . + "415adb6e34ed7227b5af245dc53d1162416bb0b8a0f7392197bbfb520a58142b" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "dcc877455e7de6765b1873c57f0660506dc5940ca89bdf84e6036cc8a7a15d9e" . + "101ffba40b0f929f8f91552595903c4650b503210bc6d8866439fdb4e92f89ed" . + "7887ee7521836bd4ff6a2ec2470a79fca0805312d85717651e720e35e5c20308" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dd768c02c1a2a5c45ab447d06c08cd12af31c072435189b5350b16e9463e2c08" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "9c26cae03156c12e7bd9a617da2c12a472716f19094a38faed83a653133179d5" . + "ca4ef568ea92d0e40b239e29b9932bc71cbafb493a11700b10db7fa41604fa95" . + . + "1e83880bb1b7f18479d2ba5e46587d67bbe50b9ccad6b70147fda3aa3a99609e" . + "4282f24540f3b16a946036253b634ee3b75221f178b65d1d6c9ebc2b9e93f59d" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "c6d16da6ae4f59277754ef34ad9a39f78babd7fba3b29e8e46e65f5737139c56" . + "0cd69756d75847165237ba4ae58b675cf898ab4af94387fa956a283a0bb1f651" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aba1b4f3ec02577d5d59dcf1ee7fd1980b18676e389be2a494095d20ed31faa7" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "3b78fb67f752025cb8022345429ee4b6617e181efc04c827dd90474dd52e6e78" . + "fdaafeed585ff010c9293c2054dee7e979f4dee16c0ade6efbdc1c4f31a90806" . + . + "90009b1ed202df98f290e0f94d720c3715c41282ef44ba9059a01bdb28b216da" . + "6c0f6f20c91a9a5f330554f9139139bbfc39c13bef27d13476bad94e5ce3daaf" . + "fc771945098cdcdca0f6a6ef56ff5b3c24c4ee1b601d4f6c3e9bb13edcdae21f" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "165a453eefdb593f5d1261eec3e2570b1e30303bf667eba93aa35122f8c463cd" . + "f2a138d3002237a1810a1b38c5e4e1f63bc00da467eb645f64d0f77146107ce8" . + "0ebf7fc609fd6c42e756c3fe316eeac26822c054e2add6e70af16ca3df7945cb" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8dae7e99b50fcefae2f749447988f762bcd2cd4a9e80d290c7a3b7ea25835845" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "6ce8a16059c751815faeb77b974ca9fd8e9fa0efb3e9222bd925375df4b69985" . + "aaf2ea186ccb017de753c45ad3e7b70c8364cd019aeae31b0df267ecd83b31b2" . + . + "367b47c2a681ae98ab5ce7e57515c7be90406e3bebb88b3e161b215df768a75a" . + "d7c502266d2ef3db301cb4cd507b00b61c6e8908b405408dc71585c5ec827596" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "45def638188b73dc0dd111fd6a6334bd80bc0e422bdd649f629e5133fb46d5d7" . + "eaf73771fdc47b66799c9dd628637da65f2631e3c9f24f0c8624d5d0313b5045" . + "276f2f3dc70f3cf1fcae31ff31376836f80cdae382dbf8f7e26d8289deb3146f" . + "3779c371001342e62821aa072ffd7fee5f3f86d44b11dc462a97f9ebf2212c1e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "79c1cd873b25302d56727728b442f950f0c524b6a0757a61681f053d8ce30309" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "2019ae60b3296830335b1e21a8f7759f95263ced1cb0abe6c2e289886707e54b" . + "d61d4c23b96bb1a2f83e7dc7c16f9f3edaf4e77406db4ffc553d4ecf1d8c1163" . + . + "03b0590f57d9e6db07d6f3745469d95f037703a63c34d10d2ea8a51c05212771" . + "4e2aa3c399a035ae7ac02f99e86dc476e41049738617d7d3a0e30f214ef32d93" . + "92faf599e07ac16fe2c0ad064117f72a7e8046fae1be4a46d876f16023d9b0f0" . + "56b341278d8602a6c4173f59160bed66e923d04c68abf2ca41347d52e5618fe9" . + "9253aaa01abe7427bf1f13b378eedcca0fb5dd28ef21931951689c6e18ca1f1e" . + "1644b784ec3cb6cb2e219ebdb7f0b029ee48b0428ae0be5bb5d9827799d42efb" . + "92b7885cd41af5298c4641f7d8c5fbc59110fe9919386e26f1f0bb8a9e8df17e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aaddc6982a7057dfd777e3374574f918e68f2c20c3283d51ac6e54de46418ed6" . + "394d34fec049c58793a3cfddc2459649598c594c7fe8ecdb9be349e27dd29577" . + "85ddd0f50d685ee40cb81a7664ec9a758b2d29cbf810baa8e0ebc9884bb7e649" . + "c7b1f1c3f0aebe00d708fbe3b8cf9a6f6164c2366759325ff5a1d4e8d8a496a7" . + . + "cb1412e495792345ad3556de289316846007f4b86668947bb1395c467cead133" . + "cfbf53183bc6868b938d44ae967bbf2aa40df496ffd1e8909ce6d5c05e6358a4" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "9b326c336a8ca7a5856abcdab1755379835266f7a578872fc9ad71ae11a4232d" . + "45760d7d0a8319f33a5fcbbf33c322909c4da869b3bb8e42564bb81c1c8db8db" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d6ea69b3a72c1138262047b2fa872cd24e314a970c7a1643995958b7a5ba4f5d" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "b455878568bae6312fd65e7d9b13627974feafdb1a1171fc9dea424185b72cf9" . + "be0a82262e24de528b222435b32374f50df6398a226b8df370b204d784f64300" . + . + "20273a2b0c667ca44c25733d28e4702c3c81b6674a361e8c2be6dd8dd44a06ee" . + "b121c07b06d00a711d1d7a9727ae4fb52884f711cf67cfce0c534f1a8a357c52" . + "aa60b07ab3c642d864dceb4bb1663620965e7307e3753b28d992234659d7748e" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "c09af799e6ec52ec4cd5408da7a110753223b7120ffbc81b7ee99bbade7508aa" . + "840a5b60ca5e1eae7190ec610eb37307840f080208b0b01807433231d3234254" . + "35b925d7fdbe4570de21f3762daf002d885f213b0f0c2f67e34f205715659df6" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7c3608b867c190aebfa03d9ae9f404fdfeea745523ec95c3d681f29566136b63" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "3e1182aa5e328bc2a2c68dbeb06a20c3ede2044349960f4b8bfafcada3b5cf1b" . + "2063d65769dc2316653551736d22083fecebeceafaa792d1a834f8c4a294ac94" . + . + "802cacf89d2397caffbccb65acd4c6276612f85d29adaa52eee0135db01348f5" . + "a55294e94ff17e3b5d3da7da6616b46c9afac536dec3aac2a7d859ada91fb060" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + "2b3082fa9ba7bf9c2795af8db93b2e9c4841d433607c86dd742e605d0ef6344f" . + . + "1a160935c1168fde492f189710db8a85ca8afcfb92806a3dabf220236eaa46a6" . + "226bed8924524ed1c5bb37330078783f94f4baa47a1ef669a18002ef835547e2" . + "c43efcb5640e4aec86f5470e327e20fb56f4f389199ca750c8e8872909ebfac0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "318f245bae11d84accd0e96cf3b2b6e30cd02635165f820fa7cd39e7361edfbe" . + "186ab62640ee5de5ac62673211f20998963f5aaafff77e9908a1020daec5d5d0" . + "eafc7d0e135b3c4f00fc819db03cf62e5b182ad4a2abb17defa3e79f1e0c440b" . + "77f673e1491f16e25e9f2b5ec5c8e760ffac64b93326cde4a839c070401a6ac0" . + . + "e5bf049c25d01a8397fe3d95947022b368613a7121fbfaf2c6d76772c27d9e72" . + "cc1f27a6e3a307619766253439e5f9b232c91861616cf9036eaaa3751f2c0896" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "ef64fba7cce96b2bf6bba2746115601ce43cdc9b12a232ab53e9f2b2e8bfb856" . + "59230627f3d5027f11baef30d1f765d02a684742b8d0087ea1324078480e156d" . + "7c287ba87c420f7d6d2fd1dac3bbbcec64ebc1b56d24a13178c06bae994cfc49" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f428757a0f1d3f12d20cb4b2a164652ccab77aa7eeb124fac0590321b19bc439" . + "4a2dd3ab5fb50dbbd91ba9a8a206a81ba1328e3e0ed92e27cfb5ea7e8799f777" . + . + "2a9fafce4b374196e0d36908cdcb1195d6ead47bf2427fa84082819f2642b21b" . + "1e2b7fd49dec79876a5292b852e5b6af4d78a05f40f511f743219059c6c675c6" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "21a044dd51d6300b5b8b0fb8f74b20df78e660e5b210f87d6d6dc338b0dfc945" . + "baa40dcbe2137827432504bd79c533dde1c245a8f689160c4ef800368c5f856e" . + "7543e93becf67b62fe63d48af904460c16b49022285823d6e1c12d7690603641" . + "820920acd8743ed8805bd6de98cd7b9d5a252371add5e19e9ff405ae9b008ca1" . + "05f5efdab0e58f35eaec09f949f67fa970dbf1e9b355d78cae386c9f3cec314b" . + "e9d2fd99e76c9417515259d5ea4ad5eed8000633d8c0e51d0fda8d7d4c2ddefc" . + . + "07e188cec03d94cb6aa0b1518a665c77b48e72b7375b037955ed60c75f0a2650" . + "e6bad387fa99716b3c00c3e25c6c2720e53ac986f37d58a7a9d25c945384622f" . + "415adb6e34ed7227b5af245dc53d1162416bb0b8a0f7392197bbfb520a58142b" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "e8204bc9d8194f20002a4f99e5e6ac8353b8ed68aa62c1a0b0fbae5ef27fae40" . + "c67d6ba5725f60a2fa2942fcb1aa2abe6e580d1a6e666c3ae287ae46be124fbc" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4c4dfc239733140b95b40ddece2837e86f4607fe771996a658fba576faa617df" . + "8b2c6bf4866c27cf068ccc8f52107c06b79d66cb53801b7c51b6e282ac439426" . + "1fc6a356ca48a5decde65b6e2f5c828d0a451948ead9b35cce026786c1a7eb9c" . + "baf8b075aeb9b1cafe80d9cba8784dde5cd9306cbb88989eb8947b0a82f249fa" . + . + "c0eb782d024d061272cce13e729c6b00d9079c51a8f0ac93142908dfff684ece" . + "7b88acfa66f5898e7a9b8b942dea49453a938210e88fac8d993931373f7b9a42" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "893b487f3ebf16558d797bb2db95b78b77a80afb840b4f9c1d2df5e9783bc239" . + "d2fa888d09c5e71c61744aed7a84c9713abf4f504a28e601081fbdcf5eef833e" . + "b19b83fb6bb0db06cd7a524830e1d2dbc0887d6660c0c260e5cdf827331ab175" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a3af3af12cd2ffc6adcf10cb9a9326583b059fbb6aac5fb4eb37b1d5e1db22ec" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "911c2be5a0247b45afc23bd521f5188f2a12be29c14bbd0711ebb7935c075aa1" . + "b213c04e189e1e41b1eb1a0dce9a2c9d001fabf93d6011444c5d351607798911" . + . + "5d3a073f128bc2519a204274452730abf227e7010057b3a0f17c6ef00348b78b" . + "f53f4902acd623be242ea24bb93839e7784ce2b2bf46bc44b3817b81555bee0e" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "ff52512a71ca524d294dc5491bb30da39fe43c4d91727996903c0491157345b4" . + "e25c3fb2320e60615675c0c26dd191dd61346ee6a19d84ac8a2cef150e9de026" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "fbeee3f757cda62812c8e2c0fff2240f4ff7dd4fced1a33030b2e1e257379679" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "fa757051e85a31688a049037d22547665d82bfe693b133714177ad1d5ae2638b" . + "aa8f064b2b185173f80bfb5956e312bc685525eb900d51f40692e66be4ef93f4" . + . + "75bf121b8f4505a862c1d32559e4b44c2448c99403e7bf510080ef7ed51b46cd" . + "7f46c461148b3f95c722ecf8d5574528649177763931a6ee666c49e67069cb9d" . + "fe18d19b23496f9ad76bd24316a2a88e33a19dc6b00d7caab79934e5cf7787f3" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "d3db3c5dc7a090c0260f214a6b9449d0f6e289647b94304378d90ecce5c0497e" . + "c83bf14c4f417dfa06c2f917e629ae34276e29b025a36abfa86ff820415d4df7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "72fbafb75fd03ade45384871753cc02c9b8967deae04c9c114e44385890d28bd" . + "36404f433c116c18553eb71d136a9255a13aa73319a2f218e3f97c4828de7739" . + "a7e12d2788dcc206da2fdf55652e670322f7dd0b34e45c82e503a4943552b966" . + "3e9b80159dbca8fd6aa093da7c293c40da9de813d98fceb26ec8f2e581ae1890" . + . + "77dd261d3e5d11968eea7b36b205a78f9b581c6f5234b8ef7fec1e13ed09c351" . + "52739e45dc4b408821c3f18b0fa3528cc3c05c041ded9ebeb066e9452df3da43" . + "fd3f17bb6d9874278412b0ab2c9adc38eb636f32177e9f0302641fba6354b9e8" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + "7fa7e49b681f9de500a19725629e61d5d254213a477fe98a57ea67da6a41d8a1" . + "0a0f1fbd2eec835d92b9388293c03ad23bff41c52386aad4a0b50cf99aecc824" . + "988970e3ddaeaf82803247d27ba5cad92f764231f227eaf48deec0499a19a70b" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7008389303b5b2bd623c3955d45f575eec8299693d0421e64d0e22dd9da2cf29" . + "9b35387553feff822b28f460d888bdd4afd5ef07f52834799476b52c79d0e81c" . + "e19aea21530e4569d0e60a1ba81246031102ebef6e6ef8876ff24c171e6e27ee" . + "21b8eb2b99ff11168252733a978ce96c0ab303e1dd27a7d4c3b28c267ff30e2e" . + . + "354f6906344cca8533f655a127f984dc791e67662a4cbaacc8a128397bb37377" . + "5f93e927dfadf47331565446d0a4e4dcf242bdcbf63491865326a0a721726f24" . + "46def03d77c1c3d49c50f4b929f803e7b19e0642996479217d4e6ac357efd2b9" . + "78086e86ee14abb36d43f0e5a5eb00babdefdba1ba624bca97e776e4f23dcc84" . + "9a2c590b449cbcecec7a59829fdda49ed34e2525e2d1b464bfbf0abe77641e6f" . + "e0e96ab673265aee02cdac3c790f4d66d2378506c28e6d99a2e879d1034b25a9" . + "f422e01ca1f9d12e1511c3b414272728f2e072e3358e0ea05f7487ac5af84bf9" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0cfd5611438d9cfd5c719cc5915571dd11102228e79852098a3e42a3fe81d2da" . + "e53b630957f5d48c3f2255a1e664cd017e4bc3539817b91650d6ffc3a3388c66" . + "8f765849f9384b6a59539d637596880844c2767701b6ad0d0954de51db0437b1" . + "cdfacea8b6a56dcc213823febcd33b2fd760c13ffc01e66bf1e9557f76e990a5" . + . + "8e8742a351cae276b39e012b7b8f8630730bd26351634dc9b1c04a1707fead29" . + "3ae378f3702f30ded93e25c1ba7f96f28a11ffcaf4627fb63a081959acf183a0" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "267de746c679b735b9d838de50ed52bd14eb4edd7b1568a56428f9947a177fd8" . + "0adfdd37dda0f56029c17a6c0e2e0cee3061598fd8a2223b50a560f3b1650564" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c1501de754361ff15338bea4028197ac0a25398eda36134483f56aa7eabbca4e" . + "051a7a6db85621a1d5011d536595c39b8c9d54ba249b8423fe846020326db11e" . + "bd92b3fe278d01bbb150ae59ab49e6a02d895440565e4c9a74fdd439e35c543f" . + "c3c316a34d149b02a578330ca42f4bcc904b70aa755fe6d99d5d70e450f50f8f" . + . + "dc7b89ebaae27f01e0af65183a17912c9f608384635171c69b7b936a74e18e59" . + "fbc3ab546648bab6653aea7c8808aa7d501a200587f66729489adca565c5756c" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "c95d8f2bd318fbd5a64c580ef03b404b08327d9882c62e797481849462f820c7" . + "85a5db16679d9300049dd8a3fef1e06f096ff400e516b17ef498b1eb2b7c24e2" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ace52763a16fa96dbfade8f3f4a22b279df108f9a1c9422da285b27ad02cdaa9" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "66607dcc1a5d973450c21cb3fcdd516fb476a7a7384ff682007cd8555b9700dc" . + "fa04b500a6e3747c195dafe88d0f0c5c818336bebc24b19b0bf219c41ac3682a" . + . + "8e11af97e8ef82c4741251b506503c9acad5656f6cda87fcd84590d64cc65dcb" . + "3d5ed0173ee065b0d2ae0b901cae841ab2885800b93fa64ad88b1d3667e0166b" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "a7aa0859702eb2aad335884183b9fbaafdea9f0456ccbd3f2da74ad9447d296e" . + "cf46420127e70ae9d648417b088a24f3c6de13b958099cef020a876f8bf279cf" . + "85c657df186763fc008a044ae972c0bbbd131bb802171d4945d9b48819ce1bc3" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f773f97557656ba1f9728134c61f306a39568a849174d89a691f810c7c7a70de" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "077ba515fe573d9fc65942170c744415c20aa7c3be528e7195258eea6b877ae9" . + "13c4c48c9e857c84b3b639401e4aa08a67d99b6a7a07334bed4e13b9360014f4" . + . + "546205b3f38d3990545006c7fd210801c0239fc1ea3aba77b72eb5fb89c69153" . + "6e14b8ff98a19c55afdb7344bfca310420a7507903acedc279ad7cedc35a454b" . + "d8ff900de629f800e9a69e4e25612449c8bc93edcaee5847ad97fd539a90c083" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "26d2256c4c89df210cb0c0709944d65db8378a5b7efcb310683b2fbb84a9ecda" . + "679b47986e1f318b6348138e4fed067c1225209a2c3596018e9baa35e2ba4497" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aae02f45978fd14482dd1dd24557dc0df51b2294dce1436ff0f01ffb2948bdbf" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "7bdad8adb48793779f0827c7cfe1e04e907bd0a6182ca10bcad8a20cb404ecae" . + "98a8616c8b9a11f94594fe71222191316248f6c9eac45b188ece584602ac3427" . + . + "dad7bfad233f974c583360271a1639dd04a8631e9b49502e1aa6ed9025dea028" . + "b9db8f3a8c6fa811afe3e0f3dad5e1e0295f1471bedcbff80db1ca31d295c071" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + "75284c90d9ff382c5e8054140f194c7e8305df3192c1972926ccc63140e4da31" . + "3122dc308a5665728c53c6243b22aebc43072f76707dcc8ad336fa21124d29bd" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "23d74c5a6dab65d4061eb796bf30ae6b75c1002a64aefd4d95f3e251c716328c" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "3dde5e62393b74f9262046d7b029bffcb2d9c5e8915178e872c13d0ca8c44732" . + "71147e1cabd92744f76699fcf9b0069d48ee420d21a0245b8457377570983f5b" . + . + "8966b1e98df1d1063f36ba410d180333d9abed75a5f78da113418fc73a82c34f" . + "20e8f6774cae5522b7c38ede57678fff9f46ceb735184d5ee462c4196d7c2d30" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "1d70b2a23123bc5e0acb9602e08c7c7e61f60c2adb5185c5b7b78866a0c9a688" . + "14dbed6df7e4e5f47e522fd771528583a83cb22abf445a5b180cde0d9a7998aa" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "814b6f04578a4db4a1ae1e2c54f3d4aa07204ab457e4a196af7a69e87de531f7" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "110f55d2934f55a44914f52220121c7d8f699488b0c2b8bf1bdb669356a39f3f" . + "3c2b4e26b525d4d6ce4ab5933f813366fe356425d7b301689f9563e4c736f1a9" . + . + "3b2d17fffb94f53f0ef3ea11c550ccef1d883d895bc8b6526ddfbe2de50eb7dc" . + "85f649c03b493bf9b58ea93fc33bb6bb567f899078b37dac81317d13f06fb0b4" . + "7f3355eb89be6c7bc83eed17328c00ea77dbbfb824a4d84b6644185ef53a6e4b" . + "d76d043013dede77f1bfd16714c039de5205fdfed7983e0c0e8badd02ae9e3c7" . + "d31a6d95bb2e2a5fabf227feef6a05a607b99eacd540fe6ddd85812e8b8d6752" . + "5b0c4c7cf34e42235d6db14f8fa9038df9c7bd5153bfe1a79b4726658ae53028" . + "b18f123907b589817454a13adefd2ca757766afaddf3414175f988e99ddced9d" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "239329a762a49368b47d8b01df3ec8df05767020b47ec4f22891037e1dd210be" . + "113a3acc5f487d6b2ee424a99cce36b246a6d1a802022f8010c4af9f9aab1eb5" . + "36c9b775edc3bc4cde74560e983c04a4678a3e474e5f82bb67cc0162fda0e155" . + "87b6500aa9f316f0af9ffa49e9c6d696da8cb9a8bded512efdf6129c2d70b601" . + . + "fef97924a036913e3c7fffcdaa467f14ffdb373dbc043c3b1c73d5fe0ad20555" . + "a84a39d8fe5380c4d88150198b563de3cc94b32f90ec16513c1881470d7052af" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "a5834d8585b82ab028a7044de375353d52245424a4b86e23495cfdffcb088fc0" . + "80628a0462a63d4f0de3812a8f09f4da5b425920483f37fcee515e3f05a688b9" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4e77a2daa6a4a43ae562acaf90f3174a3da8895c67349c9b1e3651c3051275f4" . + "b4df167fa748b65bdc451f614f08b9c60368eba4aa0c124e246ae11c0b7a45f7" . + "b023a97c8c0fb52822559b5666122f802c43103219dd6a3ae5fb41740243c29b" . + "541a3565f748feb01e09455659d19388783136135881b183f835a2551e400d39" . + . + "084d10996e97f0c225150157934a05067c6d19b5d3c52a9c2871356c7da8ca65" . + "7b44a89301e5cc90c0248ac6ab0a3443dcec78a8e5e6cab5cd869070fa0c5483" . + "dbdfd7f10cebaae71d266219d1eba2a3a049bb40a2ba27d798249cf53dee5fa7" . + "f8ebf613745f56e3bd0a6f34ee3acb3968c30e70ca33b26db442689a239d14f1" . + "0b812a64789b6e88342d73544f7327752e925f62f02db29304dc658468cabe00" . + "3e747a3e286c3f6d45337e06eb7a3e610880deeba6405548c183b9ed95b1e470" . + "70fd5a17883dc0b1aaf4e4b9202d6aa417b3b55506cc1aa876ca62391e21b0ff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e3e84e8a5d60b754d19032647d6b42bd601e2155b6cf98b6f3795aafea18747b" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "662a4eeb836bd8a9281e2ffd0d0e614a461957db465b7637796280ce07712b6e" . + "c794fa61cb75938162660aa732ab49135049984bd5aff15299f1b25339b44ef4" . + . + "da457c19768710bdc5341e08c39b6f9a43487f897be04e949e28be82f03b6c88" . + "c3d14dbc83a5ff211640f7d3572517b57bea4a441391899e4a0c5487bff57323" . + "eae713d060c4a0b29e368bda568314da5624d76e12542c3aff4ef3495b664327" . + "2d6ba55314375d0a6cd5c62953f16d704baf3d58d6f17da2172d0a7b7b9eca49" . + "aae1fe069204b40798a8f47e71ac9da99ada904c52443a32feaa07dcf97ae9eb" . + "b14d44f74238c27a283aa11f857b1a2b08a5be1160a072beaaa1890b269d3f27" . + "251461164a647bf78b3a252b3606cf56e305360bef52d729bf10e763f1874d7f" . + "04fa731b2fd2cd75e34cefefaac73f546c9bef7b8604c0fdc21e8ef9a6bff7e7" . + "309435e8f8ccb31a8bd37e75bf371ea78c077ac2a860d580f0e10cfbf8746aad" . + "6171d8906cdd17be8d1b413eb510fe4bfef6e08ac99b92dbd66bfb556364d008" . + "48628ccf79fff86cde8fb89bad2baa0a9e42083562e6efe30506c9656e809d6f" . + "b738a12a316f43756e7fd5fa77283a36098406366b503c1343a419cc7a4087ea" . + . + "69b7df40144f2af5ad698eb336a82ac4e812b1c0e4caf6fe6b20e58862f56f2c" . + "9dd28ed86dde0132d7b54ad1d3d1011c39624018092b56586ff34b15ef88c907" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "0354ae9f68657951ce85c6b4955e1e3a6d7f0f275dc69c33598c8316b5a00513" . + "cec2fec1f2d80718c290a36e6175c1f2e113420a56012e8a392b5ab3e8cc6512" . + "02b35ae708c6a098e6d3eb8bc6b0587fc60405f29b26b17c42cb3f30b94668d0" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "fc3748b98dcf72cd657d40bdd65ca6121d1d93a900807f556246cab0f5dcd112" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "4eefda5e768c574737088f4cc03435e412039a11ba951b9c3318cda7d80a9043" . + "6db3e2df89c059dd9ece416e279d52e53a9014a01df4eb08473d65f0dd453cec" . + . + "d335f60c526aafd09578feb5cce8f526890baa970a357a910f6d1e4f997a2908" . + "187f8dbbced6f83a65311d2ae3d930c51c19defe72069e597e8354d177814240" . + "38611443bd7b744094296e0caedb44eb3875f06f8612db9e731ec2b416051c05" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "fbcc7da90211e4d303f11581c8a0034ebc3a702c63054ab3f3f3f7d2a2437926" . + "e7d81b678e2440568c27cec5bdb5598d61e0c7e1d5a55f31340758fd059de34c" . + "752e2e4e9b96a179e1334a8a3a0e3b9dfcc9532401bc766159850de6f8168ef0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6bbe977dfab6261f0737966139548f46852294d48ba430cd406bb890c12eb74e" . + "95d876359404c731ed0bcf5771681136a75d92eae98728211df7f5cb8f08eeaa" . + "f5c9c24f59f55f332d1856c4887ba48c7fccc61753568739aa05688324694c42" . + "406862ccd0e1dc19dbf73f074b68239cca4fa08510d3007d795ef9fd25616ee1" . + . + "00339fb68c88c23881bac6bcac52b51877db7ad27057f29df5dd173219eb30b2" . + "60d2db69f62f48bf2a9db526e8140608b2bbf995584290a5483b410e6c28a44b" . + "5e2aeadb587dc88db24a593c90de8f30590e972f42f0d52f86f4d5b120038cc4" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "f9161caab49f55eec880a0774a453071fe6b1f674d3840dc84700bb887893663" . + "ec7a1ad0622a7ea0128475443ad27057668781c6c27069676f1bbe3f5b289ba0" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1bbe4bf9654fb66ee5908f245b8a7f96058b9bbf57a6f25ea71286fe2bab9b80" . + "3c0a095e8a2a2d4779c65d18678b266d3c20264ef5f915f400386abb49942066" . + . + "f338c3a2281d1c764a1cd5c51f2ba083656a00cd8f3aad89a39ed62c6ae5ea3c" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "9c684b4f3c2689ec51c16d613b610658c0299cf593c046330d07b5de23732b3e" . + "62a9efc573cb1e5324f277efa0c6fe3842d16984178893ba8052d28de18ed85d" . + "ca7fe3e3f4fc27a03766f8cf4e8bca6dbf47e19482583680e8f565a7c8cd7ba3" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7dd322fefef6707432049bb80357e78aafa3bceb07a9f51416de285e0c1d490" . + "373c7acd496a2ed0f76c93f66c084c05608a672eb3ec13b29ec616ea4e9bc8fa" . + "e096f22fc42b6c53034fbae6648b2dc84bb70579f5a4fa1e0b42990cf52e1f43" . + "ba4a533b3947264bb423aaf185ef13589d380bd446791d8ad86b3730017bddb5" . + . + "d5a22637ed4db67e4ffb0d6e0672065e206e560bb7f58f5a59c5382244b38312" . + "8eb5972d158965e3865d23e3d989485402e0ff3aae3557f145daea92c9cf4ca2" . + "9e16690d06dc729b371bc0a1cd8212c013f2fc8aab73369349f96207987daf48" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "a4b145589ca9bdf69202dfe3bf4448780a4277b82a9da1573b3b922464d762c0" . + "b88a17db5d68009b57d04df0769e53b6895b1c05231e3ca29f62b13c18529c7a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b3e784792941f98136f41622e8f9145ddc9d752763438e42dfd28c474d05ec98" . + "aefea0a1036649614326c5e6c34adb319ad906ee4e69a27553fbe14a4b38de2d" . + . + "7f8a0ab60a7474ee6b4acfadfc715aa936f1830d9f6104321761cef906e2853f" . + "71305389dadea7f8e479aea779f4c8e71a76fbdcaa265bdef44b29cc514e9a7d" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "c035249a3af00519961984844ce6b1e3528772053cf5c093b656968249de7258" . + "d4de7a14f5279481514c08935e429c3bef52403434c25ec15ee86ee072476edc" . + "d3dd7ae7244a2021c8d566deb15256359c508a6330d5eb0b6f7e54af1fb65c75" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "64d2437262bb5039442c95b81aa89fee6afa0945779d32a68242487931d3d61b" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "9a7848f193f481ea4f28ce281156d7999a63d35aa8cedef899ce4e13f73477b4" . + "0342d76e366cd5da5fe421321a436b16e355de691aabba9904e185947047b6d8" . + . + "850a9c33bea22677e813403c1da200e1b7ee005a0ed611d482b34cbf6e8c1a20" . + "211e5fb4ec08dcc7ca9f8174cb4e1142ced0ee3d6855d16f827fa47fe5f969c7" . + "b45eb4a3b9f0b58cf4fc4dab558798ff0623ff04a605004c422bf53a88659f47" . + "796af0413542d792cdb3c5602b3a6848b184a39d8e378561f41a202fd17eb5de" . + "7cab0a867bbf96cf1c34d68f6c1101dccc29a883518343074fcc556a1fceb50c" . + "4fde67cf6ce38822a6feeffe83d2af11f77ab91c314fe1706726cdfb37a6709a" . + "1f8048d41ceaffa6dd7f855cac3370e2165777c71925da611f67de00726c687c" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "417c872a5b1fdb579a29c3732fc54d788e70409f34b3a8d4d2902c33d366ca31" . + "48234a7fa3e122ca3acf3fac7c511ea050025b3ff802b4e49dccb8d2a628819f" . + "af8880e2ea3d318ddfbf25429de8f97d933a7bbe376a715341e38f19ce547f0d" . + "6bf746a113376c96a31df72ffb17b2a9df4f3ebcee98f5b684771eaf10f47f07" . + . + "23e4f88f8f1e6bc00041a1b800530ccf9f0912b2d7096752dbbd22705de4f2ec" . + "1098d158285e5630eb583ba80602170075b7a1740fb52530d22c6a4920c945cf" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "b31370f502b834e2107d574a8b40cf8419b79068f3c20b2c92d3ae1a2c25c52e" . + "de4e62231762977cb33dae5b35b046d689b090a6c792c1cf0a99d9d1c51b32c5" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2b16e51a4b219c6cf8451ff8376839fe8699e22e70e7818cb80314b4c3526fd6" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "0efbd0538fec233ed2cfe92644af8984563dfa072f2997d58a14d17ecfe1f509" . + "a86d72e3ee948365f62a830ce8408085bd07f76211a9cf4064d2fc498bff68d0" . + . + "8f8b5a0b438a6790341a5a398b4db97487b9afa71a55e443eb5c45c23aee94e8" . + "ff5c3c4178a9d16bea60f0670f11ebee250d7c15cdd5677e00cd3b8f194c3d2a" . + "1726867f21bb706caab2e441dd7e3941a60d53d8e5523c2f2b2742c2e4aec1b5" . + "1ee9b4e05622a736ab56a0a6c5d6e8a7b2d241d9cc5a8409f66ecf0b44f0fa8c" . + "044b4b930de6e081f0910894a0965bbd12886a872cc0d62ebf94549731cd0103" . + "89a93229422a2b454bd590222acecadf2a8443ddca3184fd68bf5cf6e8da2c1b" . + "7774487c8de38d72e0ec90950144c3653cd6d5afd0e9cdf92878adb317e50b74" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "fd360a4dfbfa557134c4222e92aab03e509dd28afae90216dc9fdcc6aa6e50e2" . + "8a5c3ad4e8f42aa19317f571f3c3f88a734c5b66c4f0c3c39abb88759474aa68" . + "c07669f293f7537536791be61df74f1aba6e544099e97605bd0f25abff1abc3c" . + "7702ae9655502ab3126b4240f0ca53a337bc17617a59f6a9dedb7a28ffe6d672" . + . + "b17da9a55dae07c635b31da47703e84aa2a10f0b3792434c536f56db660cbd82" . + "dbb3274246bf17bf87e17497c039aac3fe3d8740ec3eac8492e1455a31a544bb" . + "311a534775194997b48ba112e08e97cc057d990bdcd29c9a06b1e852fca2fe50" . + "0a80c102c9f3469568debad7eb0c114bfc6e8a418f8dc98a3246a61e4694c9f0" . + . + . + "8d4a59fc51f9c84f9061988f72bba2947d81d0e76496c93e21388d46e79e2f8a" . + "0a0f79db49dc1615f5bc68de65de221f23e623a572ea0b9062f5c00e614c166d" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "ea40ddce8fd305df65dede5c9b1e8d44713026604e672cee4c0f334c851c1a59" . + "ddec34111dbafd5f0f3b30aeeb8bf961fc822c94ad4906efaaf0942bc2529525" . + "5a9e1f95c5023c2c2a0d7d28ec67a0a3e1df6d3edba4f1b37ad290c26a74f525" . + "635d2cb6d42fa53e04d2bf931707ea5da0407e61a540f07d06bdbd5017c2f793" . + . + "51c4130a60e6e88295801e7f85b23662cf3574599e650fba2115908e201aee1f" . + "ed5e9741ea9efe16563b08539d1c8847a21720be9f369c922db825c9bb6c1ced" . + "f5b3ed7f83cace6c939f9e464943707a52f8b17fe85ceb8bdfbedc1817e2c406" . + "c95ef4586c50539df2494b9aa0684a634dfc1c44f6ac1b28f9da5817ee9d5269" . + "e07b8e75e1e331d2615e9a7612b098b525bc1217677663a3724d2c33bdb9e8f0" . + "6c967a6eae06713dc973704a3f43ca716bf60a5a89722b3f725b347eb84efaef" . + "c1d47a6a92970a8c3a04a4fc42a979fc47c9db13f2e188419393481e2bf7c46b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "85c4706ab121491bb980d5b1a7fd1eb8a0026649828fdf1dc0e4c34496d1c097" . + "b96714f107fa82d8ae1906ce55b9f054f69c4373c147d98986cb303b2e27f6aa" . + "254e9b30c6173755635a3d00d5cfd45aa262baac851dca6e986f8af5b550f513" . + "ffdc9734b619974b423555c34056fdd3726e2002f26e986e5499623d7f7d7f19" . + . + "05583723f6be15b4bbd9d9468700852bd6b6f3e5fe09cbb027d2cd2bc65391f6" . + "6b8895ff8dac968cf5bb9c785e11cddb55b5c23095994e082060564dd3f73f6d" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "3a1c3f99d7d9ac09b163a95cf4eb18629c80b9346c6a07c8e37c0c30632d2cb0" . + "8c76caf12be41a0a04a6ba0127ec62f05194197a81ae719f3871b6a7afd755be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5444c42577bddfece438bd412ef4b8fab76f5b5ad1dbf4ffce701a8cc7fd7873" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + "496f9ab8edd642775ea688e6307b401835a2c1f36daf805a78ae35f727331969" . + "25f5cd4d60f7c6f1408a3ee0a641f592e25306f32b7ab6a9b00a04c7fb646d1a" . + . + "98b74dd01c27b3c84877a1727e1350072dd03c91d13e56a523a73bdef323a981" . + "d35f449f4031d5621980936665d55f10e453552a6018c89606444845e8b1f861" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "1286b89eac1e7715253ae839117ebb05288ad7f34d5674c33f56868476a9a249" . + "f7a51b936f9b00350b9ee7a38ad6211ad67b53ed1e660d945d6cdee9decd6be2" . + "98c1bf168d90c09426af7d4346a14719ed36522dc2f96c17f0eb23da75864683" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5d37821c813c878f7150d0489c4956540cba1ad28576e98e7b53accadbbd664b" . + "fd2e135a5cdc47865c9ca24e6ca1430a27588e9f61a1618a8dfdc2e7afa4338c" . + . + "ba3b1413a1e96cb5a105017ed01b4675ab660517a5d5f6f359d683a946b017ed" . + "48d1d5c41ab606f11bd159281c17d9d0f61d079321412b97e0179d350c6cde4a" . + "6a522c214efd2b43a26a63f8bd0b6f58ce8e117ffa55c0ba0764ce9e02c18c7d" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "a266ee17ebc8fb1a17458fc04fa2f000ca7ce1a392032482e61ce172590e2868" . + "70210ed59bd7b56f3f44eab031812c163fe16c8040274636b44df4e3854f5bb4" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2426ee7bce418259913b26f6af17f9787e6db1139bb382d13399295c0fb04131" . + "dd5de631b66cb93653d4a5ad3adf930617dff04b31e84399b76474cf3da73de5" . + . + "da7d7c8e670fad37ed2c36ab5afe38fb8d57473faf15891fe5320e2bb7aa07e6" . + "943da48a0af5b3dea5cf327ebcda67f8ff92731c6c846946f7a7d5fbe05956a7" . + "51d1df17f7212802fe788ddbb16477e613f839dd9c502a6f9fc5cbc2aa1732fd" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "fd8f76bd4ddc09aca5591a4f023b3f800604c9c0168dc389bef7f27841c7d232" . + "42d079486aef36a0a2f05df525792f334a56836b168a7a18a9334d40ec2da30e" . + "29337472987317942412376ad3a148b299242a887306a7cb1d499c394964e5cf" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c8ae6be20721410777597088a34856aaf887facde501ae527814d1b8d4465d0a" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "97d7fc84416d10f4ee13f1219b34aa7e023cb2587e87d1ceda6a940fb989bcce" . + "f3a70d2dce7af6df4db156dc20b7d0eb93d3fb5ce78dd346e8856fb12311f490" . + . + "e018f181beb1f01b6332d6eeb2306642da04d189006c6ef37907342d80e745e1" . + "81e8617d9e11c6a1bf90226dab8448ea301f4b1c9378467742dd53403b619f67" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + . + . + "68b32577d972d5ee7d26b58a522606bd8cc6403f7283843816d50a133e93b967" . + "3c61ab1f1648faaa50f549ae985c98dad0bdd24e0976a40f2e821eb064546f7d" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "51876336cef5103f9663001397ca87ba9713a83f05e5d580f1040547dc16b22a" . + "97e7441cf5cabaf41a86f814ee4a2d022bd9558b449e34217f055c0d5bb33c00" . + "4b10ab18f06c4eefd143e2bef13335f19296441f9a4550e09791f2d5d57e5fff" . + "4c11779ce225f8e0c022b252b1554fcbbea2f972db8073f7b5c5688f58699ec6" . + . + "e4939f4b31feaa303635644109a46dc06afd66b176ebad59b0d5b8c75d8c345d" . + "18901659d334f97d2d64c68d335c0c32abd16ba31fb577f5a70dbbfa146ee45d" . + "cc080cbdddac41c08456c42841304c6bbb7b677975b4f750f14fe8eb4e455d53" . + "cbb3412af9c688ef84a2c87796ebe7ed87d197fc2ce59fd76abdaa8f34328f6c" . + . + "7113f4cfe17ad3b202f46eacb66326c47bd1f2112112f2fcb74ebb81786744fe" . + "e3db4c7e5ea0bc612d4cd1ad103d10bf0bdbe1d15c6d3d4f12ab908f647132be" . + "5186e0e3bbb439a5e33141f670031b3bbfac732001d7b6da56a3c4c4871610a7" . + "02113f4a5aad3f8869dfb47c582d985ccba2c7b548d8c8e51a12df05a0db6036" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dd8b46db7149aa00614453de85887c425a86078a076d265a8892c9434e0f153b" . + "7f7f399030998c3bbe95a1d10c57cf517922081bc09d3b991e34ccbc6b867dae" . + . + "875c76a93cf5493e3b04b1730bd8f6f2648a3b1accae613aa633fee06d260b44" . + "77cc62e6115abbf2f46ebc9c26969111076f064b8b3e66efaca37b62c284bed8" . + "3bfa84890796d106e5e5493037b002c3d43b5664a4506413f72668637e6b2e12" . + "0216d1ee943adcbe8b3837bfa49b02a325bf8d7c056d986a6e3b8c02ef374a44" . + . + . + . + . + . + . + "3457567374c46090e2409412275456c9653a0fa4c39c2198a1fd7504e060574c" . + "25491e148bf50e1aeedf44fa3c41eaec162a5f2fe07911ad3f2391340e6589aa" . + "d7c569e11b9b496b2003e0710b14c44d41f16b975fe327d721cd51b39ab14432" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6a4ee21e75d3aa983f0a8cca0f9b3c42974f401a44fe57de57139b8ce3a18073" . + "55b04b6eeb150638c6bd47c262906df873409831c98649e7baa19515cfd84a41" . + "8ab5d3a0b86ec11144c1fd2b26160ed9f56b6c284b7cd1225cbf0964c54c2e7f" . + "1ff6f145aacd042cdfc90dc6e246150ff85c9d289b5182e66e1733bb12991813" . + . + "eb563f3b729c9d49bb7662acbeff8e200708d5f2da7543d49a1d16756fd94d4a" . + "c97b20621e276d5aa5b205580d176a821c4e66f0589595f5773bf3fc8da6e7ec" . + "4d71a227a27bbee34c174fb418356edb690b58f2a5f1a801379a258701cfc4fa" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + . + "649a954890a99f7633a54e92fa5e2863dc623dfa14240b16fa80168946626489" . + "5a63dc160ec5f22cabdc474eea1c7ee39e4995207400c8e421d91b94829de104" . + "0f03691e4586af67c3298375ac121e5e445ddfdf456f190a493bd1b41d725587" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "09c463a66035ee9c0b6384b9c5f4a1fff228bcebcdac01b2e4b6e0513cd52695" . + "9d433cbeef056c19bde7a5cb1cc7c645abbcb795592ce1e4a5e3aa345c808ad0" . + "45a25dc6fb9d0bc4e59a64b3e48af2edc1dcec356d1c963fcc7dd9666713060a" . + "51f479e75df90565c072e4be1fe5b43304ac7d89a5b0533f037ea6c3a54f8a2f" . + . + "969ed8e528a5f06f8bfe810cac78d2b28cb7990ee435ae170ed04f4cfd19a657" . + "3439a709bac7c6aba5a8c73bff3ecf896f259697221c2ad17f1638743161e772" . + "9c90d4e14ca21ac587337db2aea788824a1b50a7a462e6227ac0dfd7ab6146d7" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "d797dc3de3fc5de6fb6e71b1bb38643e1078fa1b471c5dd39ac4cfc7e6a340d5" . + "80316b31f01e242a4bfbc2f711d90f7c1aaff087c4f6a9c2bb75660642a64e58" . + "a9e73101a009821d6b6c384d87b4ccc05ea77a11a41a7fc359a9f7955e89a741" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2674d2203f015675e0f90b9c4ef5ddd9e51a048b87b6d95113ec21eee8f8f613" . + "9039a4f4e026e18c18a7734d333c7be075437b76bd0fcd68cf016c0caf229aea" . + . + "386d6f0ab0dd978f12c78e2948dde24d45bdb26de173060825389f8186ed2672" . + "ba7984c249603f940439278ad2ab8d9f7ad133a235ba89d12275f88f43aeb51a" . + "3f8981a7f31723392e6b3cc796e6f8fb58e8e93a72f1a23de9b35aa74771c2f1" . + "1de8f31e9ce88c3e17e42b1d43d2044e9136c0a39422434fc6db2f6f8d5e31fc" . + "2c184655c263f179fec86bb871f3bf29b14953b9bd7afd29741be037f88d071b" . + "53eaa31e421fbfcdfe543f13002b27e7df61310e5fab8f921377bd9ad2f0e5c0" . + "1b7fcd7d77e3541e6af4265a17b87ca6eb2223548d618f9364833d54369bf38e" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "37d8f2bea398d8b93874d8a8b185374515f56d6b945bc63f63d391741b298623" . + "d3f82918937c659641c46f241ffd98e6f5eb50b6745f2c4cd6922436af8fb969" . + "e15ad65646b65b3aeb42f09b2d72f4ef1287f1e4b254c4c9a1539ff6565eb171" . + "5306866a9b9e08f11437baf3e895b956d68b783b49a534a8a853bfbfc566894d" . + . + "7c0d9f5effcdce046701e7bde4931e362f5abd5708d65349220c0d0dd252c594" . + "2baaf415d16c6d5585f19f1cbf1e5628d298de546b369032df6dd10d13a73c8b" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "998509d98297be80c82f153f0446c1d4bdafde25fafa5ba545d4c11aefa32513" . + "b94cfa56c5101c65143601300b3dd75434e56606da129ecafb54710805f77266" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f3baaf570a343ce869d6f96784f3c36849ee7cb5d796d8c467299b676c941cec" . + "6926d5c67b71f639b54b490e79efe22e6a6c926bdf21e09e6c0f6d74803bb532" . + "148ec294ccb79ad6a3e9f0895627af16469ca9a0ac58bc28c0d805392d5ee280" . + "fe423c4d69fa936aa36a557a61e97dea3660c221ef75118d229d33c967f2331f" . + . + "dd85569349af191b92e4e49e6b54dd7c2877f8c8b20043253ec0f14ffdc52e0b" . + "0f1129eb7ebd8e8609b0872907a998887d4d251b44aaa050c6cb42e0360f88ad" . + "5f5559693456faff03d519ebbd26143adedf617b055631514c17a757e05d8aa2" . + "6171d8906cdd17be8d1b413eb510fe4bfef6e08ac99b92dbd66bfb556364d008" . + "65b5a22abe6fa091fb851c459c696524a9a64f50f4857d37eb5bf2d457ab2626" . + "9832236858ab7b232768f1cfe1a312bb8dae930372e114db98e0619e4e68bd8a" . + "c06d44da788edc93996757e660188b135ced14a18cce9b34a0b2cc15b6dc2242" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f116ced8ed5345de78ddb33242ca413239f3d2ada835ecb042c0a3224a71bb0d" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "18cbac06af4252cc2036b828f9b85b2f7076c94c5d42ad80635c2e6b529107c0" . + "7752258bf2cb3c5c1232b4ee42edc2568c24a24d34a58f8badd01c5d9802b6e2" . + . + "0f8c3b56adbeeb1e06aa74cfd434369d17e69f39ffb769024eb6ab55ee1f61d2" . + "ed80401c3fedac74917a7fb06e6d70fd1c0944b63d40311290c694e13aafa40f" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "8aff6e8a9189dc78312f9d1f485e86a3b5edde1a49c637ee0329e8c062d6d5d3" . + "0bf5824918e63f0c3bc214bcadd60064ff10a1938b9bab2098446f89d083fb36" . + "2978e09f52408b62f72afcd999577d97dab87d929e087e69228014a98f28149d" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b1100a22be4fd692e44e5be91b8b9a2fc7fa771c7167215b9ef5716393a5bada" . + "d1e2908ac5d9c5566b51643f0005275c4d2b5f5af407d9574297781a843e5245" . + "8f213043b3f048ee7b88bd8d1da3fb6e299ecc890da3349ebb8e7a96d67fad3d" . + "f4a8e4633a7dc9e7304114b7e52e2655f79f8655ded7e0d5a699d61c8992f4f8" . + . + "ca8bca5761d1c1b4af7aebbf8fe5a5a819986ee30b7232290d2c5a1a57b1c29f" . + "63daa04d21ca12e1743285121d8521ea9e469a1d13fe29ae590c5e38d641264f" . + "4d5c9d932bc8c4a6850b7c38b78b1f395420ad314fb37b75488aee1975bf2dea" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "7ec396d0d9bd374d9f6f5293578acb6eb7be03cde7decd9a3b98925d2b52d2e0" . + "e3c62de1f8f7148f987429622c747661a740b774f8efe707afa53cc172e51162" . + "a71df1d32018bf842176093cfed4457f10a01f11260402d9c7ca1ef27e343788" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "05e58974fd78f79ed4ee0b0702d6ad60686c19a4eccb3449d3b2cf00a9ae3304" . + "0cf7c98a2a8f246057f8e6439dc96840cfd266839cb15eca436826f4355cf0d6" . + "73522b83bea148ed5ec8f74af5fa12209a3639c8dad9176a35413e4a5b31e156" . + "49a1826be52c90c89d671806539c93250b500043b52673ad91c680f6a9ed27fe" . + . + "3f28a34879498f7d0fa59bd975e78dec62ab8b306de94c9209f958c048b62308" . + "633341177b5cd9799308155c997b324b5f21cca9e8adf872652dfbe12515495b" . + "dcc9cb2e3a84486bf2d243f0f62f51209b53a2567e27b0b716de2a0c8de32089" . + "9c90d4e14ca21ac587337db2aea788824a1b50a7a462e6227ac0dfd7ab6146d7" . + "5249abfd34fcc8fe13aa51247df08e85231a09936e8f3e2626af230cafc9398e" . + "43bafdfc57e271fcfb0ae4e64ad40ed362aac73a7e03f2fd81ac77825de26f45" . + "d65c415a257447f4948b3c31cc3c26ea883f1ceb61b115b2981ca8dc15a59c0b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "78ff4fb7154afdfcfe8d6e39db31d82627b6398ee04ddcee48853b2e8abf8fb6" . + "19eb09a5200554fcbd9dc7c09eec1aaa3eb3ff8876dd8010d310fd07f3b70c1c" . + "0389e8b8d48ab4ed0ccc806c0e6f8bc0c202bc2460319d6d6f156f1a58e1647b" . + "bce078fb8c87d39850bc4b89ecd7bdb9963199e69beab30ba2e9f40c77fcc968" . + . + "23ce7838e8df724229bdb95ec5e2f3de80539271c604fd649ec000f247ddbabb" . + "496a01309bb3c8159fcdef9cbc33a95a97839f25b9e6a3f9007eefc7c90ed471" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "3ccf40482e90f24e717347d111ba29e22acb3e642f440ca265020b95b855b951" . + "b48a44a07810033264b186ebac33ea305307e38725f800dece29d4e60147c974" . + "0843b17b768556c9ba875ee4909448d80b3af33e30837ae614994360d9a5f42c" . + "09245df6129712de2a683e9bd31433e14793be84a46fff11f55f2242cc3c74ff" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0085e9789afb666fea5c49a39127be51a0cf464c7dbd4acf9d66fcf77351df8c" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "0d37dd679fd9be0cd74f962c8b5014a794c5b078d59b43ed33271c22737dfa2b" . + "cb1844b55da272d7648212567f2b2831ee9ec60eac7315f00a5c0283d5b9380f" . + . + "2ba61cb9ca1218b91c8bd9d8bcdbb0660722f15e76fe587f0f3f8670d60abe36" . + "51ae6dcb6bd8fb2cf155d26039350f0e7023fe83a55e86a6d8732939005fc00c" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "772fbf014b7fd6c7a3516970892e9fddced26578ff845ec29343d2165df653ac" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0952651639c49d351e476da2f2b5cae1a2f2466b8addb9fc7dd0ccd96d1917a0" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "8d557cba9764887ac0c67f52853bf26b91d9455a76071e98f25e05338808a539" . + "82917ab8681da2dbed8d781310b1d5e3dc2f3bda8756a362e9647d5372af2580" . + . + "cdca03aacb276cf78292aef7bfb9afd463d1f8e6c66004b181968de0989ea822" . + "a1a677485f03a0a4573924421b6372bdf5d51f1389f7d20efc9205cbf4407841" . + "b5b3b5142e1deb34bbe41bb6ba1fe96f90ca77f5cb76de16ad7c424543c548c5" . + "70fa41883a3634c6af50afec8da62693f6ab5c92c2356ffb6d4ed2c2d4597b01" . + "fb317c51acd0c7460086d9073f7d3b53096b42472ad14f2abf251f04b28e16f5" . + "36fc9ad280c911102e76db9c211374a0224507f12164cfaeea9661cde0aaecfe" . + "54e54645a09e76f805d76b362bec8c83c3d2cffc870f94c082532482a3cf2e08" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1e906c15417460602c5efc717590d82fca42607b77e77cfa67059c43e7770684" . + "818f3d9f399b02cabcf2b894ba543eccc355c34f6ed0a0924b396dcebeca61b8" . + "8a24e0019d72169f35b88d552341afa3bb5511ae31021971e9db40617189c0c8" . + "4fe46c309af27bec671cfe595b882563d1daa92657ddebb9b8cf959c4185814f" . + . + "803c8b1ba3db7ac5feaadf9740b45bf29389a999503b0a00dc13524f9a93cc44" . + "3154ed897731d9f61a026bcdfe411a69438cc3556c32727b0a24bcc64dccbda1" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "0e43c2bce8da65d804c3628780b7531047aa61f825e4bef657175cf72dc1d2ec" . + "efbafae86ffbf4bf8996fa9ed89e4ef21f2650e2f7891412222b1d2c1c646059" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "c64519ee4b06cdc96d25385284876521297204398b53f1a256547afdc47ff3bd" . + "a37ff197b7eae203d41ba8a5220dc50d374b106b57aff2f952bc113e83000e94" . + "8b0b7884786973d43370e1b022ae98ac2c945f680b9d73bee5545b08df8d1d4f" . + "98f4c63f32ac0553e5c16e21a617d65ae104ea44c526bc8535d54a0cc33dd67a" . + . + "eb0c774dd586c5dc04a9d3e4c5038c942d2f92ba92c416bf2fb9c1c5265dddf7" . + "d201fb1a5f5287e679e4ff3fba4f9b0637ba4fb544aa4ce7c8ded61a23dfad7b" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "57b000671c5b0a349f19d18ef83f0382211aedaa616de7941b9dcc2f2fdaee2f" . + "1b128f3cf330e770c0ff41ebcf0591c3ac945c94be8fd724450d7d02a10391eb" . + "542fae80622159f5d5acb66cb2977a5fdc53ceb3a1a9c239e2a85a11d6dff6b9" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0552526e40901889f6fdda16bea72324b4c20190b6c6990b2e58719724bd6ad" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "04dbbd947ca065866838e7055f12a75418d72cc5db82c6265cf96cfe198459b7" . + "635a02dd954092b0d9302de766e357a799e86fc07bcd3e064b7dd2c343d66e38" . + . + "46ed131bce64ae80fc11be29ddbe2523535aa09e50411be51b00e5304818a35c" . + "4f484033a027120098c94af7082440771e3171a612289d9973a9900406fed22c" . + "c5da779c1a858a0adb16336b3ede2a5e2eb3d5a7595b57ff52cf51a0bc3ef7b6" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + "c8eb14a9f5eebc05f0c302c85765cb1960b90d1d5888150ffdc802959660ba47" . + "05b74207ef742bc6a44a1950658239e137e9624e6a5981864fed202908afadce" . + "ad05f3a62a9bb7fcee365c936b494cc09a9c19cc1ba66aa0df429496d9e66887" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "967ea7143807169c3f4fd9761839b460e041328c126c5c5437f66d9e1996b2e6" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "887055042d90bc39ae0fadb1317e141e16eed8aa3b81e5e162447a9e0d15fd7e" . + "52b17d1006e4c5f5f87483f840f621524d0b4e9a1227db8092500f5805506295" . + . + "3e2f9378fe08a97a2c6bb0b16e59e75ecb9cc5209dc4d2509e6d6457772581d4" . + "5acfbe4fee80b98bbb1722ebfbc080136fd02827f8169767c96c5b06c990fa0a" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "4c1a229f607d19ed3827fc30a6c6c5bd6869235c1058348b909793f5d98bd954" . + "145362cb106c1bb4a722db408d80cb968aa7375e90c8170b2fc14ddc9dc57e9b" . + "5fca961bf0bdf651935fa1ecb4fb2b56d2b04c18397ccf4ad691ac4620bc0667" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "3953b393914fed9176754c082d9432e1807d38af58c9603829147b72daeb7029" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "dbca9530563a511ec11fc019ed8edc044fb5954ca13e7bb6d4c3f0d952cfdb8f" . + "6d0834eee16fe671e7a1b78a7aa5257fb7874a6992c9342b61eee7b3470cff14" . + . + "9aa1df03d60204fe5dddaf4c15c10799f3210c899281e7e9c6a743a54482879d" . + "89244545b53a889a23756a21bed89f12bce74ef67921fe33f4b84943636c935c" . + "59090a163b3011e09d8fde8a441fc293ab6ff43c44815bb5519f45311eb4cade" . + "b63d2399ab4453c5b67e85e6b384a4be638a2ce892bfe27b1fe88db2eec6571f" . + "aa2f16ed913d84fcb4261c894db07edc07051bb3db2f24bf48d2d71af6b7bf85" . + "693c8b513be940a0c7e17b7c38414d85d29ddb49fdcb67faf5c9824dd157314f" . + "3916a86cfda08b3db1a1407eb4a1726e2e1f37c77d3e5e470d3ff86d6dc78a3e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2d426509a74008281a4b7717091206c7b091204520086ad2b20a8e0b6d9be462" . + "2a75fc21c406fd838cd5f61b232c0664257273e1dc39b31e74572b5e12085d9e" . + "660161d38847a76016ee70e25eb37f086bc6c8d2c5d703abd75a3832a36d60bb" . + "451b702001e869c063ea9145c98ac749e147f0cf0d01b401df9d588373c46af2" . + . + "e713280c650fb9211fbdbe305fe724382454f2e3c8e588139911ac9ede4c24c2" . + "d0a81a7d44572c397ce4c44058606973dad0837a94b207fc3856cf14dc440e08" . + "0be97a098dc366547fe21157df14d10a308e3e75f5dba26074f4951c98cd1faa" . + "671ec131b833a744b6ff517d7724cadb844bfe2c714a099353bf9b0078f48337" . + "9d7273927d1201c9680417ef2cda00b505daf054f5f5d3ee5293d3c04d1b7fd5" . + "fe682732f96a4a1c2c2924b2992fcc67b48515528bf26d30042fc4caa01fb09f" . + "8e1faddf90cfdced8d962d00de372a7c7a5b4c25b5bcc4d03d204c17b656dc2c" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40cf6379d1faa7db12e72702897ede767df90199b756883cc63ad9d0aed7e0b2" . + "7238d5eb1cef03b158f29bfe96380b73a941b331cbb93fa20279d3df0776e274" . + "e15971b14751c5d016921eaa03e4fc2e0e400909c935459927d7c39188084e6b" . + "d6e175d0026e2b2eec8deaa0fca61d57162d098d5cb2bf25fd0652791ab58e9f" . + . + "8749b318fb00fcb0b2aaba2b1a91056939260b1e1d078159c44eb22b17dac90f" . + "feee813896166a4da9a2f6ed660baad9f35d16fae7d3a92ae29ade6a465c97bf" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + "cb49e157ea1f2a98d8cae8cfe30710f53f4f31b22d5c7e38523bb53937cae6d3" . + "f37226e0a3f11f61083c6c4bb1c5436f7bf9cdf6a2beadf70731f4994e5773b4" . + "dfb8f5491999e765af08e0644069853ea0fe0b505a12afeda46767326ecdd052" . + "68d891c05649f2d836ca9c05b67fefc249cd97dea535e7f9ff86fa43214cf4f7" . + "264579c4cf7c569eab06020d61e057e943e1590514fcf024ded522f676f4baea" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "678ff8ec1561579f4de24d8782a4a4b3c3e79cfd14e73c19e4cadbeb1bb41a9a" . + "652683217b6a7f2e3d8cd12a1506b3fbff1d1f12eeddefba689bc9f01183073a" . + "4b9d0dfa537e5d79d3c0415c95652fdfaedcedea06b8dc2995dcafaa08864288" . + "2c68c6890a9fbc0de84fd847745731ebff7aa8eefacc271437974158bbb70aab" . + . + "226c2aa895f47e22d69c967856719515be31420053956af1bbed1c4b41f623cc" . + "bb7e9bf3929e29600c80ebe51ddc025d3f100cc71d5bd89e47ef858f84477c9b" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "01cf5e91f33be6ec76abf6a8cd79ad81d98dbd6246cb956c81057b3cdf32c883" . + "a959f347603b9a8fa1b0dfe301855ed178d75fe559c09573af9e2334a22e68bb" . + "6a62af4b2150af3de9c3a1b7ad8d5dbbfa03430dfaef0269ad95b5196259c9de" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "3adf2a4ebe731ce3dec15fa08b12fdb87b9e091c90dade4483fb80cefd673ec7" . + "65dc16e19618313fa1ffbac310b5779e5025f8c810762ddcca79e095bb1fb917" . + . + "1fd10d9aac08b43bf3b42916c5fbf45327d66b2c516edb711ef07f10104847b5" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "7d927d20f6eb8d7acd833fa526de76cc45599ad941e0b5dcd9431919b9bb671d" . + "b2e46d9036ba2ebbf88f090c9006d3946a59ec16a2f8b4d70d2d3856ce8096d9" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cedd03dc7a07abd8a5c344b690e8bb02265b5491ba01ecb6981affcb02dbf04a" . + "5babf380a5992c1976e2342b2fa7f717427911323404c5cd1d1189c281a9647c" . + . + "c8756d3cfd2c0985fe13aea16c5bfb138de8bf2fee50dfc0ee376c6a4421ddf2" . + "e29d37abe8d989842ea50c5332a4c651fed14f84386ee7cec5926c9e52c53d1f" . + "3d49754e05968a9c543a23cb4892f368709c2206328cac7f7fd988f6af8e31d4" . + "fe18d19b23496f9ad76bd24316a2a88e33a19dc6b00d7caab79934e5cf7787f3" . + . + "4c6b67748419816deb4af168f610190190080d0e18bf2a2a33412da2c5fae4b9" . + "ef83952d6b6bf40e09be46820b75dfffa15492eec2d3c0516925ee9a73589fb2" . + "c9f229867f229d238a856e8938d0c47e026453fc1850c53e66fc055a5b876c80" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cae5d553c39ad162f4c54a739542e90f821eaa36ec36559155f2453e087125b3" . + "6a0db4931c34a3c0b8c6c33c29c10c1c312da7e62041d974442ab851f372bd21" . + "ad2845d181a2a52f0049f04003974936f892024787aeaf24fa9c2b20205468f9" . + "337fe163474362cb080263f219e4951c0985e11cafc28e803f214dada676c78c" . + . + "8b632eef724333c614e86176d1f3307ef046f6b36a288ae789c6c2d694229722" . + "7b43dc39b3a8584ef9eea4126aade71f9cd9c9f9dbd02d4d52fdcc3f6fd2f9f4" . + "53b47f85d7ed28499892a90049cdacec2913b4f35cc248deb88dcaea774a76e5" . + "153d9cbfda37228e79442b1b8a8799d562868ef6d58f93f6ce94514ede25fb14" . + "94310dc73e55aab9ce806f4053aaed7e96c35c562a0e7900c1cf62b96d0844b4" . + "a70363d8f81f5163826213e6668ce68ad822f8b02e547b91881a65534dbdc831" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "d3b79e9b9638433afdbdf43969e5dd58f33e9ab59e82be70f0154d4f28ef0c09" . + "433497e396f2710a79a7f562111cdf21c261d6a4d3de699d99a8712fd4d02762" . + "a824c912f3fbc142876bdbb542d8b90761d8edc05edaff2a9a4411b3a2cd929b" . + "14bebd614d3e8a10fcf6135ee777299050fd03a0aa8ab4863b3b2ec60815938a" . + . + "47c9173a6be4a893802bc53dec4ad6a884c7dc1c16f4204640e5d51298ad7c02" . + "22d3a3c0e3d26af6e2e5b7e31db0ac67ce0dee955726948f9b3a9daa3a6b489f" . + "45640839700d5e7a9ef3bad6b15cab0266ac34eaffff5a1950bc43d9658b7678" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "1eb1aa950f671bde69e544be1fa5ee0278ebd95b3e6738d1a6519413f50085ed" . + "b7570cc6ede9565ab26fc64bf8dd08b44ac9858d86e26ee0a7f59aa28cb3699b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "df5bbdd88b8ebdf8c87666f67112f3804f646e48d70ec9a435006a72f8bd504c" . + "5ff0c21ba6723a875cc99d2f267d0c1e7ee56e660659082339b6cab39d71e749" . + "6943449eff34c49efbe413eb8d76859f3f3e30c48a7a99a0deafd01636030f84" . + "aa9e74e8faf47be7fd5d0900eaaf72b9b39232540a6d77fb51532eb8ca7f2828" . + . + "b9cad575c078caea402de546e77ba32fef7a87c8d54b53cbee14285f9a83fa22" . + "791479b223c8474291c212a4f3e4a6ddedbe5db29489fc86f9da8408d0ae60d7" . + "50e55454eac27cb31f8e72a52bccaaf9cf855468e6a32722306621b8d953f059" . + "82ef415545d171a15f6a891c49cc070b3270a1971e814488515947af29556b8f" . + "8487ef7e93ea00f41e21803732a1d130264f90d060af020be36bb8721a77c678" . + "2f4500b4adf073194e1aaba23b58e233964ee62ddffd937712930c1c55fc6b09" . + "057db10d56864e2cc1bbe64c7a04d24ec2e70cd40cc0ea21bda29f6f120026f6" . + "0294769e916ba664d57ad1e4184c18ba754f3cc1609c892bcebe8ca6bb0fe582" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b284fa4f00ebabbbf03fb106230bfd0ee7fb9a890b0819cc339b9a3499d32d15" . + "32206ba08cac75a61bf8824efcda76adf62193f506185262e3db754788a35133" . + "d0494f8ba6b250c82056c071acbe95081c3fa2c747e1aa02679cc762ffb6994e" . + "664e11107da82d366ac53e0e0a747c8dc9d97e4cd527216eb71bbfff5ab8d061" . + . + "497777469d2a7390adeef71aebfa49ae8697bec84d9dd89ece14cdc125d35dfc" . + "36b24e15d4f350bc366c0394289e366cf6f82447f5d479079fc71c1fa676e2dd" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "22937d1f6365843b736b3f233daff8c71855b5286edc227cef823dc46e53cdf7" . + "66f1da2258c7e16fe7278b81b2f2863ad23e15647ea6b9558ac03d12e2b5c7cd" . + "0ad6bcc566d393f2108a99277f3b345bb76bee66430cf17ae40a336243f335d2" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7718c9a2f98fbdde08ac8d356f38307c828bd24c72140198780f1d0666fa541" . + "f464cd14fc43c86fde02e2120e225c8a4397b766c48dc18a94033791466f0255" . + "59e85cfaf75bdb5c4d83805345c1f6167c3405debb76c8bffb0177fcc7430762" . + "c84e6b2b4340764efa389b15a7d449b0858959c5a2e7ae6190692ef0a6ef92dd" . + . + "0a1f0fb2ecfc374186833544856d9df146522437e4a348cf06b16f2675c2de32" . + "eb7082903ca47329df8a139112d8ed841992dfb1e3f35d25a22c6895b0713399" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "38c4666ded0ffb2a91dbe4184ef159b027adfd021a30c384a80419c89dad2ad0" . + "e0f989570c4dd38905c7b77026e14652eb894f1d6ddd990ea774624894c81f19" . + "e8c4d449523d3f0cb5384c756528171d18b5df0a5560a73ad9f85e65e88fbb80" . + "e8c4d449523d3f0cb5384c756528171d18b5df0a5560a73ad9f85e65e88fbb80" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "575943f7e3360c2c6b98276533a55e5dcf983d653719d44bb5c222211207ffb9" . + "653d42bc0dadd0d3b10b08acff06954374f896ccdda62abf9942cc87f885175e" . + "5788b8243da16e59c2e5be23b61fbcafd14bd71d9e362f4a23289a2a97df2bc9" . + "cbd1fbe5bddacf00552ea824301e381fc410794c67083c7fbb9fef8c78962581" . + . + "35e5f71ab5b8bdb6c48c4da170209cc4c19afd4b01e83cbc5cd020b52b44fc51" . + "d262cd001db7fd77cf0b5f501701ccfc88c7e35748b1b8929da3d105a5d2c54a" . + "aa9e5497104830204feafb84bd2585af9a479c0e8f4cb8572e6c573cbfbc4831" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "df0cb7ccb4428f83ec7d66a57ca8b38ef197bcb375be7eaea9f600d99872ad93" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a8dce8a002bccfd09352ef690a0b5550184da2310ede9f32bad0dae9ba73f123" . + "e6392c3860839d6334e57a5b735fbc16e34c0ff96e7880c62e08625989b80306" . + "d206fcc07d7574dd11e9ac4471ec7dc65ec431046efa09a8f213693b421a794e" . + "25ab0dff84d12e27b62f04356ffd5ddfe651d64f4b5fd20a4614a2f59eea2055" . + . + "a6ed3554feaaa793faba60f863ec64eec450de7cf93d8ed2970e4b716c6ab37c" . + "db0f0b8f8379576e0b5069acf1de8ced8bbf72874790dcf7aed0b2990243dee1" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "a6ed3554feaaa793faba60f863ec64eec450de7cf93d8ed2970e4b716c6ab37c" . + "965e753a8d47f7b02e63b95a0cf80a0a98f0adf9846e9f004a0220ff700baaee" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e42b30e4036d9c752bb16d7398c14e3f8fc3acae83a94bb4e6cf3f0ceddb5be9" . + "957dfab90d1ea6b17bbee096c4caaaac122d837e2b2968137ef38637ca48db79" . + . + "602a0843d3af2b6424939c5f24386c76be57a3d7834eb1117b5d88c81f053860" . + "67cb7e9c87253f06e7cda723e3fcbee9944be9cd821138c2213a6d5258b790a7" . + "0eab66ef0b564dbc00812a4c8c02d07848174811eb431c7f0dd4c16df7eb7c1e" . + "f96b364db91aa1e659efd835d8e48e991fb43e8bfdf4158acf23c9b8b7d997e0" . + . + "241858ebc3c5539c7f1e8eda16be4551c4708f8bad37b14f12fbd6427dcd8ee2" . + "5ffced72aa8369928db26b90b307f96684cc30597bcbdd553d321df4fca4111a" . + "d4ef2a031d73151f8783b7177600969fda2171991bd2eddc3e879b3365812676" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "6b655bf88e2daafee3ba1d504c4e7fba2d9cc250909c531e4c2edc4e27e54d1f" . + "76c503887238b94e0cd27716c100b45179667a94406989c66afa95793d35becc" . + "b98c3dd242d53ccce4e3d437430a7217df586d26f2d838536a82390fb414e072" . + "5f7d283ade1991dc8c75b40f374d072cbd13679c3f587bd838411372f7d348ab" . + . + "cabb7d0bd14356323b816d970823d8bba664172821090d13c52a8798d30391a3" . + "21366fa6b15e4da3c8f039c9f993d42ac88235eb5b69198e2b1351b1a1e79f71" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + . + . + . + "20c7261c8bab10f69fed370b809eb7908153c694ecba8c0e9ccf66af24f2018f" . + "26eab11218b948169e2f90fd81908458d897b76e853136216bb4b6c28e884499" . + "16d6410e6491c1b87f56b25c4837869725600f2b047d8ff7ee68ec4ca7d918c6" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "981faa9d9324693a54b839d2b683d4f6e5bd44a7a1489eadf805382234836be9" . + "407d7b988c1ba20be1ab28c6a6e8c138c978275b548d33f5c3f1effa52b07b2c" . + "9c5547779d9725fa9beeedea45a9be29e0498d3f106595cb100e376b190a27b8" . + "aee2aaed7006b3b0d9c5aa50597a52b966d38bb32708f025e2771043a4d50967" . + . + "9284bfae9a8457abb67db2f137d0fd09947509575989ad3b6a2249be9f6cc8b2" . + "de78d3d8ccc5e7799ad61bdac1dbb108b7ab94a4e65ca9aa4906b11ef603c293" . + "840680d6a49263690ebe09642372c48a10b046a99856b1253ccb3d5f7e145dc8" . + "5a5a9658f4301fad791b3e1fc3e5dd73f37a2019c72adbea75e5838d0cf7e1c2" . + "841c45fbbdafa12b4323d3a1d1f0d9c64776af2380909d2e8ad8199dc46202c5" . + "8ccae2f710cc031d001153c125a7f2b54ba0a22d7e6ee0d85578d602506f71a9" . + "9bcdf1f0ec386da35b8132012a8fa064e561a9ab55f59e241fc19e5df7ea6cf1" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0f092576e526c4ea4cee12052adfd68d99853cabfddd36e67f0b81541597ac51" . + "571fef046b5221c66852243f622178305996c1d6469550997cd5ccc97047a389" . + "2d740dd37f7496a70612cf9f064649449c76936ebe4c4e77cac4a7f9e6904f0e" . + "f3a6c39875eb888b5387af9946834e675bdc6e028b412e5fd9a6a2ff89962c87" . + . + "0f240d20fa0e1cd7f22ead20a6d63378b57bef391ee0536c40a0406ac1ac84ee" . + "d9fa0a8b1f5930367b02a2deb3583302a8a12a09b26676c74d9ee13e675ad8a7" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "03f39f75dce06d64ea4a97480179d70f65b338e5d4fb4be945dfa86383eb078d" . + "8d67722762867340a081a3122089ab6a4d78e99f9d2d1b3e282f5465454a00e4" . + "935359adeac3477b48a71aa95b4ad2cfa3f06f39fddd717df2d1ef91b2542c9b" . + "29990bc4a24c6315450eeaf9410fde4e9c030c6ba4c040a84ec0bffbe8f13cf7" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "254ebf3c35b64a4a39123ba92c98798d8b26b1397c359f3813041369a8cb1868" . + "1380a6d484999aa8151c80d5a9b8a1e61404ce66e505c7a2d609e5b47b0165c7" . + "b675e199a7041a58192e08477c0b1e8bafc6f08f8fab3ca1f1c2268b6fff0336" . + "cb8fbe6662cc8ec12ac8ac125f9c9e63d62e491d91bf550b780718a0954c6dde" . + . + "4d87e7c77365e9a75668eaf4ef9f793eaac73bddb494dda965a78a8293d444e6" . + "b35a68390002b76d2ed3c8ef47686d10a1cd5f848f1e7804c2b4dfb590275a70" . + "78c7f1c12db904ad372996b1357df7ccd137e82ccfd00a6288da16c1a9f12b70" . + "96a54f9630a1c37631af19d95b27487ce7efcbb03e0b78e5e68fd97080db6510" . + "ca05ff836824f9a868d717f75f9964cb5b70f9b35fb4d376a1ae9ea026f22d87" . + "03936f68329e2fc1ea55a617747c0370076694ad82d43110128a713eb4d04f3b" . + "06f6784ac1e3cb4d6f1a0a2e5fbaa99aba50a7c349b1e1d7fc71a299490aad24" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "952be740e62f1a57b853ffef21e951b11fd1f9212fe088f5fca0ecb3875c4dfe" . + "a4228e6449a3ed551300981706c5b4d155409519e20b2aa4cf8be00b5be67361" . + "f92b0d2af1cadb1776495cb48def85a048b95c89896389b36ef2efcf1cbc861e" . + "7db98a68cf17779b47a656e7e3e9d3d19c3ad0b5dc21480ce8966fe489bd5aaf" . + . + "c2047a49fcc2c021b4bfd04067ad054b49cc75504649b18e529a8c1e0aa0704d" . + "f45dc2f125e9e634358deea09042fb1a3d59779914990ffa8a9e1740f4c0434d" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + "b7af33004a63c98c72f7daec5b25383fff386b9057f9bab9119bbe7db27a653e" . + "ecfc87b53eb5ca3a51e328a999b446b44616208e87ec378df8ec7d158d86be47" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "60af84c2984f27545dc00a6600b2670490705fbb07f581c2d750072cbe7445e2" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "2144ffc907705299d95c6098c3a5e32fca11462c8986aa006241f0df5134c116" . + "7bd3f2c0fdf4d08450b9d81477269653eb4b3160c167b2a7e136d8f9168d6c66" . + . + "2de6e1d6c9f4029e4b3f67dedc79c126af34cba73f85f1d32480e11e8de01f93" . + "f12352991779c9873ce6625651d8a2b5bced1a73e94c81d5041cc47d3c02704c" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "a061735dc96b59aba79ff3769b4f1a8110421a372c3e1e96d244166fe561541f" . + "2db3744ebbd9c298fde062a6c75a503f99bb868ee61cb1cfb6b0d28577c8987a" . + "bf23a61224d5d182aa673dab200cf88281a31f4399a993cb53b7862280398780" . + "02ec0f029ed7ff9e2315228013be0c6e0b993e329f587784350f437620532e19" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f15e10d6d0e0995be3a75c2cb14f7bae4a94d2e7352415cbf407d0e0601f37b6" . + "ad9f4371f03317be6b22abd2449c615194685b257a0532bfe2d62e74eb7e5f29" . + . + "130725c17c0141ce92c7063f91056cc6ad6851c84afeaaa99b9ea57be4f27155" . + "26509ab4684927ae3208686973ffe37950ba7053c94ecf32efe75fb9d977a805" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "f2632e4d130d5c621e715880faa0f6e5ae9ac64f9ea8e2eca1555ea59f93aef5" . + "94b99918bc5146772106571ed681cbb9ca0c930daabe793fade89a2f5846799c" . + "86582c5db9388974b2cd2efcae136920e274e9b91582221fadbe53796b93d68d" . + "264579c4cf7c569eab06020d61e057e943e1590514fcf024ded522f676f4baea" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c1c10b6c6e332fd67c4af7df897f004576e45fe53bb5a34a0c0c0bbc4138c567" . + "8ba4e720e980566a6a971be2f4aa27995964eaa275c8ba4ed88d28451d736067" . + . + "5234caf065581f7bafa505867e8973270e660ad51a64c5dd5ef6cfc917cc89ef" . + "a678c6e12ce394a267af5a5f91c585c1ae39d5549a5f16511092a4c880e401d7" . + "68840373647d62b2950ea3032ef9d3d453c9870df6fbeb0951b922a36a381f7f" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + "45b7ae5d56d7aab3cc4d1e4321c9687d41551b832c125633f63e09eaadcc45ae" . + "feac77ba3d1b99ab7825d371971c6dc69016b28cf1218782c1c9b3431008cff0" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "625445fdb5bd62319536bb428d5126c33b3de171ce2ab8f69712f7f6c150dca8" . + "822b10afdc13752a4b2ef5352e2985d4d916df0dce0490c344e6360de9f19f83" . + . + "76bd57e9b9ace65d881e4fe68f9c46a119b9cd7b56d968f779affb59172c686d" . + "60ede4e825664cc0c97bb081ad43f41da9b2a04c79c47f4ef3cef35525258922" . + "d449b897f216b5320951aabd67796c0eefcff450c9e31fcb5d3e254044d1e377" . + "6996fae59714f0a0365e23409e9a5056a141c5954bed3a961bfbe8bbdbd0c611" . + "299d81d1622d5b4ee6f3bf70a539e4a844eba4633eb48d22921177bde78af59f" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "60ede4e825664cc0c97bb081ad43f41da9b2a04c79c47f4ef3cef35525258922" . + "e9ee379024484f13b7f0698b6560b1deb290079e367ee9f5e410a0924c8bea9d" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f36ee3b34470dc31a2c2e29b561a0dbb2a8871e313c418a2a00284d5b8404333" . + "90ccbb12e756969bac7c3f8200ba5e87d96024cd3d97a917dca19ebbf1d87fb7" . + "030213c18980d636e4f3b21c913312bdd8bef0a6c015b6b99ef1495bdd06b0e2" . + "2f9f8dd60dd6ef24be5b35dd4fcde20e2101bd5eebc4a85fbd0eedad0f3a469e" . + . + "acd70dc90f89e2d1cd6ee8e7f3d0ef82b02b20542c4dfbf29bc8c88d81cb508d" . + "5e9055a7ffabd3cc77e4b07e87ff9e5dcdd180c56ee4ae62b7986f68ca4f998f" . + "c36affd4b410d778d2e78b3f1801f7bd486fd33b29030c4aefb8f8ec25fd1f6d" . + "c462d8d2941fd08c4c60f087c75b92d030a147ab1a62aac1e793127b2591659d" . + . + "32a2122cc2adea2408dfb7f341615f22689a190fbfbe485fddbbd35ffd879960" . + "19179554ec974993ab733ed5cdcab81961fdd4bef36bb149cebd31b7d00abdbd" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9ea210e62c58a61ca378e2df7859812447164c7a22136e00a829dd197f7a1621" . + "4be68e428eff93e79f70db04957c07de2a9acc94d67815634eb315ebff138b30" . + "6844476a608b4736e359b69707be8e64a43237235d75027a49e8490c80f38b20" . + "bc1b57ec2e3ce2f8c387dea0a944d80e1ebff48ba73ad6866a873df9c890f8a6" . + . + "b976a5135674daa9e179243d0120ee9122d57ea6366ca5fc14ca8a8aa519e923" . + "b995c4eccf4918e0d210191e904d4edbc2b396423e50028fc9899a9669315305" . + "0af92101b0612f0eaf762deec25411afe69eb22dc632db42c5fb5232c4fc741c" . + "d8e4859dae22183853bf5c2ad2fd5d9ef858f59dcf4bec346fe9102396d13eca" . + "b976a5135674daa9e179243d0120ee9122d57ea6366ca5fc14ca8a8aa519e923" . + "ac77c28ed785be78541f52365b438eaf017d920b65c24dfcd320f9970c48eb2f" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0ea927cf068e2f63a9bb2344f6eaa01dc5ccb72c390ccdd17e337663a9b75148" . + "b62fda4e76148c80f70802adbcba28a653d1551f7f4c43c3a2da012ddd243cee" . + "de935572c3429b905a2fd5f2b0730d5c927187a2279d39eee0ad595c6cce7d23" . + "82e2a64197639789c2e4e42f53a18085b67cce99078558b08c681b0fe7037638" . + . + "0d85959b8f7f625310ad87ec4cf5889e67736a350a9e199031bd4c2b5febe19a" . + "e6279397894cddb7993fc68d6c7986efdfb8d4fdf248f4105d67ecad81d1694f" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "b41adcace24346d40e3cbc0ce6248e9bac73a8922b359d97fa1367b5384f0e81" . + "1bc5b0a34b09fbe1f1f9f357f41e1a8252401c90dc514db3e988a36d881695c9" . + "b076b4f163cd9801d0c024d132a6f639c70163c2d96413639caf4dae9c944510" . + "db0727489431e7b54f401fa0229d571c24fec20bc0ba65ad7b93bdbe672dfeaf" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "37d2f648d3acbedcddc99f3760f953a9624f9f0e862548d57929651a9a873f6f" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + "c2a67ea20fa599834127bb7ad747a50da858105c24ac7d56221bee39fdb9d813" . + "5056fc1a750dc901179ba908ead42def225d4212dbc0709adeec9f4072355745" . + . + "c8838ef709cafc872425f600d57f63833e4d56bfc2b6fa19d0c9db970203eedb" . + "1a00fac92de89b3b06e4dcfb650e3c4224cdcb18f92a10a3467600cb30803213" . + "2c225a5b5a7467d869d60e697f677c5a20d068b2e3fae593b3e141a11236e7cb" . + "372292fbc697fdc94d1fbc74a2e0c123ab63d018991e265229938fd96735422b" . + "8d966302e5da0cd25af217479bd3b2e245fb7162e3f5ed3c9f6554fa96f85cfd" . + "76109c291e4137fed9c20205f3d5aecae1481813dbf43e7663168839f657df2a" . + "647fff338c39f4397dbcc701af00118e2fde12c38ee32da9f9b947cac08d19a3" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "99ca2ff5a10189a322cfa328fbfcb9311b1d60db674f1e58cb72ae4ae4ee779d" . + "c32258116fc5820123fed50bff6cc339d905df30fb9474f7cd5b5abf5f7c604c" . + "99f6a6ca488822555321e91652be3ffc64200ec01cdca10c31adf6a43bd2f522" . + "da54e87832b27f41259dd5eb9d072133ecfc46d013c60e04bbe0e5144f197ac7" . + . + "86d869fbccaefa5411b184a3dd55ef776c760966697fb20b5d29a20c93e37304" . + "5064367da3be1535f4db9adf3e04eca9628f40ab4a900cecdc290b3de6436e03" . + "e0673971b79a9c221a04a56f1716bbc5773a8b0e0e4a96809de782571b715690" . + "961c112e9572fac19dc6c211ca25beeb58461c83908402ddae7fa031faa32179" . + "eebae5063ad697af8c5ba720c8950f74040bb0cf204d5c15d119c9f46d9abbd4" . + "105903f0ca93fd15a9ac072cc3fbc0a06c41385d9b322ac1d75a677c9bb5ed14" . + "240f85d03d65734eddfadb1221ca575f58a45e2308ec061b94a290d5b8337465" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "076d8c0bff3faa528eb514f553ed3bf526b5af94cfd483fd6f759c5275497b2f" . + "9c281de8ed0d8c2b2471f86ff01ee1f9681b635f94137b3b1cbc89a074259432" . + "218edf21e07fe5a31adbd81af30368dd52e12c6d6d0b1c0e91a0f6a2a3de446c" . + "979bccff9560a56271f3429b3a8d5f8958b58e3561ac9b9eccd531a516a73151" . + . + "5bea2d4b42ded2aefe85872ca27bf0959528855f5126c6235b24f9fc747c7096" . + "1c8a68d976bd69839c39304805fb83b05402ef2e0d2f7ec29d67339d8275df36" . + "efe22a33b5b1169085e64ad6f92918bfce28f8ec0d56b5af64c124ef18e2f2d7" . + "6e566fb673f401e094a3772df49eec5d85824efb3763e5d3e09548ab55a7fb88" . + "50d981a7cb9d2a62ea4ec479539ba9a1289d3286168d26d4b0ae239a75529146" . + "2cb8322922ce15dc86cd918999814f8f8f321e7c5c36cc45af010aabeeeed03a" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "eb0f25fc55526a7458d4ccaefa2a7d00da3d5f565264bb5bdf27c630318b1a49" . + "44dd0f0602d1eff0503d1b56ec00dee5f3875d35c13bae50a1f4ed6758f506b2" . + "13a6abbc563324715569603627e0644cd78ac05f17e02f3386abaa3901fa8d52" . + "cdd0cd68c26901bb647a6996cf4d1d643dd35e3c359079e8ac12133876720c00" . + . + "a0795236730981e8244d66e1a7188f2990fdf275a972d65607101f2deae1649a" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "c3cac3d8cc81850d167f3882b70c12cceef166bc16500c286823bae9bb03f33d" . + "a970c117b5086b15000086785464695fa6fe6680efc69621d0ab5c5ae8be8be2" . + "a0795236730981e8244d66e1a7188f2990fdf275a972d65607101f2deae1649a" . + "bcd3168182e335775f78787fd88129519d6a7e282c4583f88d730f21de25a45b" . + "5d257421883b7f655c212c93ca0eb629551beb8db4bc0aa4f24bef6d7bc8261e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "343c708345ae97958932da69e6b77ad34482f209c14c84c4158478870fb9837d" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "8ea4aa63c2d074b359b26bd8ba7ce3c5baafb4ad98f6c14490bed880e2ca6e59" . + "7a02a794babfcd1a2c9394e021e9e07e98dc203a632239448046213e6c4cff26" . + . + "b04efef9db83f956532d56e7f99722fdda6b068e8ec226d963355a8270a268de" . + "cdb5698a5f1c6efce0208038111239616a20240ebadd19ea0801b1f81b09e854" . + "5b5a97bc08ea49c7fb59a6cbff98cf1df5adf4cbe4f04b11094f8b7036199bd0" . + "3fbe30f5e97a1bd554a5fbf42300af1ee40961a08351401d5329b20da0923e59" . + "b04efef9db83f956532d56e7f99722fdda6b068e8ec226d963355a8270a268de" . + "d90ca40c874fef5f1bd45eb0edd26f23e1d30a67e9c2fd49abdee71ee878524a" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "0d77e4c9e47871f3da16931f521d60262b65b00240f9c40256f8e6a323bc2805" . + "b6ef7ef8fe336737bef2bddf25d3f8b895eb8766d02817c79ae9c8eda2f911a8" . + "d189b4ef9702a02d5e19fbe72ae783e6d2d671f00ec867ed26395a7aae8fc9d2" . + "bd6f891b34179449ce5343cc83a4dea38e3f935a2006aed8f035e2d518d5489c" . + . + "2491ca9b4d8b7a42d09388400cb858e6eaccfab6eee74cd356d935895f34814f" . + "e46e2b945db29f6b736ed286a8405e219d55bce8e898d40155db91fc44afe8f8" . + "d0fbbe4361d89474d7861c1ee0c1d898f46980711e054b4bab36eb4bbb069acd" . + "15fc7dba8cdb48931c2bc5be5277cc54d84548f143d67cb17ea22c8d40103d50" . + "2491ca9b4d8b7a42d09388400cb858e6eaccfab6eee74cd356d935895f34814f" . + "de8a37a748713fe1c0afa22911c13fc2653384e9bafff3fc560dfbc8cd7b4e23" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e2d0d91520cbb524017b17d6692a1ff8cb556ccf418ac63d91c8fa65561c0f27" . + "310eaa488a0197760ee587443ec8064bbbc2e62d16d6970ed6dd6438a38deaf9" . + "0df54ae531611f496ad6891f3b5d5b7428b44bfdd049037706bbc0a7077cbd6b" . + "622cac0638a580883391c4e663af7c80a0a17c9e70125c7c9913652f3055df9b" . + . + "8b708c2576352fea4472f87ab9758acbfb6a18a6b51de03a7cb2d0146f43ba14" . + "a7c4abd8137247e91ed78691183760ae31a298ee67ba192d1075603e01d73960" . + "06b0f31fc4913ccbf61717d91bd368b0aa0cef1f9a909c134ea1f0113f60d548" . + "03dde32747441418f8bbb7b6cbc148de8ed3e0c20f2b2d294ae6f38ba28f607a" . + "6e02d9a273626a9b18542df47df92f3439df1ddc57932fdac7ee71e9191998a7" . + "1c423264a3002dae42c5475370cdb917f6d463c2676aae7787c6ae05c06d7222" . + "5d257421883b7f655c212c93ca0eb629551beb8db4bc0aa4f24bef6d7bc8261e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f1479a89f591404c1effd942e56ff1ff649866923a60b706ef4c3850875a871e" . + "bdf448efd15e55ffc5b66c8ab743637ebead0f9e273f7cf60ea30ef50dbd6401" . + "13b7e54f6299646e7d67d804275637f687c9ea9a045abe355884af57827a1cc8" . + "7ca385f523821d15a4ea7fa9d38e5d33dc4f6fe8f9d0895bac937b5f175b7f1f" . + . + "f987eede86b84e0747a1a8f68fe9b69cda682fdf57aa25174f0ab54e8ac9f0f7" . + "4651ffca88a3a12aa81cecbb362651b498e6754b0f2dff81fe263447ba3121b8" . + "4bd943933ca57c87db85cc28070a745d95125b364012db5925d6b432bd3e3e39" . + "e70305867276a7890c919ff3fdda4ce8c85c656deae2ace3988340d440c256f7" . + "104f569c8056d961d8ca5590a918203c5d61d3ea234b3e9608331b1185478a97" . + "5ea05ed2b22bd0f1f112039c6e339e62b953c078b53209d859eaac0e6ba3a3e2" . + "f8047476cfb6537ff369ea2eab3f3fda13c9906a8e37d2e1c21f245827919d90" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9c019b45ceee64eaaf304cc00dd183d92a25de0a4154a8e7581d54b5fb613e80" . + "c2ed0724724a299d82403fca852732774d82fc098b6aaad08009a0c41c9db94c" . + "d98e6f44a0a7a752120c5df2871212e521e59e3a5315b3446db1a5524d9174cc" . + "d3bea580995b60d85d4e6cd98d86d6522f6d13bea0f08d64e99bc3952755bde8" . + . + "b3c16f79ed506afe1f02791d060570bd802dcddc98a2a6a3c4a0a585ee8d204a" . + "3eb797dab7a2f7687294b1b5e9df54fa3e692b4aabd0d14d011dc634c83e280b" . + "57dfc90cb639b283df540cb36515c7994fcefdc36fc6d82c689eb6db4251fa55" . + "a216a4c935b9b55a080be54c384156f7fff1b2690328be5a532b346820e2104f" . + "25f3e21601a1f48c4d758fa064a55be277eaf83dcc522c02c1da461ad0f2a860" . + "5d792f4c29c18f43350282350575b739d476ce47dd23466cf7181d850392cf5c" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "9446c7152122ccb4f61fabfbb4330598959bdfc600ab7478a176537e9ec76d55" . + "c38321172a808399e5ce2baaf2d61bb774bb19735c8b0251733b503258ca25c3" . + "b535b578e5a7f334523cbdc86971d8fbd03750a585f4738f371f3300a1d2b70a" . + "9408e4756f35a300de60569534ca6bff143e8250a03244e63edf1aea1a998a2e" . + . + "4d67b4be40fc22e5786a6af14855abe28a4939dc6161c2da257519dd5e8ccde0" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "9c6db3986fe4d429d9c29aad4fad55dc4941f38f96a1aabaef59e633f148f7c1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f07366f476b87cf7a68e775b44221dc679f3e350105a5f3f4cb54f29297603b7" . + "3ea7ffed0bf06f7d388020b5f985607f121244b8ea7e10a41ea0cf55526f4220" . + . + "b6af3b9cff5be24a3ee4333f375062bc1cbb3ae8a10d427998d365f7cbc0b877" . + "d04b2dde477fb270efc87fd0d5d88fc1cf40f084b06ad972b846eb62023c4646" . + "802dbbd0ee0d5920cc79b65e89fb4383f952893119c5b2030e9bc76fe93f4b09" . + "b1fe06d40bf6667372aa6836a985e3e6b3840d74560e266fdbdd5ff53f9d36e7" . + "58134349701f656575f3c247706dbe60dbdbe8662201ce826b63c0118f8f14d6" . + "687a9c46ea6724bd7f27621e77453ccec60571cfea4e969356fb4c4beb7b4186" . + "15b5c2c2179f247d0f7579284d1286178462fd0aa1105f00dcca1f9a7d45ca3d" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4dc1262fbd89d021f740c816d8e99ed1a84774d0007e782ee64138b0ca97f0dd" . + "caef7f8939854b5f95e2c6519f7b5d857fd853c051ee8e839e115005ca2ec226" . + "bf12209252fc0da42d41aff4356349f309e038155e3328d2319f4defee86cd61" . + "50bc900f80ee321929467f88b136fd067c0e8bb0ced143afcc454533919ace37" . + . + "00f0964fcea786335ed51362c2e570c16b2a32968fd561c6a3150653c46e83bb" . + "072b8ca37870f73bdd0e076906adc599428987c701928079ed75a9642870a152" . + "f15a65515f8fad981b4e7965f4be849d53b8d27d8b9e6f9d9cdec85d87ad4fe5" . + "d0ba6820c2fc60a4d32557902d0ce2508c5a84725dddbe245bf263d37aa31c03" . + "46c2cd8c4083e4085cdbfef9535ad10f0bc953eaddcef0383669cfe4336178b9" . + "fcd89d51dc37eeb03418cc1203092a3f62ab3fd60e4067cd5533862ec5420961" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd223a3fe423eb7115d5bda9a3a070f70faae457d3953b92c8967221552e06c3" . + "779a159c1bad5b2daded91e4832fe5d5302f86894b1951d90ac9878a3231f76f" . + "a5e8c9ef3636e9164f805a3fd470baf253efef5cbe7930d02fce03dc8b5d78e9" . + "a6a41c35b58eeadf461d94c4ba2b7d6d9c676fb32ca1e87866df447afe556875" . + . + "8f9df335082dcc48c6914a6999333922f37d0eb3f8d499fede73f24dfe67859b" . + "07fbc97aeafb80a4497cadbb986f64127d5e918a0e4eab3c093fdec5805788ec" . + "817512e524ec25ed2ea278f9bfe72e9ea3ed19b347ff4ca70a4ff99277c9f3b6" . + "afb23120eee569074b4b16b94781ab03ad311011c6892ce0881bd1044a12ba26" . + "a9d68c156945a4fe8eea10056c13b6f286bd4943e077fd5aa2b3df0c4020e08f" . + "fe51e5086d44b15b703dbbe422251d7c56727da6dbc538be7961763b5938395d" . + "6864d9e2ff4528be2f2b6b60d8e9719db7ddec879f711a9556a77a83efbb22ea" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eb9ebda9756d6c84edf566af2bd81a62452965eb393faddd76e40ea70d015863" . + "601590e85405649a300ef2fab3974c94cae80060e6aa72ff48718ea7e0a8c203" . + "9f0251eb27a86ecbad922695a7d80b2adcce2a1c3d61e737fe83e898253fc4b3" . + "3a13a94af4dcef6c99804a88342d094fda30e8499db022eab0ea44df19ae5748" . + . + "a21e628d80b8e91f71309ad2c8ade5ce9748938cc1c840c8ff5dec2fb9c4c5b0" . + "b15e8761b2b689419d3b3daa933bb34c99ac081d38bc564c529eb57cfd30c7c1" . + "b3f226147c4b9272043a35fc04e84b7bd3cf869815de1ec52041652474531ab9" . + "f3980393e81693f01cb804ae1c37df97d18b23d45ba9ef8d63f9415d46258487" . + "5937d5bd41a68df10371759cbfef617de1e8ed31c0f914dea79fe749e3617819" . + "25e5f751c1f5656857f3bd534a614cf1d810c29745a1bcb9ef9b6db030fc13c8" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e2b8a2fc85c820989e1360c35ac8739eb6d9e94196539aed884a564c4b105779" . + "566d1bd5cfdcd9a4826277abc752c39917e1fc20a1d3ea0b254cec48b99f1f64" . + "5101c1181300e3b2737ea6c50f3badce3130bf342b32a0c81e01091451519cc4" . + "ccdedcc703e7fa571d3d87cea685ee3de0df2c4ebf0ef30c502a7c1c32717a1e" . + . + "331ec39a40e2a2fde33b778dc1ef7d56fce87848ecc105407b00f7c969d87d10" . + "98dadff672642e00e6c9aa8a255e52a939c94cdbfe7f70b51f022711a932a38d" . + "03f307d37cf2d7e3057ebcc9e31ad0d462d86a5da967007730f9f0b16eed982c" . + "ff35fcb63774b492431d8b8127673478b666b27f1a7f260097ca9ba6e832b879" . + "2c2de79b06826ec9659434dc1574931c516ea7b7c0c400d03d996638a805e6a0" . + "5bd8b160f7f94ef42ffd2a7dfc90915aaac0d5b03fba1ea899554e1f9997652a" . + "9e89586a202b11abf4852eafa257f84efe658bf3c4b30ff94439e6f3856e3f1b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7e6b244e873f03aedc0a3365f38cababf0b3c483622ef15a5b01c95ef83afd52" . + "a5a7df96563d3bc3c6d00471b28597840f326a0a0a9d0e35e4f1caed2142127f" . + "c8a860fe928d73630cfa681d1d4ed55eb07c69a3dcf6891563b5ced4e1d959b2" . + "3c38d8b8d35dea92dc585e84ca31957f6827d59200430a1d869b6df3a0fa42af" . + . + "3a258d894a2f6c355a9913d6e5d3564ab721c3a3da6c67d40208d630934153b7" . + "52741bba3cab4a76d6cb96924a791b100492404e57f05c2e6505b8ecc483e46d" . + "175ac280818c387906c568f8734a20f3145ba0ccfe4942e5dcb069d896d88df2" . + "aa0e03ac1c33000bb4a060b675588e3fd02e66ff55ccb77dd758272d93e80a5f" . + "ae48adb45b7fc26a601477ec783334a38959f62bf03a60712741f8fc735b6dd5" . + "566ea48c3eed8bb0e93257c4572c72f3670d7e09a14c55ca03dcb5e55e40e4e5" . + "c5e8e6251818930fc1c883fd9295662f965a979b664ae59df3299865a3cac35b" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c9faa0cb9879706e566d3a343ae4351ad4e4838e63a7f33499ca6699a0261566" . + "d3c46a217446de3305dbd8c79fb4cb61d5a605a214d71ad6abf12ff97d8cdc10" . + "bdcf396bf8109eb64fd0b3f5a7c8052d0218edef030649478ca0c35333f0e396" . + "75a32ceef083d8c607211aae44920d9e5ed9d203d51fd772f199881e77ca7c39" . + . + "9379fae2bc714686b8ec6797afd4f9ab37389e05b791bed545dd21703f212bc1" . + "599c39bba08a29bc84ce08771686c043366004dda0dfb6a1bbce2661210b8bfd" . + "4c7ead98b4d7a86cfb92302cdd5ce694a3343d1f1f304149889d3203791f1646" . + "da9a37dc8aff9f2048c737cc65184006a8f8b13d2f7b1b756bffc66bffd20d82" . + "2d9e3fe4b8505c20563956aa7c751984b49b7b1bc50943cc92cfb6732c793832" . + "91a28ab7030b87a697821eb910f6b3f69cb536b57dec3c8ef75f8035b3703e2b" . + "91d7558f8dc8c43386d82b17a63f3ed6796806f523fb46e096ec1e1bbea19ced" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c51e1496d0b6aa3019157d936aba21710a2bee5de4eff73d0d8599540ac99030" . + "60632feda92f6f3d2143d9c6be7eb0bd1d4b9ce7fd9fff2d333b3204dc925440" . + "59306dffab125217c5be20c6ee2114a5942417814a9af834264b6961021e3321" . + "83e6c927e320a345608161fc449cd36c248b7f9d8df4e6cf7aadd2e8790872d0" . + . + "1d8ee25c327a05900c22d232d91b08f06f2ce47c2415f66e95b91d554c9ace88" . + "27b2224533505d5f951e064df8fc6f9d2318154bd4004065437d58cc2cddd5f5" . + "fa4d9c80ca5c6732b0b8d8dcb3c35f470b550beba2dabd65668bed29dba3f07a" . + "95d03459560b3d1583c1d0fe75a205065ed7ca28cc324085e59bb34f25c548e9" . + "bdb472fd5a2948b9e002f14b93fca32b5e014cf0657cb35cebc4e15347086d53" . + "630034da67e293904af7be02c4149cacd9eed300c3fd3cbd80f52cc11b7d01d1" . + "891d64170fbc75bd89924f875df71bdc5df9739091b9c9154d0b4c20cf4860f6" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "24b0830589284ff3915c03d6012f9f65367c82e1a58058f084b2d75bcc272e22" . + "067228384bbe28af84f3ca5b8e8bd8241af5d4178ea00f46f5d06a9f0682af5d" . + "bf7c0dc69325611b59a24dc1b3e4919e319d361e814469872165807eea4d1bce" . + "6042ddf98a6f7db2b114bb005c2e83f27878f73f833ccf8daa111cfc475f60ec" . + . + "3c218d6f10239246785118dec5d4586e958ca1393c4a596b9e9f9b9e0bdd42c7" . + "27e01d08ba6dd0ed5f67dabdfa6a30be9434d04a53922097f1141a7ba3843416" . + "6ca8f66a407c72db7359cee7833c72ca9709cbf9397ee1593d8f3e1e21b3940e" . + "590c4029a63d3533371e92f735998be9faa2aad62f2146c0aee590cce9242853" . + "6694e4e5db51156985e1b209eeaf02a83643546a63232bfaad8379d4b80461cd" . + "7435515e345e5f6cc45f841043889e0fac30f6f6be8dadcc6012bcb0ac8db407" . + "6321a3aeca976acc381617ca3f4f7528b06f8e13cc8a8fe41c6d3a611b0b0381" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "852da716713edf80efff58973da1f946b9683e14bd8f884a24ed8e6ceeb0b476" . + "ed54859b869e19d57dcf6774659903978c1fbcdc0e9f8438ce53f4dd1d23143f" . + "687ef2d46dbf343932c7106c32694317e68b8a6b78fb9054a6d5c2c7c5187645" . + "ef2756aeb79987e8fc78896f63db2491a59b11bd60f44e2857c0b1afa0cf17f6" . + . + "06fbdfea4e96090e28b7240863bc07a617446ce09bc9a150b35b7b06904771f1" . + "99c0ecd2108c77e06550fa00cab8bd39d454334fa5bbf59f6475fb2df92bd716" . + "e88020e3aab3ca808ffd44b3f592241b4adb280eb93e0959d74d56f2f15b4bb1" . + "1244e471798ab1c1c1765ad755c2227fe52536fe7512db6f25ed8e5cfd9fa305" . + "770da4c5283f9ef77f5094634d82e496c1f46cd6fb26e31abdd5f6ea102f681d" . + "be15c0d8e98be2ae80c73e452d587f674dbd67d9f28bfe0720640916437812ed" . + "d896bd3f194bb428377c4ce9d02b928e691e3ae08d7fba87151d1e6ae9be76ef" . + "0fbbeadcad014819126a1c6f878cb4ab77cd410f41f8b5182b75f3bdd0a7026f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f6b300aabe605e6ae8993cc34b1990c32ec754a0e51880e36697de44858cc09b" . + "5f79d0a20ceb3a45d3b75de5d61b5ff1b5c656231b87f158a4b7c5bc9e76a445" . + "2a155ab7ee9f2edec2beb6e18b8655b8632b073cd836797a608bdafee7960bcb" . + "59d371610532c29d3ba1fbc1ea3ee787c1a93e6ee5753910294c102442e040fe" . + . + "4d4db55a5e2d059544cd547410169323ddaa4c1c738677353f20da24234d1e5a" . + "50fad8fa745b74134e83bd045cbb29810a5d9e9807139a0c84c715fc25b304ea" . + "19279e2cbca001e01ecce306ecec6e699d6ad32bdfb1ccfd103377eac603dfc6" . + "2de5a1932d7be6044dc9e81b0b750bb47fe05f3ad90af93205ab0326d48ad436" . + "6f6bf9429f501e5ee5f04ada7fdf99fb45e770d7401fbb1d789432d4150133e2" . + "ce4a4da6218e3ff3d9b160eda8b73705ee22cda93dbff98aee5622560666fd0d" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "19a4c974fb04b7bfddf445369050ced568b15afdf91650fd387aee095fe87548" . + "dab0f6450b23792699760a7702fa9b353ab2171f27bf865b727512977c2b8566" . + "2f487599defda5d00290545f32bd17631bef25cad1415f542b307018d8e5cbdb" . + "18503addc9a158603202bcd9010de3c1284c4438e657cf6144df13f9b58839af" . + . + "c70a0cc267f798fdedb9c0219afcfa5196a50da4c18e9de39b49686981104f93" . + "83b42a32c4bae656e00ec1b6c4d7de269096a5ea85b1bba73409c0a0ea3133ae" . + "dd4a2e6b3d5388bad4a6a1964751e40bc954f826773ad7ab0bf82bfe93f36f53" . + "1054520cf06a2f28cd8b8f76081da66cb074dd175258af23d1a30594c315d238" . + "c70a0cc267f798fdedb9c0219afcfa5196a50da4c18e9de39b49686981104f93" . + "ef1ead8a9ad8897e4f5eb4fca4007a4c8824befd8ab08427ed5d0ded5cf316bd" . + "37be69267092a8a68d7592883ad4a039a18058634d523bcc56ad64981a508c40" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "5cfaada95325307a38f70aa405408c13fdc018a5ad14f4227fc3a8396460c1a2" . + "49c33c744b6f97de00a3c01f12563e405bbb0cde2367ee0288a4dc96cd3e705a" . + "b56cedd6a197f3b2fdc1af8b351ef174b9b51581a848ba0ea4c9141a2b0e5f76" . + "2392a6089012a119d0c54f2ddef5b87c24cbd6eb824918b0cbf51a3d46477cfd" . + . + "a346c911ee274b3c46ba2239d3aacdc0394d7109f34f2fa5ca105e3a1ce23ec3" . + "7f941f0fc9f26f9233f8be9c1c907c60c61d96dae0d7892e8202bc804370dda4" . + "70fa41883a3634c6af50afec8da62693f6ab5c92c2356ffb6d4ed2c2d4597b01" . + "df3e8bdb8c701466c16198ffb5c0d9f3033123089befdad2bcc3820e64370bf9" . + "521ba292f976c8e15aff577f562260a1a07c37200260c7caae1fa37f13821e7a" . + "678fb42c61a1833c0b1cecb0d5a2107140568cae8ee43e90698390dae6ee7760" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "408d4850a08bddbd4a4ca2b3bddece8e79b8b63e1a5dfa8307c59335ac9e0212" . + "e640e3b94c36bb6ab3a9c2a5a77ee2bf4e389619f559ce5e6b8e53790546cddc" . + "ee3be2e62cb1f8b65e016cf2a2e5d68a4daa5f827525a350af92ad0ad919c096" . + "f29a9aebd97cbd6fe592ce56d6d6e50fe71011a211f29fd59be4b17a5d52f36b" . + . + "6d9f908f65fb23b0aca7a179837efe5dd42e3735010cbe95fab4a3cc35933920" . + "6cb903bb0e85459642fb716c6216de3d310bd210d9fafdd5f0533c76ec7da02e" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "ec7a2999a0f26572e8c92a0364438b12a105014d6f541c4ff3d09f4d9de5be60" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "6c4c89ca1fb6510cd093e645ea5f0c777c5a4b41e62b1b97b3a8a4ca366c48ba" . + "72ca580519d446c2fac7f21cfd34ef1d83bb4d6ed0a98ff4d22455a5946e9672" . + "7a713336539385d8cf34c1e6b3db20dcf4bdcc04d9fa4e5e2488d605deb45008" . + "dec88c206ac3b77e12a6bc0c827040ff015da9dfc87dfe6c1d871c0411033269" . + . + "f89e8365e21d1145edcf82c36ec9a772d7334cc705ce9f5789235e459ba6bab6" . + "e94ea84dd94641069fa650091738e8c76339cbfd6ff2163bb141f7ce3db53e74" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + "73546fec7fb87e1e7e341651d8885ca8ede0806aa40a242d9b385543f6040d6f" . + "ccf4a58ab132ee0553e4ab9c2a9ff63c4360540312e91f8534d1bd4f8b4e6634" . + "da519a9b2959a344deb71f1aa1e74a73e09fe366f5370f21c6430d8543581468" . + "47ea5efa31cdbd9a3d7b10f1bce1c6c6e579c469f9a98b745bdef57833e918dd" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "68500aa80984feb3af507b896381266fbce95875cd4a4e84cefd320b885d2119" . + "b72a635a81041d9d7aa36037d995db8ab1e6a5ae77ec5a408bc86613c7dc4181" . + "bb02b83d5fe08e22fa6590fa4f4ddcfcd009b7f33f6e842cad3bc1fc7d732836" . + "252ef9ca7bd596064c9ff148be7d5d155fc79b16d35801a27f3629ed0db42ce0" . + . + "a0d9900eb9720ae552cb9737c72b7ca9e30219d401d94c9793356018eaca849b" . + "02dbbaebc11ce4c95b188789f913a83ffd0028bd6b81827f27652b844446fc15" . + "f661441324c09d177f5b71fee249a691d9a319687337f64b3f1d3e35c2626875" . + "b5df9f0b844dbc338923c6bc306fc6a5af31e1837dc80e3681e1be79f7cc212f" . + "c96b8a773b241c6480d1095538e7a1f7dcab8c612f1a176b91b2023b2af35d8d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b05c7a9a170727414de2b16381325db52d96fd02e349cc4f0b719c6f3c2d8b2d" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "bccd9bad7cb3365d19321c42acb5753f9d9717c7ecca7f42cc87ec72b8b665c4" . + "a894e77e27e5bbd7eeeb37926cc80e29ebb76c3b2d11032c367e98808b5df1d1" . + . + "10753e6dd376ad93f92299074fd25b587912a97a6e3d95b332c501b295f13170" . + "28f65239cf8ce8d2285d52a74a0cce9c2bfbe259914b770cf5de2bf46e554f4c" . + "4a93893eba7743f9a294ac076d15b8c0177f4db23e8cd930e3812e6928632c7d" . + "cf38d717b48f45d9b37c69ee7a72cc67848c8cd0fefeac1f2ccdfad615b340d2" . + "541487c3698140c65a873a876cae83c9384f5a765c5fd5e8cbfdf06cf6cd0d95" . + "80f5a8d31d8f39d999b52816aff870432065a51c05f75862ead4058dbb592fe0" . + "57849eb500e505f3f1cec6ea4e7a297b0ae245b92270a61bb1b32aea5f8a4a61" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1563a065bf2cda0ae31952fd75e037cc3347dab9bf97a51120716b36dc91a1c6" . + "6f2206c9c0455da64e480d2a551f35770f5455b0286bfdc6d5ec9b78df69f8bc" . + "74f2eec3f6501a4bb6811dd5a993f2275d97a64581ca0baa083752b518daba31" . + "a146deb767a262db0e8974d5dd095fd9e5357d4bf4cf34374133196741d04cf4" . + . + "706ec4f0182b438ea2a3bfe3372beb51a747e60c18cace0ab6e119feebf666b5" . + "25d6dccb98ca6f3757585d1fdecd7f8ebb5426e4f794808ddf58c194c4c9502a" . + "c7961cf65e9f8a964db1eaec78293691bf89da887a4b83fa38e6561a584f6a80" . + "850919cadf479891be14dc9b74a49fb8351112627bdc31d6cd3482cbcfcbf0dc" . + "251402948194d8f296ed0195c3f80deb5ca6dab0db0ec3b6e041a7fae6002e7d" . + "c1605097ec09361a13f6ad4dfa06880e14b659422500d8d0faf73fd7dc5f9992" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ea6773ce9bfa789a9fdd00da9efbc40867990e3d43081f18ca85c15927c1f027" . + "f56cddd02a052226dfbf51c1ade1185a50a52d8ea5c13b30d5b389764b21fa9f" . + "169eb5fe08e2196b4f52fe18c61c1f660a65514a96d9929f43423f02f40a0a7d" . + "e5f688948835c52fc9cc08762f95f63d31a3ac9f3f5421cdad62cbdd68e4c32e" . + . + "78cc1c87bf691a53f5df6cabc8ee126c1f57de25e32f9bbe69d0be0744cc699b" . + "74c570902a007c2e3eddb744a4c56bfc001f582732173b5086bb8748d4471938" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "7c3fdaf87e5d51a0ef8be3f59f03a8ef00d48843c0feb5f31efba2d3669fde3b" . + "e3e586328f8c8ef72fb95e780b4b80bf0d1549aaa0d4b4b74a521652f31a91d0" . + "936545d2bebaa3ac501242b6092f179a193a7e3f3b93c46c5253dbe795a94aa2" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "db6124978c93e8f52ffc6d9a59d13a429353c51b7487811ac2bd997657de413b" . + "b2e1cc7d9548b94b5bccbd9f6bd6c83ff3e92a0f271452ce70b876593f2c9259" . + . + "48cdc2376a540d51e42fa01d308a7020c22b64f5eeb0299dc3e9a5a463633e5d" . + "650f5348997a207fcff386a7baa9045e09c65abb05c42006963f62533db9b909" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + "65f02e64051d479122d4c09c1c72ddc860038e473a9d2691e0a1b09153c2d71b" . + "fd714045b6210b243c2892f3b8a81e37fd13170cce4e082faeb342ecd28a20fc" . + "8e0524866f407920e1ca2b1d9a9eb1e7084461b1d3d5d0bbd1e2f8ee8f474438" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e1aa850526418c74ecc375ac65fe9b24c582b9d52eb6f7a5c5a53c9e0ed0dec0" . + "7ea3b5fe9191e4cca6246f7b01dce874d90447e581c1e361d4e0c6c3b9a86f10" . + "a02549147e9b3da123b24d06902a804b3cf29fa4521ea904ba4ace26c221509e" . + "4b3f4b1b440b9581d550e9aa2ff44b15f8b91d63c50b35d2dd2ab838f2a82790" . + . + "5b747dff44e27e1b8150f250f39fb7584931e2e903323c51f7748e065b2a55d9" . + "5f92f0feed95851b0a42132d6512a404fa1485d738cad4dd3a137253dacf9095" . + "58a50b63a096cb71bf4f6f622906cf5beb9599ddbe00eda3456446ce8e072ba5" . + "2bf9c1c7b679ad681fc1466bd4c63cfc9f1315a791ad3bf86e080a7586c1db7e" . + "a1567dc43dfec93a4d2c1d487e6e1f4d42b90e1e3474f544303b742dc1f86a86" . + "b8e1f8795515cdf47af9ac3f5d6e857f9b7a8e1ee1e09a5bb6dce972e4f16468" . + "f266c31cc942520e6ee6c4afc4a834d3a3976ff9ab6a1b95c27fd01d812bb7e8" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "1ebcb7a793b538623e8a9db6075bd3a8ae73c044482599cac30b37ff49a68e87" . + "c9c24dac8d1707c2af7de1dd3fae8e678e5f3614322e2c717b6fc60d067d71ab" . + "a5e23ceb4c58f0c79dabff9cb5eb3cfc78ec1bb587ec05b5224eb697a17ff088" . + "70749d6c3a6756f4ee61ce3a22c27150244cf204194fc53ab9ad33f80e28d502" . + . + "0d425b865bcf55fd3068b18d29ad26e292a896af28f3ef33a95ee947f8da488a" . + "eb812481401a3e4136b6e3237339c1d20fa61ae9c36489e15cee2fd60f8e7766" . + "5e3c75f78221d52e3968445ede68b17beebc8aa838401586365a2ca121abca5a" . + "e9055490c68ea3b8c094dde507a9ed1fe3f21109d1e9541d526867a8a0e7adb3" . + "530dc369ea8498f987603de1934de401b2e794820ba6b8719838e2fc88a9488c" . + "7b115232966d9c59d654189a3ddec7106cb7347f7653619f67e287889f44cc0a" . + "044af855421b2e7e3e864e4aeca694eccd4a82ee648bfe486db899e3c32f0c79" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "ac953143775612e6c9dd5b9f311a4901208eb3db123c6a73b8f30b9a0cf2dd62" . + "401227171092b77ff669e7f0b50de6ac8220426607c8c14a0ffd76425fe34262" . + "16dc2d1956ab67afdc0d4d17c9aa550d9df2f2aeae38540df2cc990ebcc74341" . + "c253f77aafef06e70514aeb604a8250401f4ad3bf326d22441082e8b0c7d1fd4" . + "59f679e5bca5f4557dc853f2f6880cd7345b0badb8f2ae3de8770da34291d7e3" . + . + "9add10161e8845249ae3d75556dafdef76f49f8a4a7f9a99bd4ce7a39c435ffb" . + "1e2de41e0d335fd0087d1b1b8c6fa65d51c196e24d70bbb06e2e5e8f150b92cc" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "db1b581d9c34b05dbcbb59ec0f854aa9b287c77b99efbace481322012d435db2" . + "525c756039bf26850358b389d6e8cac442b5a8280147fed6cb33475a01109814" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "2a64d131c3345cc70d0892c05ab487f3f96cbdfde1a15b116abd0c3854b9da41" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "aa8bf84cbdcfc55bb3cf3be97ebb9126931a9c4fc4725b9e80bd7e4559df600a" . + "b5bf883119d17bc56ebd4c28b6c5a96b4953399ed165effac3b19ed7ebf18575" . + . + "2596e384dab2c607e72f33ec523774e76962aad9b2b36db352072ae153b0d63f" . + "8b854ae57dc9252e1ff2d76b72e855527793775729d549f0cb386f4b2cd37830" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "2596e384dab2c607e72f33ec523774e76962aad9b2b36db352072ae153b0d63f" . + "4ecbae3875d107d59e15257ea16860c617f555bc24db317ba7c8932f057f0aed" . + "bcf5143374e1eaa78d276b2a2f23ad328666cb191d6befce744c9c00894c0b99" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f3d6c76049b21c5ab018f9e934d189d75f2de64dd3109233a6084dae54307611" . + "4d900aec3a3b0488ed02ae19fde73a192d8434bb8739a1af4db0cc3047cd09f1" . + "996cedc66cc25e0568952e37090f776df74f0c4b35d80f3411785c2eb8978572" . + "603024a4eb12050794f0f00a593c76d5dd2f15c4a34a6164217987160e093b9c" . + . + "d807cd1419213b68c0b531fbed9865b64e57573ccfbec8d477d10054fb8f7e21" . + "af756864dc9af1dd8b28ba1631e656aa31873cf5e65ec7d02974ed5d605bcde7" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "9d2934420be2600044cf9f34dfb65fe538aedde7faae5d14cc579eece6ed87e3" . + "bf0b34a8a5f9f090a4ac38275090ca66fe3328ebae595a1bb61a3608c6542c6c" . + "a11da42411960bee23dfcacc92a2029ffeddaf187ccf3860cac38ab7701b67f6" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "cad16f008bcf705e45feca48066fc644e5671bff38fb14cb7dd25afec830a7b6" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "0a15b29d0956f4bdb4edc7d81be86c7ab5d0502df465888e222c57252682c5e2" . + "37210089789abce1e3995d28f3b636ca66e27113327a4d5fde53d315b9567b33" . + . + "ce2d965139f207c47fc0027084a6d374cb11b713bbcc3c93805574799b40003e" . + "16f00dc80e3b3d687641bb4efed511d10266be29aebda0ff7c0a91b012529461" . + "d8fd11425b096a14662a314fa299fdbf2285c7e3fb2fa32cc8089fbc15c3121f" . + "9efe7d539ac4f56412e410c87bbb50f222c547d1d49834a07fa7f5e8587aff3a" . + "a1a90e03af865674616e74a7f6d3c8e5bb32315300cab9631440ca915442966c" . + "68269e36a4be45bb3e47536719fa31e74f68ce059e5a58d4082d1c0d2871def8" . + "1a50f074e990f22c2e9b507f8c11d6b932384151aa0ed19036a71296058af336" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "61faccb5bf3281b84e97c9efd8576057801ae46db31283f5a711bd2cab79d818" . + "efa77cf227082f08e7eca1aec89440c4cb1b162b73b8ac44b024cee7b71205e1" . + "4549a703b211a952ad3b6fe9c526b72045932f06222d7d3f306cf9f873986d1c" . + "7599b54259628960596641519d46fc77e9975ae8bc6ac141165ff365a1645e48" . + . + "070d718c7f45cc27ccbe332eaece1014094361f6f0bb8b039e6c189201bd139a" . + "e2bf0e864c5eb746c364b313ceacf0475bd6f14b7159e9fca00e4cac4832882f" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + "8f2ac1221930aa415b67bfd64caaa0217c60f5ed2d02ea94e4abb49b9dcf6a08" . + "3ca1f91790855aaff605bd6698dec91f4d81c60b8f7dcb4c5c1cdd690333a755" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "b95ad8e1809f35e7590629ff30f53a6c9c56f5ab9ec91d224a39cf477bb0715f" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "23e060e1286f44dd00c534b669e7365530525c871a273c1f1f02289193136eaf" . + "8158a1053c7d4ff07da539da1669d1c0421c4959774aec2307c7651ab6ab3983" . + . + "cc9582480f4f279e2597ad8d1c1d3acc12393310a90b2901c5e41ad3771c11b8" . + "6ab8c925c82fa6d96cc2231b077548392c6c5aaa54bd76f1c35f42fa0d09e938" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "afded94c012139168e5b4c019009e827b25174dff2631ac2f663eb517503851e" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "37e23b3b96ff163a24c93317b43f0414296c5436110e561658b9fb9d1f2e7ff4" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "65a5431348514082974da789e400a5e2b66520f8406712bb161cfc3fc9cc0256" . + "6e4f9227e97d1d249e23a10c33663b30d3f8e83c5f1bcf3cef97cdb4323ca981" . + . + "8421ba1f0e1cbdad94ba2265e828891662a48fb4d292a74f84ac78d3cb57c87c" . + "576bfbcef4924cb45e040489da9cbb8c8ae4c02db18f845738e0c09fcc97e2b2" . + "2ccbaa9f1cd96fdadad41b139297d91480420ee9ae49b99f8498cd067319fea9" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "5ad4a5cd83f17078274e03eb880ac0c93c70104c014497f280b23def76c65e44" . + "1435842348aac5ebd5bab54ce5440d6a9214ba764a82a8e6782e076b7fb93a66" . + "b0fc9745eba2c7af3d37b27b5859bf2abd53f112f659e8f0ac41ee4eb3c673d2" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "7357a7d2c03175e95f9d8168e2ee590b01192ac92f8138a290f8554b542f2a2c" . + "b653078425ebdce59b5007168b2fcd098dd107c1a439c9665b825f2ff5ca9e18" . + "54231ffe6eb84f96da19f7ea6f8690e935ad4f180549cdd38b473664d086176f" . + "e54ac3223298465ef1c67eaa99372afb4e54de0adb0b90b9bf1e6cd8c9e20910" . + . + "22427864fc1e37ebb7a930d6f1e179d0765b21acbf409a8a43134186de564ae7" . + "3892706385d31e5b8d811a568b7a6b58f140441e1ad17753e8fb3dd9d9b57b7a" . + "efa77cf227082f08e7eca1aec89440c4cb1b162b73b8ac44b024cee7b71205e1" . + "b180913f5c437da34eaaeeac350596f36e96a532e4f2214c83b5a5829bc158dd" . + "fd48b6b43ef34ec6b976e6bf627f3bd475c0f82ff67700e0d1dc750a07102555" . + "6afb28df75b7fd04d3f65de96224fd7fb2923e8d43d251db3be00f16041dc9a6" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "99516e7bb5d0868e27d951c3f031f4ee9c848871ea44045812f07d16f49ca67f" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "bb253804dfa97066befb65dac559d3058537dd7a9e05d83ff98a6bd4f66dbd62" . + "65a784b8be258341a39818bde986aafdc9e7b34766945392380b4d89860c4651" . + . + "f3efb4993a7d6b04f07e87a2095461783e8984fca1955da71a507c0ab198a5a4" . + "6c8d1ec97a3a7f42ef6cf592553d9bf1edfc7b8471177a22d3bd6471fa72b1f7" . + "028a084ea5cb638c3df5aaa1c0f65a5297f8cc4abbdc8879da470f1c5d98d618" . + "ad6d85223d2fecf2a728e710cd0c84ec6eb54f14c04657b98372b550a5be6b58" . + "17f947e3d96b46fe474ea85a7117a5bcac5d046c1e2bad31093f7f1d5b10be3c" . + "ca62dbf747b640c03dd2100289423c01912fd06e7ea06723d95899c81bd4febd" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "c4ce2b453b9159e2b27c8a7536c8d112cdbf41430aba455265330babc721a203" . + "8f9e48ff5cb39f83a7dd78010435226ddb8d6c75cd83fc0a2d4cfe69d8081fe6" . + "7e4884504b9a6e1ff06a6822283ffceb0de8452c5ddf75954f906a4af7a30b5a" . + "737854bae806e289836a1799c36227340462920622d0a259807967458f9142c0" . + . + "fbce5fa5c621b659f58b0a5865288a3e035da613081ed30836cc2d9057ab26af" . + "609562d0471ad40a4aa0693ce591d9a4e6a0ac6e208a40b2969c6e24c7c0451a" . + "0a14b674527dd969ca0cc1bd9a560028025c543d0b8c2323012c33f2fcd28400" . + "6ddb17a81e6dbf16ab235922eb6ec03fc40bc781d88243789443d19b0d31c619" . + "11b520712fd9b0220233c23b13d9f79f1b7e2c33176c06749fed602898deb387" . + "de2ba755e043d77f820b58fe7845ccd604cd5af7a13c4a62dab420ed10e98595" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "d172f76216f9fcc0f5a71b572680f6039ceab643de0919b4df82ce65186cb1ba" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d6aa194cadfb9dc8d88d64cccd641f979503ee14276599151fc186bcb69c1696" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "0e29e735931efb29b0c4234a2a526981986e26224ed65ed45f15fab0718d9562" . + "e535463a1e38d891a49c65dd7e6b1cf6b270f9e7128a18ca596c6c563d577fb0" . + . + "0ec9e246ff90ba332345033c319ad52fcaac4f1b649e2afba262e7ff87914c69" . + "2838f761ba98916f108872860ecf2edff0c3b68a301eadc323bdfe317defb197" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "d8a5d9a957d0d5157fce34034513024ac29756791fce83a08343c29219c53aa9" . + "35d98d7d7191a1abecfa051e2a69310ae781bc0d0448565d7db4016be56ae6f6" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "72f6eeb2b895e42a74f2d4f78b3662c0cc2e171a54aa31b930f579d75236725e" . + "4f1852774f1625de6eb3360245cf263a66fa34b660e1245d3b4905e22ace1171" . + "e84d880e5ec490367adbb1c10000092385329a486028b66fe8f2b912f9e99bf8" . + "0dfed28e93683b7fd47329709dba7737e23c2a782f7543387183ba71b9ca3a51" . + . + "e32b40bba3b8c30faa415ff88f728aa53499bc5bb65a489125b3f2cc8f6b2c2f" . + "87550f50bbda8e2d6315b3645427cb8de7847d8d809ef49cdfa0e26475974418" . + "e6dc508a22881fa1fa3a08c6d5195590c9ae81eb51c51bb088f586b3c85d71bc" . + "6926d5c67b71f639b54b490e79efe22e6a6c926bdf21e09e6c0f6d74803bb532" . + "dc04e9a4a52ae4413c957c344883a944ece1aa2bb9c74468dbf685f7f91b1f9b" . + "4453446e0e03e6b14cae8ce2fc4a9f1ce368a9d209635b2102e16aec6db18c5f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "12c2f022dc92fede0039a19b026184e71a8d3952b8c9d9b007946b27fdb08497" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "a556dc0132ba955c229e979fa5705e63adac7d04485b606c4446df263c84c152" . + "9769fc87e3217616585fff73417cc90180f1c2df6650e7465ab45ca249285e7f" . + . + "9d71f4702abdd87a7d30844f271dad655ec9311f918276ea99e508ba2b8d171a" . + "69a223f9beb0458ff10e84b5f155032c1314177e7f0177eabcebf4dc94e038c5" . + "eae41ab5587623fc82a3d3478d0df95c49140df2f29b5eee74673a31ed2aa8e3" . + "78fe9b33cafe58c172914578844edb2fd35543ea84f346b4fc6969012eb915e3" . + "5e365f7f80a9b7faa627cf9161eca01ca9d1232b1aa39e8da1bc41cbc35a2769" . + "c49d1aee1f64e4f443e9eac532213d222fe284a6bb6a486120162ad04bba9b4e" . + "8a1d64d29cd80985a38987eaff40c895c72fecbc41662f35973929d41f54c45c" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "238f137b3fd84fcbd4b19f03b272b46aa50693b203d452ac11d6b56c75034088" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "984708a57bcf8f1c3373e01de141899ddc0cde1bed0445479eb85c863cb680d3" . + "40697d04d8114a70cd957fb06220df1149be44ac65e3515362cc56ed5e9ffa74" . + . + "2c07ea9ae350ac7b4a1a882c5eebf011be7943bfd9c2dec6c696e3aa7e54b87b" . + "f9043150c13fc3e20a43c8cadb0a25c2b876060e670da3e865ad0c2477e3996b" . + "c12d8440402ecd931a45fff2bc83b0f11b351032a8efd1a577be67a8ca262faf" . + "bb68d79ea034bdec036640d49ba2ca938a808ad385cbcd1ffe58072ecaa66aa9" . + "47f29f64c2b9676a2a86181e15403f56aa1500be2183f1f15f6467216462140a" . + "933283b68499709d1fb34fd954f39720e0d72d57c59713cdeb4d8cf94ccb8cf9" . + "75ad31b0831e1ded16ac12fa061dc1c1b7682e598ab901ece4e6c16eaeeeed84" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7320d4108b6afd777ce4390026035dac1efe73f7a9539e0fb50ebde3e4bff0ab" . + "df93c3e88c686ca27cb687d509566b69f3975432df6aa4e90e64d506984f11fb" . + "02d24d188e522ded2f8433857d416ff0c3372c3e29a8ea289b497e802c95fca9" . + "1056085f4ebe353ffeb3500ccb3e46cf277d910a136ec29600eef2f836a4336b" . + . + "00f53334bf10c0769a70ea3cf31795c251ab5bf883453dc3313eb0cad795badb" . + "04ad7a7f354761c3c95f2d30efc5f5a528eaa584958b21a7b1c97865fcd28359" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + . + "984c55c8be91383707e9665cdb2c189ed53d7f6c94eb15441c98d2caf5678a47" . + "7b111b460bda3fed5848d133aa3fd1c021d2fe62589bc31efe21842985a58cd7" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "4a86a3eca47707ecbec7f6d2c910c8246361242f9db740ce8c21bb032781d1c0" . + "18788f6aa185b45efc46d8b8db2b8e66d7a97d2082f5c61e0aece0916e287872" . + "2567110cb06e83571f3462c7ca69b7df4ec5fa2671b8070754e237d3df13ca39" . + "89b79ffe652d74bd4ee7430619b0aca3fe5b61791af4d4ce95bbe0acd8a6a195" . + "1128c0dd9e39279d765cb76c7af0dd6dc7369a8c0a1e3c727acaa8aa77be297e" . + . + "3fcc27e4c7ca76457bb331fa899aa6c31fe1c23242db9312616a90bb80ae0401" . + "76b29af555456e24d5810d32b73a8a30262ee290b12081fe3f0d9929baaca904" . + "300e710438b7b1e25ba243d92a07f63a3e4f9ae8320868d9076271750e855f71" . + "153d9cbfda37228e79442b1b8a8799d562868ef6d58f93f6ce94514ede25fb14" . + "7abc933e5c88490b2ff15cc9d08889e4dc1f75b1297d83c69b881a90afcd7976" . + "8581ff1c92ca45135bd69f52481710cfb8ca35ac5bf21c912e64a4be6d26e861" . + "db50e0e67db02a239da86ce44c2cb540b499e916bc450d59bf6f99fecb0e2ec9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ce76109b89463f7b1f705be204b7af6677e02df3aa3cb701d5a4f6a85a6721eb" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "35c167302a2cf939985464c9abf41ff9d8fd45ae7c1992d4eb3778cbf8cdc51b" . + "a5928a5c486fe1779e2b46b4ea73973ab3cdbcab90d641c6d7b828a892fae327" . + . + "85de9beae963c1c242aa83305f4c6858c0cee0c9a74d05f1cf436defda869a8f" . + "1c95b350db1eeffdfc07028929dfee087112a2bed62cc3b72d5e090d7f8163ed" . + "79d88833058183da924c88a3ec614cf739d2caa08db09e6e482e62bdfd3efb26" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "cccc24b50c95033816bfec6ac600aa592219ceff6646156674ddf3f61915f148" . + "ab54ce1e6b824e036d1ebd32283da10a1fb26af8d7376e2f83a795f19eb69da8" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cf2d484b339f6a2559ab1e395d9dcae5c70ce5309420bb882e087fd12db65fb2" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "59c3b2c3f2e17c239cc54d8494ad9fc79fc4b2b02e408a960ddad75ac29076a2" . + "b16d4adde2d6ff2d14e62c0d2402e73b467a044b359fe4b00475a75679063116" . + . + "d2189e61745e78915fac2dbd86ee36522ad20c6d030302e6551c781a185f89a7" . + "d53aaa17722dfca1573313de7005db3d127b7c3cd28a6d7cfab036767d505cbb" . + "07b1dec88163c8c477ee87aedc3a19160271bc8c4d95afa823aee247f7071d7d" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "d2189e61745e78915fac2dbd86ee36522ad20c6d030302e6551c781a185f89a7" . + "688b4ef8cf134e761b1431f6c517d0bb34d2906ea319d7388eda02eaa17c9709" . + "18b998a3dabe12e8a63c7d09ffef11f2147f32b35d20302a3a19f2ca6851a8b7" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7afef080ce9849f2c8a089cfb3a043e6e15ad383f6ab0c0cd117d2a78458fe2" . + "8805c833570eb23337ac9c3c7536fd135bd4871c1eff2b9d29738bb1aa7da115" . + "d8c401712cead84e0cee5b9f82974530a7909902342e328181a4947e43269e7c" . + "e33a89d0bb8875d0b8db4f360cd68fc90d3c6afd55d510655a6c4d53eee7fc73" . + . + "4bf3791f98c4cfa0896abe37b2567242f308b5ca9660c65cb61f83b922e5fd71" . + "e72739a88db442f8667ab4f063dc032e3d1956fcae609472e27dc81c3f96a5ff" . + "6273850257cd414bc98064ee4e11ebdc49ec671b035a77103bb5e368b3d932ee" . + "99784d0d4bc911ca4487197bf17f02d792a342a1ca9f4443f8e8bf87369bc75b" . + "d7fbea1fab21e47bd15af7280cf2377dddd9f3b6bc01e412878dab7502622c32" . + "7421df1ea9dd5644fc305636d919376cdca1386a7b69fa889487dc6bde318396" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "1aa6252bae37926536ce56c83104358bc14caf33ff6b20c9bd7b97afefb62f25" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5ffecb8ba7d416915d2e9cd8df8667f45f8e8ec148a7f6afb6e280d4a5672d15" . + "e451955970295ed8798c17bed8642ae82766d3d28a01abdb4bf993ea82d6c444" . + "3ee9d49861f2811a11909ddac8c552aa4c4a2dea7535032e8f2d7ca6e7236ec4" . + "56556bfd016c3b0acbd32e146e292138fbfe46004ead3dc623079db978f6b052" . + . + "088f62e8361c8043ab6e591d6359cef1175907c19619b95a031fdd416ea1686e" . + "273195acedc1d1542a7332ce7ba59161c3618dfca3892c84956070b08990bfe4" . + "e3c43683d8ffb5e2817327ffae2549bea0aea0f2474f2c2865d35f50a2e2504c" . + "b0e9caefe2d7d085b80d9bec3a79d0c0594cc25b5b3a3cdf36ea13afad34bcaf" . + "6d3a42856a6ef51e020420702984ad6669c31db677fcfa35b50ae442deab9eca" . + "68d7865e7a923f462ae047ceec33027fdae20f35aa53bae7c72b285173d8dc5e" . + "60f69e480d6ff7fbe0822ba484c66ab9a7ff1dabaaa46635c2c28601c92b46c3" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c28d9cc87cf272f550cbdccbde834753b726d1cf82b44343a1b313f5c950d6ee" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + "404f0414978115da01986441164798ca4066e0d3f5ce51becba5253c20545585" . + "6349e11718d5a9ad8ed18c4c4c00dd642a082f712be1956faa918ae6a9dc0cb3" . + . + "14daac14a022bc8e0d821c89be4b34f625e5ea5bd611de31494aa7c059bb5e70" . + "b2e3ea3740fb31bb1dd21eb0b2edfe18b4907129d660e6569cc24d8b3c15a567" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "f15291dbd3d134f63d1a33d03d663e6edb1cf2efc83da07bdb057a98af3d22aa" . + "a19134b16bf572118b6734b41495b262f353717f9d65c9cafcc23393a7a6e236" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "e210fc4674f8c9029c37d40ae9f67cc18760edc54f37edb52a68f96388348157" . + "f6f550c1f196ed8ebf8ad744365bfa245179e65a3cac7aaa3d014e176f3edb57" . + "a0929529a755e6bd48c16795bcf6d768a6a6081819362694f905583d8dc4899e" . + "3e4eaef603c1872b431724363824456b28171a517d39b063a6f379c7f5f5e149" . + . + "38ab84a889ca617dc8242f4bde11990fa1bd7acda3cca522bb9a7b1eaf8c20f5" . + "751ac926038d72d62471343a530ae9ee73335f5c0db4402c3a5bfdfb2329d43e" . + "8209821a29fa9927bdd806a6de64df78d4b9594ba5e1e481e7a552939ae6fd67" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + "1dcac61e1b04ed00da6857f49a7c4940549620f3a3264e3d9b9a4c37c6325d97" . + "64f921a0b7111e004a7892333234fe8fd7e4c7d1859a1272e5ef31ef89be3628" . + "e9966114794205e773f444235fedcf3cd3ee986cd627e493ae90722fd497a1ab" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "7cf10ea134da60dcf7a6a4ec7ed172e5570096ecd2add40998a2e0a6953816b5" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "bf56c50fe30ce21d8670965a1bba9409373a4ac9966de4ba5880b4960abc0188" . + "f561cc128c693538d085f160f09e849177bc53a5417dc2bd0adc90d5651da077" . + . + "13f6c3e10eecbac3ae43762f5c45a0e346563be85999bc45abfc450806a11e44" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "824250c30719223fc696fb4ccaa54f7a621e8d15d0b37d32b57cc0718b8118c4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5c1e8dee5f4e7f9248a71fad558bc8e06d8b3141e91b023cbd27484e616429be" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + "bab385376be62688faefee23d63d631c45d9e49123c3d3a4f8399153f0064708" . + "f572cc1b500c8d83854cabc09abec7c0a10b149b2062b844df53ee84c56c1ca2" . + . + "05dd911f1ea7b7af4b0eca6c7f4b6f230044708c20f537569bd2f2b99f4dbd23" . + "c4138e597efbc40a1e12658d04d0d936481abbcf58880c8641ad72b97c451944" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "05dd911f1ea7b7af4b0eca6c7f4b6f230044708c20f537569bd2f2b99f4dbd23" . + "11eb1fa88663fffd62682797563c9278ae263e723bbab3bee082f0c6f864a353" . + "240ad372367fb1fd9d5606068c5a5e5fd0cf0d1345a9bbc0687be03758b14391" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "ca182ffad5bc5ae6653dcdd0cef98bb2d4deb9d4602ec87518eaf0d5cab3215a" . + "99108d1898a19b3dbd0c97fbc79a7ae95c1c71f1c916313ebd86b735c411e021" . + "187ec437183a7c01325b4a0b4c64893334dc5f808fdcfbe47e8a6684f934330d" . + "5da5d189a75e2c157bd83975ce8f1f3818dbdae1155811aeeb786684d916ba21" . + . + "69d66822f4535a2f1994795eda343d2e64542455320bf5ebd9d16bb612caf39b" . + "0e27940e117251f4b5a0fa9f187cf0ad17b69b9b294847c94d28686e235551fa" . + "840680d6a49263690ebe09642372c48a10b046a99856b1253ccb3d5f7e145dc8" . + "9a3457fa81a5fd35da7d6feeef8270392c0a60b929f8b5e4566a444c5732404a" . + "772453072d612cfc4638f0f17e621666b7d34313e5d9e0d4779e1c3a1a69ed90" . + "f78d2161a383582ff9fa2360a6f2fa55498c6f387a5c3c3a1f3293dfa707c6d2" . + "5ee2389f2705ef4ac9fc783133958992521337894dd9c45edbb8bff470d5b527" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "f64945f20dea14d95e74460e1b15783f26a9ebd3647931c8c6f5bb50bfccfbc2" . + "ffd399054320219f2d4e1a21c5ac0e2a48ebede67aad97737563dbd54fabcac6" . + "173e35c11f28cba32ea6597170b7429b5dc09211ab41bf5fa16a326a4244d62d" . + "e1df607f016de6256f4fc0c301f3f52f18832fd5237c668a9d6c42825d977fea" . + . + "8fc874f3e87f8a3b62ecebce50ce116900ea939ec144ad7c6d4bdb9e8d0f38e8" . + "dcdc9d3317ae3bc3d2d5f748f1e29951a7d83fc4869557d1539bdb79c1ba93d3" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "df1f51c7ffe041d194d85152312de16c18f547a813001cbbf9c73a111be3ab3d" . + "4151630261f8d183f69d7c7667e13985530d9c289f1d1941c02c60d0226850b9" . + "7bf959b4699fecd513d4164068934b0c58b177a6e46462fa16dfb5e11f673d51" . + "194450add26c4fa6cf5b1125943daa2baca4f749cac26666b6f2366c781cd384" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "6f0b6daf3bcdf1219fd7d41de33a5b4f9e2bb01934e63786443c204c28d42181" . + "45cef59118fee56650673fc8e57dd2b2fae79ab69a008e811028fc0fcc0320b5" . + "f5ef932b783e5fdca56ccc2e8f42c1bb77f5667a18ed65e1d9362ce7ac18c999" . + "4c58450e285835d34a4528aaec11c0265f0df92630384262a80a6e0b45ddebda" . + . + "3bf5c2faf0b6c997097bc9824f072bf4de8a615dfe080402bce960bf61aba628" . + "25b43b85763831cf8a1b6be3ef7399e176331a63a13280037b1906569f1d0246" . + "a42344c7437c8bf3db3918d67e77163f11a1f2e0570faa26cd52031a2733c70e" . + "051a7a6db85621a1d5011d536595c39b8c9d54ba249b8423fe846020326db11e" . + "8989131475550eb3b51c1f6bc7b1b019688736a6c8d923b477fac535d0552f57" . + "ecbf4eaa2db5cd2cb5c69b93c9af4964fbae816693214520ed890c7940dbcd60" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "40787622b29afbfd3b0b5e12c3c56a0e90696bce104dddf9eaf7a0c48ce379b1" . + "514781c41ce4773e376065a7085b8b60c6c83ed0ccd72063cdfd2793a909ffb9" . + . + "f8414e8e6a66d93efcd91ff8e605f4f399cff866813b79b4b25d188f07f3e35b" . + "99ba47d8d204cc14eff92fffbcaacdc60a5c4ccc3e2ed2b0e878f7c23bb26f1e" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + "ef08bd72a8547f4263fa102027bd048ccb853714b9ee31eba2d126a46b905a53" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d08bebc89c659b64578ddf42f2eeb833d178cd3e6cb14be0733da71107070d4f" . + "77804e2ee9fe1ee7597e3bb78a7a0284d24a7837d0ac7f7d9a2c56abb57258d6" . + . + "efd356b6bf885dc53e9d03219b25329b42c52fffd197f3c8acc9c84b1c0f044f" . + "27c4c14612d9f15b351dd918a53f3d0e1869b769a2baabbeddfdd6c1bf27c0ec" . + "0b215f33a4782e72455c0400543392ebf159a708532ccdd5ee1861a481534eb8" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + "9662ed7dafb1d2805e1f4a774ec33c9f5a880bbef6ae70d538201f9e004c962b" . + "154961f80f905050c8355bb9ce75fd58a836c95d842f6a4b2e7c53183ab4f119" . + "ef10768af965d1ec41bdae4d5eb116511a43272806f5e44561e580dc1217e4b8" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "717b508b6fef54b46e28a098f6f6e45a3503f4a417f4768557cd33b9e21674a6" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "ffff6926a4d3c72f3f2b0b26a228699f8fe7e65b4a8c6beeb057b1ddf6679f4f" . + "875ff86bf06963f951addce85b96d65be514b2f6d098234c2784bd84dce63a03" . + . + "30b4d63f2ecca7c3280a36f576a3ef9e8ed486c1a0f8e2aeae5fa8eee18a0c95" . + "8de39554d0b2bb160b6c00ff93b5c535a768659dc32f611d3df9e71013116a68" . + "f6eac97c000903b0b70b0891eb514bcd0880bb24f138d1a26d5a53b8001ee1c7" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "95c394271baa5ea4dc3db3879830594673c8de838dc37d9dac241c94193ba188" . + "7e9ad576af1f49ef05bfb170c70be31ea0617881b78fb2927dba36daa38af83c" . + "79357df99c07dbd894ee2a3b3fa11f8b2b94ec37e9b6a29e3cb27422d3ff1b85" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "5df375d8971a4740bb22ffaaf88dbad70093ceb839f8145f81fa59cba1f4adb8" . + "e770bafee42d9e5755c230aa0200867672ecc2e1ce5a243344582646c2de5a7f" . + "dc813ace9bda8cbe8731a0d87e0726d8ca2feb2017a13afb4a0f621ac518fc7c" . + "ae056d745129b75ee270e7f64735bc765e6ba3385984efcf65bb5d24766abfa6" . + . + "78dbe598636c4bb05729fa057c1f51f35e525cb13a34849e8d9a607caf9a7447" . + "b6a6a0b768ba3d4671625ed5ae6f4e73e1f64350f841b70fb5dd118f5b4b9abe" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "3352521819b266ea3f9698e56f6e328cbd528eb8c865cdc2ca95fdf97785b622" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3769f29f5679f006f4acdbc6bb5a7e2b4a37a6dcef54863a1a118acc83fa60b3" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "62b4c7ad1892e50dd8fdde325fc304d467652c57d730b6656d6cea196507f56e" . + "babee97e60fd19c0bdbfcbf07a6e04b76828769f72dd3116724be2472c8abead" . + . + "c3da9a7341034481de62c99d118fee095bca918a398479698aabf7e362fadece" . + "88a86738e05a4e85e99d063d76934226b86abc2b72b95682de12d5ed654edd0a" . + "c14261f606fc688af7d7eaa3a5839115d4a98487b82f2667bb685e7a5fd62cb4" . + "0f94ce473060e7c5503d6bc14495551118663605be875c111b20ae9f9a3080b9" . + "4813175056c7c9e0528a0318c279e6d9e40bc7d322dfe0f87df53229f7d6956b" . + "55cfaa98a6b0e5e63dbe5973cd7847c7782acb08f8ec3d9178f2c0b7ba20b98e" . + "168a0a0d4515e231fb8220a4c9d25876d1c56045572f7a444db736c49338f1dc" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "6ef242b661348fd6401510127c13b6c7c77470b0a7ec853b20c08585985dbd9e" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + "28b816f36f3268a39b05c5cbd3a0dbc08aae7377f70cdcfbbc6efef405535b80" . + "3533c03ec1ed4c15841e647a9a3ab9be5f3f2cfc28e51e8b0a95ac22ca52e9f1" . + . + "e5d395f8f6850dd239617d73207d1f82e03f6fb69dca81fec6e1804d7a08477c" . + "2585c3207cbb7c22571442ccdcada0e907fbe0a01142e3c60c2e0b433656be94" . + "4070eb6e877128c341ae4290e9e1de89912bdec3059b7b36118f1a6dd01d8003" . + "bfdbf47a991998dd646608a14c4c12c7c078fdd8d2bed8cf227ea453ce4317ed" . + "963bce7d97fe9bed3e3f4bb9575af12344ae1a5a9eb2e9e9623b5eef6a90cbde" . + "dd63d37a4e32948c9879949dc9dd52b821cbb30329fe49e6ed795d2182e406d2" . + "ae28889a685d2b4768b6dbcc3d20954beb19b1484fa508c34e72a4e1d023f97a" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7716e8ddbb5ca58de1b96ea180830f8da1ef1bd20e9fc5ad063ecfd62786e744" . + "9429a124933dd7b20fd9f88474afda11067c580ddfbb38b286573859a3e17a52" . + "00672b764728a55247d9a668ea569cb21d8d9fff0f4e271315c349e384648dc1" . + "bde58df08070ed6fcd32f24ad9f0bc062939bed3d0df70c6a4e4d936cc1b42df" . + . + "0f3caad44cd7c09520f1e093f6a56009827aac1275f2bc1157140186478e8f7e" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "ac8b6e7f28c6f7d16cce71924ae1233933907381bf3ab40bfacf3a17a61b7945" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "f700d0313525c0887cfc2823c75f0fd87ae26bf52383de3b80ffa33bd1f0e8fe" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c4eb62705b98684da465d1328e2f90c77c51b9f384c68fa699aac3b1793c6616" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "73dfa4fe16facef48d8f2ff21055719a15164bb6e316cea80d2e93f5985c6cf1" . + "5b791b086fb19e900ed17ad7ac38fade164f53329c76acaa8c868bd50c3bd7c8" . + . + "59ccb48fbd13eb0713a32bb4447d7af7a9d72f8185df862d5b1b33cde5547b3e" . + "658d52b186006443df2651393c7266016307377eb7f1619100ba2f978c41f275" . + "bbd951163f93af9ac80177215337b6be57642e1ca28e4d78b73f1ed088bbd287" . + "60d0a414731c0ea7be495cc1ce8ce0a23975cfdda37a8ddac0a89f3c7e8fcc8a" . + "5ef216a5cf9ea6b93b94d5edf3399a1fce334b4cf4f75daf0f94b21d93d40424" . + "4ba1e7a32cc5358c8087913a1cc17a13b081b124630cd503644e57d29304e479" . + "66348930532252e3080e40b70b9d88ae345754d7c686502740a8d04e5beff41c" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "41eae7c0b666b2afcda96305804e3a0385c15bf1f2ca758d67cf815b3aa919b1" . + "b6e348cbd841405d67f9dcee938d5d5b143675a4d5b8f39c634c103a775d6785" . + "fdb909fd438277fd4b497991b437f465185d0027fb3d350e9cba7a37301511ad" . + "a328f80ba8f9df6b00e19500c97cb98f1b6d2dd3fd075c9fc32279e48b689a53" . + . + "96d75feadf03b8027b3ff9b3d745bb5851ee3c46f24d735e49d7d1083ade7f26" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "30da0c04123ce59219af6c9bf44e41d7a078e7c6eb0fad6415952ad38b83a8e5" . + "a42344c7437c8bf3db3918d67e77163f11a1f2e0570faa26cd52031a2733c70e" . + "289046db9bea1f88fddd0e7487e45323e76ae875c1fe05046dc2974a8f0425d2" . + "d4a2656f81b3ba39e97a43e03a23fd880a328b11ef12cec0fd56d5a6a11103d9" . + "d65c415a257447f4948b3c31cc3c26ea883f1ceb61b115b2981ca8dc15a59c0b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c3135cd87e4f46e6bc49521157fe1aa5c52f99664c768b94b2523ac8084d4538" . + "2d6ba55314375d0a6cd5c62953f16d704baf3d58d6f17da2172d0a7b7b9eca49" . + "f915d21f726b738a7becca81a59e57ff04f80db911512164e5a6778b4467019c" . + "ae9696f63ceb1672921f8e47e2bb32c0663847b773d8cfc3e06320f500c3b704" . + . + "3acbd2f371de320a9e1ab4e4d4624e46cafbcbc1f0abcdffa9fd52f2171bd6c0" . + "b7e18268b5bdeb37eb9ab257d64f1bd8fcfd010a8b451dab5e285fee669543e8" . + "045daa014617aab6d64110a83080c52c62f2c8b025e7a6607942253819a8eae4" . + "f96b3b016a6e7cfad0d262dde34131b9948ede708e7028a4332054f2ad9c623a" . + "ac00c67b9bb521364c1fafd303b5577b91c8db486ea3c1fab550ed17e3a18a82" . + "1612f1a47f0ffca1bdab765b50ee25979ebe8a0bf5cf081bdc67aedd797412e2" . + "52cc91afd91b06d3058da1419ccd12ad354772c89d0cdac8200b190b7b6053df" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cf4f48e62430bdc499614e7167de5d8743238910387879a24bfc98e0c27b5578" . + "09de13f4701d85d74298e4b230e017fb4c4446ad1a89d26b8cafd7f71366b3bc" . + "73e9ac1fa2c6c2894950183a196a82736187c5fcc93856d41dc75b75be72d437" . + "1bc6f82d61c66404918d687750d944ddbceeb0c43c4ec32cb0374ba15d6fa1b0" . + . + "5df41312cd3967db941bc9f1f5dac223fcd4cfa3ee62a3ef8f1aa4c0ff480ceb" . + "8349b18f5e26b270894ac4559a8baf3164a32d23edbe771e07d5bf7a724b7d95" . + "a60480d05a514fa03ef9ecbcf01236e814d3c25a51c3ec7fc6150c6f8883df21" . + "0d7f4f862c9c1a1f8cd19f20ca2f48b01300fb1b7849702f00f34115058ec0d2" . + "5df41312cd3967db941bc9f1f5dac223fcd4cfa3ee62a3ef8f1aa4c0ff480ceb" . + "009352773b301833007c46b216a4b7eace6cdee5b9bf014ccd1fb4ee01ab7d1e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4ea9bb51623460af6b0f4fd352fbcd07d7f2d56a0d8c3ed3a315d2e240565ff6" . + "8734901f969c02c0b8eca2cc6207125322ada644a09175567d0a19e3ba4e09b9" . + "68afd8ad08fc87113613989a3f01745e8a5360c7109064b7d9dca9c07cab5521" . + "da7cebde1ccf204fd467ecc59e69e774ce8bbbeb0b25a31712fd72765b42579b" . + . + "9c0df64cc0c5ad11c0015b5efb3a30a98e0519674230c1bfc07117ba20f44b66" . + "cc60694e97e598ef9b10b1bcc39fbe92f55bc7e770132779ad50a302f748df13" . + "6ccaae62864bf2a9fc767953cd1f1501eeb59aba5458ce771cf15ac8534325f1" . + "1aa60c3507d6f591856c12131f5eb3b28eed039d94b5e7d20160e06a5d355ca0" . + "4cd145ecd28574ac94967d927dd3040f5a4e51d763a0be00176e56406757a972" . + "dafbfcb6b3c201fd0b08bf5deacbff00084f1989101065d8756cfcbda10eb701" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d04b365a269696aa7b7b7a6974f789f2803533503acb18ad5ef6f632c42afdab" . + "555a1cc0498dedfb008a6134c026feabd7408ec196dc7503068004446b7e6527" . + "e5fc9dc5f80412e5d6971ebda38f979b0e9bd40642c06b71eed512b555d55849" . + "b4981f342c443b3311e611f4d235e5c105eb4990737efdb284744232fbddd992" . + . + "f9d105f35774d9e840b8437e4fe748cd6cd088b4136c8d9a75534adefe7beb72" . + "8eaa204d03aa7dae6c94ef0b74f9d9b8dc02068d8a25e2d3f72bd85625894f8b" . + "e44ae713f3b34e612ef31438a077455f5c8ec5dfdc9f1d236e96731a02fbd24a" . + "efe73101a5eed5278706676ce8725e6e6fe83132cb95b51e72c5a9308e4be6cf" . + "26bde4939a03dffa2afa82c7cc46a9c8da065b4a7fe10bfc10259a377771175f" . + "c1ec4294d07c821ddcaa83daecf0f91feeb644d671cfa11c8c9342e33fd7121a" . + "5cf1d78a3ca4f9f4f5bde60556503ad5158370821e20196bc104c822aeb71478" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "2db87899202a4df5fadb5ec62821e5a57284068804fced3d0c20297b3857ab86" . + "4fb92a5c9e2c5d8f01e0332e048493e69c21ab2d46627d38b746ec24d34815ed" . + "8a93eb9da04c93b599ec0c428ce33d8ba3253fbe3c44a61b62af9a7848f5a441" . + "eb1422cad1d746b21a19cb13f230a4294e59365d45a0af4722ed02ca237da56c" . + . + "c7a377924ee9f3fe54da548694f3b76fb1159e1755f58937b13325ec1640cd98" . + "0b0bdca51606c5ef8d1f6b07be8132764863dd55f1d0bc8c0b4b67678ce39f4f" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + "0c1f6ca47a82db370556558869e43a26befef4132b92052a6e7c86d1ebc14b69" . + "3e7d8090dea3e3407502e2294246089a81767ed3530851378e02f3fa1c60af74" . + "f516f085466bfbffffd4bd5cf593bd20c34db2667b0bc8d57bc1c0e9cb347b7e" . + "56d3c7c585bb41a33878682beafbed0bfc42c892012d1dfab08d255616fc3f77" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "558a1c8f7d2cb164effe944df80694b5b1a5561e4f418c16008eb9b41f7f55b3" . + "1d6fd46ac5903df6c13f49d442048ff07d67c92e90f5b9be5ab3dc3b1b8a52da" . + "5dbb7eb06aa0f91be426f14dbaa48ffc747b1c7330a33456801a81919bfc3f06" . + "b657e8d5e020d53462d4b24524a33051c7c30d4a4163497a1318d89c61053e84" . + . + "be6ce9c0cee961b669cdece986011f07d0cf8fe6f6183da682d5f11072f7dd22" . + "73208edb895c892265bdc650b90eeb2369f75f921c5032985961ae06b0c9fdd6" . + "26b96ce8020f6460db2f8bae3a82045c39f913efb946e8ce4c70f4d46da4a798" . + "c91bee449065238860869ec12aa5358298caab010385253c97d285468a892db6" . + "737ac90cae8adf43cc4d0a9eb20107b403f1f1d02018ce307ee88460af4b233d" . + "7f18b47db12447bb8daf53d47270824ce55f19024d30ebf223ca76b645774d23" . + "4e6873a065b51a56958c19ce3975ac1e13f0aed5bb3a43aab51dc7c8d53d4345" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3adc2f996344622b0eab71ef664a00034e33ad1f58c5debcf86f6f4707363aff" . + "0b2d104f967258a041bb02ea358b79d8165856219cab2dca9827f6221278f558" . + "ff6386e205151f32a76b0a8b6e7a7aba22bfa61aeb18f4b147579936028ec152" . + "99ccf46f13823ffe9512097182e6077a02d81c57e36b91fa479881ddd9d389ad" . + . + "3993272ce793b5b46986de11800cb4da9496e5d03264b1c57335761e070ec2b8" . + "7096a83319ca15e40bd5662e01b0f04965aab7bfb685a37f88790af6fbe05ed6" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "9710576545339be8b6322da4fc7abead6f5b022989b17b6b1be222a0d5a297d3" . + "697379ad024de815d525df94faf170c95cba7880d9cd8ea0e7014406f1f0730b" . + "147db201c7d0133e99f9c6ef6ff7b581271920261d6f84324fbc4798bbba1f3e" . + "4e6873a065b51a56958c19ce3975ac1e13f0aed5bb3a43aab51dc7c8d53d4345" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "44b43fd4f2a3ecd73366d7435dedeae8c6c6550df7d9afb46d30709eb9b02f25" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "985474a89b7ad31f021ca2674bbf2dfaf76c0d5818c77653e16b457e37c66460" . + "295f0f410d7cf3966612c331ca7265b68e615160c92e2bb1e90f4bbd7bbaad11" . + . + "c15f7c505c2916f2557556a5cd0c44f1a7d0517b179baffce7b024a0100a3ca5" . + "0a20e3e2f81b9fe3c40326a0cc85299af157ea5dd453692d0d13d50fc0d52ce0" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "29de6d3b75eb95842a693e8b7decc817d52e93553fb24dda2273458ff023aa57" . + "fc11bc6740ac59e1832be30360d046bb81a169d5fb6ef675123e7f4f26a5e1aa" . + "8744e88f331dd7c4306ff78435f0bb36de8407a074e205bfcab809393d8619af" . + "2d4c13016f0fb15df81ca1ab4d4a2923bbf73452bc8962a9bf935bf043ad5351" . + "5fe2548ee2826e1a3bb8f479b9e4d31b8f83d39706dd011482347fd648b9a00c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "187fa47db0a6d380025a6d9b41bfb5b23a45f76c49a074f54059bfd152bc8e4a" . + "1ea798f1763f240a01f8ca255f9e8f23ea91d73d15b938bbd91c1764234653fa" . + "b5b3fa89cbbbb8ffc9ff891f12f3951e270ab39331d52bc2fd069d6c67dae052" . + "351e01f096ae179122f142baebf1c6f65b95bc2c88b89ce17bcc612d523c726a" . + . + "47bbb6ac442326d1c005707f26cd71309fb4e9307f2bd74e091fbe9e2c710e35" . + "8e6cf80a8f9e7d4e57be3d0d1c84c2c58613a78902c74225b29600942e1a550c" . + "14916798d02e6c5a1baff9e4f36762cf3763fa88fd470b93c7fed5dc41f1fafe" . + "87c455b1d755f3509b166110579fe10ecc0ae872546d557bd6573615578b8ff6" . + "3d7cd1c07e887dd09edff60cf24f92b31e6b904caebcc93df1417ed43a58ba8e" . + "3b142fefb07a8b3ebbb2f96dde1f77f4d182f3e9d4a65d1f376d7967bf528d80" . + "8314ea9bb390587b9692fc0469b6db33cb04a7a0a0de0940e6b8b9a0335df305" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f77db2512df3f0445f8a293aeb9a98b61c020404269e24d7908ca2c597e39012" . + "5f83076e9d31f533afcf4adfba014c3dbba0679bb0bf3168eae5d407a138cb0b" . + "f52ec1859c9e8f5660ff6fc1e7aeb441f414255f49107201f4e42f28d8316844" . + "1015ace5282d474e9089b895a52acaf1085e0fa69e5022b6b0bcf3fe758648e0" . + . + "606b30346cf66fb8e47071dc83ee1d6f8d6b645b11c346770132f2bce6dba5a6" . + "e6518c676b7ff9aa8eaeb6dde836f18fd8565f8812a25dc2b0d5dd7cf3e535f8" . + "59dccc3f2101260f313e59b9e096f2d479da00442b8f70f7dc84a312f5729fae" . + "a96f5137bbbba1e2be2ec94af691f2aa313ce8a24bae734d77d8fdfb1dc3fc0b" . + "e00e386feb56245ea358b58d35c580b165d683708e3f3d456b7126dc8513f354" . + "8728c6de34b356d16b61266ef9cc368ce108dc1179603d329c541e5c10770c40" . + "ad041ca802d884897e53c69e5816cb64b69d7e1266b3810424390f0249bb6693" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "47772df5acc978df398ed3fe5475046a544b6860a2f64cade25e78890b9086ad" . + "a44f3d41823b1e9ea5cf26b98e9bde24b46b545fe5f67c94033f190460b8280c" . + "4a27dd1aa9f9bc34b0376538960d7969f88d11a2143141f63a7cf5ce6b8e4cee" . + "3b1e7eee2a2923cf2280e40f52cb76d8a71822a34bcc64131a01db1ee1437080" . + . + "91dc062ff3ece8b65657eb1c49c667a5c0826d612ebcfa185c51933bb7b1391c" . + "0bdc14929b297a3d3c61c9aae4e157fd478be3fdb20813e05872886b1250625d" . + "9b199b0090cd718f5fd5cf48aaaf9e4a008f28cb24de52c22e644abc7cde631b" . + "b6a3de01d8bc5c5c5add041156a25e0af051fa46bdf65e060e74dff6e7aa0296" . + "7d20cc0aaabd51555ac08ba988b311c9c855235f0bd4b9c454d9bf63ffceb526" . + "6cc6c2d5ee810ef53e56d765b0ac3ee0d72dd4fdab0cba25c8b39b50f2ec0af5" . + "2ec68c498a975bd0e86e00bf72fa9cd79b9685a5dfc6d75eba9ee0b29b523f0a" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "324b698ceb4fc12bfc28ec5b7240f9fac53564333dfce9d09bbd9b4af3f820ef" . + "695d91c44aa499c4e2226a16a860a773c5531cac34613124f5cfabea25345cf4" . + "ba757a5a28a85061e222c9db0cdf2dc93194a40c0cba846f3877bc03fbb9b3c0" . + "417e730af76422822623ba492e3b9f21efdbb0106091cbfe151b685636fbfe6a" . + . + "612e9b1143db8e7a511dfaebdd127e9bbedd6535807b0dc2fa5964282708ca68" . + "da45d1f7930270ccd6218bf53eb282bb16e598fc6dc584e55ca97000fcd20343" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "ac68efe404bc63b19093e3da9c0d53c9bcb7a101ae13cd13a5d7114d17674296" . + "aac324c9f8690a67f4f81d8ba1d8dabe213990cd5ee1aaf90c2e0cd3f105b850" . + "0a431914debaed58197bf76997192acb971d25e0ec6ee2a6247881ba40e64aad" . + "463fa4ea12629c1d92b7336c60d7bdaca4f5430fb4c327f3e8d107b681ed76e3" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b02c597453e4d76026c4bb980cf559a8d74e8c587213a02bd839842ec1f72db" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "cecd4c5b8df15fb76a4b3bb5a70c35b05abf901b1ff119f28908c265749dbf43" . + "3e99b013d224a7c146a33af6c280b2b577bd318d1dfd29ff318ddf7bd8efb15e" . + . + "2f65c0dceb7e1bc8e10009ebb6032257282247cf9ac1473bfe8465b8403c0957" . + "da2d1bf8a1faba3f9487f74c49e0a5f83f01fcd603c8be48ea5b9344df69bcd4" . + "0bdcbc705e945c5bd5de78bede1e23411360741f1a26a4d4b3dbb2aa2e1c9fa0" . + "0f46a36afa76862d22b6ba61740056b9832ba4616b0fc4043b22bc4dbf213510" . + "ad0810549705542bb20b274668b3b706e56b98fdc2bd91d531dc3518e8e83425" . + "bbf671ce4cabba15b94fc578355adb9e6f52442d7c438b16bfc2a5c7069c7243" . + "e7a1a2c3c8febb764db43a9932df8ecf5a0d9b560387d9b1503e64d032909989" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9024eb5af6c2b6278839c6133b3075778945cc546c0c0e6a6a55860bd076be03" . + "067228384bbe28af84f3ca5b8e8bd8241af5d4178ea00f46f5d06a9f0682af5d" . + "c49e604699688551c0443f58d69194f605309d5e7e12c5f9e498d6384740c38c" . + "18f626c0d2e27664f107514e350a7a1059b53ed9ff6aa6bad152f882c3f8fdbd" . + . + "46ca3b0a4953d95221662e9dc8e7d2fa36fe57a330d6561440085ebc5001fe0a" . + "5359621d81969a0a1a15da10371b8ed33a5b98759fb746700032db55f30d7484" . + "0dc473525fbdd0a235dfd632847a343ddd3b7a91d442d373fd582b4408359609" . + "1512b655c585bf9e844ffbe620da30e4189e9db710a745030c1daf7007c12bfa" . + "0f3288f8b86cc9d935a6b1221efaf5ff879c07596d7b6cf08e5410c146ec5b1d" . + "d0a53779541897568c2a28743b0e71719538052f75d3fc7a51f419333b060fb9" . + "9ac951e71e052ff9f32f02501168c05231bffe5db02efc30350b65d4d207ec1e" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "b13bebfd81ad415a0a0a53a5c4394b3538ff858d9bd81a8c58172bda73831b55" . + "fafe3b4e55598f719e8465f54c170e1c8e9c6985a696531a779606567290adab" . + "95f4a669cc1eb03dbeac5093d156a677c9c761016c70546673fec77806eef8ad" . + "4e1baf388b1ac0b4faf3b5c0123b7939bafa14588116e99108a38ae64cc9e777" . + . + "08f688128920385c3dd66457fde6e6450d6a8f8668390c0f4d98f2a40afa5e5f" . + "1e22feac0ca043394e8adf76dbd8037c5ee97792d78e3dd823168a336b1b6432" . + "25fc343f937336cd0c969b8ad94e7a18bb29f12640895bc37b01f81ef9ac0636" . + "e75a859e75110e175055a9cacf94c55f993a437a5121518a200721c450abc6e2" . + "0ad4adc17177d73f24aa81428fd8bb754a5c9f826e8a79f9867e5870c5f268d8" . + "36b7ae114ccc52ab008d7a9e6a08817355f63f49f67483aa35cbe455880c33c1" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "33d2a0d5fec08ebcd149f8a6dfd40e4cd3369744b351315ed3948dd806f08aa8" . + "5e61af98f8f14a58c5827f6b411e1718b1381fc3f482eb6ab5d4b7eabebee58c" . + "32ac6ddfe8791e48d7a97dd2d67b391f536ebb55123639d50fb2cbbf4a1b77ba" . + "f6e1a8a1870d29e34cf8450fdd258881eda97b0affab862d13b7327e5c2cc76e" . + . + "c255595ef617f9822e71f565eeef0fcfc87b59527318375a7a1b1d7bb459156e" . + "eb790bbc1ed0dcd59e6f10ef4d9ed5293b827c4a51d407aee588f863c248ae32" . + "edb3660f41cf9e2272e8d653df5a49fe88fa0b43fd187b3b68fb549616c4754c" . + "79efe3a38427e6917ff95b8b978a8794338591989bbc1957095bab6e4eebec5d" . + "98bd8cc7278726e350bae21491896a89e6f3beef7f58d3f678ed9759382e4d04" . + "829ba4337342c32adc99810c33a9be572943e0d2a9e3be324a05f6459cabaa1e" . + "15fcb9478369b4887f7ebc0906f0fd15a4e9283b8b7a82bc7629847ce906f004" . + "0b73ee46e72a92f897c3332b793c53adf3eada126fca4f32b787f63889050caf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "27fa64617cb426631bb4bd55d7b9aae0a62d539d5b91ff3b30a34e279d303922" . + "628bc2ce7663cb04d4b194e2f51192b18702dfc7c50139d30095bdc42aada5f1" . + "3f75a19ca539f64fc27637720d6ffbcf709312b451266aa267c23fc9ddd1892f" . + "577688e752a478d47f778da52870bfc92b5dd3c8653b78657cc0f5f5d1697833" . + . + "e0ee4626274373ffebdb65c69f21e27c60cc89cb367a32821459584a54d17583" . + "04df103a01b5c60072bb53cdeed8200b484c9266d0e6b5ff633496736b718066" . + "1e644f511cae1c98062c1b8528454ff1c73da61d263636e622361a8f69717a3b" . + "b239e2c90bc6fafb3f4aecb9342335f0b97286a789a645c193b9d0f9838b5c77" . + "f46d40fbc91f5a3c025648dde91c1b8413e2b20cb97dfefbfeb79a96d4db293c" . + "a88f54156d333ed731067c1d1a30c2c3b1499cd7cc9bdafa4fe5f82e7e19eecd" . + "b03303b3cbeb695b3a175ae043b8e6e3bb4686cf2883a9b0ce2767de1d6ab9c4" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "56abb01de67303eda40ca13863e81c56f5c21b19094506377e92bf183426dfca" . + "b0d918923b2d7239ab57630e5025d9343db3d05de1f69d8282ab88502f2ab24a" . + "7487ebbd6e3b5b6808bd6ccf3b2c07591366c0ae39714f1139e0a22481558d38" . + "b965d7819241e53646441d7de5df6293be85a8a02cf599d72b4cc6f3b519d0a1" . + . + "3b199406b1fd75e4729078b7fcb2ba41074a14707d5474afe15dd1d2ad34b2b7" . + "d49c9c86ccf1eaf4715f01faccecffb92caf9d2125f3a024b9ae8d7fb98e50ee" . + "efa6988b498aaabcb1a4fda6431a15f5c4dc2de10925ec8c89fcaafd2f78b57e" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "61e97c8d9d4b67f10d91f28c8d074dd32a28d2c1fdcd6d7efcc2eff740ea5d22" . + "6534906cbe70ba08fb43ef313931de5a4ba42310ef5672729a34f4968dea1690" . + "df2c9453612eb27a4bf60e136f3edd0e4c9b42bef2ebdbed6b3acf65201934da" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "fa20977256dfdd5a59989d6975c14a6909be1e3c9cd8bcb45ce4ffc0775c52fb" . + "4e729f98faa7506879a65c70b9df03467f8ff03d4b1d277ac0682b8c2710d1b0" . + "eff07c86080598ba632c632af4c9d538c69fa2a789c2115c4904beccb7827b6b" . + . + "203efb382bb575d652f41660affb6e05c3cba2ccbf499be7a8a8c3f770a47c0f" . + "ddd0d802ca257ef55ec7b17fb37ead78a81b85fa36e9144742fca38c94167382" . + "8dfbfb11f5b5aff81da2aaab0dff325d04f699d8f2b0618425dddd31b0022f6e" . + "ebc726403a7ebaa044a9be5cc4396be0c78551e95b4825ac6cd2bf0992561ad2" . + "224c978b4b52ce0d8459a174b0d1111aabb283cb8ce67eeb8f7677339fc6bda1" . + "52b004e75a0e488e63ab1573587cdc231a567dac12ee3b5bed34969902c5a371" . + "658fd57ad59a9abbd2ae8d3e8f7cf8d7f2fd1c5077c61e7ec3a020d41cc917a8" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d9a5344f047fd8b80d131d73b69ef37f80c8534a7b1a620f4be1a2d343c8da29" . + "a38e903e3bc8397146fc01286935b983c52cb32f5189a43219d2210200884579" . + "83f3d293feebf01c96bdaa73d0b71fcc10762ff457613579e6032f60e263e43e" . + "328f8d36dd657d35256d9c9223d5a28e1157451db94399ea3e865999215165a7" . + . + "552f5cc946a51bb6c57879ec7c9630ffddf73a0377eda3ced7fab9f53fd7f6b5" . + "77fbe164f4bb39dd2505ef24c28d29d8a288f2a91488c06179981abdf2726772" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "38b404a26a7e89befd5768a181a4c135f88bbac4246e711665802aeb8b8516b9" . + "16c98fa1a9a29559c6d6371bfa5f122eb860932baa3c071869cc424dd7f8a0a0" . + "a61fa0689306b6f8a2e5f47d8429e5bc369c9389e398e0f529500cf2bcc13bd0" . + "126d45d3bf9373d5292e584cb29437f1208019faf91fc2eeec3f29098b51cd17" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "785c2ff90103b5a667112a4cabac2d501deca33150b08fdbc222d8c293ceb9ab" . + "4b8af33ffaef6fd60642ad32e0b38edb8384283f60d27a5f4f9c33d1adf8f154" . + "225c6a4880e79d707c99cde1dea4e3bcf0fe0789dbb1acda1ce7b9659cdad495" . + "bb2d63e29badba52169ea4982a3d5d7ef19ea66b1803fe79c72061bb56f39570" . + . + "30afeb2757307bed94bc4d4bd94f74166317f3f2d9e270b2c98c323265c462b6" . + "ea9d0e7e9ceb61d1c52093188dcc03f56e39d534335725e374ef69f46b941c03" . + "7544065126eb616e77d840abb719d83353cbf02f4ed3649190e91cdde76c0232" . + "da7e9aeec6bae49b156195b0202fb383fbe6519b025259bfda43174cd002cd9e" . + "02e1843f71191ab00187517bd63c6cd1354381def8097073f9da0a559a59f6bb" . + "41066cffaef4bd5c5956c58e7f9cc1905d6ef13426b8012722859ff5a2357b48" . + "3adec907135b472554a9537b3fea2b73bf2b5e5351873754cc5126a715ef5170" . + "8998fc934f253dd44cbc138604a5bd6474d418033a98292e5c3a5bf835026190" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d60d1a303b1d68a1ecccf655a65c1ac60f310d58b1144637e6ff10ff0aab7b37" . + "d8f848aabbdc512f726b35f858bf4c2b8f9cf7379c76331fb2577480eb109699" . + "83dd6d9dcde82d82eac8d03faae0557d5589dce6509a9254d5ae1987f7a3edc1" . + "df8c64f481e7076e41b3e0d5dfb4953ef1839d7b463ba79da3030d085458a2a9" . + . + "0fd0678103635acf60d93e904662e440568f24efe5a99688c2fcbc1bef26beed" . + "0e639dc86250420defec20d3a46a6e1f5695b4db67cb414465ed5a66b4510a0f" . + "6b4ac9e6774cbf052c10a0b7011d6b743c0b495b78f059b8968e460defa3ba6e" . + "5706ef8457b1d7a4cc21cee35a0f687faae981546c356b4698716e58f54bdfec" . + "8d250f7130d3309456aa901210081648b322b98c7d2992cd3bbf943e0545838d" . + "c0c4c19259446b21354028f77b818fcd3c5d539025a2aab2aedd095f6e6e5df9" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7d4a4ee82db9645b90d8b9d8e169cff405e7bf33eadb7de260286f045de159b7" . + "6ede6c474419f0e7ae270a5951033c41d7855d47129c701187b95632bc0be221" . + "221f87a5fa619620ab626a03a1c2e93f51e735861c9fa15a069bdbf6715987b2" . + "adbf91ece59f8ddf9647e730cf1321af96f5ffcc7805551c7be3cfd1117bd157" . + . + "7f601a648af860eba423c109a21e03f7453359f886890d9f1df562d10ac40997" . + "6b191b78c7245fb61cabcc0da94e7392f26b1a3a1e035cd463290c18f2f13777" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "a1158a47e357c6ae8e50364168466c6f97de330441a53c63365de8fa9a4094bd" . + "813aa784a1decf26a9ecf010216816ae55454d82b6c02c8f380729969a7a9675" . + "b64abedc7fa4578fc707459190a105efebaa79367e808c39c1f1e0da496b5e56" . + "37712650e6ac16b5126df0db47854a658a0955da00e06c08e27987516edef680" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "04e9950d3c159ec3f4cd7b5015e0ccd474982977a4c56ce0fff1d86e7f0a43a8" . + "fd4cc8799e987c7de57c2d885586631a8b3eee50aca1f57f4dbdcad7adf1cd34" . + "0917dcde71370cd9968cf0bc8a44c4d358698a2fc63f96cd76abdeb552fcb8db" . + "53fc0c7c82c534b4de6bdef76cc47191c00fcc39592ed306188ffe07c8205d61" . + . + "16500fc1a3c1bbb056ef543e240d0bad0ed992283ee05e35e662b7e17c72117b" . + "228b52b66d57941cc04f4e12028887df7f1de7258127342c8b75ed2bec2bb1eb" . + "2641a50bbfa8dca6cb753e4024896381549e62e8e3daf0a887da7ff2e26a302d" . + "9064390b846731d96274808865d7db8db162d874f32f34d268c75affe74858e4" . + "22e7da8a40c2fc8b8693378197161ce811937d7fea87c83376bc63f28c5f9964" . + "a11ce73e5100e744ff89df6f784bf575acfb6e5259e8c72f2a66da7d27cc9e5b" . + "86d70add0c10af89d67d1444d7caf5d6dd965cc3cce614c8c0129fc5937da33b" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5be1071d68d89591ba1725a52bdaabccc40b4c560489a4dc9cab065ebf9fbcbc" . + "373f23c8e57bdc0ee16bf5c03953cf41c4904abba604d22134ee97fcc603d645" . + "012c0912330d677df865ae9db8b1f340606a826d202f6e595c794e72c7ed5b66" . + "a160ee8203a30e1d3aab23507b7f0ed7689b852aac6c628751566a30471d40d5" . + . + "37295a0ea39c10e3999b38de25955c2b40376defd24ae63990763043ecdc15dd" . + "9aff4552852105d69436a4b18c614ab6fe591f1b0cf9d9d41be6933e89071ecf" . + "88d90ffebbda29f629e13a66d5436a28348c132c61587f758df7d094f8f7cd62" . + "6ae0f766a3c3488fe4b9c58569078781cec28c635c7f46c294b9f652e7e08612" . + "37295a0ea39c10e3999b38de25955c2b40376defd24ae63990763043ecdc15dd" . + "aec1202354b621f6a4dd21ded9ecd5c07aab712fe53b3cb89130727c23de373c" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b2dc181249c13f5de421887804585cf435027571a12badc1a9f16e5d1d5679b8" . + "8b8dfac1978dc3f3fef4c9bcfccc82f295f1c42ed7e6053a1dc511fed0504d6a" . + "20f561f5a6b3aaf446b8c03ffb4f185e35398e80497f3656e384bf9ed254462a" . + "18a88e1402da507b45f41afd799bdf9c3cc71c1e51f0716d299d21c47a7bd976" . + . + "052df15d1ddebef1736cd8294a742d54076b67cbe79aa796065201fdcc8249d8" . + "470ec0a6752460b44e1825d17437b40c7d526ae499e29958a7e37198d3610c64" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "0944a25094d3484acada9099c010201047e325e085fbdba6a43048b17bd4b455" . + "97863a9de6a59fed0c692b9ae301b96b9101a5c55bdbdda2f6b75234ebbcadab" . + "2c5ed0a03b53d8fcd0714e7e26c93298319229670935c1b93b350587bfabe063" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "443d52d9acbd6cda4d009528d829d4cb048083edd7794d6cae8efb7423038a0c" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "91a8e28c01989fd762175483dc9efb8766b9185cc18528026c7c2b8699d15f06" . + "6cb86e51df11357746e0e64f74383f76ff73b524295e5ada710fc0e3a558b219" . + . + "e3be3c46ab6231509970e125dc1d0627bc0f3d2fdf4070f2406e2f16aef559fa" . + "7339b1fcf2d465f8fbbdf2bbb21e3b7a7cec03909aec0551821afe53ca0ed2df" . + "37800cc034a54522c2ff27850066e0ac5440998911a026cc1f33e12eb622761a" . + "cf9d3a1c291cb5912a59ab61aeece8ae36cd7a789613cdd48fade814968dd8bd" . + "3d57cd659a2694eece43dcea1daf61e18b516bc9e3ee2b9208c48aac7c4011ed" . + "6ef399826b9b62e096f8a13381a45d152b746bf291a9814a4e4bae757680e11f" . + "79b7bc1087d56667aea1eb0a71607a85c92391dea6fcc3e03b58325c98579e01" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5ae34399d4217fd1517db21c5355ce47112c08a70aa4cdaf601091842c2b88c0" . + "e3d5b1d40ae5a3579a5561ce5f127e14c6598d303a06db516cfc64f29621bdbc" . + "71ecb6bcef2c89d11faa704d32f88b579430da78f814d6ca7c76deefb01f484f" . + "6c949d6c6465178e95e6ff02ca19d4fe7c4866c8b7ddd7f19835563ea76bf657" . + . + "f24e33058ca27d78105489fc2eb1d614b732d1a44ca0fc4f258767768a2c4586" . + "53a1b42fba3858ecb1349f035abf9dae6ec0b282c978eaf67579eeb9d2f3a6d0" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "f2739838ade2092857961d971e114d7a430cca790e8fb5d2447ce1806e92a0d1" . + "f24e33058ca27d78105489fc2eb1d614b732d1a44ca0fc4f258767768a2c4586" . + "903f778c2ddd39837e91b505784f565437d20ab755dcce6cc960136bcb5c902e" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad634ef1f7807dd85c08671b541b0d705669841b648e8985780b29db2faa411d" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "310646d1eb79704ba0dbea6cb9d358422ab2686d99173fbc7d68f9f248417384" . + "a13789dd1e0a7be30eebcab3e2e2b1b53927a7da627e0be3f283021f2225251e" . + . + "d2707446e116e80dc72d6a68e2c4866c11ac91e59768b35135448bfbcc6e4bd3" . + "bb6d213db8aa4ce385b5639fd076a2d36150572ac59782eb6dbdf7946e84b39d" . + "0f9b376ecfa50999da987789223a2c75ed28365ae539726e08c122355821138a" . + "2b7c38d3d1d5776a220f8d4757476b87e1a630f28d1abe8ac33ec6998514566d" . + "3cd82adcf0404cceeaecb38de3b9fad1961a6d0194c50e18afaeb2ea1607e64d" . + "8a4d6fea8c6e232bf07823ef7e0e0e604ddb53b5d9a6e4f4d47ce304b845f573" . + "c500373fe6942b5f63f69e8a76f719f6ce183be3706df149896b4af6b942306e" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e387f49b20b3ffdeafb6f357e7436d4310c28ccde05282cbf9a089dc6f5c7c30" . + "3f0444ce075c4102c97597a77375e04973f0ab1c038dd059f80133a1a6718dd3" . + "dde12d3d194d4d4e8c9a413fc71c2331ac49265577f20a1cff4539e903432f5d" . + "589bc8923d4cc5443337aeb52df546d69dc18ece65214af2a04fd5a9762da20b" . + . + "d182a9ef0cfd8c243efa08bbc94bd4fb77661a9ca1f2caea59e973516b90ac31" . + "0d7cb7aec00359f1408acfd7f6bf8d0866c0385929adc42fef6bb5e1a7677158" . + "0429582b039c8d17a03cfb640abe5c48f385a94a090a60987049118f7af4ef0f" . + "96a4e33248616e5be1422bf3eae02fa4c0d5d3198fc7c65ec6675bc5ae2d6a74" . + "cad795a897296316e31132296d705ce250e6534c7426109535b240e975ab0af8" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "f512711aae176101f2cfcc37eb2ed1202d261191c14992242f095f98d414143e" . + "f37f422927b84efda545145c5277c547f7bb428cfc82018774f138daa8e48404" . + "8ab93b23ec36b19e2eaf3609f83069626ab82f347878569a09908d0a49b27504" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "83b1ddd2cc99b29b5ae1ee275f73e16d787041a1da3cded23e58bfd23db533ef" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "e9db329942a02eedeb0c6702c1744157e32776e5cd3aefa18e1d7569c8db01ec" . + "6b80aeafec883c0fa7d4aefb7be086026da29ec0606fd310b9baecfca377b3f9" . + . + "a4f0f630aa7dc906341d638d96d2e140d1406e85bf3f681bf465b1e55eb267e4" . + "e5bb055cc9f4dd9d31603d6636add235ce5acd72419d59734727aae5d3d5933f" . + "9cf2aa62235885c1016aa11d160267ce812a1579a973d10f793141db0dc180fb" . + "09a7620ac4f73286cd18437ffcff276be74a18ec9ed283fa799986f7664591b8" . + . + . + "9a2453bcf30e525731fa13016b34ae09dd4fbc3f84c6036341588b560bbb8335" . + "093a5971ab6d66ef9e8e7ed14da1db035c3efc1c0d9240ae1627b23bb3e73dd0" . + "187d6eeb01f57002975e5e35f416b2a6c0d7719382b73c2869d6a5f61a0dfc37" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2dafa5e998cbaa4d0b50f1edd4c150b86182c98b642d35d24d298860a93b05dc" . + "e593f5662db7ff660a0a96e3fb1d22a70d8e041ab7eb22957bf2335685264322" . + "c417f1fefe5919ff33ed2252196ec8fc662a669bfd40c16b62db2ebec9d4c107" . + "6977698a0344719682bc80e2a5e42c4d005e69edbedb042862eceefafd0aceae" . + . + "add09dea9c58e1a3c72872ef1c72a3eddf6ea19dd911cd386612c854f44a7e84" . + "f9baf8f18a50880c479fae65f935f95782a82e8adc5a2b7f1bd50f6d20b13207" . + "6d857d6a840b50221c15320740792e03a12280fdf69c40312b4f49ff39b5a0d8" . + "99cf43c144c9485662a202059d41a1d1756b2ab61b1b38501c612a830f529947" . + "add09dea9c58e1a3c72872ef1c72a3eddf6ea19dd911cd386612c854f44a7e84" . + "c731bb4cfe9fd498405a54bfe10aa553cb66eafdec25f29bd466f4360bb84849" . + "ffbbc90b594de234e7da6edcd140706d807640c3e660827756b00d4f3dbca6cc" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "afc132a80b938eddd959c6ba7290337c6461b53d965c0a2de954ada461ca1279" . + "d49b79af0bff7530ecd52beb761205b86d5aadf10eb8b0ad154d5a4c80edd4b7" . + "7e51d279db7171f2ad1392d0b3c281bcc22a51f52e286d1d479abe66c93a4b62" . + "e87fa9098f4b1ebe506df4a88478f056a3e1e736dde6a6a2da2d02ce7d7faa40" . + . + "563398d494502381b23cc7d267804907a8ed4e9f29322fd7c0c65d0cfc8002ca" . + "893dede7ab3f43eeb08a6bc1665f692e330f614897f7bdcc682ddcfab42b97ba" . + "6bbf838c44972e4c19862e8f38c159992242c9c3833df293bb159ba333c8693e" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + . + . + . + . + . + . + . + . + . + . + . + . + "563398d494502381b23cc7d267804907a8ed4e9f29322fd7c0c65d0cfc8002ca" . + "5b531d9c8093c4bbcaa3e32bc14aa23d171efb05ccea0e7d697a8cfb0c68a6a7" . + "54814cca62046c4a31d5b9763dadbc69657cb9e39ca16d76ff4beecfdbb79fab" . + "254b2025433c83febc176eb8b73cdaa505a898e8032962274494f1c22fa29520" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "72c336017a6f2fa7a512019e06fd3827461d377cf77a76a6cbba9e0501f76027" . + "2393f6f2b5df0715f8db09ea08733537356ffe11141fec52459265425f3649f6" . + "916c03726dc5b7e7747c1e726b8e725dcda6e153a9e740c232a998acd6352d7f" . + "274117e64512fffc98c3ad11dc7ff4f6e325f6d82b5a4fe3fbef2125282cdaed" . + . + "ebd5566441c5c7826a970bc86cb89375a1ccff8ed54f3915276d0f2a6375dd7d" . + "7973d1da2b2e90b5d5c34ad45d47c05f3b39e80f46c592583965731ff11a67ea" . + "316798040dd8b2561595b837d68830e9bd81fcb30cfe0a49ef80cf6d039aebaa" . + "f223ba6b9a1b3d89e51cb082d0037ba79cf89c14465544970636d3bfa90f7f38" . + . + . + . + . + . + . + "ecc95c50524eb3f118ec179845abcf1c94a52a6deabc54578b85a796a5feec63" . + "767cae6d1bb334809ee0ba44538e64b31776fa5e81dfe0d7f36a28faf383576c" . + "38aced240343f4d84d19f02f694938384f4d3ced8569ae726cea1424bee976d5" . + "d918e21e6845359780b08a47926dff2cd90a8b0622178681b9886e1f6d4c342b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "83471225b004fa121d74ed83ce81402367cdf6502fd8c2ae195dc684e3f986e3" . + "5013e0453185a74d4246fcbe366b5535b190da2f9cbe5dae51e54a5bf0955f30" . + "24a4df583465f8f26360ffba8220ae2cf68a42c32a93a57db866c80e09c00586" . + "928dedd070eadb627f1183339a685fe169024d06d13b65de505f8613604b70b7" . + . + "92c0b75a69696ba22fde8dfaf18d9a2c338dcdce8bb0560cb4191f1491f5cbf4" . + "931e1124e1f0c7c822857290fdff95d18425244f9cb74c70bb012416371f72f8" . + "7a4161493cbe1f9f9c7fab1c8a21efc0f1a6f6730382c0a253019e4b7b03a8dd" . + "43050ee0c58265063a9f427f0945818c9e3e915a01b06410c349f3afa00f6471" . + "8f710ae40926f405cea30f27f2bcecae07b914acfde643a37e8ef15c542a28bb" . + "25afa58c5b4409cf6f4c0bc7517770bb3e115f3c267eda68e12a0933f3af1dfc" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0dc40f4ff24ba9255bc21a0d75b297c5015a40e86b77ca1e2ccd5fd053ac19f1" . + "a9630fb437046faf1d2c807693fc8cedf68dc65f8bf14936451b4e6007df7c9c" . + "56b40da4cd27c304f50d6670ed15c5e5dcd44943e6a942ac697a8db8acd6dd7f" . + "ae30b4f61fb045d6423122d81ea3e3bb134dfbe323fdc8b561e603cac99a86eb" . + . + "0700e1ab415f4feaee32007a7f6098ba48691f1bab848e7ac9d4a78eafdd8d56" . + "dccc98a79775569f6a9fcf0564c2dc83e04b43af58bf8fb4561e10d76445333d" . + "adb70cec48df85139518f26dfa3967f40c55dcb1afdd1e3a8019805099de3f44" . + "c14261f606fc688af7d7eaa3a5839115d4a98487b82f2667bb685e7a5fd62cb4" . + "98d5aa7b40affcf3b5716f6f03a4daa285ff67c0a3b74bb6dd7c9558de50fcb0" . + "8313d0d97f37a178d1c9a6d87abb43694d27e37eae479fd6a3f3a793e3f7656e" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "efef50f8f6931f1830d23cdac51a9f8f61cbddf2b121d2b3293eb138cf2016ec" . + "82f4287c2478ccc072fc759950ce7c3ffde510bf5959aad00a2146166a935d9f" . + "d67418aff020c5551f2320461ad267daba498e891f8c93598242d2b2267a5d55" . + "4357d2d2e17217330f13ae1c656b98ef6d06b913fad70a2d03e8c6d52a860d6c" . + . + "49bea2362d52c837c02c49dc9513af2816982cd4f20d1d78e4824e9b3b90a7ae" . + "6b0a1f240e4de71f4ec03450841a68aa296e20aa178ad9b6b7a4e30b68d468a3" . + "9a4177cbb00fc4828d83313de2f1f41fb4a164984ca6a4593605022eb9313dae" . + "9149ce811fb29cc68ffca3bc08efffb0ebeb47f010395b7abeaa90cf878d22d0" . + "c59b0b0781e68701a11b18e5435e03610762e631fd5d19ae5e6f2fa069d0e641" . + "c5846674ca07d958f3ecfeb9aaa0ec138d6e40ac102f8985121130a27c7555e8" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5b22fcc119b98db291f87f41c3d89e15dbab82f97dd32a32fc792a47a0808fe8" . + "f9694aa0175a5e24564d7c9bb716e44c98fd8be0263c2558f44f4b8eb2132a0f" . + "c4b8693364c3f5a41cf673247703e24a3503c1359e7e5974b7466bb51a425dec" . + "9058a17380e4e712073995c2ba8c664727e00f1804561d70fc9b47d90f96dc8d" . + . + "98705aced922384642535981ea7ec1f06ce2689092525dfb8743aa74d96e5e92" . + "e4985af315eec76690f2de585da367bff06acc38925c3d90b03a51483b58f863" . + "4cf6b5480f3a772a9d68682d10a367f1d5aa797ecbf0d3cc1df210585c1907c8" . + "aafb1dfe342795d8bf33b384faad7c2043129ecfcc422cb3c269ad5fcaec13d4" . + . + . + . + . + "453b57fa0cea02ba4f3308e6d1c4d36c5abd9c98c68e68ab8844450055da45f7" . + "a521819d30373ee1f724772878a1799c4381c12deb8af4c1733f182e046a8932" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a91eea8cebf13c0c7bfbae4804890dbc73f86c92d8d7f6d9fe98a5e8b846c2d8" . + "455b1040284c9ec79e8e7b6c794908254b7050544def091b53d7b0242ddc0b78" . + "056112b8f9d75a66c3bad2d1bcf173fa2e3927116bfde1ec4512d87b62264990" . + "7531a95bf9f20a84b939cc64efd7a4f3dc4dfe89777724d7bcdafbd52f20f259" . + . + "9e10c50cec1b32b95f31a1d3f1beb1ad4047c0cd24066ab73a2952092eb3e68d" . + "a9e22588e272b34b469b18e8485bfc874b68748b26a8e44c165eb49070355e03" . + "6d8172e0886bf9c52c5347ce7447bd4c69a6f1a7ae31f8165b061fa282b945c0" . + "dd8d3e38be817bfc9386543b369045dd88b054c3bdf32ee4423ad5d80236d762" . + . + . + . + . + . + . + "4ef6dc9bec9826e01e88999445bafc3463c4e3ca8ac386837cbaf19ad7133d0a" . + "8c68ebcdab0233681a4eb17636e2bcb9c316c9cc9eff9efe806bc9913385ad89" . + "03d991442d36c8970dd4fc3e26a9eb8fa07ebcaa8909be7944c61e53694a6235" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f105b6bcd2aa3dc25eac2fdf95dba8d54ba594a5dbf5e840c0d3d49028996bdd" . + "90e066af0d50ee82fe1820f171c984fb9c324d4f0b10b4b1180c7e8cd5ff50dd" . + "25a26cbbeade5aaece15fb29027011514aea61735531d9d4030942e7af795370" . + "a99e16a22082a4c0c98379e285b594ae598ed55ab549abccb9180d6396f573e1" . + . + "5b90f89cef0fb4a424033255c78b3ef5b3ac4410ee423784362e0fbaf6639eaf" . + "e8621630579e9c4c5c6fa205fbd78f324a5963fe7bf0b464c7bc1a1bda6b30a0" . + "f6eac97c000903b0b70b0891eb514bcd0880bb24f138d1a26d5a53b8001ee1c7" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + . + "0c60ceb183dedd9e9018f26a0ee2e6e9b9921c7d8f76b95ef88c627b8a07e599" . + "1e220c519ea379a698f54783f5219bedd372965503457b6ca7be486c79b0811c" . + "49797b6cf956ba1fddd7fad8afc2107a8908f5b0da497134e437136abb09d1f3" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4c9a4ab87ccba70eb9503f49ef121f400863f886bc2741edcb142025c467d832" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "0fc3bd9e91a0fdb39d0b1e2579774a7bffa8e94c8813bf5111b659d7c5ef28f9" . + "bb6d68e8e97a6e7808d06b6d69b8af8fea780d2d1087810b428004bf6a71d715" . + . + "a09a0ca8acb2a40dc0d26a9f666cbb69ad3c2e0c781dfe2d9fa5159a3018ade5" . + "4e2e8a14c30054b7b1c53e327dacc8304ad7a3610f5671ca5ec62a4e3c789e3c" . + "4ac225a16dd52ce886a964338bbd400fa31ffa6455e9995fa3f3f16c7ddc576f" . + "d973683a7d2a3c1a0e1684ee8d30774fb88242d7a1a982b168618a1afd0e9afe" . + . + . + "887b2a4bbb9e8bcc03aeb6e97c5e9649c7da013f8bf8856be6558757ca0b6c93" . + "d0f94d23d853032fe9836aa73fd1e6deb65621da6bdfa5a4127965dc500cca94" . + "a4b9238fb4ba64c9c0fd794499f21102f8645c811cdd3cd2deefbaf5cace3b65" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "407c9bf4f5598beba090f7ea36ee57210bba3297645845728bf222783e215d8c" . + "905340599bf53cd5b99e91a0dc3e9f4463d7705b18e342967ae720152f5c66c3" . + "c746e9a58707e0cd030ca7ddaa0d0de01d45bff69f80b8f174081bbc7d2d641c" . + "bacdd54d2679d8f231eec4cd0ecbf6a96a6f3166b57abeb16805396d06f88216" . + . + "8f4af206c2b26c429aa377fdafdae6a73cfb30b68c8b5d5573e1f1daad8c59b0" . + "0f05ea87b31d8912fd047644ba202f7343261b43393260a08dc922793d2e1324" . + "5d7788435fa39dfe792486744ee38a065c6a819ca87063e0a9d589e460c368be" . + "68b368a01fe62c7849d2c018346a6c37a7e3e3557d6b9f587444fe663c34f895" . + "eda9bf0b893dd3d4b161dbbabfc78831832449b3a4f9af336906e73d8b9edc91" . + "4aaeaebe2337daa2d4991a7c538fbc0c724ba83ca1c82979ba1803404728abcd" . + "6c9b82d9baff48e26044f764a59cf3a054b6528fe6dd6c1dae491903e9344f5a" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d4353d97f88ffb29495482aa6b184d13cf30144d8ae1ff85fd36b04d358b6dc0" . + "11d562177b0c9c82d4ab906bceee37fcf7c3d810bc94694d68f54ec6d48db856" . + "9b7b33811a6673c0c1033d215276b22c2f08912fedacca87a96c0d652680525f" . + "9ccca4dd9440dd43f918f27b0cf16da757290dfa2fcdc442f02c9b543f86cb9b" . + . + "8f520d30502987f6d4e158ec43c4a455e62ea67781d9970ae0b5a51ec4d1df42" . + "cac70f062b1bc25b56541184cb89d9b5eb56dbaca7a673ab4a22161bb9757dfa" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "31e0758b814864188ac48056b5837f18bbadff542dd944a0dc3c166c9e5af46c" . + "53b01ed79b722ad6fa6b969a5320da789e70d6e43a2bd07175741544a5bdda18" . + "a6aca4d0a3a419341d7c1dc8526039b9de5affcb2ecf257a337b91e593327198" . + "093246560921316712ccf52962427f4c07c99826efc2cc228c245a9b7562584b" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a0d3739c0aa6aec974579d75ff96e33b0b33bc4e4e2c546e40d438af8c5f79ec" . + "9adcf21b6664bddce15eb6e4c1d69020f0b48099f4421f24df3cd7c7e5f5da0a" . + "5d4823b2d5a105e52197dc4f5bbb15506221ef220c447acbfd108c64c7f5f1bd" . + "aa54acc74a3dc901cfe86f725965b940937272c68607a3dccd753d320d923b30" . + . + "461736991d114c487d06a0e52c13343d8a5ccf043261886a3f91284e3e34489c" . + "f04481ed1bea741bd5c473afdc547d3ebc78a2b16ba518a7405a44300bdb1016" . + "8eeabf6dca13412bab051f2bdc465197809e9917f0a85fe3da039c15e9536ff3" . + "9ecc0cf421211cd3024e01f1cbaa3466b02446181c60ebcaf917a9754e282b20" . + . + . + "e7f34889e1d8ab6d33e224044b7a5436b4346e9bb8d76fdd950326f9431c8411" . + "779920812d0d8cd10afcd83b36f32eaac52a73f4746f10498fd495273c1c6e5d" . + "e64299fdb6732a7f1267b161cd3defd6debc7b00f3a3f1965148c3649d0e92f4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0c45604b0d06d352822bbe53befcfcdb020416ddff9ac46d440618cc20338dd4" . + "a875e1b88ee0aa25214994ec5f30b915221d44a5c4dd6fb9be018cf05978aaff" . + "2534e51a8342d1404a368b18ae04b7bf2518bac61954028169ce5bd8d84755e9" . + "2ed014529f6b5fd47c7a1049bc86dc9cbac8a1bda7e348a1a615c4311310819d" . + . + "e7791fc5e16ebc69144be73782692da468973d009bcfcb8da0d7e2f76782a7e1" . + "e715c563b4799b6cbcda12661bf1b59dca5a2bdd90e0258cb88f0024c60d1235" . + "4310c342407b96242ea3f3478ad55f0b6f071a58d2d7bc90c00c102452be9dad" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + . + . + . + . + . + . + . + . + . + "67834a9bc59fe8ae701166f7f9637390f93a2c26ea90aee191e5da2205814599" . + "20ad19c9a0e3707168458836c50f37f6a4d22e0652044888ac45a1de0c082591" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "64a32bc3bc2ba46e9d4dc4fad5ca5cd51eda75011451278430ba3e2834071a68" . + "3c816626f2add5248b9260287661415d7c1a96ed9ab7de880888b50d65250dc4" . + "acd45c155edea752f28885b0e469325ec5ed5d7001a4a624e8bfc23963ce910a" . + "7ab4b36f32f39f4b3bbf4aaeadf9c72670b5edb63f870be43212ccc39fa2d292" . + . + "4ca70366741e72e550aabf2c579c591de99a166ec4b3be9ec824276adb7c98b0" . + "ac03145bff51426e8f90b4a6a99c2e906c451414eae04f876b3f435ab61896a8" . + "20fe5012bb3730d4fcece058bf9723efbc6c6146bbf4caaadb3273bd1b130109" . + "6f69ca8735970133a3753aa18d7e0ade36922866cceec6cce04234dce7b7b095" . + . + . + "57b0fe8a2f41c3637ff6ef8f072c5c2560c6d812af296c9fcdeabb45772a4ef3" . + "ec8f79f1932dc74652a2959a40145ef6b4ce717f3fdec203a53b40fbac21fe92" . + "7ea53ecc0cbff7f1738b140db03f3b0785d5c49efe1845a2d6c267ce73ffd7c3" . + "7f1150ac2c9c6ef1f133f776407935a229c7544dd033b29e37e6e9f9de1420f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "66306b78c2fc20207171439da9d11a01e507a04611e8ed1842b7667ed960fddb" . + "bbaf699987824c322fe65c8d6ed4ca0c3829751beb4df4744843840df92fa76a" . + "c114f19b0c9d3a881ade21edc0022c0371c7fa0aa7a457e1f36a6971209bff7a" . + "18d604c80302dcaf0127b40d05eb570dfab5f200f84109451a45066b16e58825" . + . + "65a1db56d6b52b3091944acf1a73fafa4e47cc0b6cb1bd738defbb26314869ed" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "ca8f7d0adf9d18f592ee2cc92f8086b2a6c47ac576575d50485acc8ba183e6e5" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + . + . + "12f510497704b87882ad3e5f57850b50db30656a613bc88f21921163163ef4a7" . + "e65fcbc07fb29712bbb02d2fc7f9e39dcb2ab663a833285d6b65cf54af9b8848" . + "e270324429baa567a95d283c0555a1ffc2a269cf99976920d058f33d4d263925" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "eb140c0998a84d527c3552c2ff3438f10187b7b2dbdbced2c31672a305f87d9e" . + "0d29e3139f834e88034bc89e7897ee73c88e3148304a1f1d3fad9a0ae83877d2" . + "0fc5d2563839b65c14e83e8c087de035c6ed8d5b33e52d74fe3151a19a5a97cd" . + "74ab0ad8a7ebfd0cca9251301a2e32b40c698ff507e7df20cd9f901c9f9a8df4" . + . + "a3cf142beca697883aabd5218f862e84a6df73131d5305af7707bcae487d2de8" . + "25a3f17f8f0f0efe57e1a3af65b71a782a8c042974b217d78e21ea265b30c626" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "4426d693ac567bb6177ae6963d498686de5d9dad5335232fc4b8303433cb1339" . + . + "44244f1b5ba0a787bd765363420c38f6381185792a63c4703b20b6d2c62f2ce3" . + "6d0e79be1893afe6facbcd2182c262258bdd0dfb9982e3a728ce68a215579812" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "46207ada031a9e21d84986a1aeceaa118138838a6b3f720484cc6c00b069604a" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "6ebe30dd30c3b5615f0ef39f55b0825dab2b7f7542900f97dc8927730ac0459b" . + "3c76bc490aecf77d961eae31eb39e2793de6825a8960ca240ac745790f55cbb5" . + . + "b291395fc7868e5765763a6aa7e87b45580a6c088f011160953d332c3079cd4a" . + "ff42d3c821003e815ca43e2b01c3487735152defdcaf1fc94fb3dacdad3cb5a5" . + "ac5c36c40b4add107d5b7bba4a430072589bd381aabb3551af7088d824921d1c" . + "4fc612728b82ad3b6bf58c6c5e39accbf5df469bbe37eb699a768e6cde034a3b" . + . + . + . + . + "7c41dedd7e88285df62e0eaa44bbc1c30156554f9ab22c230b9a9d1a6218d12d" . + "9aa7b25a2d93c538dbce29773299447c6cb4d14a193bdc325c529f1198316457" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "776044dacb9ccb88c699677446492c7b6c69c4a461e3e1681633d5550414582e" . + "0bd055bc730a4c9e0424bc63d1baaf35d75cdab4d01181830e38327cbdf8c28a" . + "c178fd793f27d152a04ad7bf651dd2e38d85818a47d431e9279c17590eeeb6cb" . + "cc63940a8bf0978d58ec406e8cdb43a3a213c9117a193162d3ab16e3c6eec268" . + . + "ecfb03e470cb7c451806add565e02da8f7b3dbd14c38ee62c88984fae4604d18" . + "411be469cf9a600bf97d847f74aef3d57f15e7b341c4fa5fb5ba53cddbb6d809" . + "3651e5b49871afd5a1112023faeb31584ae983313887ab5656742c60a845c133" . + "4d5c9d932bc8c4a6850b7c38b78b1f395420ad314fb37b75488aee1975bf2dea" . + . + . + . + . + "3a16089ca5ce723592e7fc735da7afcff48446ad35b158e60101a6bcbe4b1092" . + "425546e58d44a7a60db8bb6abaa9e101b2dec2cfd2cf39d493cdb59cb96ce7e1" . + "cb69fe6a8a821876a14b39e73170b478516d651c03bfec5781ab0fadbf1c92bc" . + "3779c371001342e62821aa072ffd7fee5f3f86d44b11dc462a97f9ebf2212c1e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "3ae1ee815bf226c5f97bd9b42328b026dd387a852c76f56de208256b6b0a285f" . + "8aff6e8a9189dc78312f9d1f485e86a3b5edde1a49c637ee0329e8c062d6d5d3" . + "40c1385927d9132a476ca296f073298428363787d7e067abda0b3b985080cefa" . + "3ba3e41ac6f5e8b0316f6c1631479924b8e465a5368e3c0f96dcea302d78f629" . + . + "c1a69380a0a9504659b8ead0594ec375d40408a0a36732ad8c0f06024900c5cb" . + "f2b88f932fa5429b9f2d91975d5218628ec6e7b99636f4f0f32b1f8d162ba1fd" . + "d895bebb04cd012d596c7f3571078a6369833d4624c048c61f30a7967033f730" . + "115592de86420799b5f16beeb93142d2623e31c2ebf720bc017cf2976c54a29a" . + . + . + . + "bd637e1ac76161dd18a145b113de5485dae6c10a1b1dc90f3048b82130c00d0b" . + "3c11d9f417e12fd4eaeb0bfb47c8f3d272d882c734c1a8e1391f9baa7863c2a3" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b00990072d9d6011c4cae8cc2aa7e9de6c3691721c457d6d181bc46cc7402ac7" . + "c821dc4f278ff7de133ced545633fd9da4f261fa57268a49b6fe5ac828ecd69b" . + "a2e120390aeb2df3389a819101dd7d5af5f67c894a15e0125c0e4b91815a3423" . + "873776f5786b9de26c902351e06f567b72d6c33d19a3470812839e1df3c210d1" . + . + "f6d19e93cffe6a75086e1f7e6dc0a01e85a1c9f580354a580e4f741475eaddb0" . + "c17d5787f833d383afd4bfe91694af39e85382ec132641eca1e6809ba2cefaeb" . + "b5b7802239a5f858b1f76b6cd12e0fa0bf24f26ee9d32f2cad2b9e85308c4fbe" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + . + . + . + "882919ca18f0449b10246c277b978a3877a2a08c0f70fef10c48af8ec5d596fb" . + "a943733e1e49325f5b17ebd324710735c83a3f0017eaf37b21a8542fb117e4d4" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "4395fb7f3b202d1dbbff332429f3095096dcc7712ece5128db62f65107642107" . + "1bf2c9a9ac509db4b66b33236df0fe223b2a1484e6389ba0d096a9d389d6420d" . + "a6a6c883814b7c0abd1519ac91d9cee797a7f2ee75fef3a4bfdfcacb2b867065" . + "b4b39547d8b3239822f5b3cc09c3c6b2ec21dd7fca8d62f4c43e0457e68525ce" . + . + "d3dcb0faae85f4509730d5c0789a4e7a4ce4c5f0d6c4ec43934ed4ffb72b0a43" . + "1d90fa4b1c442c990df9e08a5cf6149cb5cbd2ddfd30dd1a20d5b21f516a3a3d" . + "7726a94abe2119131b6e4d10243f75eb047a37033ae9db2b73d2d5cd67b941b2" . + "fd4cc8799e987c7de57c2d885586631a8b3eee50aca1f57f4dbdcad7adf1cd34" . + . + "e2b14ca492ed1b65074b6e6ea5860ed8586fea0d0d20fbf265d895da7a70ef20" . + "50d59213802d472ecc65e685dfb942b486883cba6e33042651a4462fa4d13ed3" . + "91d496c0e46c0d8776c140790d83911488f4641ac7823ced6136902c9e8a84d6" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "06d6b854e88c231697db359e69f682ba4a5d5d057d348fff427b514ea40e6107" . + "a37ff197b7eae203d41ba8a5220dc50d374b106b57aff2f952bc113e83000e94" . + "e864842b88f79843b68026db413517b6076dc23528caedd92084cbaeab3c729e" . + "dfd9e85304062d4e2fc5f9e0b13595bdc94c425b6709c1401de426df8b3de742" . + . + "568a4e0185be99034b1a5dc095af1aba01752ab95fc0e2cab8a6c67ed3bd290e" . + "d8dc99976d8735dd6164a1d15fbaa057136eb35addd41e8fb9c3660ce510df1a" . + "8f11d6e1b9c17cd1f0e979c0e50578cd18bddd5bcaa626694d800b0665dd0b51" . + "8eeabf6dca13412bab051f2bdc465197809e9917f0a85fe3da039c15e9536ff3" . + . + . + . + "62ce9d79240deb8ea3a9c9411c6bb08e656cff851ca34f90f2fc8b0f10d68eff" . + "22508c29a3e5835fe37d9a9f73ed5158e7b9975b5376c6a423355f91b61037d4" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e6fbb53da6e1d7e28c0f4475766fe0138931b7bc696def9edf0bd2aea16ce777" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "68442ca6d671b5dfaca0b677b8230ce07fc7bf6eedede78749ff7695169aaeab" . + "8710ffae70cb64cd8264d807042a9626aa4fe95911d23cd4d9cd4e13e3e79c89" . + . + "62fafa8dd5669dc712d92568a87e3acce33a656aa0ab4be7e9498e8b08d14d2d" . + "6629a6128398bb6f4aa4ae3afad37d46f3cb9d9644d04fbdfadafe0dd7f5d422" . + "66d7b668fa81a9c05cfdc5d44366ab313d64b42c553dab799865217ad6d06ffb" . + "9203d12692a9aad1439e63affcd0d64b878ccf3eed0213ebd112881152a1c719" . + . + "f7090b0e30b8095a6c2679caf5957d3d86be6f32d0c03a4dc07cd9349128a2bd" . + "c9aa38e2ba36e82ba71d81727cd3c4c901c7b3017710aa60c35e615b888399ec" . + "255be0db0035432ea7dcdaa17de7c6c90648dda2695a8ca7dad83f499e898a20" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "eb5ac3b92588033b4ae7592301a30b3248129aad9789c8e05cf4720cc5f4c9c3" . + "e451955970295ed8798c17bed8642ae82766d3d28a01abdb4bf993ea82d6c444" . + "a75e213d0bf662b9a1900b290ee08f1ab87c57f3813528707790ee8a4a3af904" . + "fa039a0e5411a7e96c337dd4c29afe897037098148167c0f320245ce8df38245" . + . + "9386d81b9cffb258572135fde17a090f3be43da682292065389183dcb47e0899" . + "2da6792932f8e68c7af99417993f8468e656cdfa8025bd1ed45689f099a1d09e" . + "f619165f1154f46a1cc9c0728bc7157505dd3a2108727eaa5979f2d49f066d94" . + "518f18cedb50f9cf5b4f5020e2d239ed6a41f919243186e3dfac4f2cf508d6cc" . + . + . + . + . + . + . + "1ffee29c79de083f0d1076df4aadd58a7dbdf23116ce456627af4752f38ad862" . + "dffba2b2c8c32129cbe9696751c29628398539c98b9dc859e79b28580e3cf31e" . + "2013e4cc20c237464c16c1d3437d41144d49d2f179058156a61398f193c2c2e5" . + "9854af7cd211625c997c32cd77e475c9891320acf8dd19745b8a71a0f82ce5fb" . + "ff56f7d96c89e769f473e3656120b1b008f89549d03abe87ec9c4c562f9cc2a2" . + "9daf1c178e6cf3f7aec45506384d514a867ffef477ab1198cbf9a8ac7049ff27" . + "b1449f94e595bbca1d3069423aeca9e860d919ac74ac8d9c793529bcfc19608f" . + "40ca4ea5942403d5e9ba5895228ac37ae18ba0180b6d156776dc1c06d84bb44d" . + "cad0e097638f4e98d3d382f37c8537cd3c39f0f7717c0d3b6e88944f16276131" . + . + "7a337db017da3b4bdf295e0a5a922cef1805899cc6f491d737e0be9975e92a6d" . + "7344a3a414130703ca24834d937d90ecb1479785159f73126c5946be15040f5f" . + "5904744d7b61bd1a662f78456e945638a5fba4dd48e4ba5e2634f2706c5b7de0" . + "a8a2727880b40a9592d8b935d082e841302cd8b4f0c67cdc8d5e545a1ccd4e87" . + . + . + "92bd4a90362cfc2e8a60a50619fb0f005de1a87d9ee062fa1f9a39bee05f96d4" . + "449dda0bcd28d38454e5a109be106cdba9a1143262f37ec95b70d9c1f96d4274" . + "7e6b4f6794ad788cca2aac4abc2c6c7b503a3bf4768d184a6e4f29a87dbc890a" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5080c2fa20bb2bb25fbc934e1b36c8bf47a6af4c87b3fe168e093649ff4349c3" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "5e3cfdec79604f91d375e8d38a97892e90227e062b86303389c19057f4e7971f" . + "87e5083690505fac6b4d047ca0f53dcd3e08d636e3ebea073737dc7d27276db3" . + . + "0c0df534fdba833c2ee85381e3ecbb4fe447bc61a7bb908ca4398ae518695d02" . + "474914f92ccb5853bdb0d31d59a2531f859c3920fa092908609800bd48609be7" . + "2b415d6c84c67f565f59fa81bf218e70550cc0189e911aa4e593de3a101fd43a" . + "323df71c8909b363da3ece635c07cf203bb30f114f1daa6cfd3a8e5e8a023287" . + . + . + "95b02012e4e94b3504b2607d68a180777d8efb6bff58872ce4fd09cd170ea9f7" . + "8f937f53c406cbeb2827a42d5ca910455c71e603d60c5d5df3ce25148a644da9" . + "cb7079bfc193b9a162613f333dfc0ff16d1b3ecb3e6fc64a9e5d63220ed919c6" . + "bff67646e39fa628685cda62cbf3906406a957d083de8a336ceb0e44f3ca04aa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e34fd8bd29cc27abcb3a7100fb8d7dc38a0c2e4883e0eb6e1f87c8e374a4904" . + "b7a893be03a817cc76e01f44f313bcf872f30389611a5a0b49cdb61ed54dd988" . + "e555e7d4a7d7af78223f214f3c3df28e0411e2e308dcd664ddca30b0a640e174" . + "0cc56590c629a0431f835bd563633aa4c74fe66e6cde66ea206cc194a930165d" . + . + "526e4479f13e8b0235cf198e5f686846d6c97779e5ab14dfb6d82516f1cc29b6" . + "32e73e0d7a7360af25ab736361b2ceb956394349cf4b5b4969da1ec606c2b0fc" . + "35aaaaa61250fd310204b27a0d526073cc80260f7c2a58293aa24757188a7b56" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + . + . + . + . + . + "d5bb8317cadefdd24ca1ccba0a9411acb2031d99094fa737e082a7c36c65090b" . + "9bc435cc15ecb3de9b9ee44f3e69419b1c40a0e6615418bb17b336d0778231b6" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ab585355ff2e02e46f92c9e22ca1c6e5c99a7d2f9dfff20e3f4991de651cfefb" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "fe35364e42d697cf66ecfa86db57333f9adcee21ebfcd13462565fe0cb5c48fa" . + "e1767b0f8c901ae5d883752d59565a7d6066f6740c298fffe6f1ebdc99138860" . + . + "a1eefb1830253b311deb61fa333bb9fe3ea06027bdc60a8de0a680a84b18be2a" . + "4ab8e6ce880310c89287b809fd526cc07ab1a971731a53e3393f3dafbac05030" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + . + "294fdc0a7795d6ea3c66627df4a8a27326c7bf94dd45b1a72671076f249c15b6" . + "f4aeaac9df2ae60e9aea0f5a458a92135980f8f7afa2159c5025adc315cf0c4c" . + "e6e13e33167dfa5b46d81c0e720151f0f0a4b961749da3d23dfe00bacad1f356" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f82acaeb0d1ac8b9a36125d428e05c4b715beb698855d91b76841597a3936c2a" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "2d5549faf6aeda5ae03658ad4f7a2a7d556cecfd9a8bc15708aa4354d9e9bb64" . + "00f7ea981ae79893a27963f2e2d8c6742d43e3504b8537574eb384bfe7562ccd" . + . + "374553a47685d25896ac47cf0d0b948b8a586eca1c7d2770a9800257214c66f6" . + "cf2fa46c528c3b6b97c69dee7329b8a7e9e37f89cc4803c1bcfc86894b3a0a85" . + "47c7c8f2207a26c86e97bbe302bbf94aae303828d97f0ee8b4a5c7cd57b8735c" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + . + . + "f8bc39aa9b2b76bc4346961adf0bd0f82744fdb933e7d483636dd9b19048ed0d" . + "e8c2461343981506f4ffb61cdfc3d21ece0947a0f32aa199f85fa72da66b0fcf" . + "b92e106e5d26f333ba3a38c08c35dc751eee5d6454f35b8674f8554b3b476d90" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d2d28d15cac4a11a13d28ee58ff561b76cb9cc6b07ca610442f9a44b9e2e9218" . + "1ddeee3902f210cc2a2aafa798e473df3134799e3e7486247f0a271fc8677c51" . + "4429c73b34e9dacc0bd626332f822788a38f71d5acaffdcf8dd4a7393a7ee633" . + "3b2f81de393291f8ac251ba777e61488bd2b417721ffb0f51e7c7e3ae6ef5e29" . + . + "c00eb5dbc2206ecfeb97d06a9dfd3dc19d07ce4efce1adcbd754c5ee4bd96da8" . + "a20debb524e4c5b96c46fb3c7c32cec31abfc8a259f891750cb258c186e74869" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "c3a124817d8e87a9940e90f1e5bd6e888b99fa96e144eeae0764a555c5c9f5cd" . + . + "ce6cd21df0b2be7e23a9a5fa374cad62583a361517d89323cac444775daae53a" . + "572565a6311f3f8bab7ca6a7212d544529dbd79b210feeef70168e5706c1a9c8" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8843f8af7d28ef198f6e332f4fde6bcbcdaaa1f18302b02882caa207c4e0bc29" . + "c8380518faf285b2c75bb4c779523f1bef248d494a74d520c7322cdeaea6a2cf" . + "6704ea483bc283d686066c6772c5d4d4eac7a6bc2f75bf0182d88179a53d1b22" . + "d96780d903ce154f19924b914a7a1be95c02491fca086909d3d4cb56d73c1b64" . + . + "bcce8e9d89b446d1362a7d8538bc983c8dc1a30c351be2a5c3724fc37f8a0177" . + "6f05cbf646c20bff556b7611c08941800552bdb48e41533f3ccd6176db3aa73f" . + "8444184bd1c3cfbbdfc38c73b7864f334b4a873c8a537c657935e3338949dfc9" . + "41067360029e884a803a8dee164e2a2c25439e4125344b4a87cdb6484451a5a5" . + . + "9a2fe5a7c22f2148e49b560978d5aee31fc60bc82d372e9b8d743d9aca4c9908" . + "a1b3c87b195c64311f2c68b8b3d0f1d260ebc0253e78e429eb1b8199aa55d8ad" . + "a9a0f68f958e4654824091c0e7218502f067cffc2c11bcf428401d75b15f9ae4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c1722ef4153e6a9cac95aef0fd8cccde823ff8135ba821515b9c98a73244a253" . + "f17db1a5c487c57bdc4c5436c87e2be0b92a266ec9de8310f7718f5db4840a5a" . + "5ad2f9a1b23f3c6ea03680747a38755674d45cf12e8265d1db487640bccfd284" . + "cf701e861872c3e67e066798ff82a4bdb6d0bc80a043b4234a93c37cdbc5afc5" . + . + "540bec7bc1f134da7183c4ab0ff73e738429fdb830b41482db10862f1be3002a" . + "f418875f0ae18dcaa97df1ee4c1b441f12fcb0e44000aaeb1a6bb93d9fbe4dfd" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + "0575a5a0f350d7b97deaa4075250ef9ae604cbefb5fa4e9b134d64e85d202fee" . + . + "bb5e7a8ac1f012d1d900e7877b5ad87c6e7ee112bdc2f08cdc5a122b170a0dbc" . + "01c04b0673c067b0101300f83bab35f59a864273f8f13daabe02717a8314ed23" . + "4f0ab8ad79593c7e7b3827b54ad48ba8257f1cc7ca7721d3e15abd6807dabd96" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "143ce856eac35f5e84ab12a9eec83b4281bab1d599abdceefa8c5aa942e1194b" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + "6303ec815dcf7a1f41f4522e1488669b5a5e56d58724555e21c3097e836d78a4" . + "0d0161d27c01b465d3fc309f66ab436dcd156bf102f546f7a898782f453b61f4" . + . + "65cc7267e9a5a09e465b6676f4a05bce8fa33f3994a653fcdac7173b4b16d7bf" . + "5c8be1916f9135666e6531a94a7f220033d2fc95eb19704a11a64ff06b6429fd" . + "85368c3507d21528014e5a4265d0319792f41b8fe77a6690095aca7d629f61fe" . + "3108ea50e351957bf4fb5eb0a66011a824403be783bc16002cfe151ebd011b77" . + . + "20bcfa8202c67f94c5dab76d62aa2dafa5e30a46d993395eb373c8199d3a1e8e" . + "04b711f5e15d15e3a64b015f1d3ceb6a9306cd10f0e7409ed22802f2482a1254" . + "ce0a8e2d0f3fae2e3bc3ee912acce94dfcac0037d832f0a05a169da3f85f4bc3" . + "4a904978536dc5adbc24817d9bf5cb00b9057cf5d14cbea197042eb9db3d0bba" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bcc9fa783563b727f783817c94e7cc50ffb984c5596cb154db297de457d6a43a" . + "9c4fa637b9243e6b29b2a635014df0fbdc2e5cce4abe00c971d6787211ae6874" . + "6df4fdc52ef23806c0bcb1674043e1ccb9fe55eacd8c435d3001179baf8f6b95" . + "c20bfbdca8c40f2efb13a65f8779b8b5e46efcf81fc82ad2d129a20f46115e4f" . + . + "ec5ea5bcc353ac2c5d3f7ba006b9870748a75757006024fe1faabd3059ae5cc9" . + "e3b1a34af4ba48fa500f876bbd63e60a06a570625f42a4f01e939599bb2b1530" . + "beb479f3c195101660e285c4f90b75e296ebdc109788a13a3572a8787c2de3c5" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + . + . + . + "d55e3cc133223f635af5c532aef42e2f1fa222c87a8f9ce120b1209692695c23" . + "76db162296a61c642a1ef560fa830806338f9b9931f9effd7e47182b405f3ede" . + "bd0ac9f528ac41c8f01ad9983270b90f82abc352a48f2b80dd9a6ada83363438" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b73d1f1647f1b74ffbbc44bf761be703c1479d85468b4e4586a7fdafa1d9044e" . + "c81ef5b7ddb1de76caf8f113860614694333f51f4dd631b67f1c5ee01c3bb159" . + "774884929e3e92f339a557923ea34f6a47e490f276a90f5b4b0a9d7cbe659c42" . + "1299a890a4d35ebae794192509a794208a4db65c3bb06f841e0bd4b1de6f67df" . + . + "796b183a87bdf4f441310eda71a370e637a4f6426c4c9ba9942edabaa005af00" . + "89c6640ee3d66f68f70b03f9462fd5d3e35e3e215b12e1e578b521b0526d82b4" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "b19ea829d5bd01b2696f17588444233ac826d207b2da3d2f047ff87264c02221" . + "b4dee056c58da98fbc0f5f97a74a5e735624e3a23991ee1dce07c0898b591f1a" . + "60c8586b74537e2fbc357fe54920b928ffe256500ff7b76ac9cc7f431f8bbe87" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "753443444a8c201704425fe0ee48e323a0b633c88f7287c600ba4127d0071274" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "c20d7816b9f5667a8c3b80e820b2e6322e676d509dacb012964c918fcfe3ca24" . + "c0d4bd65d52fb74e2b1fb318ffb757c580742ad2c012b4432a2a369e9d4948b6" . + . + "402c59d5b7e2f7de3f7679cb27021d7a58ef2527547fbe2fa11e41933ff5ffc2" . + "b6a6a0b768ba3d4671625ed5ae6f4e73e1f64350f841b70fb5dd118f5b4b9abe" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + . + "2ec7bd26b73bd5aa92e4b30a123098c89f454ae95d648cbe510063d215e658ea" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c510553356cb4559d54ee2606a9640f94b6a47969c00816ecea27316ef967ec0" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "377a6032143a9295658bf5f0941700dcbd77a008762757d0058c0df25b030765" . + "5e647873530343c0b327b57e4dccd0cfd8c7501f827f168b9eb8da78832e20cd" . + . + "4de673b64d874230bbed767577f5eb4e379414368cebcd6387b852cfc9148494" . + "bf0343a1d6cbd438ab2fcdd1f9c7a94025174ad84bf21ce5e63ebe4a92dfd0df" . + "885f5a7df6f039320f33e77cf231f0c2e15c235b79f49bcbe8d78f8251abaa43" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + . + . + "fdb932478f1239d82336fdb0aac8e96671be18cc1f2b38cf73ac8eece52778f6" . + "bc66b648b5fe0e612f9dc64baa794d56a47ca302c0831970cf3c1ccb01eb0460" . + "3a198a4272d97d95a4cedc59541dc17198af91367b3054252c92ee8bd41c8c85" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f57265f9756cdb58d6c43bd6a0f4c1ecb211d782f4853cce9ed6f29669385e61" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + "fcac75163b3a3d615385b4d84692375103d598e5dd40908e9d957be3f475be71" . + "22a05e930a07e243134e82e88b5ed49a637f86a1b513b67fa839a6627b175ced" . + . + "fb53a2378fe83f723ab87b757852305e60ab90c0ffb3b89c6c1d841e741e8887" . + "adb9626afe77066d07a0c62b04695dcf63773267efd7064ec2549bafc89f37a2" . + "43cd050b5bb121619a0874daf036266fc0fc2f354a93bb0652b212d3cf194a11" . + "c6bc32ceae839935fc42d1b97a0db1719947ce71895ea4088e834a716925e68e" . + . + . + . + "fb53a2378fe83f723ab87b757852305e60ab90c0ffb3b89c6c1d841e741e8887" . + "49e8f790c39416dc2b07e95700b8b18f24f225aae809c6411221a2e3c952f7d4" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9c685b5c4ee6f0df1d4499037412277165f76c476e38a91a54522c30fe790e1b" . + "871043f36c9e4c425db28509d8ddcf051260e69fa1638476843d0efa554c0fbd" . + "54a3406cc50f47fcc4d305b06f234d79daf6b55a7dc39acb05029c66b79355b4" . + "c1745aff2db904d8a8778645f93b8678bb5668a35e9e781b9247c505fa8adfbc" . + . + "86b7cc05d2de70d8a2b6ffb6c9b6d8bf2e10ed8eed163702faf00235018e829e" . + "9bbc99c54b9a6a3ab06fbc1c58a3577270ad87d8b5d5b393b5b4e0ad30a83d6e" . + "7af5c2c7b320907831c054c77d7e725e9de600ac15322839eab0518fd551c785" . + "7a4161493cbe1f9f9c7fab1c8a21efc0f1a6f6730382c0a253019e4b7b03a8dd" . + . + "9f10641cc9c97d9d8d06c2d672001f7a92215e29c6250877786d6d8eb29fedac" . + "524d3372d3672c392227396636ae868d91c669ce6d7c32d2636480ba3d934818" . + "821cbe96291ebe9eca5c1495b08a893c69e475b72e1eb96ab4ad44b846ea4957" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d33883329c4da6dc365cb295ef0337c62a2e246321dfad68c87c4aaa641aa65e" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "b372f7b369e0b9243b50c28910c2ab354570e4eeeeda8e9a3f4b3372e18b52e3" . + "0469a207301cf2868dbdd68ed4d5ffd38159647a9522be59ea4e4e1a09d8ca62" . + . + "6e23d62c5eb318e7e87894dd7b1159b6cda28375cc289ddb77ff1349735c89e8" . + "50c653f6debda329d4bf617bc549ecf60be9e87a5e37b6beebbeebad93a40898" . + "5665231b8b74bd03b3c90ffda29f2cd4305a15b79d3cf8f44002ed39ed9c0c5a" . + "f37f763959548f87b52d9ef3d98eacf18eaafcf23779e205f0e2bc982cd42617" . + . + . + . + "47c001c01e128b94d5518d6b26804e06e786ea024124f79f7127c39057747e9a" . + "d214e42f878609ac2fa0597b380b1b773ad4064d11f211c719227446de7a6707" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "42d1d23bc45ee065aed1ca424c94a32da5adab5167d29728ede2105c226dd8b8" . + "d78c0b2eb01b747db08657e39abb94da9691e2744e16701f66e575db5058799f" . + "3d1be274591817ef8ff785f62bc83bf0f7d974e0ef3a0c731472dbf8be96f06d" . + "b02d4404339859749f0185bc0e8857f86e65a3a9fcda91afe8c9a59ff1785810" . + . + "5fc7e14c89f89fa56195f7a26a7abf6d43d97d30b1282efed5bad652fa7bc436" . + "6a9808d0a43fc21ceae7bd4147ed05e2eb6a93651bf482164e4c3d7b86e7204f" . + "f83a28e6c07b05ff54c5d87150a186632e17376032f27d813076efb2474684fa" . + "173a57de87be676f0aa989b3c64baa43c495999d575c42f037726ede4d73bb7a" . + . + . + . + "9f321ae939b8b812334196d12cd4e52cbab63826261e2b10798f61f238d35606" . + "305269b720ff1844e37698999faca23026f805fcb3b6c151264994c2132763f0" . + "e210f8e39c3742759be4b6679e3c2b159302d3f3e4b8f9f434bd58c7c62020db" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd3be23ccd23f7d2430fb42fbed411b5de2713b8b86d6f5cf6a2488ff0402e7c" . + "42985f38edce79a166b6dd6431ad93047e8b0e06f64322fefb564c231fcd0dcf" . + "faa65138259899d25fdfa0f5e51df8eef1fe7efa44ae4cf902743318b88a2921" . + "1a5ab8498791c06fb6ca6cc93e99e940aa663eb18793bb4b106699953594dc99" . + . + "156c14e389d3a2e2d5093cde718fb2db347af194feda307b49b2f091854e17b7" . + "6a869401ae5853dd2a2a54fe9a40b5dadb3f04cc4615d9924c4d06bc3d24accc" . + "00f3c97e29c7ecfd6be21471648951a59388c9892cb4d770751db5179eb16270" . + "3a708d199e6e76ae8cae55647f1fad82660c77ce2d7b58af4cbb8ac9cdf47e87" . + . + . + . + . + . + . + . + "48f24577ff13535b47a013ad285f936d536dd624d0274f166a90e239d0fcdcfd" . + "e172b0b79d5f09947ae3ecdd10e634317c777c311cfdd48c8c90175a70d41318" . + "44a4101e9dc6062a09e3a25d1a50af2851ae0bb3c1421b3390e79c70330a8992" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "994784d5f4203bdeebfb580b9d391374797621289a44e3992e6cd6dc4b274cfe" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "d189ea5c38fe7d7aa076daee0b1701e4b03468c8702084c2b96ae552a37699d3" . + "4e4e677a60923639131164dc48cbe3428c5f909fe3826cb300ed0dcdc1e53b49" . + . + "e24bd6ebe518bcf550a826a56cc40b4220d2c2e1ceb80e5d324ab02b6181bfe8" . + "fc86b4598aee9c4f69cf75a268a56e5b45228ca30588df076b75a7759dfe8c0d" . + "bf4ff78b10880659ef94195ab9a6972c5146a9a52c8be2158bc9ad57cce002da" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + . + . + . + . + "c261aa1d79940baf7decc10ffd6bdf3dea2e87712d0d26c731ecc66b84ae6edb" . + "14d5e6e5d8b4d3076c23a09039a8214bdb2f8c0dd93d75d3de9c0447311dbc47" . + "d655fffce8c4e94d0d58cbc97b9a62bf5ceefdde2a38a85b3d11bfaf14dfa321" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "14ba00619711fab581c110c61f07619a6df0d8c35da91f7ce7c4436d3c3531b5" . + "065e48aae60528be8b86b89ca8e136b5e22573ba36ababf815361010bcb2ddc5" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + "c26759a3ebdb5d3167a69f0aadff7647e0857106799164c8f6396ddbcebcc1ef" . + "9fc0c075d2358d0844c5e80382ba1ca45539281dd2d9ea395080f6ab2a48dbb6" . + . + "4228112574ff91e770d6416d56124ab97b33cae0205a0bae693fc75d8b1c6147" . + "86683e0c55498f86fb62ea3f7e27e3a62562138a48a43649744798e1f6c726c8" . + "96dca0e070b809d4d8c2a8b3d48fe92796055f9674416ab81e34ac20acc411f0" . + "fc92c08da7ae4a171aac0e53760b34f040cc82324a0d65c6f08af74d2addea23" . + . + . + "fbe7c5708846be123321d005e0f2002c0bd48305a494b19528adc1b4523ea4d2" . + "571598452c0c10b67bda2e0b9c438b63af1a015aefdda2bb9715c01f2152d201" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "021f2ebb0d89084c8fcc6c8cd5e15a36d325e4bcb244c1ac06124d8949870d9a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9b4eb61b19954112fd7f4f5b3ae393d31af7638cd9aebed1d58ebbe20cbd6a54" . + "6f69ca8735970133a3753aa18d7e0ade36922866cceec6cce04234dce7b7b095" . + "73992339b8a85048b0528ef2c5ab66174e3671f4e59c81126c1aef5e6410f2a1" . + "77ce3704b30004deee71887c74c54b12efa3c872138269baa2789b2ebcece2ba" . + . + "174c017a591f7f9106049e2573ba3ff56790500064f3e4be2547a2aae16bdb76" . + "eb72778a52231184d6ecd001b3f6eed71e55758d2d683aa932b60e55bae29888" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + . + "7cfc04ca4eccf18e9d5c560fb79e1807a02b2945aec8a37650a55bf62ac7e954" . + "52138634840e91ec82a829dfea4c237aca5bb2ddd8945e292403a814992c4129" . + "dff497773a48470e5ea3be7c52ca8a6b1fabc7722d4cea06bdcb52aac4f2e7a0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "96c5493f3a1a8d4eed35f333f115204a26ee69eeb3d483248d314a0e36a2f0a7" . + "6a3ca6e1ad51700ba684d18f0350cbce61e6ec0315a7401fcc059854126ecc89" . + . + "74e784bcd70a2a3ec68192536325dab1710783495a1f90abb529cfb53238a765" . + "2838f761ba98916f108872860ecf2edff0c3b68a301eadc323bdfe317defb197" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + . + "5ff6675a0140be81a817b5ae46a4bce8f2b74fab609d2f484121ec4400cb7e3f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fcb28d72de74c54f69a9b28df705a5873a966fec890739d56acf2ccf152a1ae8" . + "089734dbb9a2066593205b56887911028be03ee6d43658336e4cbaa711e9c183" . + "a6c23129ab6387bf150f7a5019b06440b8b589f5e0a66c2016c25b806c5b109a" . + "1e65c5acb0d5da6cee599537264701b61d52de1021b9aa2e0ec747b07659d51f" . + . + "e8858115fb77c6d237ae8fe4637a36d1e152c7273eae783c0f28408eeb06bf50" . + "3743f5ecc9c4b9245b5b326502ec30a50631b78756572115713bdd3456642268" . + "6171d8906cdd17be8d1b413eb510fe4bfef6e08ac99b92dbd66bfb556364d008" . + "c642cbe7224447b157b496b6eed5d08cb37b77d59c0447dd0336360d281592fe" . + . + "6143b1ef8367167cc06a2253e3ff07a7e6c70c3cab1e048ffa090cdd119989fb" . + "7aa9bda015cec0219913d6d815d3d3879e26e69346e3065ceff607da8cb149b2" . + "07cc8c79eb0a117296e888223ba18ce92f909b2c4da7fa1b9795609126a35c33" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b65ef709e95b2f48fd60b25877cfdcecfac45615714920af116319a0a1b3f5c0" . + "4c5cec11287709c903d50b63508e7632c95ea396f111e9556da78ba117ab9812" . + "8b338adebe486bcfdc42f4227789cbe927b5aace88cee058a097b92bc94e9c20" . + "c3402d443eb80d43856fe9ec1aac34cee172013dde920502a3acb1d40114700f" . + . + "36a38224569a5bda7db4d6e2f20090d984af2456dd71a0b58dba26dc3d45e538" . + "810cf6f44fabd0b9da330e2ad82bbd39a466abb173de9b02d0ee36d3d32d0f64" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + "a81692cc46eaecead9a284f814d2490dfd879f922b75f89114845a89ede634b1" . + . + "e25132e3bac72d1c1675d85e7730c56ae5e56ac807a9fb155d6db1ae1998abf4" . + "a959245ded6f34f7d6cd594905d92df6d46bbfdcd26726ef0b6db61103521b85" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d000d32a954c5a4e8ead26b8b58080aeb1ad7884856af97351a9900073de9abb" . + "e148f849f217435b3ac842150a31ac69362950a9b381fd5a69b03eea641746a2" . + . + "8dafedfb0b6ec63c62f4f6f9dbbc9f6f95ab8d9fb9abb2302d5ba3ad1e212989" . + "33f858084337aa31dd1a169d98d016f53dce2301e0d1110efac22a885fefe160" . + "da9e869aa96f41dd3aca2831397f9c2e411495515628d8e9353de64f031c49d5" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + . + . + . + "e0f96989cc2b4ec4e0de720a36c79bf0ad6057746ba46855aa98b1974b5a6aaf" . + "9bd7881fff154b13ae1eae25d7fa52d2f2ec4e24e46a9eaa1f2008eda2da5765" . + "3e345cc0509c31d74b8fd499137cb228cd3c6b4ed8731536e7058ccf58e3b767" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7dd0ff333d429ffa25101a77a93b844a2ece671005239eed44db2a7046502fe7" . + "9aa746b085295be78c8737f0fbc9be4f9282e7ab6a60d1461a1fc52937bfdda1" . + "9ae5368233334af9c905db85847b76aa60e16749f08975da3b17e3ef38697181" . + "e52e4b0447977f917ef05a1b72bc3b31c2a78bf265cd3a88542b0e5a618f9b65" . + . + "a2ca58520f7cdd15de631fc2aa8d984d9aafb5d8a9c6483bfcfc1ed08c8aa303" . + "860b4ff18778ba9c2befcf2bda3e10aebe24b98fd161c4c28d599922828998c6" . + "243c15151b953cc7af7f9f8a0437bdd07f56e4e7bd34c6a173dab882a787de2d" . + "9acab1999d6734b940ad35b74e51b4f1e083b19d7b29dd2b143b1a1afe4d5fc3" . + . + "a2ca58520f7cdd15de631fc2aa8d984d9aafb5d8a9c6483bfcfc1ed08c8aa303" . + "48c8d5bc4041ac1483bacf853c98c57fed91571fbb75b1dbbdc96b139ef7266e" . + "b19b83fb6bb0db06cd7a524830e1d2dbc0887d6660c0c260e5cdf827331ab175" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2dd1c1eb5f2e34f0e2aa5f92e2cc501b24f777dc9430d36f6c4420769e6f6f75" . + "56d3d3f2e3fd1999de142b054ce915e4a39a7a5ba027d0b641b6250b90ee3257" . + "d8e792e3074dead5f68f1477f5062d07a777746e95cf2491f2548281ddd4bd66" . + "def1bb97a984b96a351dde3376c94dea62c8abbbfdd4b487d8c939aba9b6aa75" . + . + "27ead22c4782468777a922e843f28029109fb4a0b89a584073605f6cfb759f57" . + "111f27b9a14634de720a76aec2ceded38c49fbbf326b492188be87c3eb50f14e" . + "c9015711fe1bfba17fd8698b5e0b150a5fbfc65504a07572332001ec6bf319eb" . + "0fad486c66392a2c1c1b4fd7fe13ab818dfe3dd7ec800218fa6e65d02e376dee" . + . + "329b6d08cd3f17e56b6b58ddd1cacde77df6112ae305e271cf8a669eae120326" . + "868137b4e06721acb138ac32d8b58ff4f0d43ed8864c609f71d3d33b4dcfcdf6" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1e4dbb8cd7a29833744dcb57e75c1c0494050656fb5ce73f758de324c04c451b" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "2dfd4ce862b07ca2f962b7173d690bd462b7efa9f0bcad2cbda4525a807619fd" . + "2220722f884944b678443864709a5465b6b1dafc37eccae3eb1673412450b536" . + . + "3d7e067861132d8af577c3e8cc6476bc24b845367716b183542a53b85535e472" . + "e006773237684a87b950b1c467813571ff621bf94f51744b12661d4f68f38a14" . + "d8fd11425b096a14662a314fa299fdbf2285c7e3fb2fa32cc8089fbc15c3121f" . + "5694b41b18a3e3ecb8f046da5890a4790898f9cdd61d777901bd421ffe6c6588" . + "c85d5bbf8360d5e2812295d231aa6fbd307a6612395a4defe3aea428b11b9049" . + "158dc89718c26ceaba13eac05ef43a7c37c7dbcdf552043972125f4bf215f6fb" . + "efbb4d27a06735aed349f587bcf85d0289f203f442e9344b90808bd14d955c1e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a017538a06e3f768d7ed8c8cbc8ffefaa574c5b72e195ebb76d5bedea7500d17" . + "1ddeee3902f210cc2a2aafa798e473df3134799e3e7486247f0a271fc8677c51" . + "eab10fbaf7454518b120e3e429b57a474ee10533862577b80a24a4c68d5c753f" . + "644c6b122ce8e810a0a932051ebeb5b0cf7d6b41b0df503ce71d3f0dc615d85a" . + . + "a9ac7978703c5fd7c8db73c246cdccf667426b8422300d1df7f42f3d9fc2d832" . + "1b66278037f58880818a73fd937c8c2b8ecb5839b24b228433814b4ac2af1919" . + "d317d06c8d3962196110f72943793c3152abbc3741a41fee3dd5c477f7cede3d" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + . + "89dc7e5b99b51f74ba32454c36c3d1a528fdf65a45944f0e5cdc6fa232656382" . + "5c844c4293fb098870f6961b8cbf46fcccf8d248fc75d522ea280d9d13a592ad" . + "85f187a225248a5b7bce72a5670836ba36f8f3933f8c2f6824eadd07bb8701b5" . + "5ca4afeebfa628dee20322126527c1cffc9b396885fa5c36d25ce4d099ef78a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b063ce7ab89532e39258c9990b7b4d7e8cd848dd56b6c94e039a6106142c9875" . + "9bdccc76fa04f8eb685af2a9cc7d2b2116d52389b54ed3ec14aaeb8343b1da43" . + . + "309e1476cb0bf95b076bfc67e0ecb2bd25e6dc48173c3e002bb6d514e8a82c3e" . + "41526441439fbe2e41be9457fd3539fb4a7c324f54ad5f90d5f80a139d87d750" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + . + "17959c0d093ea0f3679817672a318bab6309f9743aa2ec313b80d808c2bda2da" . + "3417b10b25197267c078f6c5754aff9d17db958c0ae512f927d0f5ec951ec3c9" . + "46127af6ad626a122c1c31aecf543f5305aa41df0f767dda440f8f16bde60cb0" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "0c08d4359964c5fe11f7da59a2eebd57eaf306ca8161358878c55cd9d61ff97a" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . + "0927bc60f90e2fb56122e8e37b6eeade39f70a66cd94cb44d7af538caa51f170" . + "629e6cdcaa2a80ed8dfff376b66ddbe49b9e4379777e0d4ba8f49a37cbeec1ca" . + . + "3ddec76f6bc65b3eff8ddb7e402225162c08ee7d2daaf9258375827dc4554da9" . + "3e965f9c4059c9266f7c8e89c431ef18facdded1d5d674bbf5de1e9e61585e8e" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "e68d39f02940f0cb96da629849645981764a32a34a3cfb4cdc2a8381c04a69c3" . + . + . + . + "338a45b13ea11352481aba6889efddce3510fa013c08ae9795dbb29c865691ff" . + "13935f8d3bed14fff1a6cc2a6f158ec3c1ad8d30bd078ef5e1b609c0de70f654" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26cbb46e8c3d727569ddba4c7c4654501f373bb6bbd918bbe32c5b535594c8c2" . + "26bcb904b8b401f7ce15bce697189c06f3fccc234b0224a79f235b674f018a24" . + "581dbaeea7e81f1bd0a0353b31af3f7e62392f66718915332ef71b5463eed9c4" . + "bf67484fd6fde30974282c375d8db31f088f8161bca5d8568ee5d6f505d4be9a" . + . + "60b5e71293ea93cdb5187d14e443cbb535c001fd58af100da823ba0c28e60dea" . + "d968aa5215c5fc52165b0b4216bf7546ed321480c146722064f67615d1a573e9" . + "3104a48e4212d0eff2da51d6e8bb08f3b8ba43558c6461f01c3540bdb391dc3b" . + "3e1e6e32f40250102009f12596f0ff5b9d0d11c53e9a06207d0c419d15b58558" . + . + . + "d6ae468cc408e0d6c9a5449091b55b97245914c3aa1e43b3cab9ec0f7a4fb5a2" . + "efe2b49b48fda0a5157959d6afbb63a98fdc35c6a976e17b3c5ce986440d1a38" . + "59f01f7e26ee852d3a0713b85d0dff99612ce1949222cf33dea0db10b4e2262d" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ac9f1a7079d057ecaf39742383a9f3f730945a5f7480e6925771167c06c0cf30" . + "29fe7960fb7a1ea77faaf5f1fc95b50ed6bdee907581d61e4060a315828336f9" . + "d5b7a47bbbd35126c7b240fd715acd05f6c14ef1413304d0a148c9edc6bc7181" . + "9021b01195fb624ed1d486c615bdb2572e514b0a88c937cccf3681afe631fd8e" . + . + "fb20e4eece48e390eda417c5481c7ca1ebf0260fdfe704c8d0fc6358dbe65c8f" . + "9fe82ebcb8b7c2ee51f7886096c6a88c87a0110fd94fbaea5e951ef740e8340c" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + "cabd3216d8a6997ed20e29a5a05fbe933ed4ee2f16ea5b0cb8b65f99d887eb9c" . + "fb20e4eece48e390eda417c5481c7ca1ebf0260fdfe704c8d0fc6358dbe65c8f" . + "859dd14f6d3730affbff084cb790ec1d073f773dfe24003fb502fd133add44c5" . + "47ffe97c9e345a52abb453e524c91eeef3cea3407d85f7ae6dc6cf847e1910e8" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "200600a123efb9a44c7399ed7acfa6ea7404c67a43f92db03f0998dbc2f3fce6" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + "771745983f1dfafcca2c721548507a9495fef3d91b6f1e698219274f0f08896a" . + "7e463b568523581cb6302c5ec3ee0a3d08cf7dea521e42053a4995076856221a" . + . + "2ec2ec936a6eb0081bd281c040d733d3517296e074aab347ef62b9f981ef309a" . + "36bf31278721a18214b53ff5c2859346847df30327a0d8d5ed90995790f73f7f" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "9dcbda463f50cdb34c44230d6139a468d85cf28f4b865bfccb32abe747170e0c" . + "2f74e49a8f5a55d312a910003e23a55da3394706817d7d734705b57997a154d8" . + "55d3194252aaf6aab94c4429e1af1ba9999d4dcb7c4c2d6038be9bb4de8a5dfb" . + "064c1001eb13cd0da204b2b6b6c6b49d91da117b4415239cc48f60b768428e2b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b53f4220484f37f83a458874cc6bcb5494c7c82c4a51c943831f2a37506d649f" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + "c6a13981f6e5a3cab5e37c60771b47902a2b3525ae4d270f1188a379905dfdc2" . + "11851c0dcb159b53e58bb79b9c1a104cbd55692a7b2a6e5478c4df3bd41c109a" . + . + "ff321de7c7dcba08f002065e15445df19952f5bf68b3263cbfab06374e7cb50b" . + "3a9111798821b978c0c9da72fa87d7a4f32d0de33e6b8ab8f24359919a681084" . + "03286fc5d90ff0a77c44504b74ef5ed16ee30c266161c3758d29518e7b23618c" . + "5bf67521704918c10cc557b56e057f1c9e4361a11797f60c38c64ba304463b02" . + "a2bb9036248089c95fa8ea1abcf3d626398b4261864f76d22d8ab27412f8d598" . + "4b951b04a7a0b8e2287ab909dc366357307134f769a7cb2b921d5c10a2982523" . + "68d6ff75e33c2377c4fa1c8d239a04eb782b50b0d228d0af814b1e76472324f8" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cd2bb3eee9449638073db0c9d42b19a9a2f1f2f4dfd7f40f30960cb4694e5b59" . + "3128d54f27d000b6d8e00894342704529972e959f6b97514b3fa8b3977d81195" . + "4867dbcae24b28d8db3da667acf8e4149ab4808485a19455cabf1ae1eaf621f6" . + "a636c660dba4f0081d6cd494519a1d22bc929eb643e79cbffaabf0ba68cf7ea6" . + . + "05a62061d45354f2699c477252d6ed0e493a80d1139ef9bebded8773f611fc78" . + "666f2026342ccc1b6212c74a30fa7837e1c33de223f103f0644bcd73faa303d1" . + "8ace4298aa80dd11d4373df54c5c591730705a832236116c0ba91ddb1b9327fd" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "05a62061d45354f2699c477252d6ed0e493a80d1139ef9bebded8773f611fc78" . + "fb05d17d5f9327a1618c57e0e43c0c062c8d0086b564262e66af059e2dff6380" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "920a0da91a95e993a9000011d501113e0ae0f41113cb93a88efcfe79be66e4bf" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "ed66e2e55d56157596964c68c852eedb9e91b11b7c7cfec1c23704054883030c" . + "258016c5cde2893c9025a89dd616a36bdb0997a23ed66319fba5f4871bc4d607" . + . + "24d26007281fc7be14ef06ced6c2047eb9e180d362a3d422ddcec36a5a1641e6" . + "e03288485ea0f47eb5fa2bc531934b7bb86c71ebcb876ac2d7433de0b6d89d1b" . + "368febc6c5e7967dc9023618e59f8d39bcae1ae98f0e5376d7b74522cdbf54f9" . + "a44baed6849f7f188bd4039e1b5d6cd557b22c5104318f68d3c741215273bf10" . + "d9cfca4ba4b953d390959fb3a6b8d727f1e094eecf5ae711158f03851c615c93" . + "ac7e6ffe621a5539ee4768a43beedeadcdeccd7e42f18cdf4dbf01943d8fea59" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a82622b841fcee6faac1309d9861e584c73f3a40d99e8aec0daa7a16d3433e44" . + "0642e29eeb6a797495fb20746b516a7caad96093980edce76a298a26b57695e9" . + "7d46d1998487bcc1f95689168036a9516b644887fb56868fe73715a2f2e2dd71" . + "8d39f9120f2d84bc4dae561ae4e18c45323337edb50286ac033dc69a56e3c6e5" . + . + "92b2c1ff1fa63e0a7d1059798f7d81ca5a6a12d2756d9d501deb5dd7dd764eef" . + "345218ea2efd0d976ca3d45d4d9a20019b3f2c5ab80f86075dec65be7018e83e" . + "23c2a356eb7a9a1e7983bfa9c85697dea983fffdf34f03ff605be4676365d0e7" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "0a2f306cce88587fc0f73efa68a0ab86276535347c82b10ae12f763d585938d6" . + "d853b4feb263033311a16ae7a45ad0c4389db36c49d2391ee1de02152f81850f" . + "f069dcb5dc482551cf4005f4a8076993a445ef10adde5c864f224d1184c28505" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e5ef3d18c4a63c29c4e11733dfa424c00abafaad0eebc5083c05995e51ba986f" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "f415f84d3b9fd32ef7dbadf05c0ea2f8039c46d611421b4c5e56fb3c9613b1ae" . + "babf534a7c2c8a757fbbb1b97149f2fa5c90dd8889ef6ed510e1b2ec6ecb543b" . + . + "3717a5db91ed4f29101f39a8a03edfaafab39550879b46fa67af4b0e7039e188" . + "897360122fe1e70594e6cc814ed559b9d1c6416ad9033ec781e7b0528e93bccf" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "6b1bdcdd5ad2b2dac1268a55e3860b7679c84365c32a1e65cbb5c1d3aff72b0b" . + "8a50d4a791132e894bcf02628341ff315e8559abfc71674ca9a224ffe983d31d" . + "592725cad8e7aa21fa7b409f9e65e2e440ecf9b563bed3b25fc49d39e4711ba8" . + "76e31d4bd4796566954942d7c6c7722be98cbe455b7b36777e473a0b88a3497f" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ec6149d256f84aaafacd3de65a89b814078dff59ab33c9fe1071c1b312ca9f80" . + "c1893a02f3b685f1f35081ac7038601a3adab551ac627c71bf12126c547c7fc3" . + "616fe4e07f0554772a290d409b7f0e29b6a4eea2840a3d2d38bfdcaa4aa4c187" . + "8ae0e5fe350876356d62a5ea64c63243228de2b764082e9a9d6ac09e23f04818" . + . + "dd6e643abbd65f3685e1c2026ada10b772155c936b2ba40000b53e7bdaa193fd" . + "6b6c2685b07ca49641564dcee993dc1ec414dfdc8e84142df04f72f7c6caf32f" . + "f640b3a7da52de9f89778eb6162b478b8ead5794b33dc10fbd208b25648c47de" . + "68867e5fcd8dc622fe1b395c89bc862dfe3f45605ba506029bedef59596b673b" . + "4838fc22ae575f759f1c5caadfe73c385227b6c5d91873f2351f1ffc3a2cd203" . + "d703eab1a9fef679a2973c878637c953c725bf55af5ad395920a3c94350d07a2" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "610fa4713b2198bd99b1d95d912c5d859b5d3560919cea505af3b982e8ecc75d" . + "ee680c2301526d0d37e85fecc36382dae4e99b44de858b10c38950807361b2f0" . + "0273c3614a95bbdf91f7c29083f47d6f6cda6766ed702966126023ff1a40a773" . + "1eb74134ddbd8d6847251c63b5e804a6df70be5a1cd08fe87cd7b1dc0fed5cc0" . + . + "1f2e88e560d1ce76f87bc6a3bcda26828b3d0120316e5295847110ef0556c6fa" . + "6de39b8936364db73bf137f30a3eedd6d56d8d86aa327ef63fff06a5b04e9697" . + "04d9746daeb8bdf3ed98d1d7d090936d2e3aeb68ecdc5508f59c9ab615115749" . + "368febc6c5e7967dc9023618e59f8d39bcae1ae98f0e5376d7b74522cdbf54f9" . + "94f092ed78533ebd4dc6dbb74a42d668d3ec7067a5712d71b6dc808d83b31f66" . + "db8201ad89cfac853a4eba867f91718d278e7d3e793d5c6e2bc85c567dab989c" . + "07b0c977bc118c3b6f94921e2f9954607328f2454f7d00478a4c72c360edbcb1" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cc56765c3cfe69f870e050008d759b8b0324a9553682ad9a0f8f2574be1dfc59" . + "214965bca2c51dbe2ac9dd53f90e6dff816bd9db379795cd37e2f63a69965b11" . + "40852cfbafc03013292e0d2770f0378e22c400401dc3e8b57d607b9ecdd01274" . + "af7a6e41f479a54de5dfa7d8a14e2a94e2a4b5a2945c478355551d4e29e2f4dd" . + . + "79b28850bd6a09a443ab459a735f53f5685b7f83bdd24d4ad086e3bf3b31e79e" . + "44825479896df593957bf0409ae04f33ff9c7387ad20e4b26d6b1500c9746c36" . + "c7419329de68c18db22083a93b38f76e5814a7fcf317d40e8e2f93d5f90b3ed3" . + "a9c6acd87b087ad3a9857a00185cf4d8e3c6efaabe3b8bee41029b6d889eb47e" . + "ced744e495a8c6d9fdcfde436b3b83faf40e7b98ad9bc2884a1db9e8251ee707" . + "a89654e05742feb323000ed406eaffcf7790e29f96f56e46459c3d669e5ce1f8" . + "2523a739264c7d7564850ec55c6494f2902562c3abe992ca057275ec226d7185" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "95822a21d6097a68844f4aa5457d01634e52eeb5bc93a7be1c851c06e4eeec23" . + "beca583c0ab32aeecb659353a9bb670cd82309d49133cc6445c16049e5d18b5e" . + "2f9a68ebbf8689edf17744e58872981330c50fbc7b91c9c4b9e2856006b3bb1f" . + "ddd67aa4dca06eba08d77ae64c669ce19249e360f5b2c862ab7df9ae1eba6082" . + . + "a687e2c5bcce8aa73c7e2134b6711f81d4f98588659ef195cf3010924853adc7" . + "8bcd2997de89cca0ea247b78889af5b49a4fee953bff0c2082c223d534af8e6e" . + "833cfa86bdc69541e661bab5478f81988d2bd3df4b191a9fbd4dde73528d6d89" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "681a3323fd2b890dc280433aa18a6414686a20de1b75d7ebb026bc2c3f3854d1" . + "cec1ad850472ce0f9850de684ce8386d349ceb9878467efcfabceec12a333984" . + "394606933af29a7bc610d8eb7bf9d457d0f5dbb61764004a6f3afee29ca89b27" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bf6e74c1329751634f448cf0f8e8e80b651d61f608aa2c4798ac1edb9dd90c45" . + "f65fb313e4967d20b261b3996a86322d0eebbd03237bdb0404fb1ee0f64c0c79" . + "ded8f79c61b7bd81349de57561c11a647609a668aeab33f8d1864a82d4e26649" . + "e624f39d1bc4fe37d882b4a09e752d108bd1296a3ed48b9f2fed913290f408f0" . + . + "f1df6ef2c9630ce9c10c664f7e3517dc3bac6475efc3aa26672ea49df8f9da0a" . + "0903c9defc195715ffeb77f57c4c4f5c008c21731d283c8248554dac00029919" . + "a2f10ba706914a7b68463207b8f5e5263a72b00281610e146301f3ef6ba8a8d6" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "57a3af173439052d0be4401f29357a48fff177f5bbab5d288c213a9a1a7de358" . + "429de57f399b08928cfeb5edeac70663a8ae75fc2a8cb5d2f8463b0c3efa2127" . + "0c07715eb9ce5ffa04d703370994a96f127ec0210c5d7a42958ad24b9534a7be" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "47954f0cde176a35d18f7eeba8e5f5a41de26f0ff2d569fe3fd765a748524f66" . + "9144287133e9eb7aa2373b08047f1388f68ff94ac325477cb91ba074b131717f" . + "f0c45c6c5e003cbd4b377495eea0af9d6de78e3d833451b5754e38041794ec80" . + "b2dbe2a822669d30cc11ab96acd9bf1a87056e9e7bbb35166ca3d230dc673932" . + . + "280ea9b1a1e2694aea85452bced1f59f7512331e0a900c79df55c489ca5e1f76" . + "304e4b988d05ceb007977502a6b5caaf19fd939bdac6e054f0f0d3c2d15e6db2" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "0dfcd94f95db97e36788f52b7ce425421dda810fdfafa224e86c15ffed21f18c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0ca31daad013f8784d8de49824238c7c3014a2c4a830fad3f0b2b020c0133955" . + "a354c85c6b65d514f428592b698c80df5443465c496979be99ad771361a36ab1" . + "af535619eb692ba6a40d5be19e6d7dfb57a49af2083a5fb1cef069b6989ba63c" . + "bc57f5734fbacf8f1667a21dbab3435299ac61da4d849cae571aa62daba7903b" . + . + "58c1e48f3a389a7095c4dafc9fd25db590167f3464466a89420f763a2979e2b0" . + "93b7da6409d907ae6925152c4137db4db36a1cb4cd8cb12ee496988ed060fe6e" . + "52ae9b3471f7a94aad95b38df18be7dd19691074cd7ff682a131dd3f1ec9ff93" . + "925c0221594ae0ac552f4485439b07a9e7ae1fac41d92750c8877206b6ec8a43" . + "0de2ab800a3901567fa05477a6e668181ff8e0cf775d0bddb89c18b87fbffc90" . + "1e0ebfb9a79d300da734242880cd92bc7baffc821358113dd3b225c88f27fca8" . + "0c07715eb9ce5ffa04d703370994a96f127ec0210c5d7a42958ad24b9534a7be" . + "c18e08e17b4f28c1557411d625f199c279f5f667e869d03da0b0a3f721fdb350" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2eeb1ed3d22a3c4cd17a5e96d5cd333fb795cb3735d4af85c5dc5303243e0095" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "b5040b52e2aff52ed3c0286ae43ad8217d1fcc44a586ae1c05d6b4ca7b586d64" . + "149fb105cad14c6fa6b49c59e41091fedd844f94f15e4e151a7b1979fb70701a" . + . + "0cb0945f68450eb152ca5cb4cabdb29c2862363b4580d73a67122ff2449eb8bf" . + "4a0aa9385a430dd2c4830acb63b9662b854ddd8a092d1e6dd4b75729d866f543" . + "c07040d229d0bb410659cb40d7989cce9bf6312ac96a35b5763563202d99bd2d" . + "5319cadafe5a615f7e6df1baf8a4a20ae04da9dcd6602d1d13dce5bc00485687" . + "1bc77711b990707a49dbd824925e240d3036293b9782a019eec36bad3818ecc6" . + "2b9dad7e3308225778e1a430552d4a790429438c651619f3f80c818755d1a325" . + "ff31c9355045a710e50799cb74ca5d5a7f472e4e18ac05d68bb9fc4e8ba66464" . + "5c598a2401635b3ecd4a7ab6901f92b2059df83bde3d84622fe76f6c4b198d1a" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1d481dc49ba2c504af3e91c77850059c6cefa64f46e82eab41e858c074c13c63" . + "fdd85c032ec741696203fe736e1cdd700d32a14b4363f94e17223af8a25e42b2" . + "6b84ef5550f53d507b1a5e224515f78669acd0521eeb08a51d1ca2556d995b80" . + "4641c1b80f3dd7290bc6cfecefd1ce1e4238f04c6c0b4801a98f6d695aa17032" . + . + "88674a31cf78e56d89e5920726d87a918365cb5e02a7b3ebd30dc3ade668ea05" . + "ad2ae8a1b7f5105fb4aca9a4ba62f797c9b19015f31be3b79a577d1429dce2eb" . + "aaec19d0985e172d92de1bdd4e108cb5692aded3b3f598c18c824d142c27e3ed" . + "7660a1f55d599281eae759be71c2324775a4119e0dc8c9892cde23d13e152f47" . + . + "6fe4992506ab43ad387686293f106e8698b2bb9dbd93c637b3fe965f442f5fc3" . + "e2220daa869abe6bc3ed39b51584eb026671836ab5d0d533e32d50cddc8fb9d5" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c566f7401ec7540d5f7aed1a7feb60b53aeb5bfc63ea82613388dd5a1fff6025" . + "475dbcd873196880c90f192b2fbc2656bf0eeacf2964fc9c265d9ae7fe747fdb" . + "ba1d27756c8aa03e8e767c239f6e12efe951988b40c98e2f543c349284ddeba6" . + "cad90201c304044ae2eb3106c2826faad4e85258bb70f0378b8895a594b1982a" . + . + "2391e0eee3c9522bccf1cd72ae60845ead783c2eb86dbd3670a90f7ef977eddb" . + "6732c400f9f926b5fe3d33c7d9a7529ef170cba02f8c2a34d56af3fc1599a4be" . + "5751825747d4a4b56511836cb22022d918548b22c4e07470693b8902f08e26d6" . + "f779583233d015bf73ffd266da4b112dc8d9d2aa7a0033c5311f10b7f4a08aa1" . + "c18c34f247ce13d176fa10cb39e4d15d62d532270546492f0e4836166d441bb7" . + "c4999bd6fbecec826d86b632f5e95bace79028382ec881302f524e1c83006eae" . + "792a3c280f9c87be9ff598d30ff763fb932be72c0a45301623c7cfe49b0181e9" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6e06efdc41171bb5a85b79c48d13d9acb5c9e67d37549c783caa6e6d84d32c6d" . + "41ea29b748651f152d61634f9bda104fea3812a9ef7b488db82f3ce947f00ebc" . + "2f080b8471ab77d4afff421544dcaf15a399cc2cc49192df8f8f2f4f6b0e921d" . + "98f59368c12e6b488053892f12b4b4f6050a9369ede35da90d87a43cd14be216" . + . + "93d74d5b40c6baa8c3fa81cd8093d4cedd0ebaad1ca603016c13fa6f272abc09" . + "2ca921985106140252544b6a2028c8e14458376cb005b32ecb7d77494f321b6d" . + "2f5bb29e64391c175c1f627b7f7f17a04f20f151e8f9ab2438dce2b5a2c4dfb1" . + "9dcbda463f50cdb34c44230d6139a468d85cf28f4b865bfccb32abe747170e0c" . + . + . + "7fa7280528615a38348154624cfa756538377bcc6609558a7da4654d82f97b2a" . + "5f336c25731f866b4fb9df2f9529e6ac7888cfc80e07ac1d942eec25a70e541e" . + "ba49813d0a281c869c4575ad88efd865bb20378bda00d01f9ff2785accf0deea" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "94ba9b3c86587de99ed0f45e0f6e35c85e8934e63af2fb7310b813070f7b1baa" . + "917ee9f0ee9fea4cd329b8d1a4d194b5ca10e1e693fab7ae13ea0c383b78eea0" . + "9dd66514c88b38c45b3f2edc9fafe44d39b23ce3554e5ac38795cc9bebeba61d" . + "2d6eed978added0979b521d62c92000534845a03657cdd16699e9c02f353a777" . + . + "51829a2c1454b8ba25036df21c8140d726361c8073f9176e34b3e773a38d7c7b" . + "1db19d220bb131856f21d6b4871cf14e72aa03a36da065c787583844a4df4531" . + "5f06536b696ad6110943a6eec4a12966ec48ae561f55de5bd753750bc318aa8e" . + "9c3bc73fef601577dfdcc0debab06d9a701c7bd85b42ea94ade2bad376df56f7" . + "a84d39894749c7da16684b187d039a925497203e9506c91cc5158d30b0d6c636" . + "246268c9c7b739be3849a5c9ca99023713854acb2d942461dd01d218ee745989" . + "90bb4f1e97d22feacb7a146e098f2b086115db43f95e138245a7aa0df71d7ec5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "34751aa6962ccd9f11e3306a26203526a768c7298669097acbc849c48c5a7ab2" . + "10ee811512879413e2cc432da46aed8bc0967f0c8eec00a0dfd50193e2947434" . + "490cfd1903627d5f62fddaf189d02bfe52eb2d3fa99a52e04c8fe0cf4951a5e6" . + "028024b50d2026d8160b2176435ea95df71081776167ff0169cae1d64cca44a1" . + . + "d9cf6f67ddfce7165d374304b78922b70eee88dfdd11acdf9848668fb4429f20" . + "da25f24eb1a1bb394bb47777916e4291dddf2675c804048aff347edb3a6653f8" . + "84ccc81cde19eee60f2fb6697c96f582cbcfa262cb4c921c27a05fe16c159050" . + "eaa180e59a35f6420d617db1958de65afa491c8f040d4d17faf2767921fa4c57" . + . + . + . + . + "0ac3a27e7356bbef782597de9dd2aee2766b393a634b8e8be13a79119e7c5c2c" . + "066474f56f8039573432cc7a087e2557e5614efc573b76321d970b22fa03d65b" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d5727fce17845583ad71f572330fc7a543ca4034450f67aca230099ddf4c70d4" . + "31c5b2f1408e6cd6a452f0a971c2c245842ca5c345f44705fe844cdf574c4320" . + "742215fb356433face2414cc35ed0ab7b0b460ca8ba42aba0ee9131361270b24" . + "75c81a3b0f7c8ef662a77b0e42e19650503f49f5eb96de25702607e91ea1c709" . + . + "331554b34f2d12a55c08244497f93d9dbb3624c26c8c0e4423550eb9b348fa51" . + "e9364ed59ee2dd0e9fdceff32b733b4344ae58da999b18c2f2f1c74ffb7e870f" . + "b953c7ba4621566d05e7559aea5b01e37bf4fba7051c04f4ed9c99fea832f831" . + "6ae1ee70fbcc6b2d41ba6438a37547e22f387ba7d7c732c7ff66d5e5e785e398" . + "3a8e9ee2c0b15454ebc64fa21d1de340c54f3e9bb59ff18d86ed468b9d30c9e4" . + "9116aa7610d9428164f9cc07ae4b0299163c744821b1930a96fa62d134b5c26a" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "78c72c4248b563c9ff8ea4d4ec902cd550af0ed4f479bf1b4c6c549a1f814e44" . + "e5598ea55a4ca8a89885889103ed5cbef1ec9959610bad320474c49831735d93" . + "800bbf5a13537a3bbe4047d33e6214823358780e5e1b7713856a086c305fa2e0" . + "94f66e0cdecdb218cfab40050dee064d8dce5b1419f5c8901460ab3621641a1a" . + . + "db6d0dab236b3550a403ba2b00f534d4fde78929fd5f358af1e31c50d160d333" . + "90cfb4fac5e5b96df484d0fb41de523b8ad12a99b6de5fa29fcc394a11f803a0" . + "2567110cb06e83571f3462c7ca69b7df4ec5fa2671b8070754e237d3df13ca39" . + "1c72f8bbda201f8f7ddf1d7e6f8938e4c0f800c765478aa4c267199cb1664525" . + "60b9c924237bcd8fc1eb7301fc461939269091330308fafb5fba0abe6d581da2" . + "54be8f2705a093940ff53ff7d865d9fd91df429406ca9b55d96ada77cc4a05d5" . + "6d8f4299f5878651281ce31150d749998de605ca1dc1a846cd101cc39ce69d58" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a1274ac852bd711cb676b977600a1a8c8870084c14dbafcb74a4a6b5325cfa21" . + "7a3d8a11731c59c62d53a12acc0431a1bcc89febdf5e6e2a8412a9bde30ad7c6" . + "feff76527d78e50012a6f53741fb7606a9d6a372b35297d98e63149564dd4669" . + "3e1fb4019ffe570cad4e376b6dbd53332fe0f5109f63038791f1dbbbdc14f50c" . + . + "0b124e1051afcded7f54111e0fc0abcde8a2f772f8b61b4c5f364fc72805bd4c" . + "2d26fe25bdd7a1deef288ce5ebb0debf51e78dd9f997ca132957534423b19212" . + "9c9ff662894bfd22b3baa05deaae3fe257a0934caac586e322ae8e4a9f9b1629" . + "dd8d0c9abc63287c03b96999a14c594d5b8fb70e694ce6b81a5db56fa432384f" . + "abb0edfda9eb8417d7cd8363fb3536517ec8226e6ae58ecb0ecaeaef0ac5dce2" . + "1f067402bc01f105fad00b75152488dcf9cf545277dbeb98b771e5aed2366304" . + "bc244f8fbf72164e535a8bb7d77bcc9c15d3104c7165a147b8047e6ecddc41f5" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ca86afafc28975ad402cf79a5012d90344639a462c8b7b6d0c7c5dd51eb3470a" . + "3ec3108d144b3c68b1a97d166abf68de7db2a02290309b7653e7c0afeff7b019" . + "cc65f901812dea92e1ee38acaa7cde04950e08cb3304897b41fe377cf71292fa" . + "aef5b17bebb5d27b309f4e530457ecff22c0dd551108bd2be3c7ef11061d1520" . + . + "5f4673076318a07f2ed5d5b0e802949d0d08445419d1b967c1469fba1d038e1d" . + "e46ba9882740282c40e91b230214a085076dbaccb5c3194e7ab01751a0554131" . + "f039000993cc05fea6752e906fd88782dbb9c1da5675686359303918a26d32a2" . + "9cf2aa62235885c1016aa11d160267ce812a1579a973d10f793141db0dc180fb" . + . + "411772f1f6beba2f0e04079cf6885f1c1d43ff0d03f7d523982b1b6cc3c2b45d" . + "35d675559cba63340ce4e95f21fec863618516be40b0e5a41b1144ed48a8efae" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "33a3cbd16ba2543bef91e2e949f6b9e7501b1e7349d8afaf2824653f095eaa1a" . + "a7e2e7705bb9249255f47ccf50927bdab86ad19a6d112d4c9b53451b14643926" . + . + "19f89a04f79a6e523e4d7a67859c458b3280b06dd6321dc134dc37b12afd44e7" . + "3bb81a1c15fed551db77b8930b9f47b1d3a611c7a0d408353f2a886bba218531" . + "a4228e6449a3ed551300981706c5b4d155409519e20b2aa4cf8be00b5be67361" . + "061c780ee97558d912961803f85758ccdca485d68ebf42a2aefc8275607b4ad6" . + "bdbeb35ab13343315cbdcb6d1c729a332c34a5607de54148d531515f8f318d98" . + "7178eed118fe391b1bde9f6be880480b65315e0ae285edf470220af9b5f3d0e6" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f672f261af90a78e0016449201ab667cc3afd33b09d79e12979259ec6d9669bc" . + "fbb534d437bf5cdd0b384ed2f37ea71fb5dec8a39cf68f50249bfcacf05224a2" . + "4f47e6873506b7d4b64a28e874e20ee2770c1e97ceb8006a3f4dbb5f2e481c92" . + "32c3be11004d265d12654a3cff0b7675680de70ead0240672116f9a2a2148d7a" . + . + "474853047e7fd1cfc750a2fccd3a01cb3aeaa3ffdb804ac2b6480dacd7b73802" . + "2e922d379439d396a5dfe3829f4c4b6360aa4bde5af3217ebd8c3bf87ac71af7" . + "862427cbffea4e7cfbaf932361c7781c90c8e29402a483f0bae438f5949324dc" . + "d30ef6be83289795dd1f8c3cc93720f5aa03c56eb7f3bc31938d2ec632e4c7a6" . + "01c6472d385cf314d8854f4188e8357d6c0f306246ea680ce76049876008cd82" . + "1d8482eef86ad2f089e6b676f423b07d0792a7f3e6908698aeaada2e74dbc302" . + "1160f22dd432b06fd38bab0ba83467ce12b997d11e890694b9101733c1403295" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8c1c4e6713726ef053dc387ca39f3c0f14379cd1ea64f7c1dd7d090bf3dff4d7" . + "405373a6397bd3a4e3fc82f0629e56ab41ecfa87a9b5d65c54fd829b2bcf92bd" . + "e73822e6b14d4b80bbea6098ba98215f81548f2fd86d70e4d973e96646f9bf5a" . + "f7cb6a6d53325ab1eacefa50bbf69e05edec84725b3a5d347e5354b6ae4db656" . + . + "a8999dfc1764365f78db495d0e7355499ad08210ae0d3a969151ec4bdf96285d" . + "a6d05be9c69de00d05d4e84e3cd6602e59c50ff102533b919b073953b83ff6a2" . + "aaa2fa5035da10fe69443ec552a4bfa33fadeaff74ff35dc5a4807df3b901949" . + "b6bea5a8425755cec4ce7568c5c556d10340e54f379759fe77388b80254b46ec" . + "971c69d01f013c48eac3fbb3b3cfc836ceca1136b999ea9bd1881f97b2fd73e7" . + "382238739babb9223244ee5e8b1755a6402cda0a76b70fb0caf2e132fc0377d8" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d1c1a932656fb49d0285088de9fdab790aebc229e617417daf872a6e52b4367a" . + "98d0e97a7592f9eeddb974153aeea14ff761873c8917f6385574de492480ec75" . + "2f3fe5e8e03834039e690ef9383fc47e1706dbd143575dab00d45b60cb6acda6" . + "3fcf8608a42b8bf932e4fad8a216b281a1cdbd3bfa8cf667b203575e400255fb" . + . + "f7801ae9e2b7e4fd8ff93f72b158d6717ee0c2361846ef527047e2d92f0782e2" . + "21e8864856ed6bfecab7dbc68db016a9d9bd9cf226884ce702e9c4a8cf300887" . + "edf21f35e4add4cb4683dd7ff4e6acb90dddcc5a9baafcb908021bd9e1216771" . + "d05a5505578b9bf48aa11e01ddaf9ca7b80313f9845841279509c69bd3e2d296" . + . + "281e61440cac2130b2dbd418eb8cef61e94fd4d6d63f0e46ad9fac8707873342" . + "5541adb304eb578cfb2251e3d096267f66f3c74a487eb06b6fb3b9fe5e5abd3f" . + "5a0905c3b6ce06b834dcffc291975f448e7d8886027e62015657f5d7820b3d56" . + "42ec47ad8f9d1234f0b45f35eec1a952a105c1d2829edbb530c4acfd43566ceb" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c3fc9e657b1f0938ab2e5c5fce762017fa0c3c04f905546475857ffdde04a410" . + "c8331da732d66a87fd37dd41aafbe86c3df69ee4fc5ab42cb96ac0297f215f2d" . + "c9e8439f917faa306d4c404ef5dbaf0d96a38ed90fddcdf008d2c3736156d325" . + "e8b1a2de9a57d88de0083ccb4af26bcb36ed18be3e1bfdaa184a4408b5bb9201" . + . + "a7a85108c8f96f2f8b9dfcc67be2e0ad6cb31cf564900e5d185d686c1ace33b0" . + "3741031639cdecc23fe6ac428909fda0270627e66e071d434274520b64ea2f0a" . + "0fcc19c9f32b7d0ad5220c6637efaf430c6a792e84685925b0f62931e0341aaf" . + "cdd4faeec60ae12346b868e6fbf5e2f6e768bdaf6a068bbcb0d5f5bd4e2d5dfc" . + "83140ef76369bd9ee983e25802ecf240efdbde6f67b9d6e187d4d45c31bb8d28" . + "37e146a072bd017079a72a2ecc9953c51d997d53fb2064705926c35d192c2d13" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5aeb81b698448b3fe0c79f2212ae39e061a509b3afbe154b284630aabd906b1a" . + "e5ed9c966618f9ebb695a21a7d19d3ba4726008b95f44793eeb135bd4332cd67" . + "57495f0770adafabccdbdea5427df7c4dd67a55dbed70f869ca9495a828cbc6f" . + "a8434dbc0034544a7858e177c6aba39bde5202df2e156eb0de310571e6d86e3a" . + . + "ca8d76c20d677f7b604a98d385bb00cab368478b1fec505701e4fecdce9c7348" . + "c723084392a4b7c51ef432ece9737e8c5804a477c8cdbfd32fe7d219e8bb2178" . + "8d874e51663853298f1d41d1169eeb25e788a5509845b87f87a5ddb6c8ca0673" . + "e26b27528a9b12d958731ef0d32360e3a6f1a9b723b5fccad495a28d7342eb31" . + . + "c3f048b100a78d49a85b35ef9dce4e659cfd167c318ef7f1d4db727292737f29" . + "659eb76fc84fe497abc1927f70f1d92c5578b8805ac090851e7862898c42eae4" . + "1484dbe7c869acf0dd80efcb3bad7a1dcd66675334a9a2c48a866c5e3778eb28" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1de7870a1ef1bf9f0312e1624d8ad08622e460011c1b2bcff22a471893cf833b" . + "4c5305a19e594c768721c08c3dfe8090d32a1fa11fe1715e6c38669965f8889d" . + "38551f6c9a9788ae24fd6efed1c4324875e798dd26eeb1928a8ee9eb58521aca" . + "204fe8944347e77f8c4299be7fc63e3287660415ce735191a56e3c7200f9c731" . + . + "b8eb745b41e8fd1faf17c9a89c08048a685cfd75f8205b024ac0ae6da978402e" . + "251de6cda72c17cf036a8a9ce4d9872148f0d742e84838cedb44117cf2f3f6f6" . + "18a919c3149d059d47d177039a15c13d5c74325e69964e958c20bbe26e8029d3" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + . + . + "fe0ae89b651c5a9a99275ff852eb23b09478bc85b7470184bf9090cb0156a340" . + "e80def42800db0ecd45704add5c1330c0ead8c69c0135ce28224a7484ad143fa" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5e4b9ead96f4100d3e9925dcdfdf1f76bbbadf85466f3249f18001c9226b3dde" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + "c7f1e9fb946ae4cd3288e9c7e95070e27a315edea35d80214a67cfb7234af10b" . + "7f4b543a9d79ded879eb14308189de0ead7b27e5b71445593cbf91e89093efa9" . + . + "77627bbc1e456f923122f8664cbf8023417709beb0d6376f71bc81aa15aafbca" . + "76db4c04714b8d468ef6017d6429e63ade50e9864a8a42ca53a7d1b08c25005f" . + "fed7ecb7ab034e427602e44389f712c62b012af8bd45ad03ffdbd70f199fe148" . + "b5a937129a8ebc7863ab353717ffabf8e548978e88582a929ffa44b9affcf2a6" . + . + "3f31e29e03799f8d013b6f9760095d41198e52bd1130f52026d75d78b1e727f0" . + "f41a586235404718a4974e3524e297d545b1c4d8cd9d3b5476e70d03f1b72ac9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a362c9a1c026dfc747409b69b087e9d38364651bbb08edffb5722fbd7357d5d8" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "6a5dce69543abffa72ad7b985398a8f659280337b0ed694e51bb419011303a87" . + "e9d78131b70650d5da83b8ce066884c8dbbce8daa3c9adb87a8d2c1f8f3c1bec" . + . + "8865553b7f550ec8fdda197bcce858ba0ad11c35abfe52aa5b6d888a16fe3ee6" . + "7597c69b63063e39449e20bab6b351ab49ce1cd5b96bbe56e51259d517315aeb" . + "5cf40774b4dd5aa34c8e1f8e908e53a9d279dbf7c1ea28367604393788aaa061" . + "e88020e3aab3ca808ffd44b3f592241b4adb280eb93e0959d74d56f2f15b4bb1" . + "e34d2c937fc494fdd8562ff0f96095058a639159f04de8e7a9d133445b64b94f" . + "0cbdd9645de7614a7dc6344413a01959f753345960b3a92c47e9af8a787f0d93" . + "f8448e2f2dfc4c633402004fb0d8dbbd1e87a6f6ad3e113fa0aff6cdc06696ef" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "fb0d1def712794cf6ff540f684dbe8c4837507521877c50160f8772a72e59b43" . + "17745a515426841697251425c9c69b3da00eaa930034e1ed7b1ed9ba7d8bee72" . + "bb914c6fc9ba2c8632c111e951f684961409b7e690e5a491e42a99374154dbaf" . + "140a627fa3e117805b314ac245762bc39f55ba2fe951fd3e85e04754cc638a9b" . + . + "ec8b122ee2c82f5c8c2f2ab89a9b99a80e4ee5df93e8e9d512e0743270285b4a" . + "bd911dfabfc994683bf6995d8ab87100ee9fec09b6dba92b23185d0a72625d46" . + "24963959aad5c002c68dd8ed3c79ad907b2e323f39bf14a63dbfb9727d106111" . + "01bcba8e1c29a22aaf7d04e31a959b2d59cf9fc90df31cb2c15e743430b45bfa" . + "52321eff570d19523e9b6d5f4ec5a860ac6cb5d18ce8ada169fea5f1484f73d6" . + "d22e093ca88b0e4dfd8e27119273c524766e8205da74af769696cf3467fc5f8a" . + "4901fe98eaf1490b068fb1c42891fedf14e192ff5eb273b3f8c5791b870b5457" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "56e0d5cd5a31b5b463ff91d60bf96b5f9acad1e93f7d1ad888ffcaafaaf119cf" . + "eae641f1c1419f058c6687ae4681687d7c62263c7f1b3163c1b24691741965c9" . + "ecfbc78c761727ea63c6979f670eea8059fd2afed1e3623c5db21633f15dc15e" . + "adb44e488d49d4bcdd25db75a33d12f639edc8d9be8c2d527100c7cae8792ca8" . + . + "17b3542e2022cea1ccd404606758da35935a916639d0061aa40d60325d863f2e" . + "ee756ee629bee2d730702873cdf695e68fc99847dc033db94543e0d3a1cbcf39" . + "6c03987a8b35e51edcf449b7d1b7408e998f7acd9041298192850b0865090c38" . + "8907674f11336477cdae8575d49d6b0e0cd46ad9d37afd1249c649b7ac8a099a" . + "0e00a94899cf36c0b16b650e87ecc0048dcf43086585ea381750b0528cb68947" . + "edbd77bc5c876cd8bb689f7209f85609d10ba814e5281bc50c2caa903351c3f7" . + "fb3a871afc9946fbdae343353724141c4183542921ff007bd688b4789cc86ac8" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e9be1ea712e3c8afc53485df43877f8a1040dc69c5abc8a92e6f5e01ada647af" . + "5afd713cf1a971478fcaf058431a93e819ab348cd28416f7b13ba02e513f6280" . + "5a41542c7875fc8765f6038cdf0e5b6d6e0ee29c24a2ecea98e07d6b107be662" . + "f2a6dc2adf99ea57212e43d09047f1098306cfb42250392de869c9765dcbf045" . + . + "df4ab187b41ec14d074db30bec5f1b93f5f525492572c540b8af7b706588bfdb" . + "ca0855552cc09dd876f7d5dee758728e63c414b129880985df663ea45f1891b7" . + "6593a0ff960a2aa0ffc64dea966f64a28dc4b8147e9cc120bc45744425f870ca" . + "524d2c5e682dde20bcac56d86f0473fba1e135ab7006f9c85a547c19f204bdf1" . + "432be0a047f4088555948149028850870be822cc8f822899f873a2ad5ff639b2" . + "c312f3aa9028377ce077b7af6f2a6af3b6341f0893488939e703841bf5785015" . + "81c9217d92284ea0a9712e4adf2672bcc10daf3c8e78044e51d824f4af58e717" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8e5abe1acdde068d30dea103c72d20ab9514145ec5d71590d22ab52dc11a270e" . + "73730b2bb0aead24790c4d64a461e44f584bb50cb1f818185860a15d5b32c6fd" . + "79936f386ee84ee89b9991a89faa2b1c87d43012aae10d68f88f3009303f2547" . + "56f344ae7a269ec80b3bff8ddd5389d926e3ff7f33f2d675f6ac42fd4361ca62" . + . + "546a90773e8472eb15425a26cda7e728b32a398c58954af2925b8eb5ded3467b" . + "3c8549b5846cdbfe08a8097f95f3193b1b26c771cc92262a643da77f515883b0" . + "e3d5b1d40ae5a3579a5561ce5f127e14c6598d303a06db516cfc64f29621bdbc" . + "16798b22bf7e638206abf81b48153125960be793e90e4c9023496c6ac5ac2851" . + . + "120d3ea0e9391acaae03d064a384ec48c829a8c8708a2f0a12666ba7cb3f500b" . + "c134b37359b42cbab2ba9eafd810990ec0a7f218d07041d1c03d50214cf7b134" . + "80a570e7161d3241caa1c5fb93e4bf8a5dddc015d79215b2adaa9fcceb5c1ad8" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "267cf4ad12820fd7a2cef4cd4316120fb17ca1b3ac9a53a96e8953c9af8b857c" . + "88d9fb07dfc511129ec59049a13d6c65da58c6d64b3f7e9232ab3e4e03d52254" . + "4e6d9f6da2fb45455868b3649ec5460cc4c8d6f0701270faaa262c70592f54ab" . + "92bb3f165b7f9a4afa38e2e9cc3c9ffdee7456c9fb046225c849aa890a2659d4" . + . + "4202c224e5ae0bc1dd825fef1e72aefd761a45d4bd752c2cc763a63675ed216d" . + "b9ffdf11e2d4e49d9dae7b575501a7be94fac1a092b10f21efad2777d38c06cb" . + "bb10ac23deedee64d71db2eb12c9d0abec7008392ad35ffff806ab948fffcdc2" . + "670a6e0254b9f35663e3b5796762bd4e664456724ea7548a97c350576e7b3e12" . + . + "4c421a571d40cb63fe67fcabf6a5d702a92a4475883fa1a77744524af76caec2" . + "fbe5075413172354980b1c5802fb63cd416e721e399f7c5e24c5c19fb6635d67" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26d66829be6ab4a41a07d2d22465fb10381405162d0801c25939ec4c7af7f603" . + "2a8c32c953202a402359e1c561bba97e3d776ab383a7fc93b0d5f2b2351dd6c8" . + "81b66277d0c84ad47ffbf50ec692247aea1182e9dca2c6298687418fba91101b" . + "42b8b68bb3b4a416b6f710e6973464ec3b56edeca77e75a38ba2449e2ffade28" . + . + "e6c1cd58de9ab33ed9ced31224387139fd6119decaa4193adab341b6d66bcb10" . + "8a54a6e3f0080d9fce0c12c7f9ada52d7b82ea287f4b04cdc3b82926c7b031d4" . + "6d7a24a6c634e35342c50266367fcd4d4c152df48d0d0f2613262c3eeb1b2e9f" . + "86b2d84338ebd5a589c512bebd329030659db84bd3ff0fa24dd810f21da88214" . + "751d3ae214a20d0fadce8050fd3137d286b445ec6795904885b464b1d0b4d338" . + "342a4b3af6605615dd84bc5bd2937e4c2e60b6c6a6163daba8396d272b2ea8c2" . + "1dfb275dc002587eadd76051646bc385760499a9c2a4f7e1cf1415975e80fe24" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "69c90a787d347d1924cb151a6ef9c8624b99238b8849a1e4d2a64094dee5344f" . + "14836f6ae5c98ea3bbf13a38a77e27ea0df5f359d8986d2f29c4e9ed12cadf98" . + "50b0c22eaa8493c71c9d50d3b04b78496917f9bac2a594b7cb1626df9f2ee7d0" . + "17136e2efb32a598e887e1b9a8a84476893d108a2ca7e119eae90bf9c334963b" . + . + "1344037bc65698ed8e3e9baef0970ebf05c2105f5e450875d4a88cbc8fb608e8" . + "81de4cb0f8e1345b86ebfa596d980d350750eb37a2067e429e3c054f9f998025" . + "563d75a35b5f6f2a6c4dedfb307f1e1ee3ed805835238adcee03b5cb97fe43b4" . + "29287da73218347a6915cdafce06cba61a82b131d4ade4174d34274183760a6c" . + "cddb70fbd7ed663f92c2ac510c118104016eb6d87fdfb24828d85a3a520b3ceb" . + "a72ea6c878a152756cdc9438832b766d40ffe9898bdee178cbb7a41f1b87c312" . + "17803ecbffcfee4c9243de762acfbb3684f2308ccdbd4a9291b37bdca74c51f7" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bfe23d4a94865d28d2c480243b2ba91e60d3bab643f0eb33b2c4a69e6b05fa1d" . + "e8fea482d774771ed604985f46b4926694f8d28d0e46febbdf329a3615cf5c98" . + "29b5ab1f3eef107f33c5c9a009fbe25e81c375d58796416da909f29903a65a16" . + "bd21613be8886b61cfdb437a86ff2ac8097024665e25026e7ee657f3feed151e" . + . + "d44d88dd32a254bf4b0bded0bc6673ea9304fb9b3e929ad3a9c7e7c050d93bf7" . + "786d5d2b735361f13fdf349caed7d235c2111b0f3370a8ab99d1bc97caeea9ea" . + "fb5c03d77e424d7d7bbe0e5015e06c072c87fd63c114e96c13f7850b83c1b7db" . + "5e61af98f8f14a58c5827f6b411e1718b1381fc3f482eb6ab5d4b7eabebee58c" . + . + "dd347659db6cc275c4b54bc76dd0ec2e04bebc798b451ff6f98c9d6bd6c187bd" . + "1b409b10dd687fdbb2d4b8edc8187aed48aec366531814524768ccdd224dcc82" . + "0463240ed2f8e8d822c321c19eb3d067bc056febe8e0c465c9dee5de7c220f61" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e270e0a551ed585254c9b082f8bea5b7883d6376be4d32183fb7a739341c9184" . + "470a5789e1ff7f9c01854eb237cbe5920f9335a9e3a5192573a2d851ec85501a" . + "1be4c11d6c99aadddaf243322c08abc8730ff067912aa7622b910b01cd457a0f" . + "e5d20d8facdd86184e37e3a6a1e0f6dee4d62ca72f01517d7640a5261ba4ae54" . + . + "dddef5f8dcccdc4c200880cc23d43d1a9da5abd6c1f73b906786306a2e9a7faf" . + "0a2b8957e82d2e320d2cd778cbab2cf84f1f0cbc19e87ed876d7a744d8568905" . + "57e476262d6a5e92c2cdd09b246cc1d013da4fc731efb1ba18f5a9db3832c8bd" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + . + "4bc78e4bf33ea9e42954c7b3897a569439aaa4a4ebaf4742c9514bb2a56afafe" . + "401effbff07c2b2756de58561acb00a59ada93dc27bc96453f182b963e4360f0" . + "38bdeceecd4fbf1eccc4de7af03c1589b52fd7c9a3f06e14b9d03b4d81e1e171" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "66826e25ce7f8c7658126eeeb2845702468a9811186e0ba4d294ebff19697c37" . + "eb0972cc62b52803032204ad64eae4a715fc0d4569070b2fce4715ce8a122aa6" . + "54ed71613b069558a59d02431cb25ec34ab3a52155b3069d4faa6f5bc419b5a1" . + "8e907718e716074db2d097cbfed9c2724e2f0007935d430ee404aae40ef2ff30" . + . + "2de24cfd412d7c13b48fbb3f16faa7f278c1f89feaef99265d47c9c95a43aad8" . + "f5e540143e2e421e09e39c087e44de2653efe875dc88408c77c4480105c66659" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "9c8ce5d5306dc36db02c9b4bf1f161e81bd8f523a8d6912dcf92876be6f34d9a" . + "aaac9df28212723f60ee0e0fc09fe7b61ac37657513a2b474138313d907aa646" . + "c9934f406b9e644deaff755ce9518329c08d3d18a3c8a0d89a9d012529957087" . + "48a9c1db0161e3e3cf9098411218eca127428ef1cfd4db089e7785519e7f8224" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0767529385d3859b4780180bd54c7abf7a685bacd577e02b2d0018a56fcfcc6" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "4ddc6918ef8cdf86175aeeb2c7c7edb25f105a5959c038a6eba1556ca2466685" . + "569c386c88098d7ecf6fd66709b6a9f8bd59182773a47c9ff525f5dc833aecd2" . + . + "ef09205e51e0522a7e68998fbcad9035bb0e08963ccb9f9bc88963dd90295551" . + "504c7551fddd59a32268d9c2aa12eb0b265674b02ed73a7b0a2389cac2405019" . + "e221af795e3d619313cc0c6c8343d3ef38fac0f5bc66fd62a0bdafe0356462e2" . + "b66567f4331ced47fe8c7927d4783e03778a2278232fd51312fac88b6e64ad5e" . + . + "a5a19b25851df06aec4b3ede6c108589b8a2a0371e26fe4f8d6e8f86c60dbb04" . + "b9e4be2982bda799e9c32efb30b642ebcac78dd227bdfcf21e285cd605b49420" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c51889beeafdff11f0d2b80716a8550c9bee8f3d43300674efe3589f9814000b" . + "e34bf98e97ae1f5fd3be2c39635a583ec96fbeb2c95bfdd16d126e4683e4418c" . + "e1c3e033875607a4586aa2647bc8e32cfba56ca032cb5dfeefe9d053c020d5fa" . + "afd4cc6ebf9366f76ec7c8cc3a6ffa7b7dab66dbe28d21b60fe9594c46c85f50" . + . + "02c2fe05c38ba711ec2a4374ce4572ad8477cc4478d572c6f894d5b86eb2ce4b" . + "8e8c5f5b933b5ef42575e6114ac39cfffd4efb07be305fe4723cd6afb9ba5628" . + "7ca3551ec7566658644f2bb04387edfb5c42a8d789dae3f3a3b15728d1c5b119" . + "5b767bdc607efea62b9b11d9442d5e0437817df1983a6814c6be6e2c3f5a634d" . + . + "fc9a4e21a0ddd09078f439a8ddbbc31ed00fb43120d575c6bb2aee9a361bb56f" . + "cb2c5970bb7366692820070b61f588dfa7473f27f22c049e9ae63f61c719107d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "34b1861dfb0ca412e98f4485c81007349e19f1211c44d7c0f10dd8e47b37c364" . + "7153e679c29755a9f5cfc1111811763a0b19ba14f3f740558a78c2ea05fc4c7e" . + "cb07b2ba06b413e88b08dd20f71f1b241e4f2efa51ca69e94037119cd78bb473" . + "3f2154668db7cf65d61e9d418b55d8e58fc6a65c8abb7536f0ef36f77355d2f9" . + . + "081293e501e422e4813ea4d8899aa9de9dd84e40122b97f9722bca8c2aed2988" . + "f62e5fce8695f8f534d6bdad2cdac14b00b0f0c62c4a3c8d50893944b97cafa6" . + "0f29780e1c557953271b9f53239134e1009845f452d2179c32ee9b2addcd70bc" . + "72ca580519d446c2fac7f21cfd34ef1d83bb4d6ed0a98ff4d22455a5946e9672" . + "8e310c146f66c61ba2259f83a725af9a31be4cdaee3076eb77a14b4ce870a0b2" . + "e3235a470ca9cb39df059109d0c3716960ac1b947804bc44169a2a1229eefcb8" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8b74e490d1eb29e16ac3b219ebb6d9db91eb3028f71c44d812f0b0954b8b4e23" . + "3ec669316592a6296144c893ccadfbf56e4e9bc307f1681728481acbfd2ceb5a" . + "f95adad26dbd20502a39e20597f915b9a68bd0921a5986de60811b14461dcd16" . + "cd44336aad2595e923d3aef4ca2d64a64243146365b9881ba55480a6b5463644" . + . + "94698ff9acd3503736c9b025c3b90bd3a790a1114ae0672c529e1213d4891866" . + "11c94e758739a30ba680fe37ab738874c91524064cf861f7adba954ee421a959" . + "2570e206b296622825199d9da6455eabc5dc94601523b3be507a09c18e0046f6" . + "0acbf2d73483a740cc3db137820fa72b01936b5f00deb9016e316e54fb933b67" . + "83d243dfabf85ba003018bb3dd462ecabc9d7ee066d90bdf980a7d046cb7a454" . + "0be02ecfa615869d12253b6830b68d8ee4f8dcfc2276e159f1762d53e04ac050" . + "2987d60f5affff382fac9dd72ba3d4933f5889654577f9351434d0d11d33cafc" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a952ac24d75e2978d7b6305e6f9ad32cb7d2a2357cbaa409bc9cb83ec870a954" . + "1785031823e419352a6e5e2d0791c7b884ea9de133e219dc712a0597168c2f48" . + "f89623afeba84312a8ea74b66b425b6163a2dc52c8672071e888c57ea8d72b08" . + "523a0e8c954243b3eec4dc82ab683ce7dfb320051920d1d9225046275a1ef24d" . + . + "55ca63f79c7e626c9be78608ed994d605f8808eb85eda16433784c8dea70e551" . + "4dab9035d7c570126c6eb45eb5c35f23aa562649717cfdfb0204a91a6bf93d28" . + "20fe5012bb3730d4fcece058bf9723efbc6c6146bbf4caaadb3273bd1b130109" . + "d2fa325cf37ee91578b7ae8fa567b80f94332767b24cc2aad5b82c45d099cd2a" . + "56b1b62e6fdd1045996eddefdaed8e6976c6d785bbdc3f3edbc1797c73b0217a" . + "7536049d9ec7ec99db2aed5309d52deaa24ce513f79b2d6a2cde3e9062b0f02e" . + "6bdefe9cf42f1efa0821aaddc06acb84037a14918a51c17224430a9483471897" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5ea5ed5dd80b4f2a08588ee51731d106bb57ea3aceb4705ace7f8b3aa61ff1b8" . + "8e5ac6ab96d18d386cd508e63e0de59feb5c77f40c78b0946de0be5432d5fb55" . + "dc136b68b084f09906b2f5fa236c1f55165aaea779aa32f28c097d1acaddfbb2" . + "fa5d4cb5efa83a7b397a122eee1f17c0ebd7845a791a21faebf08929073423bb" . + . + "49e25351c4aed6df312eff81fa865249cd9b967c1df9f399e4889077e9181be0" . + "23aad517b177a2c9ed01a4d28fb7f70347c977e13ab2f8d7e0da6c4f852675c7" . + "f9dc33a7676a7f3dc3e20e8746b727a9d85b46c8aa798e7af9736794f3f1b7f9" . + "ca617a499b0aa322c41d8bfaf66b4d928152d34828d51f7b98bd8fc98715e3a1" . + . + "07bac2563f9253616876ab6c54a4ac20e0c3f5fdcb6fbe5d2c4064e0ad794da1" . + "54b09c372ed1bad0c15c8e46079ead7b4bdabfcd48bddf32db441b989f934281" . + "1aed0a555088fc572a2ba268dcdd1332fa66296179f965bbdfae449763fc42f7" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ea4e93236cabd7a70b545b7ea3f46d9506f7d528e74ea95bbf9a789f47d79a68" . + "320feb45f7c7256e8d9c81c0aee2ffd4cd01f231239b257f5849aca617490a74" . + "89d9eaa6db6df42e952ed31461bfa9d9fdc561c64f11c26ace77f0377bc36b67" . + "da0e876d8d820a50c7c8b367d8f364dc77712779560bbb8317c2b1ba568fe341" . + . + "b90610deb22c4ad052bb57bc9907345511475b32fe25967c5ec2d878875f6830" . + "82d38df02f109ffa80e21122847d512dc4850b847813d45ab5715b1d62d55727" . + "33e139c31f2a1a1b5a20ee2c560dd9e3b27c3c0fdfa2d12155fed5a3786cff4a" . + "dbe70f59a012fe295fb736ce59bc2c092063c005b3f4303ec1191528f61854f5" . + . + "0bb46d22b424c46a03ef0dc3ae84dd41dbe71cff7efbbeecf525d331374c102a" . + "dc8eba3d13ade8ef452934fcab2db8c559b796604b613c394fc0243d74d7ac5f" . + "18119c60050fa742497eaea189b242e7ab44165a9418e670710010cea20e10ba" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8c3d12db937ca931635ec74f01dd1ba1055ac0d0fb29f02708058e5ce7fd102e" . + "cf490ed93f12b09aaa46f5bb871092325b45776a02bb5f9ee74009b0d05ae99f" . + "ef0626c3cdd53c23680dc82ff506688c6a59f859ed36d1090470617e994fc4c7" . + "3a3e8849707a34b5d7d861642689b7f84da9b489ddb02d486ae7f31ba4f6c1c5" . + . + "d76f1f39bd96a1fb5e33b0a23653ca7847d2bf130d55a7b1727e76a5c9ca42d2" . + "b81d10434c6d83b8b54e2003be048208b44c974d1ecee009a7ff0ca69f3dd212" . + "b0d86e92dae4406c599754b16c8a0fa6877d50aef19c500a5d3b6039782a6358" . + "fe8697d785dd0f3cb69c3330b34648debe48b405f2e4ea43bb58f7070c9dff59" . + "433a5631d65e317995557c1a9de69294083d9ea9c4655d547228fb5cd374f396" . + "cc3a80685890800bba856ff500c180a51ac2d68873afb1a6629b816f20f85f94" . + "08fd16b6c499c837b7cb6198ac9d1cf994bc580470f51062d67ada492aff3f73" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "429eec0ab81d05dbec6f30710a4d92dd48520253ca8e53f86e2c3f3dcddceb31" . + "281ba9f50de5275c695bcf14eb38d1bcc652d8beb1cde17960a420b32784711b" . + "11d7dcd6a99d5e52e3940a5f366ea9cc6a97ecd2752da7ea4c1360b5618d121d" . + "6b7f12d7ab147c4bd398eb30a47db80c853eed142ffd5aafece76ccc76e3086c" . + . + "e9abb2ae8b8537f8a05e8abedd4ad4bc4d457c04365e1c926f4b0fbdb6187b8e" . + "e9c4cf346ccce487dde0c207fb0682c405e52a5c2db256d6f92e9ec583c171ce" . + "5ea917b83529fd639d66ba53f1bb8da028bab43921880e75cc9b618507a77b4c" . + "959ae0f06de8ebb16e97280564a26a3b833b90d273f7e5c9dfe63cd476582ed9" . + "27c4647f1c9f99c993007acee2456e56c93b2c2b1ac6ff8cfc837f2de61b18c7" . + "3e6968f30239206d5347ad6b93897eee698396b77a3183db07d1169a45bcc8ed" . + "c9bcb48ebf4f026e566a0136fa7c9b7d981a4f566cdaa8e07aa374db1dd3a6c5" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6e1d3b57bde2990d593fba68d256b92aa4f60f2d888c4bf581e1da7a2d2e570d" . + "c1d8d7031c4184e8dec23bc81babe9a1ac6faeb20e9a6221523852c4661acf0b" . + "2af6014a4420bed6888223d4e7ddd3c2c057c9faeb447786de87d9626023c149" . + "845fcf1b49cef20389f4142d7e324ed83f186149dedad9e81a695de5ec620c8b" . + . + "06b28b7e0d4c46dba7ce54dde19f69e45246ca9a56d5c7887f912aaf0d7978cf" . + "49c55cd09e97ca281d39ded7f32026e3441c753544dddd65fdfc8b6779c54681" . + "0bf935c5ae1706341c1d7cc462914b309de3dd341a10253c6dfa4de814ae2516" . + "dda11e667fcbd94f0ed9741574a80c7ba95dfc65855cc86c385fe651e929c718" . + "79b5d9c43382a0ae4c16ea6af967ab39e18536c5afda15ee3341e00d9b645f28" . + "778271c5e82d6cdaddd07f0afc48f035b933bed186cd4de65bdebfceb3fb7da7" . + "20c87f53723b619a2a0ca29f518795b09e4cd9d57a0d6bb5acb4bdc644b62780" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "dbfd61fe661870b4dc319e167708785c1601777463872050439c047fab8a4d83" . + "cabd3216d8a6997ed20e29a5a05fbe933ed4ee2f16ea5b0cb8b65f99d887eb9c" . + "1821369b02a94b88fec728a66c6df169d3448da9fe89a91922a120b6f3b43732" . + "1b99c2fb853f72fa86d2cb3dd8d95e0a2dca5e77d87250e2cd304ea19b0660c9" . + . + "af73db8c92172590aed5166e9fdd659289d332e527e94763243713656c8fe7fd" . + "1719001710adc58aa0f0363392b58e3d9ab38cc4b16a7556d526f3e17c716ecf" . + "5a55fef917e57cf109ebe5a966bd97dbfd1f50b28c47c3b5e0c46b95efa48cc3" . + "005995449c83fd5ad0daeed00836cdc32972df0b21a51208cf5881722a36a166" . + . + "7acac0bbdd0af88168083871aa1334b6cbf0be45eb23c1494377b976bcbe63ab" . + "c5ef07f70a259119a4a639933356d301206cdb0f4034bb4a7cf918d4192e1f7e" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "773393292bfbc7966413123469e385cbf357de31bcf1825afce87b22212423fe" . + "ac54b0a43b0a4ee62e3548ecf7d0022f56bc5b7865b24b7d0953cb69e03b8c67" . + "acb1165cf4657bb80af26861ea04bc528f18b20a91d74f514792e0996c427e61" . + "6c2d12e38b998d074e556cdeeb3b4b17977d8a401fe4689cf529a499c7f7cb79" . + . + "370945a269961d83c731ee868d3edc4c65f61960fdf7be196dc756dafec77c48" . + "a316becbdadd91a800ef261f1125cfe6dc1f406daf0b8701cb668eeddab4ee2a" . + "f6f550c1f196ed8ebf8ad744365bfa245179e65a3cac7aaa3d014e176f3edb57" . + "0642e29eeb6a797495fb20746b516a7caad96093980edce76a298a26b57695e9" . + "f761147f6fa42c8fdb500f8729ad3c3381b1d189326c7f895b26bbf37aace073" . + "32a3d7d4da343ccb3cfac0cfa15e5106eeeb5dab1aa5af56219f7157df85fc38" . + "80a8aaa9308052e3beb0473becc1603b9aa7afb7871a6785480cb9d5951344d0" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "436130d4cd5c3ba017ad2660910bb74b6eab5a77aca793e9b162d38ba9001d3a" . + "5405bb419b1b7b154ec742af8acf48a40c7ddb4aef17141c114e8f6643efc41c" . + "b0e8d8a41bfb7a6a81a139aee66ea7cc0c855de2ad1c6d0da65c430aa73b7ebc" . + "36af71936fe39e93d383372d3af629022d36d6e3b6f5bdab71a56d89b5312ec4" . + . + "f29277ae24e18f708f675249a5f291d9421853b4ed47343cfda880c89b7b82b9" . + "40127899f18246490e67046cae628fe4d48bb37f6ccc4f3796a6f8bba0463a20" . + "559134c86aca986535242ef39e235c6be2b2117ecc1a37b35611ad168b99e6f2" . + "85946c60a7916623d85fed18816242a29f204a177d254c5afcd825b95074b01d" . + "270efffe218241151f49c384222314065bf41af2e9c9ee9de49855cceee2ffe3" . + "add0bb3f69b94f660fdb09d11636a083b40946099350dc52eff6ffeba81cba7e" . + "43202b687d07721b3a7cd4c1fb2e63d0e44f44ff4caee881b4c67d22306173a1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "cbf4c0ae64f54292420569ae760e5655a68dd5c78d16b839c0d753aa2b8d0e38" . + "a2fc4fbb9b8f8d659236982c857612d071275e55cef88cb9957a9cfed089c2a6" . + "b8dfb4c9f27c22b983aaaa30d8a1ba794296d4970bcc09bfbcb04a809172dddb" . + "05689d9f3e598d1df854983184772f7d2ad2dfba1e56546ceeb04366b1265533" . + . + "61e6245531a217310e7164185de9be6267280da66d373e5573c703675e24b195" . + "8dc14b7c9b9b7362ae209e7f46bab29041c6bcb0b7ca911ec1bc7c440db18f76" . + "7564a7d3779adfa053a822890da710f8258d4d5085ee2d0995ab7469590ca5bd" . + "17a411cbdbd3a325bcf1bbef872377b2ffb3db7c3da40b67412a5f31b86b33f0" . + "6c4fe0ce15431b82580b4c19449d4e2501e4286defb45c75893a3c4a41119c5f" . + "5a5b139fd6c200d1ecabb403b1a32a7f6458493483baa972d6d462b3d0218750" . + "23ab04c4cd33a3ebbf3955faee42d5193f86570aa217295df8266ddc4555038b" . + "2df41ec5461d5231a4b0ca7dc6de5d8dde2a0231d65fa16cca15b5cb19288829" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "bdb321aa757e9e6483f23153a98b4bce2e07a20a17455a40bf18b5f31c827ace" . + "b5b650035c443144f0c87ae76d2704de2e82db5ebafa1b158735862f87067a5f" . + "fb10f2929a961d9fe1f57734c9021c334a60a55221ffef03c1502fb93b03afba" . + "6e6b8acf955e43cfeb9b39dce374cbd43f6f720c6dad0a6968f85cc0e20029bd" . + . + "43beaba6ef9a179f70aac37c88b6f41c2381df857ff064912c6c15822c4aa716" . + "37fb6bd81ced049ea6dc18508bb9e44692c3424546f5f38f1f713127ffc1fc90" . + "b740d8b0e64f05260594fd33d2ee29a723fc0a6919af27c703a4099cf7c713eb" . + "4b8af33ffaef6fd60642ad32e0b38edb8384283f60d27a5f4f9c33d1adf8f154" . + "0fcf643c9b32be6f84a3a738f348422e477c12a7895bb28cabf343c1243558be" . + "8060c0016d0c3e54b9b555188247897fa8e7c8750319af5851b8af9a1752faa8" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "323be6f7fd3a54dc5db52e29e84911658c1f3d5234c37e8ddbdbc612fd8a41f0" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "738d3a227c9e8b5803d1fb6c835b9bbe8fa458c40e0784b750f304a78c439e4f" . + "e1af11b929b3196a3fce7247430953e14f8ba178fdff31d867f9ecece9d779d8" . + . + "ba0817788f5b130ad9b6345a879256f3282bcb7232a352fcaea43306e1f1b405" . + "1e5a12adb092837d817473330eea222514ed4865398f26645898b9b4c0b8988d" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "55c992783525d222eb453d8bdc62b0c74e3b802f1ba3b646ea7fcdc273a167ae" . + "2b1c812cfebba960491dff26cc0178cf4e6ff7e482f42015ec273413d54677e9" . + "e23b2021103c0d0029bf30982dce6f8bf9148f5c1305734d0c3aabb38b69627c" . + "62800894257999a71af1633a9fec6c4e7ae5dd4410e81c19f432317cabc03e5e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6b2ed1981280b2528fad56d4d236dc8140dd8ecfbf71023411964d41a56ab9d4" . + "bb1e6a7e2aed004a12a264bff6a8bf852a5922136e4b11d90bad4cd7da812ab9" . + "8dac65d930ee5ee9cf1a518866632c3d257b3a2697ce865ab644aadff0a26ab6" . + "2b8d375b70249b63a73ba6583873325e25ce4e98776e5f37e9f8a123bc2c324b" . + . + "c663051c550f4a06a84c57cab2f928544693dadbbc3629717e01bd8d0183cfcf" . + "a7751983c6ea006e960e73c345a792a10585fc09b4355efafff7591ba5c01352" . + "ebc726403a7ebaa044a9be5cc4396be0c78551e95b4825ac6cd2bf0992561ad2" . + "b2397986f0f608f9db7a3af3f4dceadd21c48e7fe1f870fe3151dd1cf22c01f6" . + . + "e97985f2601aa9a4eb9dd8c54b8b1bf1001b7f881f4d2bc9a9a69f8ddd061428" . + "74994b1accf633d906f1082e6ff9ad553d2960f9fda1031e4500a0d100ab8d96" . + "89a0040fd0629085262502935cfb75d5234e1c3b2ebdd8e53f94f2e89928452b" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "768062cdf2a48cefc803b632af5f2cf3bb9ec9ed2752b46ea5a2aff02f7914c4" . + "89d8004498a09f055ec1b90a9a7f4fdb11eb4d70483fca8b4fc20ecebeedb16d" . + "4cefd3800b61742336c7c52dc3f0e8a0eaf87510cc2b3826d8e5df39042b1fcd" . + "6bfc9950161ca6ec0b24963cbcf4a22c9dd0ec8702c66829e0e84635b9887d56" . + . + "29ee1a3f1a7197b4c6743f549ae1f2484df814bd938f256507e4327338e3dd2e" . + "c1556f24f77254726dea79230da5b0037299b54d13819d88e1daf908ae89dca5" . + "cb9676d927dda7e9ffe88601b945b9d9723c034f549cf722a246f185ab7e8753" . + "0d54bc3818d44994b97d7fc8040d3036f48ff6b036712dd200afd4d474a2cea4" . + . + "61bacfc21ba3ea4ff062d61bae03757d9d334e1f69366446c22075bfa999e348" . + "fe85fdda0f5cd8666135719ede8e99d5044d86063bdd6c3b9cd9b9a8bf322479" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f5ea45a7287fe9c08d747742dd453d9c6920b416bc63401d9e17733e8dfeb89d" . + "b64ad35b3aec01c98616c0fa657630f8f5ee30cae08d55fc8d70f2ca14b045a2" . + . + "bbd22fc311067880e70ce6331fcb9fc8985d2e5550de31faae923f673fc9de57" . + "077433ac10eeaefad38384c2303bf7fd4e6dda062bc66d4b251be6848ed89c8b" . + "c2b90fcf738d16095aef8061017fbba0bd928affc8fab1b6c26fa179f8df2e09" . + "f1100932b74d63e1dd6140ddb05e7c66316341ce1cbcba0ce02e38ab4d10d795" . + . + . + . + "317960506b979e6fe36e3b588e41ccd0912ca22f39cdb7d35d371d5b57e45704" . + "49b79d974825ecec9cb0ba8a99641a683a63254c44fda68666998433d4b7442c" . + "d01814ab7cbdd9f212885bffb3a74f3b82c724dec3fa6af82cf7449d12c36d95" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "aeacea9f15016161cdd0de2db2c4e4a59b697fa85e21b53277270af6d5601ef5" . + "b3756a2be578f244d6004a10a41c9e87a209e367ecacba7a9e49f9e0bf4b5f68" . + "f1b150846cfc2f3d1f23dcf2cf73c5e73ea9d070341ec9e26178418fa49b3988" . + "9f67755125f106353db7ccd1abc5097b996852c0c222d5524f87efcb03b37619" . + . + "Problematic Triple" . + "d55ca36d90d01466691f9b9d11332e21b18a4dfae5a12f3950805958769624c1" . + "d5ee1d44d6d5fbdead8de3b65f8b284b1e5607a14291426b5dcfe68b1cd6b766" . + "c821dc4f278ff7de133ced545633fd9da4f261fa57268a49b6fe5ac828ecd69b" . + . + . + "c16d033f75d7e9638815e5d705d9396beb82d1141a232594cc6d641c2d1b5c23" . + "b7eed6a15be056bf4ae79ca24246d73bfe28804704beb3accc5661f277600857" . + "9b79e46692788fed66bb45a47d07014dacc260a1ab4e40eb654ec9c23ae17d3c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "53e3d5a80c0920fe30cdcb30e117582dbea496079073ea5310564b9d604a7fbc" . + "259ce079d0ceac95c4994e1cb858c4859f60fb08ef27f2b699120642643774f8" . + "d5db3a376ffde64d8e857a4a5b23215dd3947b3108028bf2b6f54c9214fa61d6" . + "472d8d366be509f8d43527fdbb8a3c9b1dea14b084704f241733ada87d5a9271" . + . + "15978d8bdc408a5a241b58291b67b13e66745f19a1213c8cad6a8d15fc666451" . + "67493eef14f022eb26c8a335ca3b93b23588839c1e6d617c01f45e21b73434e6" . + "3c6efd43c764c68080d83be47a6a654776f5b809cfdfc574f4ebf137f59977be" . + "b8ce3c2ed9adaf4e57421bf8b32f85a41e6ec0716c1befee98cff395c2a54128" . + . + "723ddc20a42139c3d111553287b305a0d7156a65c404d8d40688487ba834a3e8" . + "2d7fb9066e2c12f0301c49ce1cf1742a7f8531da61a2050e10e0ad544dced31f" . + "8ed2a5d69609baf2a62bacfdf07b7cc0e36d292f31ba59df00b462eb3223da70" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a99843250fa5ebf5831c36d1849740ff9363a543121144cb81c798fe4179cbef" . + "6d3fb7a725b89de5d889801a69198875d2437217bfe851883af42ea3423f5efc" . + "18454e23f5611151e9ddef98f3def10253c49b37de1d5ce277f7648512a1ecfb" . + "2dfb12f770bdf03e69d02e2ee2fefe550a3dc66a0af904f86bfaa02cc9c74fc2" . + . + "2508e0a599d7794e9c0e16b6081275571744ecf8080b1c8b15b9ec3fa74dd107" . + "a2d5b4212cd52c273c0b44ca90b486d189a6cbca9c1165412e2dcd7b5ec31aaf" . + "fdf2a7ba84030f74258631dccc859548af074636b8fccd0159b6e3d37e8f6cb6" . + "ce59e5ce644ba82077ec26d854efb99d5802f9998a07cdfc1afaa9dc260fd2b0" . + . + "faf5e9c2594abdccd44895b41e828f94916a0c4d12898fff750a75e2946bc577" . + "0b2427acbda7a99cc912016b598075081354c552a0b5fb3f8d8581805168e347" . + "dd431ec08c0a889f7182ca4d68f75942b1788f81ea8b4877385b40c383f9c769" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "1401e3c63b6e174129d63dc8f2f73992fec5314df664b151a4e23e1aa7c825f6" . + "b56359fddbb80df53b6ff64f973e3875c73b91e1c1919d9b86796f2347e2f55a" . + "8400e5a1a9a561f67110789e6ff661abcd60d56f89b707c263f75698b082d682" . + "e85a19093552d008a6ccbc0079987cd13f4f831894681e443821581b25e3de81" . + . + "8f667a4382573c32b94747044b0c78c114c5768ea68f341341284b5de871ed91" . + "ef6e47ec70293209297f4a7a3918a292acb6411b9bb49d0b3c1aec3b8043a984" . + "c558d3749aa580fc0648fee03c7f5a54d0c80cb56a0ef8e7260c33cfd77a543b" . + "d1ddf0fc7e352958e7e8cc2b28d436fd4de7e8981107078e9e87f05990962554" . + "fc854eadf8222acb22df04aee8155b15e01b339da4b027aabc27cc6f32dabed8" . + "80765037792322747383689a1e6f82695ee7b7e5426124f6e2b46226c2ffc1fb" . + "6cfecd1ffd3d591b20d170565701a2cf0c46ddc550cb73e11d4175814b2521b8" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "da69512f8c03b0a360e184777a5687878622a0fc84f114aa9520d94ca037e324" . + "906039fd9f1957ca0ca4c72e1a7464901821fcf60b4aaae7f280c8e953c93b3d" . + "1213c49fd579011292bc1a8975f64219892b61b36a723425b0c62e1ea1c685d6" . + "28dfac82bd65ec486db0e8de0b5d5164112566d35e526447c2861b803e3dbff2" . + . + "36865cea2b7ace1b480ae4367238e8992ee7f89e4cc9ccfeadd2f8d308a1df34" . + "2ad53bd7f5c3afd363d608ef9292d8160e2c50b52051ba2df9794ca8f9b2d38c" . + "8ab86d592f852aefaddf7390368f5565089fc5f7a0a24a953bfafc91c67f4b1c" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "36865cea2b7ace1b480ae4367238e8992ee7f89e4cc9ccfeadd2f8d308a1df34" . + "86ffe875b88a6ab85f7d402ea30b9add5898a28408257c5b0e6c2c0aae946e18" . + "0f0bbb82ac97ec8562d59935672b6c551f6146d12489d7cd3f210967b18dd986" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "71da32d485abbcd56d5cb3e709b976370b23308abc0155d1a5699907cc0f0b94" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "0f8c67b552f395be6b162f4f42a8718eb3d7a6c2f754ec910f15c587f2b08359" . + "f65077aa7723b7934bef3b69ca82128f7e7b730fb536d17d1e9c3ad46c0af223" . + . + "5382fb2098317697caab3b0a51b1fa46fa5775697e4264154b0b3a0fdbbea1b0" . + "27d13573f53fbb2755a575175581e5c1d792209e17a00d5cb6155f7ed533012d" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "067228384bbe28af84f3ca5b8e8bd8241af5d4178ea00f46f5d06a9f0682af5d" . + . + "723ef2d3ab8ad8b87654d38069aea007c486336f352fc331be26d0e98185632f" . + "51270bf98d480b7f12fe882310fd7877fa2cc08529947189cdfc8c5b7fd980fb" . + "725f5e1935868bbe0e279480132538dbc6bb227d7efc4e96d749b46c18d2bda2" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8cd9d270cb92d6f66d33f1ffd626b515fe57fc7d75e3bdc29a7bc336a9a01628" . + "8da4f868ee179fd1ab2121639da7489344c6522bb2454a56f453dec746642895" . + "63c23b8e013729db51f58de09a41925d266e47b6be2da4d9ec6db79c8c01360e" . + "d8a5d1d4640c59e93480d25aef7faea60c769ddd2f836eff90d1826cab3d2ec2" . + . + "e4cf0531b297edc8566626d92332f3ef07f6acd6f6ccc4e7a57ea4459a4605f4" . + "e117c0444487d8046444f8a45161c1a0f97511f50c3f26b02f10e20152b16fd1" . + "2d985c9cee3afc126ff8fe1f1f73b643411c21411891f72d0701185a80cc67f2" . + "50886eed063be0c10552607f9cf8de338036cb27a4eaee93f2c561285473b447" . + "07e65362c8ee012fd1411eebe48382db2f4fdaae9633642bb4359b1819443bf4" . + "e7812526e0935322fbb8c4f2b8bc9306536133b488192fc10a4a7878c62916d3" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8d763cfef00782182cf5f373ba128b0d5e47965080a52c21eb1e1e908a7f77ee" . + "1db3a28a433590059bd6e95fdf9b8acd48257c67d795a00bf050330206c917d9" . + "184604af6720e0c6c21aebf5cac4964849bef7cd6e159a581c0c36a6f28bb0cc" . + "681702c951098889aca8797e5a65de198f55b91fd553c669806bb1d977c7230d" . + . + "4251e9ef3a243587e835101b64435cead70a5a9f7ecdf97534921c1d90f471b8" . + "fc0303862b7af8dc5848b088f55ff4b69611db4765247fdadbc786f6f2cf56ce" . + "786ffd7081ceae45ad732928c8f25c8136f1a0716ea608adbb0e0099ad57ed22" . + "bc90cd3a568d440fd0706f77b1399ebd848016dd5852fdcf41203eaa587de582" . + "6bd2b88a4a3e752dd1efd4f784fd31c30029c5a3c01870e7d9c2f4f201c9b224" . + "868c3f1edc1c3fee247322c46f44412c9a5d120fbfe42934926783f4e3494510" . + "8440f3ef5730102f6ed077b4f195011a0786118ec78ac02b46ab0d5c03d93bcf" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "be88a678ef359169c483e19079d7b55ced98d0cb627198a5229402e2a0e05edc" . + "5860d023dab81e67245ee4da76f06870555c7b7268c9baeb997b1a2fd7a25777" . + "b287a510cce592784c83ee776fc44740938ffcb49560b4ce82f8bf7196047fd7" . + "c366e710ae4f7a5bc7c18330553014f28281cd8b6ba18070d6c73f91f2682519" . + . + "d535c59932454d13f5faed9a2a90b753700dc8aeddde1a19f35966473f65cd38" . + "0fd8944a99bcc4fc4c61852b7a4ca9134139bd038a36466c528cd5ef710da7db" . + "1f20e81fddb6de16f37902eb48ec06c418507b81978775c40fbb63ff98367261" . + "58b346753519e89af7250b3562edb0dab732783b5903e4747ba430988735c520" . + "05c149fb2b2a14437ecdd6397dd6017d5f62ffcf86d3f5d4148539209aa2967c" . + "40f7bb37680e0482b9e635556f5ac9ce137126e61cd5affe6d3f5ecbdf4aaadf" . + "65a090de28d310117fab3aea91edbe7ae0ff5d75cda87a0c3c14e777993fe150" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2e7b5c63ea73850cc1bfe54fc385486d04f18768efce4abe0b9a7bf1231eaad4" . + "8c4c96865d034eb7359640b2d3f920bab4805f7528d2ea4cd5978d301b030eae" . + "38b7a3353036b277dd631dae0bdcba9a275f8d05b38394e8d6bd7d5a3387c62b" . + "5f680484f119714ce432eef6546e8fc381955c97606c687c471675c524eb0a27" . + . + "94efb82205834ccfc68a7d55e6b842cc4315041d53ab7a77396fb9891506dab1" . + "a444e02e6d5a4ccedac3c57ba4fb8df4e0f22ad7e85613c038f00872c4ef6b91" . + "5e2aeadb587dc88db24a593c90de8f30590e972f42f0d52f86f4d5b120038cc4" . + "9cdc0c0ac68a154f1fabb593bd636c50447606b005696815ba856c0d57316f69" . + "fc854eadf8222acb22df04aee8155b15e01b339da4b027aabc27cc6f32dabed8" . + "642e025df97e623ff3526cd60e48804b161ef0b7301346306bd24a6f5096a55d" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ad314a1997964b7756de049ec03a0a74eec03bef224533ab4fb87196a41b0a61" . + "360922447e0d02cae72a2a9add6d0f93f402b72a3b317dc7755ff79df5710833" . + "7e8aa2ae6340b3ac147e6bf96cc391db0ab6c42570c339d00846358bae9555b6" . + "7c254c94d0adc4875934610c3aa731a0f31f1d7c903815d86cd464ce9ed03da0" . + . + "46d7bbee71ccd50143dcafa74bfa3c2f89c5335bbb3046ad41203859cfcab2ea" . + "11feaf4662cb10854e9a8093a8f6491f9c12baa0137133eb83b2044120886240" . + "d019a46eb058da858d8fd85ce6c5f3d0162ff8fc5b4f4cd0622593dd40f1842d" . + "3108ea50e351957bf4fb5eb0a66011a824403be783bc16002cfe151ebd011b77" . + "c0f63e5a1bb79e11db951272b198366b0174cc9123aa9fbeb26b84182877ee57" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "32a040979470a428811af064a16eb71b8ec4fb484b2606366865ec3968f141e9" . + "7fe9da340d433d1a96def5fd141b35b381685dd80f46f5d55afc85b4da6cfd87" . + "74be65b244c5e007c222c827d686b1b6600e450a6392e020863b89e9368f5b1b" . + "9419cad2ce613f16c14bc750f0d5ee5705aed4b3c5c65f95d9ff2c73dd7f008c" . + . + "7055245b333d7c5e31717a54743c458e0ecb143e70417f720a587bc9224e1640" . + "9d5a63d45ac1052c7b08b52ae1be37012fe659208c58611c58f5c0e42dd778f9" . + "138173d8289e855bff066829ea9862c3f5f28d45dbed0b4f2b0cae6c1c8494cd" . + "79d88833058183da924c88a3ec614cf739d2caa08db09e6e482e62bdfd3efb26" . + . + "b42a36eb6ba0f5fb0a50fde6d42adf372f1653652321c1dc7b190b5714241bf3" . + "d4b4509e9db4e98faed7b0ce6a6d4c757e4da14631d0169887eef7023d83d10c" . + "ba33ac4693825d54ae30728fa12a239d4b8487967e15807f8d3a4815a56f1a71" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "364372edae70febbb5c00ed6d50d480d522d9826d36244dd7a9366f77a6988ba" . + "ce59e5ce644ba82077ec26d854efb99d5802f9998a07cdfc1afaa9dc260fd2b0" . + "cd39f0901f4a7f3d1332f2163e80f05f35cf6e83189d2ad034aa09e3d694bd60" . + "5fb1b8323f9d6a584f0eaf3ee0c3bf39f676cf44bf12c6e9b0266faee9b3a567" . + . + "b008c7f2b766cdac777d9b7321fc81e9a888987fd031373ba9577e5215a8670d" . + "ae81401a9def585847ab1bf909bb52ce4dc01729f0b6d9075500b2333dd3420a" . + "566d1bd5cfdcd9a4826277abc752c39917e1fc20a1d3ea0b254cec48b99f1f64" . + "4a673e34f4b60e20305dd081358a3b85b106e465201a44c2bd82a5dcbbdf1434" . + "b008c7f2b766cdac777d9b7321fc81e9a888987fd031373ba9577e5215a8670d" . + "abe9047edec3d381fb03a75ca711607ef870f0ac9e2308d1d35273d55e0f50c9" . + "5d410818896969abdcb61ff5bbd42d80ecd97e9d3c0943a5fd0c2252c08bcec4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c5a9c1a22de3b3e6d58b82c1e13d6a031ff5ef8d5eb42c31b9a9c1c2e3250808" . + "60030e450906e95f0f20af0a0433338472cf2f31460348b0e82bda378d156c40" . + "57ffab64d45e82d28dc55b1ae7f86bc5c193015315665c2bc72996c21cb3ad41" . + "ecfca8537934afdec9262da4f3adc22d5a162e288c1654c315c19c70dee0cac6" . + . + "6d11ace9a05f65e89b0e21211a8154b025bacce445a482a16c221400d023ccf0" . + "080c16f18801e4d6580353b7794e8e1d9794514a7f0bda902a1f70e3fc6241ca" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "fe1cae2408dfad43493b885d0e193ceb17e758fb4d209a286bdb90848c18d6cb" . + "f9fdd62a8c814f962fd27d76d783390ee4a48fbd0ff2bc13ee552f8a816524be" . + "6661bcf4c88cb1c85192aafe795a5e9c6274dea71ebe905d3115dad22cfd8128" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b150fd5324a1b80f365148eb63aa6f685d78d373f71c217bc1a3adfee42189b0" . + "a584cfdabaf4f4104e307b361669cf1dc93b474e12b4c2711549b30e931ca2b3" . + "add7d978494c00a81b156646ec1ee0b1bf8d1265b569e031285db3d964c40110" . + "39e7bc820e48766a077937697124d710502766fc600a360ed67c31a5b7627a0a" . + . + "d96b637ba54a67173212df61476e85217c62d859281972c2beb1627f3424b962" . + "a8d48b36eca5bfd269fe29197b568335cdcc275b9745746764c39824010bfa2f" . + "b9d03f3bf75e831568b312843f65e1d8de2416e74ac1a9264caeac578969557b" . + "12316d6c49646b3beb52076d342530bcae4b69a7ae116c9ae2d6555e9a7a5a6e" . + . + "4de65e214da7e56b28a32fe6a02fed0ef74d6649abad2e493017cf2cb6990bcc" . + "47d37b63e2afeee95f201542548bed97ffc474cf71f0a1ea479c6c591d4d3aa3" . + "d1faadfffb20bbbabcadd91f7a3af6b56dd16dc908e8a2a89ed85a7efe9c1453" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5f64cc7fcfe0aabaec09298d8ef8b2cd2eb3e954b8e9e83fa564ef9a4f27bcee" . + "9c90d4e14ca21ac587337db2aea788824a1b50a7a462e6227ac0dfd7ab6146d7" . + "0b119446d5b5db6d713c9225dbd8ac914890ef50cdf5fd7ed8fcf5634d7e61c5" . + "0fc467e4d488b626eaf9e3df12a94640fffed781e6497e9ebd4348af26110124" . + . + "fed473d743c8331467061f622618d9c9d42a6e0427fb1f156ed7a60e1fba1959" . + "581a82a715aee0be895b0cd533106c65fe87a83fccdce6a00d36f361216369b1" . + "d5fd95304fd467edf259389f712b0affdc251c30ccf9942e4b62750092de3309" . + "6f1da9528220ffcb3e68130e40ad4d0852c63dc73bd3766ed5feaa800e4b6f21" . + . + "2ba581873c8ed9ad1f4122d0719aa10e23ab56be4830ecefb3141bbbe85a12f4" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "57c5e476fefb6bff05c12c8d837829f4555eec921fa8002b311def54e304508b" . + "0573769400c68eb6f1b816e8dc76e3173b58e7549f26a5511b4b5fa10f95b65b" . + "d29e04276f820a22dbc0ed90359c232b8a380223ca2fd4538a67187b4f6b7cfb" . + "2893cd46a0d134f99b4433cb955d779b5b6e8151c52ccb92832b906e8278e2a5" . + . + "00ac46fc8b87077db8252d52a847168a6252becc17c25ccd39351a41a7817565" . + "a7e6ed7c285ed4d09f906272e77e425489209f8019572788f89ee449e178ef61" . + "368febc6c5e7967dc9023618e59f8d39bcae1ae98f0e5376d7b74522cdbf54f9" . + "d6f52605ea40f900227ae805c18f2145bd3e52b19972ec0ce0e8af69c7231adb" . + "ed30566d1dbab71d5ba5793ae7fff725258c849dd1c40a45310334e31b3c2d55" . + "442a0cbf38e2b6a9c2c77297f16de46873089fc2c2a096d762472fc3818eed3f" . + "520a668fb5ae482acdeeb86570712da7609f48652a2088c3763e88cafc459216" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8fab0e3d723a62425cf0c0496a4c654960b856eb554df5c2293abbd7a392e73c" . + "3ec669316592a6296144c893ccadfbf56e4e9bc307f1681728481acbfd2ceb5a" . + "d537975e82945c1a781be87f408cd5d484092cea65894f78729ff6e6ef6d144f" . + "b6da80567899c14fcbd16f2ee0cb41e28d09717f1dc84cc1ef115380a07e0977" . + . + "9f26ce11c89614a6913f08573568f1e290ac729890b861b3d28886056d4942af" . + "6fb24f3cc8d466165dd8cf2e147fd7ec1d22dd7de1e649976ace44f7b0efec90" . + "60233d3bb8af75447b5621e2238b17de76aa8244cc1c7cded961942968ba3727" . + "4d0f119fd6adb425760681d8fa6459e5d665690183a0ab04efc2d647ad16a9c9" . + "0743380706325230bfe4e0004ad37d4e348959b70528e87f18c1f9e5bc2dbe84" . + "42ad4debed04eff51eb0887717921a572246b04dec76542a1618179c8f26d560" . + "91b659c5b7596b69643d5acc175eab28da1fcc50633167ab069553d7e5808fa7" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f0965e8acf03d31148a1329fd3b4ea405ff098da71060a4809f719e2aca00953" . + "1c23dd7adbe032072d5dd5c378161e50577864c4f8e413eeb0997cf4367977d6" . + "096956ff5810dde2eb4257475b97d10296836118e25bb3ec2c7bdb4a76bfadaf" . + "e5bae071bd9980339623bdd76514b8f72cd142ef36c057e319479f6f9bc9c01c" . + . + "bb6c860ae0f2475725dd41e8b62c9ae94124c4d75e460f3a37b7357c83e0227f" . + "2eeb2607e5b212f135f07e1e0045b4447e9b5604f3946ff5bcd9c223139ba2aa" . + "e0f9f3edfb32223154a18e7fe7772dc9cc186899f00d98ea978a6d7b43e0dad9" . + "f3f9f8664f3742f1576c95822bfb0d16f86950364cc44085f65fc0c6578dabce" . + . + "bb6c860ae0f2475725dd41e8b62c9ae94124c4d75e460f3a37b7357c83e0227f" . + "7bd1317a1fb95afb12f0fa09195ac6a0cc87d0f6c97c35b8a11c1053ce09caf8" . + "bbd6071f8248f8e4c16b0a562ad6d3a0f027377b465f3e578125a78139f65cc9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "4b9722d11b803a1ee7245bd09d5f7e90ebd0d91121dd385df9ae9e5b94016ec9" . + "2d71fa56b216475dfcdbcdafb118f54f27f1f8330630c62a145677ab4b57edfe" . + "9f14c046ee2aaf68c6f1eae2cd5457e70022a450ee4fb9de31c16a319cd88f36" . + "870f17a27d3f94a54dc7b3e537b5aac3e7f1bfdb3de86eb2a894ef82ca9f540d" . + . + "1c0bc0bcdac8ef71eca71675c94b06cae7f4dca620d7265a9063cabad87e6cf3" . + "3f2e5140dcef7117f33874e37578d8498996f3cf300941341676a4ae27c4aa05" . + "e4f3d4593a7c077d31fae1f3b6f51d6515a2ae393b6c6f8c43bcc66d0a423cb7" . + "780d9e6a6b1e1dac3da7c630448fc93f11318a0e4256d34f2b3f385e0267daaa" . + "205ae09c41c7485dfae567a2e3b34d434243eb62220b6e4208326ded82c3696a" . + "10f0b6130c4fc7a724e7a34e393c5fcf566803121649fc02a30997d639121cd8" . + "134648f2c4dd1c743f8983c760629dd9c62ccc2756e82f09b7ea936e1a330e90" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "938b8094bb77a14e98d4c4a28fa2cc4c2a0a78351ee9796b47b4248fd39a81d5" . + "c21bf0e0ce8d945dcd785424ad87b322d9b9aef8c0181bc95983b008efe27766" . + "09dfd34493dcb4af7d42c88c00d040be9484789d9448d4e3dbcc9656b533110b" . + "5babcb4ae46fe5b716ef3abbfbbf3f86e2ca6e946240120d4569ba245b5d5c8a" . + . + "3102dc2ac123b1651eccbb56a897ea62362b4f62d31791ada2058eb49439edfc" . + "31599e17197f8c5bda7fc0e0de958875298bc5446e43017ad747cdfe9d5e244f" . + "3882cf701d4b0a8ed2aa4e7c62f7a367a5106e730e75f1975058b178dde472e5" . + "981aef51f6b7a954e5a9bdc7dba4c1aa6f66b9c262c315493fb9fe303ad9e6ae" . + "4be1806942a51ea834aeb7da41eb8b2ea5fb2d4148d95f400c28a527e9be83fc" . + "bd4d5f74bd5ec61703d9e4e35c19dfbe006cf97f0cbc33cf4894ce273d6dff17" . + "bfb3df5a15daebc8591e6691e11d017030f3411df49a8df57b5ca42945cfbd63" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "26e12ec76e4333babd13e99bfee2e20daed77f9f1871caee543587d232243df4" . + "fd7af05d788a398da80ce0f2deb74a8b31ff6a1338f44d42bc09748da782db89" . + . + "c66922e33716ef462171b28a5579d310cd6e9f517e9912926f7834bbace7dcc3" . + "51e73de9bcd4774dfdcdd5390abdc6718cca394890e73061774cee07a2b2a3c6" . + "96dca0e070b809d4d8c2a8b3d48fe92796055f9674416ab81e34ac20acc411f0" . + "995e74df8782229ad5406a98b2e205785130890b62627aaf7cbda0aa6884a398" . + "0a1383b03fcd5245c774f9b0f8ea5445889f4f585d1ff420512f7a30c54ab19d" . + "b1d47ea7f981e3fe479d685341d5e7ce05188765089425ac00139c35fbabd36f" . + "69e6b6276c32c1c3db365320ac527f77a286d2cfda1a22ca2088a91aa2dac7d0" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "748d7d9d346bc7da07ed356cd9a5e95154d929c807a75801fa0d66fd92e0303b" . + "e3552dd5b063e4a29dbddb95c879bee4dd3b768be63513b9ac7bcee1a99da75b" . + "9c3270af17b69b7ec0f6da7be4d3d2616a794f835ef0aa37bb8d3bcc14390d94" . + "132859de49ea056a07f3263a0c69fc065fa1e9561d734a00239fe01de9292687" . + . + "fa2cbfecedacd4ceb0c3985439fea87dc3966bf9c8a222703336e0c10b512fd0" . + "eef60ce34b648b431ba272e07b719eba6d117f1c77f479302c8e5ecdc50e5e07" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + "13650e9b5b6b226deffe678ef2b4e913f707b27a56abcacfbf238db8f43fe022" . + . + . + "00640519975cc32f0cf8360f9bfbc485263ccc4b19568f1459a9e656f0c9b888" . + "15330e7fbd1b27d235a0030ecc3c8d8073dd212a138791f1f2fd4eefd5612fdb" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f7df185c1f4e546963d85b5cc0f895616b504b93ac88b9c364f0591d2d348f43" . + "c1122f24eaf74ddfbdc24eedc472598136629882d1bb5a211d702b67fea15e72" . + "5bb76b93f34071456ddb74271a1cc7e2bfbf54977113220974467c5afdada559" . + "a33aa7cb9572cca8263103c65d5b9602d2c9a15edb242dedd89061f0e4caffaf" . + . + "3b60a9205cd9b6d068835be80253263bd34f6498853ca1304a33c78e1c169acd" . + "493133e5b15133992e054c514aedaca13a6baa58f6b5cbf89d1f9f829dbf1fe9" . + "5b16126f8da59ab516f1dbdbd5a7a04f9355baa6bbc82d8a62d160b725089fa7" . + "1534eb419bccfe66ce5f894c1087c4871e34463f8b8da6a6e9782e44c94edd3d" . + . + "45c6ffbb86e0d59b0a514fda965cc6ecdd835ecca97ddc06ded1b2f2471d4e32" . + "cc73c9f104140bfe921d1a311c87fac159cc22e0251abcc0b4a18df6277aaf0c" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8b41e99ce5764c655ba16d50f527cfd82cbc4b032217bdf173f4a3092dacf8db" . + "a3ea677fa4e79398983fc0821c00a37256f15ae75bee5d80103ceaecb93cf476" . + "0cb79126281b63eb81d5150a22253fa0aeeea9765569a4aed6b60e621fa67608" . + "b9e496b560b7617782887da43caae9fae8d0ea28535115282fb7bf4009a4e4ff" . + . + "94499d8c402b13cffadbd374aad6f0e8138c6fcc48f04ce6fe84d831b2c51387" . + "73d6ac81eac09018bec2f04e9409b17f6266a784816d72eb6f63d70b3b023511" . + "e6822fcb3450386037e39cb282b008dcd14ee3768fd3170178bdc29161059633" . + "8bc09abc8886ba6c3ac9619233dee6335e4e07dbaa6f40c1bc1a6d92df36ef0b" . + "1890209f0c8c3c0c9ef171f0547c9a5247ae2274e37012c161f640f560a09103" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "d00765dd519359be8766bbac8d28da9f66405bd91d0f11ce648384d6c813c236" . + "e1118781365dc60ce4689df2b989718cd99234759beef209f7cd9400da4b6a08" . + "d6666a29abbcf318f773cff6e61a352c8d22dc4320326994c8424d6b195ef5e8" . + "ed0f55ba86f6149ac0f392df7713c9dccf78edd1b745fbaa0d55112ed7d1bdbb" . + . + "c2821776246b6723ad23af508bf9a887a1ca41f3d5a3f13260a576325432aa15" . + "4d095ca3df823d9297e5e2932b3f91342bfe44c5161338894e4c1d017146564f" . + "42434f4e40cf252cfb0487053d12eca95bc6fe25e11b694f1bd8b3ad03a22f34" . + "01d1e81abe960c49d9d56c9905bd3459c4e4fb2ae9ac50d4247db3020f39e844" . + "5db7d937ba077d9df6987b6c01ff2847d598e1aa16c665543034049425f1dfc3" . + "d31e2995c5f27812106a96fb12d57a8483bf74fc807bbb2255109baba762fe9a" . + "7c2e1efe13a502fb8dbd25ab377bd195b3ac9d7646b956c284a9ba00dc8358b9" . + "3ca85f0d917edccb3c4ad18b4b25f206a1a01ffe810392243fd6a1d9572360be" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ac44c1283403eab6ac8cc8ee3a282e02c69506239ef7a1f2fa741ebd8264c6e6" . + "f6abacbd73f7f1a1fefd722b127dbc020f530d3c4d35956e3e3693b3a3946626" . + "ece7db86aa7b10a2e09e651a6c67ffcdfee52eec38126c122d149bb1a88c47f0" . + "f0b5a0d98a9b49ad8255e8404d214daae0e127d4ac5de8719da4bfa4a385eeb8" . + . + "817d43a15fb6a0ecfd687540dc712a4ff4b9eb1b85f467bb9b7818069aa19d07" . + "f02788050f5ea432e11a3fffb61d1fec6ae9b4a4a1caee73fdd5e6c319ac7f85" . + "c32fc0353371f7ab56e973daa24a79622ec06ea1a4f35297f6187599063ccd3c" . + "a5c1892c9f4fba2e5a8aacf38dfd7a0979482eaa55e2fae7ef7a9421730125c5" . + . + . + "e8be6e14dbd490c53491bb2e42f142b3ef67a2d5e5ce4e9b04221cf48eb235df" . + "5d4f2b91b89dc8b49ab8174072b85dfd0f4cff3744494e8724b43f73b07e4e2c" . + "72633eb322205983417bb7611cb0ee61233678fdb5b1ace898759d75961ce724" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "b346010c9f725a7789da4e7622b9a1402830663203bd957ce50693eb5d7ba74b" . + "72315e15292a606d7dffbe6b82771e639c3032162f9930d431433f3e1973b23b" . + "1778ba6a5f7c6c723bb9c98bdb7bffe6e5e963df63a9db1b4a6d47e556a5a798" . + "4eecca6c87e85566c37ecc6ea6f75183855a2058beb3dd229aa66944ae26916e" . + . + "bf769cfb9ab181967aca661ca7e44cbcc9abdd2d8895570aaa9799ed0f1d0f3b" . + "c8944bc29d482af98681dfa216f0e7c84cf2179360b7ff54af7331368babcce9" . + "d01d2d6c47f7d1d0fc07094dd307953e1b260d0bd51b18e2c1e7fc72d465c399" . + "c404d5a0a0b824e6ecbf4a47cba7dd9308d0e4b258d597e31c2f8c3ff2b8b80c" . + . + . + . + . + "c17eb8d4193618f0f1df42bf403916b58bc6b5ce5aade375a7d7a71684677dc7" . + "ea04f84b6335180d02aad9dad9b889309ad752c8ef6b296e0d4c2270a3e25f30" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e2ab35e247cb6c2cace9f91b3e1e4f3c6a1a3ea1e560b59bbcb077b42b243989" . + "3f3acd3a7a1e7683f6ee593af3eab99d523769f53ff66d5f728dec24912bfc94" . + "733e240667c2d5f5889b4b0b456fdc72ad18a16123e8001bb4c5435444b1df32" . + "a862f6d45d7428382b2b869cefb08cbdbbf4cd8a2e792b10871ea40bfac543a1" . + . + "57e191af5e0ec60ca08a10f1d04e08138898be9b980260f0a8b7446859d3ec3c" . + "b00459c3f309416286fc5d337e84dcb69ce7bc6ca3e40196db9c8c6e3c43daa4" . + "11ed7dcb8ebf8916633106a8909484a1a62146df83fe5b70bd2676391cf1c9b8" . + "10ee811512879413e2cc432da46aed8bc0967f0c8eec00a0dfd50193e2947434" . + . + . + "4bcb1c5c24701a850fbcd00e7ea24286b8d9be113f4fd1e70618a71084d62ccf" . + "7045b49ab692de89c640190c71ef56f4d4e5f086dbc2db0b0550182ed8d64f7f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0f6f77ff8c2aac26966cd14b351bb09aabed07a459f89aaeedb67ef39614c7f8" . + "403024ec743c0cea2e135a2b07a789f02c0e783d7f6f1edd997dd5ea2b3a9818" . + "93b8e3843d0c498b1d0ff9c9237ac346f055870e33d202209c74d635f61f718d" . + "ae0cc4fac75614774ac533d3c8d9a25f4ec4e7c94a5f0be1186331f9c9523475" . + . + "851d758b1d4137c21779fc498679334966de56fc8cef23303f1590edb8261334" . + "9e3a0f740ce9fb6c748c2033b443e67e8911b22029596b829bc5acd3d67aa855" . + "bb1e6a7e2aed004a12a264bff6a8bf852a5922136e4b11d90bad4cd7da812ab9" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + . + "b2105be5f46bee517b2400daee1e54778a8c19963a96340207ba5b19a766a0ee" . + "fba21e08a7a33783ac79262abdedb539751d40e3f3357a09a343747372dd457e" . + "f50dfcabf5a7d7a2ce2f9818a3f12832223171507d999a95b071c538ca50d742" . + "2153e0694067b46839b7375f294d6870a80ad9d55651ce34df626cca85793299" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "8a43ce1b8588882e11c7693fe1a35f95a8f1e91257e0fe181031b48fac5f6579" . + "3c65a19bb0383cbeeb1eb7eb5709e2219022c11213c8e45d14767c0a5995d916" . + . + "13b4ad3a25abf98903c73902b28c2a75157663f49c06f0532c8799bb966de875" . + "d6ecdd18e1a118a2f3978b02a40aead80da4a03a416c13d41aa0607edc051b6f" . + "b56e7b9a2c62a873d6c9ed57caaa38856668671b604e00d943b6d8439b91fb4e" . + "6a6a8f147931c0ccd72f1fe4259def5c8bc5fda519abedfc398bc83888744523" . + . + "104df7a5a961e8f1f9bf5260a620bc97ac37d18bd6a81038badefe4aa9014de9" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "01ce5e541eb1f959f629bbebc826d20e61c7b846e910021208058411b254d44b" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + "6cf1d9eed4e9c6331d279c1f548babad2d08c11ba97492b89fa9fbaf292e7312" . + "d421f9b5bc629084da4e3383de2316bde49a979971ecf5c6096aabe53776f998" . + . + "0993b370c5b34c0ccb507119e926e4c5afa05b565b12e2bf386af5fed06596d2" . + "f80249641eb943df1e62c5e5cfa732e77465b2e457260e5dfee91417518aec0b" . + "9efe7d539ac4f56412e410c87bbb50f222c547d1d49834a07fa7f5e8587aff3a" . + "f44d54ddedeebcae430a68440a853fce7010652acc0a7474abb79b04d3e78af8" . + "b76252f6dec8fbf741b75b7dfe038a23e5badf03d842a9afa60cf6a9c19ef942" . + "6f25d0b0f8818cddc2b449d4d2a4738633b3bffcf552e175a09111ff138b7476" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "031767ef590b80290d94bee6c82c8c8aed272b5cbd6822d7d8d32d43f78d2326" . + "57140ad4c41e0fb1ef9706185d97291b27bb4fc468f1f9a27b3f3e82e92d969a" . + "5d8ecba66a6d856cde2c8783150e9b433647d1f3346ad4c75f093281f500dfd8" . + "70510a5397f11ac1e7062146ea727770177ab50d60802695dadae529f55c7971" . + . + "2201e10b97c46ec2a944bcab44b0420da67ef9816b8eb538fe57506b1e5744b7" . + "e747179da76db46fedefa257d37ff0bba5f24e677571b1ef6bee215f10d22bd3" . + "37710eb062de67db2f7a009914fb75316a9bfc9246e89286383cf33a4ad837ee" . + "d78c0b2eb01b747db08657e39abb94da9691e2744e16701f66e575db5058799f" . + "6e15382499879d49f323fdbd8324327c7f962cedd8bfbc2f9f277b7402f7edbc" . + "a5a8d374cf723ec02d51c8873d63c4104070958fe6a84dcfcc646ef9116b31c9" . + "1a1e5e31c7786824e5d0c591b75e4a41714bf5324953d299c8e06a292ac9b47b" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "486dac3392cffdda2ab8d5e4a7c3a38a0e123cefe0f61d888d51ec1b8c243378" . + "008c2b9f7027e27a4a0ed8e9a4e284b43e5c106b4e44b04cbf602816ffa72abb" . + "bc6d8718ce2bef702d302867cae0831139d4bc164d2681a401ab473194e9e83d" . + "f575d54bc4a7611d872e891ff85f0d118d5e20d4cc5915fd765f9712324203bf" . + . + "dba73a5a339831063295419753817cf4c8f80883cba59e6869d6e556e521de67" . + "32fad1f261d527526a6320415cd9cbd323e449d390c853b4d99019b59e5fb865" . + "6f69ca8735970133a3753aa18d7e0ade36922866cceec6cce04234dce7b7b095" . + "174ba1079549feb4e13e0033c2f328080b5bfaa7f401946fdf0e2f97c3ddd823" . + "23edf79a55177e7fc68e8b4f1890535370e61648eaedbfc750b4c843099e6e27" . + "28c63cf9914276d63af639667b39640b60c5f2f09026090098f5945a198dfff2" . + "0a38c0db3f85f77367e8a5094ef7272ea081cebf9f9df9788d0b2771cf9643ae" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9d77cb54df3160addb89833c25d2009c93d3e4b3537037bd36ee7db6e6f2df31" . + "c27916a4480790a0de7c09b4eb0623d67c82538118c4af2e2db004cfae2b4dc7" . + "9c64602057cff4a3d881d820ebc0c8fc37cb567160bd9bedb5658b64b43cbe05" . + "9829efd902451a45e4d3ed2e52245605c0785e771e51738c650c29218d784acf" . + . + "8ef2947118f282d7f22e08e2e1cdabaa9aed9cc49dec441fb7a8d7ed1fde2830" . + "aa2cbf59251fd5916053285e37090e040a7a5fa9df2bf2297e3df4aa27d39a08" . + "2d960e5c1d4c01d169547374ae83d975e9212c5b23e64db0504f36c8367a7cb5" . + "0804b1d0653f478a48ce74d4c7c919033254afddba74e5e2b07d275146de3942" . + . + . + "16c78807a626d51b84da2d25b79dcc984dcb6605473a04ca5adb85c9912980c7" . + "db17ae4e5312de8464c009dfaba233d26f3cb2c48848e9b2111d360ece3f6667" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9a8a225311522c489508311d3d1b88502b4b9a7b967777a4faab057033fa565a" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "b1c3c5118fccd37f61c18b946d6695eba59daf89b617c70c8da76396180edf8c" . + "7726b506763b836dec40e7b665cab083aa6ed837a72875e4ea7105c5a1557a28" . + . + "8bfe7ac5ee70bfd3aae7ed144a63a38f869e92a1e1966f562117e27741f44f6c" . + "fd160cee952b4534e99bd638d62ffd340d1a6b5f6a2d39030083f78e2fa13084" . + "42d142ee9b8fbeaea2fac8ca553c2e20d32259f0201963f0407ed0fa3dacd4e0" . + "07ff4b021c8eb746158859b1ce36922f96b48264d592c3535e84e2f68069546d" . + "8bfe7ac5ee70bfd3aae7ed144a63a38f869e92a1e1966f562117e27741f44f6c" . + "bf30d108e7367bcc2df8a932145b95ae5c4bae4e204dc41b6f5dcc1bc5d46785" . + "c0eecee4317e7b9294b72831ed747560880c0dab01594d03df3e58ee19dc4036" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "2ab2cb404429c843ab24b9a292821e92ece9befde9e9c229e9dd539757cb2b58" . + "dce9a9fd1dba3d646878a5d0d9b1a51354cf5012786dc48b0ee6bcd438a817e2" . + "13a2a58779a524cb5f6a9afa7459d694616e4f44ed25be7e5225704a073afa8a" . + "54a69f1f1a099354f6b0095a10350b25c553ab19846d1e72f201cb286bc72a75" . + . + "a445714c16fff76bdee218355ffe34630e93b1036bdc8fa9d10d2690e590cf22" . + "8de7fe2c39a8faf4279fc1aef68b81f1f2407c64fdb00c8bc40068cc1c8a9ce9" . + "f22c98e2e5c5ba1c0f5466b541bd506a61631b20f496fb57fb30ef366453b90e" . + "e40f97ef96be111d7c75c721b806f0d07a64f0436550adea246d4d8a1ac3d69c" . + . + "0310267380a9a553e83cd88baac94ddbda87cc0d2184785c53f386561d5ac3e9" . + "b1ab8f62655801a5f49d8ac46b596e4892a37248d3e41d6bee846b65828580b7" . + "8ad2d811b089e6deb420aa1c239d1cf584f2768a365297ffcc8d16751562390f" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "f02c2ea830780680f71f9eaffea4b8a6bb42cb2e48dec3897ada81b9ec7f71a7" . + "0c42c149f490ac04dcf8eb1d890fa162ff8ca02d752ae2d1bbdedd38b04c6571" . + "73c24121c1b7edc9853d39cf21dfcefe703313ae95dfb535dd25360d9fc7fdd1" . + "f5345af9deedda0fb0dcd2b7b9cd463c4793cbf5ae409ebb0619e7c7e17285bd" . + . + "2534ebe7f619396d1712da171446468f44dc0d30d7cf6d14340f41827fe2c3b1" . + "2bdbe20050569aa23c656c4bb88d11c339c79460be3f88d19bf49d8e0ae530ad" . + "23c2a356eb7a9a1e7983bfa9c85697dea983fffdf34f03ff605be4676365d0e7" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "be7df7feba4083ee9e07f808d17e8580bd29c2e8167470886e74ec18ebf6c9e0" . + "d65449a9d2ee8f2babe97cd0682ffd24aea7bf5a25474132a7a6edc8873e4faa" . + "b31ffa19f0e8fdd3395eb3b2bc4e0b9e562bd70d8f3871999557fd460060e286" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7a131cd838b0c94f29e110405a34ea655f79c4c7fd22f00a769a913dbaab79d9" . + "0caf13442482cb283f8ea4158127793a2b9ea441a2cb4d547d0c49ffcdf7841e" . + "e3331ff2fabd1e0b1c603e853fc5b14de466d22511ceaa60253a980767fb3050" . + "46e8b2b5cd695567f83023a83b28856d3df65f1af970abef410add618d0dbc50" . + . + "d6c68cf650539b831ffe23de1caf0c36126ab60f68c4ac5abcde37409482ab6a" . + "364d8966143c9dcae562e7c6851f17a9dcd220f0dece4387cbd393c8644f54e6" . + "f71199dd35c1e7d2d36e39ff0860f390da350967111c3b7539c7c53bb8d0010d" . + "c9144c2edb951273e0d90ae7299e476c8fb5065dbd55b2f02d4aedbc641998d6" . + "d2193fdb6cbd4ee4413cc7d4a87377d7018e1739d6dfd5e8a774202e88149dd0" . + "666a15da60d5d62ae2e263416254a26c0067d6befcce70115c430ec5df9a9bdd" . + "8a35cd39b47b2b51311bc99e80e02adcb10c3ce0448c7ffba308624ab5ea2de6" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "6d8c1c82a700327fa4f6054f84ce3de7cab9be3bce0b0a2cbbb04550c9f4ad1d" . + "84df77b3dbdff684b5488be2aecb6900c81ac3ee2b4065fefce389a47645ea13" . + "10251532226e0089b6b0e6b1ff75382a57fa27b1a8d9fb1304aab4d9d0bff25b" . + "1bf8746c1657df07e6f56f61255bae4e90bd1a3389952d160494ca82b4b824f5" . + . + "2d88e79fad9ffe610739df6114cccf12966e02f15698c97b62853330ca8c9d8d" . + "1572e25a68cb1ebee5fc0d9c1815546cfb1dcecf07c1fff77c8cf403060ab40b" . + "0a237cd46bc96ae66295bfa912f9bff64b60e92a176f34b50bf384442c5873ce" . + "9c6b480c30de3d3bdffe075432c72743231bb93542415f131a3d3464c52e77e9" . + . + "e2a0763c818629b328e0a951eafb15e6022fc7309d8796c790c1bd0a3f5ff6c4" . + "2fbdd8cfee29d6fc71bb08e0b4a328b238b897de26f8baab48312211a0c75c1a" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "df049a67534b8c750ee0cc45766d6642b89af3945c36b11f8bbe0733bf4858db" . + "2e43189c33253ad40fd49819fa20cca23b75a89df79f08f08be1b889f3e740b7" . + "9406791ae183c784f943fe834ee740c3b03552e4fa5479d31da36c9efe2f5939" . + "45b89d046bb02b8f7c1287f5b84afdc9ac65536fc876aa7e3467c298db662037" . + . + "f8f2812272bab9f525bee55054751db5133bc7c5d52e4ed67eaa3ff2241ccfd8" . + "e5342b0dc8fc8279b872559140ba99f46bb3ccbf68c21c6e40c9f0f65cfa28d2" . + "cb9676d927dda7e9ffe88601b945b9d9723c034f549cf722a246f185ab7e8753" . + "841d5c4914ee3f75a0f8302ce7ce31ce784905bfcba29ee85e34359a81e2daac" . + "677edcea82e9cac4bf44dbe78e36167b4f3d85befc30690395ede3698ce6e020" . + "8153d1a370ebf2ca1798b76a0b64849bb8a5f9492aec9ce9f7c218cc186bc573" . + "423f6e66ba6188dc3dea317d012beac0374938ebd3490c9fa8f38a87dbf252b9" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "455950195b99942d64b572571149c47638cd072f6a0fbea72bf3c159b8f71725" . + "0da66655c5013cf2da857b6df6325cb5878c77bde8b3a9410933e3148abb7f97" . + "e08993976264c54c9279c8c95716d1d49ad789322779bcd199873c53e7852520" . + "25bc89db3909962383f45818bfe47cfa4e075b163b510711cf43c14e716005ea" . + . + "fe9cfb1ee520798a8c4f8f8af641ee2123820eff60e24f1629e9d86b3a1b6f83" . + "729e3955ccb05e1f47db2159a03541658c5bebcf0e19e624249f09de1e82008c" . + "f54bceb459d7ac7693dbab729d3e303f06c082a77ff74aa54d28451577887c69" . + "0eec93e7d5a0e604b94284b066281cd7f2c5f98f0c11e4184ff245a4b5fc9d8d" . + . + "bf9559559f28fb9d140ae23d91bbcc6f5bd0d773666abc9d46712c597575b764" . + "658d1567280f1f7621b29412d0f37913e3cffbe4b6fbd72a25bb8ced15ccd3be" . + "b11a8dfd8360e52eab2554a770f7f5a42e02c6ccd0e345ad3a6b3789d58c44cd" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "18390d24ef1ac1eb3b1fd64eaf5892262431d7de7aa3ba93d0599bc04edcd64f" . + "0a0c3ad0137c425596b2fe2328e23036fb1211b891b78cf9c07ac8155b321a18" . + . + "82397a620954ce8e9436c3cf095840c2c4d0135b47023acf8d9d90693daaf8f1" . + "6a536f9c9f329cbb034167b4fead4c897098ce39903bd4fb3c234284d6399ac1" . + "ed3501bc10965e859fc7cfd32740a425e2b3953512dd4dc06365621ea4bfaac0" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "fa933898a44e7beecfe987d16635a07dc7899aa146c7e96067f79522ff94b4dd" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "91e2655b70e3532cf64c1599171319c157813d5a659c60fe20070521060a4968" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e3168967a88a29b01e282c10755c55823a2ead176fe49686f09f22eefcbeab10" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "9ec2cdb3def000629d6e7a02858cce745a0c4eee8c195b7fe1b8cd56a33dd68a" . + "6c1061dfc158c6c15ac3b269fcb41879ea1c1e48cbf9a4879f05ed02f4b8ef63" . + . + "589b3b2015b8bf6897bf7c48661d85c1076c4f84f2433bb47b68a9ccd5337a39" . + "82a6e46c8fcd1fe99bb3a17e031a967ec59dc414bedbd90286e847a7a0219d2e" . + "faaec20ec3fcb6c05434082de0d8eb0a9cf2b2e0a5c30bca240c5b0da7f06fa8" . + "318818e81a9c5c3a26a57fbf47f2068dfe4a3dacdb22e87edf7356ef77f0b8d9" . + "e5e5f671e6e4c7e0d2d9507e29246360750936f614709b51ea15ce942b354365" . + "c958a34f52ac8e323c2219ff77a38b963e9dbf0c65f8114876e5806a227592c2" . + "3b56ff8405f329c1057ae6a3adc29a86a4b82c271adf8ef21350dcf2a45dfc3d" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "7f50d17883399103beb083c94baf96f9cf4a881c2604da23baf580f14169803e" . + "911dbc51103ecd40686a9d02c91d9406be13158f971752ffb7d47bd954deea9e" . + "8d69f401eb28f1ee90603e5bacc4c39f8ee94175c0b57e6853afe46ca2d1e74d" . + "2f5787e3e39ff70bf32b0022c4ca6850b37d433ad6d09a8828612ee2045b7d33" . + . + "fe7d89cc9ce3f651a354c56600ba7637936f4030a974bf17aff982cc6bd3ce92" . + "f6cc142823414f74bfd1fca61721c4c0b3421cff4b0058474f3a75056a6cac1b" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "2dc87748d5ea4341726b540e97ca7534e81caab2d23303ecb402cdb41a410ec5" . + "b2eaef7d880654a644f70f5c8db1a858203265c09ed7ca54e42b59e557d374a0" . + "b7ed424815f62a641b78bfbdffe2048a4244922b227adbee073bb4bad8919029" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a1ac3a2ad9d17e0be8d58d6eac6a19e86a9262e833e01767edb86c495ca520e3" . + "a0db946d15cc1010796b03b587f729698b1c9ca94ec2a4173ede4b567aff0355" . + "5c4f3ae3c270feb231d0c8958530eb5e01bca2cf8c42d22dfba56cf5a5e1caa5" . + "8a209b468e92ae07fd13d21b856a664ae29a42890db051c6917c7583360ac787" . + . + "12142cfe66a98012c9c5a25688ed1dea2929ce84f08b98706dfb21e595fef25d" . + "6f96c15389ff30b231f4e8c910dff4f4877fa341105502bcbf17790b37acf214" . + "e6dc508a22881fa1fa3a08c6d5195590c9ae81eb51c51bb088f586b3c85d71bc" . + "683702d11eba8212cb973dc258fe4ae00abda698b63c832540c04fcd782a65dc" . + . + "41cbbc83d0912b8f496790da26f7c9ca15c5cf3e1ac122ef5d64d763f2497969" . + "338b940e869aeadd4afe4995607dc3d9f28a8a2e6faf41806eda5cd01fe9b9db" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "ebc4205f993a04e5201f5f743a15779f60436aa6161bd456a83b688f2281f689" . + "c03e23cb62ca767bc274dae87cb6cbf99a141ecda69081027c86e4a8689b72f5" . + "04da8f89573f8167a4abb4f4b647af588c5e16fe341c077257412abdc84e3289" . + "f1b5168f1eb924b5ae0ae3b36a43a8878330f14f584c8f4ab4121d7ad7cc9d43" . + . + "79ccd0a84d10612fea5f870b3a18bd20ddee769b97b2c63d05f4bf286df4ea78" . + "054c6e8afc98a72f6e16c84d55892f82a5f66526167ad9b149639215787e2a04" . + "3ddce1e35d4f89463a15668d4d6375376209de324183b0164aaae660fe887e77" . + "3a1e7b476aff2d858673d3dd96b01e88dc641418730f917a55ec8806c85b05e3" . + . + "3a0473c8ef40cea5cd044e07ce98da201301dcc1c2946aea15192869eb4c907e" . + "4f5e9bc1019e15b66edfed71719550f5910a302b811a70affab6eae432d43d24" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "912042c21bf366d4934e06b2eda5925db3fee5c7daf5f9f4eef14ed46403a2f9" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9589b85881f4140ce0aeaabc78dfcb34831b1c769c96187566f35534e4afccd7" . + "a8593c744bba311d58fbda67d9ca004bc6341bbe6c757a96f0a51384a3ebd6bc" . + "f54e9bec6993a514336afab52967b33caa78e914e5200d5974044d1d69afac3f" . + "0cdbbbe0039c051cf13443d0fc9573a2ce5ffcd3cb724901e9de4d5df1c4f3e4" . + . + "77ff1145edb38b1a49700aa80b4fde398ce6b8141e2927a30d1ab4a4595a5afa" . + "f923737cb1f38906f52610c8434140f607fc13e5dfee7cf5f351f33f4465e24a" . + "5223edf9fd98030f17a6793843f3a97dfefb624929f0f09a6021f05e0c8ed291" . + "6b9b78e4e5c87912fdd70cb9a41b9108f3e461318c5ecf8976fdfdf928893cc2" . + . + "c444376e7fd7f77e951662112b72e5b6d54901cbd8b6a839cc30119a6518720f" . + "69dec0426888681f8728713540ef86cdc6242a6ade701be4110c1b9def2149ee" . + "ac706a1c2f325bd88e24d390f6428d8e7ac0792003046f119632fa49c30e94be" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "0fae9a8c9776e9edc79d5292289e3088af00cd38ef2a9697f3800434dc953b10" . + "9326fedc189d74f4c940dc4f0acd7ee13dd55d2f251b83b2a1c58043b18271f1" . + "71275ac5445e99b14e7fa7dde707cd3ac53c14d33d2a0d602e03e794639d8bdf" . + "65c70b84aefa070c5e896cbce99a7ab5e842c56411bfcb8cc6f4578bfab39e83" . + . + "a3db8b3615fa2078aec42cad1095b5706ec569c3270ff550aad8fb352d8a2d34" . + "e59acb7157cc7feb83687ca0441743137fa6996ce8cb3b26211da2376808b493" . + "d3d24769a2f2f7d03c84e7685115a1f3fe4c906b23e98b68fe3f77c5754a1a20" . + "7bbfd1c551560b47bf1d25f5c3c6a7682a4a6f5c8b51e15a17a5cf922dd98f4f" . + "afc69c42a25ebd5aaf1f912d94150b8026b88d445c807c715089667d5037224a" . + "88dfc3bf9aa6d43a56780713f146bfdb7a0f5aedd0b9320941850b0c8452bf36" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "91145e4530b86647cf822f414dddf5a16e98d5985a5ec7c4ebe5ea0ada336298" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "28adc1b86d1591f73dcff8560b1fb5a357875c6d9d6ff0f4bad20465df477c82" . + "53be02edee29edc3ca019101568b0d8fd29b7a7ad6ca7227a06a01719e121518" . + "7f93894d8713fead48e7b78f2f59565be9d022a790acc2995a03fa8c3478eb22" . + "0a9faf5f6cb815c053f0c6473bf7c72f9401a4111a5416da08e65257bf19a33b" . + . + "5e0aefc0abfdbe0c2e29b058d901cec17a8d1d51155f057fa1ae77938cf03695" . + "2636ea6e54ce41729b4105111316e3862ad278a9a5b19f2ed4953b5fd008785f" . + "773e572c162646a84a22ba38d39c640df16e314bac23433e1d1a21870ba2e20d" . + "b4b064b055f48ff7bed0e5a215553750144e7e722a362d29b401f8135f6c533d" . + . + . + . + . + "740825b744f73b33f23841d5e52f79b4bae796799b7869a5326c0b10bc7c3ec9" . + "b58873bf71a693e95ceff84504a9755673d018696c41ba468f15dc0616b3da1c" . + "e4d5b5dbd841c847fc13db885df07ae08f74ca75d24036f7a813a4c8719524c1" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "584bba1a452a7a55f1c59cd056d9c6acde39b90042b3a803c10cdd757bc4d19f" . + "840e81087a6251f49b3c9f2e7d5b745623114c0ab2e40060f656a1853ace4e79" . + . + "2d65e92cc2408839cf577faabcc7fe89cb696ae895795d18ae6fc1c724ad3ee6" . + "ec4c30f1b8e14c23bed059bdc21428de3afa62d1cd03692a7c6806e55f644895" . + "ada6624c34cba0bf403eb1f278c516c25b8b098a3ebb25b400b9282852d044ce" . + "e1a802544645beb87c65df7631117e1710ce398e34baee51e7c347cc560044e7" . + . + . + . + . + . + "7200514e7380a00ce01c5863aec50ebb878e8b4630ef6abff1ea4cae9971224c" . + "9b0b61bbe8106f032ad1c298e52c6be7288d883e3b151d9db0878413981a3d68" . + "7c8fd8d667c3432bb2292c69ec4dd95ec019ce15369a157ed2a9f6098a2ff7e1" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "47710160a6a1cb6c62d87497c833a670b3acfdf9272aef2955d7a56cf14616ac" . + "9ec7d751a00694e9431affe4acfc54a698214fd30c22ca813d1dc6a2390de896" . + "d1ddf08ff496f85f58bf177020cac678b9d9f06b642c0f949040dfebfd97305b" . + "72d460a44a43fb4e474313ea17598f84c156c39acadf2e793c9cecfc2700178f" . + . + "c25cab20030723b933ece329c15d0ace0344e449d8c7c51e991f287850f1e3c2" . + "d731a2a50ed3b1c537fc58786bd4b34f446d313262ca5f165832980afd8a0377" . + "750e866abb9ec0abfe41e157c6b4a69d3f9fd07181d480b75bb6a05f38c20968" . + "0a273fea4cc3883c9f098ad554e9dcee829cbe12b81dbca5825b0278509285eb" . + . + . + . + . + . + "5b8e8ad43a1b64644066d5486c8ac880ca200cb81f158d276dc084cecda18aeb" . + "5b42b3dc1c297a0138e9580c61c195401d5a41f136a353b5f9226ac8610a873d" . + "bb2d223e5167d517e8fb61afb7555a117d9d6c3e104cd7187a8844f8680ada49" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "169e10387636113737178701d73872fc820b8b041b21a3eb66c25ce342babb9f" . + "f01fea60881a4e4e0c631dc6f59a79ac30421ba597e46d7549527a90d13ce8bc" . + "c580199dcf2e57ae633e9963697a916f9883a03816d4d22e826bb7ac9f9b00ce" . + "e7916fc0d7a4cc787f85cc22ec8e30446738f0b39a18deceb07da87d1c7e27d0" . + . + "853c80859a12244c93a7fea8dd743affbe643c79cdd105034135bc8a1aba016f" . + "708752e0e31369bb6f35166eb0b32babe2262261d215170ab2910f07cb0bed43" . + "f6eac97c000903b0b70b0891eb514bcd0880bb24f138d1a26d5a53b8001ee1c7" . + "d27e20856029dda45b5c9fc9a9cb6b476aa918b51102d06b3b7e6d60f1aea5b3" . + . + "7602909866bf0e1a9d01e8dbf5a582c047d4d09086e4a06fdf3659c087431ef9" . + "43b29c8bbc7fe7f36efc337871537847c01d2ba90d1f7d9cb6a1072e680e8820" . + "7d1fdf00ae0d55c5441770cb0c8a25283576976041ec8d5cc05d41faae0be15a" . + "c70d2abc8a53f0a06d2ab363f2e3a6f32e6180a3a4a99f3db81374740ed4ec58" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "9030e932311638818538136524c824c10e06998cf41f09238ebb6d2dcf8439c4" . + "527d16e63e2869be91d532e906b867e92c5db0c4c540f0c2db4431054a395ff0" . + "76c74f63ba86e1b482f267709832736b54346e5a18251674b004f5e74de447de" . + "3a4aa3ce8a6b56cad9487a5bcfc5675afc2694a3baa7fa03cd666759e4d93ff9" . + . + "46b7415fdc8f4bf416ca5dc4e6fb5dce32e84248634918fdf976070a3a648137" . + "c93fc427b881ccdabe80e7a641cdbf29ab16b3d550f0d49231f6567652fa6067" . + "b5bd47b26b071a084e26cde25bebec268e60f16296de379089419fc0942723a9" . + "2379d7b0f02dd828cca0d375d404c6a15649a568dfb4c6182530d698b98eab86" . + "ac41f1d6870896e39c4c9c2580defc92c8a259ba598fe077a1e0971924cc5df3" . + "ab9b2c597092111b98fc2c5367ed8fdd73f4f205b49c0055289180fed26e7c07" . + . + . + . + . + . + . + "3124f08935187fa6baf70d1a5ce51fb614eb05eb2ed8c1ef0a671de1d8a84735" . + "358c24f2388789c5bbb3ec1d82eb9a1b4c80eade7586449244b19f33852ae5a4" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c163b94826ac44543112dd898fe536305c3a0297d91e88f124eeca0549872307" . + "0739d46cba60c1bcb6b3cff3916b4529475ebd9f695da3bbecd9784027e38497" . + "e837adfcb269045e767b73cca5aa69816a93f1bbf4310228a42092e9f99754e4" . + "39efd150b0237682aee08a6990b6b99fb28ff1797755da952c91bf6b9113ceec" . + . + "6d31038caaf5b199a76c2f20a7085d76e54d59b70518a2ab7154d30d71027cc5" . + "5e9a85cfe05b9e666b0c80719d379b1830657657af0817ea6c9bb37cc75745fb" . + "90e066af0d50ee82fe1820f171c984fb9c324d4f0b10b4b1180c7e8cd5ff50dd" . + "66fde7836c07bc13f568d627bc035288461e0298b4326493d313b78532661cef" . + . + . + . + . + "8689f8cfa442b4045b4edde2f79e54a7bfdd7a7c694401198c2357fa31afc3ee" . + "8532c678439891da252ac0b05bcf5888e0d019ca621419d4d2aee903f6eb4806" . + "60349bef3326e640ca730c31a320b4dabb6cc5b842d48212f4448785dde72035" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "02243b1dc4f75326374470b80986726d0a5932596006cfb77965e259fcbf0727" . + "b7a893be03a817cc76e01f44f313bcf872f30389611a5a0b49cdb61ed54dd988" . + "1ae8ec9164ba761887ae41d4e80df8f531f0049df79f809d560b5f3232058763" . + "17474038c07837a2dcd5561c89bb53c6cb55a20cc4c5d87ee94a28d4cb52c6ae" . + . + "05f36e3bd49072cd249b126e4b23b6cfdb851df6e2d404a30091d6a2f1c76516" . + "038ecbc562ce10ec157d4e1b0178b046eca8ede10a628f7bc421d15f714754c4" . + "c44eedc6384f700bd47720ce255e2b7f9a810c7550d936280307fada347a8448" . + "c394f974dedcb2441fe63a8c09ddfa40c07f67d8631cf18c43fec1a4977e05b2" . + . + "e18a41874f4d605ae2b5d6927a12de1f611145ce589fc6c21a8570e5ddae8cb5" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "6cade01bbee5080faa85e3590eff287be83ef43f76ac6f1ca5ddf345d8c3a851" . + "c1acc2b4efe5fdab749460f2637da6564614a9f470505efe9bf1171ceb5d26d4" . + "9b0363ec842b1b3c9347e859740d3666fc8706f38cb817faa0ece58a5cafff80" . + "462ebc4fa397dbd15e1c2c0be93b54557c49f3965cb8a2bbde89fe7098741cec" . + . + "0d49ca1313209f6a03c1de889caddf079b6233c08d219e720a352ee918c3a872" . + "15df5a46dece323f8cf01f465d18180d0e8a365e0ce4159ea2386e1b27882520" . + "eaa748f750abbe79ac59d8133dfdd6ce76fbc739db4df8991e651eab4c48f9a9" . + "7e8ad31c6559e320ef669456a674d149fe3ba52a713123854c32e611223d6658" . + . + . + "3ae23395b30372ba6e3bbe931835232bb50a57d216df8cc79864e8afb638f176" . + "cc19b1425679bb84a9ca1edf427ed9d540754b9ea02c5568172bdd6cef9c8853" . + "e6339782a8cac83bdb20fd846afe6b03060cb72277ba32ffd39287fa4fd0f8c0" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "e25b59a647ef63947aa728be07b1b076ed679a2e4c24771e3d65c43390830dbe" . + "57b5efe53e30bbecd439c8098bc10f70b33baa21c9da4196e3a81f59852b3db1" . + "5a2972726db69d63d34c39de50a0a26926114f191a05be1d149d5cc903d0771c" . + "fd09446a626530c4a08781632aed9d56882f70e6c456dffe18f70b7869d79790" . + . + "0e7b9b9dc8609c20f82251fb312976428a5bab2444d5798f0d1aad8ade67a238" . + "6285cf37f2c974c394e24f6e62752a2345ff55678927d948edfd0e97953293b6" . + "e833c7a313a481c20cebf935dab306856bdd3ab83192f6b857578ac78683483b" . + "cb421f91fa5982fbeb3105fdd0ba42d4d3811236af38aa75cb1525f2c76987fa" . + . + . + "b378d470f568a5e3d8207df30e7fa9c9b60cb0a01c0cfae58de6cfe215619652" . + "cf70f550e25dfc590e34dede959e6722a2b54b8c5f6ca64686f664d334c69d31" . + "9102bb35a7c42970c650fe6881244c262aac5565fd2bc14ec9ea08a16f6d6646" . + "ac953143775612e6c9dd5b9f311a4901208eb3db123c6a73b8f30b9a0cf2dd62" . + "957ce33851d3b0ca81aec5a23f913883138a541524b3c5982925b9ae8c741b88" . + "794550825ce2e05a864d1c8b2c8dae6d6d1fe8b30a7fadfd8cecafc0e93984eb" . + "31acba0f624ca044ee5dfb0aa2ce8fd69a7de578c3685403d6805ff5bda92069" . + "c330a6f8c653d45b9ad5c49d94b2d1e2b0b0372a1450d3ba39432b26bd843cf3" . + . + "e4299972f4bb8792434bfc2cad1acabe2b2455518aeddd07d33c789f8635c7a2" . + "65d2469cdf9a4c504c8c3f6b31a3165ab19446f3c736784f585beb1e29c4d81f" . + "946f87b589bfac7e308482761d4a5958afa6675228490b04123ec58de4bcd7a7" . + "510de2643ed4c29dffa850e8da158a9f347e4a9dbf0d1c7127796a82b510edd5" . + . + . + "0abe74a1fe6e9668d8bfe1dcfb681993e0b31ce49dbbb7612ccd54d84d96eabf" . + "5e67a294cb067b2a422db4de0ea0735be53217cb6e3504d666b3e3c4d0379da6" . + "b40ce7a4937013faf55d79b8842e0792bc550ce17c77763c345fd140086ede2b" . + "7f03d3fce6843d36345f01b40752bfa74738bfd3dfe2aee8eff32fd9e3506171" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "5ea6a378c218228573dc37dc1cf7452ab847a55c07bd0eb69b431691d3565dd6" . + "e6fba58868443f040a156269b82f7b2af0c767c5a6ccd7781d519d2f27d90745" . + . + "8d8ac46f9ac3bb58132fb24b1f895a1568e845777ecc0eb53a15e8cdbe6296dd" . + "f65b0c4b621bb07bfac49b838067b5fd799bedbb045bf80e1d7377f72fd02bdd" . + "2d960e5c1d4c01d169547374ae83d975e9212c5b23e64db0504f36c8367a7cb5" . + "af1ed2d2bef8bfee21ae508de20730aa982a86c587f9aad54dee98eb2ecc7e95" . + . + "52bd5f3d03badf80f7ab61b0ebd226fa4b122255c1293fd4530e227c9a66a3f4" . + "a05ef500b246dccb78a690bf246742ac557c694401eff33b5143d368c544d11f" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "a625481ce39c6c98e2961e1fc89c1c8a5c6eb1457869935aee44bcbc774bf536" . + "54d7dfe4b408343fc0e2211da479154d46c618f60122a9735a6a82435db1836e" . + "2b1647f3d66b0f5243250be0a9191863e7f5496518253c32b258883bb0d7cf9e" . + "91cbf245bf17f7f7ab03d1818d961f8762c44e98316a671658b0c65364ce381f" . + . + "9f302cd4c518a703e4b2af5b74ceef09ac124fbfcf0d48e5f2537b58d9577e40" . + "ab7668c4427f7742f30e198a8239940c7059d09b93e84f655775e4ea524a1830" . + "73db25f8182b6928d00f0b1fac882c8d4bb3c81e35afb4c751bdd10d264e3043" . + "c12c201def8750a7b8ca5f60d3f8d8f8ed713d4e6797eeae06c2f936c2627add" . + . + . + "9f302cd4c518a703e4b2af5b74ceef09ac124fbfcf0d48e5f2537b58d9577e40" . + "67935118b9a064f6df2218122f882fd53f2584e3bfa7330fa4890a1921186ce1" . + "5cf1d78a3ca4f9f4f5bde60556503ad5158370821e20196bc104c822aeb71478" . + "1ee6fa77ced117e6045bbb22bf6e7495c3f4721401ad9a2a9061be4ef515190e" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "db85ba46faf97e3c6c2a468cfa8ac522db0ad0ddb35de738e0b22f974c827b09" . + "7256cb5d0ba0f80b4903b6257ec7b055f6852481988d2cfc5dfdb8b25b58c613" . + "5c7be528ff2ee179fce443f7bafe1710689d4a28c2311cb26c31a55e7fd2978a" . + "93ff3e35a5c3a13c6df7c88c6eeefee53679206f032271b42881437f4e63a1b8" . + . + "69a983ba7c0489187b239f81067d4c5a6e04c6a32be46510e414bd2b11d5ef7f" . + "e1d76764be8252dc0f6802153e10ea3ab52e8b44bec15ac528bf04bcf3f92e65" . + "27b37a09608a7c7501d55c2bc0f1bfd1f7cd5f1849b5d17e9e5a5b7d93b8ad41" . + "4e4f2ae26ad5a080c0835c92d69def25c98019a3a5b2ce843c6b43e70fe0e157" . + . + . + "69a983ba7c0489187b239f81067d4c5a6e04c6a32be46510e414bd2b11d5ef7f" . + "b2e47f524733c385d330058102ddc56f1cdda9d5133ef035440975a41c1c899b" . + "255be0db0035432ea7dcdaa17de7c6c90648dda2695a8ca7dad83f499e898a20" . + "6e36e9be37fd72568e933e2f3c2b51a98a769dd51b2560be58a2ac656e1767e1" . + "92e5a66169065f84773d2d274c0cbf31bf70b2a73e0bb398ef2c9d6236246ef2" . + "86b2362835f7820dbec5fa72eb60453763792f06ebbb08d904541c1d2bff04b4" . + "25c1b85deed1a4bfdce392e0880e92fc904192d43fdf075d94219350e04bf6f2" . + "a88725ad12044a4bdfa16058e560e61906ca28d531fcaadedb0b09bf1df28183" . + "7911b717062b55cbe6bc73719683421e07a1d04da7c168a35cd600bc048772a9" . + . + "9cd1ac85c28d32d0270bce7233b5191165403dc38a94a24c53a15bc6ebb24ea5" . + "418149ff260570b209066d4fc7109a128b2d26e232753f71f2e2b3335df9aade" . + "5048a4a81df8c2b7bd396698b05c761bdfd60ee6d164e4c092451e3e98fb32aa" . + "67e69029334883cd24c078494b921bed2c6ae422001cc04d1e5dd04b62b78bac" . + . + . + . + . + . + "048f89ed14fec1dbd9050974d2200e3433b915a49bd672232bcdea1fe32fa0a4" . + "9dc289b57d83de763ce1e93a4cfdc808bc4a537ca0c85dc883eb6ce3c214b12c" . + "50eac10e7966a04e139902940a2a8e129a4597574c709cb8d01939ace56ff9c3" . + "c52a6d7b701381f556368e541b316e14d359014754df7161154de6f9436ae7ed" . + "947851fcb06c48c9f095815badcc496f21200cc952f9f244530605611041dc77" . diff --git a/compliance/store/src/test/resources/test/ask.rq b/compliance/store/src/test/resources/test/ask.rq new file mode 100644 index 00000000000..07abc4e78f9 --- /dev/null +++ b/compliance/store/src/test/resources/test/ask.rq @@ -0,0 +1,78 @@ +PREFIX xsd: +PREFIX rdf: +PREFIX rdfs: +PREFIX owl: +PREFIX skos: +PREFIX sd: +PREFIX msg: +PREFIX calli: +PREFIX audit: + +ASK { + + a , calli:Menu; + rdfs:label "menu"; + calli:reader ; + calli:editor ; + calli:administrator ; + calli:link ; + calli:item ; + calli:item ; + calli:item ; + calli:item . + + calli:position 1; rdfs:label "Site"; + calli:item ; + calli:item ; + calli:item ; + calli:item . + calli:position 8; rdfs:label "Resources"; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item . + calli:position 9; rdfs:label "Administration"; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item . + calli:position 10; rdfs:label "Toolbox"; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item . + + calli:position 1; rdfs:label "Main article"; calli:link . + calli:position 2; rdfs:label "Home folder"; calli:link . + calli:position 3; rdfs:label "Contents"; calli:link . + calli:position 4; rdfs:label "Recent changes"; calli:link . + + calli:position 1; rdfs:label "Articles"; calli:link . + calli:position 2; rdfs:label "Text files"; calli:link . + calli:position 3; rdfs:label "Pages"; calli:link . + calli:position 4; rdfs:label "Scripts"; calli:link . + calli:position 5; rdfs:label "Styles"; calli:link . + calli:position 6; rdfs:label "Transforms"; calli:link . + calli:position 7; rdfs:label "Concepts"; calli:link . + calli:position 8; rdfs:label "Classes"; calli:link . + + calli:position 1; rdfs:label "Manifest"; calli:link . + calli:position 2; rdfs:label "User groups"; calli:link . + calli:position 3; rdfs:label "Named queries"; calli:link . + calli:position 4; rdfs:label "Named graphs"; calli:link . + calli:position 5; rdfs:label "Graph documents"; calli:link . + calli:position 6; rdfs:label "SPARQL query"; calli:link . + + calli:position 1; rdfs:label "What links here"; calli:link . + calli:position 2; rdfs:label "Related changes"; calli:link . + calli:position 3; rdfs:label "Introspect resource"; calli:link . + calli:position 3; rdfs:label "Permissions"; calli:link . + calli:position 4; rdfs:label "Print this page"; calli:link . +} \ No newline at end of file diff --git a/compliance/store/src/test/resources/test/delete-insert.ru b/compliance/store/src/test/resources/test/delete-insert.ru new file mode 100644 index 00000000000..bf7c27d65c5 --- /dev/null +++ b/compliance/store/src/test/resources/test/delete-insert.ru @@ -0,0 +1,53 @@ +PREFIX xsd: +PREFIX rdf: +PREFIX rdfs: +PREFIX owl: +PREFIX skos: +PREFIX sd: +PREFIX msg: +PREFIX calli: +PREFIX audit: + +DELETE { + ?item calli:link +} INSERT { + ?item calli:link +} WHERE { + ?item calli:link + FILTER strstarts(str(?item), str()) +}; + +DELETE { + ?item calli:link +} INSERT { + ?item calli:link +} WHERE { + ?item calli:link + FILTER strstarts(str(?item), str()) +}; + +DELETE { + a calli:Menu; a ?menu_type; calli:reader ?menu_reader; calli:editor ?menu_editor; calli:administrator ?menu_administrator; + rdfs:label ?menu_label; calli:link ?menu_link; calli:item ?menu_nav . + ?menu_nav rdfs:label ?menu_nav_label; calli:position ?menu_nav_position; calli:item ?menu_item . + ?menu_item rdfs:label ?menu_item_label; calli:position ?menu_item_position; calli:link ?menu_item_link . + ?menu_nav calli:link ?menu_nav_ink +} INSERT { + a calli:Menu; a ?menu_type; calli:reader ?menu_reader; calli:editor ?menu_editor; calli:administrator ?menu_administrator; + rdfs:label ?menu_label; calli:link ?menu_link; calli:item ?manifest_menu_nav . + ?manifest_menu_nav rdfs:label ?menu_nav_label; calli:position ?menu_nav_position; calli:item ?manifest_menu_item . + ?manifest_menu_item rdfs:label ?menu_item_label; calli:position ?menu_item_position; calli:link ?menu_item_link . + ?manifest_menu_nav calli:link ?menu_nav_ink +} WHERE { + a calli:Menu; a ?menu_type; calli:reader ?menu_reader; calli:editor ?menu_editor; calli:administrator ?menu_administrator; + rdfs:label ?menu_label; calli:link ?menu_link; calli:item ?menu_nav . + ?menu_nav rdfs:label ?menu_nav_label; calli:position ?menu_nav_position; calli:item ?menu_item . + ?menu_item rdfs:label ?menu_item_label; calli:position ?menu_item_position; calli:link ?menu_item_link . + OPTIONAL { + ?menu_nav calli:link ?menu_nav_ink + } + FILTER strstarts(str(?menu_nav), str()) + FILTER strstarts(str(?menu_item), str()) + BIND (iri(concat(str(), strafter(str(?menu_nav), str()))) AS ?manifest_menu_nav) + BIND (iri(concat(str(), strafter(str(?menu_item), str()))) AS ?manifest_menu_item) +}; \ No newline at end of file diff --git a/compliance/store/src/test/resources/test/insert-data.ru b/compliance/store/src/test/resources/test/insert-data.ru new file mode 100644 index 00000000000..2714cfdbb3c --- /dev/null +++ b/compliance/store/src/test/resources/test/insert-data.ru @@ -0,0 +1,78 @@ +PREFIX xsd: +PREFIX rdf: +PREFIX rdfs: +PREFIX owl: +PREFIX skos: +PREFIX sd: +PREFIX msg: +PREFIX calli: +PREFIX audit: + +INSERT DATA { + + a , calli:Menu; + rdfs:label "menu"; + calli:reader ; + calli:editor ; + calli:administrator ; + calli:link ; + calli:item ; + calli:item ; + calli:item ; + calli:item . + + calli:position 1; rdfs:label "Site"; + calli:item ; + calli:item ; + calli:item ; + calli:item . + calli:position 8; rdfs:label "Resources"; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item . + calli:position 9; rdfs:label "Administration"; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item . + calli:position 10; rdfs:label "Toolbox"; + calli:item ; + calli:item ; + calli:item ; + calli:item ; + calli:item . + + calli:position 1; rdfs:label "Main article"; calli:link . + calli:position 2; rdfs:label "Home folder"; calli:link . + calli:position 3; rdfs:label "Contents"; calli:link . + calli:position 4; rdfs:label "Recent changes"; calli:link . + + calli:position 1; rdfs:label "Articles"; calli:link . + calli:position 2; rdfs:label "Text files"; calli:link . + calli:position 3; rdfs:label "Pages"; calli:link . + calli:position 4; rdfs:label "Scripts"; calli:link . + calli:position 5; rdfs:label "Styles"; calli:link . + calli:position 6; rdfs:label "Transforms"; calli:link . + calli:position 7; rdfs:label "Concepts"; calli:link . + calli:position 8; rdfs:label "Classes"; calli:link . + + calli:position 1; rdfs:label "Manifest"; calli:link . + calli:position 2; rdfs:label "User groups"; calli:link . + calli:position 3; rdfs:label "Named queries"; calli:link . + calli:position 4; rdfs:label "Named graphs"; calli:link . + calli:position 5; rdfs:label "Graph documents"; calli:link . + calli:position 6; rdfs:label "SPARQL query"; calli:link . + + calli:position 1; rdfs:label "What links here"; calli:link . + calli:position 2; rdfs:label "Related changes"; calli:link . + calli:position 3; rdfs:label "Introspect resource"; calli:link . + calli:position 3; rdfs:label "Permissions"; calli:link . + calli:position 4; rdfs:label "Print this page"; calli:link . +} diff --git a/core/assembly/pom.xml b/core/assembly/pom.xml new file mode 100644 index 00000000000..eef67d20b9d --- /dev/null +++ b/core/assembly/pom.xml @@ -0,0 +1,314 @@ + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-core + 4.1.0-SNAPSHOT + + + rdf4j-assembly + pom + + RDF4J: Assembly + Distribution bundle assembly + + + + org.eclipse.rdf4j + rdf4j-config + ${project.version} + + + org.eclipse.rdf4j + rdf4j-console + ${project.version} + + + org.eclipse.rdf4j + rdf4j-http-client + ${project.version} + + + org.eclipse.rdf4j + rdf4j-http-protocol + ${project.version} + + + org.eclipse.rdf4j + rdf4j-http-server-spring + ${project.version} + + + org.eclipse.rdf4j + rdf4j-model + ${project.version} + + + org.eclipse.rdf4j + rdf4j-query + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryalgebra-evaluation + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryalgebra-model + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryparser-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryparser-serql + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryparser-sparql + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryrender + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-binary + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-sparqljson + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-sparqlxml + ${project.version} + + + org.eclipse.rdf4j + rdf4j-queryresultio-text + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-contextaware + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-dataset + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-event + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-http + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-manager + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-sail + ${project.version} + + + org.eclipse.rdf4j + rdf4j-repository-sparql + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-binary + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-datatypes + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-languages + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-n3 + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-nquads + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-ntriples + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-rdfjson + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-rdfxml + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-trig + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-trix + ${project.version} + + + org.eclipse.rdf4j + rdf4j-rio-turtle + ${project.version} + + + org.eclipse.rdf4j + rdf4j-runtime + ${project.version} + + + org.eclipse.rdf4j + rdf4j-runtime-osgi + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-api + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-federation + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-inferencer + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-lucene + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-memory + ${project.version} + + + org.eclipse.rdf4j + rdf4j-sail-nativerdf + ${project.version} + + + org.eclipse.rdf4j + rdf4j-util + ${project.version} + + + + + + assembly + + + + maven-assembly-plugin + + openrdf-sesame-${project.version} + false + + src/main/assembly/sdk.xml + + + + + create-sdk + package + + single + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + + org.eclipse.rdf4j:* + + + org.eclipse.rdf4j:sesame-runtime-osgi + + + target/openrdf-sesame-${project.version}-onejar.jar + false + false + + + + + + + create-onejar + package + + shade + + + + + + + + + diff --git a/core/assembly/src/main/assembly/sdk.xml b/core/assembly/src/main/assembly/sdk.xml new file mode 100644 index 00000000000..e45e8c103f9 --- /dev/null +++ b/core/assembly/src/main/assembly/sdk.xml @@ -0,0 +1,59 @@ + + sdk + + + tar.gz + zip + + + openrdf-sesame-${project.version} + + + + false + lib + + + + + + .. + + + *.txt + + + + + ../target/apidocs + docs/apidocs + + + + + + + ../http/server/target/openrdf-sesame.war + war + + + ../http/workbench/target/openrdf-workbench.war + war + + + + src/main/dist/bin/console.bat + bin + dos + true + + + src/main/dist/bin/console.sh + bin + 755 + unix + true + + + + diff --git a/core/assembly/src/main/dist/bin/console.bat b/core/assembly/src/main/dist/bin/console.bat new file mode 100644 index 00000000000..ae41a92169b --- /dev/null +++ b/core/assembly/src/main/dist/bin/console.bat @@ -0,0 +1,60 @@ +@rem *************************************************************************** +@rem Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. +@rem All rights reserved. This program and the accompanying materials +@rem are made available under the terms of the Eclipse Distribution License v1.0 +@rem which accompanies this distribution, and is available at +@rem http://www.eclipse.org/org/documents/edl-v10.php. +@rem *************************************************************************** +@echo off + +rem Set the lib dir relative to the batch file's directory +set LIB_DIR=%~dp0\..\lib +rem echo LIB_DIR = %LIB_DIR% + +rem Slurp the command line arguments. This loop allows for an unlimited number +rem of arguments (up to the command line limit, anyway). +set CMD_LINE_ARGS=%1 +if ""%1""=="""" goto setupArgsEnd +shift +:setupArgs +if ""%1""=="""" goto setupArgsEnd +set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1 +shift +goto setupArgs + +:setupArgsEnd + +if "%JAVA_HOME%" == "" goto noJavaHome +if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome +goto javaHome + +:noJavaHome +set JAVA=java +goto javaHomeEnd + +:javaHome +set JAVA=%JAVA_HOME%\bin\java + +:javaHomeEnd + +:checkJdk14 +"%JAVA%" -version 2>&1 | findstr "1.4" >NUL +IF ERRORLEVEL 1 goto checkJdk15 +echo Java 5 or newer required to run the console +goto end + +:checkJdk15 +"%JAVA%" -version 2>&1 | findstr "1.5" >NUL +IF ERRORLEVEL 1 goto java6 +rem use java.ext.dirs hack +rem echo Using java.ext.dirs to set classpath +"%JAVA%" -Djava.ext.dirs="%LIB_DIR%" org.openrdf.console.Console %CMD_LINE_ARGS% +goto end + +:java6 +rem use java 6 wildcard feature +rem echo Using wildcard to set classpath +"%JAVA%" -cp "%LIB_DIR%\*" org.openrdf.console.Console %CMD_LINE_ARGS% +goto end + +:end diff --git a/core/assembly/src/main/dist/bin/console.sh b/core/assembly/src/main/dist/bin/console.sh new file mode 100644 index 00000000000..658bc4e43f1 --- /dev/null +++ b/core/assembly/src/main/dist/bin/console.sh @@ -0,0 +1,13 @@ +#!/bin/sh +#******************************************************************************* +# Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Distribution License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +#******************************************************************************* + +JAVA_OPT=-mx512m + +lib="$(dirname "${0}")/../lib" +java $JAVA_OPT -cp "$lib/$(ls "$lib"|xargs |sed "s; ;:$lib/;g")" org.openrdf.console.Console $* diff --git a/core/config/pom.xml b/core/config/pom.xml new file mode 100644 index 00000000000..e7d891d91fb --- /dev/null +++ b/core/config/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-core + 4.1.0-SNAPSHOT + + + rdf4j-config + + RDF4J: application configuration + RDF4J application configuration classes + + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + ch.qos.logback + logback-classic + + + + junit + junit + test + + + + diff --git a/core/config/src/main/java/org/eclipse/rdf4j/Sesame.java b/core/config/src/main/java/org/eclipse/rdf4j/Sesame.java new file mode 100644 index 00000000000..9357cdf750f --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/Sesame.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j; + +import org.eclipse.rdf4j.common.io.MavenUtil; + +/** + * @author Arjohn Kampman + */ +public class Sesame { + + private static final String VERSION = MavenUtil.loadVersion("org.openrdf.sesame", "sesame-config", "dev"); + + public final static String getVersion() { + return VERSION; + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/AppConfiguration.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/AppConfiguration.java new file mode 100644 index 00000000000..5326486774e --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/AppConfiguration.java @@ -0,0 +1,353 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app; + +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import org.eclipse.rdf4j.Sesame; +import org.eclipse.rdf4j.common.app.config.Configuration; +import org.eclipse.rdf4j.common.app.logging.LogConfiguration; +import org.eclipse.rdf4j.common.app.net.ProxySettings; +import org.eclipse.rdf4j.common.app.util.ConfigurationUtil; +import org.eclipse.rdf4j.common.io.MavenUtil; +import org.eclipse.rdf4j.common.platform.PlatformFactory; + +/** + * @author Herko ter Horst + */ +public class AppConfiguration implements Configuration { + + /*-----------* + * Constants * + *-----------*/ + + private static final String APP_CONFIG_FILE = "application.properties"; + + private static final String DEFAULT_PREFIX = "Aduna"; + + private static final String DEFAULT_LOGGING = "info.aduna.app.logging.logback.LogbackConfiguration"; + + /*-----------* + * Variables * + *-----------*/ + + private String applicationId; + + private String longName; + + private String fullName; + + private AppVersion version; + + private String[] commandLineArgs; + + private String dataDirName; + + private File dataDir; + + private LogConfiguration loggingConfiguration; + + private ProxySettings proxySettings; + + private Properties properties; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Create a new, uninitialized application configuration. + */ + public AppConfiguration() { + super(); + } + + /** + * Create the application configuration. + * + * @param applicationId + * the ID of the application + */ + public AppConfiguration(final String applicationId) { + this(); + setApplicationId(applicationId); + } + + /** + * Create the application configuration. + * + * @param applicationId + * the ID of the application + * @param version + * the application's version + */ + public AppConfiguration(final String applicationId, final AppVersion version) { + this(applicationId); + setVersion(version); + } + + /** + * Create the application configuration. + * + * @param applicationId + * the ID of the application + * @param longName + * the long name of the application + */ + public AppConfiguration(final String applicationId, final String longName) { + this(applicationId); + setLongName(longName); + } + + /** + * Create the application configuration. + * + * @param applicationId + * the ID of the application + * @param longName + * the long name of the application + * @param version + * the application's version + */ + public AppConfiguration(final String applicationId, final String longName, final AppVersion version) { + this(applicationId, version); + setLongName(longName); + } + + /*---------* + * Methods * + ----------*/ + + public void load() + throws IOException + { + properties = ConfigurationUtil.loadConfigurationProperties(APP_CONFIG_FILE, null); + } + + public void save() + throws IOException + { + if (null != loggingConfiguration) { + loggingConfiguration.save(); + } + proxySettings.save(); + } + + public void init() + throws IOException + { + this.init(true); + } + + public void init(final boolean loadLogConfig) + throws IOException + { + if (longName == null) { + setLongName(DEFAULT_PREFIX + " " + applicationId); + } + setFullName(); + configureDataDir(); + load(); + if (loadLogConfig) { + try { + loggingConfiguration = loadLogConfiguration(); + loggingConfiguration.setBaseDir(getDataDir()); + loggingConfiguration.setAppConfiguration(this); + loggingConfiguration.init(); + } + catch (ClassNotFoundException e) { + e.printStackTrace(); + } + catch (InstantiationException e) { + e.printStackTrace(); + } + catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + proxySettings = new ProxySettings(getDataDir()); + proxySettings.init(); + save(); + } + + public void destroy() + throws IOException + { + loggingConfiguration.destroy(); + // proxySettings.destroy(); + } + + /** + * Get the name of the application (e.g. "AutoFocus" or "Metadata Server"). + * + * @return the name of the application + */ + public String getApplicationId() { + return applicationId; + } + + public final void setApplicationId(final String applicationId) { + this.applicationId = applicationId; + } + + public void setDataDirName(final String dataDirName) { + this.dataDirName = dataDirName; + } + + /** + * Get the long name of the application (e.g. "Aduna AutoFocus" or "OpenRDF + * Sesame Server"). + * + * @return the long name of the application + */ + public String getLongName() { + return longName; + } + + /** + * Set the long name of the application. + * + * @param longName + * the new name + */ + public final void setLongName(final String longName) { + this.longName = longName; + } + + /** + * Get the full name of the application, which consists of the long name and + * the version number (e.g. "Aduna AutoFocus 4.0-beta1" or "OpenRDF Sesame + * Webclient 2.0") + * + * @return the full name of the application + */ + public String getFullName() { + return fullName; + } + + private void setFullName() { + this.fullName = longName; + if (version != null) { + fullName = fullName + " " + version.toString(); + } + } + + /** + * Get the version of the application. + * + * @return the version of the application + */ + public AppVersion getVersion() { + if (version == null) { + version = AppVersion.parse(Sesame.getVersion()); + } + return version; + } + + /** + * Set the version of the application. + * + * @param version + * the new version + */ + public final void setVersion(final AppVersion version) { + this.version = version; + this.fullName = longName + " " + version.toString(); + } + + /** + * Get the command line arguments of the application. + * + * @return A String array, as (typically) specified to the main method. + */ + public String[] getCommandLineArgs() { + return (String[])commandLineArgs.clone(); + } + + /** + * Set the command line arguments specified to the application. + * + * @param args + * A String array containing the arguments as specified to the main + * method. + */ + public void setCommandLineArgs(final String[] args) { + this.commandLineArgs = (String[])args.clone(); + } + + public File getDataDir() { + return dataDir; + } + + public LogConfiguration getLogConfiguration() { + return loggingConfiguration; + } + + public ProxySettings getProxySettings() { + return proxySettings; + } + + public void setProxySettings(final ProxySettings proxySettings) { + this.proxySettings = proxySettings; + } + + /** + * Configure the data dir. + * + * @param dataDirParam + * the data dir to use. If null, determination of the data dir will be + * deferred to Platform. + */ + private void configureDataDir() { + if (dataDirName != null) { + dataDirName = dataDirName.trim(); + if (!("".equals(dataDirName))) { + final File dataDirCandidate = new File(dataDirName); + dataDirCandidate.mkdirs(); + // change data directory if the previous code was successful + dataDir = (dataDirCandidate.canRead() && dataDirCandidate.canWrite()) ? dataDirCandidate + : dataDir; + } + } + if (dataDir == null) { + dataDir = PlatformFactory.getPlatform().getApplicationDataDir(applicationId); + } + } + + /** + * Load and instantiate the logging configuration. + * + * @return the logging configuration + * @throws ClassNotFoundException + * @throws IllegalAccessException + * @throws InstantiationException + */ + private LogConfiguration loadLogConfiguration() + throws ClassNotFoundException, InstantiationException, IllegalAccessException + { + String classname = this.properties.getProperty("feature.logging.impl"); + if (classname == null) { + classname = DEFAULT_LOGGING; + } + final Class logImplClass = Class.forName(classname); + final Object logImpl = logImplClass.newInstance(); + if (logImpl instanceof LogConfiguration) { + return (LogConfiguration)logImpl; + } + throw new InstantiationException(classname + " is not valid LogConfiguration instance!"); + } + + /** + * @return Returns the properties. + */ + public Properties getProperties() { + return properties; + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/AppVersion.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/AppVersion.java new file mode 100644 index 00000000000..764cd6484b6 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/AppVersion.java @@ -0,0 +1,293 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app; + +import java.util.Locale; + +import org.eclipse.rdf4j.common.lang.ObjectUtil; + +/** + * A product version in Aduna's version format (i.e. major.minor-modifier). + * Where major stands for the major version number of the release, minor is the + * minor version number, and modifier is a modifier for the release, e.g. beta1 + * or RC1. Combined, this results in versions like 2.0 and 4.1-beta1. + */ +public class AppVersion implements Comparable { + + /** + * The version's major version number. + */ + private int major; + + /** + * The version's minor version number. + */ + private int minor; + + /** + * The version's micro version number. + */ + private int micro; + + /** + * The version's modifier, if any. + */ + private String modifier; + + /** + * Construct an uninitialized AppVersion. + */ + public AppVersion() { + this(-1, -1, -1, null); + } + + /** + * Creates a new major.minor version number, e.g. 1.0. + */ + public AppVersion(int major, int minor) { + this(major, minor, -1, null); + } + + /** + * Creates a new major.minor.micro version number, e.g. + * 1.0.1. + */ + public AppVersion(int major, int minor, int micro) { + this(major, minor, micro, null); + } + + /** + * Creates a new major.minor-modifier version number, e.g. + * 1.0-beta1. + */ + public AppVersion(int major, int minor, String modifier) { + this(major, minor, -1, modifier); + } + + /** + * Creates a new major.minor.micro-modifier version number, e.g. + * 1.0.1-SNAPSHOT. + */ + public AppVersion(int major, int minor, int micro, String modifier) { + this.major = major; + this.minor = minor; + this.micro = micro; + this.modifier = modifier; + } + + /** + * Gets the version's major version number. + */ + public int getMajor() { + return major; + } + + public void setMajor(int major) { + this.major = major; + } + + /** + * Gets the version's minor version number. + */ + public int getMinor() { + return minor; + } + + public void setMinor(int minor) { + this.minor = minor; + } + + /** + * Gets the version's micro version number. + */ + public int getMicro() { + return micro; + } + + public void setMicro(int micro) { + this.micro = micro; + } + + /** + * Gets the version's release modifier part. + */ + public String getModifier() { + return modifier; + } + + public void setModifier(String modifier) { + this.modifier = modifier; + } + + @Override + public boolean equals(Object other) { + boolean isEqual = false; + + if (other instanceof AppVersion) { + AppVersion o = (AppVersion)other; + + isEqual = major == o.major && minor == o.minor && micro == o.micro; + + if (isEqual) { + isEqual = modifier == o.modifier || modifier != null && modifier.equalsIgnoreCase(o.modifier); + } + } + + return isEqual; + } + + @Override + public int hashCode() { + int hash = 31 * (31 * major + minor); + + if (micro > 0) { + hash += micro; + } + + if (modifier != null) { + hash ^= modifier.toLowerCase(Locale.ENGLISH).hashCode(); + } + + return hash; + } + + /** + * Checks if this version is older than the specified version, according to + * the result of {@link #compareTo(AppVersion)}. + */ + public boolean olderThan(AppVersion other) { + return this.compareTo(other) < 0; + } + + /** + * Checks if this version is newer than the specified version, according to + * the result of {@link #compareTo(AppVersion)}. + */ + public boolean newerThan(AppVersion other) { + return this.compareTo(other) > 0; + } + + /** + * Compares two version numbers according to their major, minor and micro + * version numbers, ordering from oldest to newests version. If all three + * version numbers are equal then their modifiers are compared + * lexicographically (based on the Unicode value of each character), ignoring + * case. Versions without a modifier are considered to be the "final" + * versions and come after otherwise equal versions with a modifier. + * + * @return 0 if both versions are equal, a negative number if this + * version is older than other, or a positive number + * otherwise. + */ + public int compareTo(AppVersion other) { + int result = major - other.major; + + if (result == 0) { + result = minor - other.minor; + } + + if (result == 0) { + result = micro - other.micro; + } + + if (result == 0 && !ObjectUtil.nullEquals(modifier, other.modifier)) { + if (modifier == null) { + result = 1; + } + else if (other.modifier == null) { + result = -1; + } + else { + result = modifier.compareToIgnoreCase(other.modifier); + } + } + + return result; + } + + /** + * Parses a version string into a Version object. + * + * @param versionString + * A version string, e.g. 1.0.1 or 1.0-beta1. + * @return The parsed Version. + * @exception NumberFormatException + * If versionString could not be parsed to a version. + */ + public static AppVersion parse(String versionString) { + if (versionString.equals("dev")) { + return new AppVersion(-1, -1, "dev"); + } + + int minorSeperator = versionString.indexOf('.'); + int microSeperator = versionString.indexOf('.', minorSeperator + 1); + int modifierSeperator = versionString.indexOf('-', Math.max(minorSeperator, microSeperator)); + + if (minorSeperator == -1) { + throw new NumberFormatException("Illegal version string: " + versionString); + } + + String major = versionString.substring(0, minorSeperator); + String minor = null; + String micro = null; + String modifier = null; + + if (microSeperator == -1) { + // Without micro version number + if (modifierSeperator == -1) { + minor = versionString.substring(minorSeperator + 1); + } + else { + minor = versionString.substring(minorSeperator + 1, modifierSeperator); + modifier = versionString.substring(modifierSeperator + 1); + } + } + else { + // With micro version number + minor = versionString.substring(minorSeperator + 1, microSeperator); + + if (modifierSeperator == -1) { + micro = versionString.substring(microSeperator + 1); + } + else { + micro = versionString.substring(microSeperator + 1, modifierSeperator); + modifier = versionString.substring(modifierSeperator + 1); + } + } + + int majorInt = Integer.parseInt(major); + int minorInt = Integer.parseInt(minor); + int microInt = micro == null ? -1 : Integer.parseInt(micro); + return new AppVersion(majorInt, minorInt, microInt, modifier); + } + + /** + * Returns the string represention of this version. + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(16); + + if (major >= 0) { + sb.append(major).append('.').append(minor); + } + + if (micro >= 0) { + sb.append('.').append(micro); + } + + if (modifier != null) { + if (sb.length() > 0) { + sb.append('-'); + } + sb.append(modifier); + } + + return sb.toString(); + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/config/Configuration.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/config/Configuration.java new file mode 100644 index 00000000000..74551c7cd57 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/config/Configuration.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app.config; + +import java.io.IOException; + +public interface Configuration { + + public static final String DIR = "conf"; + + public static final String RESOURCES_LOCATION = "/info/aduna/app/config/"; + + public static final String DEFAULT_RESOURCES_LOCATION = RESOURCES_LOCATION + "defaults/"; + + /** + * Initialize the configuration settings. + * + * @throws IOException + * if the configuration settings could not be initialized because of + * an I/O problem. + */ + public void init() + throws IOException; + + /** + * Load the configuration settings. + * + * Settings will be loaded from a user and application specific location + * first. If no such settings exists, an attempt will be made to retrieve + * settings from a resource on the classpath. If no such settings exist + * either, settings will be loaded from a default resource on the classpath. + * + * @throws IOException + * if the configuration settings could not be loaded due to an I/O + * problem. + */ + public void load() + throws IOException; + + /** + * Store configuration settings. + * + * Settings will be stored in a user and application specific location. + * + * @throws IOException + * if the configuration settings could not be saved due to an I/O + * problem. + */ + public void save() + throws IOException; + + /** + * Clean up configuration resources. + * + * @throws IOException + * if one or more resources could not be cleaned up. Implementations + * should attempt to clean up as many resources as possible before + * returning or throwing an exception. + */ + public void destroy() + throws IOException; +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/LogConfiguration.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/LogConfiguration.java new file mode 100644 index 00000000000..8e7cf7e127c --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/LogConfiguration.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app.logging; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.rdf4j.common.app.AppConfiguration; +import org.eclipse.rdf4j.common.app.config.Configuration; +import org.eclipse.rdf4j.common.logging.LogReader; + +/** + * Configuration settings for application logging. + * + * @author Herko ter Horst + */ +public interface LogConfiguration extends Configuration { + + public static final String LOGGING_DIR = "logs"; + + public static final String LOG_FILE = "main.log"; + + public static final String USER_EVENT_LOG_FILE = "user-event.log"; + + public static final String ADMIN_EVENT_LOG_FILE = "admin-event.log"; + + public static final String USER_EVENT_LOGGER_NAME = "event.user"; + + public static final String ADMIN_EVENT_LOGGER_NAME = "event.admin"; + + /** + * Set the base location on the file system for logging configuration and data + * + * @param baseDir the base location on the file system for logging configuration and data + * @throws IOException + */ + public abstract void setBaseDir(File baseDir) throws IOException; + + /** + * The base location on the file system for logging configuration and data + * + * @return the base location on the file system for logging configuration and data + */ + public abstract File getBaseDir(); + + + /** + * The location on the file system where logging configuration is stored. + * + * @return the location on the file system where logging configuration is stored + */ + public abstract File getConfDir(); + + /** + * The location on the file system where logging data is stored. + * + * @return the location on the file system where logging data is stored + */ + public abstract File getLoggingDir(); + + /** + * A reader that can read logging information as stored by the specific + * logger's appender. + * + * @param appender Name of the appender to which the LogReader is attached + * + * @return a reader that can read logging information as stored by the logger + * configured through this LogConfiguration + */ + public abstract LogReader getLogReader(String appender); + + /** + * Default (fallback) LogReader instance. + * + * @return default (fallback) LogReader instance. + */ + public abstract LogReader getDefaultLogReader(); + + /** + * Is debug logging enabled? + * + * @return true if debug logging is enabled, false otherwise + */ + public abstract boolean isDebugLoggingEnabled(); + + /** + * Enable or disable debug logging. + * + * @param enabled + * set to true if debug logging should be enabled, set to false + * otherwise + */ + public abstract void setDebugLoggingEnabled(boolean enabled); + + public abstract void setAppConfiguration(AppConfiguration config); + + public abstract AppConfiguration getAppConfiguration(); + +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/AbstractLogConfiguration.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/AbstractLogConfiguration.java new file mode 100644 index 00000000000..999eb9e5fae --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/AbstractLogConfiguration.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app.logging.base; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Properties; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.eclipse.rdf4j.common.app.AppConfiguration; +import org.eclipse.rdf4j.common.app.logging.LogConfiguration; +import org.eclipse.rdf4j.common.app.util.ConfigurationUtil; + +/** + * Base implementation of LogConfiguration. + * + * @author Herko ter Horst + */ +public abstract class AbstractLogConfiguration implements LogConfiguration { + + private static final String LOGGING_CONFIG_FILE = "logging.properties"; + + private static final String PACKAGES_SLF4J_KEY = "packages.slf4j"; + + private static final String PACKAGES_JUL_KEY = "packages.jul"; + + private File baseDir; + + private File confDir; + + private File loggingDir; + + private boolean debugLoggingEnabled; + + private Set packages; + + private AppConfiguration config; + + protected AbstractLogConfiguration() + throws IOException + { + debugLoggingEnabled = false; + packages = new LinkedHashSet(); + initBase(); + } + + public void setBaseDir(File baseDir) throws IOException { + this.baseDir = baseDir; + confDir = new File(baseDir, DIR); + loggingDir = new File(baseDir, LOGGING_DIR); + if (!loggingDir.mkdirs() && !loggingDir.canWrite()) { + throw new IOException("Unable to create logging directory " + loggingDir.getAbsolutePath()); + } + } + + public File getBaseDir() { + return this.baseDir; + } + + public File getConfDir() { + return confDir; + } + + public File getLoggingDir() { + return loggingDir; + } + + private void initBase() + throws IOException + { + Properties loggingConfig = ConfigurationUtil.loadConfigurationProperties(LOGGING_CONFIG_FILE, null); + + String slf4jPackages = loggingConfig.getProperty(PACKAGES_SLF4J_KEY); + + if (slf4jPackages != null) { + String[] slf4jPackageNames = slf4jPackages.split(","); + + for (String packageName : slf4jPackageNames) { + packages.add(packageName); + } + } + + String julPackages = loggingConfig.getProperty(PACKAGES_JUL_KEY); + + if (julPackages != null) { + String[] julPackageNames = julPackages.split(","); + + for (String packageName : julPackageNames) { + packages.add(packageName); + + Logger logger = Logger.getLogger(packageName.trim()); + logger.setUseParentHandlers(false); + logger.setLevel(Level.ALL); + logger.addHandler(new LogConverterHandler()); + } + } + } + + public boolean isDebugLoggingEnabled() { + return debugLoggingEnabled; + } + + public void setDebugLoggingEnabled(boolean debugLoggingEnabled) { + this.debugLoggingEnabled = debugLoggingEnabled; + } + + protected Set getPackages() { + return Collections.unmodifiableSet(packages); + } + + public AppConfiguration getAppConfiguration() { + return this.config; + } + + public void setAppConfiguration(AppConfiguration config) { + this.config = config; + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/LogConfigurationBase.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/LogConfigurationBase.java new file mode 100644 index 00000000000..1eca4c635fe --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/LogConfigurationBase.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app.logging.base; + +import java.io.IOException; + +/** + * @deprecated since 4.0. Use {@link AbstractLogConfiguration} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class LogConfigurationBase extends AbstractLogConfiguration { + + protected LogConfigurationBase() + throws IOException + { + super(); + } + +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/LogConverterHandler.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/LogConverterHandler.java new file mode 100644 index 00000000000..6bbe9632313 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/base/LogConverterHandler.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app.logging.base; + +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handler to convert java.util.logging events to SLF4J logging events. + * + * @author Herko ter Horst + */ +public class LogConverterHandler extends Handler { + + public LogConverterHandler() { + setLevel(Level.ALL); + } + + @Override + public void close() + throws SecurityException + { + // do nothing + } + + @Override + public void flush() { + // do nothing + } + + @Override + public void publish(LogRecord record) { + Logger logger = LoggerFactory.getLogger(record.getLoggerName()); + + int level = record.getLevel().intValue(); + String message = record.getMessage(); + Throwable thrown = record.getThrown(); + + if (level >= Level.SEVERE.intValue()) { + logger.error(message, thrown); + } + else if (level < Level.SEVERE.intValue() && level >= Level.WARNING.intValue()) { + logger.warn(message, thrown); + } + else if (level < Level.WARNING.intValue() || level >= Level.CONFIG.intValue()) { + logger.info(message, thrown); + } + else { + logger.debug(message, thrown); + } + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/logback/LogConfigurator.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/logback/LogConfigurator.java new file mode 100644 index 00000000000..b3a494de07c --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/logback/LogConfigurator.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app.logging.logback; + +import java.util.HashMap; +import java.util.Map; + +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ElementSelector; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.RuleStore; +import ch.qos.logback.core.util.OptionHelper; + +import org.eclipse.rdf4j.common.logging.LogReader; +import org.xml.sax.Attributes; + +/** + * @author alex + */ +public class LogConfigurator extends JoranConfigurator { + + Map logReaderClassNames = new HashMap(); + + Map> appenders = new HashMap>(); + + String defaultAppender = null; + + public LogReader getDefaultLogReader() { + if (defaultAppender == null) { + if (appenders.keySet().iterator().hasNext()) { + defaultAppender = appenders.keySet().iterator().next(); + } + } + return this.getLogReader(defaultAppender); + } + + public LogReader getLogReader(String appenderName) { + if (appenderName != null) { + String className = logReaderClassNames.get(appenderName); + if (className != null) { + try { + LogReader logReader = (LogReader)OptionHelper.instantiateByClassName(className, + org.eclipse.rdf4j.common.logging.LogReader.class, context); + logReader.setAppender(appenders.get(appenderName)); + return logReader; + } + catch (Exception ex) { + System.err.println("Could not create logreader of type " + className + " !"); + ex.printStackTrace(); + } + } + else { + System.err.println("Could not find logreader for appender " + appenderName + " !"); + } + } + return null; + } + + @Override + public void addInstanceRules(RuleStore rs) + { + // parent rules already added + super.addInstanceRules(rs); + rs.addRule(new ElementSelector("configuration/appender/logreader"), new LogReaderAction()); + } + + public class LogReaderAction extends Action { + + String className; + + boolean def = false; + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + { + className = attributes.getValue(CLASS_ATTRIBUTE); + def = (attributes.getValue("default") != null) + && attributes.getValue("default").equalsIgnoreCase("true"); + ec.pushObject(className); + } + + @Override + public void end(InterpretationContext ec, String arg1) + { + Object o = ec.peekObject(); + if (o != className) { + addWarn("The object on the top the of the stack is not the logreader classname pushed earlier."); + } + else { + ec.popObject(); + Appender appender = (Appender)ec.peekObject(); + logReaderClassNames.put(appender.getName(), className); + appenders.put(appender.getName(), appender); + if (def) { + defaultAppender = appender.getName(); + } + } + } + + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/logback/LogbackConfiguration.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/logback/LogbackConfiguration.java new file mode 100644 index 00000000000..9751b410b77 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/logging/logback/LogbackConfiguration.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app.logging.logback; + +import java.io.File; +import java.io.IOException; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; + +import org.eclipse.rdf4j.common.app.logging.base.AbstractLogConfiguration; +import org.eclipse.rdf4j.common.app.util.ConfigurationUtil; +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.common.logging.LogReader; +import org.eclipse.rdf4j.common.logging.file.logback.FileLogReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogbackConfiguration extends AbstractLogConfiguration { + + public static final String LOGGING_DIR_PROPERTY = "info.aduna.logging.dir"; + + private static final String LOGBACK_CONFIG_FILE = "logback.xml"; + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private File configFile; + + private LogConfigurator configurator = null; + + public LogbackConfiguration() + throws IOException + { + super(); + // USE init() FOR FURTHER CONFIGURATION + // it will be called from the super constructor + } + + public void init() + throws IOException + { + configFile = getConfigFile(); + + load(); + + logger.info("Logback logging API implementation is configured."); + logger.debug("Log dir: {}", getLoggingDir().getAbsolutePath()); + + save(); + } + + public void load() + throws IOException + { + try { + if (System.getProperty(LOGGING_DIR_PROPERTY) == null) { + System.setProperty(LOGGING_DIR_PROPERTY, getLoggingDir().getAbsolutePath()); + } + } + catch (SecurityException e) { + System.out.println("Not allowed to read or write system property '" + LOGGING_DIR_PROPERTY + "'"); + } + + LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory(); + try { + configurator = new LogConfigurator(); + configurator.setContext(lc); + lc.reset(); + configurator.doConfigure(configFile); + } + catch (JoranException je) { + System.out.println("Logback configuration error"); + je.printStackTrace(); + StatusPrinter.print(lc); + } + } + + public void save() + throws IOException + { + // nop + } + + public void destroy() { + // look up all loggers in the logger context and close + // all appenders configured for them. + LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory(); + lc.reset(); + } + + private File getConfigFile() + throws IOException + { + File f = new File(getConfDir(), LOGBACK_CONFIG_FILE); + if (!f.exists() || !f.canRead()) { + String content = ConfigurationUtil.loadConfigurationContents(LOGBACK_CONFIG_FILE); + content = content.replace("${logging.main.file}", LOG_FILE); + content = content.replace("${logging.event.user.file}", USER_EVENT_LOG_FILE); + content = content.replace("${logging.event.admin.file}", ADMIN_EVENT_LOG_FILE); + content = content.replace("${logging.event.user.logger}", USER_EVENT_LOGGER_NAME); + content = content.replace("${logging.event.admin.logger}", ADMIN_EVENT_LOGGER_NAME); + if (!f.getParentFile().mkdirs() && !f.getParentFile().canWrite()) { + throw new IOException("Not allowed to write logging configuration file to " + f.getParent()); + } + else { + IOUtil.writeString(content, f); + } + } + return f; + } + + public LogReader getLogReader(String appender) { + return this.configurator.getLogReader(appender); + } + + public LogReader getDefaultLogReader() { + LogReader logReader = this.configurator.getDefaultLogReader(); + if (logReader != null) { + return logReader; + } + return new FileLogReader(new File(getLoggingDir(), LOG_FILE)); + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/net/ProxySettings.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/net/ProxySettings.java new file mode 100644 index 00000000000..feb0dff19a5 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/net/ProxySettings.java @@ -0,0 +1,251 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.app.net; + +import java.io.File; +import java.io.IOException; +import java.util.Properties; +import java.util.StringTokenizer; + +import org.eclipse.rdf4j.common.app.config.Configuration; +import org.eclipse.rdf4j.common.app.util.ConfigurationUtil; + +/** + * Utility class for handling proxy connection settings. + */ +public class ProxySettings implements Configuration { + + private final static String PROPNAME_PROXIES_ENABLED = "proxies.enabled"; + + private final static String PROPNAME_PROXIES_NONPROXYHOSTS_STARTING = "proxies.nonProxyHosts.starting"; + + private final static String PROPNAME_HTTP_PROXYHOST = "http.proxyHost"; + + private final static String PROPNAME_HTTP_PROXYPORT = "http.proxyPort"; + + private final static String PROPNAME_HTTPS_PROXYHOST = "https.proxyHost"; + + private final static String PROPNAME_HTTPS_PROXYPORT = "https.proxyPort"; + + private final static String PROPNAME_FTP_PROXYHOST = "ftp.proxyHost"; + + private final static String PROPNAME_FTP_PROXYPORT = "ftp.proxyPort"; + + private final static String PROPNAME_SOCKS_PROXYHOST = "socksProxyHost"; + + private final static String PROPNAME_SOCKS_PROXYPORT = "socksProxyPort"; + + private Properties props; + + public static final String PROXY_SETTINGS_FILENAME = "proxy.properties"; + + private File confDir; + + private File propsFile; + + public ProxySettings(File applicationDataDir) throws IOException { + confDir = new File(applicationDataDir, DIR); + } + + public void setProperty(String key, String val) { + if (val == null) { + props.remove(key); + } + else { + props.setProperty(key, val); + } + } + + private void setSystemProperty(String key, String val) { + if (val == null) { + System.getProperties().remove(key); + } + else { + System.setProperty(key, val); + } + } + + public boolean getProxiesEnabled() { + String val = props.getProperty(PROPNAME_PROXIES_ENABLED); + if (val != null) { + val = val.trim(); + } + return String.valueOf(true).equalsIgnoreCase(val); + } + + public void setProxiesEnabled(boolean proxiesEnabled) { + props.setProperty(PROPNAME_PROXIES_ENABLED, String.valueOf(proxiesEnabled)); + } + + public String getHttpProxyHost() { + return props.getProperty(PROPNAME_HTTP_PROXYHOST); + } + + public void setHttpProxyHost(String httpProxyHost) { + setProperty(PROPNAME_HTTP_PROXYHOST, httpProxyHost); + setProxySystemProperty(PROPNAME_HTTP_PROXYHOST, httpProxyHost); + } + + public String getHttpProxyPort() { + return props.getProperty(PROPNAME_HTTP_PROXYPORT); + } + + public void setHttpProxyPort(String httpProxyPort) { + setProperty(PROPNAME_HTTP_PROXYPORT, httpProxyPort); + setProxySystemProperty(PROPNAME_HTTP_PROXYPORT, httpProxyPort); + } + + public String getHttpsProxyHost() { + return props.getProperty(PROPNAME_HTTPS_PROXYHOST); + } + + public void setHttpsProxyHost(String httpsProxyHost) { + setProperty(PROPNAME_HTTPS_PROXYHOST, httpsProxyHost); + setProxySystemProperty(PROPNAME_HTTPS_PROXYHOST, httpsProxyHost); + } + + public String getHttpsProxyPort() { + return props.getProperty(PROPNAME_HTTPS_PROXYPORT); + } + + public void setHttpsProxyPort(String httpsProxyPort) { + setProperty(PROPNAME_HTTPS_PROXYPORT, httpsProxyPort); + setProxySystemProperty(PROPNAME_HTTPS_PROXYPORT, httpsProxyPort); + } + + public String getFtpProxyHost() { + return props.getProperty(PROPNAME_FTP_PROXYHOST); + } + + public void setFtpProxyHost(String ftpProxyHost) { + setProperty(PROPNAME_FTP_PROXYHOST, ftpProxyHost); + setProxySystemProperty(PROPNAME_FTP_PROXYHOST, ftpProxyHost); + } + + public String getFtpProxyPort() { + return props.getProperty(PROPNAME_FTP_PROXYPORT); + } + + public void setFtpProxyPort(String ftpProxyPort) { + setProperty(PROPNAME_FTP_PROXYPORT, ftpProxyPort); + setProxySystemProperty(PROPNAME_FTP_PROXYPORT, ftpProxyPort); + } + + public String getSocksProxyHost() { + return props.getProperty(PROPNAME_SOCKS_PROXYHOST); + } + + public void setSocksProxyHost(String socksProxyHost) { + setProperty(PROPNAME_SOCKS_PROXYHOST, socksProxyHost); + setProxySystemProperty(PROPNAME_SOCKS_PROXYHOST, socksProxyHost); + } + + public String getSocksProxyPort() { + return props.getProperty(PROPNAME_SOCKS_PROXYPORT); + } + + public void setSocksProxyPort(String socksProxyPort) { + setProperty(PROPNAME_SOCKS_PROXYPORT, socksProxyPort); + setProxySystemProperty(PROPNAME_SOCKS_PROXYPORT, socksProxyPort); + } + + private void setProxySystemProperty(String key, String val) { + if (getProxiesEnabled()) { + setSystemProperty(key, val); + } + // See SES-1100: Sesame should leave proxy settings alone if not enabled +// else { +// setSystemProperty(key, null); +// } + } + + /** + * Get the semicolon-separated list of hostnames starting with given + * strings, that do not use the proxy settings. + */ + public String getNonProxyHostsStarting() { + return props.getProperty(PROPNAME_PROXIES_NONPROXYHOSTS_STARTING); + } + + /** + * Set the semicolon separated list of hostnames starting with given + * strings, that do not use the proxy settings. + */ + public void setNonProxyHostsStarting(String nonProxyHostsStarting) { + setProperty(PROPNAME_PROXIES_NONPROXYHOSTS_STARTING, nonProxyHostsStarting); + + // parse nonproxy hosts + StringBuilder sysPropBuffer = new StringBuilder(); + if (nonProxyHostsStarting != null) { + StringTokenizer st = new StringTokenizer(nonProxyHostsStarting, ";"); + while (st.hasMoreTokens()) { + sysPropBuffer.append(st.nextToken().trim()); + sysPropBuffer.append('*'); + if (st.hasMoreTokens()) { + sysPropBuffer.append('|'); + } + } + } + String sysPropValue = null; + if (sysPropBuffer.length() > 0) { + sysPropValue = sysPropBuffer.toString(); + } + + // set system properties accordingly + setProxySystemProperty("http.nonProxyHosts", sysPropValue); + setProxySystemProperty("ftp.nonProxyHosts", sysPropValue); + } + + /** + * (Re-)loads the proxy system properties. + */ + public void load() throws IOException { + Properties proxyConfig = ConfigurationUtil.loadConfigurationProperties(PROXY_SETTINGS_FILENAME, null); + + propsFile = new File(confDir, PROXY_SETTINGS_FILENAME); + + props = ConfigurationUtil.loadConfigurationProperties(propsFile, proxyConfig); + } + + /** + * Saves the currently known settings. + */ + public void save() throws IOException { + if(!props.isEmpty()) { + ConfigurationUtil.saveConfigurationProperties(props, propsFile, false); + } + ConfigurationUtil.saveConfigurationProperties(props, new File(propsFile.getParentFile(), propsFile.getName()+".default"), true); + + } + + public void destroy() + throws IOException + { + // no-op + } + + public void init() + throws IOException + { + load(); + + // make sure some system properties are set properly + setHttpProxyHost(getHttpProxyHost()); + setHttpProxyPort(getHttpProxyPort()); + setHttpsProxyHost(getHttpsProxyHost()); + setHttpsProxyPort(getHttpsProxyPort()); + setFtpProxyHost(getFtpProxyHost()); + setFtpProxyPort(getFtpProxyPort()); + setSocksProxyHost(getSocksProxyHost()); + setSocksProxyPort(getSocksProxyPort()); + setNonProxyHostsStarting(getNonProxyHostsStarting()); + + save(); + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/app/util/ConfigurationUtil.java b/core/config/src/main/java/org/eclipse/rdf4j/common/app/util/ConfigurationUtil.java new file mode 100644 index 00000000000..c039f91308b --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/app/util/ConfigurationUtil.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app.util; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.eclipse.rdf4j.common.app.config.Configuration; +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.common.io.ResourceUtil; + +public class ConfigurationUtil { + + /** + * Load configuration settings from the specified file. + * + * @param file + * the file to load from + * @return the contents of the file as a String, or null if the file did not + * exist + * @throws IOException + * if the contents of the file could not be read due to an I/O + * problem + */ + public static String loadConfigurationContents(File file) + throws IOException + { + String result = null; + if (file.exists()) { + result = IOUtil.readString(file); + } + return result; + } + + /** + * Load configuration settings from a resource on the classpath. + * + * @param resourceName + * the name of the resource + * @return the contents of the resources as a String, or null if the + * resource, nor its default, could be found + * @throws IOException + * if the resource could not be read due to an I/O problem + */ + public static String loadConfigurationContents(String resourceName) + throws IOException + { + String result = null; + InputStream in = ResourceUtil.getInputStream(getResourceName(resourceName)); + if (in == null) { + in = ResourceUtil.getInputStream(getDefaultResourceName(resourceName)); + } + if (in != null) { + result = IOUtil.readString(in); + } + return result; + } + + /** + * Load configuration properties from the specified file. + * + * @param file + * the file to load from + * @return the contents of the file as Properties, or null if the file did + * not exist + * @throws IOException + * if the contents of the file could not be read due to an I/O + * problem + */ + public static Properties loadConfigurationProperties(File file, Properties defaults) + throws IOException + { + Properties result = null; + if (file.exists()) { + result = IOUtil.readProperties(file, defaults); + } + else { + result = new Properties(defaults); + } + return result; + } + + /** + * Load configuration properties from a resource on the classpath. + * + * @param resourceName + * the name of the resource + * @return the contents of the resource as Properties + * @throws IOException + * if the resource could not be read due to an I/O problem + */ + public static Properties loadConfigurationProperties(String resourceName, Properties defaults) + throws IOException + { + Properties result = null; + + String defaultResourceName = getDefaultResourceName(resourceName); + + Properties defaultResult = null; + InputStream in = ResourceUtil.getInputStream(defaultResourceName); + if (in != null) { + defaultResult = IOUtil.readProperties(in, defaults); + } + else { + defaultResult = new Properties(defaults); + } + + // load application-specific overrides + in = ResourceUtil.getInputStream(getResourceName(resourceName)); + if (in != null) { + result = IOUtil.readProperties(in, defaultResult); + } + else { + result = new Properties(defaultResult); + } + + return result; + } + + private static String getResourceName(String resourceName) { + StringBuilder result = new StringBuilder(Configuration.RESOURCES_LOCATION); + if (resourceName.startsWith("/")) { + resourceName = resourceName.substring(1); + } + result.append(resourceName); + return result.toString(); + } + + private static String getDefaultResourceName(String resourceName) { + StringBuilder result = new StringBuilder(Configuration.DEFAULT_RESOURCES_LOCATION); + if (resourceName.startsWith("/")) { + resourceName = resourceName.substring(1); + } + result.append(resourceName); + return result.toString(); + } + + /** + * Save configuration settings to a file. + * + * @param contents + * the configuration settings + * @param file + * the file to write to + * @throws IOException + * if the settings could not be saved because of an I/O problem + */ + public static void saveConfigurationContents(String contents, File file) + throws IOException + { + if (file.getParentFile().mkdirs() || file.getParentFile().canWrite()) { + IOUtil.writeString(contents, file); + } + } + + /** + * Save configuration properties to a file. + * + * @param props + * the configuration properties + * @param file + * the file to write to + * @throws IOException + * if the settings could not be saved because of an I/O problem + */ + public static void saveConfigurationProperties(Properties props, File file, boolean includeDefaults) + throws IOException + { + if (file.getParentFile().mkdirs() || file.getParentFile().canWrite()) { + IOUtil.writeProperties(props, file, includeDefaults); + } + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogLevel.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogLevel.java new file mode 100644 index 00000000000..bfdb5d5b197 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogLevel.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.logging; + +public enum LogLevel { + ERROR, + WARN, + INFO, + DEBUG, + TRACE +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogReader.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogReader.java new file mode 100644 index 00000000000..381ae0b7287 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogReader.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.logging; + +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import ch.qos.logback.core.Appender; + +public interface LogReader extends Iterator { + + /** + * Initialize the log reader. + * + * @throws Exception + */ + public void init() + throws Exception; + + /** + * Destroy the log reader and release all used resources. + * + * @throws Exception + */ + public void destroy() + throws Exception; + + /** + * Logging appender associated with this reader. + * + * @param appender + * logging appender associated with this reader + */ + public void setAppender(Appender appender); + + /** + * Logging appender associated with this reader. + * + * @return logging appender associated with this reader. + */ + public Appender getAppender(); + + /** + * Max. number of records returned by this log reader. Zero value (default) + * indicates no limit. + * + * @param limit + * max. number of records returned by this log reader. + */ + public void setLimit(int limit); + + /** + * Max. number of records returned by this log reader. + * + * @return max. number of records returned by this log reader or zero value + * if no limit has been set. + */ + public int getLimit(); + + /** + * Check if more records are available after limit is reached. + * + * @return true if more records are available + */ + public boolean isMoreAvailable(); + + /** + * Index of the first record returned by this log reader. + * + * @param offset + * index of the first record returned by this log reader. + */ + public void setOffset(int offset); + + /** + * Index of the first record returned by this log reader. + * + * @return index of the first record returned by this log reader. + */ + public int getOffset(); + + /** + * Test if this LogReader implementation supports level-based records + * filtering. + * + * @return true if level filtering is supported. + */ + public boolean supportsLevelFilter(); + + /** + * Level of the log records returned by this log reader. + */ + public void setLevel(LogLevel level); + + /** + * Level of the log records returned by this log reader. + * + * @return Level of the log records returned by this log reader or 'null' if + * no level filter has been set. + */ + public LogLevel getLevel(); + + /** + * Test if this LogReader implementation supports thread-based records + * filtering. + * + * @return true if thread filtering is supported. + */ + public boolean supportsThreadFilter(); + + /** + * Thread name of the log records returned by this log reader. + */ + public void setThread(String threadname); + + /** + * Thread name of the log records returned by this log reader. + * + * @return thread name of the log records returned by this log reader or + * 'null' if no thread filter has been set. + */ + public String getThread(); + + /** + * All available thread names of the log records. + * + * @return a List of thread names of the log records. + */ + public List getThreadNames(); + + /** + * Test if this LogReader implementation supports date-based records + * filtering. + * + * @return true if date filtering is supported + */ + public boolean supportsDateRanges(); + + /** + * Start (earliest) date of the log records returned by this log reader. + */ + public void setStartDate(Date date); + + /** + * Start (earliest) date of the log records returned by this log reader. + * + * @return Start date of the log records or 'null' if no start date has been + * set + */ + public Date getStartDate(); + + /** + * End (latest) date of of the log records returned by this log reader. + */ + public void setEndDate(Date date); + + /** + * End (latest) date of of the log records returned by this log reader. + * + * @return End date of the log records or 'null' if no end date has been set + */ + public Date getEndDate(); + + /** + * Min (earliest) available date of the log records. + */ + public Date getMinDate(); + + /** + * Max (latest) available date of the log records. + */ + public Date getMaxDate(); + +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogRecord.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogRecord.java new file mode 100644 index 00000000000..ca2a68fa57d --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/LogRecord.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.logging; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +public interface LogRecord { + + public static final SimpleDateFormat ISO8601_TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); + + public LogLevel getLevel(); + public Date getTime(); + public String getThreadName(); + public String getMessage(); + public List getStackTrace(); +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/AbstractLogReader.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/AbstractLogReader.java new file mode 100644 index 00000000000..be5c6540dee --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/AbstractLogReader.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.logging.base; + +import java.util.Date; +import java.util.List; + +import org.eclipse.rdf4j.common.logging.LogLevel; +import org.eclipse.rdf4j.common.logging.LogReader; +import org.eclipse.rdf4j.common.logging.LogRecord; + +import ch.qos.logback.core.Appender; + +public abstract class AbstractLogReader implements LogReader { + + public abstract boolean hasNext(); + + public abstract LogRecord next(); + + private int limit = 0; + private int offset = 0; + + private Appender appender; + + public final void remove() { + throw new UnsupportedOperationException("Removing log records is not supported."); + } + + public void setAppender(Appender appender) { + this.appender = appender; + } + + public Appender getAppender() { + return this.appender; + } + + public Date getEndDate() { + return null; + } + + public LogLevel getLevel() { + return null; + } + + public Date getStartDate() { + return null; + } + + public void setEndDate(Date date) { + throw new UnsupportedOperationException("Date ranges are not supported by this LogReader implementation!"); + } + + public void setLevel(LogLevel level) { + throw new UnsupportedOperationException("Level filter is not supported by this LogReader implementation!"); + } + + public void setStartDate(Date date) { + throw new UnsupportedOperationException("Date ranges are not supported by this LogReader implementation!"); + } + + public boolean supportsDateRanges() { + return false; + } + + public Date getMaxDate() { + return null; + } + + public Date getMinDate() { + return null; + } + + public boolean supportsLevelFilter() { + return false; + } + + public String getThread() { + return null; + } + + public void setThread(String threadname) { + throw new UnsupportedOperationException("Thread filter is not supported by this LogReader implementation!"); + } + + public boolean supportsThreadFilter() { + return false; + } + + /** + * @return Returns the limit. + */ + public int getLimit() { + return limit; + } + + /** + * @param limit The limit to set. + */ + public void setLimit(int limit) { + this.limit = limit; + } + + /** + * @return Returns the offset. + */ + public int getOffset() { + return offset; + } + + /** + * @param offset The offset to set. + */ + public void setOffset(int offset) { + this.offset = offset; + } + + public List getThreadNames() { + return null; + } + +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/LogReaderBase.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/LogReaderBase.java new file mode 100644 index 00000000000..2b076c360ee --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/LogReaderBase.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.logging.base; + +/** + * @deprecated since 4.0. Use {@link AbstractLogReader} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class LogReaderBase extends AbstractLogReader { + +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/LogRecordBase.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/LogRecordBase.java new file mode 100644 index 00000000000..0af3b9f18ee --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/LogRecordBase.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.logging.base; + +/** + * @deprecated since 4.0. Use {@link SimpleLogRecord} instead. + * @author Jeen Broekstra + */ +@Deprecated +public class LogRecordBase extends SimpleLogRecord { + +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/SimpleLogRecord.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/SimpleLogRecord.java new file mode 100644 index 00000000000..a1d27747305 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/base/SimpleLogRecord.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.logging.base; + +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.rdf4j.common.logging.LogLevel; +import org.eclipse.rdf4j.common.logging.LogRecord; + +public class SimpleLogRecord implements LogRecord { + + private LogLevel level; + + private String message; + + private List stackTrace; + + private String threadName; + + private Date time; + + public LogLevel getLevel() { + return level; + } + + public String getMessage() { + return message; + } + + public List getStackTrace() { + return stackTrace; + } + + public String getThreadName() { + return threadName; + } + + public Date getTime() { + return time; + } + + public void setLevel(LogLevel level) { + this.level = level; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setStackTrace(List stackTrace) { + this.stackTrace = stackTrace; + } + + public void setThreadName(String threadName) { + this.threadName = threadName; + } + + public void setTime(Date time) { + this.time = time; + } + + public String toString() { + StringBuilder result = new StringBuilder(); + result.append(level); + result.append(" "); + result.append(LogRecord.ISO8601_TIMESTAMP_FORMAT.format(time)); + result.append(" ("); + result.append(threadName); + result.append("): "); + result.append(message); + Iterator tracerator = stackTrace.iterator(); + if(tracerator.hasNext()) { + result.append("\n\t"); + result.append(tracerator.next()); + if(tracerator.hasNext()) { + result.append("\n\t"); + result.append(tracerator.next()); + result.append("\n\t... "+(stackTrace.size()-2)+" more lines"); + } + } + return result.toString(); + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/FileLogReader.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/FileLogReader.java new file mode 100644 index 00000000000..4fb49a86bd3 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/FileLogReader.java @@ -0,0 +1,210 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.logging.file.logback; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Matcher; + +import org.eclipse.rdf4j.common.logging.LogLevel; +import org.eclipse.rdf4j.common.logging.LogRecord; +import org.eclipse.rdf4j.common.logging.base.AbstractLogReader; +import org.eclipse.rdf4j.common.logging.base.SimpleLogRecord; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.FileAppender; + +public class FileLogReader extends AbstractLogReader { + + private File logFile = null; + + private RandomAccessFile log = null; + + private long fileLength; + + private long byteOffset; + + private LogRecord next = null; + + private int count = 0; + + public FileLogReader() { + } + + public FileLogReader(File logFile) { + this.logFile = logFile; + } + + public void setAppender(Appender appender) { + super.setAppender(appender); + if (appender instanceof FileAppender) { + this.logFile = new File(((FileAppender)appender).getFile()); + } + else { + throw new RuntimeException("FileLogReader appender must be an instance of FileAppender!"); + } + this.next = null; + } + + public void init() + throws Exception + { + if (logFile == null) { + throw new RuntimeException("Log file is undefined for this FileLogReader!"); + } + if (log != null) { + log.close(); + } + log = new RandomAccessFile(logFile, "r"); + fileLength = log.length(); + byteOffset = fileLength - 1; + count = 0; + next = getNext(); + if (getOffset() > 0) { + doSkip(getOffset()); + } + } + + private void doSkip(int offset) { + while (this.hasNext() && (count < offset)) { + this.next(); + } + } + + public boolean isMoreAvailable() { + return next != null; + } + + public boolean hasNext() { + if (getLimit() == 0) { + return isMoreAvailable(); + } + return isMoreAvailable() && (count < (getOffset() + getLimit())); + } + + public LogRecord next() { + LogRecord result = next; + try { + next = getNext(); + count++; + } + catch (IOException ioe) { + throw new RuntimeException("Unable to get next log record.", ioe); + } + if (!hasNext()) { + try { + destroy(); + } + catch (IOException e) { + // too bad + } + } + return result; + } + + private LogRecord getNext() + throws IOException + { + SimpleLogRecord result = null; + + StringBuilder message = new StringBuilder(); + + List stackTrace = new LinkedList(); + + while (result == null && byteOffset > 0) { + List bytesRead = new LinkedList(); + if (byteOffset < 0) { + System.err.println("Subzero byteOffset with: "); + System.err.println("\tMessage: " + message); + System.err.println("\tStacktrace: " + stackTrace.size()); + } + // find start of previous line + byte currentByte; + do { + log.seek(byteOffset--); + currentByte = log.readByte(); + if(currentByte != '\n' && currentByte != '\r') { + bytesRead.add(0, currentByte); + } + } + while (byteOffset > 0 && currentByte != '\n' && currentByte != '\r'); + + // if at start of file, retrieve the byte we just read in the do/while + if (byteOffset < 1) { + byteOffset = 0; + log.seek(0); + } + + // read the line + byte[] lineBytes = new byte[bytesRead.size()]; + int index = 0; + Iterator byteIt = bytesRead.iterator(); + while(byteIt.hasNext()) { + lineBytes[index] = byteIt.next(); + index++; + } + String lastLine = new String(lineBytes, "UTF-8"); + + if (lastLine != null) { + // is this a log line? + Matcher matcher = StackTracePatternLayout.DEFAULT_PARSER_PATTERN.matcher(lastLine); + if (matcher.matches()) { + try { + LogLevel level = LogLevel.valueOf(matcher.group(1).trim()); + Date timestamp = LogRecord.ISO8601_TIMESTAMP_FORMAT.parse(matcher.group(2).trim()); + String threadName = matcher.group(3); + message.insert(0, matcher.group(4)); + + result = new SimpleLogRecord(); + result.setLevel(level); + result.setTime(timestamp); + result.setThreadName(threadName); + result.setMessage(message.toString()); + result.setStackTrace(stackTrace); + + message = new StringBuilder(); + stackTrace = new ArrayList(); + } + catch (ParseException pe) { + throw new IOException("Unable to parse timestamp in log record"); + } + } + // it may be a message line or a stacktrace line + else { + if (!lastLine.trim().equals("")) { + if (lastLine.startsWith("\t")) { + stackTrace.add(0, lastLine.trim()); + } + else { + message.insert(0, lastLine); + } + } + } + } + } + + return result; + } + + public void destroy() + throws IOException + { + if (log != null) { + log.close(); + } + log = null; + } + +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/MultipleFileLogReader.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/MultipleFileLogReader.java new file mode 100644 index 00000000000..c83e591b47d --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/MultipleFileLogReader.java @@ -0,0 +1,278 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.logging.file.logback; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.Iterator; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.rdf4j.common.logging.LogReader; +import org.eclipse.rdf4j.common.logging.LogRecord; +import org.eclipse.rdf4j.common.logging.base.AbstractLogReader; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.rolling.RollingFileAppender; +import ch.qos.logback.core.rolling.RollingPolicy; +import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; + +/** + * Date range-enabled wrapper for FileLogReader. Reads multiple logfiles chunked + * by dates as a single log. + * + * @author alex + */ +public class MultipleFileLogReader extends AbstractLogReader implements LogReader { + + private Date startDate = null; + + private Date endDate = null; + + private Date minDate = new Date(); + + private Date maxDate = new Date(); + + private String fileNamePattern = null; + + private Vector logFiles = new Vector(); + + private Iterator logFilesIterator = null; + + private LogRecord next = null; + + private int count = 0; + + private FileLogReader currentReader = null; + + public boolean supportsDateRanges() { + return true; + } + + public void setAppender(Appender appender) { + super.setAppender(appender); + if (appender instanceof RollingFileAppender) { + RollingPolicy rp = ((RollingFileAppender)appender).getRollingPolicy(); + if (rp instanceof TimeBasedRollingPolicy) { + fileNamePattern = ((TimeBasedRollingPolicy)rp).getFileNamePattern(); + } + else { + throw new UnsupportedOperationException("Must be TimeBasedRollingPolicy!"); + } + } + else { + throw new RuntimeException( + "MultipleFileLogReader appender must be an instance of RollingFileAppender!"); + } + } + + public void init() + throws Exception + { + if (this.getAppender() == null) { + throw new RuntimeException("Appender must be set before initialization!"); + } + count = 0; + logFiles = new Vector(); + Calendar startCal = null; + Calendar endCal = null; + if (startDate != null) { + startCal = Calendar.getInstance(); + startCal.setTime(startDate); + } + if (endDate != null) { + endCal = Calendar.getInstance(); + endCal.setTime(endDate); + } + // Extracts date pattern + Pattern dfPattern = Pattern.compile("(.+)%d\\{(.+)\\}"); + Matcher dfMatcher = dfPattern.matcher(fileNamePattern); + if (!dfMatcher.matches()) { + throw new RuntimeException("Wrong filename pattern: " + fileNamePattern); + } + String dfs = dfMatcher.group(2); + SimpleDateFormat df = new SimpleDateFormat(dfs); + String spattern = new File(fileNamePattern).getName(); + spattern = spattern.replace(".", "\\."); + spattern = spattern.replace("%d{" + dfs + "}", "(.*)"); + Pattern pattern = Pattern.compile(spattern); + File dir = new File(fileNamePattern).getParentFile(); + String[] files = dir.list(new DateRangeFilenameFilter(pattern, df, startCal, endCal)); + Arrays.sort(files); + for (int i = files.length - 1; i >= 0; i--) { + File f = new File(dir, files[i]); + logFiles.add(f); + System.out.println(f.getAbsolutePath()); + } + logFilesIterator = logFiles.iterator(); + if (logFilesIterator.hasNext()) { + currentReader = new FileLogReader(logFilesIterator.next()); + currentReader.init(); + next = getNext(); + if (getOffset() > 0) + doSkip(getOffset()); + } + } + + public boolean hasNext() { + if (getLimit() == 0) { + return isMoreAvailable(); + } + return isMoreAvailable() && (count < (getOffset() + getLimit())); + } + + public boolean isMoreAvailable() { + return next != null; + } + + public LogRecord next() { + LogRecord result = next; + try { + next = getNext(); + count++; + } + catch (Exception ex) { + throw new RuntimeException("Unable to get next log record.", ex); + } + if (!hasNext()) { + try { + destroy(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + return result; + } + + private LogRecord getNext() + throws Exception + { + if (currentReader.hasNext()) { + return currentReader.next(); + } + if (logFilesIterator.hasNext()) { + currentReader = new FileLogReader(logFilesIterator.next()); + currentReader.init(); + return getNext(); + } + return null; + } + + private void doSkip(int offset) { + while (this.hasNext() && (count < offset)) { + this.next(); + } + } + + public void destroy() + throws IOException + { + if (currentReader.hasNext()) { + currentReader.destroy(); + } + } + + /** + * @return Returns the startDate. + */ + public Date getStartDate() { + return startDate; + } + + /** + * @param startDate + * The startDate to set. + */ + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + /** + * @return Returns the endDate. + */ + public Date getEndDate() { + return endDate; + } + + /** + * @param endDate + * The endDate to set. + */ + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + public Date getMaxDate() { + return this.maxDate; + } + + public Date getMinDate() { + return this.minDate; + } + + /** + * + * @author alex + */ + public class DateRangeFilenameFilter implements FilenameFilter { + + Pattern pattern; + + SimpleDateFormat df; + + Calendar startCal, endCal; + + /** + * @param pattern + * @param df + * @param startCal + * @param endCal + */ + public DateRangeFilenameFilter(Pattern pattern, SimpleDateFormat df, Calendar startCal, Calendar endCal) + { + this.pattern = pattern; + this.df = df; + this.startCal = startCal; + this.endCal = endCal; + } + + public boolean accept(File dir, String name) { + Matcher matcher = pattern.matcher(name); + if (!matcher.matches()) { + return false; + } + String ds = matcher.group(1); + Date d; + try { + d = df.parse(ds); + } + catch (ParseException e) { + e.printStackTrace(); + return false; + } + if ((maxDate == null) || (d.compareTo(maxDate) > 0)) { + maxDate = d; + } + if ((minDate == null) || (d.compareTo(minDate) < 0)) { + minDate = d; + } + Calendar cal = Calendar.getInstance(); + cal.setTime(d); + return (((startCal == null) || (cal.compareTo(startCal) >= 0)) && ((endCal == null) || (cal.compareTo(endCal) <= 0))); + } + + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/StackTracePatternLayout.java b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/StackTracePatternLayout.java new file mode 100644 index 00000000000..0c7eae8166e --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/logging/file/logback/StackTracePatternLayout.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.logging.file.logback; + +import java.util.regex.Pattern; + +import ch.qos.logback.classic.PatternLayout; + +/** + * PatternLayout that also prints stacktraces. + * + * @author Herko ter Horst + */ +public class StackTracePatternLayout extends PatternLayout { + + static final String DEFAULT_CONVERSION_PATTERN = "[%-5p] %d{ISO8601} [%t] %m%n%ex"; + + public static final Pattern DEFAULT_PARSER_PATTERN = Pattern.compile("\\[([^\\]]*)\\] ([^\\[]*)\\[([^\\]]*)\\] (.*)"); + + /** + * Construct a StacktracePatternLayout with the default conversion pattern. + */ + public StackTracePatternLayout() { + this(DEFAULT_CONVERSION_PATTERN); + } + + /** + * Construct a StacktracePatternLayout with the specified conversion pattern. + * + * @param conversionPattern + * the conversion pattern to use + * @see + * Information on Log4J conversion patterns. + */ + public StackTracePatternLayout(String conversionPattern) { + super(); + this.setPattern(conversionPattern); + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/AbstractPlatform.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/AbstractPlatform.java new file mode 100644 index 00000000000..cfdb12bef24 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/AbstractPlatform.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform; + +import java.io.File; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility base class for Platform implementations. + */ +public abstract class AbstractPlatform implements Platform { + + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + protected String whitespaceReplacement = "-"; + + protected String separatorReplacement = "-"; + + protected String colonReplacement = ""; + + public File getUserHome() { + File result = null; + + String userHome = System.getProperty("user.home"); + result = new File(userHome); + + return result; + } + + public final File getApplicationDataDir() { + File result; + String sysProp; + + if ((sysProp = System.getProperty(APPDATA_BASEDIR_PROPERTY)) != null) { + result = new File(sysProp); + } + else if ((sysProp = System.getProperty(OLD_DATADIR_PROPERTY)) != null) { + logger.info( + "Old Aduna datadir property \"{}\" detected. This property has been replaced with \"{}\". " + + "Support for the old property may be removed in a future version of this application.", + OLD_DATADIR_PROPERTY, APPDATA_BASEDIR_PROPERTY); + + result = new File(sysProp); + } + else { + result = getOSApplicationDataDir(); + } + + return result; + } + + public final File getApplicationDataDir(String applicationName) { + return new File(getApplicationDataDir(), getRelativeApplicationDataDir(applicationName)); + } + + public final File getOSApplicationDataDir(String applicationName) { + return new File(getOSApplicationDataDir(), getRelativeApplicationDataDir(applicationName)); + } + + public String getRelativeApplicationDataDir(String applicationName) { + return getRelativeApplicationDataDir(applicationName, dataDirPreserveCase(), + dataDirReplaceWhitespace(), dataDirReplaceColon()); + } + + public String getRelativeApplicationDataDir(String applicationName, boolean caseSensitive, + boolean replaceWhitespace, boolean replaceColon) + { + String result = applicationName.replace(File.separator, separatorReplacement); + + if (!caseSensitive) { + result = result.toLowerCase(); + } + if (replaceWhitespace) { + result = result.replaceAll("\\s", whitespaceReplacement); + } + if (replaceColon) { + result = result.replace(":", colonReplacement); + } + + return result; + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/DefaultPlatform.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/DefaultPlatform.java new file mode 100644 index 00000000000..7f5f6d7ba9c --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/DefaultPlatform.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform; + +import java.io.File; + +public class DefaultPlatform extends AbstractPlatform { + + public String getName() { + return "Default"; + } + + public File getOSApplicationDataDir() { + return new File("Aduna"); + } + + public boolean dataDirPreserveCase() { + return false; + } + + public boolean dataDirReplaceWhitespace() { + return false; + } + + public boolean dataDirReplaceColon() { + return false; + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/Platform.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/Platform.java new file mode 100644 index 00000000000..9230201ee37 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/Platform.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform; + +import java.io.File; + +/** + * The Platform interface defines methods that are expected to differ slightly + * between operating systems, e.g. methods for opening local files, storing + * application data, etc. + */ +public interface Platform { + + public static final String APPDATA_BASEDIR_PROPERTY = "info.aduna.platform.appdata.basedir"; + + @Deprecated + public static final String OLD_DATADIR_PROPERTY = "aduna.platform.applicationdata.dir"; + + /** + * Get a descriptive name for this platform. + */ + public String getName(); + + /** + * Returns the operating system dependend application data dir. + */ + public File getOSApplicationDataDir(); + + /** + * Returns the operating system dependend application data dir. This will be + * a sub-directory of the directory returned by the no-argument version of + * this method. + */ + public File getOSApplicationDataDir(String applicationName); + + /** + * Returns the directory for the current user. + * + * @return the current user home directory + */ + public File getUserHome(); + + /** + * Returns the directory in which Aduna applications can store their + * application-dependent data, returns 'getOSApplicationDataDir' unless the + * system property "aduna.platform.applicationdata.dir" has been set. + * + * @return the Aduna-specific application data directory + */ + public File getApplicationDataDir(); + + /** + * Returns the directory in which a specific application can store all its + * application-dependent data. This will be a sub-directory of the directory + * returned by the no-argument version of this method. Note: the directory + * might not exist yet. + * + * @see #getApplicationDataDir() + * @param applicationName + * the name of the application for which to determine the + * directory + * @return an application-specific data directory + */ + public File getApplicationDataDir(String applicationName); + + /** + * Get the directory relative to getApplicationDataDir() for the specified application. + * @param applicationName the name of the application + * @return the directory relative to getApplicationDataDir() for the specified application + */ + public String getRelativeApplicationDataDir(String applicationName); + + public boolean dataDirPreserveCase(); + + public boolean dataDirReplaceWhitespace(); + + public boolean dataDirReplaceColon(); +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/PlatformBase.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/PlatformBase.java new file mode 100644 index 00000000000..44782ff03ec --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/PlatformBase.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.platform; + +/** + * @deprecated since 4.0. Use {@link AbstractPlatform} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class PlatformBase extends AbstractPlatform { + +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/PlatformFactory.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/PlatformFactory.java new file mode 100644 index 00000000000..0db39b5d350 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/PlatformFactory.java @@ -0,0 +1,183 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform; + +import org.eclipse.rdf4j.common.platform.support.MacOSXPlatform; +import org.eclipse.rdf4j.common.platform.support.PosixGnomePlatform; +import org.eclipse.rdf4j.common.platform.support.PosixKDEPlatform; +import org.eclipse.rdf4j.common.platform.support.PosixPlatform; +import org.eclipse.rdf4j.common.platform.support.WindowsPlatform; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * PlatformFactory creates a Platform instance corresponding with the current + * platform. + */ +public class PlatformFactory { + + private static PlatformFactory sharedInstance; + + /** + * Returns the Platform instance corresponding with the current platform. + */ + public static PlatformFactory getInstance() { + if (sharedInstance == null) { + sharedInstance = new PlatformFactory(); + } + return sharedInstance; + } + + /** + * Returns the Platform instance corresponding with the current platform. + */ + public static Platform getPlatform() { + return getInstance().platform; + } + + /*-----------* + * Constants * + *-----------*/ + + public final Platform platform; + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /*--------------* + * Constructors * + *--------------*/ + + private PlatformFactory() { + platform = createPlatform(); + } + + /** + * Tries to determine the platform we're running on based on Java system + * properties and/or environment variables. See + * http://lopica.sourceforge.net/os.html for an overview. + */ + private Platform createPlatform() { + Platform platform; + + try { + String osName = System.getProperty("os.name"); + + if (osName != null) { + osName = osName.toLowerCase(); + + logger.debug("os.name = {}", osName); + + if (osName.contains("windows")) { + logger.debug("Detected Windows platform"); + platform = new WindowsPlatform(); + } + else if (osName.contains("solaris") || osName.contains("sunos") || osName.contains("linux") + || osName.contains("hp-ux")) + { + // Try to detect specific window managers + if (isGnome()) { + logger.debug("Detected Gnome window manager on Posix platform"); + platform = new PosixGnomePlatform(); + } + else if (isKDE()) { + logger.debug("Detected KDE window manager on Posix platform"); + platform = new PosixKDEPlatform(); + } + else { + logger.debug("Detected Posix platform"); + platform = new PosixPlatform(); + } + } + else if (osName.contains("mac os x") || osName.contains("macos") || osName.contains("darwin") || + System.getProperty("mrj.version") != null) { + logger.debug("Detected Mac OS X platform"); + platform = new MacOSXPlatform(); + } + else { + logger.warn("Unrecognized operating system: '{}', falling back to default platform", osName); + platform = new DefaultPlatform(); + } + } + else { + logger.warn("System property 'os.name' is null, falling back to default platform"); + platform = new DefaultPlatform(); + } + } + catch (SecurityException e) { + logger.warn("Not allowed to read system property 'os.name', falling back to default platform", e); + platform = new DefaultPlatform(); + } + + return platform; + } + + /** + * Detect gnome environments. + */ + private boolean isGnome() { + // check gdm session + String gdmSession = getSystemEnv("GDMSESSION"); + if (gdmSession != null && gdmSession.toLowerCase().contains("gnome")) { + return true; + } + + // check desktop session + String desktopSession = getSystemEnv("DESKTOP_SESSION"); + if (desktopSession != null && desktopSession.toLowerCase().contains("gnome")) { + return true; + } + + // check gnome desktop id + String gnomeDesktopSessionId = getSystemEnv("GNOME_DESKTOP_SESSION_ID"); + if (gnomeDesktopSessionId != null && gnomeDesktopSessionId.trim().length() > 0) { + return true; + } + + return false; + } + + /** + * Detect KDE environments. + */ + private boolean isKDE() { + // check gdm session + String gdmSession = getSystemEnv("GDMSESSION"); + if (gdmSession != null && gdmSession.toLowerCase().contains("kde")) { + return true; + } + + // check desktop session + String desktopSession = getSystemEnv("DESKTOP_SESSION"); + if (desktopSession != null && desktopSession.toLowerCase().contains("kde")) { + return true; + } + + // check window manager + String windowManager = getSystemEnv("WINDOW_MANAGER"); + if (windowManager != null && windowManager.trim().toLowerCase().endsWith("kde")) { + return true; + } + + return false; + } + + private String getSystemEnv(String propertyName) { + try { + return System.getenv(propertyName); + } + catch (SecurityException e) { + logger.warn("Not allowed to read environment variable '" + propertyName + "'", e); + return null; + } + } + + public static void main(String[] args) { + System.out.println(getPlatform().getApplicationDataDir("My Application: Test").getAbsolutePath()); + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/ProcessLauncher.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/ProcessLauncher.java new file mode 100644 index 00000000000..c04c9516e70 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/ProcessLauncher.java @@ -0,0 +1,317 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Iterator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Launches a process, redirecting the output of that sub-process to the output + * of this (the parent) process. + */ +public final class ProcessLauncher { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + private String commandLine; + + private String[] commandArray; + + private File baseDir; + + private ArrayList listeners = new ArrayList(1); + + private Process subProcess; + + private boolean finished = false; + + private StringBuilder out = new StringBuilder(); + + private StringBuilder err = new StringBuilder(); + + /** + * Constructs a new ProcessLauncher with the given command line. + */ + public ProcessLauncher(String commandLine) { + this(commandLine, null); + } + + public ProcessLauncher(String commandLine, File baseDir) { + this.commandLine = commandLine; + this.baseDir = baseDir; + } + + /** + * Constructs a new ProcessLauncher with the given command array. + */ + public ProcessLauncher(String[] commandArray) { + this(commandArray, null); + } + + public ProcessLauncher(String[] commandArray, File baseDir) { + this.commandArray = commandArray; + this.baseDir = baseDir; + } + + /** + * Constructs new process launcher with the given command element list. + */ + public ProcessLauncher(ArrayList commandList) { + this(commandList, null); + } + + public ProcessLauncher(ArrayList commandList, File baseDir) { + this(toStringArray(commandList), baseDir); + } + + private static String[] toStringArray(ArrayList list) { + String[] result = new String[list.size()]; + Iterator iter = list.iterator(); + int arrayIndex = 0; + while (iter.hasNext()) { + result[arrayIndex++] = iter.next().toString(); + } + return result; + } + + /** + * Classes implementing this interface can receive output generated by + * processes launched using the ProcessLauncher. + */ + public interface OutputListener { + + public void standardOutput(char[] output); + + public void errorOutput(char[] output); + } + + /** + * Add a listener for output from the to-be-launched process. + */ + public void addOutputListener(OutputListener listener) { + this.listeners.add(listener); + } + + /** fire error output event */ + private void fireErr(char[] err) { + if (this.listeners.isEmpty()) { + this.err.append(out); + } + Iterator iter = this.listeners.iterator(); + while (iter.hasNext()) { + iter.next().errorOutput(err); + } + } + + /** fire standard output event */ + private void fireOut(char[] out) { + if (this.listeners.isEmpty()) { + this.out.append(out); + } + Iterator iter = this.listeners.iterator(); + while (iter.hasNext()) { + iter.next().standardOutput(out); + } + } + + /** + * Get standard output, in case no listeners were registered - never returns + * null. + */ + public String getStandardOutput() { + if (!this.listeners.isEmpty()) { + throw new IllegalStateException("Cannot get standard output, because outputlisteners have been registered."); + } + return this.out.toString(); + } + + /** + * Get error output, in case no listeners were registered - never returns + * null. + */ + public String getErrorOutput() { + if (!this.listeners.isEmpty()) { + throw new IllegalStateException("Cannot get error output, because outputlisteners have been registered."); + } + return this.err.toString(); + } + + /** + * Get the commandline that is used to launch the process. + */ + public String getCommandLine() { + if (this.commandLine != null) { + return this.commandLine; + } + else if (this.commandArray != null) { + StringBuilder result = new StringBuilder(64); + for (int i = 0; i < this.commandArray.length; i++) { + if (i > 0) { + result.append(' '); + } + result.append(this.commandArray[i]); + } + return result.toString(); + } + else { + return null; + } + } + + /** + * Check whether execution has finished. + */ + public boolean hasFinished() { + return finished; + } + + /** + * Launches the process, and blocks until that process completes execution. + * + * @throws CommandNotExistsException + * If the command could not be executed because it does not exist + */ + public int launch() throws CommandNotExistsException { + this.err.setLength(0); + this.out.setLength(0); + BackgroundPrinter stdout = null; + BackgroundPrinter stderr = null; + try { + if (this.commandArray != null) { + this.subProcess = Runtime.getRuntime().exec(this.commandArray, null, this.baseDir); + } + else { + this.subProcess = Runtime.getRuntime().exec(this.commandLine, null, this.baseDir); + } + stdout = new BackgroundPrinter(subProcess.getInputStream(), false); + stderr = new BackgroundPrinter(subProcess.getErrorStream(), true); + stdout.start(); + stderr.start(); + // kill process and wait max 10 seconds for output to complete + int exitValue = this.subProcess.waitFor(); + stdout.join(10000); + stderr.join(10000); + if (exitValue != 0) { + logger.info("WARNING: exit value " + exitValue + " for command \"" + getCommandLine() + "\""); + } + return exitValue; + } + catch (IOException ioe) { + // usually caused if the command does not exist at all + throw new CommandNotExistsException("Command probably does not exist: " + ioe); + } + catch (Exception e) { + logger.error("Exception while running/launching \"" + getCommandLine() + "\".", e); + } + finally { + if (this.subProcess != null) { + this.subProcess.destroy(); + this.subProcess = null; + } + if (stdout != null) { + stdout.close(); + } + if (stderr != null) { + stderr.close(); + } + this.finished = true; + } + return -1; + } + + /** + * Tries to abort the currently running process. + */ + public void abort() { + if (this.subProcess != null) { + this.subProcess.destroy(); + this.subProcess = null; + } + } + + /** + * Catches output from a "java.lang.Process" and writes it to either + * System.err or System.out. + */ + private class BackgroundPrinter extends Thread { + + private InputStream in; + + boolean isErrorOutput; + + public BackgroundPrinter(InputStream in, boolean isErrorOutput) { + this.in = in; + this.isErrorOutput = isErrorOutput; + } + + public void run() { + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(this.in)); + // read buffer + char[] buf = new char[1024]; + // write data to target, until no more data is left to read + int numberOfReadBytes; + while ((numberOfReadBytes = reader.read(buf)) != -1) { + char[] clearedbuf = new char[numberOfReadBytes]; + System.arraycopy(buf, 0, clearedbuf, 0, numberOfReadBytes); + if (this.isErrorOutput) { + fireErr(clearedbuf); + } + else { + fireOut(clearedbuf); + } + } + /* + * } catch (IOException ioe) { // ignore this: process has + * ended, causing IOException } catch (NullPointerException ioe) { // + * ignore this: there was no resulting output + */ + } + catch (Exception e) { + logger.warn("Exception while reading from stream from subprocess.", e); + } + } + + public void close() { + try { + this.in.close(); + } + catch (Exception e) { + logger.warn("Closing background stream for launched process caused exception.", e); + } + } + } + + /** + * Exception that is thrown when a command could not be executed because it + * (probably) does not exist at all. + */ + public static class CommandNotExistsException extends RuntimeException { + + private static final long serialVersionUID = -3770613178610919742L; + + /** + * Construct a new exception for a command that does not exist. + * + * @param msg + * The message for this exception. + */ + public CommandNotExistsException(String msg) { + super(msg); + } + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/MacOSXPlatform.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/MacOSXPlatform.java new file mode 100644 index 00000000000..5f645c5ce60 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/MacOSXPlatform.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform.support; + +import java.io.File; + +/** + * Platform implementation for Mac OS X platforms. + */ +public class MacOSXPlatform extends PosixPlatform { + + public static final String APPLICATION_DATA = "Library/Application Support/Aduna"; + + public String getName() { + return "Mac OS X"; + } + + @Override + public File getOSApplicationDataDir() { + return new File(System.getProperty("user.home"), APPLICATION_DATA); + } + + public boolean dataDirPreserveCase() { + return true; + } + + public boolean dataDirReplaceWhitespace() { + return false; + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixGnomePlatform.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixGnomePlatform.java new file mode 100644 index 00000000000..5a9413d2131 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixGnomePlatform.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform.support; + +/** + * Platform implementation for gnome environments under UNIX. + */ +public class PosixGnomePlatform extends PosixPlatform { + + public String getName() { + return "POSIX-compatible with Gnome"; + } + +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixKDEPlatform.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixKDEPlatform.java new file mode 100644 index 00000000000..c4c77eea860 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixKDEPlatform.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform.support; + +/** + * Platform implementation for KDE environments under UNIX. + */ +public class PosixKDEPlatform extends PosixPlatform { + + public String getName() { + return "POSIX-compatible with KDE"; + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixPlatform.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixPlatform.java new file mode 100644 index 00000000000..b933c764812 --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/PosixPlatform.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform.support; + +import java.io.File; + +import org.eclipse.rdf4j.common.platform.AbstractPlatform; + +/** + * Platform implementation for *nix platforms. + */ +public class PosixPlatform extends AbstractPlatform { + + public String getName() { + return "POSIX-compatible"; + } + + public File getOSApplicationDataDir() { + return new File(System.getProperty("user.home"), ".aduna"); + } + + public boolean dataDirPreserveCase() { + return false; + } + + public boolean dataDirReplaceWhitespace() { + return true; + } + + public boolean dataDirReplaceColon() { + return false; + } +} diff --git a/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/WindowsPlatform.java b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/WindowsPlatform.java new file mode 100644 index 00000000000..da4bcd32dae --- /dev/null +++ b/core/config/src/main/java/org/eclipse/rdf4j/common/platform/support/WindowsPlatform.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.common.platform.support; + +import java.io.File; + +import org.eclipse.rdf4j.common.platform.AbstractPlatform; +import org.eclipse.rdf4j.common.platform.ProcessLauncher; + +/** + * Platform implementation for all Windows' platforms. + */ +public class WindowsPlatform extends AbstractPlatform { + + /** name of the directory containing application data */ + public static final String APPLICATION_DATA = "Application Data"; + + /** name of the app data subdirectory containing all Aduna files * */ + public static final String ADUNA_APPLICATION_DATA = "Aduna"; + + /** + * indication whether this is a windows9x platform: 0 means not initialized, + * -1 means false, 1 means true + */ + private int isWin9x = 0; + + /** + * Returns the name of this windows platform. + */ + public String getName() { + if (isWin9x()) { + return "Windows 9x"; + } + else if (isWinNT()) { + return "Windows NT"; + } + else if (isWin2000()) { + return "Windows 2000"; + } + else if (isWinXP()) { + return "Windows XP"; + } + else if (isWin2003()) { + return "Windows 2003"; + } + else if (isWinVista()) { + return "Windows Vista"; + } + else { + return "Windows"; + } + } + + public File getUserHome() { + File result = super.getUserHome(); + + String homeDrive = System.getenv("HOMEDRIVE"); + String homePath = System.getenv("HOMEPATH"); + if (homeDrive != null && homePath != null) { + File homeDir = new File(homeDrive + homePath); + if (homeDir.isDirectory() && homeDir.canWrite()) { + result = homeDir; + } + } + else { + String userProfile = System.getenv("USERPROFILE"); + if (userProfile != null) { + File userProfileDir = new File(userProfile); + if (userProfileDir.isDirectory() && userProfileDir.canWrite()) { + result = userProfileDir; + } + } + } + + return result; + } + + /** + * Returns an application data directory in the "Application Data" userdir of + * Windows. + */ + public File getOSApplicationDataDir() { + File result = new File(getUserHome(), APPLICATION_DATA); + + // check for the APPDATA environment variable + String appData = System.getenv("APPDATA"); + if (appData != null) { + File appDataDir = new File(appData); + if (appDataDir.isDirectory() && appDataDir.canWrite()) { + result = appDataDir; + } + } + + return new File(result, ADUNA_APPLICATION_DATA); + } + + /** + * Returns true when the platform is not a Windows 9x platform. + */ + public boolean warnsWhenOpeningExecutable() { + return !isWin9x() && !isWinNT() && !isWin2000(); + } + + /** + * Check whether this is windows 9x, or windows NT and higher. + */ + public boolean isWin9x() { + if (isWin9x == 0) { + // let's see if this is windows 9x + try { + ProcessLauncher launcher = new ProcessLauncher(new String[] { "cmd", "/c", "echo" }); + launcher.launch(); + isWin9x = -1; + } + catch (ProcessLauncher.CommandNotExistsException nosuchcommand) { + isWin9x = 1; + } + catch (Exception e) { + logger.error("Unexpected exception while checking isWin9x", e); + } + } + return isWin9x == 1; + } + + /** + * Check whether this is an Windows NT environment. + */ + public boolean isWinNT() { + return System.getProperty("os.name").toLowerCase().indexOf("nt") >= 0; + } + + /** + * Check whether this is an Windows 2000 environment. + */ + public boolean isWin2000() { + return System.getProperty("os.name").indexOf("2000") >= 0; + } + + /** + * Check whether this is an Windows NT environment. + */ + public boolean isWinXP() { + return System.getProperty("os.name").toLowerCase().indexOf("xp") >= 0; + } + + /** + * Check whether this is an Windows 2003 environment. + */ + public boolean isWin2003() { + return System.getProperty("os.name").indexOf("2003") >= 0; + } + + /** + * Check whether this is an Windows Vista environment. + */ + public boolean isWinVista() { + return System.getProperty("os.name").indexOf("Vista") >= 0; + } + + /** + * Returns appropriate command shell for the current windows shell. + */ + public String getCommandShell() { + if (isWin9x()) { + return "command.com"; + } + else { + return "cmd"; + } + } + + public boolean dataDirPreserveCase() { + return true; + } + + public boolean dataDirReplaceWhitespace() { + return false; + } + + public boolean dataDirReplaceColon() { + return true; + } +} diff --git a/core/config/src/main/resources/info/aduna/app/config/defaults/application.properties b/core/config/src/main/resources/info/aduna/app/config/defaults/application.properties new file mode 100644 index 00000000000..46a0a399a78 --- /dev/null +++ b/core/config/src/main/resources/info/aduna/app/config/defaults/application.properties @@ -0,0 +1,5 @@ +feature.logging.exists=true +feature.proxy.exists=true +feature.logging.impl=info.aduna.app.logging.logback.LogbackConfiguration +org.openrdf.workbench.jsonp.enabled=true +org.openrdf.workbench.jsonp.callbackparameter=callback \ No newline at end of file diff --git a/core/config/src/main/resources/info/aduna/app/config/defaults/logback.xml b/core/config/src/main/resources/info/aduna/app/config/defaults/logback.xml new file mode 100644 index 00000000000..f9393ff6d64 --- /dev/null +++ b/core/config/src/main/resources/info/aduna/app/config/defaults/logback.xml @@ -0,0 +1,19 @@ + + + + ${info.aduna.logging.dir}/main.log + + ${info.aduna.logging.dir}/main-%d{yyyy-MM-dd}.log + + + + UTF-8 + + + + + + + + + diff --git a/core/config/src/main/resources/info/aduna/app/config/defaults/logging.properties b/core/config/src/main/resources/info/aduna/app/config/defaults/logging.properties new file mode 100644 index 00000000000..7e512457452 --- /dev/null +++ b/core/config/src/main/resources/info/aduna/app/config/defaults/logging.properties @@ -0,0 +1,3 @@ +logging.debug.enabled=false +packages.slf4j=info.aduna,org.openrdf,org.semanticdesktop.aperture +packages.jul=org.quartz \ No newline at end of file diff --git a/core/config/src/main/resources/info/aduna/app/config/defaults/proxy.properties b/core/config/src/main/resources/info/aduna/app/config/defaults/proxy.properties new file mode 100644 index 00000000000..bfcf1ef819c --- /dev/null +++ b/core/config/src/main/resources/info/aduna/app/config/defaults/proxy.properties @@ -0,0 +1 @@ +proxies.enabled=false \ No newline at end of file diff --git a/core/config/src/test/java/org/eclipse/rdf4j/common/app/AppVersionTest.java b/core/config/src/test/java/org/eclipse/rdf4j/common/app/AppVersionTest.java new file mode 100644 index 00000000000..a33222295e5 --- /dev/null +++ b/core/config/src/test/java/org/eclipse/rdf4j/common/app/AppVersionTest.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.app; + +import static org.junit.Assert.*; + +import org.eclipse.rdf4j.common.app.AppVersion; +import org.junit.Test; + + +/** + * + * @author jeen + */ +public class AppVersionTest { + + @Test + public void testCreateFromString() throws Exception { + AppVersion v = AppVersion.parse("1.0.3"); + + assertEquals(1, v.getMajor()); + assertEquals(0, v.getMinor()); + assertEquals(3, v.getMicro()); + assertNull(v.getModifier()); + + v = AppVersion.parse("2.8.0-beta3-SNAPSHOT"); + assertEquals(2, v.getMajor()); + assertEquals(8, v.getMinor()); + assertEquals(0, v.getMicro()); + assertEquals("beta3-SNAPSHOT", v.getModifier()); + } + +} diff --git a/core/console/pom.xml b/core/console/pom.xml new file mode 100644 index 00000000000..b360742b865 --- /dev/null +++ b/core/console/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-core + 4.1.0-SNAPSHOT + + + rdf4j-console + + RDF4J: Console + Command line user interface to RDF4J repositories. + + + + ${project.groupId} + rdf4j-runtime + ${project.version} + + + ${project.groupId} + rdf4j-query + ${project.version} + + + ${project.groupId} + rdf4j-queryparser-serql + ${project.version} + + + ${project.groupId} + rdf4j-queryparser-sparql + ${project.version} + + + ${project.groupId} + rdf4j-rio-ntriples + ${project.version} + + + ${project.groupId} + rdf4j-config + ${project.version} + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + ch.qos.logback + logback-classic + runtime + + + + junit + junit + 4.11 + test + + + + org.mockito + mockito-core + 1.9.5 + test + + + commons-cli + commons-cli + + + org.slf4j + jcl-over-slf4j + runtime + true + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.openrdf.console.Console + org.openrdf.console + true + + + + + + + + + + diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Clear.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Clear.java new file mode 100644 index 00000000000..7bba45c5f50 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Clear.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.IOException; + +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.RepositoryReadOnlyException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dale Visser + */ +public class Clear implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Clear.class); + + private final ConsoleIO consoleIO; + + private final ConsoleState state; + + private final LockRemover lockRemover; + + Clear(ConsoleIO consoleIO, ConsoleState state, LockRemover lockRemover) { + this.consoleIO = consoleIO; + this.state = state; + this.lockRemover = lockRemover; + } + + public void execute(String... tokens) { + Repository repository = state.getRepository(); + if (repository == null) { + consoleIO.writeUnopenedError(); + } + else { + final ValueFactory valueFactory = repository.getValueFactory(); + Resource[] contexts = new Resource[tokens.length - 1]; + for (int i = 1; i < tokens.length; i++) { + final String contextID = tokens[i]; + if (contextID.equalsIgnoreCase("null")) { + contexts[i - 1] = null; // NOPMD + } + else if (contextID.startsWith("_:")) { + contexts[i - 1] = valueFactory.createBNode(contextID.substring(2)); + } + else { + try { + contexts[i - 1] = valueFactory.createIRI(contextID); + } + catch (IllegalArgumentException e) { + consoleIO.writeError("illegal URI: " + contextID); + consoleIO.writeln(PrintHelp.CLEAR); + return; + } + } + } + clear(repository, contexts); + } + } + + private void clear(Repository repository, Resource[] contexts) { + if (contexts.length == 0) { + consoleIO.writeln("Clearing repository..."); + } + else { + consoleIO.writeln("Removing specified contexts..."); + } + try { + final RepositoryConnection con = repository.getConnection(); + try { + con.clear(contexts); + if (contexts.length == 0) { + con.clearNamespaces(); + } + } + finally { + con.close(); + } + } + catch (RepositoryReadOnlyException e) { + try { + if (lockRemover.tryToRemoveLock(repository)) { + this.clear(repository, contexts); + } + else { + consoleIO.writeError("Failed to clear repository"); + LOGGER.error("Failed to clear repository", e); + } + } + catch (RepositoryException e1) { + consoleIO.writeError("Unable to restart repository: " + e1.getMessage()); + LOGGER.error("Unable to restart repository", e1); + } + catch (IOException e1) { + consoleIO.writeError("Unable to remove lock: " + e1.getMessage()); + } + } + catch (RepositoryException e) { + consoleIO.writeError("Failed to clear repository: " + e.getMessage()); + LOGGER.error("Failed to clear repository", e); + } + } + +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Close.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Close.java new file mode 100644 index 00000000000..7123d5bfd0d --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Close.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import org.eclipse.rdf4j.repository.Repository; + +/** + * @author Dale Visser + */ +public class Close implements Command { + + private final ConsoleIO consoleIO; + + private final ConsoleState appInfo; + + Close(ConsoleIO consoleIO, ConsoleState appInfo) { + this.consoleIO = consoleIO; + this.appInfo = appInfo; + } + + public void execute(String... tokens) { + if (tokens.length == 1) { + closeRepository(true); + } + else { + consoleIO.writeln(PrintHelp.CLOSE); + } + } + + protected void closeRepository(final boolean verbose) { + final Repository repository = this.appInfo.getRepository(); + if (repository == null) { + if (verbose) { + consoleIO.writeln("There are no open repositories that can be closed"); + } + } + else { + consoleIO.writeln("Closing repository '" + this.appInfo.getRepositoryID() + "'..."); + this.appInfo.setRepository(null); + this.appInfo.setRepositoryID(null); + } + } + +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Command.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Command.java new file mode 100644 index 00000000000..652735da3a9 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Command.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.IOException; + +/** + * Abstraction of console commands. + * + * @author Dale Visser + */ +public interface Command { + + /** + * Execute the given parameters. + * + * @param parameters + * parameters typed by user + * @throws IOException + * if a problem occurs reading or writing + */ + void execute(String... parameters) throws IOException; +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Connect.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Connect.java new file mode 100644 index 00000000000..75ec9f8bd26 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Connect.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.rdf4j.http.client.SesameClient; +import org.eclipse.rdf4j.http.client.SesameClientImpl; +import org.eclipse.rdf4j.http.client.SesameSession; +import org.eclipse.rdf4j.http.protocol.UnauthorizedException; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.manager.LocalRepositoryManager; +import org.eclipse.rdf4j.repository.manager.RemoteRepositoryManager; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author dale + */ +public class Connect implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Connect.class); + + private final ConsoleState appInfo; + + private final ConsoleIO consoleIO; + + private final Disconnect disconnect; + + Connect(ConsoleIO consoleIO, ConsoleState info, Disconnect disconnect) { + super(); + this.consoleIO = consoleIO; + this.appInfo = info; + this.disconnect = disconnect; + } + + public void execute(String... tokens) { + if (tokens.length < 2) { + consoleIO.writeln(PrintHelp.CONNECT); + return; + } + final String target = tokens[1]; + if ("default".equalsIgnoreCase(target)) { + connectDefault(); + } + else { + try { + new URL(target); + // target is a valid URL + final String username = (tokens.length > 2) ? tokens[2] : null; // NOPMD + final String password = (tokens.length > 3) ? tokens[3] : null; // NOPMD + connectRemote(target, username, password); + } + catch (MalformedURLException e) { + // assume target is a directory path + connectLocal(target); + } + } + } + + protected boolean connectDefault() { + return installNewManager(new LocalRepositoryManager(this.appInfo.getDataDirectory()), + "default data directory"); + } + + private boolean connectRemote(final String url, final String user, final String passwd) { + final String pass = (passwd == null) ? "" : passwd; + boolean result = false; + try { + // Ping server + final SesameClient client = new SesameClientImpl(); + try { + SesameSession httpClient = client.createSesameSession(url); + + if (user != null) { + httpClient.setUsernameAndPassword(user, pass); + } + + // Ping the server + httpClient.getServerProtocol(); + } + finally { + client.shutDown(); + } + final RemoteRepositoryManager manager = new RemoteRepositoryManager(url); + manager.setUsernameAndPassword(user, pass); + result = installNewManager(manager, url); + } + catch (UnauthorizedException e) { + if (user != null && pass.length() > 0) { + consoleIO.writeError("Authentication for user '" + user + "' failed"); + LOGGER.warn("Authentication for user '" + user + "' failed", e); + } + else { + // Ask user for credentials + try { + consoleIO.writeln("Authentication required"); + final String username = consoleIO.readln("Username:"); + final String password = consoleIO.readPassword("Password:"); + connectRemote(url, username, password); + } + catch (IOException ioe) { + consoleIO.writeError("Failed to read user credentials"); + LOGGER.warn("Failed to read user credentials", ioe); + } + } + } + catch (IOException e) { + consoleIO.writeError("Failed to access the server: " + e.getMessage()); + LOGGER.warn("Failed to access the server", e); + } + catch (RepositoryException e) { + consoleIO.writeError("Failed to access the server: " + e.getMessage()); + LOGGER.warn("Failed to access the server", e); + } + + return result; + } + + protected boolean connectLocal(final String path) { + final File dir = new File(path); + boolean result = false; + if (dir.exists() && dir.isDirectory()) { + result = installNewManager(new LocalRepositoryManager(dir), dir.toString()); + } + else { + consoleIO.writeError("Specified path is not an (existing) directory: " + path); + } + return result; + } + + private boolean installNewManager(final RepositoryManager newManager, final String newManagerID) { + boolean installed = false; + final String managerID = this.appInfo.getManagerID(); + if (newManagerID.equals(managerID)) { + consoleIO.writeln("Already connected to " + managerID); + installed = true; + } + else { + try { + newManager.initialize(); + disconnect.execute(false); + this.appInfo.setManager(newManager); + this.appInfo.setManagerID(newManagerID); + consoleIO.writeln("Connected to " + newManagerID); + installed = true; + } + catch (RepositoryException e) { + consoleIO.writeError(e.getMessage()); + LOGGER.error("Failed to install new manager", e); + } + } + return installed; + } + + protected boolean connectRemote(final String url) { + return connectRemote(url, null, null); + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Console.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Console.java new file mode 100644 index 00000000000..24f8050c988 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Console.java @@ -0,0 +1,386 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.cli.AlreadySelectedException; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.PosixParser; +import org.eclipse.rdf4j.Sesame; +import org.eclipse.rdf4j.common.app.AppConfiguration; +import org.eclipse.rdf4j.common.app.AppVersion; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; + +/** + * The RDF4J Console is a command-line application for interacting with RDF4J. + * It reads commands from standard input and prints feedback to standard output. + * Available options include loading and querying of data in repositories, + * repository creation and verification of RDF files. + * + * @author Jeen Broekstra + * @author Arjohn Kampman + */ +public class Console implements ConsoleState, ConsoleParameters { + + /*------------------* + * Static constants * + *------------------*/ + + private static final AppVersion VERSION = AppVersion.parse(Sesame.getVersion()); + + private static final String APP_NAME = "RDF4J Console"; + + private static boolean exitOnError; + + /*-----------* + * Constants * + *-----------*/ + + private final AppConfiguration appConfig = new AppConfiguration(APP_NAME, APP_NAME, VERSION); + + /*-----------* + * Variables * + *-----------*/ + + private RepositoryManager manager; + + private String managerID; + + private Repository repository; + + private String repositoryID; + + private final ConsoleIO consoleIO; + + private int consoleWidth = 80; + + private boolean showPrefix = true; + + private boolean queryPrefix = false; + + /*----------------* + * Static methods * + *----------------*/ + + public static void main(final String[] args) + throws IOException + { + final Console console = new Console(); + final Option helpOption = new Option("h", "help", false, "print this help"); + final Option versionOption = new Option("v", "version", false, "print version information"); + final Option serverURLOption = new Option("s", "serverURL", true, + "URL of Sesame server to connect to, e.g. http://localhost/openrdf-sesame/"); + final Option dirOption = new Option("d", "dataDir", true, "data dir to 'connect' to"); + Option echoOption = new Option("e", "echo", false, + "echoes input back to stdout, useful for logging script sessions"); + Option quietOption = new Option("q", "quiet", false, "suppresses prompts, useful for scripting"); + Option forceOption = new Option("f", "force", false, + "always answer yes to (suppressed) confirmation prompts"); + Option cautiousOption = new Option("c", "cautious", false, + "always answer no to (suppressed) confirmation prompts"); + Option exitOnErrorMode = new Option("x", "exitOnError", false, + "immediately exit the console on the first error"); + final Options options = new Options(); + OptionGroup cautionGroup = new OptionGroup().addOption(cautiousOption).addOption(forceOption).addOption( + exitOnErrorMode); + OptionGroup locationGroup = new OptionGroup().addOption(serverURLOption).addOption(dirOption); + options.addOptionGroup(locationGroup).addOptionGroup(cautionGroup); + options.addOption(helpOption).addOption(versionOption).addOption(echoOption).addOption(quietOption); + CommandLine commandLine = parseCommandLine(args, console, options); + handleInfoOptions(console, helpOption, versionOption, options, commandLine); + console.consoleIO.setEcho(commandLine.hasOption(echoOption.getOpt())); + console.consoleIO.setQuiet(commandLine.hasOption(quietOption.getOpt())); + exitOnError = commandLine.hasOption(exitOnErrorMode.getOpt()); + String location = handleOptionGroups(console, serverURLOption, dirOption, forceOption, cautiousOption, + options, cautionGroup, locationGroup, commandLine); + final String[] otherArgs = commandLine.getArgs(); + if (otherArgs.length > 1) { + printUsage(console.consoleIO, options); + System.exit(1); + } + connectAndOpen(console, locationGroup.getSelected(), location, otherArgs); + console.start(); + } + + private static String handleOptionGroups(final Console console, final Option serverURLOption, + final Option dirOption, Option forceOption, Option cautiousOption, final Options options, + OptionGroup cautionGroup, OptionGroup locationGroup, CommandLine commandLine) + { + String location = null; + try { + if (commandLine.hasOption(forceOption.getOpt())) { + cautionGroup.setSelected(forceOption); + console.consoleIO.setForce(); + } + if (commandLine.hasOption(cautiousOption.getOpt())) { + cautionGroup.setSelected(cautiousOption); + console.consoleIO.setCautious(); + } + if (commandLine.hasOption(dirOption.getOpt())) { + locationGroup.setSelected(dirOption); + location = commandLine.getOptionValue(dirOption.getOpt()); + } + if (commandLine.hasOption(serverURLOption.getOpt())) { + locationGroup.setSelected(serverURLOption); + location = commandLine.getOptionValue(serverURLOption.getOpt()); + } + } + catch (AlreadySelectedException e) { + printUsage(console.consoleIO, options); + System.exit(3); + } + return location; + } + + private static CommandLine parseCommandLine(final String[] args, final Console console, + final Options options) + { + CommandLine commandLine = null; + try { + commandLine = new PosixParser().parse(options, args); + } + catch (ParseException e) { + console.consoleIO.writeError(e.getMessage()); + System.exit(1); + } + return commandLine; + } + + private static void handleInfoOptions(final Console console, final Option helpOption, + final Option versionOption, final Options options, final CommandLine commandLine) + { + if (commandLine.hasOption(helpOption.getOpt())) { + printUsage(console.consoleIO, options); + System.exit(0); + } + if (commandLine.hasOption(versionOption.getOpt())) { + console.consoleIO.writeln(console.appConfig.getFullName()); + System.exit(0); + } + } + + private static void connectAndOpen(Console console, String selectedLocationOption, String location, + String[] otherArgs) + { + boolean connected; + if ("s".equals(selectedLocationOption)) { + connected = console.connect.connectRemote(location); + } + else if ("d".equals(selectedLocationOption)) { + connected = console.connect.connectLocal(location); + } + else { + connected = console.connect.connectDefault(); + } + if (!connected) { + System.exit(2); + } + if (otherArgs.length > 0) { + console.open.openRepository(otherArgs[0]); + } + } + + private static void printUsage(ConsoleIO cio, Options options) { + cio.writeln("Sesame Console, an interactive shell based utility to communicate with Sesame repositories."); + final HelpFormatter formatter = new HelpFormatter(); + formatter.setWidth(80); + formatter.printHelp("start-console [OPTION] [repositoryID]", options); + cio.writeln(); + cio.writeln("For bug reports and suggestions, see http://www.openrdf.org/"); + } + + private final Map commandMap = new HashMap(); + + private final Connect connect; + + private final Disconnect disconnect; + + private final Open open; + + private final QueryEvaluator queryEvaluator; + + public Console() + throws IOException + { + appConfig.init(); + consoleIO = new ConsoleIO(new BufferedReader(new InputStreamReader(System.in)), System.out, System.err, + this); + commandMap.put("federate", new Federate(consoleIO, this)); + this.queryEvaluator = new QueryEvaluator(consoleIO, this, this); + LockRemover lockRemover = new LockRemover(consoleIO); + Close close = new Close(consoleIO, this); + commandMap.put("close", close); + this.disconnect = new Disconnect(consoleIO, this, close); + commandMap.put("help", new PrintHelp(consoleIO)); + commandMap.put("info", new PrintInfo(consoleIO, this)); + this.connect = new Connect(consoleIO, this, disconnect); + commandMap.put("connect", connect); + commandMap.put("create", new Create(consoleIO, this, lockRemover)); + commandMap.put("drop", new Drop(consoleIO, this, close, lockRemover)); + this.open = new Open(consoleIO, this, close, lockRemover); + commandMap.put("open", open); + commandMap.put("show", new Show(consoleIO, this)); + commandMap.put("load", new Load(consoleIO, this, lockRemover)); + commandMap.put("verify", new Verify(consoleIO)); + commandMap.put("clear", new Clear(consoleIO, this, lockRemover)); + commandMap.put("set", new SetParameters(consoleIO, this)); + } + + public void start() + throws IOException + { + consoleIO.writeln("Sesame Console, an interactive shell to communicate with Sesame repositories."); + consoleIO.writeln(); + consoleIO.writeln("Type 'help' for help."); + int exitCode = 0; + try { + boolean exitFlag = false; + while (!exitFlag) { + final String command = consoleIO.readCommand(); + if (command == null) { + // EOF + break; + } + exitFlag = executeCommand(command); + if (exitOnError && consoleIO.wasErrorWritten()) { + exitCode = 2; + exitFlag = true; + } + } + } + finally { + disconnect.execute(false); + } + if (exitCode != 0) { + System.exit(exitCode); + } + consoleIO.writeln("Bye"); + } + + private boolean executeCommand(final String command) + throws IOException + { + boolean exit = false; + + // only try to parse the command if non-empty. + if (0 < command.length()) { + final String[] tokens = parse(command); + final String operation = tokens[0].toLowerCase(Locale.ENGLISH); + exit = "quit".equals(operation) || "exit".equals(operation); + if (!exit) { + if (commandMap.containsKey(operation)) { + commandMap.get(operation).execute(tokens); + } + else if ("disconnect".equals(operation)) { + disconnect.execute(true); + } + else { + queryEvaluator.executeQuery(command, operation); + } + } + } + + return exit; + } + + private String[] parse(final String command) { + final Pattern pattern = Pattern.compile("\"([^\"]*)\"|(\\S+)"); + final Matcher matcher = pattern.matcher(command); + final List tokens = new ArrayList(); + while (matcher.find()) { + if (matcher.group(1) == null) { + tokens.add(matcher.group()); + } + else { + tokens.add(matcher.group(1)); + } + } + return tokens.toArray(new String[tokens.size()]); + } + + public String getApplicationName() { + return this.appConfig.getFullName(); + } + + public File getDataDirectory() { + return this.appConfig.getDataDir(); + } + + public String getManagerID() { + return this.managerID; + } + + public String getRepositoryID() { + return this.repositoryID; + } + + public RepositoryManager getManager() { + return this.manager; + } + + public void setManager(RepositoryManager manager) { + this.manager = manager; + } + + public void setManagerID(String managerID) { + this.managerID = managerID; + } + + public Repository getRepository() { + return this.repository; + } + + public void setRepositoryID(String repositoryID) { + this.repositoryID = repositoryID; + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public int getWidth() { + return this.consoleWidth; + } + + public void setWidth(int width) { + this.consoleWidth = width; + } + + public boolean isShowPrefix() { + return this.showPrefix; + } + + public void setShowPrefix(boolean value) { + this.showPrefix = value; + } + + public boolean isQueryPrefix() { + return this.queryPrefix; + } + + public void setQueryPrefix(boolean value) { + this.queryPrefix = value; + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleIO.java b/core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleIO.java new file mode 100644 index 00000000000..95024c662f2 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleIO.java @@ -0,0 +1,205 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintStream; + +import org.eclipse.rdf4j.rio.RDFParseException; + +/** + * @author Dale Visser + */ +class ConsoleIO { + + private static final String PLEASE_OPEN_FIRST = "please open a repository first"; + + private final BufferedReader input; + + private final PrintStream out, err; + + private final ConsoleState appInfo; + + private boolean echo = false; + + private boolean quiet = false; + + private boolean force = false; + + private boolean cautious = false; + + private boolean errorWritten; + + ConsoleIO(BufferedReader input, PrintStream out, PrintStream err, ConsoleState info) { + this.input = input; + this.out = out; + this.err = err; + this.appInfo = info; + } + + protected String readCommand() throws IOException { + String repositoryID = appInfo.getRepositoryID(); + if (!quiet) { + if (repositoryID != null) { + write(repositoryID); + } + write("> "); + } + String line = input.readLine().trim(); + if (line.endsWith(".")) { + line = line.substring(0, line.length() - 1); + } + return line; + } + + /** + * Reads multiple lines from the input until a line that with a '.' on its own is + * read. + */ + protected String readMultiLineInput() + throws IOException + { + String line = input.readLine(); + String result = null; + if (line != null) { + final StringBuilder buf = new StringBuilder(256); + buf.append(line); + while (line != null && !(line.length() == 1 && line.endsWith("."))) { + line = input.readLine(); + buf.append('\n'); + buf.append(line); + } + + // Remove closing dot + buf.setLength(buf.length() - 1); + result = buf.toString().trim(); + } + if (echo) { + writeln(result); + } + return result; + } + + protected String readln(String... message) + throws IOException + { + if (!quiet && message.length > 0) { + String prompt = message[0]; + if (prompt != null) { + write(prompt + " "); + } + } + String result = input.readLine(); + if (echo) { + writeln(result); + } + return result; + } + + protected String readPassword(final String message) + throws IOException + { + // TODO: Proper password reader + String result = readln(message); + if (echo && !result.isEmpty()) { + writeln("************"); + } + return result; + } + + protected void write(final String string) { + out.print(string); + } + + protected void writeln() { + out.println(); + } + + protected void writeln(final String string) { + out.println(string); + } + + protected void writeError(final String errMsg) { + err.println(errMsg); + errorWritten = true; + } + + protected void writeUnopenedError() { + writeError(PLEASE_OPEN_FIRST); + } + + protected void writeParseError(final String prefix, final long lineNo, final long colNo, final String msg) { + String locationString = RDFParseException.getLocationString(lineNo, colNo); + int locSize = locationString.length(); + final StringBuilder builder = new StringBuilder(locSize + prefix.length() + msg.length() + 3); + builder.append(prefix).append(": ").append(msg); + if (locSize > 0) { + builder.append(" ").append(locationString); + } + writeError(builder.toString()); + } + + protected boolean askProceed(final String msg, final boolean defaultValue) + throws IOException + { + final String defaultString = defaultValue ? "yes" : "no"; + boolean result = force ? true : (cautious ? false : defaultValue); + if (!force && !cautious) { + while (true) { + writeln(msg); + write("Proceed? (yes|no) [" + defaultString + "]: "); + final String reply = readln(); + if ("no".equalsIgnoreCase(reply) || "no.".equalsIgnoreCase(reply)) { + result = false; + break; + } + else if ("yes".equalsIgnoreCase(reply) || "yes.".equalsIgnoreCase(reply)) { + result = true; + break; + } + else if (reply.trim().isEmpty()) { + break; + } + } + } + return result; + } + + /** + * @param echo + * whether to echo user input to output stream + */ + protected void setEcho(boolean echo) { + this.echo = echo; + } + + /** + * @param quiet + * whether to suppress printing of prompts to output + */ + public void setQuiet(boolean quiet) { + this.quiet = quiet; + } + + /** + */ + public void setForce() { + this.force = true; + } + + /** + */ + public void setCautious() { + this.cautious = true; + } + + public boolean wasErrorWritten() { + return errorWritten; + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleParameters.java b/core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleParameters.java new file mode 100644 index 00000000000..ed25ca4630f --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleParameters.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +/** + * @author dale + */ +public interface ConsoleParameters { + + int getWidth(); + + void setWidth(int width); + + boolean isShowPrefix(); + + void setShowPrefix(boolean value); + + boolean isQueryPrefix(); + + void setQueryPrefix(boolean value); +} \ No newline at end of file diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleState.java b/core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleState.java new file mode 100644 index 00000000000..04bb11eb7dd --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/ConsoleState.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.File; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; + +/** + * @author Dale Visser + */ +public interface ConsoleState { + + String getApplicationName(); + + File getDataDirectory(); + + String getManagerID(); + + String getRepositoryID(); + + RepositoryManager getManager(); + + void setManager(RepositoryManager manager); + + void setManagerID(String managerID); + + Repository getRepository(); + + void setRepositoryID(String repositoryID); + + void setRepository(Repository repository); +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Create.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Create.java new file mode 100644 index 00000000000..f2ad8cd0144 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Create.java @@ -0,0 +1,202 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.util.Models; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryReadOnlyException; +import org.eclipse.rdf4j.repository.config.ConfigTemplate; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigSchema; +import org.eclipse.rdf4j.repository.config.RepositoryConfigUtil; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dale Visser + */ +public class Create implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Create.class); + + private static final String TEMPLATES_DIR = "templates"; + + private final ConsoleIO consoleIO; + + private final ConsoleState state; + + private final LockRemover lockRemover; + + Create(ConsoleIO consoleIO, ConsoleState state, LockRemover lockRemover) { + this.consoleIO = consoleIO; + this.state = state; + this.lockRemover = lockRemover; + } + + public void execute(String... tokens) + throws IOException + { + if (tokens.length < 2) { + consoleIO.writeln(PrintHelp.CREATE); + } + else { + createRepository(tokens[1]); + } + } + + private void createRepository(final String templateName) + throws IOException + { + try { + // FIXME: remove assumption of .ttl extension + final String templateFileName = templateName + ".ttl"; + final File templatesDir = new File(state.getDataDirectory(), TEMPLATES_DIR); + final File templateFile = new File(templatesDir, templateFileName); + InputStream templateStream = createTemplateStream(templateName, templateFileName, templatesDir, + templateFile); + if (templateStream != null) { + String template; + try { + template = IOUtil.readString(new InputStreamReader(templateStream, "UTF-8")); + } + finally { + templateStream.close(); + } + final ConfigTemplate configTemplate = new ConfigTemplate(template); + final Map valueMap = new HashMap(); + final Map> variableMap = configTemplate.getVariableMap(); + boolean eof = inputParameters(valueMap, variableMap, configTemplate.getMultilineMap()); + if (!eof) { + final String configString = configTemplate.render(valueMap); + final Repository systemRepo = this.state.getManager().getSystemRepository(); + final Model graph = new LinkedHashModel(); + final RDFParser rdfParser = Rio.createParser(RDFFormat.TURTLE, systemRepo.getValueFactory()); + rdfParser.setRDFHandler(new StatementCollector(graph)); + rdfParser.parse(new StringReader(configString), RepositoryConfigSchema.NAMESPACE); + final Resource repositoryNode = Models.subject( + graph.filter(null, RDF.TYPE, RepositoryConfigSchema.REPOSITORY)).orElseThrow( + () -> new RepositoryConfigException("missing repository node")); + final RepositoryConfig repConfig = RepositoryConfig.create(graph, repositoryNode); + repConfig.validate(); + boolean proceed = RepositoryConfigUtil.hasRepositoryConfig(systemRepo, repConfig.getID()) + ? consoleIO.askProceed( + "WARNING: you are about to overwrite the configuration of an existing repository!", + false) + : true; + if (proceed) { + try { + RepositoryConfigUtil.updateRepositoryConfigs(systemRepo, repConfig); + consoleIO.writeln("Repository created"); + } + catch (RepositoryReadOnlyException e) { + if (lockRemover.tryToRemoveLock(systemRepo)) { + RepositoryConfigUtil.updateRepositoryConfigs(systemRepo, repConfig); + consoleIO.writeln("Repository created"); + } + else { + consoleIO.writeError("Failed to create repository"); + LOGGER.error("Failed to create repository", e); + } + } + } + else { + consoleIO.writeln("Create aborted"); + } + } + } + } + catch (Exception e) { + consoleIO.writeError(e.getClass().getName() + ": " + e.getMessage()); + LOGGER.error("Failed to create repository", e); + } + } + + private boolean inputParameters(final Map valueMap, + final Map> variableMap, Map multilineInput) + throws IOException + { + if (!variableMap.isEmpty()) { + consoleIO.writeln("Please specify values for the following variables:"); + } + boolean eof = false; + for (Map.Entry> entry : variableMap.entrySet()) { + final String var = entry.getKey(); + final List values = entry.getValue(); + consoleIO.write(var); + if (values.size() > 1) { + consoleIO.write(" ("); + for (int i = 0; i < values.size(); i++) { + if (i > 0) { + consoleIO.write("|"); + } + consoleIO.write(values.get(i)); + } + consoleIO.write(")"); + } + if (!values.isEmpty()) { + consoleIO.write(" [" + values.get(0) + "]"); + } + consoleIO.write(": "); + String value = multilineInput.containsKey(var) ? consoleIO.readMultiLineInput() : consoleIO.readln(); + eof = (value == null); + if (eof) { + break; // for loop + } + value = value.trim(); + if (value.length() == 0) { + value = null; // NOPMD + } + valueMap.put(var, value); + } + return eof; + } + + private InputStream createTemplateStream(final String templateName, final String templateFileName, + final File templatesDir, final File templateFile) + throws FileNotFoundException + { + InputStream templateStream = null; + if (templateFile.exists()) { + if (templateFile.canRead()) { + templateStream = new FileInputStream(templateFile); + } + else { + consoleIO.writeError("Not allowed to read template file: " + templateFile); + } + } + else { + // Try class path for built-ins + templateStream = RepositoryConfig.class.getResourceAsStream(templateFileName); + if (templateStream == null) { + consoleIO.writeError("No template called " + templateName + " found in " + templatesDir); + } + } + return templateStream; + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Disconnect.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Disconnect.java new file mode 100644 index 00000000000..b2de41b21e5 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Disconnect.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import org.eclipse.rdf4j.repository.manager.RepositoryManager; + + +/** + * + * @author Dale Visser + */ +public class Disconnect { + + private final ConsoleIO consoleIO; + private final ConsoleState appInfo; + private final Close close; + + Disconnect(ConsoleIO consoleIO, ConsoleState appInfo, Close close){ + this.consoleIO = consoleIO; + this.appInfo = appInfo; + this.close = close; + } + + public void execute(boolean verbose) { + final RepositoryManager manager = this.appInfo.getManager(); + if (manager == null) { + if (verbose) { + consoleIO.writeln("Already disconnected"); + } + } + else { + close.closeRepository(false); + consoleIO.writeln("Disconnecting from " + this.appInfo.getManagerID()); + manager.shutDown(); + appInfo.setManager(null); + appInfo.setManagerID(null); + } + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Drop.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Drop.java new file mode 100644 index 00000000000..1c1ed1d1365 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Drop.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.IOException; + +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.RepositoryReadOnlyException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dale Visser + */ +public class Drop implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Drop.class); + + private final ConsoleIO consoleIO; + + private final ConsoleState state; + + private final Close close; + + private final LockRemover lockRemover; + + Drop(ConsoleIO consoleIO, ConsoleState state, Close close, LockRemover lockRemover) { + this.consoleIO = consoleIO; + this.state = state; + this.close = close; + this.lockRemover = lockRemover; + } + + public void execute(String... tokens) + throws IOException + { + if (tokens.length < 2) { + consoleIO.writeln(PrintHelp.DROP); + } + else { + final String repoID = tokens[1]; + try { + dropRepository(repoID); + } + catch (RepositoryConfigException e) { + consoleIO.writeError("Unable to drop repository '" + repoID + "': " + e.getMessage()); + LOGGER.warn("Unable to drop repository '" + repoID + "'", e); + } + catch (RepositoryReadOnlyException e) { + try { + if (lockRemover.tryToRemoveLock(state.getManager().getSystemRepository())) { + execute(tokens); + } + else { + consoleIO.writeError("Failed to drop repository"); + LOGGER.error("Failed to drop repository", e); + } + } + catch (RepositoryException e2) { + consoleIO.writeError("Failed to restart system: " + e2.getMessage()); + LOGGER.error("Failed to restart system", e2); + } + } + catch (RepositoryException e) { + consoleIO.writeError("Failed to update configuration in system repository: " + e.getMessage()); + LOGGER.warn("Failed to update configuration in system repository", e); + } + } + } + + private void dropRepository(final String repoID) + throws IOException, RepositoryException, RepositoryConfigException + { + boolean proceed = consoleIO.askProceed("WARNING: you are about to drop repository '" + repoID + + "'.", true); + if (proceed && !state.getManager().isSafeToRemove(repoID)) { + proceed = consoleIO.askProceed("WARNING: dropping this repository may break another that is proxying it.", false); + } + if (proceed) { + if (repoID.equals(state.getRepositoryID())) { + close.closeRepository(false); + } + final boolean isRemoved = state.getManager().removeRepository(repoID); + if (isRemoved) { + consoleIO.writeln("Dropped repository '" + repoID + "'"); + } + else { + consoleIO.writeln("Unknown repository '" + repoID + "'"); + } + } + else { + consoleIO.writeln("Drop aborted"); + } + } + +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Federate.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Federate.java new file mode 100644 index 00000000000..ec7a22d02d4 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Federate.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedList; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.eclipse.rdf4j.runtime.RepositoryManagerFederator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implements the 'federate' command for the Sesame Console. + * + * @author Dale Visser + */ +public class Federate implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Federate.class); + + private final ConsoleIO cio; + + private final ConsoleState state; + + protected Federate(ConsoleIO cio, ConsoleState state) { + this.cio = cio; + this.state = state; + } + + /** + * Executes a 'federate' command for the Sesame Console. + * + * @param parameters + * the expectations for the tokens in this array are fully documented + * in {@link PrintHelp#FEDERATE}. + */ + @Override + public void execute(String... parameters) + throws IOException + { + if (parameters.length < 4) { + cio.writeln(PrintHelp.FEDERATE); + } + else { + LinkedList plist = new LinkedList(Arrays.asList(parameters)); + plist.remove(); // "federate" + boolean distinct = getOptionalParamValue(plist, "distinct", false); + boolean readonly = getOptionalParamValue(plist, "readonly", true); + if (distinctValues(plist)) { + String fedID = plist.pop(); + federate(distinct, readonly, fedID, plist); + } + else { + cio.writeError("Duplicate repository id's specified."); + } + } + } + + private boolean distinctValues(Deque plist) { + return plist.size() == new HashSet(plist).size(); + } + + private void federate(boolean distinct, boolean readonly, String fedID, Deque memberIDs) { + if (LOGGER.isDebugEnabled()) { + logCallDetails(distinct, readonly, fedID, memberIDs); + } + else { + RepositoryManager manager = state.getManager(); + try { + if (manager.hasRepositoryConfig(fedID)) { + cio.writeError(fedID + " already exists."); + } + else if (validateMembers(manager, readonly, memberIDs)) { + String description = cio.readln("Federation Description (optional):"); + RepositoryManagerFederator rmf = new RepositoryManagerFederator(manager); + rmf.addFed(fedID, description, memberIDs, readonly, distinct); + cio.writeln("Federation created."); + } + } + catch (RepositoryConfigException rce) { + cio.writeError(rce.getMessage()); + } + catch (RepositoryException re) { + cio.writeError(re.getMessage()); + } + catch (MalformedURLException mue) { + cio.writeError(mue.getMessage()); + } + catch (OpenRDFException ore) { + cio.writeError(ore.getMessage()); + } + catch (IOException ioe) { + cio.writeError(ioe.getMessage()); + } + } + } + + private boolean validateMembers(RepositoryManager manager, boolean readonly, Deque memberIDs) { + boolean result = true; + try { + for (String memberID : memberIDs) { + if (manager.hasRepositoryConfig(memberID)) { + if (!readonly) { + if (!manager.getRepository(memberID).isWritable()) { + result = false; + cio.writeError(memberID + " is read-only."); + } + } + } + else { + result = false; + cio.writeError(memberID + " does not exist."); + } + } + } + catch (RepositoryException re) { + cio.writeError(re.getMessage()); + } + catch (RepositoryConfigException rce) { + cio.writeError(rce.getMessage()); + } + return result; + } + + private void logCallDetails(boolean distinct, boolean readonly, String fedID, Deque memberIDs) { + StringBuilder builder = new StringBuilder(); + builder.append("Federate called with federation ID = " + fedID + ", and member ID's = "); + for (String member : memberIDs) { + builder.append("[").append(member).append("]"); + } + builder.append(".\n Distinct set to ").append(distinct).append(", and readonly set to ").append( + readonly).append(".\n"); + LOGGER.debug(builder.toString()); + } + + private boolean getOptionalParamValue(Deque parameters, String name, boolean defaultValue) { + return Boolean.parseBoolean(getOptionalParamValue(parameters, name, Boolean.toString(defaultValue))); + } + + private String getOptionalParamValue(Deque parameters, String name, String defaultValue) { + String result = defaultValue; + for (String parameter : parameters) { + if (parameter.length() >= name.length() + && parameter.substring(0, name.length()).equalsIgnoreCase(name)) + { + String[] parsed = parameter.split("="); + if (parsed.length == 2 && parsed[0].equalsIgnoreCase(name)) { + result = parsed[1].toLowerCase(); + parameters.remove(parameter); + break; + } + } + } + return result; + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Load.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Load.java new file mode 100644 index 00000000000..31521e473e0 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Load.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.RepositoryReadOnlyException; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.UnsupportedRDFormatException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dale Visser + */ +class Load implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Load.class); + + private final ConsoleIO consoleIO; + + private final ConsoleState state; + + private final LockRemover lockRemover; + + Load(ConsoleIO consoleIO, ConsoleState state, LockRemover lockRemover) { + this.consoleIO = consoleIO; + this.state = state; + this.lockRemover = lockRemover; + } + + public void execute(final String... tokens) { + Repository repository = state.getRepository(); + if (repository == null) { + consoleIO.writeUnopenedError(); + } + else { + if (tokens.length < 2) { + consoleIO.writeln(PrintHelp.LOAD); + } + else { + String baseURI = null; + String context = null; + int index = 2; + if (tokens.length >= index + 2 && tokens[index].equalsIgnoreCase("from")) { + baseURI = tokens[index + 1]; + index += 2; + } + if (tokens.length >= index + 2 && tokens[index].equalsIgnoreCase("into")) { + context = tokens[tokens.length - 1]; + index += 2; + } + if (index < tokens.length) { + consoleIO.writeln(PrintHelp.LOAD); + } + else { + load(repository, baseURI, context, tokens); + } + } + } + } + + private void load(Repository repository, String baseURI, String context, final String... tokens) { + final String dataPath = tokens[1]; + URL dataURL = null; + File dataFile = null; + try { + dataURL = new URL(dataPath); + // dataPath is a URI + } + catch (MalformedURLException e) { + // dataPath is a file + dataFile = new File(dataPath); + } + try { + addData(repository, baseURI, context, dataURL, dataFile); + } + catch (RepositoryReadOnlyException e) { + handleReadOnlyException(repository, e, tokens); + } + catch (MalformedURLException e) { + consoleIO.writeError("Malformed URL: " + dataPath); + } + catch (IllegalArgumentException e) { + // Thrown when context URI is invalid + consoleIO.writeError(e.getMessage()); + } + catch (IOException e) { + consoleIO.writeError("Failed to load data: " + e.getMessage()); + } + catch (UnsupportedRDFormatException e) { + consoleIO.writeError("No parser available for this RDF format"); + } + catch (RDFParseException e) { + consoleIO.writeError("Malformed document: " + e.getMessage()); + } + catch (RepositoryException e) { + consoleIO.writeError("Unable to add data to repository: " + e.getMessage()); + LOGGER.error("Failed to add data to repository", e); + } + } + + private void handleReadOnlyException(Repository repository, RepositoryReadOnlyException caught, + final String... tokens) + { + try { + if (lockRemover.tryToRemoveLock(repository)) { + execute(tokens); + } + else { + consoleIO.writeError("Failed to load data"); + LOGGER.error("Failed to load data", caught); + } + } + catch (RepositoryException e1) { + consoleIO.writeError("Unable to restart repository: " + e1.getMessage()); + LOGGER.error("Unable to restart repository", e1); + } + catch (IOException e1) { + consoleIO.writeError("Unable to remove lock: " + e1.getMessage()); + } + } + + private void addData(Repository repository, String baseURI, String context, URL dataURL, File dataFile) + throws RepositoryException, IOException, RDFParseException + { + Resource[] contexts = getContexts(repository, context); + consoleIO.writeln("Loading data..."); + final long startTime = System.nanoTime(); + final RepositoryConnection con = repository.getConnection(); + try { + if (dataURL == null) { + con.add(dataFile, baseURI, null, contexts); + } + else { + con.add(dataURL, baseURI, null, contexts); + } + } + finally { + con.close(); + } + final long endTime = System.nanoTime(); + consoleIO.writeln("Data has been added to the repository (" + (endTime - startTime) + / 1000000 + " ms)"); + } + + private Resource[] getContexts(Repository repository, String context) { + Resource[] contexts = new Resource[0]; + if (context != null) { + Resource contextURI; + if (context.startsWith("_:")) { + contextURI = repository.getValueFactory().createBNode(context.substring(2)); + } + else { + contextURI = repository.getValueFactory().createIRI(context); + } + contexts = new Resource[] { contextURI }; + } + return contexts; + } + +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/LockRemover.java b/core/console/src/main/java/org/eclipse/rdf4j/console/LockRemover.java new file mode 100644 index 00000000000..eca3dae84f0 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/LockRemover.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.IOException; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.RepositoryLockedException; +import org.eclipse.rdf4j.sail.LockManager; +import org.eclipse.rdf4j.sail.SailLockedException; +import org.eclipse.rdf4j.sail.helpers.DirectoryLockManager; + +/** + * + * @author DAle Visser + */ +public class LockRemover { + + private final ConsoleIO consoleIO; + + LockRemover(ConsoleIO consoleIO) { + this.consoleIO = consoleIO; + } + + protected boolean tryToRemoveLock(final Repository repo) + throws IOException, RepositoryException + { + boolean lockRemoved = false; + final LockManager lockManager = new DirectoryLockManager(repo.getDataDir()); + if (lockManager.isLocked() + && consoleIO.askProceed( + "WARNING: The lock from another process on this repository needs to be removed", true)) + { + repo.shutDown(); + lockRemoved = lockManager.revokeLock(); + repo.initialize(); + } + return lockRemoved; + } + + protected boolean tryToRemoveLock(final RepositoryLockedException rle) + throws IOException + { + boolean lockRemoved = false; + if (rle.getCause() instanceof SailLockedException) { + final SailLockedException sle = (SailLockedException)rle.getCause(); + final LockManager lockManager = sle.getLockManager(); + if (lockManager != null + && lockManager.isLocked() + && consoleIO.askProceed("WARNING: The lock from process '" + sle.getLockedBy() + + "' on this repository needs to be removed", true)) + { + lockRemoved = lockManager.revokeLock(); + } + } + return lockRemoved; + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Open.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Open.java new file mode 100644 index 00000000000..1e9003dbbf9 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Open.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.IOException; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.RepositoryLockedException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dale Visser + */ +public class Open implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Open.class); + + private final ConsoleIO consoleIO; + + private final ConsoleState state; + + private final Close close; + + private final LockRemover lockRemover; + + Open(ConsoleIO consoleIO, ConsoleState state, Close close, LockRemover lockRemover) { + this.consoleIO = consoleIO; + this.state = state; + this.close = close; + this.lockRemover = lockRemover; + } + + public void execute(String... tokens) { + if (tokens.length == 2) { + openRepository(tokens[1]); + } + else { + consoleIO.writeln(PrintHelp.OPEN); + } + } + + private static final String OPEN_FAILURE = "Failed to open repository"; + + protected void openRepository(final String repoID) { + try { + final Repository newRepository = state.getManager().getRepository(repoID); + + if (newRepository == null) { + consoleIO.writeError("Unknown repository: '" + repoID + "'"); + } + else { + // Close current repository, if any + close.closeRepository(false); + state.setRepository(newRepository); + state.setRepositoryID(repoID); + consoleIO.writeln("Opened repository '" + repoID + "'"); + } + } + catch (RepositoryLockedException e) { + try { + if (lockRemover.tryToRemoveLock(e)) { + openRepository(repoID); + } + else { + consoleIO.writeError(OPEN_FAILURE); + LOGGER.error(OPEN_FAILURE, e); + } + } + catch (IOException e1) { + consoleIO.writeError("Unable to remove lock: " + e1.getMessage()); + } + } + catch (RepositoryConfigException e) { + consoleIO.writeError(e.getMessage()); + LOGGER.error(OPEN_FAILURE, e); + } + catch (RepositoryException e) { + consoleIO.writeError(e.getMessage()); + LOGGER.error(OPEN_FAILURE, e); + } + } + +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/PrintHelp.java b/core/console/src/main/java/org/eclipse/rdf4j/console/PrintHelp.java new file mode 100644 index 00000000000..0588dda9ed2 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/PrintHelp.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * Prints help to the console. + * + * @author Dale Visser + */ +public class PrintHelp implements Command { + + private static final String USAGE = "Usage:\n"; + + protected static final String CONNECT = USAGE + + "connect default Opens the default repository set for this console\n" + + "connect Opens the repository set in the specified data dir\n" + + "connect [user [password]] Connects to a Sesame server with optional credentials\n"; + + protected static final String CREATE = USAGE + "create \n" + + " The name of a repository configuration template\n"; + + private static final String DISCONNECT = USAGE + + "disconnect Disconnects from the current set of repositories or server\n"; + + protected static final String DROP = USAGE + + "drop Drops the repository with the specified id\n"; + + protected static final String INFO = USAGE + + "info Shows information about the console\n"; + + protected static final String OPEN = USAGE + + "open Opens the repository with the specified ID\n"; + + protected static final String CLOSE = USAGE + "close Closes the current repository\n"; + + protected static final String SHOW = USAGE + "show {r, repositories} Shows all available repositories\n" + + "show {n, namespaces} Shows all namespaces\n" + + "show {c, contexts} Shows all context identifiers\n"; + + protected static final String LOAD = USAGE + + "load [from ] [into ]\n" + + " The path or URL identifying the data file\n" + + " The base URI to use for resolving relative references, defaults to \n" + + " The ID of the context to add the data to, e.g. foo:bar or _:n123\n" + + "Loads the specified data file into the current repository\n"; + + protected static final String VERIFY = USAGE + "verify \n" + + " The path or URL identifying the data file\n" + + "Verifies the validity of the specified data file\n"; + + protected static final String CLEAR = USAGE + "clear Clears the entire repository\n" + + "clear (|null)... Clears the specified context(s)\n"; + + protected static final String SPARQL = USAGE + + "sparql Evaluates the SPARQL query on the currently open repository.\n" + + "sparql Starts multi-line input for large SPARQL queries.\n" + + "select|construct|ask|describe|prefix|base \n" + + " Evaluates a SPARQL query on the currently open repository.\n"; + + + protected static final String SERQL = USAGE + + "serql Evaluates the SeRQL query on the currently open repository\n" + + "serql Starts multi-line input for large SeRQL queries.\n" ; + + protected static final String SET = USAGE + + "set Shows all parameter values\n" + + "set width= Set the width for query result tables\n" + + "set log= Set the logging level (none, error, warning, info or debug)\n" + + "set showPrefix= Toggles use of prefixed names in query results\n" + + "set queryPrefix= Toggles automatic use of known namespace prefixes in queries\n"; + + protected static final String FEDERATE = USAGE + + "federate [distinct=] [readonly=] []*\n" + + " [distinct=] If true, uses a DISTINCT filter that suppresses duplicate results for identical quads\n" + + " from different federation members. Default is false.\n" + + " [readonly=] If true, sets the fedearated repository as read-only. If any member is read-only, then\n" + + " this may only be set to true. Default is true. \n" + + " The id to assign the federated repository.\n" + + " The id's of at least 2 repositories to federate.\n" + + " []* The id's of 0 or mare additional repositories to federate.\n\n" + + "You will be prompted to enter a description for the federated repository as well."; + + private final Map topics = new HashMap(); + + private final ConsoleIO consoleIO; + + PrintHelp(ConsoleIO consoleIO) { + super(); + this.consoleIO = consoleIO; + topics.put("clear", CLEAR); + topics.put("close", CLOSE); + topics.put("connect", CONNECT); + topics.put("create", CREATE); + topics.put("disconnect", DISCONNECT); + topics.put("drop", DROP); + topics.put("federate", FEDERATE); + topics.put("info", INFO); + topics.put("load", LOAD); + topics.put("open", OPEN); + topics.put("serql", SERQL); + topics.put("set", SET); + topics.put("show", SHOW); + topics.put("sparql", SPARQL); + topics.put("verify", VERIFY); + } + + public void execute(String... parameters) { + if (parameters.length < 2) { + printCommandOverview(); + } + else { + final String target = parameters[1].toLowerCase(Locale.ENGLISH); + if (topics.containsKey(target)) { + consoleIO.writeln(topics.get(target)); + } + else { + consoleIO.writeln("No additional info available for command " + parameters[1]); + } + } + } + + private void printCommandOverview() { + consoleIO.writeln("For more information on a specific command, try 'help '."); + consoleIO.writeln("List of all commands:"); + consoleIO.writeln("help Displays this help message"); + consoleIO.writeln("info Shows info about the console"); + consoleIO.writeln("connect Connects to a (local or remote) set of repositories"); + consoleIO.writeln("disconnect Disconnects from the current set of repositories"); + consoleIO.writeln("create Creates a new repository"); + consoleIO.writeln("federate Federate existing repositories."); + consoleIO.writeln("drop Drops a repository"); + consoleIO.writeln("open Opens a repository to work on, takes a repository ID as argument"); + consoleIO.writeln("close Closes the current repository"); + consoleIO.writeln("show Displays an overview of various resources"); + consoleIO.writeln("load Loads a data file into a repository, takes a file path or URL as argument"); + consoleIO.writeln("verify Verifies the syntax of an RDF data file, takes a file path or URL as argument"); + consoleIO.writeln("clear Removes data from a repository"); + consoleIO.writeln("sparql Evaluate a SPARQL query"); + consoleIO.writeln("serql Evaluate a SeRQL query"); + consoleIO.writeln("set Allows various console parameters to be set"); + consoleIO.writeln("exit, quit Exit the console"); + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/PrintInfo.java b/core/console/src/main/java/org/eclipse/rdf4j/console/PrintInfo.java new file mode 100644 index 00000000000..3d90fa8070d --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/PrintInfo.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + + +/** + * @author Dale Visser + */ +class PrintInfo implements Command { + + private final ConsoleState appInfo; + + private final ConsoleIO consoleIO; + + PrintInfo(ConsoleIO consoleIO, ConsoleState appInfo) { + this.consoleIO = consoleIO; + this.appInfo = appInfo; + } + + public void execute(String... parameters) { + consoleIO.writeln(appInfo.getApplicationName()); + consoleIO.writeln("Data dir: " + appInfo.getDataDirectory()); + String managerID = appInfo.getManagerID(); + consoleIO.writeln("Connected to: " + (managerID == null ? "-" : managerID)); + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/QueryEvaluator.java b/core/console/src/main/java/org/eclipse/rdf4j/console/QueryEvaluator.java new file mode 100644 index 00000000000..afe54f941d5 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/QueryEvaluator.java @@ -0,0 +1,245 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import static org.eclipse.rdf4j.query.QueryLanguage.SERQL; +import static org.eclipse.rdf4j.query.QueryLanguage.SPARQL; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Locale; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryInterruptedException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.query.UpdateExecutionException; +import org.eclipse.rdf4j.query.parser.ParsedBooleanQuery; +import org.eclipse.rdf4j.query.parser.ParsedGraphQuery; +import org.eclipse.rdf4j.query.parser.ParsedOperation; +import org.eclipse.rdf4j.query.parser.ParsedTupleQuery; +import org.eclipse.rdf4j.query.parser.ParsedUpdate; +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.eclipse.rdf4j.query.parser.serql.SeRQLUtil; +import org.eclipse.rdf4j.query.parser.sparql.SPARQLUtil; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dale Visser + */ +public class QueryEvaluator { + + private static final Logger LOGGER = LoggerFactory.getLogger(QueryEvaluator.class); + + private final ConsoleIO consoleIO; + + private final ConsoleState state; + + private final ConsoleParameters parameters; + + private final TupleAndGraphQueryEvaluator tg_eval; + + QueryEvaluator(ConsoleIO consoleIO, ConsoleState state, ConsoleParameters parameters) { + this.consoleIO = consoleIO; + this.state = state; + this.parameters = parameters; + this.tg_eval = new TupleAndGraphQueryEvaluator(consoleIO, state, parameters); + } + + public void executeQuery(final String command, final String operation) { + final List sparqlQueryStart = Arrays.asList(new String[]{ "select", "construct", "describe", "ask", "prefix", "base"}); + if (sparqlQueryStart.contains(operation)) { + evaluateQuery(QueryLanguage.SPARQL, command); + } + else if ("serql".equals(operation)) { + evaluateQuery(QueryLanguage.SERQL, command.substring("serql".length())); + } + else if ("sparql".equals(operation)) { + evaluateQuery(QueryLanguage.SPARQL, command.substring("sparql".length())); + } + else { + consoleIO.writeError("Unknown command"); + } + } + + private void evaluateQuery(final QueryLanguage queryLn, String queryText) { + try { + if (queryText.trim().isEmpty()) { + consoleIO.writeln("enter multi-line " + queryLn.getName() + " query (terminate with line containing single '.')"); + queryText = consoleIO.readMultiLineInput(); + } + final String queryString = addQueryPrefixes(queryLn, queryText); + final ParsedOperation query = QueryParserUtil.parseOperation(queryLn, queryString, null); + evaluateQuery(queryLn, queryString, query); + } + catch (UnsupportedQueryLanguageException e) { + consoleIO.writeError("Unsupported query lanaguge: " + queryLn.getName()); + } + catch (MalformedQueryException e) { + consoleIO.writeError("Malformed query: " + e.getMessage()); + } + catch (QueryInterruptedException e) { + consoleIO.writeError("Query interrupted: " + e.getMessage()); + LOGGER.error("Query interrupted", e); + } + catch (QueryEvaluationException e) { + consoleIO.writeError("Query evaluation error: " + e.getMessage()); + LOGGER.error("Query evaluation error", e); + } + catch (RepositoryException e) { + consoleIO.writeError("Failed to evaluate query: " + e.getMessage()); + LOGGER.error("Failed to evaluate query", e); + } + catch (UpdateExecutionException e) { + consoleIO.writeError("Failed to execute update: " + e.getMessage()); + LOGGER.error("Failed to execute update", e); + } + catch (IOException e) { + consoleIO.writeError("I/O error: " + e.getMessage()); + LOGGER.error("Failed to read query", e); + } + } + + private void evaluateQuery(final QueryLanguage queryLn, final String queryString, + final ParsedOperation query) + throws MalformedQueryException, QueryEvaluationException, RepositoryException, UpdateExecutionException + { + if (query instanceof ParsedTupleQuery) { + tg_eval.evaluateTupleQuery(queryLn, queryString); + } + else if (query instanceof ParsedGraphQuery) { + tg_eval.evaluateGraphQuery(queryLn, queryString); + } + else if (query instanceof ParsedBooleanQuery) { + evaluateBooleanQuery(queryLn, queryString); + } + else if (query instanceof ParsedUpdate) { + executeUpdate(queryLn, queryString); + } + else { + consoleIO.writeError("Unexpected query type"); + } + } + + private String addQueryPrefixes(final QueryLanguage queryLn, final String queryString) { + final StringBuffer result = new StringBuffer(queryString.length() + 512); + result.append(queryString); + final String lowerCaseQuery = queryString.toLowerCase(Locale.ENGLISH); + Repository repository = state.getRepository(); + if (repository != null + && parameters.isQueryPrefix() + && ((SERQL.equals(queryLn) && lowerCaseQuery.indexOf("using namespace ") == -1) || SPARQL.equals(queryLn) + && !lowerCaseQuery.startsWith("prefix"))) + { + // FIXME this is a bit of a sloppy hack, a better way would be to + // explicitly provide the query parser with name space mappings in + // advance. + try { + final RepositoryConnection con = repository.getConnection(); + try { + final Collection namespaces = Iterations.asList(con.getNamespaces()); + if (!namespaces.isEmpty()) { + addQueryPrefixes(queryLn, result, namespaces); + } + } + finally { + con.close(); + } + } + catch (RepositoryException e) { + consoleIO.writeError("Error connecting to repository: " + e.getMessage()); + LOGGER.error("Error connecting to repository", e); + } + } + return result.toString(); + } + + private void addQueryPrefixes(final QueryLanguage queryLn, final StringBuffer result, + final Collection namespaces) + { + final StringBuilder namespaceClause = new StringBuilder(512); + if (SERQL.equals(queryLn)) { + namespaceClause.append(" USING NAMESPACE "); + for (Namespace namespace : namespaces) { + namespaceClause.append(namespace.getPrefix()); + namespaceClause.append(" = "); + namespaceClause.append("<"); + namespaceClause.append(SeRQLUtil.encodeString(namespace.getName())); + namespaceClause.append(">, "); + } + // Remove trailing ", " + namespaceClause.setLength(namespaceClause.length() - 2); + result.append(namespaceClause.toString()); + } + else if (SPARQL.equals(queryLn)) { + for (Namespace namespace : namespaces) { + namespaceClause.append("PREFIX "); + namespaceClause.append(namespace.getPrefix()); + namespaceClause.append(": "); + namespaceClause.append("<"); + namespaceClause.append(SPARQLUtil.encodeString(namespace.getName())); + namespaceClause.append("> "); + } + result.insert(0, namespaceClause); + } + } + + private void evaluateBooleanQuery(final QueryLanguage queryLn, final String queryString) + throws UnsupportedQueryLanguageException, MalformedQueryException, QueryEvaluationException, + RepositoryException + { + Repository repository = state.getRepository(); + if (repository == null) { + consoleIO.writeUnopenedError(); + return; + } + final RepositoryConnection con = repository.getConnection(); + try { + consoleIO.writeln("Evaluating " + queryLn.getName() + " query..."); + final long startTime = System.nanoTime(); + final boolean result = con.prepareBooleanQuery(queryLn, queryString).evaluate(); + consoleIO.writeln("Answer: " + result); + final long endTime = System.nanoTime(); + consoleIO.writeln("Query evaluated in " + (endTime - startTime) / 1000000 + " ms"); + } + finally { + con.close(); + } + } + + private void executeUpdate(final QueryLanguage queryLn, final String queryString) + throws RepositoryException, UpdateExecutionException, MalformedQueryException + { + Repository repository = state.getRepository(); + if (repository == null) { + consoleIO.writeUnopenedError(); + return; + } + final RepositoryConnection con = repository.getConnection(); + try { + consoleIO.writeln("Executing update..."); + final long startTime = System.nanoTime(); + con.prepareUpdate(queryLn, queryString).execute(); + final long endTime = System.nanoTime(); + consoleIO.writeln("Update executed in " + (endTime - startTime) / 1000000 + " ms"); + } + finally { + con.close(); + } + } + +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/SetParameters.java b/core/console/src/main/java/org/eclipse/rdf4j/console/SetParameters.java new file mode 100644 index 00000000000..adbfede89bb --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/SetParameters.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +/** + * @author dale + */ +public class SetParameters implements Command { + + private final ConsoleIO consoleIO; + + private final ConsoleParameters parameters; + + SetParameters(ConsoleIO consoleIO, ConsoleParameters parameters) { + this.consoleIO = consoleIO; + this.parameters = parameters; + } + + public void execute(String... tokens) { + if (tokens.length == 1) { + showParameters(); + } + else if (tokens.length == 2) { + final String param = tokens[1]; + String key, value; + final int eqIdx = param.indexOf('='); + if (eqIdx == -1) { + key = param; + value = null; // NOPMD + } + else { + key = param.substring(0, eqIdx); + value = param.substring(eqIdx + 1); + } + setParameter(key, value); + } + else { + consoleIO.writeln(PrintHelp.SET); + } + } + + private void showParameters() { + setWidth(null); + setShowPrefix(null); + setQueryPrefix(null); + } + + private void setParameter(final String key, final String value) { + if ("width".equalsIgnoreCase(key)) { + setWidth(value); + } + else if ("showprefix".equalsIgnoreCase(key)) { + setShowPrefix(value); + } + else if ("queryprefix".equalsIgnoreCase(key)) { + setQueryPrefix(value); + } + else { + consoleIO.writeError("unknown parameter: " + key); + } + } + + private void setWidth(final String value) { + if (value == null) { + consoleIO.writeln("width: " + parameters.getWidth()); + } + else { + try { + final int width = Integer.parseInt(value); + if (width > 0) { + parameters.setWidth(width); + } + else { + consoleIO.writeError("Width must be larger than 0"); + } + } + catch (NumberFormatException e) { + consoleIO.writeError("Width must be a positive number"); + } + } + } + + private void setShowPrefix(final String value) { + if (value == null) { + consoleIO.writeln("showPrefix: " + parameters.isShowPrefix()); + } + else { + parameters.setShowPrefix(Boolean.parseBoolean(value)); + } + } + + private void setQueryPrefix(final String value) { + if (value == null) { + consoleIO.writeln("queryPrefix: " + parameters.isQueryPrefix()); + } + else { + parameters.setQueryPrefix(Boolean.parseBoolean(value)); + } + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Show.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Show.java new file mode 100644 index 00000000000..f760cc17fa8 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Show.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.util.Locale; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.manager.RepositoryInfo; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dale Visser + */ +public class Show implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Show.class); + + private static final String OUTPUT_SEPARATOR = "+----------"; + + private final ConsoleIO consoleIO; + + private final ConsoleState state; + + Show(ConsoleIO consoleIO, ConsoleState state) { + this.consoleIO = consoleIO; + this.state = state; + } + + public void execute(String... tokens) { + if (tokens.length == 2) { + final String target = tokens[1].toLowerCase(Locale.ENGLISH); + if ("repositories".equals(target) || "r".equals(target)) { + showRepositories(); + } + else if ("namespaces".equals(target) || "n".equals(target)) { + showNamespaces(); + } + else if ("contexts".equals(target) || "c".equals(target)) { + showContexts(); + } + else { + consoleIO.writeError("Unknown target '" + tokens[1] + "'"); + } + } + else { + consoleIO.writeln(PrintHelp.SHOW); + } + } + + private void showRepositories() { + try { + RepositoryManager manager = state.getManager(); + final Set repIDs = manager.getRepositoryIDs(); + if (repIDs.isEmpty()) { + consoleIO.writeln("--no repositories found--"); + } + else { + consoleIO.writeln(OUTPUT_SEPARATOR); + for (String repID : repIDs) { + consoleIO.write("|" + repID); + + try { + final RepositoryInfo repInfo = manager.getRepositoryInfo(repID); + if (repInfo.getDescription() != null) { + consoleIO.write(" (\"" + repInfo.getDescription() + "\")"); + } + } + catch (RepositoryException e) { + consoleIO.write(" [ERROR: " + e.getMessage() + "]"); + } + consoleIO.writeln(); + } + consoleIO.writeln(OUTPUT_SEPARATOR); + } + } + catch (RepositoryException e) { + consoleIO.writeError("Failed to get repository list: " + e.getMessage()); + LOGGER.error("Failed to get repository list", e); + } + } + + private void showNamespaces() { + Repository repository = state.getRepository(); + if (repository == null) { + consoleIO.writeUnopenedError(); + return; + } + + RepositoryConnection con; + try { + con = repository.getConnection(); + try { + final CloseableIteration namespaces = con.getNamespaces(); + try { + if (namespaces.hasNext()) { + consoleIO.writeln(OUTPUT_SEPARATOR); + while (namespaces.hasNext()) { + final Namespace namespace = namespaces.next(); + consoleIO.writeln("|" + namespace.getPrefix() + " " + namespace.getName()); + } + consoleIO.writeln(OUTPUT_SEPARATOR); + } + else { + consoleIO.writeln("--no namespaces found--"); + } + } + finally { + namespaces.close(); + } + } + finally { + con.close(); + } + } + catch (RepositoryException e) { + consoleIO.writeError(e.getMessage()); + LOGGER.error("Failed to show namespaces", e); + } + } + + private void showContexts() { + Repository repository = state.getRepository(); + if (repository == null) { + consoleIO.writeUnopenedError(); + return; + } + + RepositoryConnection con; + try { + con = repository.getConnection(); + try { + final CloseableIteration contexts = con.getContextIDs(); + try { + if (contexts.hasNext()) { + consoleIO.writeln(OUTPUT_SEPARATOR); + while (contexts.hasNext()) { + consoleIO.writeln("|" + contexts.next().toString()); + } + consoleIO.writeln(OUTPUT_SEPARATOR); + } + else { + consoleIO.writeln("--no contexts found--"); + } + } + finally { + contexts.close(); + } + } + finally { + con.close(); + } + } + catch (RepositoryException e) { + consoleIO.writeError(e.getMessage()); + LOGGER.error("Failed to show contexts", e); + } + } + +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/TupleAndGraphQueryEvaluator.java b/core/console/src/main/java/org/eclipse/rdf4j/console/TupleAndGraphQueryEvaluator.java new file mode 100644 index 00000000000..9ff9e8df426 --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/TupleAndGraphQueryEvaluator.java @@ -0,0 +1,209 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.util.Collection; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.common.text.StringUtil; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.GraphQueryResult; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.rio.ParserConfig; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.eclipse.rdf4j.rio.ntriples.NTriplesUtil; + +/** + * @author dale + */ +public class TupleAndGraphQueryEvaluator { + + private final ConsoleIO consoleIO; + + private final ConsoleState state; + + private final ConsoleParameters parameters; + + private static final ParserConfig nonVerifyingParserConfig; + + static { + nonVerifyingParserConfig = new ParserConfig(); + nonVerifyingParserConfig.set(BasicParserSettings.VERIFY_DATATYPE_VALUES, false); + nonVerifyingParserConfig.set(BasicParserSettings.VERIFY_LANGUAGE_TAGS, false); + nonVerifyingParserConfig.set(BasicParserSettings.VERIFY_RELATIVE_URIS, false); + } + + TupleAndGraphQueryEvaluator(ConsoleIO consoleIO, ConsoleState state, ConsoleParameters parameters) { + this.consoleIO = consoleIO; + this.state = state; + this.parameters = parameters; + } + + protected void evaluateTupleQuery(final QueryLanguage queryLn, final String queryString) + throws UnsupportedQueryLanguageException, MalformedQueryException, QueryEvaluationException, + RepositoryException + { + Repository repository = state.getRepository(); + if (repository == null) { + consoleIO.writeUnopenedError(); + return; + } + final RepositoryConnection con = repository.getConnection(); + try { + final long startTime = System.nanoTime(); + consoleIO.writeln("Evaluating " + queryLn.getName() + " query..."); + final TupleQueryResult tupleQueryResult = con.prepareTupleQuery(queryLn, queryString).evaluate(); + try { + int resultCount = 0; + final List bindingNames = tupleQueryResult.getBindingNames(); + if (bindingNames.isEmpty()) { + while (tupleQueryResult.hasNext()) { + tupleQueryResult.next(); + resultCount++; + } + } + else { + int consoleWidth = parameters.getWidth(); + final int columnWidth = (consoleWidth - 1) / bindingNames.size() - 3; + + // Build table header + final StringBuilder builder = new StringBuilder(consoleWidth); + for (String bindingName : bindingNames) { + builder.append("| ").append(bindingName); + StringUtil.appendN(' ', columnWidth - bindingName.length(), builder); + } + builder.append("|"); + final String header = builder.toString(); + + // Build separator line + builder.setLength(0); + for (int i = bindingNames.size(); i > 0; i--) { + builder.append('+'); + StringUtil.appendN('-', columnWidth + 1, builder); + } + builder.append('+'); + final String separatorLine = builder.toString(); + + // consoleIO.write table header + consoleIO.writeln(separatorLine); + consoleIO.writeln(header); + consoleIO.writeln(separatorLine); + + // consoleIO.write table rows + final Collection namespaces = Iterations.asList(con.getNamespaces()); + while (tupleQueryResult.hasNext()) { + final BindingSet bindingSet = tupleQueryResult.next(); + resultCount++; + builder.setLength(0); + for (String bindingName : bindingNames) { + final Value value = bindingSet.getValue(bindingName); + final String valueStr = getStringRepForValue(value, namespaces); + builder.append("| ").append(valueStr); + StringUtil.appendN(' ', columnWidth - valueStr.length(), builder); + } + builder.append("|"); + consoleIO.writeln(builder.toString()); + } + consoleIO.writeln(separatorLine); + } + final long endTime = System.nanoTime(); + consoleIO.writeln(resultCount + " result(s) (" + (endTime - startTime) / 1000000 + " ms)"); + } + finally { + tupleQueryResult.close(); + } + } + finally { + con.close(); + } + } + + protected void evaluateGraphQuery(final QueryLanguage queryLn, final String queryString) + throws UnsupportedQueryLanguageException, MalformedQueryException, QueryEvaluationException, + RepositoryException + { + Repository repository = state.getRepository(); + if (repository == null) { + consoleIO.writeUnopenedError(); + return; + } + final RepositoryConnection con = repository.getConnection(); + con.setParserConfig(nonVerifyingParserConfig); + try { + consoleIO.writeln("Evaluating " + queryLn.getName() + " query..."); + final long startTime = System.nanoTime(); + final Collection namespaces = Iterations.asList(con.getNamespaces()); + final GraphQueryResult queryResult = con.prepareGraphQuery(queryLn, queryString).evaluate(); + try { + int resultCount = 0; + while (queryResult.hasNext()) { + final Statement statement = queryResult.next(); // NOPMD + resultCount++; + consoleIO.write(getStringRepForValue(statement.getSubject(), namespaces)); + consoleIO.write(" "); + consoleIO.write(getStringRepForValue(statement.getPredicate(), namespaces)); + consoleIO.write(" "); + consoleIO.write(getStringRepForValue(statement.getObject(), namespaces)); + consoleIO.writeln(); + } + final long endTime = System.nanoTime(); + consoleIO.writeln(resultCount + " results (" + (endTime - startTime) / 1000000 + " ms)"); + } + finally { + queryResult.close(); + } + } + finally { + con.close(); + } + } + + private String getStringRepForValue(final Value value, final Collection namespaces) { + String result = ""; + if (value != null) { + if (parameters.isShowPrefix() && value instanceof IRI) { + final IRI uri = (IRI)value; + final String prefix = getPrefixForNamespace(uri.getNamespace(), namespaces); + if (prefix == null) { + result = NTriplesUtil.toNTriplesString(value); + } + else { + result = prefix + ":" + uri.getLocalName(); + } + } + else { + result = NTriplesUtil.toNTriplesString(value); + } + } + return result; + } + + private String getPrefixForNamespace(final String namespace, final Collection namespaces) { + String result = null; + for (Namespace ns : namespaces) { + if (namespace.equals(ns.getName())) { + result = ns.getPrefix(); + break; + } + } + return result; + } + +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/VerificationLIstener.java b/core/console/src/main/java/org/eclipse/rdf4j/console/VerificationLIstener.java new file mode 100644 index 00000000000..9cdbdd4f3ef --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/VerificationLIstener.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.rio.ParseErrorListener; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.helpers.AbstractRDFHandler; + +/** + * @author Dale Visser + */ +class VerificationListener extends AbstractRDFHandler implements ParseErrorListener { + + private final ConsoleIO consoleIO; + + VerificationListener(ConsoleIO consoleIO) { + super(); + this.consoleIO = consoleIO; + } + + private int warnings; + + private int errors; + + private int statements; + + public int getWarnings() { + return warnings; + } + + public int getErrors() { + return errors; + } + + public int getStatements() { + return statements; + } + + public void handleStatement(final Statement statement) + throws RDFHandlerException + { + statements++; + } + + public void warning(final String msg, final long lineNo, final long colNo) { + warnings++; + consoleIO.writeParseError("WARNING", lineNo, colNo, msg); + } + + public void error(final String msg, final long lineNo, final long colNo) { + errors++; + consoleIO.writeParseError("ERROR", lineNo, colNo, msg); + } + + public void fatalError(final String msg, final long lineNo, final long colNo) { + errors++; + consoleIO.writeParseError("FATAL ERROR", lineNo, colNo, msg); + } +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/Verify.java b/core/console/src/main/java/org/eclipse/rdf4j/console/Verify.java new file mode 100644 index 00000000000..e9378cb0d5b --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/Verify.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.UnsupportedRDFormatException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dale Visser + */ +public class Verify implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Verify.class); + + private final ConsoleIO consoleIO; + + Verify(ConsoleIO consoleIO) { + this.consoleIO = consoleIO; + } + + public void execute(String... tokens) { + if (tokens.length != 2) { + consoleIO.writeln(PrintHelp.VERIFY); + return; + } + String dataPath = parseDataPath(tokens); + try { + final URL dataURL = new URL(dataPath); + final RDFFormat format = Rio.getParserFormatForFileName(dataPath).orElseThrow( + Rio.unsupportedFormat(dataPath)); + consoleIO.writeln("RDF Format is " + format.getName()); + final RDFParser parser = Rio.createParser(format); + final VerificationListener listener = new VerificationListener(consoleIO); + parser.setDatatypeHandling(RDFParser.DatatypeHandling.VERIFY); + parser.setVerifyData(true); + parser.setParseErrorListener(listener); + parser.setRDFHandler(listener); + consoleIO.writeln("Verifying data..."); + final InputStream dataStream = dataURL.openStream(); + try { + parser.parse(dataStream, "urn://openrdf.org/RioVerifier/"); + } + finally { + dataStream.close(); + } + final int warnings = listener.getWarnings(); + final int errors = listener.getErrors(); + if (warnings + errors > 0) { + consoleIO.writeln("Found " + warnings + " warnings and " + errors + " errors"); + } + else { + consoleIO.writeln("Data verified, no errors were found"); + } + if (errors == 0) { + consoleIO.writeln("File contains " + listener.getStatements() + " statements"); + } + } + catch (MalformedURLException e) { + consoleIO.writeError("Malformed URL: " + dataPath); + } + catch (IOException e) { + consoleIO.writeError("Failed to load data: " + e.getMessage()); + } + catch (UnsupportedRDFormatException e) { + consoleIO.writeError("No parser available for this RDF format"); + } + catch (RDFParseException e) { + LOGGER.error("Unexpected RDFParseException", e); + } + catch (RDFHandlerException e) { + consoleIO.writeError("Unable to verify : " + e.getMessage()); + LOGGER.error("Unable to verify data file", e); + } + } + + private String parseDataPath(String... tokens) { + StringBuilder dataPath = new StringBuilder(tokens[1]); + try { + new URL(dataPath.toString()); + // dataPath is a URI + } + catch (MalformedURLException e) { + // File path specified, convert to URL + dataPath.insert(0, "file:"); + } + return dataPath.toString(); + } + +} diff --git a/core/console/src/main/java/org/eclipse/rdf4j/console/package.html b/core/console/src/main/java/org/eclipse/rdf4j/console/package.html new file mode 100644 index 00000000000..236b9fe3bea --- /dev/null +++ b/core/console/src/main/java/org/eclipse/rdf4j/console/package.html @@ -0,0 +1,8 @@ + + +

+A command line console tool for communicating with local Sesame repositories. +

+Usage:

java org.openrdf.console.Console [datadir [repository-id]]
+ + diff --git a/core/console/src/test/java/org/eclipse/rdf4j/console/AbstractCommandTest.java b/core/console/src/test/java/org/eclipse/rdf4j/console/AbstractCommandTest.java new file mode 100644 index 00000000000..074958ebad8 --- /dev/null +++ b/core/console/src/test/java/org/eclipse/rdf4j/console/AbstractCommandTest.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import static org.mockito.Mockito.mock; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URL; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.console.ConsoleIO; +import org.eclipse.rdf4j.model.Graph; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.util.GraphUtil; +import org.eclipse.rdf4j.model.util.Models; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigSchema; +import org.eclipse.rdf4j.repository.config.RepositoryConfigUtil; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; + +/** + * @author Dale Visser + */ +public class AbstractCommandTest { + + protected RepositoryManager manager; + + protected ConsoleIO streams = mock(ConsoleIO.class); + + protected final void addRepositories(String... identities) + throws UnsupportedEncodingException, IOException, OpenRDFException + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + for (String identity : identities) { + addRepository(classLoader.getResourceAsStream("federate/" + identity + "-config.ttl"), + classLoader.getResource("federate/" + identity + ".ttl")); + } + } + + protected void addRepository(InputStream configStream, URL data) + throws UnsupportedEncodingException, IOException, OpenRDFException + { + Repository systemRepo = manager.getSystemRepository(); + RDFParser rdfParser = Rio.createParser(RDFFormat.TURTLE, systemRepo.getValueFactory()); + Model graph = new LinkedHashModel(); + rdfParser.setRDFHandler(new StatementCollector(graph)); + rdfParser.parse(new StringReader(IOUtil.readString(new InputStreamReader(configStream, "UTF-8"))), + RepositoryConfigSchema.NAMESPACE); + configStream.close(); + Resource repositoryNode = Models.subject( + graph.filter(null, RDF.TYPE, RepositoryConfigSchema.REPOSITORY)).orElseThrow( + () -> new RepositoryConfigException("could not find subject resource")); + RepositoryConfig repoConfig = RepositoryConfig.create(graph, repositoryNode); + repoConfig.validate(); + RepositoryConfigUtil.updateRepositoryConfigs(systemRepo, repoConfig); + if (null != data) { // null if we didn't provide a data file + final String repId = Models.objectLiteral( + graph.filter(repositoryNode, RepositoryConfigSchema.REPOSITORYID, null)).orElseThrow( + () -> new RepositoryConfigException("missing repository id")).stringValue(); + RepositoryConnection connection = manager.getRepository(repId).getConnection(); + try { + connection.add(data, null, RDFFormat.TURTLE); + } + finally { + connection.close(); + } + } + } + +} diff --git a/core/console/src/test/java/org/eclipse/rdf4j/console/ConsoleIOTest.java b/core/console/src/test/java/org/eclipse/rdf4j/console/ConsoleIOTest.java new file mode 100644 index 00000000000..ae6bfe15ee6 --- /dev/null +++ b/core/console/src/test/java/org/eclipse/rdf4j/console/ConsoleIOTest.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import org.eclipse.rdf4j.console.ConsoleIO; +import org.eclipse.rdf4j.console.ConsoleState; +import org.junit.Before; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.PrintStream; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +public class ConsoleIOTest { + + private ConsoleIO io; + + @Before + public void initConsoleObject() { + BufferedReader input = mock(BufferedReader.class); + PrintStream out = mock(PrintStream.class); + PrintStream err = mock(PrintStream.class); + ConsoleState info = mock(ConsoleState.class); + io = new ConsoleIO(input, out, err, info); + } + + @Test + public void shouldSetErrorWrittenWhenErrorsAreWritten() { + io.writeError(null); + assertThat(io.wasErrorWritten(), equalTo(true)); + } + + @Test + public void shouldSetErroWrittenOnParserError() { + io.writeParseError("", 0, 0, ""); + assertThat(io.wasErrorWritten(), equalTo(true)); + } + + @Test + public void shouldSetErroWrittenOnWriteUnoppenedError() { + io.writeUnopenedError(); + assertThat(io.wasErrorWritten(), equalTo(true)); + } +} diff --git a/core/console/src/test/java/org/eclipse/rdf4j/console/DropTest.java b/core/console/src/test/java/org/eclipse/rdf4j/console/DropTest.java new file mode 100644 index 00000000000..884d4bcb466 --- /dev/null +++ b/core/console/src/test/java/org/eclipse/rdf4j/console/DropTest.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.startsWith; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.never; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.console.Close; +import org.eclipse.rdf4j.console.ConsoleState; +import org.eclipse.rdf4j.console.Drop; +import org.eclipse.rdf4j.console.LockRemover; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.manager.LocalRepositoryManager; +import org.eclipse.rdf4j.repository.sail.config.ProxyRepositoryConfig; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * @author Dale Visser + */ +public class DropTest extends AbstractCommandTest { + + private static final String MEMORY_MEMBER_ID1 = "alien"; + + private static final String PROXY_ID = "proxyID"; + + private Drop drop; + + @Rule + public final TemporaryFolder LOCATION = new TemporaryFolder(); + + @Before + public void prepareManager() + throws UnsupportedEncodingException, IOException, OpenRDFException + { + manager = new LocalRepositoryManager(LOCATION.getRoot()); + manager.initialize(); + addRepositories(MEMORY_MEMBER_ID1); + manager.addRepositoryConfig(new RepositoryConfig(PROXY_ID, new ProxyRepositoryConfig(MEMORY_MEMBER_ID1))); + ConsoleState state = mock(ConsoleState.class); + when(state.getManager()).thenReturn(manager); + drop = new Drop(streams, state, new Close(streams, state), new LockRemover(streams)); + } + + private void setUserDropConfirm(boolean confirm) throws IOException { + when(streams.askProceed(startsWith("WARNING: you are about to drop repository '"), anyBoolean())).thenReturn( + confirm); + } + + @After + public void tearDown() + throws OpenRDFException + { + manager.shutDown(); + } + + @Test + public final void testSafeDrop() + throws RepositoryException, IOException + { + setUserDropConfirm(true); + assertThat(manager.isSafeToRemove(PROXY_ID), is(equalTo(true))); + drop.execute("drop", PROXY_ID); + verify(streams).writeln("Dropped repository '" + PROXY_ID + "'"); + assertThat(manager.isSafeToRemove(MEMORY_MEMBER_ID1), is(equalTo(true))); + drop.execute("drop", MEMORY_MEMBER_ID1); + verify(streams).writeln("Dropped repository '" + MEMORY_MEMBER_ID1 + "'"); + } + + @Test + public final void testUnsafeDropCancel() + throws RepositoryException, IOException + { + setUserDropConfirm(true); + assertThat(manager.isSafeToRemove(MEMORY_MEMBER_ID1), is(equalTo(false))); + when(streams.askProceed(startsWith("WARNING: dropping this repository may break"), anyBoolean())).thenReturn( + false); + drop.execute("drop", MEMORY_MEMBER_ID1); + verify(streams).writeln("Drop aborted"); + } + + @Test + public final void testUserAbortedUnsafeDropBeforeWarning() + throws IOException + { + setUserDropConfirm(false); + drop.execute("drop", MEMORY_MEMBER_ID1); + verify(streams, never()).askProceed(startsWith("WARNING: dropping this repository may break"), + anyBoolean()); + verify(streams).writeln("Drop aborted"); + } +} diff --git a/core/console/src/test/java/org/eclipse/rdf4j/console/FederateTest.java b/core/console/src/test/java/org/eclipse/rdf4j/console/FederateTest.java new file mode 100644 index 00000000000..b1e30aad087 --- /dev/null +++ b/core/console/src/test/java/org/eclipse/rdf4j/console/FederateTest.java @@ -0,0 +1,298 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.console; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.console.ConsoleState; +import org.eclipse.rdf4j.console.Federate; +import org.eclipse.rdf4j.console.PrintHelp; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.config.RepositoryImplConfig; +import org.eclipse.rdf4j.repository.http.config.HTTPRepositoryConfig; +import org.eclipse.rdf4j.repository.http.config.HTTPRepositoryFactory; +import org.eclipse.rdf4j.repository.manager.LocalRepositoryManager; +import org.eclipse.rdf4j.repository.sail.config.ProxyRepositoryConfig; +import org.eclipse.rdf4j.repository.sail.config.ProxyRepositoryFactory; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.repository.sparql.config.SPARQLRepositoryConfig; +import org.eclipse.rdf4j.repository.sparql.config.SPARQLRepositoryFactory; +import org.eclipse.rdf4j.sail.federation.config.FederationConfig; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * Unit tests for {@link Federate}. + * + * @author Dale Visser + */ +public class FederateTest extends AbstractCommandTest { + + private static final String FED_ID = "fedID"; + + private static final String MEMORY_MEMBER_ID1 = "alien"; + + private static final String MEMORY_MEMBER_ID2 = "scary"; + + private static final String HTTP_MEMBER_ID = "http"; + + private static final String HTTP2_MEMBER_ID = "http2"; + + private static final String SPARQL_MEMBER_ID = "sparql"; + + private static final String SPARQL2_MEMBER_ID = "sparql2"; + + private static final String FED_DESCRIPTION = "Test Federation Title"; + + private Federate federate; + + @Rule + public final TemporaryFolder LOCATION = new TemporaryFolder(); + + @Before + public void prepareManager() + throws UnsupportedEncodingException, IOException, OpenRDFException + { + manager = new LocalRepositoryManager(LOCATION.getRoot()); + manager.initialize(); + addRepositories(MEMORY_MEMBER_ID1, MEMORY_MEMBER_ID2, HTTP_MEMBER_ID, HTTP2_MEMBER_ID, + SPARQL_MEMBER_ID, SPARQL2_MEMBER_ID); + ConsoleState state = mock(ConsoleState.class); + when(state.getManager()).thenReturn(manager); + when(streams.readln("Federation Description (optional):")).thenReturn(FED_DESCRIPTION); + federate = new Federate(streams, state); + } + + + @After + public void tearDown() + throws OpenRDFException + { + manager.shutDown(); + } + + private void execute(String... args) + throws IOException + { + List execArgs = new ArrayList(args.length + 1); + execArgs.add("federate"); + Collections.addAll(execArgs, args); + federate.execute(execArgs.toArray(new String[execArgs.size()])); + } + + @Test + public void noArgumentsPrintsHelp() + throws IOException, OpenRDFException + { + execute(); + verify(streams).writeln(PrintHelp.FEDERATE); + } + + @Test + public void oneArgumentPrintsHelp() + throws IOException, OpenRDFException + { + execute(FED_ID); + verify(streams).writeln(PrintHelp.FEDERATE); + } + + @Test + public void twoArgumentsPrintsHelp() + throws IOException, OpenRDFException + { + execute(FED_ID, MEMORY_MEMBER_ID1); + verify(streams).writeln(PrintHelp.FEDERATE); + } + + @Test + public void invalidArgumentPrintsError() + throws IOException, OpenRDFException + { + execute("type=memory", FED_ID, MEMORY_MEMBER_ID1, MEMORY_MEMBER_ID2); + verifyFailure(); + } + + @Test + public void duplicateMembersPrintsError() + throws IOException, OpenRDFException + { + execute(FED_ID, MEMORY_MEMBER_ID1, MEMORY_MEMBER_ID1); + verifyFailure(); + } + + @Test + public void fedSameAsMemberPrintsError() + throws IOException, OpenRDFException + { + execute(FED_ID, MEMORY_MEMBER_ID1, FED_ID, MEMORY_MEMBER_ID1); + verifyFailure(); + } + + @Test + public void sparqlAndNotReadOnlyPrintsError() + throws IOException, OpenRDFException + { + execute("readonly=false", FED_ID, SPARQL_MEMBER_ID, SPARQL2_MEMBER_ID); + verifyFailure(SPARQL_MEMBER_ID + " is read-only."); + verifyFailure(SPARQL2_MEMBER_ID + " is read-only."); + } + + @Test + public void fedAlreadyExistsPrintsSpecificError() + throws IOException, OpenRDFException + { + execute(MEMORY_MEMBER_ID1, FED_ID, MEMORY_MEMBER_ID2); + verifyFailure(MEMORY_MEMBER_ID1 + " already exists."); + } + + @Test + public void nonexistentMemberPrintsSpecificError() + throws IOException, OpenRDFException + { + execute(FED_ID, MEMORY_MEMBER_ID1, "FreeLunch"); + verifyFailure("FreeLunch does not exist."); + } + + @Test + public void federateMemoryMembersSuccess() + throws UnsupportedEncodingException, IOException, RepositoryException, RepositoryConfigException + { + execute(FED_ID, MEMORY_MEMBER_ID1, MEMORY_MEMBER_ID2); + verifySuccess(ProxyRepositoryFactory.REPOSITORY_TYPE, ProxyRepositoryFactory.REPOSITORY_TYPE); + long expectedSize = getSize(MEMORY_MEMBER_ID1) + getSize(MEMORY_MEMBER_ID2); + assertThat(getSize(FED_ID), is(equalTo(expectedSize))); + } + + private long getSize(String memberID) + throws RepositoryException, RepositoryConfigException + { + RepositoryConnection connection = manager.getRepository(memberID).getConnection(); + try { + return connection.size(); + } + finally { + connection.close(); + } + } + + @Test + public void federateSucceedsWithHTTPandSPARQLmembers() + throws UnsupportedEncodingException, IOException, OpenRDFException + { + execute(FED_ID, HTTP_MEMBER_ID, SPARQL_MEMBER_ID); + verifySuccess(HTTPRepositoryFactory.REPOSITORY_TYPE, SPARQLRepositoryFactory.REPOSITORY_TYPE); + } + + @Test + public void federateHTTPtypeSucceeds() + throws IOException, OpenRDFException + { + execute(FED_ID, HTTP_MEMBER_ID, HTTP2_MEMBER_ID); + verifySuccess(HTTPRepositoryFactory.REPOSITORY_TYPE, HTTPRepositoryFactory.REPOSITORY_TYPE); + } + + @Test + public void federateSPARQLtypeSucceeds() + throws IOException, OpenRDFException + { + execute(FED_ID, SPARQL_MEMBER_ID, SPARQL2_MEMBER_ID); + verifySuccess(SPARQLRepositoryFactory.REPOSITORY_TYPE, SPARQLRepositoryFactory.REPOSITORY_TYPE); + } + + @Test + public void successWithNonDefaultReadonlyAndDistinct() + throws IOException, RepositoryException, RepositoryConfigException + { + execute(FED_ID, "distinct=true", "readonly=false", MEMORY_MEMBER_ID1, MEMORY_MEMBER_ID2); + verifySuccess(false, true, ProxyRepositoryFactory.REPOSITORY_TYPE, + ProxyRepositoryFactory.REPOSITORY_TYPE); + long expectedSize = getSize(MEMORY_MEMBER_ID1) + getSize(MEMORY_MEMBER_ID2); + assertThat(getSize(FED_ID), is(equalTo(expectedSize))); + } + + @Test + public void fullyHeterogeneousSuccess() + throws IOException, RepositoryException, RepositoryConfigException + { + execute(FED_ID, SPARQL_MEMBER_ID, MEMORY_MEMBER_ID1, HTTP_MEMBER_ID); + verifySuccess(SPARQLRepositoryFactory.REPOSITORY_TYPE, ProxyRepositoryFactory.REPOSITORY_TYPE, + HTTPRepositoryFactory.REPOSITORY_TYPE); + } + + private void verifySuccess(String... memberTypes) + throws RepositoryException, RepositoryConfigException, IOException + { + verifySuccess(true, false, memberTypes); + } + + private void verifySuccess(boolean readonly, boolean distinct, String... memberTypes) + throws RepositoryException, RepositoryConfigException, IOException + { + assertThat(manager.hasRepositoryConfig(FED_ID), is(equalTo(true))); + verify(streams, times(1)).writeln("Federation created."); + verify(streams, never()).writeError(anyString()); + verify(streams, times(1)).readln("Federation Description (optional):"); + assertThat(manager.getRepositoryInfo(FED_ID).getDescription(), is(equalTo(FED_DESCRIPTION))); + SailRepositoryConfig sailRepoConfig = (SailRepositoryConfig)manager.getRepositoryConfig(FED_ID).getRepositoryImplConfig(); + FederationConfig fedSailConfig = (FederationConfig)sailRepoConfig.getSailImplConfig(); + assertThat(fedSailConfig.isReadOnly(), is(equalTo(readonly))); + assertThat(fedSailConfig.isDistinct(), is(equalTo(distinct))); + List members = fedSailConfig.getMembers(); + assertThat(members.size(), is(equalTo(memberTypes.length))); + int i = 0; + for (RepositoryImplConfig ric : members) { + String memberType = memberTypes[i]; + i++; + assertThat(ric.getType(), is(equalTo(memberType))); + Class implType; + if (HTTPRepositoryFactory.REPOSITORY_TYPE.equals(memberType)) { + implType = HTTPRepositoryConfig.class; + } + else if (SPARQLRepositoryFactory.REPOSITORY_TYPE.equals(memberType)) { + implType = SPARQLRepositoryConfig.class; + } + else { + implType = ProxyRepositoryConfig.class; + } + assertThat(ric, is(instanceOf(implType))); + } + } + + private void verifyFailure(String... error) + throws RepositoryException, RepositoryConfigException + { + if (error.length > 0) { + verify(streams).writeError(error[0]); + } + else { + verify(streams).writeError(anyString()); + } + assertThat(manager.hasRepositoryConfig(FED_ID), is(equalTo(false))); + } +} \ No newline at end of file diff --git a/core/console/src/test/java/org/eclipse/rdf4j/console/package-info.java b/core/console/src/test/java/org/eclipse/rdf4j/console/package-info.java new file mode 100644 index 00000000000..0be944756ea --- /dev/null +++ b/core/console/src/test/java/org/eclipse/rdf4j/console/package-info.java @@ -0,0 +1,13 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/** + * Unit tests for the OpenRDF Console application. + * + * @author Dale Visser + */ +package org.eclipse.rdf4j.console; \ No newline at end of file diff --git a/core/console/src/test/resources/federate/alien-config.ttl b/core/console/src/test/resources/federate/alien-config.ttl new file mode 100644 index 00000000000..f739a784da9 --- /dev/null +++ b/core/console/src/test/resources/federate/alien-config.ttl @@ -0,0 +1,17 @@ +@prefix rdfs: . +@prefix rep: . +@prefix sr: . +@prefix sail: . +@prefix ms: . + +[] a rep:Repository ; + rep:repositoryID "alien" ; + rdfs:label "Worthwhile Alien Movies" ; + rep:repositoryImpl [ + rep:repositoryType "openrdf:SailRepository" ; + sr:sailImpl [ + sail:sailType "openrdf:MemoryStore" ; + ms:persist true ; + ms:syncDelay 0 + ] + ]. diff --git a/core/console/src/test/resources/federate/alien.ttl b/core/console/src/test/resources/federate/alien.ttl new file mode 100644 index 00000000000..1fb68c9edbc --- /dev/null +++ b/core/console/src/test/resources/federate/alien.ttl @@ -0,0 +1,14 @@ +@prefix dc: . +@prefix xsd: . +@base . + + dc:title "Alien"@en ; + dc:date "1979-05-25T00:00:00Z"^^xsd:dateTime . + dc:title "Aliens"@en ; + dc:date "1986-07-18T00:00:00Z"^^xsd:dateTime . + dc:title "Alien³"@en ; + dc:date "1992-05-22T00:00:00Z"^^xsd:dateTime . + dc:title "Alien: Resurrection"@en ; + dc:date "1997-11-26T00:00:00Z"^^xsd:dateTime . + dc:title "Prometheus"@en ; + dc:date "2012-06-08T00:00:00Z"^^xsd:dateTime . diff --git a/core/console/src/test/resources/federate/http-config.ttl b/core/console/src/test/resources/federate/http-config.ttl new file mode 100644 index 00000000000..0c8aaa47f1e --- /dev/null +++ b/core/console/src/test/resources/federate/http-config.ttl @@ -0,0 +1,11 @@ +@prefix rdfs: . +@prefix rep: . +@prefix hr: . + +[] a rep:Repository ; + rep:repositoryID "http" ; + rdfs:label "HTTP" ; + rep:repositoryImpl [ + rep:repositoryType "openrdf:HTTPRepository" ; + hr:repositoryURL + ]. diff --git a/core/console/src/test/resources/federate/http2-config.ttl b/core/console/src/test/resources/federate/http2-config.ttl new file mode 100644 index 00000000000..eb3de347e5b --- /dev/null +++ b/core/console/src/test/resources/federate/http2-config.ttl @@ -0,0 +1,11 @@ +@prefix rdfs: . +@prefix rep: . +@prefix hr: . + +[] a rep:Repository ; + rep:repositoryID "http2" ; + rdfs:label "HTTP2" ; + rep:repositoryImpl [ + rep:repositoryType "openrdf:HTTPRepository" ; + hr:repositoryURL + ]. diff --git a/core/console/src/test/resources/federate/scary-config.ttl b/core/console/src/test/resources/federate/scary-config.ttl new file mode 100644 index 00000000000..fda57439960 --- /dev/null +++ b/core/console/src/test/resources/federate/scary-config.ttl @@ -0,0 +1,17 @@ +@prefix rdfs: . +@prefix rep: . +@prefix sr: . +@prefix sail: . +@prefix ms: . + +[] a rep:Repository ; + rep:repositoryID "scary" ; + rdfs:label "Scary Movies" ; + rep:repositoryImpl [ + rep:repositoryType "openrdf:SailRepository" ; + sr:sailImpl [ + sail:sailType "openrdf:MemoryStore" ; + ms:persist true ; + ms:syncDelay 0 + ] + ]. diff --git a/core/console/src/test/resources/federate/scary.ttl b/core/console/src/test/resources/federate/scary.ttl new file mode 100644 index 00000000000..a58f7a2fd26 --- /dev/null +++ b/core/console/src/test/resources/federate/scary.ttl @@ -0,0 +1,21 @@ +@prefix xsd: . +@prefix dc: . +@prefix dcterms: . +@prefix imdb: . +@prefix fake: . + +imdb:tt0175142 dc:title "Scary Movie"@en ; + dc:date "2000-07-07T00:00:00Z"^^xsd:dateTime ; + dc:type fake:comedy ; + dcterms:references imdb:tt0119345 ; + dcterms:references imdb:tt0117571 . +imdb:tt0119345 dc:title "I Know What You Did Last Summer"@en ; + dc:date "1997-10-17T00:00:00Z"^^xsd:dateTime ; + dc:type fake:thriller . +imdb:tt0117571 dc:title "Scream"@en ; + dc:date "1996-12-20T00:00:00Z"^^xsd:dateTime ; + dc:type fake:thriller . + + + + diff --git a/core/console/src/test/resources/federate/sparql-config.ttl b/core/console/src/test/resources/federate/sparql-config.ttl new file mode 100644 index 00000000000..e86dd65bbdf --- /dev/null +++ b/core/console/src/test/resources/federate/sparql-config.ttl @@ -0,0 +1,11 @@ +@prefix rdfs: . +@prefix rep: . +@prefix sparql: . + +[] a rep:Repository ; + rep:repositoryID "sparql" ; + rdfs:label "SPARQL" ; + rep:repositoryImpl [ + rep:repositoryType "openrdf:SPARQLRepository" ; + sparql:query-endpoint + ]. diff --git a/core/console/src/test/resources/federate/sparql2-config.ttl b/core/console/src/test/resources/federate/sparql2-config.ttl new file mode 100644 index 00000000000..6793338e7c7 --- /dev/null +++ b/core/console/src/test/resources/federate/sparql2-config.ttl @@ -0,0 +1,11 @@ +@prefix rdfs: . +@prefix rep: . +@prefix sparql: . + +[] a rep:Repository ; + rep:repositoryID "sparql2" ; + rdfs:label "SPARQL2" ; + rep:repositoryImpl [ + rep:repositoryType "openrdf:SPARQLRepository" ; + sparql:query-endpoint + ]. diff --git a/core/console/src/test/resources/logback-test.xml b/core/console/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..4a6f17fbfa4 --- /dev/null +++ b/core/console/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + diff --git a/core/http/client/pom.xml b/core/http/client/pom.xml new file mode 100644 index 00000000000..3379855a80c --- /dev/null +++ b/core/http/client/pom.xml @@ -0,0 +1,83 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-http + 4.1.0-SNAPSHOT + + + rdf4j-http-client + + RDF4J: HTTP client + Client functionality for communicating with an RDF4J server over HTTP. + + + + ${project.groupId} + rdf4j-http-protocol + ${project.version} + + + ${project.groupId} + rdf4j-query + ${project.version} + + + ${project.groupId} + rdf4j-queryresultio-api + ${project.version} + + + ${project.groupId} + rdf4j-rio-api + ${project.version} + + + ${project.groupId} + rdf4j-model + ${project.version} + + + ${project.groupId} + rdf4j-repository-api + ${project.version} + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + org.apache.httpcomponents + httpclient + + + + + commons-codec + commons-codec + + + + org.slf4j + slf4j-api + + + + org.slf4j + jcl-over-slf4j + test + + + + junit + junit + test + + + + + diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/BackgroundGraphResult.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/BackgroundGraphResult.java new file mode 100644 index 00000000000..5db0d412a3e --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/BackgroundGraphResult.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.UndeclaredThrowableException; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; + +import org.eclipse.rdf4j.common.iteration.IterationWrapper; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.query.GraphQueryResult; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.rio.RDFHandler; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; + +/** + * Provides concurrent access to statements as they are being parsed. + * + * @author James Leigh + */ +public class BackgroundGraphResult extends IterationWrapper implements + GraphQueryResult, Runnable, RDFHandler +{ + + private volatile boolean closed; + + private RDFParser parser; + + private Charset charset; + + private InputStream in; + + private String baseURI; + + private CountDownLatch namespacesReady = new CountDownLatch(1); + + private Map namespaces = new ConcurrentHashMap(); + + private QueueCursor queue; + + public BackgroundGraphResult(RDFParser parser, InputStream in, Charset charset, String baseURI) { + this(new QueueCursor(10), parser, in, charset, baseURI); + } + + public BackgroundGraphResult(QueueCursor queue, RDFParser parser, InputStream in, + Charset charset, String baseURI) + { + super(queue); + this.queue = queue; + this.parser = parser; + this.in = in; + this.charset = charset; + this.baseURI = baseURI; + } + + public boolean hasNext() + throws QueryEvaluationException + { + return queue.hasNext(); + } + + public Statement next() + throws QueryEvaluationException + { + return queue.next(); + } + + public void remove() + throws QueryEvaluationException + { + queue.remove(); + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + try { + super.handleClose(); + } + finally { + closed = true; + try { + in.close(); + } + catch (IOException e) { + throw new QueryEvaluationException(e); + } + finally { + queue.close(); + } + } + } + + public void run() { + try { + parser.setRDFHandler(this); + if (charset == null) { + parser.parse(in, baseURI); + } + else { + parser.parse(new InputStreamReader(in, charset), baseURI); + } + } + catch (RDFHandlerException e) { + // parsing was cancelled or interrupted + } + catch (RDFParseException e) { + queue.toss(e); + } + catch (IOException e) { + queue.toss(e); + } + finally { + queue.done(); + namespacesReady.countDown(); + } + } + + public void startRDF() + throws RDFHandlerException + { + // no-op + } + + public Map getNamespaces() { + try { + namespacesReady.await(); + return namespaces; + } + catch (InterruptedException e) { + throw new UndeclaredThrowableException(e); + } + } + + public void handleComment(String comment) + throws RDFHandlerException + { + // ignore + } + + public void handleNamespace(String prefix, String uri) + throws RDFHandlerException + { + namespaces.put(prefix, uri); + } + + public void handleStatement(Statement st) + throws RDFHandlerException + { + namespacesReady.countDown(); + try { + queue.put(st); + } + catch (InterruptedException e) { + throw new RDFHandlerException(e); + } + if (closed) + throw new RDFHandlerException("Result closed"); + } + + public void endRDF() + throws RDFHandlerException + { + namespacesReady.countDown(); + } + +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/BackgroundTupleResult.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/BackgroundTupleResult.java new file mode 100644 index 00000000000..8b54f6d1a4f --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/BackgroundTupleResult.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.TupleQueryResultHandler; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; +import org.eclipse.rdf4j.query.impl.IteratingTupleQueryResult; +import org.eclipse.rdf4j.query.resultio.QueryResultParseException; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultParser; + +/** + * Provides concurrent access to tuple results as they are being parsed. + * + * @author James Leigh + */ +public class BackgroundTupleResult extends IteratingTupleQueryResult implements Runnable, TupleQueryResultHandler { + + private volatile boolean closed; + + private TupleQueryResultParser parser; + + private InputStream in; + + private QueueCursor queue; + + private List bindingNames; + + private CountDownLatch bindingNamesReady = new CountDownLatch(1); + + public BackgroundTupleResult(TupleQueryResultParser parser, InputStream in) { + this(new QueueCursor(10), parser, in); + } + + public BackgroundTupleResult(QueueCursor queue, TupleQueryResultParser parser, InputStream in) + { + super(Collections. emptyList(), queue); + this.queue = queue; + this.parser = parser; + this.in = in; + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + try { + try { + closed = true; + super.handleClose(); + } finally { + in.close(); + } + } + catch (IOException e) { + throw new QueryEvaluationException(e); + } + } + + @Override + public List getBindingNames() { + try { + bindingNamesReady.await(); + queue.checkException(); + return bindingNames; + } + catch (InterruptedException e) { + throw new UndeclaredThrowableException(e); + } + catch (QueryEvaluationException e) { + throw new UndeclaredThrowableException(e); + } + } + + @Override + public void run() { + try { + parser.setQueryResultHandler(this); + parser.parseQueryResult(in); + } + catch (QueryResultHandlerException e) { + // parsing cancelled or interrupted + } + catch (QueryResultParseException e) { + queue.toss(e); + } + catch (IOException e) { + queue.toss(e); + } + finally { + queue.done(); + bindingNamesReady.countDown(); + } + } + + @Override + public void startQueryResult(List bindingNames) + throws TupleQueryResultHandlerException + { + this.bindingNames = bindingNames; + bindingNamesReady.countDown(); + } + + @Override + public void handleSolution(BindingSet bindingSet) + throws TupleQueryResultHandlerException + { + try { + queue.put(bindingSet); + } + catch (InterruptedException e) { + throw new TupleQueryResultHandlerException(e); + } + if (closed) + throw new TupleQueryResultHandlerException("Result closed"); + } + + @Override + public void endQueryResult() + throws TupleQueryResultHandlerException + { + // no-op + } + + @Override + public void handleBoolean(boolean value) + throws QueryResultHandlerException + { + throw new UnsupportedOperationException("Cannot handle boolean results"); + } + + @Override + public void handleLinks(List linkUrls) + throws QueryResultHandlerException + { + // ignore + } +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/HttpClientDependent.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/HttpClientDependent.java new file mode 100644 index 00000000000..d580c6a895b --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/HttpClientDependent.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import org.apache.http.client.HttpClient; + +/** + * Common interface for objects, such as Repository and RepositoryConnection, + * that are dependent on {@link HttpClient}. + * + * @author James Leigh + */ +public interface HttpClientDependent { + + /** + * {@link HttpClient} that has been assigned or has been used by this object. + * The life cycle might not be or might be tied to this object, depending on + * whether {@link HttpClient} was passed to or created by this object + * respectively. + * + * @return an {@link HttpClient} instance or null + */ + HttpClient getHttpClient(); + + /** + * Assign an {@link HttpClient} that this object should use. The life cycle + * of the given {@link HttpClient} is independent of this object. Closing or + * shutting down this object does not have any impact on the given client. + * Callers must ensure that the given client is properly closed elsewhere. + * + * @param client + */ + void setHttpClient(HttpClient client); +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/QueueCursor.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/QueueCursor.java new file mode 100644 index 00000000000..fd34a73feba --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/QueueCursor.java @@ -0,0 +1,192 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * Makes working with a queue easier by adding the methods {@link #done()} and + * {@link #toss(Exception)} and automatically converting the exception into a + * QueryEvaluationException with an appropriate stack trace. + * + * @author James Leigh + */ +public class QueueCursor extends LookAheadIteration { + + private volatile boolean done; + + private BlockingQueue queue; + + private E afterLast = createAfterLast(); + + private volatile Queue exceptions = new LinkedList(); + + /** + * Creates an QueueCursor with the given (fixed) capacity and + * default access policy. + * + * @param capacity + * the capacity of this queue + */ + public QueueCursor(int capacity) { + this(capacity, false); + } + + /** + * Creates an QueueCursor with the given (fixed) capacity and the + * specified access policy. + * + * @param capacity + * the capacity of this queue + * @param fair + * if true then queue accesses for threads blocked on + * insertion or removal, are processed in FIFO order; if + * false the access order is unspecified. + */ + public QueueCursor(int capacity, boolean fair) { + this.queue = new ArrayBlockingQueue(capacity, fair); + } + + /** + * The next time {@link #next()} is called this exception will be thrown. If + * it is not a QueryEvaluationException or RuntimeException it will be + * wrapped in a QueryEvaluationException. + */ + public void toss(Exception exception) { + synchronized (exceptions) { + exceptions.add(exception); + } + } + + /** + * Adds another item to the queue, blocking while the queue is full. + */ + public void put(E item) + throws InterruptedException + { + if (!done) { + queue.put(item); + } + } + + /** + * Indicates the method {@link #put(Object)} will not be called in the queue + * anymore. + */ + public void done() { + done = true; + try { + queue.add(afterLast); + } + catch (IllegalStateException e) { + // no thread is waiting on this queue anyway + } + } + + /** + * Returns the next item in the queue or throws an exception. + */ + @Override + public E getNextElement() + throws QueryEvaluationException + { + try { + checkException(); + E take; + if (done) { + take = queue.poll(); + } + else { + take = queue.take(); + if (done) { + done(); // in case the queue was full before + } + } + if (isAfterLast(take)) { + checkException(); + done(); // put afterLast back for others + return null; + } + return take; + } + catch (InterruptedException e) { + checkException(); + throw new QueryEvaluationException(e); + } + } + + @Override + public void handleClose() + throws QueryEvaluationException + { + done = true; + do { + queue.clear(); // ensure extra room is available + } + while (!queue.offer(afterLast)); + checkException(); + } + + public void checkException() + throws QueryEvaluationException + { + synchronized (exceptions) { + if (!exceptions.isEmpty()) { + try { + throw exceptions.remove(); + } + catch (OpenRDFException e) { + if (e instanceof QueryEvaluationException) { + List stack = new ArrayList(); + stack.addAll(Arrays.asList(e.getStackTrace())); + StackTraceElement[] thisStack = new Throwable().getStackTrace(); + stack.addAll(Arrays.asList(thisStack).subList(1, thisStack.length)); + e.setStackTrace(stack.toArray(new StackTraceElement[stack.size()])); + throw e; + } + else { + throw new QueryEvaluationException(e); + } + } + catch (RuntimeException e) { + // any RuntimeException that is not an OpenRDFException should be + // reported as-is + List stack = new ArrayList(); + stack.addAll(Arrays.asList(e.getStackTrace())); + StackTraceElement[] thisStack = new Throwable().getStackTrace(); + stack.addAll(Arrays.asList(thisStack)); + e.setStackTrace(stack.toArray(new StackTraceElement[stack.size()])); + throw e; + } + catch (Throwable e) { + throw new QueryEvaluationException(e); + } + } + } + } + + private boolean isAfterLast(E take) { + return take == null || take == afterLast; + } + + @SuppressWarnings("unchecked") + private E createAfterLast() { + return (E)new Object(); + } + +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClient.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClient.java new file mode 100644 index 00000000000..ac3d21667e5 --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClient.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import org.apache.http.client.HttpClient; + +/** + * Manages remote HTP connections. + * + * @author James Leigh + */ +public interface SesameClient { + + /** + * @return Returns the httpClient. + */ + HttpClient getHttpClient(); + + /** + * Creates a new session to the remote SPARQL endpoint to manage the auth + * state. + */ + SparqlSession createSparqlSession(String queryEndpointUrl, String updateEndpointUrl); + + /** + * Creates a new session to the remote Sesame server to manage the auth + * state. + */ + SesameSession createSesameSession(String serverURL); + + /** + * Closes any remaining TCP connections and threads used by the sessions + * created by this object. + */ + void shutDown(); + +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClientDependent.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClientDependent.java new file mode 100644 index 00000000000..a027d724b42 --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClientDependent.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +/** + * Common interface for objects, such as Repository and RepositoryConnection, + * that are dependent on {@link SesameClient}. + * + * @author James Leigh + */ +public interface SesameClientDependent { + + /** + * {@link SesameClient} that has been assigned or has been used by this + * object. The life cycle might not be or might be tied to this object, + * depending on whether {@link SesameClient} was passed to or created by this + * object respectively. + * + * @return a {@link SesameClient} instance or null + */ + SesameClient getSesameClient(); + + /** + * Assign an {@link SesameClient} that this object should use. The life cycle + * of the given {@link SesameClient} is independent of this object. Closing + * or shutting down this object does not have any impact on the given client. + * Callers must ensure that the given client is properly closed elsewhere. + * + * @param client + */ + void setSesameClient(SesameClient client); +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClientImpl.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClientImpl.java new file mode 100644 index 00000000000..9a26134f39d --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameClientImpl.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.apache.http.client.HttpClient; +import org.apache.http.client.utils.HttpClientUtils; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.eclipse.rdf4j.http.client.util.HttpClientBuilders; + +/** + * Uses {@link HttpClient} to manage HTTP connections. + * + * @author James Leigh + */ +public class SesameClientImpl implements SesameClient, HttpClientDependent { + + /** independent life cycle */ + private HttpClient httpClient; + + /** dependent life cycle */ + private CloseableHttpClient dependentClient; + + private ExecutorService executor = null; + + /** + * Optional {@link HttpClientBuilder} to create the inner + * {@link #httpClient} (if not provided externally) + */ + private HttpClientBuilder httpClientBuilder; + + /*--------------* + * Constructors * + *--------------*/ + + public SesameClientImpl() { + initialize(); + } + + public SesameClientImpl(CloseableHttpClient dependentClient, ExecutorService dependentExecutorService) { + this.httpClient = this.dependentClient = dependentClient; + this.executor = dependentExecutorService; + } + + /** + * @return Returns the httpClient. + */ + public synchronized HttpClient getHttpClient() { + if (httpClient == null) { + httpClient = dependentClient = createHttpClient(); + } + return httpClient; + } + + /** + * @param httpClient The httpClient to use for remote/service calls. + */ + public synchronized void setHttpClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + /** + * Set an optional {@link HttpClientBuilder} to create the inner + * {@link #httpClient} (if the latter is not provided externally + * as dependent client). + * + * @param httpClientBuilder the builder for the managed HttpClient + * @see HttpClientBuilders + */ + public synchronized void setHttpClientBuilder(HttpClientBuilder httpClientBuilder) { + this.httpClientBuilder = httpClientBuilder; + } + + private CloseableHttpClient createHttpClient() { + if (this.httpClientBuilder!=null) { + return httpClientBuilder.build(); + } + return HttpClients.createSystem(); + } + + @Override + public synchronized SparqlSession createSparqlSession(String queryEndpointUrl, String updateEndpointUrl) { + SparqlSession session = new SparqlSession(getHttpClient(), executor); + session.setQueryURL(queryEndpointUrl); + session.setUpdateURL(updateEndpointUrl); + return session; + } + + @Override + public synchronized SesameSession createSesameSession(String serverURL) { + SesameSession session = new SesameSession(getHttpClient(), executor); + session.setServerURL(serverURL); + return session; + } + + /*-----------------* + * Get/set methods * + *-----------------*/ + + @Override + public synchronized void shutDown() { + if (executor != null) { + executor.shutdown(); + executor = null; + } + if (dependentClient != null) { + HttpClientUtils.closeQuietly(dependentClient); + dependentClient = null; + } + } + + /** + * (re)initializes the connection manager and HttpClient (if not already + * done), for example after a shutdown has been invoked earlier. Invoking + * this method multiple times will have no effect. + */ + public synchronized void initialize() { + if (executor == null) { + executor = Executors.newCachedThreadPool(); + } + } + +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameSession.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameSession.java new file mode 100644 index 00000000000..27de5fd091a --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SesameSession.java @@ -0,0 +1,870 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.AbstractHttpEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.InputStreamEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.OpenRDFUtil; +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.protocol.UnauthorizedException; +import org.eclipse.rdf4j.http.protocol.Protocol.Action; +import org.eclipse.rdf4j.http.protocol.transaction.TransactionWriter; +import org.eclipse.rdf4j.http.protocol.transaction.operations.TransactionOperation; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.impl.SimpleIRI; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryInterruptedException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.TupleQueryResultHandler; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; +import org.eclipse.rdf4j.query.impl.TupleQueryResultBuilder; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFHandler; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; + +/** + * An {@link SparqlSession} subclass which bundles special functionality for + * Sesame remote repositories. + * + * @author Andreas Schwarte + */ +public class SesameSession extends SparqlSession { + + private String serverURL; + + private String transactionURL; + + public SesameSession(HttpClient client, ExecutorService executor) { + super(client, executor); + + // we want to preserve bnode ids to allow Sesame API methods to match + // blank nodes. + getParserConfig().set(BasicParserSettings.PRESERVE_BNODE_IDS, true); + + // Sesame client has preference for binary response formats, as these are + // most performant + setPreferredTupleQueryResultFormat(TupleQueryResultFormat.BINARY); + setPreferredRDFFormat(RDFFormat.BINARY); + } + + public void setServerURL(String serverURL) { + if (serverURL == null) { + throw new IllegalArgumentException("serverURL must not be null"); + } + + this.serverURL = serverURL; + } + + public String getServerURL() { + return serverURL; + } + + public String getRepositoryURL() { + return this.getQueryURL(); + } + + public void setRepository(String repositoryURL) { + // Try to parse the server URL from the repository URL + Pattern urlPattern = Pattern.compile("(.*)/" + Protocol.REPOSITORIES + "/[^/]*/?"); + Matcher matcher = urlPattern.matcher(repositoryURL); + + if (matcher.matches() && matcher.groupCount() == 1) { + setServerURL(matcher.group(1)); + } + + setQueryURL(repositoryURL); + } + + protected void checkRepositoryURL() { + if (getRepositoryURL() == null) { + throw new IllegalStateException("Repository URL has not been set"); + } + } + + protected void checkServerURL() { + if (serverURL == null) { + throw new IllegalStateException("Server URL has not been set"); + } + } + + @Override + public String getUpdateURL() { + return Protocol.getStatementsLocation(getQueryURL()); + } + + /*-----------------* + * Repository list * + *-----------------*/ + + public TupleQueryResult getRepositoryList() + throws IOException, RepositoryException, UnauthorizedException, QueryInterruptedException + { + try { + TupleQueryResultBuilder builder = new TupleQueryResultBuilder(); + getRepositoryList(builder); + return builder.getQueryResult(); + } + catch (TupleQueryResultHandlerException e) { + // Found a bug in TupleQueryResultBuilder? + throw new RuntimeException(e); + } + } + + public void getRepositoryList(TupleQueryResultHandler handler) + throws IOException, TupleQueryResultHandlerException, RepositoryException, UnauthorizedException, + QueryInterruptedException + { + checkServerURL(); + + HttpGet method = new HttpGet(Protocol.getRepositoriesLocation(serverURL)); + + try { + getTupleQueryResult(method, handler); + } + catch (MalformedQueryException e) { + // This shouldn't happen as no queries are involved + logger.warn("Server reported unexpected malfored query error", e); + throw new RepositoryException(e.getMessage(), e); + } + } + + /*------------------* + * Protocol version * + *------------------*/ + + public String getServerProtocol() + throws IOException, RepositoryException, UnauthorizedException + { + checkServerURL(); + + HttpGet method = new HttpGet(Protocol.getProtocolLocation(serverURL)); + + try { + return EntityUtils.toString(executeOK(method).getEntity()); + } + catch (RepositoryException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + /*-------------------------* + * Repository/context size * + *-------------------------*/ + + public long size(Resource... contexts) + throws IOException, RepositoryException, UnauthorizedException + { + checkRepositoryURL(); + + try { + final boolean useTransaction = transactionURL != null; + + String baseLocation = useTransaction ? appendAction(transactionURL, Action.SIZE) + : Protocol.getSizeLocation(getQueryURL()); + URIBuilder url = new URIBuilder(baseLocation); + + String[] encodedContexts = Protocol.encodeContexts(contexts); + for (int i = 0; i < encodedContexts.length; i++) { + url.addParameter(Protocol.CONTEXT_PARAM_NAME, encodedContexts[i]); + } + + final HttpUriRequest method = useTransaction ? new HttpPut(url.build()) : new HttpGet(url.build()); + + String response = EntityUtils.toString(executeOK(method).getEntity()); + try { + return Long.parseLong(response); + } + catch (NumberFormatException e) { + throw new RepositoryException("Server responded with invalid size value: " + response); + } + } + catch (URISyntaxException e) { + throw new AssertionError(e); + } + catch (RepositoryException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + public void deleteRepository(String repositoryID) + throws IOException, RepositoryException + { + + HttpUriRequest method = new HttpDelete(Protocol.getRepositoryLocation(serverURL, repositoryID)); + + try { + executeNoContent(method); + } + catch (RepositoryException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + /*---------------------------* + * Get/add/remove namespaces * + *---------------------------*/ + + public TupleQueryResult getNamespaces() + throws IOException, RepositoryException, UnauthorizedException, QueryInterruptedException + { + try { + TupleQueryResultBuilder builder = new TupleQueryResultBuilder(); + getNamespaces(builder); + return builder.getQueryResult(); + } + catch (TupleQueryResultHandlerException e) { + // Found a bug in TupleQueryResultBuilder? + throw new RuntimeException(e); + } + } + + public void getNamespaces(TupleQueryResultHandler handler) + throws IOException, TupleQueryResultHandlerException, RepositoryException, UnauthorizedException, + QueryInterruptedException + { + checkRepositoryURL(); + + HttpUriRequest method = new HttpGet(Protocol.getNamespacesLocation(getQueryURL())); + + try { + getTupleQueryResult(method, handler); + } + catch (MalformedQueryException e) { + logger.warn("Server reported unexpected malfored query error", e); + throw new RepositoryException(e.getMessage(), e); + } + } + + public String getNamespace(String prefix) + throws IOException, RepositoryException, UnauthorizedException + { + checkRepositoryURL(); + + HttpUriRequest method = new HttpGet(Protocol.getNamespacePrefixLocation(getQueryURL(), prefix)); + + try { + HttpResponse response = execute(method); + int code = response.getStatusLine().getStatusCode(); + if (code == HttpURLConnection.HTTP_OK || code == HttpURLConnection.HTTP_NOT_AUTHORITATIVE) { + return EntityUtils.toString(response.getEntity()); + } + else { + EntityUtils.consume(response.getEntity()); + return null; + } + } + catch (RepositoryException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + public void setNamespacePrefix(String prefix, String name) + throws IOException, RepositoryException, UnauthorizedException + { + checkRepositoryURL(); + + HttpPut method = new HttpPut(Protocol.getNamespacePrefixLocation(getQueryURL(), prefix)); + method.setEntity(new StringEntity(name, ContentType.create("text/plain", "UTF-8"))); + + try { + executeNoContent(method); + } + catch (RepositoryException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + public void removeNamespacePrefix(String prefix) + throws IOException, RepositoryException, UnauthorizedException + { + checkRepositoryURL(); + + HttpUriRequest method = new HttpDelete(Protocol.getNamespacePrefixLocation(getQueryURL(), prefix)); + + try { + executeNoContent(method); + } + catch (RepositoryException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + public void clearNamespaces() + throws IOException, RepositoryException, UnauthorizedException + { + checkRepositoryURL(); + + HttpUriRequest method = new HttpDelete(Protocol.getNamespacesLocation(getQueryURL())); + + try { + executeNoContent(method); + } + catch (RepositoryException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + /*-------------* + * Context IDs * + *-------------*/ + + public TupleQueryResult getContextIDs() + throws IOException, RepositoryException, UnauthorizedException, QueryInterruptedException + { + try { + TupleQueryResultBuilder builder = new TupleQueryResultBuilder(); + getContextIDs(builder); + return builder.getQueryResult(); + } + catch (TupleQueryResultHandlerException e) { + // Found a bug in TupleQueryResultBuilder? + throw new RuntimeException(e); + } + } + + public void getContextIDs(TupleQueryResultHandler handler) + throws IOException, TupleQueryResultHandlerException, RepositoryException, UnauthorizedException, + QueryInterruptedException + { + checkRepositoryURL(); + + HttpGet method = new HttpGet(Protocol.getContextsLocation(getQueryURL())); + + try { + getTupleQueryResult(method, handler); + } + catch (MalformedQueryException e) { + logger.warn("Server reported unexpected malfored query error", e); + throw new RepositoryException(e.getMessage(), e); + } + } + + /*---------------------------* + * Get/add/remove statements * + *---------------------------*/ + + public void getStatements(Resource subj, IRI pred, Value obj, boolean includeInferred, RDFHandler handler, + Resource... contexts) + throws IOException, RDFHandlerException, RepositoryException, UnauthorizedException, + QueryInterruptedException + { + checkRepositoryURL(); + + try { + final boolean useTransaction = transactionURL != null; + + String baseLocation = useTransaction ? transactionURL + : Protocol.getStatementsLocation(getQueryURL()); + URIBuilder url = new URIBuilder(baseLocation); + + if (subj != null) { + url.setParameter(Protocol.SUBJECT_PARAM_NAME, Protocol.encodeValue(subj)); + } + if (pred != null) { + url.setParameter(Protocol.PREDICATE_PARAM_NAME, Protocol.encodeValue(pred)); + } + if (obj != null) { + url.setParameter(Protocol.OBJECT_PARAM_NAME, Protocol.encodeValue(obj)); + } + for (String encodedContext : Protocol.encodeContexts(contexts)) { + url.addParameter(Protocol.CONTEXT_PARAM_NAME, encodedContext); + } + url.setParameter(Protocol.INCLUDE_INFERRED_PARAM_NAME, Boolean.toString(includeInferred)); + if (useTransaction) { + url.setParameter(Protocol.ACTION_PARAM_NAME, Action.GET.toString()); + } + + HttpUriRequest method = useTransaction ? new HttpPut(url.build()) : new HttpGet(url.build()); + + try { + getRDF(method, handler, true); + } + catch (MalformedQueryException e) { + logger.warn("Server reported unexpected malfored query error", e); + throw new RepositoryException(e.getMessage(), e); + } + } + catch (URISyntaxException e) { + throw new AssertionError(e); + } + } + + public synchronized void beginTransaction(IsolationLevel isolationLevel) + throws OpenRDFException, IOException, UnauthorizedException + { + checkRepositoryURL(); + + if (transactionURL != null) { + throw new IllegalStateException("Transaction URL is already set"); + } + + HttpPost method = new HttpPost(Protocol.getTransactionsLocation(getRepositoryURL())); + + method.setHeader("Content-Type", Protocol.FORM_MIME_TYPE + "; charset=utf-8"); + + List params = new ArrayList(); + if (isolationLevel != null) { + params.add(new BasicNameValuePair(Protocol.ISOLATION_LEVEL_PARAM_NAME, + isolationLevel.getURI().stringValue())); + } + + method.setEntity(new UrlEncodedFormEntity(params, UTF8)); + HttpResponse response = execute(method); + int code = response.getStatusLine().getStatusCode(); + + try { + if (code == HttpURLConnection.HTTP_CREATED) { + transactionURL = response.getFirstHeader("Location").getValue(); + if (transactionURL == null) { + throw new RepositoryException("no valid transaction ID received in server response."); + } + } + else { + throw new RepositoryException("unable to start transaction. HTTP error code " + code); + } + } + finally { + EntityUtils.consume(response.getEntity()); + } + } + + public synchronized void commitTransaction() + throws OpenRDFException, IOException, UnauthorizedException + { + checkRepositoryURL(); + + if (transactionURL == null) { + throw new IllegalStateException("Transaction URL has not been set"); + } + + HttpPut method = null; + try { + URIBuilder url = new URIBuilder(transactionURL); + url.addParameter(Protocol.ACTION_PARAM_NAME, Action.COMMIT.toString()); + method = new HttpPut(url.build()); + } + catch (URISyntaxException e) { + logger.error("could not create URL for transaction commit", e); + throw new RuntimeException(e); + } + + final HttpResponse response = execute(method); + try { + int code = response.getStatusLine().getStatusCode(); + if (code == HttpURLConnection.HTTP_OK) { + // we're done. + transactionURL = null; + } + else { + throw new RepositoryException("unable to commit transaction. HTTP error code " + code); + } + } + finally { + EntityUtils.consumeQuietly(response.getEntity()); + } + + } + + public synchronized void rollbackTransaction() + throws OpenRDFException, IOException, UnauthorizedException + { + checkRepositoryURL(); + + if (transactionURL == null) { + throw new IllegalStateException("Transaction URL has not been set"); + } + + String requestURL = transactionURL; + HttpDelete method = new HttpDelete(requestURL); + + final HttpResponse response = execute(method); + try { + int code = response.getStatusLine().getStatusCode(); + if (code == HttpURLConnection.HTTP_NO_CONTENT) { + // we're done. + transactionURL = null; + } + else { + throw new RepositoryException("unable to rollback transaction. HTTP error code " + code); + } + } + finally { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + + /** + * Appends the action as a parameter to the supplied url + * + * @param url + * a url on which to append the parameter. it is assumed the url has + * no parameters. + * @param action + * the action to add as a parameter + * @return the url parametrized with the supplied action + */ + private String appendAction(String url, Action action) { + return url + "?" + Protocol.ACTION_PARAM_NAME + "=" + action.toString(); + } + + /** + * Sends a transaction list as serialized XML to the server. + * + * @deprecated since 2.8.0 + * @param txn + * @throws IOException + * @throws RepositoryException + * @throws UnauthorizedException + */ + @Deprecated + public void sendTransaction(final Iterable txn) + throws IOException, RepositoryException, UnauthorizedException + { + checkRepositoryURL(); + + HttpPost method = new HttpPost(Protocol.getStatementsLocation(getQueryURL())); + + // Create a RequestEntity for the transaction data + method.setEntity(new AbstractHttpEntity() { + + public long getContentLength() { + return -1; // don't know + } + + public Header getContentType() { + return new BasicHeader("Content-Type", Protocol.TXN_MIME_TYPE); + } + + public boolean isRepeatable() { + return true; + } + + public boolean isStreaming() { + return true; + } + + public InputStream getContent() + throws IOException, IllegalStateException + { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + writeTo(buf); + return new ByteArrayInputStream(buf.toByteArray()); + } + + public void writeTo(OutputStream out) + throws IOException + { + TransactionWriter txnWriter = new TransactionWriter(); + txnWriter.serialize(txn, out); + } + }); + + try { + executeNoContent(method); + } + catch (RepositoryException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + public void addData(InputStream contents, String baseURI, RDFFormat dataFormat, Resource... contexts) + throws UnauthorizedException, RDFParseException, RepositoryException, IOException + { + upload(contents, baseURI, dataFormat, false, true, Action.ADD, contexts); + } + + public void removeData(InputStream contents, String baseURI, RDFFormat dataFormat, Resource... contexts) + throws UnauthorizedException, RDFParseException, RepositoryException, IOException + { + upload(contents, baseURI, dataFormat, false, true, Action.DELETE, contexts); + } + + public void upload(InputStream contents, String baseURI, RDFFormat dataFormat, boolean overwrite, + boolean preserveNodeIds, Resource... contexts) + throws IOException, RDFParseException, RepositoryException, UnauthorizedException + { + upload(contents, baseURI, dataFormat, overwrite, preserveNodeIds, Action.ADD, contexts); + } + + protected void upload(InputStream contents, String baseURI, RDFFormat dataFormat, boolean overwrite, + boolean preserveNodeIds, Action action, Resource... contexts) + throws IOException, RDFParseException, RepositoryException, UnauthorizedException + { + // Set Content-Length to -1 as we don't know it and we also don't want to + // cache + HttpEntity entity = new InputStreamEntity(contents, -1, + ContentType.parse(dataFormat.getDefaultMIMEType())); + upload(entity, baseURI, overwrite, preserveNodeIds, action, contexts); + } + + public void upload(final Reader contents, String baseURI, final RDFFormat dataFormat, boolean overwrite, + boolean preserveNodeIds, Resource... contexts) + throws UnauthorizedException, RDFParseException, RepositoryException, IOException + { + upload(contents, baseURI, dataFormat, overwrite, preserveNodeIds, Action.ADD, contexts); + } + + @Override + protected HttpUriRequest getQueryMethod(QueryLanguage ql, String query, String baseURI, Dataset dataset, + boolean includeInferred, int maxQueryTime, Binding... bindings) + { + RequestBuilder builder = null; + if (transactionURL != null) { + builder = RequestBuilder.put(transactionURL); + builder.setHeader("Content-Type", Protocol.SPARQL_QUERY_MIME_TYPE + "; charset=utf-8"); + builder.addParameter(Protocol.ACTION_PARAM_NAME, Action.QUERY.toString()); + for (NameValuePair nvp : getQueryMethodParameters(ql, null, baseURI, dataset, includeInferred, + maxQueryTime, bindings)) + { + builder.addParameter(nvp); + } + // in a PUT request, we carry the actual query string as the entity + // body rather than a parameter. + builder.setEntity(new StringEntity(query, UTF8)); + } + else { + builder = RequestBuilder.post(getQueryURL()); + builder.setHeader("Content-Type", Protocol.FORM_MIME_TYPE + "; charset=utf-8"); + + builder.setEntity(new UrlEncodedFormEntity( + getQueryMethodParameters(ql, query, baseURI, dataset, includeInferred, maxQueryTime, bindings), + UTF8)); + } + + return builder.build(); + } + + @Override + protected HttpUriRequest getUpdateMethod(QueryLanguage ql, String update, String baseURI, Dataset dataset, + boolean includeInferred, Binding... bindings) + { + RequestBuilder builder = null; + if (transactionURL != null) { + builder = RequestBuilder.put(transactionURL); + builder.addHeader("Content-Type", Protocol.SPARQL_UPDATE_MIME_TYPE + "; charset=utf-8"); + builder.addParameter(Protocol.ACTION_PARAM_NAME, Action.UPDATE.toString()); + for (NameValuePair nvp : getUpdateMethodParameters(ql, null, baseURI, dataset, includeInferred, + bindings)) + { + builder.addParameter(nvp); + } + // in a PUT request, we carry the only actual update string as the + // request body - the rest is sent as request parameters + builder.setEntity(new StringEntity(update, UTF8)); + } + else { + builder = RequestBuilder.post(getUpdateURL()); + builder.addHeader("Content-Type", Protocol.FORM_MIME_TYPE + "; charset=utf-8"); + + builder.setEntity(new UrlEncodedFormEntity( + getUpdateMethodParameters(ql, update, baseURI, dataset, includeInferred, bindings), UTF8)); + } + + return builder.build(); + } + + protected void upload(final Reader contents, String baseURI, final RDFFormat dataFormat, boolean overwrite, + boolean preserveNodeIds, Action action, Resource... contexts) + throws IOException, RDFParseException, RepositoryException, UnauthorizedException + { + final Charset charset = dataFormat.hasCharset() ? dataFormat.getCharset() : Charset.forName("UTF-8"); + + HttpEntity entity = new AbstractHttpEntity() { + + private InputStream content; + + public long getContentLength() { + return -1; // don't know + } + + public Header getContentType() { + return new BasicHeader("Content-Type", + dataFormat.getDefaultMIMEType() + "; charset=" + charset.name()); + } + + public boolean isRepeatable() { + return false; + } + + public boolean isStreaming() { + return true; + } + + public synchronized InputStream getContent() + throws IOException, IllegalStateException + { + if (content == null) { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + writeTo(buf); + content = new ByteArrayInputStream(buf.toByteArray()); + } + return content; + } + + public void writeTo(OutputStream out) + throws IOException + { + try { + OutputStreamWriter writer = new OutputStreamWriter(out, charset); + IOUtil.transfer(contents, writer); + writer.flush(); + } + finally { + contents.close(); + } + } + }; + + upload(entity, baseURI, overwrite, preserveNodeIds, action, contexts); + } + + protected void upload(HttpEntity reqEntity, String baseURI, boolean overwrite, boolean preserveNodeIds, + Action action, Resource... contexts) + throws IOException, RDFParseException, RepositoryException, UnauthorizedException + { + OpenRDFUtil.verifyContextNotNull(contexts); + + checkRepositoryURL(); + + boolean useTransaction = transactionURL != null; + + try { + + String baseLocation = useTransaction ? transactionURL + : Protocol.getStatementsLocation(getQueryURL()); + URIBuilder url = new URIBuilder(baseLocation); + + // Set relevant query parameters + for (String encodedContext : Protocol.encodeContexts(contexts)) { + url.addParameter(Protocol.CONTEXT_PARAM_NAME, encodedContext); + } + if (baseURI != null && baseURI.trim().length() != 0) { + String encodedBaseURI = Protocol.encodeValue(SimpleValueFactory.getInstance().createIRI(baseURI)); + url.setParameter(Protocol.BASEURI_PARAM_NAME, encodedBaseURI); + } + if (preserveNodeIds) { + url.setParameter(Protocol.PRESERVE_BNODE_ID_PARAM_NAME, "true"); + } + + if (useTransaction) { + if (action == null) { + throw new IllegalArgumentException("action can not be null on transaction operation"); + } + url.setParameter(Protocol.ACTION_PARAM_NAME, action.toString()); + } + + // Select appropriate HTTP method + HttpEntityEnclosingRequest method; + if (overwrite || useTransaction) { + method = new HttpPut(url.build()); + } + else { + method = new HttpPost(url.build()); + } + + // Set payload + method.setEntity(reqEntity); + + // Send request + try { + executeNoContent((HttpUriRequest)method); + } + catch (RepositoryException e) { + throw e; + } + catch (RDFParseException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + catch (URISyntaxException e) { + throw new AssertionError(e); + } + } + + @Override + public void setUsernameAndPassword(String username, String password) { + checkServerURL(); + setUsernameAndPasswordForUrl(username, password, getServerURL()); + } +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SparqlSession.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SparqlSession.java new file mode 100644 index 00000000000..0be3db58b58 --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SparqlSession.java @@ -0,0 +1,1162 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import static org.eclipse.rdf4j.http.protocol.Protocol.ACCEPT_PARAM_NAME; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutorService; + +import org.apache.http.Header; +import org.apache.http.HeaderElement; +import org.apache.http.HttpEntity; +import org.apache.http.HttpException; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.CookieStore; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.params.ClientPNames; +import org.apache.http.client.params.CookiePolicy; +import org.apache.http.client.protocol.ClientContext; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.CoreConnectionPNames; +import org.apache.http.params.HttpParams; +import org.apache.http.util.EntityUtils; +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.protocol.UnauthorizedException; +import org.eclipse.rdf4j.http.protocol.error.ErrorInfo; +import org.eclipse.rdf4j.http.protocol.error.ErrorType; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.GraphQueryResult; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryInterruptedException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.TupleQueryResultHandler; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultParser; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultParserRegistry; +import org.eclipse.rdf4j.query.resultio.QueryResultFormat; +import org.eclipse.rdf4j.query.resultio.QueryResultIO; +import org.eclipse.rdf4j.query.resultio.QueryResultParseException; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultParser; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultParserRegistry; +import org.eclipse.rdf4j.query.resultio.UnsupportedQueryResultFormatException; +import org.eclipse.rdf4j.query.resultio.helpers.QueryResultCollector; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.rio.ParserConfig; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFHandler; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFParserRegistry; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.UnsupportedRDFormatException; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.eclipse.rdf4j.rio.helpers.ParseErrorLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The SparqlSession provides low level HTTP methods for the HTTP communication + * of the SPARQL repository as well as the HTTP Repository. All methods are + * compliant to the SPARQL 1.1 protocol. For both Tuple and Graph queries there + * is a variant which parses the result in the background, see + * {@link BackgroundTupleResult} and {@link BackgroundGraphResult}. For boolean + * queries the result is parsed in the current thread. All methods in this class + * guarantee that HTTP connections are closed properly and returned to the + * connection pool. Functionality specific to the Sesame HTTP protocol can be + * found in {@link SesameSession} (which is used by Remote Repositories). The + * methods in this class are not guaranteed to be thread-safe. + * + * @author Herko ter Horst + * @author Arjohn Kampman + * @author Andreas Schwarte + * @see SesameSession + */ +public class SparqlSession implements HttpClientDependent { + + /*-----------* + * Constants * + *-----------*/ + + protected static final Charset UTF8 = Charset.forName("UTF-8"); + + /** + * The threshold for URL length, beyond which we use the POST method based on + * the lowest common denominator for various web servers + * + * @since 2.8.0 + */ + public static final int MAXIMUM_URL_LENGTH = 8192; + + final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /*-----------* + * Variables * + *-----------*/ + + private ValueFactory valueFactory; + + private String queryURL; + + private String updateURL; + + private HttpClient httpClient; + + private final ExecutorService executor; + + private final HttpClientContext httpContext; + + private final HttpParams params = new BasicHttpParams(); + + private ParserConfig parserConfig = new ParserConfig(); + + private TupleQueryResultFormat preferredTQRFormat = TupleQueryResultFormat.BINARY; + + private BooleanQueryResultFormat preferredBQRFormat = BooleanQueryResultFormat.TEXT; + + private RDFFormat preferredRDFFormat = RDFFormat.TURTLE; + + private Map additionalHttpHeaders = Collections.emptyMap(); + + /*--------------* + * Constructors * + *--------------*/ + + public SparqlSession(HttpClient client, ExecutorService executor) { + this.httpClient = client; + this.httpContext = new HttpClientContext(); + this.executor = executor; + valueFactory = SimpleValueFactory.getInstance(); + params.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, true); + CookieStore cookieStore = new BasicCookieStore(); + httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); + params.setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109); + + // parser used for processing server response data should be lenient + parserConfig.addNonFatalError(BasicParserSettings.VERIFY_DATATYPE_VALUES); + parserConfig.addNonFatalError(BasicParserSettings.VERIFY_LANGUAGE_TAGS); + } + + /*-----------------* + * Get/set methods * + *-----------------*/ + + public final HttpClient getHttpClient() { + return httpClient; + } + + public void setHttpClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public void setValueFactory(ValueFactory valueFactory) { + this.valueFactory = valueFactory; + } + + public ValueFactory getValueFactory() { + return valueFactory; + } + + protected void setQueryURL(String queryURL) { + if (queryURL == null) { + throw new IllegalArgumentException("queryURL must not be null"); + } + this.queryURL = queryURL; + } + + protected void setUpdateURL(String updateURL) { + if (updateURL == null) { + throw new IllegalArgumentException("updateURL must not be null"); + } + this.updateURL = updateURL; + } + + /** + * Sets the preferred format for encoding tuple query results. The + * {@link TupleQueryResultFormat#BINARY binary} format is preferred by + * default. + * + * @param format + * The preferred {@link TupleQueryResultFormat}, or null to + * indicate no specific format is preferred. + */ + public void setPreferredTupleQueryResultFormat(TupleQueryResultFormat format) { + preferredTQRFormat = format; + } + + /** + * Gets the preferred {@link TupleQueryResultFormat} for encoding tuple query + * results. + * + * @return The preferred format, of null if no specific format is + * preferred. + */ + public TupleQueryResultFormat getPreferredTupleQueryResultFormat() { + return preferredTQRFormat; + } + + /** + * Sets the preferred format for encoding RDF documents. The + * {@link RDFFormat#TURTLE Turtle} format is preferred by default. + * + * @param format + * The preferred {@link RDFFormat}, or null to indicate no + * specific format is preferred. + */ + public void setPreferredRDFFormat(RDFFormat format) { + preferredRDFFormat = format; + } + + /** + * Gets the preferred {@link RDFFormat} for encoding RDF documents. + * + * @return The preferred format, of null if no specific format is + * preferred. + */ + public RDFFormat getPreferredRDFFormat() { + return preferredRDFFormat; + } + + /** + * Sets the preferred format for encoding boolean query results. The + * {@link BooleanQueryResultFormat#TEXT binary} format is preferred by + * default. + * + * @param format + * The preferred {@link BooleanQueryResultFormat}, or null to + * indicate no specific format is preferred. + */ + public void setPreferredBooleanQueryResultFormat(BooleanQueryResultFormat format) { + preferredBQRFormat = format; + } + + /** + * Gets the preferred {@link BooleanQueryResultFormat} for encoding boolean + * query results. + * + * @return The preferred format, of null if no specific format is + * preferred. + */ + public BooleanQueryResultFormat getPreferredBooleanQueryResultFormat() { + return preferredBQRFormat; + } + + /** + * Set the username and password for authentication with the remote server. + * + * @param username + * the username + * @param password + * the password + */ + public void setUsernameAndPassword(String username, String password) { + setUsernameAndPasswordForUrl(username, password, getQueryURL()); + } + + protected void setUsernameAndPasswordForUrl(String username, String password, String url) { + + if (username != null && password != null) { + logger.debug("Setting username '{}' and password for server at {}.", username, url); + java.net.URI requestURI = java.net.URI.create(url); + String host = requestURI.getHost(); + int port = requestURI.getPort(); + AuthScope scope = new AuthScope(host, port); + UsernamePasswordCredentials cred = new UsernamePasswordCredentials(username, password); + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(scope, cred); + httpContext.setCredentialsProvider(credsProvider); + AuthCache authCache = new BasicAuthCache(); + BasicScheme basicAuth = new BasicScheme(); + HttpHost httpHost = new HttpHost(requestURI.getHost(), requestURI.getPort(), requestURI.getScheme()); + authCache.put(httpHost, basicAuth); + httpContext.setAuthCache(authCache); + } + else { + httpContext.removeAttribute(HttpClientContext.AUTH_CACHE); + httpContext.removeAttribute(HttpClientContext.CREDS_PROVIDER); + } + } + + protected void execute(Runnable command) { + executor.execute(command); + } + + public String getQueryURL() { + return queryURL; + } + + public String getUpdateURL() { + return updateURL; + } + + /*------------------* + * Query evaluation * + *------------------*/ + + public TupleQueryResult sendTupleQuery(QueryLanguage ql, String query, Dataset dataset, + boolean includeInferred, Binding... bindings) + throws IOException, RepositoryException, MalformedQueryException, UnauthorizedException, + QueryInterruptedException + { + return sendTupleQuery(ql, query, null, dataset, includeInferred, 0, bindings); + } + + public TupleQueryResult sendTupleQuery(QueryLanguage ql, String query, String baseURI, Dataset dataset, + boolean includeInferred, int maxQueryTime, Binding... bindings) + throws IOException, RepositoryException, MalformedQueryException, UnauthorizedException, + QueryInterruptedException + { + HttpUriRequest method = getQueryMethod(ql, query, baseURI, dataset, includeInferred, maxQueryTime, + bindings); + return getBackgroundTupleQueryResult(method); + } + + public void sendTupleQuery(QueryLanguage ql, String query, String baseURI, Dataset dataset, + boolean includeInferred, int maxQueryTime, TupleQueryResultHandler handler, Binding... bindings) + throws IOException, TupleQueryResultHandlerException, RepositoryException, + MalformedQueryException, UnauthorizedException, QueryInterruptedException + { + HttpUriRequest method = getQueryMethod(ql, query, baseURI, dataset, includeInferred, maxQueryTime, + bindings); + getTupleQueryResult(method, handler); + } + + public void sendUpdate(QueryLanguage ql, String update, String baseURI, Dataset dataset, + boolean includeInferred, Binding... bindings) + throws IOException, RepositoryException, MalformedQueryException, UnauthorizedException, + QueryInterruptedException + { + HttpUriRequest method = getUpdateMethod(ql, update, baseURI, dataset, includeInferred, bindings); + + try { + executeNoContent(method); + } + catch (RepositoryException e) { + throw e; + } + catch (MalformedQueryException e) { + throw e; + } + catch (QueryInterruptedException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + public GraphQueryResult sendGraphQuery(QueryLanguage ql, String query, Dataset dataset, + boolean includeInferred, Binding... bindings) + throws IOException, RepositoryException, MalformedQueryException, UnauthorizedException, + QueryInterruptedException + { + return sendGraphQuery(ql, query, null, dataset, includeInferred, 0, bindings); + } + + public GraphQueryResult sendGraphQuery(QueryLanguage ql, String query, String baseURI, Dataset dataset, + boolean includeInferred, int maxQueryTime, Binding... bindings) + throws IOException, RepositoryException, MalformedQueryException, UnauthorizedException, + QueryInterruptedException + { + try { + HttpUriRequest method = getQueryMethod(ql, query, baseURI, dataset, includeInferred, maxQueryTime, + bindings); + return getRDFBackground(method, false); + } + catch (RDFHandlerException e) { + // Found a bug in TupleQueryResultBuilder? + throw new RuntimeException(e); + } + } + + public void sendGraphQuery(QueryLanguage ql, String query, Dataset dataset, boolean includeInferred, + RDFHandler handler, Binding... bindings) + throws IOException, RDFHandlerException, RepositoryException, MalformedQueryException, + UnauthorizedException, QueryInterruptedException + { + sendGraphQuery(ql, query, null, dataset, includeInferred, 0, handler, bindings); + } + + public void sendGraphQuery(QueryLanguage ql, String query, String baseURI, Dataset dataset, + boolean includeInferred, int maxQueryTime, RDFHandler handler, Binding... bindings) + throws IOException, RDFHandlerException, RepositoryException, MalformedQueryException, + UnauthorizedException, QueryInterruptedException + { + HttpUriRequest method = getQueryMethod(ql, query, baseURI, dataset, includeInferred, maxQueryTime, + bindings); + getRDF(method, handler, false); + } + + public boolean sendBooleanQuery(QueryLanguage ql, String query, Dataset dataset, boolean includeInferred, + Binding... bindings) + throws IOException, RepositoryException, MalformedQueryException, UnauthorizedException, + QueryInterruptedException + { + return sendBooleanQuery(ql, query, null, dataset, includeInferred, 0, bindings); + } + + public boolean sendBooleanQuery(QueryLanguage ql, String query, String baseURI, Dataset dataset, + boolean includeInferred, int maxQueryTime, Binding... bindings) + throws IOException, RepositoryException, MalformedQueryException, UnauthorizedException, + QueryInterruptedException + { + HttpUriRequest method = getQueryMethod(ql, query, baseURI, dataset, includeInferred, maxQueryTime, + bindings); + try { + return getBoolean(method); + } + catch (RepositoryException e) { + throw e; + } + catch (MalformedQueryException e) { + throw e; + } + catch (QueryInterruptedException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + /** + * Get the additional HTTP headers which will be used + * + * @return a read-only view of the additional HTTP headers which will be + * included in every request to the server. + */ + public Map getAdditionalHttpHeaders() { + return Collections.unmodifiableMap(additionalHttpHeaders); + } + + /** + * Set additional HTTP headers to be included in every request to the server, + * which may be required for certain unusual server configurations. + * + * @param additionalHttpHeaders + * a map containing pairs of header names and values. May be null + */ + public void setAdditionalHttpHeaders(Map additionalHttpHeaders) { + if (additionalHttpHeaders == null) { + this.additionalHttpHeaders = Collections.emptyMap(); + } + else { + this.additionalHttpHeaders = additionalHttpHeaders; + } + } + + protected HttpUriRequest getQueryMethod(QueryLanguage ql, String query, String baseURI, Dataset dataset, + boolean includeInferred, int maxQueryTime, Binding... bindings) + { + List queryParams = getQueryMethodParameters(ql, query, baseURI, dataset, includeInferred, + maxQueryTime, bindings); + HttpUriRequest method; + String queryUrlWithParams; + try { + URIBuilder urib = new URIBuilder(getQueryURL()); + for (NameValuePair nvp : queryParams) + urib.addParameter(nvp.getName(), nvp.getValue()); + queryUrlWithParams = urib.toString(); + } + catch (URISyntaxException e) { + throw new AssertionError(e); + } + if (shouldUsePost(queryUrlWithParams)) { + // we just built up a URL for nothing. oh well. + // It's probably not much overhead against + // the poor triplestore having to process such as massive query + HttpPost postMethod = new HttpPost(getQueryURL()); + postMethod.setHeader("Content-Type", Protocol.FORM_MIME_TYPE + "; charset=utf-8"); + postMethod.setEntity(new UrlEncodedFormEntity(queryParams, UTF8)); + method = postMethod; + } + else { + method = new HttpGet(queryUrlWithParams); + } + // functionality to provide custom http headers as required by the + // applications + for (Map.Entry additionalHeader : additionalHttpHeaders.entrySet()) { + method.addHeader(additionalHeader.getKey(), additionalHeader.getValue()); + } + return method; + } + + /** + * Return whether the provided query should use POST (otherwise use GET) + * + * @param fullQueryUrl + * the complete URL, including hostname and all HTTP query parameters + */ + protected boolean shouldUsePost(String fullQueryUrl) { + return fullQueryUrl.length() > MAXIMUM_URL_LENGTH; + } + + protected HttpUriRequest getUpdateMethod(QueryLanguage ql, String update, String baseURI, Dataset dataset, + boolean includeInferred, Binding... bindings) + { + HttpPost method = new HttpPost(getUpdateURL()); + + method.setHeader("Content-Type", Protocol.FORM_MIME_TYPE + "; charset=utf-8"); + + List queryParams = getUpdateMethodParameters(ql, update, baseURI, dataset, + includeInferred, bindings); + + method.setEntity(new UrlEncodedFormEntity(queryParams, UTF8)); + + if (this.additionalHttpHeaders != null) { + for (Map.Entry additionalHeader : additionalHttpHeaders.entrySet()) + method.addHeader(additionalHeader.getKey(), additionalHeader.getValue()); + } + + return method; + } + + protected List getQueryMethodParameters(QueryLanguage ql, String query, String baseURI, + Dataset dataset, boolean includeInferred, int maxQueryTime, Binding... bindings) + { + if (ql == null) { + throw new NullPointerException("ql may not be null"); + } + + // TODO there is a bunch of HttpRepository specific parameters here + List queryParams = new ArrayList(bindings.length + 10); + + queryParams.add(new BasicNameValuePair(Protocol.QUERY_LANGUAGE_PARAM_NAME, ql.getName())); + if (query != null) { + queryParams.add(new BasicNameValuePair(Protocol.QUERY_PARAM_NAME, query)); + } + + if (baseURI != null) { + queryParams.add(new BasicNameValuePair(Protocol.BASEURI_PARAM_NAME, baseURI)); + } + queryParams.add( + new BasicNameValuePair(Protocol.INCLUDE_INFERRED_PARAM_NAME, Boolean.toString(includeInferred))); + if (maxQueryTime > 0) { + queryParams.add(new BasicNameValuePair(Protocol.TIMEOUT_PARAM_NAME, Integer.toString(maxQueryTime))); + } + + if (dataset != null) { + for (IRI defaultGraphURI : dataset.getDefaultGraphs()) { + queryParams.add( + new BasicNameValuePair(Protocol.DEFAULT_GRAPH_PARAM_NAME, String.valueOf(defaultGraphURI))); + } + for (IRI namedGraphURI : dataset.getNamedGraphs()) { + queryParams.add( + new BasicNameValuePair(Protocol.NAMED_GRAPH_PARAM_NAME, String.valueOf(namedGraphURI))); + } + } + + for (int i = 0; i < bindings.length; i++) { + String paramName = Protocol.BINDING_PREFIX + bindings[i].getName(); + String paramValue = Protocol.encodeValue(bindings[i].getValue()); + queryParams.add(new BasicNameValuePair(paramName, paramValue)); + } + + return queryParams; + } + + protected List getUpdateMethodParameters(QueryLanguage ql, String update, String baseURI, + Dataset dataset, boolean includeInferred, Binding... bindings) + { + if (ql == null) { + throw new NullPointerException("ql may not be null"); + } + + List queryParams = new ArrayList(bindings.length + 10); + + queryParams.add(new BasicNameValuePair(Protocol.QUERY_LANGUAGE_PARAM_NAME, ql.getName())); + if (update != null) { + queryParams.add(new BasicNameValuePair(Protocol.UPDATE_PARAM_NAME, update)); + logger.debug("added update string {}", update); + } + + if (baseURI != null) { + queryParams.add(new BasicNameValuePair(Protocol.BASEURI_PARAM_NAME, baseURI)); + } + queryParams.add( + new BasicNameValuePair(Protocol.INCLUDE_INFERRED_PARAM_NAME, Boolean.toString(includeInferred))); + + if (dataset != null) { + for (IRI graphURI : dataset.getDefaultRemoveGraphs()) { + queryParams.add( + new BasicNameValuePair(Protocol.REMOVE_GRAPH_PARAM_NAME, String.valueOf(graphURI))); + } + if (dataset.getDefaultInsertGraph() != null) { + queryParams.add(new BasicNameValuePair(Protocol.INSERT_GRAPH_PARAM_NAME, + String.valueOf(dataset.getDefaultInsertGraph()))); + } + for (IRI defaultGraphURI : dataset.getDefaultGraphs()) { + queryParams.add( + new BasicNameValuePair(Protocol.USING_GRAPH_PARAM_NAME, String.valueOf(defaultGraphURI))); + } + for (IRI namedGraphURI : dataset.getNamedGraphs()) { + queryParams.add(new BasicNameValuePair(Protocol.USING_NAMED_GRAPH_PARAM_NAME, + String.valueOf(namedGraphURI))); + } + } + + for (int i = 0; i < bindings.length; i++) { + String paramName = Protocol.BINDING_PREFIX + bindings[i].getName(); + String paramValue = Protocol.encodeValue(bindings[i].getValue()); + queryParams.add(new BasicNameValuePair(paramName, paramValue)); + } + + return queryParams; + } + + /*------------------* + * Response parsing * + *------------------*/ + + /** + * Parse the response in a background thread. HTTP connections are dealt with + * in the {@link BackgroundTupleResult} or (in the error-case) in this + * method. + */ + protected BackgroundTupleResult getBackgroundTupleQueryResult(HttpUriRequest method) + throws RepositoryException, QueryInterruptedException, MalformedQueryException, IOException + { + + boolean submitted = false; + + // Specify which formats we support + Set tqrFormats = TupleQueryResultParserRegistry.getInstance().getKeys(); + if (tqrFormats.isEmpty()) { + throw new RepositoryException("No tuple query result parsers have been registered"); + } + + // send the tuple query + HttpResponse response = sendTupleQueryViaHttp(method, tqrFormats); + try { + + // if we get here, HTTP code is 200 + String mimeType = getResponseMIMEType(response); + QueryResultFormat format = TupleQueryResultFormat.matchMIMEType(mimeType, tqrFormats).orElseThrow( + () -> new RepositoryException("Server responded with an unsupported file format: " + mimeType)); + TupleQueryResultParser parser = QueryResultIO.createTupleParser(format, getValueFactory()); + BackgroundTupleResult tRes = new BackgroundTupleResult(parser, response.getEntity().getContent()); + execute(tRes); + submitted = true; + return tRes; + } + finally { + if (!submitted) + EntityUtils.consumeQuietly(response.getEntity()); + } + } + + /** + * Parse the response in this thread using the provided + * {@link TupleQueryResultHandler}. All HTTP connections are closed and + * released in this method + */ + protected void getTupleQueryResult(HttpUriRequest method, TupleQueryResultHandler handler) + throws IOException, TupleQueryResultHandlerException, RepositoryException, MalformedQueryException, + UnauthorizedException, QueryInterruptedException + { + // Specify which formats we support + Set tqrFormats = TupleQueryResultParserRegistry.getInstance().getKeys(); + if (tqrFormats.isEmpty()) { + throw new RepositoryException("No tuple query result parsers have been registered"); + } + + // send the tuple query + HttpResponse response = sendTupleQueryViaHttp(method, tqrFormats); + try { + + // if we get here, HTTP code is 200 + String mimeType = getResponseMIMEType(response); + try { + QueryResultFormat format = TupleQueryResultFormat.matchMIMEType(mimeType, tqrFormats).orElseThrow( + () -> new RepositoryException("Server responded with an unsupported file format: " + + mimeType)); + TupleQueryResultParser parser = QueryResultIO.createTupleParser(format, getValueFactory()); + parser.setQueryResultHandler(handler); + parser.parseQueryResult(response.getEntity().getContent()); + } + catch (QueryResultParseException e) { + throw new RepositoryException("Malformed query result from server", e); + } + catch (QueryResultHandlerException e) { + if (e instanceof TupleQueryResultHandlerException) { + throw (TupleQueryResultHandlerException)e; + } + else { + throw new TupleQueryResultHandlerException(e); + } + } + } + finally { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + + /** + * Send the tuple query via HTTP and throws an exception in case anything + * goes wrong, i.e. only for HTTP 200 the method returns without exception. + * If HTTP status code is not equal to 200, the request is aborted, however + * pooled connections are not released. + * + * @param method + * @throws RepositoryException + * @throws HttpException + * @throws IOException + * @throws QueryInterruptedException + * @throws MalformedQueryException + */ + private HttpResponse sendTupleQueryViaHttp(HttpUriRequest method, Set tqrFormats) + throws RepositoryException, IOException, QueryInterruptedException, MalformedQueryException + { + + for (QueryResultFormat format : tqrFormats) { + // Determine a q-value that reflects the user specified preference + int qValue = 10; + + if (preferredTQRFormat != null && !preferredTQRFormat.equals(format)) { + // Prefer specified format over other formats + qValue -= 2; + } + + for (String mimeType : format.getMIMETypes()) { + String acceptParam = mimeType; + + if (qValue < 10) { + acceptParam += ";q=0." + qValue; + } + + method.addHeader(ACCEPT_PARAM_NAME, acceptParam); + } + } + + try { + return executeOK(method); + } + catch (RepositoryException | MalformedQueryException | QueryInterruptedException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + /** + * Parse the response in a background thread. HTTP connections are dealt with + * in the {@link BackgroundGraphResult} or (in the error-case) in this + * method. + */ + protected BackgroundGraphResult getRDFBackground(HttpUriRequest method, boolean requireContext) + throws IOException, RDFHandlerException, RepositoryException, MalformedQueryException, + UnauthorizedException, QueryInterruptedException + { + + boolean submitted = false; + + // Specify which formats we support using Accept headers + Set rdfFormats = RDFParserRegistry.getInstance().getKeys(); + if (rdfFormats.isEmpty()) { + throw new RepositoryException("No tuple RDF parsers have been registered"); + } + + // send the tuple query + HttpResponse response = sendGraphQueryViaHttp(method, requireContext, rdfFormats); + try { + + // if we get here, HTTP code is 200 + String mimeType = getResponseMIMEType(response); + RDFFormat format = RDFFormat.matchMIMEType(mimeType, rdfFormats).orElseThrow( + () -> new RepositoryException("Server responded with an unsupported file format: " + mimeType)); + RDFParser parser = Rio.createParser(format, getValueFactory()); + parser.setParserConfig(getParserConfig()); + parser.setParseErrorListener(new ParseErrorLogger()); + + Charset charset = null; + + // SES-1793 : Do not attempt to check for a charset if the format is + // defined not to have a charset + // This prevents errors caused by people erroneously attaching a + // charset to a binary formatted document + HttpEntity entity = response.getEntity(); + if (format.hasCharset() && entity != null && entity.getContentType() != null) { + // TODO copied from SPARQLGraphQuery repository, is this + // required? + try { + charset = ContentType.parse(entity.getContentType().getValue()).getCharset(); + } + catch (IllegalCharsetNameException e) { + // work around for Joseki-3.2 + // Content-Type: application/rdf+xml; + // charset=application/rdf+xml + } + if (charset == null) { + charset = UTF8; + } + } + + if (entity == null) { + throw new RepositoryException("Server response was empty."); + } + + String baseURI = method.getURI().toASCIIString(); + BackgroundGraphResult gRes = new BackgroundGraphResult(parser, entity.getContent(), charset, baseURI); + execute(gRes); + submitted = true; + return gRes; + } + finally { + if (!submitted) { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + + } + + /** + * Parse the response in this thread using the provided {@link RDFHandler}. + * All HTTP connections are closed and released in this method + */ + protected void getRDF(HttpUriRequest method, RDFHandler handler, boolean requireContext) + throws IOException, RDFHandlerException, RepositoryException, MalformedQueryException, + UnauthorizedException, QueryInterruptedException + { + // Specify which formats we support using Accept headers + Set rdfFormats = RDFParserRegistry.getInstance().getKeys(); + if (rdfFormats.isEmpty()) { + throw new RepositoryException("No tuple RDF parsers have been registered"); + } + + // send the tuple query + HttpResponse response = sendGraphQueryViaHttp(method, requireContext, rdfFormats); + try { + + String mimeType = getResponseMIMEType(response); + try { + RDFFormat format = RDFFormat.matchMIMEType(mimeType, rdfFormats).orElseThrow( + () -> new RepositoryException("Server responded with an unsupported file format: " + + mimeType)); + RDFParser parser = Rio.createParser(format, getValueFactory()); + parser.setParserConfig(getParserConfig()); + parser.setParseErrorListener(new ParseErrorLogger()); + parser.setRDFHandler(handler); + parser.parse(response.getEntity().getContent(), method.getURI().toASCIIString()); + } + catch (RDFParseException e) { + throw new RepositoryException("Malformed query result from server", e); + } + } + finally { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + + private HttpResponse sendGraphQueryViaHttp(HttpUriRequest method, boolean requireContext, + Set rdfFormats) + throws RepositoryException, IOException, QueryInterruptedException, MalformedQueryException + { + + List acceptParams = RDFFormat.getAcceptParams(rdfFormats, requireContext, + getPreferredRDFFormat()); + for (String acceptParam : acceptParams) { + method.addHeader(ACCEPT_PARAM_NAME, acceptParam); + } + + try { + return executeOK(method); + } + catch (RepositoryException | MalformedQueryException | QueryInterruptedException e) { + throw e; + } + catch (OpenRDFException e) { + throw new RepositoryException(e); + } + } + + /** + * Parse the response in this thread using a suitable + * {@link BooleanQueryResultParser}. All HTTP connections are closed and + * released in this method + * + * @throws OpenRDFException + */ + protected boolean getBoolean(HttpUriRequest method) + throws IOException, OpenRDFException + { + // Specify which formats we support using Accept headers + Set booleanFormats = BooleanQueryResultParserRegistry.getInstance().getKeys(); + if (booleanFormats.isEmpty()) { + throw new RepositoryException("No boolean query result parsers have been registered"); + } + + // send the tuple query + HttpResponse response = sendBooleanQueryViaHttp(method, booleanFormats); + try { + + // if we get here, HTTP code is 200 + String mimeType = getResponseMIMEType(response); + try { + QueryResultFormat format = BooleanQueryResultFormat.matchMIMEType(mimeType, booleanFormats).orElseThrow( + () -> new RepositoryException("Server responded with an unsupported file format: " + + mimeType)); + BooleanQueryResultParser parser = QueryResultIO.createBooleanParser(format); + QueryResultCollector results = new QueryResultCollector(); + parser.setQueryResultHandler(results); + parser.parseQueryResult(response.getEntity().getContent()); + return results.getBoolean(); + } + catch (QueryResultParseException e) { + throw new RepositoryException("Malformed query result from server", e); + } + } + finally { + EntityUtils.consumeQuietly(response.getEntity()); + } + + } + + private HttpResponse sendBooleanQueryViaHttp(HttpUriRequest method, Set booleanFormats) + throws IOException, OpenRDFException + { + + for (QueryResultFormat format : booleanFormats) { + // Determine a q-value that reflects the user specified preference + int qValue = 10; + + if (preferredBQRFormat != null && !preferredBQRFormat.equals(format)) { + // Prefer specified format over other formats + qValue -= 2; + } + + for (String mimeType : format.getMIMETypes()) { + String acceptParam = mimeType; + + if (qValue < 10) { + acceptParam += ";q=0." + qValue; + } + + method.addHeader(ACCEPT_PARAM_NAME, acceptParam); + } + } + + return executeOK(method); + } + + /** + * Convenience method to deal with HTTP level errors of tuple, graph and + * boolean queries in the same way. This method aborts the HTTP connection. + * + * @param method + * @throws OpenRDFException + */ + protected HttpResponse executeOK(HttpUriRequest method) + throws IOException, OpenRDFException + { + boolean fail = true; + HttpResponse response = execute(method); + + try { + int httpCode = response.getStatusLine().getStatusCode(); + if (httpCode == HttpURLConnection.HTTP_OK || httpCode == HttpURLConnection.HTTP_NOT_AUTHORITATIVE) { + fail = false; + return response; // everything OK, control flow can continue + } + else { + // trying to contact a non-Sesame server? + throw new RepositoryException("Failed to get server protocol; no such resource on this server: " + + method.getURI().toString()); + } + } + finally { + if (fail) { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + } + + protected void executeNoContent(HttpUriRequest method) + throws IOException, OpenRDFException + { + HttpResponse response = execute(method); + try { + if (response.getStatusLine().getStatusCode() >= 300) { + // trying to contact a non-Sesame server? + throw new RepositoryException("Failed to get server protocol; no such resource on this server: " + + method.getURI().toString()); + } + } + finally { + EntityUtils.consume(response.getEntity()); + } + } + + protected HttpResponse execute(HttpUriRequest method) + throws IOException, OpenRDFException + { + boolean consume = true; + method.setParams(params); + HttpResponse response = httpClient.execute(method, httpContext); + + try { + int httpCode = response.getStatusLine().getStatusCode(); + if (httpCode >= 200 && httpCode < 300 || httpCode == HttpURLConnection.HTTP_NOT_FOUND) { + consume = false; + return response; // everything OK, control flow can continue + } + else { + switch (httpCode) { + case HttpURLConnection.HTTP_UNAUTHORIZED: // 401 + throw new UnauthorizedException(); + case HttpURLConnection.HTTP_UNAVAILABLE: // 503 + throw new QueryInterruptedException(); + default: + ErrorInfo errInfo = getErrorInfo(response); + // Throw appropriate exception + if (errInfo.getErrorType() == ErrorType.MALFORMED_DATA) { + throw new RDFParseException(errInfo.getErrorMessage()); + } + else if (errInfo.getErrorType() == ErrorType.UNSUPPORTED_FILE_FORMAT) { + throw new UnsupportedRDFormatException(errInfo.getErrorMessage()); + } + else if (errInfo.getErrorType() == ErrorType.MALFORMED_QUERY) { + throw new MalformedQueryException(errInfo.getErrorMessage()); + } + else if (errInfo.getErrorType() == ErrorType.UNSUPPORTED_QUERY_LANGUAGE) { + throw new UnsupportedQueryLanguageException(errInfo.getErrorMessage()); + } + else { + throw new RepositoryException(errInfo.toString()); + } + } + } + } + finally { + if (consume) { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + } + + /*-------------------------* + * General utility methods * + *-------------------------*/ + + /** + * Gets the MIME type specified in the response headers of the supplied + * method, if any. For example, if the response headers contain + * Content-Type: application/xml;charset=UTF-8, this method will + * return application/xml as the MIME type. + * + * @param method + * The method to get the reponse MIME type from. + * @return The response MIME type, or null if not available. + */ + protected String getResponseMIMEType(HttpResponse method) + throws IOException + { + Header[] headers = method.getHeaders("Content-Type"); + + for (Header header : headers) { + HeaderElement[] headerElements = header.getElements(); + + for (HeaderElement headerEl : headerElements) { + String mimeType = headerEl.getName(); + if (mimeType != null) { + logger.debug("reponse MIME type is {}", mimeType); + return mimeType; + } + } + } + + return null; + } + + protected ErrorInfo getErrorInfo(HttpResponse response) + throws RepositoryException + { + try { + ErrorInfo errInfo = ErrorInfo.parse(EntityUtils.toString(response.getEntity())); + logger.warn("Server reports problem: {}", errInfo.getErrorMessage()); + return errInfo; + } + catch (IOException e) { + logger.warn("Unable to retrieve error info from server"); + throw new RepositoryException("Unable to retrieve error info from server", e); + } + } + + /** + * Sets the parser configuration used to process HTTP response data. + * + * @param parserConfig + * The parserConfig to set. + */ + public void setParserConfig(ParserConfig parserConfig) { + this.parserConfig = parserConfig; + } + + /** + * @return Returns the parser configuration used to process HTTP response + * data. + */ + public ParserConfig getParserConfig() { + return parserConfig; + } + + /** + * Gets the http connection read timeout in milliseconds. + */ + public long getConnectionTimeout() { + return (long)params.getIntParameter(CoreConnectionPNames.SO_TIMEOUT, 0); + } + + /** + * Sets the http connection read timeout. + * + * @param timeout + * timeout in milliseconds. Zero sets to infinity. + */ + public void setConnectionTimeout(long timeout) { + params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, (int)timeout); + } +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/query/AbstractHTTPQuery.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/query/AbstractHTTPQuery.java new file mode 100644 index 00000000000..4641cc92967 --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/query/AbstractHTTPQuery.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client.query; + +import java.util.Iterator; + +import org.eclipse.rdf4j.http.client.SparqlSession; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Query; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.impl.AbstractQuery; + +/** + * Base class for any {@link Query} operation over HTTP. + * + * @author Andreas Schwarte + */ +public abstract class AbstractHTTPQuery extends AbstractQuery { + + private final SparqlSession httpClient; + + protected final QueryLanguage queryLanguage; + + protected final String queryString; + + protected final String baseURI; + + public AbstractHTTPQuery(SparqlSession httpClient, QueryLanguage queryLanguage, String queryString, + String baseURI) + { + super(); + this.httpClient = httpClient; + this.queryLanguage = queryLanguage; + this.queryString = queryString; + // TODO think about the following + // for legacy reasons we should support the empty string for baseURI + // this is used in the SPARQL repository in several places, e.g. in + // getStatements + this.baseURI = baseURI != null && baseURI.length() > 0 ? baseURI : null; + } + + /** + * @return Returns the {@link SparqlSession} to be used for all HTTP based + * interaction + */ + protected SparqlSession getHttpClient() { + return httpClient; + } + + public Binding[] getBindingsArray() { + BindingSet bindings = this.getBindings(); + + Binding[] bindingsArray = new Binding[bindings.size()]; + + Iterator iter = bindings.iterator(); + for (int i = 0; i < bindings.size(); i++) { + bindingsArray[i] = iter.next(); + } + + return bindingsArray; + } + + @Override + public void setMaxExecutionTime(int maxExecutionTime) { + super.setMaxExecutionTime(maxExecutionTime); + this.httpClient.setConnectionTimeout(1000L * this.getMaxExecutionTime()); + } + + @Override + public String toString() { + return queryString; + } +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/query/AbstractHTTPUpdate.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/query/AbstractHTTPUpdate.java new file mode 100644 index 00000000000..59532dfd7be --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/query/AbstractHTTPUpdate.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client.query; + +import java.util.Iterator; + +import org.eclipse.rdf4j.http.client.SparqlSession; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.Update; +import org.eclipse.rdf4j.query.impl.AbstractUpdate; + +/** + * Base class for any {@link Update} operation over HTTP. + * + * @author Andreas Schwarte + */ +public abstract class AbstractHTTPUpdate extends AbstractUpdate { + + private final SparqlSession httpClient; + + protected final QueryLanguage queryLanguage; + + protected final String queryString; + + protected final String baseURI; + + public AbstractHTTPUpdate(SparqlSession httpClient, QueryLanguage queryLanguage, String queryString, + String baseURI) + { + super(); + this.httpClient = httpClient; + this.queryLanguage = queryLanguage; + this.queryString = queryString; + this.baseURI = baseURI; + } + + /** + * @return Returns the {@link SparqlSession} to be used for all HTTP based interaction + */ + protected SparqlSession getHttpClient() { + return httpClient; + } + + public Binding[] getBindingsArray() { + BindingSet bindings = this.getBindings(); + + Binding[] bindingsArray = new Binding[bindings.size()]; + + Iterator iter = bindings.iterator(); + for (int i = 0; i < bindings.size(); i++) { + bindingsArray[i] = iter.next(); + } + + return bindingsArray; + } + + /** + * @return Returns the baseURI. + */ + public String getBaseURI() { + return baseURI; + } + + /** + * @return Returns the queryLanguage. + */ + public QueryLanguage getQueryLanguage() { + return queryLanguage; + } + + /** + * @return Returns the queryString. + */ + public String getQueryString() { + return queryString; + } + + @Override + public String toString() { + return queryString; + } +} diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/util/HttpClientBuilders.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/util/HttpClientBuilders.java new file mode 100644 index 00000000000..d370bb9e7ad --- /dev/null +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/util/HttpClientBuilders.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client.util; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLSession; + +import org.apache.http.client.HttpClient; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.ssl.TrustStrategy; +import org.eclipse.rdf4j.http.client.HttpClientDependent; + +/** + * Convenience utility class offering helper methods to configure + * {@link HttpClient}s and {@link HttpClientBuilders}. + * + * @author Andreas Schwarte + * @see HttpClientDependent + */ +public class HttpClientBuilders { + + + /** + * Return an {@link HttpClientBuilder} that can be used to + * build an {@link HttpClient} which trusts all certificates + * (particularly including self-signed certificates). + * + * @return a {@link HttpClientBuilder} for SSL trust all + */ + public static HttpClientBuilder getSSLTrustAllHttpClientBuilder() { + try { + SSLContextBuilder builder = new SSLContextBuilder(); + builder.loadTrustMaterial(null, new TrustStrategy() { + @Override + public boolean isTrusted(X509Certificate[] chain, + String authType) throws CertificateException { + return true; + } + }); + + HostnameVerifier hostNameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory( + builder.build(), hostNameVerifier); + + return HttpClients.custom().setSSLSocketFactory(sslSF) + .useSystemProperties(); + } catch (Exception e) { + // key management exception, etc. + throw new RuntimeException(e); + } + } +} diff --git a/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/BackgroundGraphResultHangTest.java b/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/BackgroundGraphResultHangTest.java new file mode 100644 index 00000000000..a89eaaa28ed --- /dev/null +++ b/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/BackgroundGraphResultHangTest.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.nio.charset.Charset; + +import org.eclipse.rdf4j.http.client.BackgroundGraphResult; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.helpers.AbstractRDFParser; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * @author Damyan Ognyanov + */ +public class BackgroundGraphResultHangTest { + + static class DummyParser extends AbstractRDFParser { + + @Override + public RDFFormat getRDFFormat() { + return null; + } + + @Override + public void parse(InputStream in, String baseURI) + throws IOException, RDFParseException, RDFHandlerException + { + throw new RDFParseException("invalid RDF "); + } + + @Override + public void parse(Reader reader, String baseURI) + throws IOException, RDFParseException, RDFHandlerException + { + throw new RDFParseException("invalid RDF "); + } + + } + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test(timeout = 1000) + public void testBGRHang() + throws Exception + { + String data = "@not-rdf"; + + BackgroundGraphResult gRes = new BackgroundGraphResult(new DummyParser(), new ByteArrayInputStream( + data.getBytes(Charset.forName("UTF-8"))), Charset.forName("UTF-8"), "http://base.org"); + + gRes.run(); + + gRes.getNamespaces(); + + thrown.expect(QueryEvaluationException.class); + gRes.hasNext(); + } +} diff --git a/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/SesameHTTPClientTest.java b/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/SesameHTTPClientTest.java new file mode 100644 index 00000000000..2b69b90d813 --- /dev/null +++ b/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/SesameHTTPClientTest.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.client; + +import static org.junit.Assert.*; + +import org.eclipse.rdf4j.http.client.SesameSession; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +@Ignore("FIXME: Migrate this test to Apache HTTP Client 4 methods") +public class SesameHTTPClientTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private SesameSession httpClient = new SesameSession(null, null); + + @Test + public void setUsernameAndPassword_should_succeed_with_server_url_but_no_query_url() { + + httpClient.setServerURL("http://www.repo.org/server"); + + //assertFalse(httpClient.getHttpClient().getParams().isAuthenticationPreemptive()); + + httpClient.setUsernameAndPassword("user01", "secret"); + + //assertTrue(httpClient.getHttpClient().getParams().isAuthenticationPreemptive()); + + } + + @Test + public void setUsernameAndPassword_should_throw_exception_when_serverUrl_not_set() { + + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Server URL has not been set"); + + //assertFalse(httpClient.getHttpClient().getParams().isAuthenticationPreemptive()); + + httpClient.setUsernameAndPassword("user01", "secret"); + + fail("Don't reach this point"); + } + +} diff --git a/core/http/pom.xml b/core/http/pom.xml new file mode 100644 index 00000000000..c1cd0b21efd --- /dev/null +++ b/core/http/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-core + 4.1.0-SNAPSHOT + + + rdf4j-http + pom + + RDF4J: HTTP + Client and server for repository communication over HTTP. + + + protocol + client + server + server-spring + workbench + + + diff --git a/core/http/protocol/pom.xml b/core/http/protocol/pom.xml new file mode 100644 index 00000000000..d60b8ffcec3 --- /dev/null +++ b/core/http/protocol/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-http + 4.1.0-SNAPSHOT + + + rdf4j-http-protocol + + RDF4J: HTTP protocol + HTTP protocol (REST-style) + + + + ${project.groupId} + rdf4j-repository-api + ${project.version} + + + ${project.groupId} + rdf4j-rio-ntriples + ${project.version} + + + ${project.groupId} + rdf4j-model + ${project.version} + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + junit + junit + + + + diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/Protocol.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/Protocol.java new file mode 100644 index 00000000000..d72c28f4ce8 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/Protocol.java @@ -0,0 +1,544 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol; + +import org.eclipse.rdf4j.OpenRDFUtil; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.rio.ntriples.NTriplesUtil; + +public abstract class Protocol { + + /** + * Defines the action a particular transaction update is executing. + * + * @author Jeen Broekstra + */ + public static enum Action { + /** adding data */ + ADD, + /** deleting data */ + DELETE, + /** getStatements or exportStatements */ + GET, + /** retrieving repository size */ + SIZE, + /** SPARQL or SeRQL query */ + QUERY, + /** SPARQL Update */ + UPDATE, + /** commit */ + COMMIT, + /** rollback */ + ROLLBACK; + } + + /** + * Protocol version. + */ + public static final String VERSION = "7"; + + /** + * Parameter name for the 'subject' parameter of a statement query. + */ + public static final String SUBJECT_PARAM_NAME = "subj"; + + /** + * Parameter name for the 'predicate' parameter of a statement query. + */ + public static final String PREDICATE_PARAM_NAME = "pred"; + + /** + * Parameter name for the 'object' parameter of statement query. + */ + public static final String OBJECT_PARAM_NAME = "obj"; + + /** + * Parameter name for the 'includeInferred' parameter. + */ + public static final String INCLUDE_INFERRED_PARAM_NAME = "infer"; + + /** + * Parameter name for the context parameter. + */ + public static final String CONTEXT_PARAM_NAME = "context"; + + /** + * Parameter value for the NULL context. + */ + public static final String NULL_PARAM_VALUE = "null"; + + /** + * Parameter name for the graph parameter. + */ + public static final String GRAPH_PARAM_NAME = "graph"; + + /** + * Parameter name for the update parameter. + */ + public static final String UPDATE_PARAM_NAME = "update"; + + /** + * Parameter name for the base-URI parameter. + */ + public static final String BASEURI_PARAM_NAME = "baseURI"; + + /** + * Parameter name for the query parameter. + */ + public static final String QUERY_PARAM_NAME = "query"; + + /** + * Parameter name for the query language parameter. + */ + public static final String QUERY_LANGUAGE_PARAM_NAME = "queryLn"; + + public static final String TIMEOUT_PARAM_NAME = "timeout"; + + /** + * Parameter name for the default remove graph URI parameter. + */ + public static final String REMOVE_GRAPH_PARAM_NAME = "remove-graph-uri"; + + /** + * Parameter name for the default insert graph URI parameter. + */ + public static final String INSERT_GRAPH_PARAM_NAME = "insert-graph-uri"; + + /** + * Parameter name for the default graph URI parameter for update. + */ + public static final String USING_GRAPH_PARAM_NAME = "using-graph-uri"; + + /** + * Parameter name for the named graph URI parameter for update. + */ + public static final String USING_NAMED_GRAPH_PARAM_NAME = "using-named-graph-uri"; + + /** + * Parameter name for the default graph URI parameter. + */ + public static final String DEFAULT_GRAPH_PARAM_NAME = "default-graph-uri"; + + /** + * Parameter name for the named graph URI parameter. + */ + public static final String NAMED_GRAPH_PARAM_NAME = "named-graph-uri"; + + /** + * Parameter name for the Accept parameter (may also be used as the name of + * the Accept HTTP header). + */ + public static final String ACCEPT_PARAM_NAME = "Accept"; + + /** + * Parameter name for the isolation level used in transactions. + */ + public static final String ISOLATION_LEVEL_PARAM_NAME = "isolation-level"; + + /** + * Parameter name for the action parameter used in transactions. + */ + public static final String ACTION_PARAM_NAME = "action"; + + /** + * Relative location of the protocol resource. + */ + public static final String PROTOCOL = "protocol"; + + /** + * Relative location of the config resource. + */ + public static final String CONFIG = "config"; + + /** + * Relative location of the repository list resource. + */ + public static final String REPOSITORIES = "repositories"; + + /** + * Relative location of the statement list resource of a repository. + */ + public static final String STATEMENTS = "statements"; + + /** + * Relative location of the transaction resources of a repository. + */ + public static final String TRANSACTIONS = "transactions"; + + /** + * Relative location of the context list resource of a repository. + */ + public static final String CONTEXTS = "contexts"; + + /** + * Relative location of the namespaces list resource of a repository. + */ + public static final String NAMESPACES = "namespaces"; + + /** + * Parameter prefix for query-external variable bindings. + */ + public static final String BINDING_PREFIX = "$"; + + /** + * Relative location of the 'size' resource of a repository. + */ + public static final String SIZE = "size"; + + /** + * MIME type for transactions: application/x-rdftransaction. + */ + public static final String TXN_MIME_TYPE = "application/x-rdftransaction"; + + /** + * MIME type for www forms: application/x-www-form-urlencoded. + */ + public static final String FORM_MIME_TYPE = "application/x-www-form-urlencoded"; + + /** + * MIME type for SPARQL update: application/sparql-query. + */ + public static final String SPARQL_QUERY_MIME_TYPE = "application/sparql-query"; + + /** + * MIME type for SPARQL update: application/sparql-update. + */ + public static final String SPARQL_UPDATE_MIME_TYPE = "application/sparql-update"; + + /** + * Parameter for server instruction to preserve blank node ids when parsing + * request data. + * + * @since 2.8.0 + */ + public static final String PRESERVE_BNODE_ID_PARAM_NAME = "preserveNodeId"; + + private static String getServerDir(String serverLocation) { + if (serverLocation.endsWith("/")) { + return serverLocation; + } + else { + return serverLocation + "/"; + } + } + + /** + * Get the location of the protocol resource on the specified server. + * + * @param serverLocation + * the base location of a server implementing this REST protocol. + * @return the location of the protocol resource on the specified server + */ + public static final String getProtocolLocation(String serverLocation) { + return getServerDir(serverLocation) + PROTOCOL; + } + + /** + * Get the location of the server configuration resource on the specified + * server. + * + * @param serverLocation + * the base location of a server implementing this REST protocol. + * @return the location of the server configuration resource on the specified + * server + */ + public static final String getConfigLocation(String serverLocation) { + return getServerDir(serverLocation) + CONFIG; + } + + /** + * Get the location of the repository list resource on the specified server. + * + * @param serverLocation + * the base location of a server implementing this REST protocol. + * @return the location of the repository list resource on the specified + * server + */ + public static final String getRepositoriesLocation(String serverLocation) { + return getServerDir(serverLocation) + REPOSITORIES; + } + + /** + * Get the location of a specific repository resource on the specified + * server. + * + * @param serverLocation + * the base location of a server implementing this REST protocol. + * @param repositoryID + * the ID of the repository + * @return the location of a specific repository resource on the specified + * server + */ + public static final String getRepositoryLocation(String serverLocation, String repositoryID) { + return getRepositoriesLocation(serverLocation) + "/" + repositoryID; + } + + /** + * Get the location of the statements resource for a specific repository. + * + * @param repositoryLocation + * the location of a repository implementing this REST protocol. + * @return the location of the statements resource for the specified + * repository + */ + public static final String getStatementsLocation(String repositoryLocation) { + return repositoryLocation + "/" + STATEMENTS; + } + + /** + * Get the location of the transaction resources for a specific repository. + * + * @param repositoryLocation + * the location of a repository implementing this REST protocol. + * @return the location of the transaction resources for the specified + * repository + * @since 2.8.0 + */ + public static final String getTransactionsLocation(String repositoryLocation) { + return repositoryLocation + "/" + TRANSACTIONS; + } + + /** + * Extracts the server location from the repository location. + * + * @param repositoryLocation + * the location of a repository implementing this REST protocol. + * @return the location of the server resource for the specified repository. + */ + public static final String getServerLocation(String repositoryLocation) { + String serverLocation = repositoryLocation.substring(0, repositoryLocation.lastIndexOf('/')); + serverLocation = serverLocation.substring(0, serverLocation.lastIndexOf('/')); + return serverLocation; + } + + /** + * Extracts the repository ID from the repository location. + * + * @param repositoryLocation + * the location of a repository implementing this REST protocol. + * @return the ID of the repository. + */ + public static final String getRepositoryID(String repositoryLocation) { + String repositoryID = repositoryLocation.substring(repositoryLocation.lastIndexOf('/') + 1); + return repositoryID; + } + + /** + * Get the location of the contexts lists resource for a specific repository. + * + * @param repositoryLocation + * the location of a repository implementing this REST protocol. + * @return the location of the contexts lists resource for the specified + * repository + */ + public static final String getContextsLocation(String repositoryLocation) { + return repositoryLocation + "/" + CONTEXTS; + } + + /** + * Get the location of the namespaces lists resource for a specific + * repository on the specified server. + * + * @param repositoryLocation + * the base location of a server implementing this REST protocol. + * @return the location of the namespaces lists resource for a specific + * repository on the specified server + */ + public static final String getNamespacesLocation(String repositoryLocation) { + return repositoryLocation + "/" + NAMESPACES; + } + + /** + * Get the location of the namespace with the specified prefix for a specific + * repository on the specified server. + * + * @param repositoryLocation + * the location of a repository implementing this REST protocol. + * @param prefix + * the namespace prefix + * @return the location of the the namespace with the specified prefix for a + * specific repository on the specified server + */ + public static final String getNamespacePrefixLocation(String repositoryLocation, String prefix) { + return getNamespacesLocation(repositoryLocation) + "/" + prefix; + } + + /** + * Get the location of the 'size' resource for a specific repository on the + * specified server. + * + * @param repositoryLocation + * the location of a repository implementing this REST protocol. + * @return the location of the 'size' resource for a specific repository on + * the specified server + */ + public static final String getSizeLocation(String repositoryLocation) { + return repositoryLocation + "/" + SIZE; + } + + /** + * Encodes a value in a canonical serialized string format, for use in a URL query parameter. + * + * @param value + * The value to encode, possibly null. + * @return The protocol-serialized representation of the supplied value, or + * {@link #NULL_PARAM_VALUE} if the supplied value was null. + */ + public static String encodeValue(Value value) { + if (value instanceof BNode) { + // SES-2129 special treatment of blank node names to avoid problems with round-tripping. + return "_:" + ((BNode)value).getID(); + } + + // for everything else we just use N-Triples serialization. + return NTriplesUtil.toNTriplesString(value); + } + + /** + * Decode a previously encoded value. + * + * @param encodedValue + * the encoded value + * @param valueFactory + * the factory to use for constructing the Value + * @return the decoded Value + * @see #encodeValue(Value) + */ + public static Value decodeValue(String encodedValue, ValueFactory valueFactory) { + if (encodedValue != null) { + return NTriplesUtil.parseValue(encodedValue, valueFactory); + } + + return null; + } + + /** + * Decode a previously encoded Resource. + * + * @param encodedValue + * the encoded value + * @param valueFactory + * the factory to use for constructing the Resource + * @return the decoded Resource + * @see #encodeValue(Value) + */ + public static Resource decodeResource(String encodedValue, ValueFactory valueFactory) { + if (encodedValue != null) { + return NTriplesUtil.parseResource(encodedValue, valueFactory); + } + + return null; + } + + /** + * Decode a previously encoded URI. + * + * @param encodedValue + * the encoded value + * @param valueFactory + * the factory to use for constructing the URI + * @return the decoded URI + * @see #encodeValue(Value) + */ + public static IRI decodeURI(String encodedValue, ValueFactory valueFactory) { + if (encodedValue != null) { + return NTriplesUtil.parseURI(encodedValue, valueFactory); + } + + return null; + } + + /** + * Encodes a context resource for use in a URL. + * + * @param context + * The context to encode, possibly null. + * @return The protocol-serialized representation of the supplied context, or + * {@link #NULL_PARAM_VALUE} if the supplied value was null. + */ + public static String encodeContext(Resource context) { + if (context == null) { + return Protocol.NULL_PARAM_VALUE; + } + else { + return encodeValue(context); + } + } + + /** + * Decode a previously encoded context Resource. + * + * @param encodedValue + * the encoded value + * @param valueFactory + * the factory to use for constructing the Resource + * @return the decoded Resource, or null if the encoded values was null or + * equal to {@link #NULL_PARAM_VALUE} + */ + public static Resource decodeContext(String encodedValue, ValueFactory valueFactory) { + if (encodedValue == null) { + return null; + } + else if (NULL_PARAM_VALUE.equals(encodedValue)) { + return null; + } + else { + return decodeResource(encodedValue, valueFactory); + } + } + + /** + * Encode context resources for use in a URL. + * + * @param contexts + * the contexts to encode, must not be null. + * @return the encoded contexts + * @throws IllegalArgumentException + * If the contexts is null. + */ + public static String[] encodeContexts(Resource... contexts) { + OpenRDFUtil.verifyContextNotNull(contexts); + + String[] result = new String[contexts.length]; + for (int index = 0; index < contexts.length; index++) { + result[index] = encodeContext(contexts[index]); + } + + return result; + } + + /** + * Decode previously encoded contexts. + * + * @param encodedValues + * the encoded values + * @param valueFactory + * the factory to use for constructing the Resources + * @return the decoded Resources, or an empty array if the supplied + * encodedValues was null. + */ + public static Resource[] decodeContexts(String[] encodedValues, ValueFactory valueFactory) { + Resource[] result; + + if (encodedValues == null) { + result = new Resource[0]; + } + else { + result = new Resource[encodedValues.length]; + for (int index = 0; index < encodedValues.length; index++) { + result[index] = decodeContext(encodedValues[index], valueFactory); + } + } + + return result; + } +} \ No newline at end of file diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/UnauthorizedException.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/UnauthorizedException.java new file mode 100644 index 00000000000..712171fb13e --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/UnauthorizedException.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol; + +import org.eclipse.rdf4j.repository.RepositoryException; + +public class UnauthorizedException extends RepositoryException { + + private static final long serialVersionUID = 4322677542795160482L; + + public UnauthorizedException() { + super(); + } + + public UnauthorizedException(String msg) { + super(msg); + } + + public UnauthorizedException(Throwable t) { + super(t); + } + + public UnauthorizedException(String msg, Throwable t) { + super(msg, t); + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/error/ErrorInfo.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/error/ErrorInfo.java new file mode 100644 index 00000000000..41296c211c4 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/error/ErrorInfo.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.error; + +/** + * @author Herko ter Horst + * @author Arjohn Kampman + */ +public class ErrorInfo { + + private final ErrorType errorType; + + private final String errMSg; + + public ErrorInfo(String errMsg) { + this(null, errMsg); + } + + public ErrorInfo(ErrorType errorType, String errMsg) { + assert errMsg != null : "errMsg must not be null"; + this.errorType = errorType; + this.errMSg = errMsg; + } + + public ErrorType getErrorType() { + return errorType; + } + + public String getErrorMessage() { + return errMSg; + } + + @Override + public String toString() { + if (errorType != null) { + StringBuilder sb = new StringBuilder(64); + sb.append(errorType); + sb.append(": "); + sb.append(errMSg); + return sb.toString(); + } + else { + return errMSg; + } + } + + /** + * Parses the string output that is produced by {@link #toString()}. + */ + public static ErrorInfo parse(String errInfoString) { + String message = errInfoString; + ErrorType errorType = null; + + int colonIdx = errInfoString.indexOf(':'); + if (colonIdx >= 0) { + String label = errInfoString.substring(0, colonIdx).trim(); + errorType = ErrorType.forLabel(label); + + if (errorType != null) { + message = errInfoString.substring(colonIdx + 1); + } + } + + return new ErrorInfo(errorType, message.trim()); + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/error/ErrorType.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/error/ErrorType.java new file mode 100644 index 00000000000..f25c0bda818 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/error/ErrorType.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.error; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Arjohn Kampman + */ +public class ErrorType { + + private static final Map registry = new HashMap(); + + public static final ErrorType MALFORMED_QUERY = register("MALFORMED QUERY"); + + public static final ErrorType MALFORMED_DATA = register("MALFORMED DATA"); + + public static final ErrorType UNSUPPORTED_QUERY_LANGUAGE = register("UNSUPPORTED QUERY LANGUAGE"); + + public static final ErrorType UNSUPPORTED_FILE_FORMAT = register("UNSUPPORTED FILE FORMAT"); + + protected static ErrorType register(String label) { + synchronized (registry) { + ErrorType errorType = registry.get(label); + + if (errorType == null) { + errorType = new ErrorType(label); + registry.put(label, errorType); + } + + return errorType; + } + } + + public static ErrorType forLabel(String label) { + synchronized (registry) { + return registry.get(label); + } + } + + /** + * The error type's label. + */ + private String label; + + private ErrorType(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } + + @Override + public boolean equals(Object other) { + if (other instanceof ErrorType) { + return ((ErrorType)other).getLabel().equals(this.getLabel()); + } + + return false; + } + + @Override + public int hashCode() { + return getLabel().hashCode(); + } + + @Override + public String toString() { + return label; + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionReader.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionReader.java new file mode 100644 index 00000000000..540b310d45d --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionReader.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.Collection; + +import org.eclipse.rdf4j.common.xml.SimpleSAXParser; +import org.eclipse.rdf4j.http.protocol.transaction.operations.TransactionOperation; +import org.xml.sax.SAXException; + +public class TransactionReader { + + /** + * parse the transaction from the serialization + * + * @throws SAXException + * If the SimpleSAXParser was unable to create an XMLReader or if the + * XML is faulty. + * @throws IOException + * If IO problems during parsing. + */ + public Collection parse(InputStream in) + throws SAXException, IOException + { + SimpleSAXParser saxParser = new SimpleSAXParser(); + saxParser.setPreserveWhitespace(true); + + TransactionSAXParser handler = new TransactionSAXParser(); + saxParser.setListener(handler); + saxParser.parse(in); + return handler.getTxn(); + } + + /** + * parse the transaction from the serialization + * + * @throws SAXException + * If the SimpleSAXParser was unable to create an XMLReader or if the + * XML is faulty. + * @throws IOException + * If IO problems during parsing. + */ + public Collection parse(Reader in) + throws SAXException, IOException + { + SimpleSAXParser saxParser = new SimpleSAXParser(); + TransactionSAXParser handler = new TransactionSAXParser(); + saxParser.setPreserveWhitespace(true); + saxParser.setListener(handler); + saxParser.parse(in); + return handler.getTxn(); + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionSAXParser.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionSAXParser.java new file mode 100644 index 00000000000..27b626b7418 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionSAXParser.java @@ -0,0 +1,336 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.eclipse.rdf4j.common.xml.SimpleSAXAdapter; +import org.eclipse.rdf4j.http.protocol.transaction.operations.AddStatementOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.ClearNamespacesOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.ClearOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.RemoveNamespaceOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.RemoveStatementsOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.SPARQLUpdateOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.SetNamespaceOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.TransactionOperation; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.impl.SimpleBinding; +import org.eclipse.rdf4j.query.impl.SimpleDataset; +import org.xml.sax.SAXException; + +/** + * Parses an RDF transaction document into a collection of + * {@link TransactionOperation} objects. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +class TransactionSAXParser extends SimpleSAXAdapter { + + private ValueFactory valueFactory; + + protected Collection txn; + + private List parsedValues = new ArrayList(); + + private List bindings; + + private SPARQLUpdateOperation currentSPARQLUpdate = null; + + private SimpleDataset currentDataset; + + public TransactionSAXParser() { + this(SimpleValueFactory.getInstance()); + } + + public TransactionSAXParser(ValueFactory valueFactory) { + this.valueFactory = valueFactory; + } + + /** + * get the parsed transaction + * + * @return the parsed transaction + */ + public Collection getTxn() { + return txn; + } + + @Override + public void startDocument() + throws SAXException + { + txn = new ArrayList(); + } + + @Override + public void startTag(String tagName, Map atts, String text) + throws SAXException + { + if (TransactionXMLConstants.URI_TAG.equals(tagName)) { + parsedValues.add(valueFactory.createIRI(text)); + } + else if (TransactionXMLConstants.BNODE_TAG.equals(tagName)) { + parsedValues.add(valueFactory.createBNode(text)); + } + else if (TransactionXMLConstants.LITERAL_TAG.equals(tagName)) { + String lang = atts.get(TransactionXMLConstants.LANG_ATT); + String datatype = atts.get(TransactionXMLConstants.DATATYPE_ATT); + String encoding = atts.get(TransactionXMLConstants.ENCODING_ATT); + + if (encoding != null && "base64".equalsIgnoreCase(encoding)) { + text = new String(javax.xml.bind.DatatypeConverter.parseBase64Binary(text)); + } + Literal lit; + if (lang != null) { + lit = valueFactory.createLiteral(text, lang); + } + else if (datatype != null) { + IRI dtURI = valueFactory.createIRI(datatype); + lit = valueFactory.createLiteral(text, dtURI); + } + else { + lit = valueFactory.createLiteral(text); + } + + parsedValues.add(lit); + } + else if (TransactionXMLConstants.NULL_TAG.equals(tagName)) { + parsedValues.add(null); + } + else if (TransactionXMLConstants.SET_NAMESPACE_TAG.equals(tagName)) { + String prefix = atts.get(TransactionXMLConstants.PREFIX_ATT); + String name = atts.get(TransactionXMLConstants.NAME_ATT); + txn.add(new SetNamespaceOperation(prefix, name)); + } + else if (TransactionXMLConstants.REMOVE_NAMESPACE_TAG.equals(tagName)) { + String prefix = atts.get(TransactionXMLConstants.PREFIX_ATT); + txn.add(new RemoveNamespaceOperation(prefix)); + } + else if (TransactionXMLConstants.CLEAR_NAMESPACES_TAG.equals(tagName)) { + txn.add(new ClearNamespacesOperation()); + } + else if (TransactionXMLConstants.SPARQL_UPDATE_TAG.equals(tagName)) { + if (currentSPARQLUpdate != null) { + throw new SAXException("unexpected start of SPARQL Update operation"); + } + currentSPARQLUpdate = new SPARQLUpdateOperation(); + + String baseURI = atts.get(TransactionXMLConstants.BASE_URI_ATT); + boolean includeInferred = Boolean.parseBoolean(atts.get(TransactionXMLConstants.INCLUDE_INFERRED_ATT)); + + currentSPARQLUpdate.setIncludeInferred(includeInferred); + currentSPARQLUpdate.setBaseURI(baseURI); + } + else if (TransactionXMLConstants.UPDATE_STRING_TAG.equals(tagName)) { + currentSPARQLUpdate.setUpdateString(text); + } + else if (TransactionXMLConstants.DATASET_TAG.equals(tagName)) { + currentDataset = new SimpleDataset(); + } + else if (TransactionXMLConstants.DEFAULT_INSERT_GRAPH.equals(tagName)) { + currentDataset.setDefaultInsertGraph(valueFactory.createIRI(text)); + } + else if (TransactionXMLConstants.GRAPH_TAG.equals(tagName)) { + parsedValues.add(valueFactory.createIRI(text)); + } + else if (TransactionXMLConstants.BINDINGS.equals(tagName)) { + if (bindings != null) { + throw new SAXException("unexpected start of SPARQL Update operation bindings"); + } + + bindings = new ArrayList(); + } + else if (TransactionXMLConstants.BINDING_URI.equals(tagName) + || TransactionXMLConstants.BINDING_BNODE.equals(tagName) + || TransactionXMLConstants.BINDING_LITERAL.equals(tagName)) + { + if (bindings == null) { + throw new SAXException("unexpected start of SPARQL Update operation binding (without )"); + } + + String value = text; + String name = atts.get(TransactionXMLConstants.NAME_ATT); + + if (name != null && value != null) { + Value v; + + if (TransactionXMLConstants.BINDING_URI.equals(tagName)) { + v = valueFactory.createIRI(value); + } + else if (TransactionXMLConstants.BINDING_BNODE.equals(tagName)) { + v = valueFactory.createBNode(value); + } + else { + String language = atts.get(TransactionXMLConstants.LANGUAGE_ATT); + String dataType = atts.get(TransactionXMLConstants.DATA_TYPE_ATT); + + if (language != null) { + v = valueFactory.createLiteral(value, language); + } + else if (dataType != null) { + v = valueFactory.createLiteral(value, valueFactory.createIRI(dataType)); + } + else { + v = valueFactory.createLiteral(value); + } + } + bindings.add(new SimpleBinding(name, v)); + } + } + } + + @Override + public void endTag(String tagName) + throws SAXException + { + if (TransactionXMLConstants.ADD_STATEMENT_TAG.equals(tagName)) { + txn.add(createAddStatementOperation()); + } + else if (TransactionXMLConstants.REMOVE_STATEMENTS_TAG.equals(tagName)) { + txn.add(createRemoveStatementsOperation()); + } + else if (TransactionXMLConstants.CLEAR_TAG.equals(tagName)) { + txn.add(createClearOperation()); + } + else if (TransactionXMLConstants.SPARQL_UPDATE_TAG.equals(tagName)) { + txn.add(currentSPARQLUpdate); + currentSPARQLUpdate = null; + } + else if (TransactionXMLConstants.DEFAULT_GRAPHS_TAG.equals(tagName)) { + for (Value parsedValue : parsedValues) { + try { + currentDataset.addDefaultGraph((IRI)parsedValue); + } + catch (ClassCastException e) { + throw new SAXException("unexpected value in default graph list: " + parsedValue); + } + } + parsedValues.clear(); + } + else if (TransactionXMLConstants.NAMED_GRAPHS_TAG.equals(tagName)) { + for (Value parsedValue : parsedValues) { + try { + currentDataset.addNamedGraph((IRI)parsedValue); + } + catch (ClassCastException e) { + throw new SAXException("unexpected value in named graph list: " + parsedValue); + } + } + parsedValues.clear(); + } + else if (TransactionXMLConstants.DEFAULT_REMOVE_GRAPHS_TAG.equals(tagName)) { + for (Value parsedValue : parsedValues) { + try { + currentDataset.addDefaultRemoveGraph((IRI)parsedValue); + } + catch (ClassCastException e) { + throw new SAXException("unexpected value in default remove graph list: " + parsedValue); + } + } + parsedValues.clear(); + } + else if (TransactionXMLConstants.DATASET_TAG.equals(tagName)) { + currentSPARQLUpdate.setDataset(currentDataset); + currentDataset = null; + } + else if (TransactionXMLConstants.BINDINGS.equals(tagName)) { + Binding b[] = bindings.toArray(new Binding[0]); + currentSPARQLUpdate.setBindings(b); + bindings.clear(); + bindings = null; + } + } + + private TransactionOperation createClearOperation() + throws SAXException + { + Resource[] contexts = createContexts(0); + parsedValues.clear(); + + return new ClearOperation(contexts); + } + + private TransactionOperation createAddStatementOperation() + throws SAXException + { + if (parsedValues.size() < 3) { + throw new SAXException("At least three values required for AddStatementOperation, found: " + + parsedValues.size()); + } + + try { + Resource subject = (Resource)parsedValues.get(0); + IRI predicate = (IRI)parsedValues.get(1); + Value object = parsedValues.get(2); + Resource[] contexts = createContexts(3); + + parsedValues.clear(); + + if (subject == null || predicate == null || object == null) { + throw new SAXException( + "Subject, predicate and object cannot be null for an AddStatementOperation"); + } + return new AddStatementOperation(subject, predicate, object, contexts); + } + catch (ClassCastException e) { + throw new SAXException("Invalid argument(s) for AddStatementOperation", e); + } + } + + private TransactionOperation createRemoveStatementsOperation() + throws SAXException + { + if (parsedValues.size() < 3) { + throw new SAXException("At least three values required for RemoveStatementsOperation, found: " + + parsedValues.size()); + } + + try { + Resource subject = (Resource)parsedValues.get(0); + IRI predicate = (IRI)parsedValues.get(1); + Value object = parsedValues.get(2); + Resource[] contexts = createContexts(3); + + parsedValues.clear(); + + return new RemoveStatementsOperation(subject, predicate, object, contexts); + } + catch (ClassCastException e) { + throw new SAXException("Invalid argument(s) for RemoveStatementsOperation", e); + } + } + + private Resource[] createContexts(int startIdx) + throws SAXException + { + List contexts = new ArrayList(); + + for (int i = startIdx; i < parsedValues.size(); i++) { + Value contextCandidate = parsedValues.get(i); + + if (contextCandidate == null || contextCandidate instanceof Resource) { + contexts.add((Resource)contextCandidate); + } + else { + throw new SAXException("Invalid context value: " + contextCandidate.getClass()); + } + } + + return contexts.toArray(new Resource[contexts.size()]); + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionWriter.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionWriter.java new file mode 100644 index 00000000000..656f3c97bfb --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionWriter.java @@ -0,0 +1,361 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction; + +import java.io.IOException; +import java.io.OutputStream; + +import org.eclipse.rdf4j.common.xml.XMLUtil; +import org.eclipse.rdf4j.common.xml.XMLWriter; +import org.eclipse.rdf4j.http.protocol.transaction.operations.AddStatementOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.ClearNamespacesOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.ClearOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.RemoveNamespaceOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.RemoveStatementsOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.SPARQLUpdateOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.SetNamespaceOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.StatementOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.TransactionOperation; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.util.Literals; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.Dataset; + +/** + * Serializes of an RDF transaction. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public class TransactionWriter { + + public TransactionWriter() { + } + + /** + * serialize the passed list of operations to the passed writer. + * + * @param txn + * the operations + * @param out + * the output stream to write to + * @throws IllegalArgumentException + * when one of the parameters is null + */ + public void serialize(Iterable txn, OutputStream out) + throws IOException + { + assert txn != null : "operation list must not be null"; + assert out != null : "output stream must not be null"; + + XMLWriter xmlWriter = new XMLWriter(out); + xmlWriter.setPrettyPrint(true); + + xmlWriter.startDocument(); + xmlWriter.startTag(TransactionXMLConstants.TRANSACTION_TAG); + + for (TransactionOperation op : txn) { + serialize(op, xmlWriter); + } + + xmlWriter.endTag(TransactionXMLConstants.TRANSACTION_TAG); + xmlWriter.endDocument(); + } + + /** + * Serializes the supplied operation. + * + * @param op + * The operation to serialize + */ + protected void serialize(TransactionOperation op, XMLWriter xmlWriter) + throws IOException + { + if (op instanceof AddStatementOperation) { + serialize((AddStatementOperation)op, xmlWriter); + } + else if (op instanceof RemoveStatementsOperation) { + serialize((RemoveStatementsOperation)op, xmlWriter); + } + else if (op instanceof ClearOperation) { + serialize((ClearOperation)op, xmlWriter); + } + else if (op instanceof SetNamespaceOperation) { + serialize((SetNamespaceOperation)op, xmlWriter); + } + else if (op instanceof RemoveNamespaceOperation) { + serialize((RemoveNamespaceOperation)op, xmlWriter); + } + else if (op instanceof ClearNamespacesOperation) { + serialize((ClearNamespacesOperation)op, xmlWriter); + } + else if (op instanceof SPARQLUpdateOperation) { + serialize((SPARQLUpdateOperation)op, xmlWriter); + } + else if (op == null) { + // ignore(?) + } + else { + throw new IllegalArgumentException("Unknown operation type: " + op.getClass()); + } + } + + protected void serialize(AddStatementOperation op, XMLWriter xmlWriter) + throws IOException + { + xmlWriter.startTag(TransactionXMLConstants.ADD_STATEMENT_TAG); + serialize((StatementOperation)op, xmlWriter); + xmlWriter.endTag(TransactionXMLConstants.ADD_STATEMENT_TAG); + } + + protected void serialize(SPARQLUpdateOperation op, XMLWriter xmlWriter) + throws IOException + { + String baseURI = op.getBaseURI(); + if (baseURI != null) { + xmlWriter.setAttribute(TransactionXMLConstants.BASE_URI_ATT, baseURI); + } + xmlWriter.setAttribute(TransactionXMLConstants.INCLUDE_INFERRED_ATT, op.isIncludeInferred()); + xmlWriter.startTag(TransactionXMLConstants.SPARQL_UPDATE_TAG); + + // serialize update string + String updateString = op.getUpdateString(); + xmlWriter.textElement(TransactionXMLConstants.UPDATE_STRING_TAG, updateString); + + // serialize dataset definition (if any) + Dataset dataset = op.getDataset(); + if (dataset != null) { + xmlWriter.startTag(TransactionXMLConstants.DATASET_TAG); + + xmlWriter.startTag(TransactionXMLConstants.DEFAULT_GRAPHS_TAG); + for (IRI defaultGraph : dataset.getDefaultGraphs()) { + xmlWriter.textElement(TransactionXMLConstants.GRAPH_TAG, defaultGraph.stringValue()); + } + xmlWriter.endTag(TransactionXMLConstants.DEFAULT_GRAPHS_TAG); + + xmlWriter.startTag(TransactionXMLConstants.NAMED_GRAPHS_TAG); + for (IRI namedGraph : dataset.getNamedGraphs()) { + xmlWriter.textElement(TransactionXMLConstants.GRAPH_TAG, namedGraph.stringValue()); + } + xmlWriter.endTag(TransactionXMLConstants.NAMED_GRAPHS_TAG); + + xmlWriter.startTag(TransactionXMLConstants.DEFAULT_REMOVE_GRAPHS_TAG); + for (IRI defaultRemoveGraph : dataset.getDefaultRemoveGraphs()) { + xmlWriter.textElement(TransactionXMLConstants.GRAPH_TAG, defaultRemoveGraph.stringValue()); + } + xmlWriter.endTag(TransactionXMLConstants.DEFAULT_REMOVE_GRAPHS_TAG); + + if (dataset.getDefaultInsertGraph() != null) { + xmlWriter.textElement(TransactionXMLConstants.DEFAULT_INSERT_GRAPH, + dataset.getDefaultInsertGraph().stringValue()); + } + xmlWriter.endTag(TransactionXMLConstants.DATASET_TAG); + } + + if (op.getBindings() != null && op.getBindings().length > 0) { + xmlWriter.startTag(TransactionXMLConstants.BINDINGS); + + for (Binding binding : op.getBindings()) { + if (binding.getName() != null && binding.getValue() != null + && binding.getValue().stringValue() != null) + { + if (binding.getValue() instanceof IRI) { + xmlWriter.setAttribute(TransactionXMLConstants.NAME_ATT, binding.getName()); + xmlWriter.textElement(TransactionXMLConstants.BINDING_URI, binding.getValue().stringValue()); + } + + if (binding.getValue() instanceof BNode) { + xmlWriter.setAttribute(TransactionXMLConstants.NAME_ATT, binding.getName()); + xmlWriter.textElement(TransactionXMLConstants.BINDING_BNODE, + binding.getValue().stringValue()); + } + + if (binding.getValue() instanceof Literal) { + xmlWriter.setAttribute(TransactionXMLConstants.NAME_ATT, binding.getName()); + + Literal literal = (Literal)binding.getValue(); + if (Literals.isLanguageLiteral(literal)) { + xmlWriter.setAttribute(TransactionXMLConstants.LANGUAGE_ATT, literal.getLanguage().get()); + } + else { + xmlWriter.setAttribute(TransactionXMLConstants.DATA_TYPE_ATT, + literal.getDatatype().stringValue()); + } + + xmlWriter.textElement(TransactionXMLConstants.BINDING_LITERAL, + binding.getValue().stringValue()); + } + } + } + + xmlWriter.endTag(TransactionXMLConstants.BINDINGS); + } + + xmlWriter.endTag(TransactionXMLConstants.SPARQL_UPDATE_TAG); + + } + + protected void serialize(RemoveStatementsOperation op, XMLWriter xmlWriter) + throws IOException + { + xmlWriter.startTag(TransactionXMLConstants.REMOVE_STATEMENTS_TAG); + serialize((StatementOperation)op, xmlWriter); + xmlWriter.endTag(TransactionXMLConstants.REMOVE_STATEMENTS_TAG); + } + + protected void serialize(StatementOperation op, XMLWriter xmlWriter) + throws IOException + { + serialize(op.getSubject(), xmlWriter); + serialize(op.getPredicate(), xmlWriter); + serialize(op.getObject(), xmlWriter); + serialize(op.getContexts(), xmlWriter); + } + + protected void serialize(ClearOperation op, XMLWriter xmlWriter) + throws IOException + { + xmlWriter.startTag(TransactionXMLConstants.CLEAR_TAG); + serialize(op.getContexts(), xmlWriter); + xmlWriter.endTag(TransactionXMLConstants.CLEAR_TAG); + } + + protected void serialize(SetNamespaceOperation op, XMLWriter xmlWriter) + throws IOException + { + xmlWriter.setAttribute(TransactionXMLConstants.PREFIX_ATT, op.getPrefix()); + xmlWriter.setAttribute(TransactionXMLConstants.NAME_ATT, op.getName()); + xmlWriter.emptyElement(TransactionXMLConstants.SET_NAMESPACE_TAG); + } + + protected void serialize(RemoveNamespaceOperation op, XMLWriter xmlWriter) + throws IOException + { + xmlWriter.setAttribute(TransactionXMLConstants.PREFIX_ATT, op.getPrefix()); + xmlWriter.emptyElement(TransactionXMLConstants.REMOVE_NAMESPACE_TAG); + } + + protected void serialize(ClearNamespacesOperation op, XMLWriter xmlWriter) + throws IOException + { + xmlWriter.emptyElement(TransactionXMLConstants.CLEAR_NAMESPACES_TAG); + } + + protected void serialize(Resource[] contexts, XMLWriter xmlWriter) + throws IOException + { + if (contexts.length > 0) { + xmlWriter.startTag(TransactionXMLConstants.CONTEXTS_TAG); + for (Resource context : contexts) { + serialize(context, xmlWriter); + } + xmlWriter.endTag(TransactionXMLConstants.CONTEXTS_TAG); + } + else { + xmlWriter.emptyElement(TransactionXMLConstants.CONTEXTS_TAG); + } + } + + protected void serialize(Value value, XMLWriter xmlWriter) + throws IOException + { + if (value instanceof Resource) { + serialize((Resource)value, xmlWriter); + } + else if (value instanceof Literal) { + serialize((Literal)value, xmlWriter); + } + else if (value == null) { + serializeNull(xmlWriter); + } + else { + throw new IllegalArgumentException("Unknown value type: " + value.getClass().toString()); + } + } + + protected void serialize(Resource resource, XMLWriter xmlWriter) + throws IOException + { + if (resource instanceof IRI) { + serialize((IRI)resource, xmlWriter); + } + else if (resource instanceof BNode) { + serialize((BNode)resource, xmlWriter); + } + else if (resource == null) { + serializeNull(xmlWriter); + } + else { + throw new IllegalArgumentException("Unknown resource type: " + resource.getClass().toString()); + } + } + + protected void serialize(IRI uri, XMLWriter xmlWriter) + throws IOException + { + if (uri != null) { + xmlWriter.textElement(TransactionXMLConstants.URI_TAG, uri.toString()); + } + else { + serializeNull(xmlWriter); + } + } + + protected void serialize(BNode bnode, XMLWriter xmlWriter) + throws IOException + { + if (bnode != null) { + xmlWriter.textElement(TransactionXMLConstants.BNODE_TAG, bnode.getID()); + } + else { + serializeNull(xmlWriter); + } + } + + protected void serialize(Literal literal, XMLWriter xmlWriter) + throws IOException + { + if (literal != null) { + if (Literals.isLanguageLiteral(literal)) { + xmlWriter.setAttribute(TransactionXMLConstants.LANG_ATT, literal.getLanguage().get()); + } + else { + xmlWriter.setAttribute(TransactionXMLConstants.DATATYPE_ATT, literal.getDatatype().toString()); + } + + String label = literal.getLabel(); + + boolean valid = true; + int i = 0; + while (valid && i < label.length()) { + char c = label.charAt(i++); + valid = XMLUtil.isValidCharacterDataChar(c); + } + + if (!valid) { + xmlWriter.setAttribute(TransactionXMLConstants.ENCODING_ATT, "base64"); + label = javax.xml.bind.DatatypeConverter.printBase64Binary(label.getBytes("UTF-8")); + } + + xmlWriter.textElement(TransactionXMLConstants.LITERAL_TAG, label); + } + else { + serializeNull(xmlWriter); + } + } + + protected void serializeNull(XMLWriter xmlWriter) + throws IOException + { + xmlWriter.emptyElement(TransactionXMLConstants.NULL_TAG); + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionXMLConstants.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionXMLConstants.java new file mode 100644 index 00000000000..51e54669c69 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionXMLConstants.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction; + +/** + * Interface defining tags and attribute names for the XML serialization of + * transactions. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +interface TransactionXMLConstants { + + public static final String TRANSACTION_TAG = "transaction"; + + public static final String ADD_STATEMENT_TAG = "add"; + + public static final String REMOVE_STATEMENTS_TAG = "remove"; + + public static final String REMOVE_NAMED_CONTEXT_STATEMENTS_TAG = "removeFromNamedContext"; + + public static final String CLEAR_TAG = "clear"; + + public static final String NULL_TAG = "null"; + + public static final String URI_TAG = "uri"; + + public static final String BNODE_TAG = "bnode"; + + public static final String LITERAL_TAG = "literal"; + + public static final String ENCODING_ATT = "encoding"; + + public static final String LANG_ATT = "xml:lang"; + + public static final String DATATYPE_ATT = "datatype"; + + public static final String SET_NAMESPACE_TAG = "setNamespace"; + + public static final String REMOVE_NAMESPACE_TAG = "removeNamespace"; + + public static final String PREFIX_ATT = "prefix"; + + public static final String NAME_ATT = "name"; + + public static final String CLEAR_NAMESPACES_TAG = "clearNamespaces"; + + public static final String CONTEXTS_TAG = "contexts"; + + /** + * @since 2.7.0 + */ + public static final String SPARQL_UPDATE_TAG = "sparql"; + + /** + * @since 2.7.0 + */ + public static final String UPDATE_STRING_TAG = "updateString"; + + /** + * @since 2.7.0 + */ + public static final String BASE_URI_ATT = "baseURI"; + + /** + * @since 2.7.0 + */ + public static final String INCLUDE_INFERRED_ATT = "includeInferred"; + + /** + * @since 2.7.0 + */ + public static final String DATASET_TAG = "dataset"; + + /** + * @since 2.7.0 + */ + public static final String GRAPH_TAG = "graph"; + + /** + * @since 2.7.0 + */ + public static final String DEFAULT_GRAPHS_TAG = "defaultGraphs"; + + /** + * @since 2.7.0 + */ + public static final String NAMED_GRAPHS_TAG = "namedGraphs"; + + /** + * @since 2.7.0 + */ + public static final String DEFAULT_REMOVE_GRAPHS_TAG = "defaultRemoveGraphs"; + + /** + * @since 2.7.0 + */ + public static final String DEFAULT_INSERT_GRAPH = "defaultInsertGraph"; + + public static final String BINDINGS = "bindings"; + + public static final String BINDING_URI = "binding_uri"; + + public static final String BINDING_BNODE = "binding_bnode"; + + public static final String BINDING_LITERAL = "binding_literal"; + + public static final String LANGUAGE_ATT = "language"; + + public static final String DATA_TYPE_ATT = "dataType"; +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/AddStatementOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/AddStatementOperation.java new file mode 100644 index 00000000000..e0897aa4667 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/AddStatementOperation.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import java.io.Serializable; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * Operation to add a statement. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public class AddStatementOperation extends StatementOperation implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 7055177153036638975L; + + /** + * Create an AddStatementOperation. + */ + public AddStatementOperation(Resource subj, IRI pred, Value obj, Resource... contexts) { + super(contexts); + + assert subj != null : "subj must not be null"; + assert pred != null : "pred must not be null"; + assert obj != null : "obj must not be null"; + + setSubject(subj); + setPredicate(pred); + setObject(obj); + } + + public void execute(RepositoryConnection con) + throws RepositoryException + { + con.add(getSubject(), getPredicate(), getObject(), getContexts()); + } + + @Override + public boolean equals(Object other) + { + if (other instanceof AddStatementOperation) { + return super.equals(other); + } + + return false; + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ClearNamespacesOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ClearNamespacesOperation.java new file mode 100644 index 00000000000..77b1d6d46d2 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ClearNamespacesOperation.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import java.io.Serializable; + +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * Operation that removes all namespace declarations. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public class ClearNamespacesOperation implements TransactionOperation, Serializable { + + /** + * + */ + private static final long serialVersionUID = 804163331093326031L; + + public ClearNamespacesOperation() { + } + + public void execute(RepositoryConnection con) + throws RepositoryException + { + con.clearNamespaces(); + } + + @Override + public boolean equals(Object other) + { + return other instanceof ClearNamespacesOperation; + } + + @Override + public int hashCode() + { + return 101; + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ClearOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ClearOperation.java new file mode 100644 index 00000000000..70972c4cd90 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ClearOperation.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import java.io.Serializable; + +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * Operation that clears the whole repository. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public class ClearOperation extends ContextOperation implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -1570893715836564121L; + + public ClearOperation(Resource... contexts) { + super(contexts); + } + + public void execute(RepositoryConnection con) + throws RepositoryException + { + con.clear(getContexts()); + } + + @Override + public boolean equals(Object other) + { + if (other instanceof ClearOperation) { + return super.equals(other); + } + + return false; + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ContextOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ContextOperation.java new file mode 100644 index 00000000000..babd867ec1d --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/ContextOperation.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import java.util.Arrays; + +import org.eclipse.rdf4j.OpenRDFUtil; +import org.eclipse.rdf4j.model.Resource; + +/** + * A TransactionOperation that operates on a specific (set of) contexts. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public abstract class ContextOperation implements TransactionOperation { + + protected Resource[] contexts; + + protected ContextOperation(Resource... contexts) { + setContexts(contexts); + } + + public Resource[] getContexts() { + return contexts; + } + + public void setContexts(Resource... contexts) { + OpenRDFUtil.verifyContextNotNull(contexts); + + this.contexts = contexts; + } + + @Override + public boolean equals(Object other) + { + if (other instanceof ContextOperation) { + ContextOperation o = (ContextOperation)other; + return Arrays.deepEquals(getContexts(), o.getContexts()); + } + + return false; + } + + @Override + public int hashCode() + { + return Arrays.deepHashCode(getContexts()); + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/RemoveNamespaceOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/RemoveNamespaceOperation.java new file mode 100644 index 00000000000..aa04b3a8993 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/RemoveNamespaceOperation.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import java.io.Serializable; + +import org.eclipse.rdf4j.common.lang.ObjectUtil; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * Operation that removes the namespace for a specific prefix. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public class RemoveNamespaceOperation implements TransactionOperation, Serializable { + + /** + * + */ + private static final long serialVersionUID = 3227597422508894927L; + + private String prefix; + + public RemoveNamespaceOperation() { + } + + public RemoveNamespaceOperation(String prefix) { + setPrefix(prefix); + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public void execute(RepositoryConnection con) + throws RepositoryException + { + con.removeNamespace(prefix); + } + + @Override + public boolean equals(Object other) + { + if (other instanceof RemoveNamespaceOperation) { + RemoveNamespaceOperation o = (RemoveNamespaceOperation)other; + return ObjectUtil.nullEquals(getPrefix(), o.getPrefix()); + } + + return false; + } + + @Override + public int hashCode() + { + return ObjectUtil.nullHashCode(getPrefix()); + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/RemoveStatementsOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/RemoveStatementsOperation.java new file mode 100644 index 00000000000..fa306def293 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/RemoveStatementsOperation.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import java.io.Serializable; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * Operation to remove statements matching specific pattern of subject, + * predicate and object. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public class RemoveStatementsOperation extends StatementOperation implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1497684375399016153L; + + /** + * Creates a RemoveStatementsOperation. + */ + public RemoveStatementsOperation(Resource subj, IRI pred, Value obj, Resource... contexts) { + super(contexts); + + setSubject(subj); + setPredicate(pred); + setObject(obj); + } + + public void execute(RepositoryConnection con) + throws RepositoryException + { + con.remove(getSubject(), getPredicate(), getObject(), getContexts()); + } + + @Override + public boolean equals(Object other) + { + if (other instanceof RemoveStatementsOperation) { + return super.equals(other); + } + + return false; + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/SPARQLUpdateOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/SPARQLUpdateOperation.java new file mode 100644 index 00000000000..49101d9208e --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/SPARQLUpdateOperation.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import java.io.Serializable; + +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.Update; +import org.eclipse.rdf4j.query.UpdateExecutionException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * Encapsulation of a SPARQL 1.1 update operation executed as part of a transaction. + * + * @author Jeen Broekstra + * @since 2.7.0 + */ +public class SPARQLUpdateOperation implements TransactionOperation, Serializable { + + /** + * + */ + private static final long serialVersionUID = 4432275498318918582L; + + private String updateString; + + private String baseURI; + + private boolean includeInferred; + + private Dataset dataset; + + private Binding[] bindings; + + public SPARQLUpdateOperation() { + super(); + } + + public SPARQLUpdateOperation(String updateString, String baseURI, boolean includeInferred, + Dataset dataset, Binding... bindings) + { + this.setUpdateString(updateString); + this.setBaseURI(baseURI); + this.setIncludeInferred(includeInferred); + this.setDataset(dataset); + this.setBindings(bindings); + } + + public void execute(RepositoryConnection con) + throws RepositoryException + { + try { + Update preparedUpdate = con.prepareUpdate(QueryLanguage.SPARQL, getUpdateString(), getBaseURI()); + preparedUpdate.setIncludeInferred(isIncludeInferred()); + preparedUpdate.setDataset(getDataset()); + + if (getBindings() != null) { + for (Binding binding : getBindings()) { + preparedUpdate.setBinding(binding.getName(), binding.getValue()); + } + } + + preparedUpdate.execute(); + } + catch (MalformedQueryException e) { + throw new RepositoryException(e); + } + catch (UpdateExecutionException e) { + throw new RepositoryException(e); + } + + } + + /** + * @return Returns the updateString. + */ + public String getUpdateString() { + return updateString; + } + + /** + * @param updateString + * The updateString to set. + */ + public void setUpdateString(String updateString) { + this.updateString = updateString; + } + + /** + * @return Returns the baseURI. + */ + public String getBaseURI() { + return baseURI; + } + + /** + * @param baseURI + * The baseURI to set. + */ + public void setBaseURI(String baseURI) { + this.baseURI = baseURI; + } + + /** + * @return Returns the includeInferred. + */ + public boolean isIncludeInferred() { + return includeInferred; + } + + /** + * @param includeInferred + * The includeInferred to set. + */ + public void setIncludeInferred(boolean includeInferred) { + this.includeInferred = includeInferred; + } + + /** + * @return Returns the dataset. + */ + public Dataset getDataset() { + return dataset; + } + + /** + * @param dataset + * The dataset to set. + */ + public void setDataset(Dataset dataset) { + this.dataset = dataset; + } + + /** + * @return Returns the bindings. + */ + public Binding[] getBindings() { + return bindings; + } + + /** + * @param bindings + * The bindings to set. + */ + public void setBindings(Binding[] bindings) { + this.bindings = bindings; + } + +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/SetNamespaceOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/SetNamespaceOperation.java new file mode 100644 index 00000000000..98889f573fd --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/SetNamespaceOperation.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import java.io.Serializable; + +import org.eclipse.rdf4j.common.lang.ObjectUtil; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * Operation that sets the namespace for a specific prefix. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public class SetNamespaceOperation implements TransactionOperation, Serializable { + + /** + * + */ + private static final long serialVersionUID = 7197096029612751574L; + + private String prefix; + + private String name; + + public SetNamespaceOperation() { + } + + public SetNamespaceOperation(String prefix, String name) { + setPrefix(prefix); + setName(name); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public void execute(RepositoryConnection con) + throws RepositoryException + { + con.setNamespace(prefix, name); + } + + @Override + public boolean equals(Object other) + { + if (other instanceof SetNamespaceOperation) { + SetNamespaceOperation o = (SetNamespaceOperation)other; + return ObjectUtil.nullEquals(getPrefix(), o.getPrefix()) + && ObjectUtil.nullEquals(getName(), o.getName()); + } + + return false; + } + + @Override + public int hashCode() + { + int hashCode = ObjectUtil.nullHashCode(getPrefix()); + hashCode = 31 * hashCode + ObjectUtil.nullHashCode(getName()); + return hashCode; + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/StatementOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/StatementOperation.java new file mode 100644 index 00000000000..5bfac05df63 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/StatementOperation.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import org.eclipse.rdf4j.common.lang.ObjectUtil; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; + +/** + * A context operation with (optional) subject, predicate, object. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public abstract class StatementOperation extends ContextOperation { + + private Resource subject; + + private IRI predicate; + + private Value object; + + protected StatementOperation(Resource... contexts) { + super(contexts); + } + + public Resource getSubject() { + return subject; + } + + public void setSubject(Resource subject) { + this.subject = subject; + } + + public IRI getPredicate() { + return predicate; + } + + public void setPredicate(IRI predicate) { + this.predicate = predicate; + } + + public Value getObject() { + return object; + } + + public void setObject(Value object) { + this.object = object; + } + + @Override + public boolean equals(Object other) + { + if (other instanceof StatementOperation) { + StatementOperation o = (StatementOperation)other; + + return ObjectUtil.nullEquals(getSubject(), o.getSubject()) + && ObjectUtil.nullEquals(getPredicate(), o.getPredicate()) + && ObjectUtil.nullEquals(getObject(), o.getObject()) + && super.equals(other); + } + + return false; + } + + @Override + public int hashCode() + { + int hashCode = ObjectUtil.nullHashCode(getSubject()); + hashCode = 31 * hashCode + ObjectUtil.nullHashCode(getPredicate()); + hashCode = 31 * hashCode + ObjectUtil.nullHashCode(getObject()); + hashCode = 31 * hashCode + super.hashCode(); + return hashCode; + } +} diff --git a/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/TransactionOperation.java b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/TransactionOperation.java new file mode 100644 index 00000000000..0a636e52b92 --- /dev/null +++ b/core/http/protocol/src/main/java/org/eclipse/rdf4j/http/protocol/transaction/operations/TransactionOperation.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction.operations; + +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * An update operation that is part of a transaction. + * + * @author Arjohn Kampman + * @author Leo Sauermann + */ +public interface TransactionOperation { + + /** + * Executes this operation on the supplied connection. + * + * @param con + * The connection the operation should be performed on. + * @throws RepositoryException + * If such an exception is thrown by the connection while executing + * the operation. + */ + public abstract void execute(RepositoryConnection con) + throws RepositoryException; +} diff --git a/core/http/protocol/src/test/java/org/eclipse/rdf4j/http/protocol/ProtocolTest.java b/core/http/protocol/src/test/java/org/eclipse/rdf4j/http/protocol/ProtocolTest.java new file mode 100644 index 00000000000..688731de316 --- /dev/null +++ b/core/http/protocol/src/test/java/org/eclipse/rdf4j/http/protocol/ProtocolTest.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.http.protocol; + +import static org.eclipse.rdf4j.http.protocol.Protocol.CONFIG; +import static org.eclipse.rdf4j.http.protocol.Protocol.CONTEXTS; +import static org.eclipse.rdf4j.http.protocol.Protocol.NAMESPACES; +import static org.eclipse.rdf4j.http.protocol.Protocol.PROTOCOL; +import static org.eclipse.rdf4j.http.protocol.Protocol.REPOSITORIES; +import static org.eclipse.rdf4j.http.protocol.Protocol.getConfigLocation; +import static org.eclipse.rdf4j.http.protocol.Protocol.getContextsLocation; +import static org.eclipse.rdf4j.http.protocol.Protocol.getNamespacesLocation; +import static org.eclipse.rdf4j.http.protocol.Protocol.getProtocolLocation; +import static org.eclipse.rdf4j.http.protocol.Protocol.getRepositoriesLocation; +import static org.eclipse.rdf4j.http.protocol.Protocol.getRepositoryID; +import static org.eclipse.rdf4j.http.protocol.Protocol.getRepositoryLocation; +import static org.eclipse.rdf4j.http.protocol.Protocol.getServerLocation; +import static org.junit.Assert.assertEquals; + +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.junit.Test; + +public class ProtocolTest { + + private static final String serverLocation = "http://localhost/openrdf"; + + private static final String repositoryID = "mem-rdf"; + + private static final String repositoryLocation = serverLocation + "/" + REPOSITORIES + "/" + repositoryID; + + @Test + public void testGetProtocolLocation() { + String result = getProtocolLocation(serverLocation); + assertEquals(result, serverLocation + "/" + PROTOCOL); + } + + @Test + public void testGetConfigLocation() { + String result = getConfigLocation(serverLocation); + assertEquals(result, serverLocation + "/" + CONFIG); + } + + @Test + public void testGetRepositoriesLocation() { + String result = getRepositoriesLocation(serverLocation); + assertEquals(result, serverLocation + "/" + REPOSITORIES); + } + + @Test + public void testGetServerLocation() { + String repositoryLocation = getRepositoryLocation(serverLocation, repositoryID); + + String result = getServerLocation(repositoryLocation); + assertEquals(serverLocation, result); + } + + + @Test + public void testGetRepositoryID() { + String repositoryLocation = getRepositoryLocation(serverLocation, repositoryID); + + String result = getRepositoryID(repositoryLocation); + assertEquals(repositoryID, result); + } + + @Test + public void testGetRepositoryLocation() { + String result = getRepositoryLocation(serverLocation, repositoryID); + assertEquals(result, repositoryLocation); + } + + @Test + public void testGetContextsLocation() { + String result = getContextsLocation(repositoryLocation); + assertEquals(result, repositoryLocation + "/" + CONTEXTS); + } + + @Test + public void testGetNamespacesLocation() { + String result = getNamespacesLocation(repositoryLocation); + assertEquals(result, repositoryLocation + "/" + NAMESPACES); + } + + @Test + public void testEncodeValueRoundtrip() { + final ValueFactory vf = SimpleValueFactory.getInstance(); + IRI uri = vf.createIRI("http://example.org/foo-bar"); + + String encodedUri = Protocol.encodeValue(uri); + IRI decodedUri = (IRI)Protocol.decodeValue(encodedUri, vf); + + assertEquals(uri, decodedUri); + + BNode bnode = vf.createBNode("foo-bar-1"); + String encodedBnode = Protocol.encodeValue(bnode); + + BNode decodedNode = (BNode)Protocol.decodeValue(encodedBnode, vf); + assertEquals(bnode, decodedNode); + + } +} diff --git a/core/http/protocol/src/test/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionReaderTest.java b/core/http/protocol/src/test/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionReaderTest.java new file mode 100644 index 00000000000..3e780a44ff1 --- /dev/null +++ b/core/http/protocol/src/test/java/org/eclipse/rdf4j/http/protocol/transaction/TransactionReaderTest.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.protocol.transaction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.rdf4j.http.protocol.transaction.TransactionReader; +import org.eclipse.rdf4j.http.protocol.transaction.TransactionWriter; +import org.eclipse.rdf4j.http.protocol.transaction.operations.AddStatementOperation; +import org.eclipse.rdf4j.http.protocol.transaction.operations.TransactionOperation; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.junit.Test; + +/** + * @author jeen + */ +public class TransactionReaderTest { + + private static final ValueFactory vf = SimpleValueFactory.getInstance(); + + private static final IRI bob = vf.createIRI("http://example.org/bob"); + + private static final IRI alice = vf.createIRI("http://example.org/alice"); + + private static final IRI knows = vf.createIRI("http://example.org/knows"); + + private static final char ux0005 = 0x0005; + + private static final Literal controlCharText = vf.createLiteral("foobar." + ux0005 + " foo."); + + private static final IRI context1 = vf.createIRI("http://example.org/context1"); + + private static final IRI context2 = vf.createIRI("http://example.org/context2"); + + @Test + public void testRoundtrip() + throws Exception + { + + AddStatementOperation operation = new AddStatementOperation(bob, knows, alice, context1, context2); + + List txn = new ArrayList(); + txn.add(operation); + + ByteArrayOutputStream out = new ByteArrayOutputStream(4096); + TransactionWriter w = new TransactionWriter(); + w.serialize(txn, out); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + TransactionReader r = new TransactionReader(); + Collection parsedTxn = r.parse(in); + + assertNotNull(parsedTxn); + + for (TransactionOperation op : parsedTxn) { + assertTrue(op instanceof AddStatementOperation); + AddStatementOperation addOp = (AddStatementOperation)op; + + Resource[] contexts = addOp.getContexts(); + + assertEquals(2, contexts.length); + assertTrue(contexts[0].equals(context1) || contexts[1].equals(context1)); + assertTrue(contexts[0].equals(context2) || contexts[1].equals(context2)); + } + + } + + @Test + public void testControlCharHandling() + throws Exception + { + AddStatementOperation operation = new AddStatementOperation(bob, knows, controlCharText); + + List txn = new ArrayList(); + txn.add(operation); + + ByteArrayOutputStream out = new ByteArrayOutputStream(4096); + TransactionWriter w = new TransactionWriter(); + w.serialize(txn, out); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + TransactionReader r = new TransactionReader(); + Collection parsedTxn = r.parse(in); + + assertNotNull(parsedTxn); + + for (TransactionOperation op : parsedTxn) { + assertTrue(op instanceof AddStatementOperation); + AddStatementOperation addOp = (AddStatementOperation)op; + assertTrue(addOp.getObject().equals(controlCharText)); + } + + } + +} diff --git a/core/http/server-spring/pom.xml b/core/http/server-spring/pom.xml new file mode 100644 index 00000000000..f77d308e0e0 --- /dev/null +++ b/core/http/server-spring/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-http + 4.1.0-SNAPSHOT + + + rdf4j-http-server-spring + + RDF4J: HTTP server - core + HTTP server implementing a REST-style protocol + + + + ${project.groupId} + rdf4j-runtime + ${project.version} + + + ${project.groupId} + rdf4j-config + ${project.version} + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + javax.servlet + servlet-api + + + javax.servlet.jsp + jsp-api + + + javax.servlet + jstl + + + taglibs + standard + + + + org.springframework + spring-aop + runtime + + + org.springframework + spring-webmvc + + + + cglib + cglib + + + + org.slf4j + slf4j-api + + + + junit + junit + + + com.google.guava + guava + + + + diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/CommonValuesHandlerInterceptor.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/CommonValuesHandlerInterceptor.java new file mode 100644 index 00000000000..53b36b46332 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/CommonValuesHandlerInterceptor.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp; + +import java.util.Calendar; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +/** + * Interceptor that inserts some commonly used values into the model. + * + * The inserted values are: + * + * - path, equal to request.getContextPath() (e.g. /context) + * - basePath, equal to the fully qualified context path (e.g. http://www.example.com/context/) + * - currentYear, equal to the current year + * + * @author Herko ter Horst + */ +public class CommonValuesHandlerInterceptor implements HandlerInterceptor { + + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + // nop + } + + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav) { + mav.addObject("path", request.getContextPath()); + mav.addObject("basePath", request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + + request.getContextPath() + "/"); + mav.addObject("currentYear", Calendar.getInstance().get(Calendar.YEAR)); + } + + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + return true; + } + +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/Message.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/Message.java new file mode 100644 index 00000000000..78b4789c051 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/Message.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp; + +/** + * + * @author Herko ter Horst + */ +public class Message { + + public static final String ATTRIBUTE_KEY = "message"; + + public static enum Type { + ERROR, + WARN, + INFO + }; + + private Type type; + + private String i18n; + + public Message(Type type, String i18n) { + this.type = type; + this.i18n = i18n; + } + + /** + * @return Returns the type. + */ + public Type getType() { + return type; + } + + /** + * @return Returns the i18n. + */ + public String getI18n() { + return i18n; + } + +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/MessageHandlerInterceptor.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/MessageHandlerInterceptor.java new file mode 100644 index 00000000000..4622652735c --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/MessageHandlerInterceptor.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.view.RedirectView; + +/** + * Interceptor that inserts some commonly used values into the model. + * + * The inserted values are: + * - path, equal to request.getContextPath() (e.g. /context) - basePath, equal + * to the fully qualified context path (e.g. http://www.example.com/context/) - + * currentYear, equal to the current year + * + * @author Herko ter Horst + */ +public class MessageHandlerInterceptor implements HandlerInterceptor { + + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, + Exception ex) + { + // nop + } + + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView mav) + { + HttpSession session = request.getSession(); + + if (session != null) { + Message message = (Message)session.getAttribute(Message.ATTRIBUTE_KEY); + if (message != null && !mav.getModelMap().containsKey(Message.ATTRIBUTE_KEY)) { + mav.addObject(Message.ATTRIBUTE_KEY, message); + } + + boolean shouldRemove = true; + if (mav.hasView() && mav.getView() instanceof RedirectView) { + shouldRemove = false; + } + if (mav.getViewName() != null && mav.getViewName().startsWith("redirect:")) { + shouldRemove = false; + } + + if (shouldRemove) { + session.removeAttribute(Message.ATTRIBUTE_KEY); + } + } + } + + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception + { + return true; + } + +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/filters/PathFilter.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/filters/PathFilter.java new file mode 100644 index 00000000000..8ecf7b6b1f0 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/filters/PathFilter.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.filters; + +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +/** + * + * @author Herko ter Horst + */ +public class PathFilter implements Filter { + + public void init(FilterConfig filterConf) + throws ServletException + { + // do nothing + } + + public void destroy() { + // do nothing + } + + public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) + throws IOException, ServletException + { + if (req instanceof HttpServletRequest) { + HttpServletRequest request = (HttpServletRequest)req; + HttpServletResponse response = (HttpServletResponse)res; + String path = request.getContextPath(); + + PrintWriter out = response.getWriter(); + CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse)response); + filterChain.doFilter(request, wrapper); + CharArrayWriter caw = new CharArrayWriter(); + caw.write(wrapper.toString().replace("${path}", path)); + String result = caw.toString(); + response.setContentLength(result.length()); + out.write(result); + } + } + + private static class CharResponseWrapper extends HttpServletResponseWrapper { + + private CharArrayWriter output; + + @Override + public String toString() { + return output.toString(); + } + + public CharResponseWrapper(HttpServletResponse response) { + super(response); + output = new CharArrayWriter(); + } + + @Override + public PrintWriter getWriter() { + return new PrintWriter(output); + } + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/AbstractNavigationNode.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/AbstractNavigationNode.java new file mode 100644 index 00000000000..6b1b6f3a06c --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/AbstractNavigationNode.java @@ -0,0 +1,268 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation; + +/** + * Base implementation of the NavigationNode interface. + * + * @author Herko ter Horst + */ +public abstract class AbstractNavigationNode implements NavigationNode { + + private String id; + + private boolean hidden; + + private boolean enabled; + + private NavigationNode parent; + + protected String path; + + protected String icon; + + protected String i18n; + + protected String viewSuffix; + + public AbstractNavigationNode(String id) { + setId(id); + setEnabled(true); + } + + public String getId() { + return id; + } + + void setId(String id) { + this.id = id; + } + + public boolean isHidden() { + return hidden; + } + + public void setHidden(boolean hidden) { + this.hidden = hidden; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public NavigationNode getParent() { + return parent; + } + + public void setParent(NavigationNode parent) { + this.parent = parent; + } + + public boolean isParent(NavigationNode node) { + boolean result = false; + + if (node != null && node != this) { + if (node.getParent() == this) { + result = true; + } else if (node.getParent() != null) { + result = isParent(node.getParent()); + } + } + + return result; + } + + public String getPathPrefix() { + StringBuilder result = new StringBuilder(); + if (getParent() != null) { + if (getParent().getPathPrefix() != null) { + result.append(getParent().getPathPrefix()); + } + if (getParent().getId().length() > 0) { + result.append(getParent().getId()); + result.append(getPathSeparator()); + } + } + return result.toString(); + } + + public String getPathSeparator() { + String result = null; + if (getParent() != null) { + result = getParent().getPathSeparator(); + } + return result; + } + + public String getPath() { + if (path == null) { + StringBuilder result = new StringBuilder(); + result.append(getPathPrefix()); + result.append(getId()); + setPath(result.toString()); + } + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getIconPrefix() { + StringBuilder result = new StringBuilder(); + if (getParent() != null) { + if (getParent().getIconPrefix() != null) { + result.append(getParent().getIconPrefix()); + } + if (getParent().getId().length() > 0) { + result.append(getParent().getId()); + result.append(getIconSeparator()); + } + } + return result.toString(); + } + + public String getIconSeparator() { + String result = null; + if (getParent() != null) { + result = getParent().getIconSeparator(); + } + return result; + } + + public String getIconSuffix() { + String result = null; + if (getParent() != null) { + result = getParent().getIconSuffix(); + } + return result; + } + + public String getIcon() { + if (icon == null) { + StringBuilder result = new StringBuilder(); + result.append(getIconPrefix()); + result.append(getId()); + result.append(getIconSuffix()); + setIcon(result.toString()); + } + + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getI18nPrefix() { + StringBuilder result = new StringBuilder(); + if (getParent() != null) { + if (getParent().getI18nPrefix() != null) { + result.append(getParent().getI18nPrefix()); + } + if (getParent().getId().length() > 0) { + result.append(getParent().getId()); + result.append(getI18nSeparator()); + } + } + return result.toString(); + } + + public String getI18nSeparator() { + String result = null; + if (getParent() != null) { + result = getParent().getI18nSeparator(); + } + return result; + } + + public String getI18nSuffix() { + String result = null; + if (getParent() != null) { + result = getParent().getI18nSuffix(); + } + return result; + } + + public String getI18n() { + if (i18n == null) { + StringBuilder result = new StringBuilder(); + result.append(getI18nPrefix()); + result.append(getId()); + result.append(getI18nSuffix()); + setI18n(result.toString()); + } + return i18n; + } + + public void setI18n(String i18n) { + this.i18n = i18n; + } + + public String getViewSuffix() { + if (viewSuffix == null) { + if (getParent() != null) { + setViewSuffix(getParent().getViewSuffix()); + } + } + return viewSuffix; + } + + public void setViewSuffix(String viewSuffix) { + this.viewSuffix = viewSuffix; + } + + public int getDepth() { + int result = 0; + + if (getParent() != null) { + result = getParent().getDepth() + 1; + } + + return result; + } + + public boolean equals(Object other) { + boolean result = this == other; + if (!result && other instanceof NavigationNode + && getClass().equals(other.getClass())) { + NavigationNode otherNode = (NavigationNode) other; + result = getId().equals(otherNode.getId()); + if (result + && !(getParent() == null && otherNode.getParent() == null)) { + if (getParent() != null && otherNode.getParent() != null) { + result = getParent().equals(otherNode.getParent()); + } else { + result = false; + } + } + } + return result; + } + + public int hashCode() { + int result = getId().hashCode(); + if (getParent() != null) { + result += 31 * getParent().hashCode(); + } + return result; + } + + protected void copyCommonAttributes(NavigationNode node) { + node.setEnabled(isEnabled()); + node.setHidden(isHidden()); + node.setI18n(getI18n()); + node.setIcon(getIcon()); + node.setPath(getPath()); + node.setViewSuffix(getViewSuffix()); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/Group.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/Group.java new file mode 100644 index 00000000000..7f49250609a --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/Group.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Group represents a logical group of views in a NavigationModel. + * + * @author Herko ter Horst + * + */ +public class Group extends AbstractNavigationNode { + + protected Map groups; + + protected Map views; + + protected Map viewNames; + + /** + * Construct a new group with the specified ID. + * + * @param id + * the ID of the group + */ + public Group(String id) { + super(id); + groups = new LinkedHashMap(); + views = new LinkedHashMap(); + viewNames = new LinkedHashMap(); + } + + /** + * Add a group to this group. The group becomes a sub-group of this group. + * + * @param group + * the group to add + */ + public void addGroup(Group group) { + group.setParent(this); + groups.put(group.getId(), group); + } + + /** + * Get the sub-group with the specified ID. + * + * @param id + * the ID of the sub-group + * @return the sub-group with the specified ID, or null if this group + * doesn't contain a sub-group with that ID + */ + public Group getGroup(String id) { + return groups.get(id); + } + + /** + * Get the list of sub-groups + * + * @return the list of sub-groups + */ + public List getGroups() { + return new ArrayList(groups.values()); + } + + /** + * Add a view to this group. + * + * @param view + * the view to add + */ + public void addView(View view) { + view.setParent(this); + views.put(view.getId(), view); + viewNames.put(view.getId()+view.getViewSuffix(), view); + } + + public View getView(String viewId) { + return views.get(viewId); + } + + /** + * Get the view with the specified name. + * + * @param viewName + * the name of the view (ID+suffix) + * @return the view with the specified name, or null if this group doesn't + * contain a view with that name + */ + public View getViewByName(String viewName) { + return viewNames.get(viewName); + } + + protected View findViewInternal(String viewName) { + View result = null; + + int indexOfSeparator = viewName.indexOf(getPathSeparator()); + if (indexOfSeparator > 0) { + String groupId = viewName.substring(0, indexOfSeparator); + Group subGroup = getGroup(groupId); + result = subGroup.findViewInternal(viewName + .substring(indexOfSeparator + 1)); + } else { + result = getViewByName(viewName); + } + + return result; + } + + /** + * Get the list of views. + * + * @return the list of views + */ + public List getViews() { + return new ArrayList(views.values()); + } + + public Object clone() { + Group result = new Group(getId()); + copyCommonAttributes(result); + copyGroupsAndViews(result); + return result; + } + + protected void copyGroupsAndViews(Group group) { + for (Group subGroup : getGroups()) { + Group clonedGroup = (Group) subGroup.clone(); + group.addGroup(clonedGroup); + } + for (View view : getViews()) { + View clonedView = (View) view.clone(); + group.addView(clonedView); + } + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationHandlerInterceptor.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationHandlerInterceptor.java new file mode 100644 index 00000000000..936cd998be9 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationHandlerInterceptor.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.eclipse.rdf4j.common.webapp.navigation.NavigationModel; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +/** + * Interceptor that inserts the navigation model for the current Spring view + * into the model. + * + * @author Herko ter Horst + */ +public class NavigationHandlerInterceptor implements HandlerInterceptor { + + private NavigationModel navigationModel; + + public NavigationModel getNavigationModel() { + return navigationModel; + } + + public void setNavigationModel(NavigationModel navigationModel) { + this.navigationModel = navigationModel; + } + + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, + Exception ex) + { + // nop + } + + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView mav) + { + NavigationModel sessionNavigationModel = (NavigationModel)request.getSession().getAttribute( + NavigationModel.NAVIGATION_MODEL_KEY); + if (sessionNavigationModel == null) { + sessionNavigationModel = navigationModel; + } + + if (mav != null && sessionNavigationModel != null) { + mav.addObject("view", sessionNavigationModel.findView(request.getRequestURI().substring( + request.getContextPath().length()))); + } + } + + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + HttpSession session = request.getSession(true); + if (session.getAttribute(NavigationModel.NAVIGATION_MODEL_KEY) == null) { + session.setAttribute(NavigationModel.NAVIGATION_MODEL_KEY, getNavigationModel().clone()); + } + + return true; + } + +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationModel.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationModel.java new file mode 100644 index 00000000000..5a626596070 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationModel.java @@ -0,0 +1,252 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.common.io.ResourceUtil; + +/** + * NavigationModel represents the navigation structure of a web application. A + * model consists of groups and views. + * + * @author Herko ter Horst + */ +public class NavigationModel extends Group { + + public static final String NAVIGATION_MODEL_KEY = "navigation-model"; + + public static final String DEFAULT_PATH_PREFIX = "/"; + + public static final String DEFAULT_PATH_SEPARATOR = "/"; + + public static final String DEFAULT_VIEW_SUFFIX = ".view"; + + public static final String DEFAULT_ICON_PREFIX = "/images/icons/"; + + public static final String DEFAULT_ICON_SEPARATOR = "_"; + + public static final String DEFAULT_ICON_SUFFIX = ".png"; + + public static final String DEFAULT_I18N_PREFIX = ""; + + public static final String DEFAULT_I18N_SEPARATOR = "."; + + public static final String DEFAULT_I18N_SUFFIX = ".title"; + + private List navigationModelLocations = new ArrayList(); + + private String pathPrefix; + + private String pathSeparator; + + private String iconPrefix; + + private String iconSeparator; + + private String iconSuffix; + + private String i18nPrefix; + + private String i18nSeparator; + + private String i18nSuffix; + + /** + * Construct a new, anonymous, empty NavigationModel + */ + public NavigationModel() { + super(null); + } + + /** + * Construct a new emtpy NavigationModel with the specified ID. + * + * @param id + * the ID of the NavigationModel + */ + public NavigationModel(String id) { + super(id); + } + + public String getId() { + return ""; + } + + public String getPathPrefix() { + if (pathPrefix == null) { + setPathPrefix(DEFAULT_PATH_PREFIX); + } + return pathPrefix; + } + + public void setPathPrefix(String pathPrefix) { + this.pathPrefix = pathPrefix; + } + + @Override + public String getPathSeparator() { + if (pathSeparator == null) { + setPathSeparator(DEFAULT_PATH_SEPARATOR); + } + return pathSeparator; + } + + public void setPathSeparator(String pathSeparator) { + this.pathSeparator = pathSeparator; + } + + @Override + public String getIconPrefix() { + if (iconPrefix == null) { + setIconPrefix(DEFAULT_ICON_PREFIX); + } + return iconPrefix; + } + + public void setIconPrefix(String iconPrefix) { + this.iconPrefix = iconPrefix; + } + + @Override + public String getIconSeparator() { + if (iconSeparator == null) { + setIconSeparator(DEFAULT_ICON_SEPARATOR); + } + return iconSeparator; + } + + public void setIconSeparator(String iconSeparator) { + this.iconSeparator = iconSeparator; + } + + @Override + public String getIconSuffix() { + if (iconSuffix == null) { + setIconSuffix(DEFAULT_ICON_SUFFIX); + } + return iconSuffix; + } + + public void setIconSuffix(String iconSuffix) { + this.iconSuffix = iconSuffix; + } + + public String getI18nPrefix() { + if (i18nPrefix == null) { + setI18nPrefix(DEFAULT_I18N_PREFIX); + } + return i18nPrefix; + } + + public void setI18nPrefix(String i18nPrefix) { + this.i18nPrefix = i18nPrefix; + } + + @Override + public String getI18nSeparator() { + if (i18nSeparator == null) { + setI18nSeparator(DEFAULT_I18N_SEPARATOR); + } + return i18nSeparator; + } + + public void setI18nSeparator(String i18nSeparator) { + this.i18nSeparator = i18nSeparator; + } + + @Override + public String getI18nSuffix() { + if (i18nSuffix == null) { + setI18nSuffix(DEFAULT_I18N_SUFFIX); + } + return i18nSuffix; + } + + public void setI18nSuffix(String i18nSuffix) { + this.i18nSuffix = i18nSuffix; + } + + public String getViewSuffix() { + if (viewSuffix == null) { + setViewSuffix(DEFAULT_VIEW_SUFFIX); + } + return viewSuffix; + } + + /** + * Find the view with the specified name in the NavigationModel. + * + * @param viewName + * the name of the view, specified as a /-separated hierarchy of + * groups, where the part after the last / is interpreted as the name + * of the view itself. + * @return the view, or null if no view matching the specified name could be + * found + */ + public View findView(String viewName) { + View result = null; + + int prefixLength = getPathPrefix().length(); + viewName = viewName.substring(prefixLength); + result = findViewInternal(viewName); + + return result; + } + + /** + * Add another NavigationModel to this one. This is done by adding all groups + * and view from the other model to this one. + * + * @param other + * the model to add to this one. + */ + public void addModel(NavigationModel other) { + for (Group group : other.getGroups()) { + addGroup(group); + } + for (View view : other.getViews()) { + addView(view); + } + } + + /** + * Set the locations of the navigation model resources to be used in the + * construction of this model. Calling this method will cause this + * NavigationModel to be initialized. + * + * @param navigationModelLocations + * a list of resource names + */ + public void setNavigationModels(List navigationModelLocations) { + this.navigationModelLocations = navigationModelLocations; + createNavigationModel(); + } + + private void createNavigationModel() { + boolean first = true; + for (String navigationModelLocation : navigationModelLocations) { + NavigationXmlParser parser = new NavigationXmlParser(); + if (first) { + parser.parseInto(this, ResourceUtil.getURL(navigationModelLocation)); + first = false; + } + else { + addModel(parser.parse(ResourceUtil.getURL(navigationModelLocation))); + } + } + } + + public Object clone() { + NavigationModel result = new NavigationModel(getId()); + copyCommonAttributes(result); + copyGroupsAndViews(result); + return result; + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationNode.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationNode.java new file mode 100644 index 00000000000..00d789c32c8 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationNode.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation; + +/** + * NavigationNode represents a node in a NavigationModel. + * + * @author Herko ter Horst + */ +public interface NavigationNode extends Cloneable { + + /** + * Get the ID of the node. + * + * @return the ID of the node + */ + public String getId(); + + /** + * Is the node hidden? + * + * @return true if the node is hidden, false otherwise + */ + public boolean isHidden(); + + /** + * Set the hidden status of the node. + * + * @param hidden + * the new hidden status of the node + */ + public void setHidden(boolean hidden); + + /** + * Is the node enabled/active? + * + * @return true if the node is enabled, false otherwise + */ + public boolean isEnabled(); + + /** + * Set the enabled status of the node. + * + * @param enabled + * the new enabled status of the node + */ + public void setEnabled(boolean enabled); + + /** + * Get the parent node of this node. + * + * @return the parent node of this node, or null if this node is the root + * NavigationModel + */ + public NavigationNode getParent(); + + /** + * Set the parent of this node. + * + * @param parent + * the new parent of this node + */ + public void setParent(NavigationNode parent); + + /** + * Is this node a parent of the specified node? + * + * @param node + * the node to check + * @return true if this node is a direct or indirect parent of the specified + * node, false otherwise + */ + public boolean isParent(NavigationNode node); + + /** + * Get the depth of this node in the hierarchy. The root NavigationModel has + * depth 0, all other nodes have a depth equal to the depth of their parent + + * 1. + * + * @return the depth of the node in the hierarhcy + */ + public int getDepth(); + + public String getPathPrefix(); + + public String getPathSeparator(); + + public String getPath(); + + public void setPath(String path); + + public String getIconPrefix(); + + public String getIconSeparator(); + + public String getIconSuffix(); + + public String getIcon(); + + public void setIcon(String icon); + + public String getI18nPrefix(); + + public String getI18nSeparator(); + + public String getI18nSuffix(); + + public String getI18n(); + + public void setI18n(String i18n); + + public String getViewSuffix(); + + public void setViewSuffix(String suffix); +} \ No newline at end of file diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationNodeBase.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationNodeBase.java new file mode 100644 index 00000000000..59d617b24f7 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationNodeBase.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation; + +/** + * @deprecated since 4.0. Use {@link AbstractNavigationNode} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class NavigationNodeBase extends AbstractNavigationNode { + + public NavigationNodeBase(String id) { + super(id); + } + +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationXmlParser.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationXmlParser.java new file mode 100644 index 00000000000..94c03405a35 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationXmlParser.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation; + +import java.io.IOException; +import java.net.URL; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.eclipse.rdf4j.common.xml.DocumentUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * XPath-based parser for NavigationModel configuration files. + * + * @author Herko ter Horst + */ +public class NavigationXmlParser { + + private XPath xpath = XPathFactory.newInstance().newXPath(); + + public NavigationModel parse(URL navigationXml) { + NavigationModel result = new NavigationModel(); + parseInto(result, navigationXml); + return result; + } + + public void parseInto(NavigationModel result, URL navigationXml) { + try { + Document document = DocumentUtil.getDocument(navigationXml); + Node rootNode = (Node) xpath.evaluate("/navigation", document, + XPathConstants.NODE); + fillModel(result, rootNode); + } catch (IOException e) { + e.printStackTrace(); + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + private void fillModel(NavigationModel result, Node modelNode) + throws XPathExpressionException { + String id = xpath.evaluate("@id", modelNode); + result.setId(id); + + String pathPrefix = xpath.evaluate("path-prefix", modelNode); + if (!"".equals(pathPrefix)) { + result.setPathPrefix(pathPrefix); + } + String pathSeparator = xpath.evaluate("path-separator", modelNode); + if (!"".equals(pathSeparator)) { + result.setPathSeparator(pathSeparator); + } + + String iconPrefix = xpath.evaluate("icon-prefix", modelNode); + if (!"".equals(iconPrefix)) { + result.setIconPrefix(iconPrefix); + } + String iconSeparator = xpath.evaluate("icon-separator", modelNode); + if (!"".equals(iconSeparator)) { + result.setIconSeparator(iconSeparator); + } + String iconSuffix = xpath.evaluate("icon-suffix", modelNode); + if (!"".equals(iconSuffix)) { + result.setIconSuffix(iconSuffix); + } + + String i18nPrefix = xpath.evaluate("i18n-prefix", modelNode); + if (!"".equals(i18nPrefix)) { + result.setI18nPrefix(i18nPrefix); + } + String i18nSeparator = xpath.evaluate("i18n-separator", modelNode); + if (!"".equals(i18nSeparator)) { + result.setI18nSeparator(i18nSeparator); + } + String i18nSuffix = xpath.evaluate("i18n-suffix", modelNode); + if (!"".equals(i18nSuffix)) { + result.setI18nSuffix(i18nSuffix); + } + + setAttributes(result, modelNode); + + setGroupsAndViews(result, modelNode); + } + + private void setAttributes(NavigationNode navNode, Node xmlNode) + throws XPathExpressionException { + boolean hidden = getBooleanAttribute( + xpath.evaluate("@hidden", xmlNode), false); + navNode.setHidden(hidden); + + boolean enabled = getBooleanAttribute(xpath.evaluate("@enabled", + xmlNode), true); + navNode.setEnabled(enabled); + + String path = xpath.evaluate("path", xmlNode); + if (!"".equals(path)) { + navNode.setPath(path); + } + + String icon = xpath.evaluate("icon", xmlNode); + if (!"".equals(icon)) { + navNode.setIcon(icon); + } + + String i18n = xpath.evaluate("i18n", xmlNode); + if (!"".equals(i18n)) { + navNode.setI18n(i18n); + } + + String viewSuffix = xpath.evaluate("view-suffix", xmlNode); + if (!"".equals(viewSuffix)) { + navNode.setViewSuffix(viewSuffix); + } + } + + private void setGroupsAndViews(Group parent, Node xmlNode) + throws XPathExpressionException { + NodeList groupList = (NodeList) xpath.evaluate("group", xmlNode, + XPathConstants.NODESET); + int groupCount = groupList.getLength(); + for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) { + Node groupNode = groupList.item(groupIndex); + + Group group = new Group(xpath.evaluate("@id", groupNode)); + parent.addGroup(group); + setAttributes(group, groupNode); + setGroupsAndViews(group, groupNode); + } + + NodeList viewList = (NodeList) xpath.evaluate("view", xmlNode, + XPathConstants.NODESET); + int viewCount = viewList.getLength(); + for (int viewIndex = 0; viewIndex < viewCount; viewIndex++) { + Node viewNode = viewList.item(viewIndex); + + View view = new View(xpath.evaluate("@id", viewNode)); + parent.addView(view); + setAttributes(view, viewNode); + } + } + + private boolean getBooleanAttribute(String attrValue, boolean defaultValue) { + boolean result = defaultValue; + if (attrValue != null && !attrValue.trim().equals("")) { + result = attrValue.equalsIgnoreCase("true") + || attrValue.equalsIgnoreCase("yes") + || attrValue.equalsIgnoreCase("on"); + } + return result; + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/View.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/View.java new file mode 100644 index 00000000000..24112759503 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/View.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation; + +/** + * View represents a "leaf" in the navigation model, for example a page in a + * website. + * + * @author Herko ter Horst + */ +public class View extends AbstractNavigationNode { + + /** + * Construct a new view with the specified ID. + * + * @param id + * the ID of the view + */ + public View(String id) { + super(id); + } + + public String getPath() { + if(path == null) { + StringBuilder result = new StringBuilder(); + result.append(super.getPath()); + result.append(getViewSuffix()); + setPath(result.toString()); + } + return path; + } + + public Object clone() { + View result = new View(getId()); + copyCommonAttributes(result); + return result; + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/functions/NavigationFunctions.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/functions/NavigationFunctions.java new file mode 100644 index 00000000000..c8b44057732 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/navigation/functions/NavigationFunctions.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation.functions; + +import org.eclipse.rdf4j.common.webapp.navigation.NavigationNode; + +/** + * JSTL functions for navigation. + * + * @author Herko ter Horst + */ +public class NavigationFunctions { + /** + * Is the specified potential parent indeed a parent of the specified node. + * + * @param potentialParent + * the potential parent + * @param node + * the node + * @return true if the potential parent is part of the hierarchical string + * of parents for the specified node + */ + public static boolean isParent(NavigationNode potentialParent, + NavigationNode node) { + return potentialParent.isParent(node); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/SystemInfoController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/SystemInfoController.java new file mode 100644 index 00000000000..c0415b526f4 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/SystemInfoController.java @@ -0,0 +1,159 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.system; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.app.AppConfiguration; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.Controller; + +public class SystemInfoController implements Controller { + + private String view; + + private AppConfiguration config; + + private ServerInfo server; + + public SystemInfoController() { + server = new ServerInfo(); + } + + public String getView() { + return view; + } + + public void setView(String view) { + this.view = view; + } + + public ModelAndView handleRequest(HttpServletRequest request, + HttpServletResponse response) throws Exception { + ModelAndView result = new ModelAndView(); + result.setViewName(view); + + Map model = new HashMap(); + model.put("appConfig", config); + model.put("server", server); + model.put("memory", new MemoryInfo()); + model.put("javaProps", getJavaPropStrings()); + model.put("envVars", getEnvVarStrings()); + result.addAllObjects(model); + + return result; + } + + public AppConfiguration getConfig() { + return config; + } + + public void setConfig(AppConfiguration config) { + this.config = config; + } + + public static class ServerInfo { + private String os; + + private String java; + + private String user; + + public ServerInfo() { + os = System.getProperty("os.name") + " " + + System.getProperty("os.version") + " (" + + System.getProperty("os.arch") + ")"; + java = System.getProperty("java.vendor") + " " + + System.getProperty("java.vm.name") + " " + + System.getProperty("java.version"); + user = System.getProperty("user.name"); + } + + public String getOs() { + return os; + } + + public String getJava() { + return java; + } + + public String getUser() { + return user; + } + } + + public static class MemoryInfo { + + private int maximum; + private int used; + private float percentageInUse; + + public MemoryInfo() { + Runtime runtime = Runtime.getRuntime(); + long usedMemory = runtime.totalMemory() - runtime.freeMemory(); + long maxMemory = runtime.maxMemory(); + + // Memory usage (percentage) + percentageInUse = (float) ((float) usedMemory / (float) maxMemory); + + // Memory usage in MB + used = (int) (usedMemory / 1024 / 1024); + maximum = (int) (maxMemory / 1024 / 1024); + } + + public int getMaximum() { + return maximum; + } + + public int getUsed() { + return used; + } + + public float getPercentageInUse() { + return percentageInUse; + } + } + + private Map getJavaPropStrings() { + Properties sysProps = System.getProperties(); + ArrayList keyList = new ArrayList(sysProps.keySet()); + Collections.sort(keyList); + Map result = new LinkedHashMap(keyList.size()); + Iterator sysPropNames = keyList.iterator(); + while (sysPropNames.hasNext()) { + String name = sysPropNames.next(); + if (!name.startsWith("aduna")) { + result.put(name, sysProps.get(name)); + } + } + return result; + } + + private Map getEnvVarStrings() { + Map envProps = System.getenv(); + ArrayList keyList = new ArrayList(envProps.keySet()); + Collections.sort(keyList); + Map result = new LinkedHashMap(keyList.size()); + Iterator envPropNames = keyList.iterator(); + while (envPropNames.hasNext()) { + String name = envPropNames.next(); + result.put(name, envProps.get(name)); + } + return result; + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/SystemOverviewController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/SystemOverviewController.java new file mode 100644 index 00000000000..a1195c11c79 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/SystemOverviewController.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.system; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.app.AppConfiguration; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.Controller; + +public class SystemOverviewController implements Controller { + + private String view; + + private AppConfiguration config; + + private ServerInfo server; + + public SystemOverviewController() { + server = new ServerInfo(); + } + + public String getView() { + return view; + } + + public void setView(String view) { + this.view = view; + } + + public ModelAndView handleRequest(HttpServletRequest request, + HttpServletResponse response) throws Exception { + ModelAndView result = new ModelAndView(); + result.setViewName(view); + + Map model = new HashMap(); + model.put("appConfig", config); + model.put("server", server); + model.put("memory", new MemoryInfo()); + result.addAllObjects(model); + + return result; + } + + public AppConfiguration getConfig() { + return config; + } + + public void setConfig(AppConfiguration config) { + this.config = config; + } + + public static class ServerInfo { + private String os; + + private String java; + + private String user; + + public ServerInfo() { + os = System.getProperty("os.name") + " " + + System.getProperty("os.version") + " (" + + System.getProperty("os.arch") + ")"; + java = System.getProperty("java.vendor") + " " + + System.getProperty("java.vm.name") + " " + + System.getProperty("java.version"); + user = System.getProperty("user.name"); + } + + public String getOs() { + return os; + } + + public String getJava() { + return java; + } + + public String getUser() { + return user; + } + } + + public static class MemoryInfo { + + private int maximum; + private int used; + private float percentageInUse; + + public MemoryInfo() { + Runtime runtime = Runtime.getRuntime(); + long usedMemory = runtime.totalMemory() - runtime.freeMemory(); + long maxMemory = runtime.maxMemory(); + + // Memory usage (percentage) + percentageInUse = (float) ((float) usedMemory / (float) maxMemory); + + // Memory usage in MB + used = (int) (usedMemory / 1024 / 1024); + maximum = (int) (maxMemory / 1024 / 1024); + } + + public int getMaximum() { + return maximum; + } + + public int getUsed() { + return used; + } + + public float getPercentageInUse() { + return percentageInUse; + } + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/logging/LoggingOverviewController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/logging/LoggingOverviewController.java new file mode 100644 index 00000000000..4a404903c41 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/logging/LoggingOverviewController.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.system.logging; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.app.AppConfiguration; +import org.eclipse.rdf4j.common.logging.LogLevel; +import org.eclipse.rdf4j.common.logging.LogReader; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.Controller; + +public class LoggingOverviewController implements Controller { + + private AppConfiguration config; + + String viewName = "system/logging/overview"; + + String appenderName = null; + + String[] loglevels = { + "All", + LogLevel.ERROR.toString(), + LogLevel.WARN.toString(), + LogLevel.INFO.toString(), + LogLevel.DEBUG.toString() }; + + public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + int offset = getOffset(request); + int count = getCount(request); + Map model = new HashMap(); + LogReader logReader = getLogReader(offset, count, request); + model.put("logreader", logReader); + model.put("offset", new Integer(offset)); + model.put("count", new Integer(count)); + model.put("countsAvailable", Arrays.asList(new Integer[] { + Integer.valueOf(50), + Integer.valueOf(100), + Integer.valueOf(200), + Integer.valueOf(500) })); + if (logReader.supportsLevelFilter()) { + LogLevel level = logReader.getLevel(); + model.put("level", (level == null) ? "ALL" : level.toString()); + model.put("loglevels", Arrays.asList(this.loglevels)); + } + if (logReader.supportsThreadFilter()) { + String thread = logReader.getThread(); + model.put("thread", (thread == null) ? "ALL" : thread); + List l = new ArrayList(); + l.add("All"); + l.addAll(logReader.getThreadNames()); + model.put("threadnames", l); + } + if (logReader.supportsDateRanges()) { + Calendar cal = Calendar.getInstance(); + if (logReader.getStartDate() != null) { + cal.setTime(logReader.getStartDate()); + model.put("startDate", Boolean.TRUE); + } + else { + cal.setTime(logReader.getMinDate()); + model.put("startDate", Boolean.FALSE); + } + model.put("s_year", cal.get(Calendar.YEAR)); + model.put("s_month", cal.get(Calendar.MONTH)); + model.put("s_day", cal.get(Calendar.DAY_OF_MONTH)); + model.put("s_hour", cal.get(Calendar.HOUR_OF_DAY)); + model.put("s_min", cal.get(Calendar.MINUTE)); + cal = Calendar.getInstance(); + if (logReader.getEndDate() != null) { + cal.setTime(logReader.getEndDate()); + model.put("endDate", Boolean.TRUE); + } + else { + cal.setTime(logReader.getMaxDate()); + model.put("endDate", Boolean.FALSE); + } + model.put("e_year", cal.get(Calendar.YEAR)); + model.put("e_month", cal.get(Calendar.MONTH)); + model.put("e_day", cal.get(Calendar.DAY_OF_MONTH)); + model.put("e_hour", cal.get(Calendar.HOUR_OF_DAY)); + model.put("e_min", cal.get(Calendar.MINUTE)); + } + return new ModelAndView(this.viewName, model); + } + + public LogReader getLogReader(int offset, int count, HttpServletRequest request) { + LogReader logReader = (LogReader)request.getSession().getAttribute( + "logreader" + (appenderName != null ? "+" + appenderName : "")); + if (logReader == null) { + if (appenderName == null) { + logReader = config.getLogConfiguration().getDefaultLogReader(); + } + else { + logReader = config.getLogConfiguration().getLogReader(appenderName); + } + request.getSession().setAttribute("logreader" + (appenderName != null ? "+" + appenderName : ""), + logReader); + } + logReader.setOffset(offset); + logReader.setLimit(count); + if (logReader.supportsLevelFilter() && (request.getParameter("level") != null)) { + if (request.getParameter("level").equalsIgnoreCase("ALL")) { + logReader.setLevel(null); + } + else { + logReader.setLevel(LogLevel.valueOf(request.getParameter("level"))); + } + } + if (logReader.supportsThreadFilter() && (request.getParameter("thread") != null)) { + if (request.getParameter("thread").equalsIgnoreCase("ALL")) { + logReader.setThread(null); + } + else { + logReader.setThread(request.getParameter("thread")); + } + } + if (logReader.supportsDateRanges() && (request.getParameter("filterapplied") != null)) { + if (request.getParameter("applystartdate") != null) { + Calendar cal = Calendar.getInstance(); + cal.set(Integer.parseInt(request.getParameter("s_year")), + Integer.parseInt(request.getParameter("s_month")), + Integer.parseInt(request.getParameter("s_day")), + Integer.parseInt(request.getParameter("s_hour")), + Integer.parseInt(request.getParameter("s_min")), 0); + logReader.setStartDate(cal.getTime()); + } + else if (logReader.getStartDate() != null) { + logReader.setStartDate(null); + } + if (request.getParameter("applyenddate") != null) { + Calendar cal = Calendar.getInstance(); + cal.set(Integer.parseInt(request.getParameter("e_year")), + Integer.parseInt(request.getParameter("e_month")), + Integer.parseInt(request.getParameter("e_day")), + Integer.parseInt(request.getParameter("e_hour")), + Integer.parseInt(request.getParameter("e_min")), 59); + logReader.setEndDate(cal.getTime()); + } + else if (logReader.getEndDate() != null) { + logReader.setEndDate(null); + } + } + try { + logReader.init(); + } + catch (Exception e) { + throw new RuntimeException("Unable to initialize log reader.", e); + } + return logReader; + } + + public AppConfiguration getConfig() { + return config; + } + + public void setConfig(AppConfiguration config) { + this.config = config; + } + + private int getOffset(HttpServletRequest request) { + int result = 0; + + String offsetString = request.getParameter("offset"); + if (offsetString != null && !offsetString.equals("")) { + try { + result = Integer.parseInt(offsetString); + } + catch (NumberFormatException nfe) { + // ignore, result stays 0 + } + } + + return (result > 0) ? result : 0; + } + + private int getCount(HttpServletRequest request) { + int result = 50; // Default entries count + + String countString = request.getParameter("count"); + if (countString != null && !countString.equals("")) { + try { + result = Integer.parseInt(countString); + } + catch (NumberFormatException nfe) { + // ignore, result stays 50 + } + } + + return result; + } + + /** + * @return Returns the appenderName. + */ + public String getAppenderName() { + return appenderName; + } + + /** + * @param appenderName + * The appenderName to set. + */ + public void setAppenderName(String appenderName) { + this.appenderName = appenderName; + } + + public void setViewName(String viewName) { + this.viewName = viewName; + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/proxy/ProxySettingsController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/proxy/ProxySettingsController.java new file mode 100644 index 00000000000..3967aa40863 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/system/proxy/ProxySettingsController.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.system.proxy; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.app.net.ProxySettings; +import org.eclipse.rdf4j.common.webapp.util.HttpServerUtil; + +/** + * + * @author Herko ter Horst + */ +public class ProxySettingsController { + + // FIXME: fix this non-implementation + private ProxySettings PROXY_SETTINGS = null; + + private void setProxies(Map params, HttpServletResponse response) + throws IOException + { + boolean useProxies = HttpServerUtil.isTrue(HttpServerUtil.getPostDataParameter(params, "connection")); + + if (!useProxies) { + PROXY_SETTINGS.setProxiesEnabled(false); + } + else { + String httpProxyHost = HttpServerUtil.getPostDataParameter(params, "httpProxyHost"); + String httpProxyPort = HttpServerUtil.getPostDataParameter(params, "httpProxyPort"); + if (!HttpServerUtil.isEmpty(httpProxyHost)) { + PROXY_SETTINGS.setHttpProxyHost(httpProxyHost); + if (checkPort(httpProxyPort)) { + PROXY_SETTINGS.setHttpProxyPort(httpProxyPort); + } + } + + String httpsProxyHost = HttpServerUtil.getPostDataParameter(params, "httpsProxyHost"); + String httpsProxyPort = HttpServerUtil.getPostDataParameter(params, "httpsProxyPort"); + if (!HttpServerUtil.isEmpty(httpsProxyHost)) { + PROXY_SETTINGS.setHttpsProxyHost(httpsProxyHost); + if (checkPort(httpsProxyPort)) { + PROXY_SETTINGS.setHttpsProxyPort(httpsProxyPort); + } + } + + String ftpProxyHost = HttpServerUtil.getPostDataParameter(params, "ftpProxyHost"); + String ftpProxyPort = HttpServerUtil.getPostDataParameter(params, "ftpProxyPort"); + if (!HttpServerUtil.isEmpty(ftpProxyHost)) { + PROXY_SETTINGS.setFtpProxyHost(ftpProxyHost); + if (checkPort(ftpProxyPort)) { + PROXY_SETTINGS.setFtpProxyPort(ftpProxyPort); + } + } + + String socksProxyHost = HttpServerUtil.getPostDataParameter(params, "socksProxyHost"); + String socksProxyPort = HttpServerUtil.getPostDataParameter(params, "socksProxyPort"); + if (!HttpServerUtil.isEmpty(socksProxyHost)) { + PROXY_SETTINGS.setSocksProxyHost(socksProxyHost); + if (checkPort(socksProxyPort)) { + PROXY_SETTINGS.setHttpProxyPort(socksProxyPort); + } + } + + String proxyExceptions = HttpServerUtil.getPostDataParameter(params, "proxyExceptions"); + if (!HttpServerUtil.isEmpty(proxyExceptions)) { + PROXY_SETTINGS.setNonProxyHostsStarting(proxyExceptions); + } + + PROXY_SETTINGS.setProxiesEnabled(true); + } + + PROXY_SETTINGS.save(); + } + + private boolean checkPort(String proxyPort) + throws IOException + { + boolean result = false; + + int port = -1; + if (!HttpServerUtil.isEmpty(proxyPort)) { + try { + port = Integer.parseInt(proxyPort); + if (port > 0 || port < 65536) { + result = true; + } + } + catch (NumberFormatException nfe) { + result = false; + } + } + + return result; + } + +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/HeaderElement.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/HeaderElement.java new file mode 100644 index 00000000000..30bc7d10106 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/HeaderElement.java @@ -0,0 +1,184 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.rdf4j.common.text.StringUtil; + + +/** + * An element in an HTTP header value. An HTTP header element has a value and + * zero or more parameters consisting of a key and a value. An example header + * element is audio/*; q=0.2. + */ +public class HeaderElement { + + /*----------------* + * Static methods * + *----------------*/ + + public static HeaderElement parse(String encodedValue) { + HeaderElement result = new HeaderElement(); + + List tokens = HttpServerUtil.splitHeaderString(encodedValue, ';'); + + if (!tokens.isEmpty()) { + // First token is the value of the header element + String token = tokens.get(0); + + // Remove any whitespace and double quotes from the token + token = StringUtil.trimDoubleQuotes( token.trim() ); + + result.setValue(token); + + // Add parameters to the header element + for (int i = 1; i < tokens.size(); i++) { + token = (String)tokens.get(i); + + int splitIdx = token.indexOf('='); + + if (splitIdx == -1) { + // No value, only key + token = StringUtil.trimDoubleQuotes( token.trim() ); + + // Ignore empty parameters + if (token.length() > 0) { + result.addParameter(token); + } + } + else { + String key = token.substring(0, splitIdx).trim(); + String value = token.substring(splitIdx + 1).trim(); + value = StringUtil.trimDoubleQuotes(value); + result.addParameter(key, value); + } + } + } + + return result; + } + + /*-----------* + * Variables * + *-----------*/ + + private String value; + + private final List parameters; + + /*--------------* + * Constructors * + *--------------*/ + + public HeaderElement() { + this(""); + } + + public HeaderElement(String value) { + setValue(value); + parameters = new ArrayList(); + } + + /*---------* + * Methods * + *---------*/ + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public int getParameterCount() { + return parameters.size(); + } + + public Parameter getParameter(int i) { + return parameters.get(i); + } + + public Parameter getParameter(String key) { + for (int i = 0; i < parameters.size(); i++) { + Parameter param = parameters.get(i); + if (param.getKey().equals(key)) { + return param; + } + } + + return null; + } + + public String getParameterValue(String key) { + Parameter param = getParameter(key); + + if (param != null) { + return param.getValue(); + } + + return null; + } + + public List getParameters() { + return Collections.unmodifiableList(parameters); + } + + public void addParameter(String key) { + addParameter(key, null); + } + + public void addParameter(String key, String value) { + addParameter( new Parameter(key, value) ); + } + + public void addParameter(Parameter param) { + parameters.add(param); + } + + public Parameter removeParameter(int idx) { + return parameters.remove(idx); + } + + public boolean removeParameter(Parameter param) { + return parameters.remove(param); + } + + public boolean equals(Object obj) { + if (obj instanceof HeaderElement) { + HeaderElement other = (HeaderElement)obj; + + return + value.equals(other.getValue()) && + parameters.equals(other.getParameters()); + } + + return false; + } + + public int hashCode() { + return value.hashCode(); + } + + public String toString() { + StringBuilder sb = new StringBuilder(32); + sb.append(value); + + for (int i = 0; i < parameters.size(); i++) { + Parameter param = parameters.get(i); + + sb.append("; "); + sb.append(param.toString()); + } + + return sb.toString(); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/HttpServerUtil.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/HttpServerUtil.java new file mode 100644 index 00000000000..fe62a5c4eb9 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/HttpServerUtil.java @@ -0,0 +1,416 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.util; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +public class HttpServerUtil { + + /** + * Extracts the MIME type from the specified content type string. This method + * parses the content type string and returns just the MIME type, ignoring + * any parameters that are included. + * + * @param contentType + * A content type string, e.g. application/xml; charset=utf-8 + * . + * @return The MIME type part of the specified content type string, or + * null if the specified content type string was + * null. + */ + public static String getMIMEType(String contentType) { + if (contentType == null) { + return null; + } + + return HeaderElement.parse(contentType).getValue(); + } + + /** + * Selects from a set of MIME types, the MIME type that has the highest + * quality score when matched with the Accept headers in the supplied + * request. + * + * @param mimeTypes + * The set of available MIME types. + * @param request + * The request to match the MIME types against. + * @return The MIME type that best matches the types that the client finds + * acceptable, or null in case no acceptable MIME type could + * be found. + */ + public static String selectPreferredMIMEType(Iterator mimeTypes, HttpServletRequest request) { + List acceptElements = getHeaderElements(request, "Accept"); + + if (acceptElements.isEmpty()) { + // Client does not specify any requirements, return first MIME type + // from the list + if (mimeTypes.hasNext()) { + return mimeTypes.next(); + } + else { + return null; + } + } + + String result = null; + HeaderElement matchingAcceptType = null; + + double highestQuality = 0.0; + + while (mimeTypes.hasNext()) { + String mimeType = mimeTypes.next(); + HeaderElement acceptType = matchAcceptHeader(mimeType, acceptElements); + + if (acceptType != null) { + // quality defaults to 1.0 + double quality = 1.0; + + String qualityStr = acceptType.getParameterValue("q"); + if (qualityStr != null) { + try { + quality = Double.parseDouble(qualityStr); + } + catch (NumberFormatException e) { + // Illegal quality value, assume it has a different meaning + // and ignore it + } + } + + if (quality > highestQuality) { + result = mimeType; + matchingAcceptType = acceptType; + highestQuality = quality; + } + else if (quality == highestQuality) { + // found a match with equal quality preference. check if the + // accept type is more specific + // than the previous match. + if (isMoreSpecificType(acceptType, matchingAcceptType)) { + result = mimeType; + matchingAcceptType = acceptType; + } + } + } + } + + return result; + } + + /** + * Checks if the first supplied MIME type is more specific than the second + * supplied MIME type. + * + * @param leftMimeTypeElem + * @param rightMimeTypeElem + * @return true iff leftMimeTypeElem is a more specific MIME type spec than + * rightMimeTypeElem, false otherwise. + */ + private static boolean isMoreSpecificType(HeaderElement leftMimeTypeElem, HeaderElement rightMimeTypeElem) + { + + String[] leftMimeType = splitMIMEType(leftMimeTypeElem.getValue()); + String[] rightMimeType = splitMIMEType(rightMimeTypeElem.getValue()); + + if (rightMimeType != null) { + if (rightMimeType[1].equals("*")) { + if (!leftMimeType[1].equals("*")) { + return true; + } + } + if (rightMimeType[0].equals("*")) { + if (!leftMimeType[0].equals("*")) { + return true; + } + } + + return false; + } + else { + return true; + } + } + + private static String[] splitMIMEType(String mimeTypeString) { + int slashIdx = mimeTypeString.indexOf('/'); + if (slashIdx > 0) { + String type = mimeTypeString.substring(0, slashIdx); + String subType = mimeTypeString.substring(slashIdx + 1); + return new String[] { type, subType }; + } + else { + // invalid mime type + return null; + } + } + + /** + * Gets the elements of the request header with the specified name. + * + * @param request + * The request to get the header from. + * @param headerName + * The name of the header to get the elements of. + * @return A List of {@link HeaderElement} objects. + */ + public static List getHeaderElements(HttpServletRequest request, String headerName) { + List elemList = new ArrayList(8); + + @SuppressWarnings("unchecked") + Enumeration headerValues = request.getHeaders(headerName); + while (headerValues.hasMoreElements()) { + String value = headerValues.nextElement(); + + List subValues = splitHeaderString(value, ','); + + for (String subValue : subValues) { + // Ignore any empty header elements + subValue = subValue.trim(); + if (subValue.length() > 0) { + elemList.add(HeaderElement.parse(subValue)); + } + } + } + + return elemList; + } + + /** + * Splits the supplied string into sub parts using the specified splitChar as + * a separator, ignoring occurrences of this character inside quoted strings. + * + * @param s + * The header string to split into sub parts. + * @param splitChar + * The character to use as separator. + * @return A List of Strings. + */ + public static List splitHeaderString(String s, char splitChar) { + List result = new ArrayList(8); + + boolean parsingQuotedString = false; + int i, startIdx = 0; + + for (i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + if (c == splitChar && !parsingQuotedString) { + result.add(s.substring(startIdx, i)); + startIdx = i + 1; + } + else if (c == '"') { + parsingQuotedString = !parsingQuotedString; + } + } + + if (startIdx < s.length()) { + result.add(s.substring(startIdx)); + } + + return result; + } + + /** + * Tries to match the specified MIME type spec against the list of Accept + * header elements, returning the applicable header element if available. + * + * @param mimeTypeSpec + * The MIME type to determine the quality for, e.g. "text/plain" or + * "application/xml; charset=utf-8". + * @param acceptElements + * A List of {@link HeaderElement} objects. + * @return The Accept header element that matches the MIME type spec most + * closely, or null if no such header element could be + * found. + */ + public static HeaderElement matchAcceptHeader(String mimeTypeSpec, List acceptElements) { + HeaderElement mimeTypeElem = HeaderElement.parse(mimeTypeSpec); + + while (mimeTypeElem != null) { + for (HeaderElement acceptElem : acceptElements) { + if (matchesAcceptHeader(mimeTypeElem, acceptElem)) { + return acceptElem; + } + } + + // No match found, generalize the MIME type spec and try again + mimeTypeElem = generalizeMIMEType(mimeTypeElem); + } + + return null; + } + + private static boolean matchesAcceptHeader(HeaderElement mimeTypeElem, HeaderElement acceptElem) { + if (!mimeTypeElem.getValue().equals(acceptElem.getValue())) { + return false; + } + + // Values match, check parameters + if (mimeTypeElem.getParameterCount() > acceptElem.getParameterCount()) { + return false; + } + + for (int i = 0; i < mimeTypeElem.getParameterCount(); i++) { + if (!mimeTypeElem.getParameter(i).equals(acceptElem.getParameter(i))) { + return false; + } + } + + return true; + } + + /** + * Generalizes a MIME type element. The following steps are taken for + * generalization: + *
    + *
  • If the MIME type element has one or more parameters, the last + * parameter is removed. + *
  • Otherwise, if the MIME type element's subtype is not equal to '*' then + * it is set to this value. + *
  • Otherwise, if the MIME type element's type is not equal to '*' then it + * is set to this value. + *
  • Otherwise, the MIME type is equal to "*&slash;*" and cannot be + * generalized any further; null is returned. + *
+ *

+ * Example generalizations: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
inputresult
application/xml; charset=utf-8application/xml
application/xmlapplication/*
application/*&slash;*
&slash;*null
+ * + * @param mimeTypeElem + * The MIME type element that should be generalized. + * @return The generalized MIME type element, or null if it could + * not be generalized any further. + */ + private static HeaderElement generalizeMIMEType(HeaderElement mimeTypeElem) { + int parameterCount = mimeTypeElem.getParameterCount(); + if (parameterCount > 0) { + // remove last parameter + mimeTypeElem.removeParameter(parameterCount - 1); + } + else { + String mimeType = mimeTypeElem.getValue(); + + int slashIdx = mimeType.indexOf('/'); + if (slashIdx > 0) { + String type = mimeType.substring(0, slashIdx); + String subType = mimeType.substring(slashIdx + 1); + + if (!subType.equals("*")) { + // generalize subtype + mimeTypeElem.setValue(type + "/*"); + } + else if (!type.equals("*")) { + // generalize type + mimeTypeElem.setValue("*/*"); + } + else { + // Cannot generalize any further + mimeTypeElem = null; + } + } + else { + // invalid MIME type + mimeTypeElem = null; + } + } + + return mimeTypeElem; + } + + /** + * Gets the trimmed value of a request parameter as a String. + * + * @return The trimmed value, or null if the parameter does not exist. + */ + public static String getPostDataParameter(Map formData, String name) { + String result = null; + + try { + Object param = formData.get(name); + if (param instanceof String[]) { + String[] paramArray = (String[])param; + if (paramArray.length > 0) { + result = paramArray[0]; + } + } + else if (param instanceof String) { + result = (String)param; + } + + if (result != null) { + result = result.trim(); + } + } + catch (ClassCastException cce) { + // ignore, return null + } + + return result; + } + + /** + * @return true if the string is either null or equal to "" + */ + public static boolean isEmpty(String string) { + boolean result = false; + if (string == null || string.trim().equals("")) { + result = true; + } + return result; + } + + /** + * @return true if the string is !isEmpty and equal to "true" + */ + public static boolean isTrue(String string) { + boolean result = false; + if (!isEmpty(string) && (string.equalsIgnoreCase("true") || string.equalsIgnoreCase("on"))) { + result = true; + } + return result; + } + + /** + * @return true if the string is !isEmpty and equal to "false" + */ + public static boolean isFalse(String string) { + boolean result = false; + if (!isEmpty(string) && (string.equalsIgnoreCase("false") || string.equalsIgnoreCase("off"))) { + result = true; + } + return result; + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/Parameter.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/Parameter.java new file mode 100644 index 00000000000..682251c40af --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/util/Parameter.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.util; + + +/** + * A parameter consisting of a key and a value, which are both strings. + */ +public class Parameter { + + private final String key; + private final String value; + + public Parameter(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + public boolean equals(Object obj) { + if (obj instanceof Parameter) { + Parameter other = (Parameter)obj; + return + key.equals(other.getKey()) && + value.equals(other.getValue()); + } + + return false; + } + + public int hashCode() { + return key.hashCode(); + } + + public String toString() { + if (value == null) { + return key; + } + else { + return key + "=" + value; + } + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/EmptySuccessView.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/EmptySuccessView.java new file mode 100644 index 00000000000..f7280d03649 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/EmptySuccessView.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.views; + +import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.View; + +/** + * + * @author Herko ter Horst + */ +public class EmptySuccessView implements View { + + private static final EmptySuccessView INSTANCE = new EmptySuccessView(); + + public static EmptySuccessView getInstance() { + return INSTANCE; + } + + private EmptySuccessView() {} + + public String getContentType() { + return null; + } + + @SuppressWarnings("rawtypes") + public void render(Map model, HttpServletRequest request, HttpServletResponse response) + throws Exception + { + // Indicate success with a 204 NO CONTENT response + response.setStatus(SC_NO_CONTENT); + response.getOutputStream().close(); + } + +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/SimpleCustomResponseView.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/SimpleCustomResponseView.java new file mode 100644 index 00000000000..418703975bf --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/SimpleCustomResponseView.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.views; + +import java.io.InputStream; +import java.util.Map; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.io.IOUtil; +import org.springframework.web.servlet.View; + +/** + * + * @author Herko ter Horst + */ +public class SimpleCustomResponseView implements View { + + public static final String SC_KEY = "sc"; + + public static final String CONTENT_KEY = "content"; + + public static final String CONTENT_LENGTH_KEY = "contentLength"; + + public static final String CONTENT_TYPE_KEY = "contentType"; + + private static final int DEFAULT_SC = HttpServletResponse.SC_OK; + + private static final SimpleCustomResponseView INSTANCE = new SimpleCustomResponseView(); + + public static SimpleCustomResponseView getInstance() { + return INSTANCE; + } + + public String getContentType() { + return null; + } + + @SuppressWarnings("rawtypes") + public void render(Map model, HttpServletRequest request, HttpServletResponse response) + throws Exception + { + int sc = DEFAULT_SC; + if (model.containsKey(SC_KEY)) { + sc = (Integer)model.get(SC_KEY); + } + String contentType = (String)model.get(CONTENT_TYPE_KEY); + Integer contentLength = (Integer)model.get(CONTENT_LENGTH_KEY); + InputStream content = (InputStream)model.get(CONTENT_KEY); + + try { + response.setStatus(sc); + + ServletOutputStream out = response.getOutputStream(); + if (content != null) { + if (contentType != null) { + response.setContentType(contentType); + } + if (contentLength != null) { + response.setContentLength(contentLength); + } + IOUtil.transfer(content, out); + } + else { + response.setContentLength(0); + } + out.close(); + } + finally { + if (content != null) { + content.close(); + } + } + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/SimpleResponseView.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/SimpleResponseView.java new file mode 100644 index 00000000000..c392a46f531 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/common/webapp/views/SimpleResponseView.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.views; + +import java.io.OutputStream; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.View; + +/** + * @author Herko ter Horst + */ +public class SimpleResponseView implements View { + + public static final String SC_KEY = "sc"; + + public static final String CONTENT_KEY = "content"; + + private static final int DEFAULT_SC = HttpServletResponse.SC_OK; + + private static final String CONTENT_TYPE = "text/plain; charset=UTF-8"; + + public static final String CUSTOM_HEADERS_KEY = "headers"; + + private static final SimpleResponseView INSTANCE = new SimpleResponseView(); + + public static SimpleResponseView getInstance() { + return INSTANCE; + } + + private SimpleResponseView() { + } + + public String getContentType() { + return CONTENT_TYPE; + } + + @SuppressWarnings("rawtypes") + public void render(Map model, HttpServletRequest request, HttpServletResponse response) + throws Exception + { + Integer sc = (Integer)model.get(SC_KEY); + if (sc == null) { + sc = DEFAULT_SC; + } + response.setStatus(sc.intValue()); + + response.setContentType(CONTENT_TYPE); + + if (model.containsKey(CUSTOM_HEADERS_KEY)) { + Map customHeaders = (Map)model.get(CUSTOM_HEADERS_KEY); + if (customHeaders != null) { + for (String headerName : customHeaders.keySet()) { + response.setHeader(headerName, customHeaders.get(headerName)); + } + } + } + + OutputStream out = response.getOutputStream(); + + String content = (String)model.get(CONTENT_KEY); + if (content != null) { + byte[] contentBytes = content.getBytes("UTF-8"); + response.setContentLength(contentBytes.length); + out.write(contentBytes); + } + else { + response.setContentLength(0); + } + + out.close(); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ClientHTTPException.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ClientHTTPException.java new file mode 100644 index 00000000000..4a3ce9f9df2 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ClientHTTPException.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +import java.net.HttpURLConnection; + +/** + * HTTP-related exception indicating that an HTTP client has erred. Status codes + * for these types of errors are in the 4xx range. The default status code for + * constructors without a statusCode parameter is + * 400 Bad Request. + * + * @author Arjohn Kampman + */ +public class ClientHTTPException extends HTTPException { + + private static final long serialVersionUID = 7722604284325312749L; + + private static final int DEFAULT_STATUS_CODE = HttpURLConnection.HTTP_BAD_REQUEST; + + /** + * Creates a {@link ClientHTTPException} with status code 400 "Bad Request". + */ + public ClientHTTPException() { + this(DEFAULT_STATUS_CODE); + } + + /** + * Creates a {@link ClientHTTPException} with status code 400 "Bad Request". + */ + public ClientHTTPException(String msg) { + this(DEFAULT_STATUS_CODE, msg); + } + + /** + * Creates a {@link ClientHTTPException} with status code 400 "Bad Request". + */ + public ClientHTTPException(String msg, Throwable t) { + this(DEFAULT_STATUS_CODE, t); + } + + /** + * Creates a {@link ClientHTTPException} with the specified status code. + * + * @throws IllegalArgumentException + * If statusCode is not in the 4xx range. + */ + public ClientHTTPException(int statusCode) { + super(statusCode); + } + + /** + * Creates a {@link ClientHTTPException} with the specified status code. + * + * @throws IllegalArgumentException + * If statusCode is not in the 4xx range. + */ + public ClientHTTPException(int statusCode, String message) { + super(statusCode, message); + } + + /** + * Creates a {@link ClientHTTPException} with the specified status code. + * + * @throws IllegalArgumentException + * If statusCode is not in the 4xx range. + */ + public ClientHTTPException(int statusCode, String message, Throwable t) { + super(statusCode, message, t); + } + + /** + * Creates a {@link ClientHTTPException} with the specified status code. + * + * @throws IllegalArgumentException + * If statusCode is not in the 4xx range. + */ + public ClientHTTPException(int statusCode, Throwable t) { + super(statusCode, t); + } + + @Override + protected void setStatusCode(int statusCode) { + if (statusCode < 400 || statusCode > 499) { + throw new IllegalArgumentException("Status code must be in the 4xx range, is: " + statusCode); + } + + super.setStatusCode(statusCode); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/HTTPException.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/HTTPException.java new file mode 100644 index 00000000000..1a954b212f9 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/HTTPException.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +/** + * HTTP-related exception that includes the relevant HTTP status code. + * + * @author Arjohn Kampman + */ +public class HTTPException extends Exception { + + private static final long serialVersionUID = 1356463348553827230L; + + private int statusCode; + + public HTTPException(int statusCode) { + super(); + setStatusCode(statusCode); + } + + public HTTPException(int statusCode, String message) { + super(message); + setStatusCode(statusCode); + } + + public HTTPException(int statusCode, String message, Throwable t) { + super(message, t); + setStatusCode(statusCode); + } + + public HTTPException(int statusCode, Throwable t) { + super(t); + setStatusCode(statusCode); + } + + public final int getStatusCode() { + return statusCode; + } + + protected void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ProtocolExceptionResolver.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ProtocolExceptionResolver.java new file mode 100644 index 00000000000..80535fcae21 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ProtocolExceptionResolver.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.webapp.views.SimpleResponseView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.servlet.HandlerExceptionResolver; +import org.springframework.web.servlet.ModelAndView; + +/** + * Simple resolver for Exceptions: returns the correct response code and message + * to the client. + * + * @author Herko ter Horst + */ +public class ProtocolExceptionResolver implements HandlerExceptionResolver { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, + Object handler, Exception exception) + { + logger.debug("ProtocolExceptionResolver.resolveException() called"); + + int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; + String errMsg = exception.getMessage(); + + if (exception instanceof HTTPException) { + HTTPException httpExc = (HTTPException)exception; + statusCode = httpExc.getStatusCode(); + + if (exception instanceof ClientHTTPException) { + logger.info("Client sent bad request ( " + statusCode + ")", exception); + } + else { + logger.error("Error while handling request (" + statusCode + ")", exception); + } + } + else { + logger.error("Error while handling request", exception); + } + + Map model = new HashMap(); + model.put(SimpleResponseView.SC_KEY, Integer.valueOf(statusCode)); + model.put(SimpleResponseView.CONTENT_KEY, errMsg); + + return new ModelAndView(SimpleResponseView.getInstance(), model); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ProtocolUtil.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ProtocolUtil.java new file mode 100644 index 00000000000..fc95aea2596 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ProtocolUtil.java @@ -0,0 +1,203 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_NOT_ACCEPTABLE; + +import java.util.Collection; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Optional; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.lang.FileFormat; +import org.eclipse.rdf4j.common.lang.service.FileFormatServiceRegistry; +import org.eclipse.rdf4j.common.webapp.util.HttpServerUtil; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.protocol.error.ErrorInfo; +import org.eclipse.rdf4j.http.protocol.error.ErrorType; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utilities to help with the transition between HTTP requests/responses and + * values expected by the protocol. + * + * @author Herko ter Horst + * @author Arjohn Kampman + */ +public class ProtocolUtil { + + public static Value parseValueParam(HttpServletRequest request, String paramName, ValueFactory vf) + throws ClientHTTPException + { + String paramValue = request.getParameter(paramName); + try { + return Protocol.decodeValue(paramValue, vf); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Invalid value for parameter '" + paramName + "': " + + paramValue); + } + } + + public static Resource parseResourceParam(HttpServletRequest request, String paramName, ValueFactory vf) + throws ClientHTTPException + { + String paramValue = request.getParameter(paramName); + try { + return Protocol.decodeResource(paramValue, vf); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Invalid value for parameter '" + paramName + "': " + + paramValue); + } + } + + public static IRI parseURIParam(HttpServletRequest request, String paramName, ValueFactory vf) + throws ClientHTTPException + { + String paramValue = request.getParameter(paramName); + try { + return Protocol.decodeURI(paramValue, vf); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Invalid value for parameter '" + paramName + "': " + + paramValue); + } + } + + public static IRI parseGraphParam(HttpServletRequest request, ValueFactory vf) + throws ClientHTTPException + { + String paramValue = request.getParameter(Protocol.GRAPH_PARAM_NAME); + if (paramValue == null) { + return null; + } + + try { + return Protocol.decodeURI("<" + paramValue + ">", vf); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Invalid value for parameter '" + + Protocol.GRAPH_PARAM_NAME + "': " + paramValue); + } + } + + public static Resource[] parseContextParam(HttpServletRequest request, String paramName, ValueFactory vf) + throws ClientHTTPException + { + String[] paramValues = request.getParameterValues(paramName); + try { + return Protocol.decodeContexts(paramValues, vf); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Invalid value for parameter '" + paramName + "': " + + e.getMessage()); + } + } + + public static boolean parseBooleanParam(HttpServletRequest request, String paramName, boolean defaultValue) + { + String paramValue = request.getParameter(paramName); + if (paramValue == null) { + return defaultValue; + } + else { + return Boolean.parseBoolean(paramValue); + } + } + + /** + * Logs all request parameters of the supplied request. + */ + public static void logRequestParameters(HttpServletRequest request) { + Logger logger = LoggerFactory.getLogger(ProtocolUtil.class); + if (logger.isDebugEnabled()) { + @SuppressWarnings("unchecked") + Enumeration paramNames = request.getParameterNames(); + while (paramNames.hasMoreElements()) { + String name = paramNames.nextElement(); + for (String value : request.getParameterValues(name)) { + logger.debug("{}=\"{}\"", name, value); + } + } + } + } + + public static S getAcceptableService(HttpServletRequest request, + HttpServletResponse response, FileFormatServiceRegistry serviceRegistry) + throws ClientHTTPException + { + // Accept-parameter takes precedence over request headers + String mimeType = request.getParameter(Protocol.ACCEPT_PARAM_NAME); + boolean hasAcceptParam = mimeType != null; + + if (mimeType == null) { + // Find an acceptable MIME type based on the request headers + logAcceptableFormats(request); + + Collection mimeTypes = new LinkedHashSet(16); + // Prefer the default mime types, explicitly before non-default + for (FileFormat format : serviceRegistry.getKeys()) { + mimeTypes.add(format.getDefaultMIMEType()); + } + for (FileFormat format : serviceRegistry.getKeys()) { + mimeTypes.addAll(format.getMIMETypes()); + } + + mimeType = HttpServerUtil.selectPreferredMIMEType(mimeTypes.iterator(), request); + + response.setHeader("Vary", "Accept"); + } + + if (mimeType != null) { + Optional format = serviceRegistry.getFileFormatForMIMEType(mimeType); + + if (format.isPresent()) { + return serviceRegistry.get(format.get()).get(); + } + } + + if (hasAcceptParam) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.UNSUPPORTED_FILE_FORMAT, mimeType); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + else { + // No acceptable format was found, send 406 as required by RFC 2616 + throw new ClientHTTPException(SC_NOT_ACCEPTABLE, "No acceptable file format found."); + } + } + + public static void logAcceptableFormats(HttpServletRequest request) { + Logger logger = LoggerFactory.getLogger(ProtocolUtil.class); + if (logger.isDebugEnabled()) { + StringBuilder acceptable = new StringBuilder(64); + + @SuppressWarnings("unchecked") + Enumeration acceptHeaders = request.getHeaders("Accept"); + + while (acceptHeaders.hasMoreElements()) { + acceptable.append(acceptHeaders.nextElement()); + + if (acceptHeaders.hasMoreElements()) { + acceptable.append(','); + } + } + + logger.debug("Acceptable formats: " + acceptable); + } + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ServerHTTPException.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ServerHTTPException.java new file mode 100644 index 00000000000..2c67adaf198 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ServerHTTPException.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +import java.net.HttpURLConnection; + +/** + * HTTP-related exception indicating that an error occurred in a server. Status + * codes for these types of errors are in the 5xx range. The default status code + * for constructors without a statusCode parameter is + * 500 Internal Server Error. + * + * @author Arjohn Kampman + */ +public class ServerHTTPException extends HTTPException { + + private static final long serialVersionUID = -3949837199542648966L; + + private static final int DEFAULT_STATUS_CODE = HttpURLConnection.HTTP_INTERNAL_ERROR; + + /** + * Creates a {@link ServerHTTPException} with status code 500 "Internal + * Server Error". + */ + public ServerHTTPException() { + this(DEFAULT_STATUS_CODE); + } + + /** + * Creates a {@link ServerHTTPException} with status code 500 "Internal + * Server Error". + */ + public ServerHTTPException(String msg) { + this(DEFAULT_STATUS_CODE, msg); + } + + /** + * Creates a {@link ServerHTTPException} with status code 500 "Internal + * Server Error". + */ + public ServerHTTPException(String msg, Throwable t) { + this(DEFAULT_STATUS_CODE, t); + } + + /** + * Creates a {@link ServerHTTPException} with the specified status code. The + * supplied status code must be in the 5xx range. + * + * @throws IllegalArgumentException + * If statusCode is not in the 5xx range. + */ + public ServerHTTPException(int statusCode) { + super(statusCode); + } + + /** + * Creates a {@link ServerHTTPException} with the specified status code. The + * supplied status code must be in the 5xx range. + * + * @throws IllegalArgumentException + * If statusCode is not in the 5xx range. + */ + public ServerHTTPException(int statusCode, String message) { + super(statusCode, message); + } + + /** + * Creates a {@link ServerHTTPException} with the specified status code. The + * supplied status code must be in the 5xx range. + * + * @throws IllegalArgumentException + * If statusCode is not in the 5xx range. + */ + public ServerHTTPException(int statusCode, String message, Throwable t) { + super(statusCode, message, t); + } + + /** + * Creates a {@link ServerHTTPException} with the specified status code. The + * supplied status code must be in the 5xx range. + * + * @throws IllegalArgumentException + * If statusCode is not in the 5xx range. + */ + public ServerHTTPException(int statusCode, Throwable t) { + super(statusCode, t); + } + + @Override + protected void setStatusCode(int statusCode) { + if (statusCode < 500 || statusCode > 599) { + throw new IllegalArgumentException("Status code must be in the 5xx range, is: " + statusCode); + } + + super.setStatusCode(statusCode); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ServerInterceptor.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ServerInterceptor.java new file mode 100644 index 00000000000..f2d45136edb --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/ServerInterceptor.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + + +/** + * Base class for single-use request interceptors. This implementation sets the + * thread name to something sensible at the start of the request handling and + * resets the name at the end. This is useful for logging frameworks that make + * use of thread names, such as Log4J. Should not be a singleton bean! Configure + * as inner bean in openrdf-servlet.xml + * + * @author Herko ter Horst + */ +public abstract class ServerInterceptor extends HandlerInterceptorAdapter { + + private String origThreadName; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception + { + origThreadName = Thread.currentThread().getName(); + Thread.currentThread().setName(getThreadName()); + + setRequestAttributes(request); + + return super.preHandle(request, response, handler); + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, + Exception exception) + throws Exception + { + cleanUpResources(); + Thread.currentThread().setName(origThreadName); + } + + /** + * Determine the thread name to use. Called before the request is forwarded + * to a handler. + * + * @return a name that makes sense based on the request + * @throws ServerHTTPException + * if it was impossible to determine a name due to an internal error + */ + protected abstract String getThreadName() + throws ServerHTTPException; + + /** + * Set attributes for this request. Called before the request is forwarded to + * a handler. By default, this method does nothing. + * + * @param request + * the request + * @throws ClientHTTPException + * if it was impossible to set one or more attributes due to a bad + * request on the part of the client + * @throws ServerHTTPException + * if it was impossible to set one or more attributes due to an + * internal error + */ + protected void setRequestAttributes(HttpServletRequest request) + throws ClientHTTPException, ServerHTTPException + { + } + + /** + * Clean up resources used in handling this request. Called after the request + * is handled and a the view is rendered (or an exception has occurred). By + * default, this method does nothing. + * + * @throws ServerHTTPException + * if some resources could not be cleaned up because of an internal + * error + */ + protected void cleanUpResources() + throws ServerHTTPException + { + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/protocol/ProtocolController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/protocol/ProtocolController.java new file mode 100644 index 00000000000..cd6e011b93b --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/protocol/ProtocolController.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.protocol; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.webapp.views.SimpleResponseView; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles requests for protocol information. + * + * Currently returns the protocol version as plain text. + * + * @author Herko ter Horst + */ +public class ProtocolController extends AbstractController { + + public ProtocolController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_GET, METHOD_HEAD }); + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + Map model = new HashMap(); + model.put(SimpleResponseView.CONTENT_KEY, Protocol.VERSION); + return new ModelAndView(SimpleResponseView.getInstance(), model); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/protocol/ProtocolInterceptor.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/protocol/ProtocolInterceptor.java new file mode 100644 index 00000000000..36263929dc2 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/protocol/ProtocolInterceptor.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.protocol; + +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.server.ServerInterceptor; + +/** + * Interceptor for protocol requests. Should not be a singleton bean! Configure + * as inner bean in openrdf-servlet.xml + * + * @author Herko ter Horst + */ +public class ProtocolInterceptor extends ServerInterceptor { + + @Override + protected String getThreadName() + { + return Protocol.PROTOCOL; + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/BooleanQueryResultView.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/BooleanQueryResultView.java new file mode 100644 index 00000000000..18bc0171a9d --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/BooleanQueryResultView.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository; + +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultWriter; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultWriterFactory; + +/** + * View used to render boolean query results. Renders results in a format + * specified using a parameter or Accept header. + * + * @author Arjohn Kampman + */ +public class BooleanQueryResultView extends QueryResultView { + + private static final BooleanQueryResultView INSTANCE = new BooleanQueryResultView(); + + public static BooleanQueryResultView getInstance() { + return INSTANCE; + } + + private BooleanQueryResultView() { + } + + public String getContentType() { + return null; + } + + @SuppressWarnings("rawtypes") + protected void renderInternal(Map model, HttpServletRequest request, HttpServletResponse response) + throws IOException + { + BooleanQueryResultWriterFactory brWriterFactory = (BooleanQueryResultWriterFactory)model.get(FACTORY_KEY); + BooleanQueryResultFormat brFormat = brWriterFactory.getBooleanQueryResultFormat(); + + response.setStatus(SC_OK); + setContentType(response, brFormat); + setContentDisposition(model, response, brFormat); + + boolean headersOnly = (Boolean)model.get(HEADERS_ONLY); + + if (!headersOnly) { + OutputStream out = response.getOutputStream(); + try { + BooleanQueryResultWriter qrWriter = brWriterFactory.getWriter(out); + boolean value = (Boolean)model.get(QUERY_RESULT_KEY); + qrWriter.handleBoolean(value); + } + catch (QueryResultHandlerException e) { + if (e.getCause() != null && e.getCause() instanceof IOException) { + throw (IOException)e.getCause(); + } + else { + throw new IOException(e); + } + } + finally { + out.close(); + } + } + logEndOfRequest(request); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/GraphQueryResultView.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/GraphQueryResultView.java new file mode 100644 index 00000000000..978c94ad6b7 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/GraphQueryResultView.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository; + +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; +import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.query.GraphQueryResult; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryInterruptedException; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.RDFWriterFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * View used to render graph query results. Renders the graph as RDF using a + * serialization specified using a parameter or Accept header. + * + * @author Herko ter Horst + * @author Arjohn Kampman + */ +public class GraphQueryResultView extends QueryResultView { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + private static final GraphQueryResultView INSTANCE = new GraphQueryResultView(); + + public static GraphQueryResultView getInstance() { + return INSTANCE; + } + + private GraphQueryResultView() { + } + + public String getContentType() { + return null; + } + + @SuppressWarnings("rawtypes") + protected void renderInternal(Map model, HttpServletRequest request, HttpServletResponse response) + throws IOException + { + RDFWriterFactory rdfWriterFactory = (RDFWriterFactory)model.get(FACTORY_KEY); + RDFFormat rdfFormat = rdfWriterFactory.getRDFFormat(); + + response.setStatus(SC_OK); + setContentType(response, rdfFormat); + setContentDisposition(model, response, rdfFormat); + + boolean headersOnly = (Boolean)model.get(HEADERS_ONLY); + + if (!headersOnly) { + OutputStream out = response.getOutputStream(); + try { + RDFWriter rdfWriter = rdfWriterFactory.getWriter(out); + GraphQueryResult graphQueryResult = (GraphQueryResult)model.get(QUERY_RESULT_KEY); + QueryResults.report(graphQueryResult, rdfWriter); + } + catch (QueryInterruptedException e) { + logger.error("Query interrupted", e); + response.sendError(SC_SERVICE_UNAVAILABLE, "Query evaluation took too long"); + } + catch (QueryEvaluationException e) { + logger.error("Query evaluation error", e); + response.sendError(SC_INTERNAL_SERVER_ERROR, "Query evaluation error: " + e.getMessage()); + } + catch (RDFHandlerException e) { + logger.error("Serialization error", e); + response.sendError(SC_INTERNAL_SERVER_ERROR, "Serialization error: " + e.getMessage()); + } + finally { + out.close(); + } + } + logEndOfRequest(request); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/QueryResultView.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/QueryResultView.java new file mode 100644 index 00000000000..c4f93054504 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/QueryResultView.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository; + +import static org.eclipse.rdf4j.http.protocol.Protocol.QUERY_PARAM_NAME; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.lang.FileFormat; +import org.eclipse.rdf4j.http.server.repository.transaction.ActiveTransactionRegistry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.servlet.View; + +/** + * Base class for rendering query results. + * + * @author Herko ter Horst + * @author Arjohn Kampman + */ +public abstract class QueryResultView implements View { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * Key by which the query result is stored in the model. + */ + public static final String QUERY_RESULT_KEY = "queryResult"; + + /** + * Key by which the query result writer factory is stored in the model. + */ + public static final String FACTORY_KEY = "factory"; + + /** + * Key by which a filename hint is stored in the model. The filename hint may + * be used to present the client with a suggestion for a filename to use for + * storing the result. + */ + public static final String FILENAME_HINT_KEY = "filenameHint"; + + /** + * Key by which the id of the current transaction is stored in the model. If + * this is present, the QueryResultView will take care to release the + * connection back to the + * {@link org.eclipse.rdf4j.http.server.repository.transaction.ActiveTransactionRegistry} + * after processing the query result. + * + * @since 2.8.5 + */ + public static final String TRANSACTION_ID_KEY = "transactionID"; + + public static final String HEADERS_ONLY = "headersOnly"; + + @SuppressWarnings("rawtypes") + public final void render(Map model, HttpServletRequest request, HttpServletResponse response) + throws IOException + { + UUID txnId = null; + try { + txnId = (UUID)model.get(TRANSACTION_ID_KEY); + renderInternal(model, request, response); + } + finally { + if (txnId != null) { + ActiveTransactionRegistry.INSTANCE.returnTransactionConnection(txnId); + } + } + } + + @SuppressWarnings("rawtypes") + protected abstract void renderInternal(Map model, HttpServletRequest request, HttpServletResponse response) + throws IOException; + + protected void setContentType(HttpServletResponse response, FileFormat fileFormat) + throws IOException + { + String mimeType = fileFormat.getDefaultMIMEType(); + if (fileFormat.hasCharset()) { + Charset charset = fileFormat.getCharset(); + mimeType += "; charset=" + charset.name(); + } + response.setContentType(mimeType); + } + + @SuppressWarnings("rawtypes") + protected void setContentDisposition(Map model, HttpServletResponse response, FileFormat fileFormat) + throws IOException + { + // Report as attachment to make use in browser more convenient + String filename = (String)model.get(FILENAME_HINT_KEY); + + if (filename == null || filename.length() == 0) { + filename = "result"; + } + + if (fileFormat.getDefaultFileExtension() != null) { + filename += "." + fileFormat.getDefaultFileExtension(); + } + + response.setHeader("Content-Disposition", "attachment; filename=" + filename); + } + + protected void logEndOfRequest(HttpServletRequest request) { + if (logger.isInfoEnabled()) { + String queryStr = request.getParameter(QUERY_PARAM_NAME); + int qryCode = String.valueOf(queryStr).hashCode(); + logger.info("Request for query {} is finished", qryCode); + } + } + +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryController.java new file mode 100644 index 00000000000..de5ea19e77d --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryController.java @@ -0,0 +1,369 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository; + +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE; +import static javax.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE; +import static org.eclipse.rdf4j.http.protocol.Protocol.BINDING_PREFIX; +import static org.eclipse.rdf4j.http.protocol.Protocol.DEFAULT_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.INCLUDE_INFERRED_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.NAMED_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.QUERY_LANGUAGE_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.QUERY_PARAM_NAME; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpStatus; +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.lang.FileFormat; +import org.eclipse.rdf4j.common.lang.service.FileFormatServiceRegistry; +import org.eclipse.rdf4j.common.webapp.util.HttpServerUtil; +import org.eclipse.rdf4j.common.webapp.views.EmptySuccessView; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.protocol.error.ErrorInfo; +import org.eclipse.rdf4j.http.protocol.error.ErrorType; +import org.eclipse.rdf4j.http.server.ClientHTTPException; +import org.eclipse.rdf4j.http.server.HTTPException; +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BooleanQuery; +import org.eclipse.rdf4j.query.GraphQuery; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.Query; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryInterruptedException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.query.impl.SimpleDataset; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultWriterRegistry; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterRegistry; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.eclipse.rdf4j.repository.manager.SystemRepository; +import org.eclipse.rdf4j.rio.RDFWriterRegistry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles queries and admin (delete) operations on a repository and renders the + * results in a format suitable to the type of operation. + * + * @author Herko ter Horst + */ +public class RepositoryController extends AbstractController { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + private RepositoryManager repositoryManager; + + private static final String METHOD_DELETE = "DELETE"; + + public RepositoryController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_GET, METHOD_POST, METHOD_DELETE, METHOD_HEAD }); + } + + public void setRepositoryManager(RepositoryManager repMan) { + repositoryManager = repMan; + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + String reqMethod = request.getMethod(); + String queryStr = request.getParameter(QUERY_PARAM_NAME); + + if (METHOD_POST.equals(reqMethod)) { + String mimeType = HttpServerUtil.getMIMEType(request.getContentType()); + + if (!(Protocol.FORM_MIME_TYPE.equals(mimeType) || Protocol.SPARQL_QUERY_MIME_TYPE.equals(mimeType))) { + throw new ClientHTTPException(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported MIME type: " + mimeType); + } + + if (Protocol.SPARQL_QUERY_MIME_TYPE.equals(mimeType)) { + // The query should be the entire body + try { + queryStr = IOUtils.toString(request.getReader()); + } + catch (IOException e) { + throw new HTTPException(HttpStatus.SC_BAD_REQUEST, "Error reading request message body", e); + } + if (queryStr.isEmpty()) queryStr = null; + } + } + else if (METHOD_DELETE.equals(reqMethod)) { + String repId = RepositoryInterceptor.getRepositoryID(request); + logger.info("DELETE request invoked for repository '" + repId + "'"); + + if (queryStr != null) { + logger.warn("query supplied on repository delete request, aborting delete"); + throw new HTTPException(HttpStatus.SC_BAD_REQUEST, + "Repository delete error: query supplied with request"); + } + + if (SystemRepository.ID.equals(repId)) { + logger.warn("attempted delete of SYSTEM repository, aborting"); + throw new HTTPException(HttpStatus.SC_FORBIDDEN, "SYSTEM Repository can not be deleted"); + } + + try { + // we need to forcibly close the default repository connection + // opened for this repository by + // the interceptor. + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + repositoryCon.close(); + } + + boolean success = repositoryManager.removeRepository(repId); + if (success) { + logger.info("DELETE request successfully completed"); + return new ModelAndView(EmptySuccessView.getInstance()); + } + else { + logger.error("error while attempting to delete repository '" + repId + "'"); + throw new HTTPException(HttpStatus.SC_BAD_REQUEST, + "could not locate repository configuration for repository '" + repId + "'."); + } + } + catch (OpenRDFException e) { + logger.error("error while attempting to delete repository '" + repId + "'", e); + throw new ServerHTTPException("Repository delete error: " + e.getMessage(), e); + } + } + + Repository repository = RepositoryInterceptor.getRepository(request); + + int qryCode = 0; + if (logger.isInfoEnabled() || logger.isDebugEnabled()) { + qryCode = String.valueOf(queryStr).hashCode(); + } + + boolean headersOnly = false; + if (METHOD_GET.equals(reqMethod)) { + logger.info("GET query {}", qryCode); + } + else if (METHOD_HEAD.equals(reqMethod)) { + logger.info("HEAD query {}", qryCode); + headersOnly = true; + } + else if (METHOD_POST.equals(reqMethod)) { + logger.info("POST query {}", qryCode); + } + + logger.debug("query {} = {}", qryCode, queryStr); + + if (queryStr != null) { + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + Query query = getQuery(repository, repositoryCon, queryStr, request, response); + + View view; + Object queryResult; + FileFormatServiceRegistry registry; + + try { + if (query instanceof TupleQuery) { + TupleQuery tQuery = (TupleQuery)query; + + queryResult = headersOnly ? null : tQuery.evaluate(); + registry = TupleQueryResultWriterRegistry.getInstance(); + view = TupleQueryResultView.getInstance(); + } + else if (query instanceof GraphQuery) { + GraphQuery gQuery = (GraphQuery)query; + + queryResult = headersOnly ? null : gQuery.evaluate(); + registry = RDFWriterRegistry.getInstance(); + view = GraphQueryResultView.getInstance(); + } + else if (query instanceof BooleanQuery) { + BooleanQuery bQuery = (BooleanQuery)query; + + queryResult = headersOnly ? null : bQuery.evaluate(); + registry = BooleanQueryResultWriterRegistry.getInstance(); + view = BooleanQueryResultView.getInstance(); + } + else { + throw new ClientHTTPException(SC_BAD_REQUEST, "Unsupported query type: " + + query.getClass().getName()); + } + } + catch (QueryInterruptedException e) { + logger.info("Query interrupted", e); + throw new ServerHTTPException(SC_SERVICE_UNAVAILABLE, "Query evaluation took too long"); + } + catch (QueryEvaluationException e) { + logger.info("Query evaluation error", e); + if (e.getCause() != null && e.getCause() instanceof HTTPException) { + // custom signal from the backend, throw as HTTPException + // directly (see SES-1016). + throw (HTTPException)e.getCause(); + } + else { + throw new ServerHTTPException("Query evaluation error: " + e.getMessage()); + } + } + Object factory = ProtocolUtil.getAcceptableService(request, response, registry); + + Map model = new HashMap(); + model.put(QueryResultView.FILENAME_HINT_KEY, "query-result"); + model.put(QueryResultView.QUERY_RESULT_KEY, queryResult); + model.put(QueryResultView.FACTORY_KEY, factory); + model.put(QueryResultView.HEADERS_ONLY, headersOnly); + + return new ModelAndView(view, model); + } + } + else { + throw new ClientHTTPException(SC_BAD_REQUEST, "Missing parameter: " + QUERY_PARAM_NAME); + } + } + + private Query getQuery(Repository repository, RepositoryConnection repositoryCon, String queryStr, + HttpServletRequest request, HttpServletResponse response) + throws IOException, ClientHTTPException + { + Query result = null; + + // default query language is SPARQL + QueryLanguage queryLn = QueryLanguage.SPARQL; + + String queryLnStr = request.getParameter(QUERY_LANGUAGE_PARAM_NAME); + logger.debug("query language param = {}", queryLnStr); + + if (queryLnStr != null) { + queryLn = QueryLanguage.valueOf(queryLnStr); + + if (queryLn == null) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Unknown query language: " + queryLnStr); + } + } + + String baseURI = request.getParameter(Protocol.BASEURI_PARAM_NAME); + + // determine if inferred triples should be included in query evaluation + boolean includeInferred = ProtocolUtil.parseBooleanParam(request, INCLUDE_INFERRED_PARAM_NAME, true); + + String timeout = request.getParameter(Protocol.TIMEOUT_PARAM_NAME); + int maxQueryTime = 0; + if (timeout != null) { + try { + maxQueryTime = Integer.parseInt(timeout); + } + catch (NumberFormatException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Invalid timeout value: " + timeout); + } + } + + // build a dataset, if specified + String[] defaultGraphURIs = request.getParameterValues(DEFAULT_GRAPH_PARAM_NAME); + String[] namedGraphURIs = request.getParameterValues(NAMED_GRAPH_PARAM_NAME); + + SimpleDataset dataset = null; + if (defaultGraphURIs != null || namedGraphURIs != null) { + dataset = new SimpleDataset(); + + if (defaultGraphURIs != null) { + for (String defaultGraphURI : defaultGraphURIs) { + try { + IRI uri = createURIOrNull(repository, defaultGraphURI); + dataset.addDefaultGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Illegal URI for default graph: " + + defaultGraphURI); + } + } + } + + if (namedGraphURIs != null) { + for (String namedGraphURI : namedGraphURIs) { + try { + IRI uri = createURIOrNull(repository, namedGraphURI); + dataset.addNamedGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Illegal URI for named graph: " + + namedGraphURI); + } + } + } + } + + try { + result = repositoryCon.prepareQuery(queryLn, queryStr, baseURI); + + result.setIncludeInferred(includeInferred); + + if (maxQueryTime > 0) { + result.setMaxQueryTime(maxQueryTime); + } + + if (dataset != null) { + result.setDataset(dataset); + } + + // determine if any variable bindings have been set on this query. + @SuppressWarnings("unchecked") + Enumeration parameterNames = request.getParameterNames(); + + while (parameterNames.hasMoreElements()) { + String parameterName = parameterNames.nextElement(); + + if (parameterName.startsWith(BINDING_PREFIX) && parameterName.length() > BINDING_PREFIX.length()) + { + String bindingName = parameterName.substring(BINDING_PREFIX.length()); + Value bindingValue = ProtocolUtil.parseValueParam(request, parameterName, + repository.getValueFactory()); + result.setBinding(bindingName, bindingValue); + } + } + } + catch (UnsupportedQueryLanguageException e) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.UNSUPPORTED_QUERY_LANGUAGE, queryLn.getName()); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + catch (MalformedQueryException e) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.MALFORMED_QUERY, e.getMessage()); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + catch (RepositoryException e) { + logger.error("Repository error", e); + response.sendError(SC_INTERNAL_SERVER_ERROR); + } + + return result; + } + + private IRI createURIOrNull(Repository repository, String graphURI) { + if ("null".equals(graphURI)) + return null; + return repository.getValueFactory().createIRI(graphURI); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryInterceptor.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryInterceptor.java new file mode 100644 index 00000000000..59595d9e4d8 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryInterceptor.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository; + +import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.server.ClientHTTPException; +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.ServerInterceptor; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Interceptor for repository requests. Handles the opening and closing of + * connections to the repository specified in the request. Should not be a + * singleton bean! Configure as inner bean in openrdf-servlet.xml + * + * @author Herko ter Horst + * @author Arjohn Kampman + */ +public class RepositoryInterceptor extends ServerInterceptor { + + /*-----------* + * Constants * + *-----------*/ + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private static final String REPOSITORY_ID_KEY = "repositoryID"; + + private static final String REPOSITORY_KEY = "repository"; + + private static final String REPOSITORY_CONNECTION_KEY = "repositoryConnection"; + + /*-----------* + * Variables * + *-----------*/ + + private RepositoryManager repositoryManager; + + private String repositoryID; + + private RepositoryConnection repositoryCon; + + /*---------* + * Methods * + *---------*/ + + public void setRepositoryManager(RepositoryManager repMan) { + repositoryManager = repMan; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse respons, Object handler) + throws Exception + { + String pathInfoStr = request.getPathInfo(); + logger.debug("path info: {}", pathInfoStr); + + repositoryID = null; + + if (pathInfoStr != null && !pathInfoStr.equals("/")) { + String[] pathInfo = pathInfoStr.substring(1).split("/"); + if (pathInfo.length > 0) { + repositoryID = pathInfo[0]; + logger.debug("repositoryID is '{}'", repositoryID); + } + } + + ProtocolUtil.logRequestParameters(request); + + return super.preHandle(request, respons, handler); + } + + @Override + protected String getThreadName() { + String threadName = Protocol.REPOSITORIES; + + if (repositoryID != null) { + threadName += "/" + repositoryID; + } + + return threadName; + } + + @Override + protected void setRequestAttributes(HttpServletRequest request) + throws ClientHTTPException, ServerHTTPException + { + if (repositoryID != null) { + try { + Repository repository = repositoryManager.getRepository(repositoryID); + + if (repository == null) { + throw new ClientHTTPException(SC_NOT_FOUND, "Unknown repository: " + repositoryID); + } + + repositoryCon = repository.getConnection(); + + // SES-1834 by default, the Sesame server should not treat datatype or language value verification errors + // as fatal. This is to be graceful, by default, about accepting "dirty" data. + // FIXME SES-1833 this should be configurable by the user. + repositoryCon.getParserConfig().addNonFatalError(BasicParserSettings.VERIFY_DATATYPE_VALUES); + repositoryCon.getParserConfig().addNonFatalError(BasicParserSettings.VERIFY_LANGUAGE_TAGS); + + // FIXME: hack for repositories that return connections that are not + // in auto-commit mode by default + if (!repositoryCon.isAutoCommit()) { + repositoryCon.setAutoCommit(true); + } + + request.setAttribute(REPOSITORY_ID_KEY, repositoryID); + request.setAttribute(REPOSITORY_KEY, repository); + request.setAttribute(REPOSITORY_CONNECTION_KEY, repositoryCon); + } + catch (RepositoryConfigException e) { + throw new ServerHTTPException(e.getMessage(), e); + } + catch (RepositoryException e) { + throw new ServerHTTPException(e.getMessage(), e); + } + } + } + + @Override + protected void cleanUpResources() + throws ServerHTTPException + { + if (repositoryCon != null) { + try { + repositoryCon.close(); + } + catch (RepositoryException e) { + throw new ServerHTTPException(e.getMessage(), e); + } + } + } + + public static String getRepositoryID(HttpServletRequest request) { + return (String)request.getAttribute(REPOSITORY_ID_KEY); + } + + public static Repository getRepository(HttpServletRequest request) { + return (Repository)request.getAttribute(REPOSITORY_KEY); + } + + public static RepositoryConnection getRepositoryConnection(HttpServletRequest request) { + return (RepositoryConnection)request.getAttribute(REPOSITORY_CONNECTION_KEY); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryListController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryListController.java new file mode 100644 index 00000000000..8edc8a8926e --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/RepositoryListController.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.impl.IteratingTupleQueryResult; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterFactory; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterRegistry; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles requests for the list of repositories available on this server. + * + * @author Herko ter Horst + */ +public class RepositoryListController extends AbstractController { + + private static final String REPOSITORY_LIST_QUERY; + + static { + StringBuilder query = new StringBuilder(256); + query.append("SELECT id, title, \"true\"^^xsd:boolean as \"readable\", \"true\"^^xsd:boolean as \"writable\""); + query.append("FROM {} rdf:type {sys:Repository};"); + query.append(" [rdfs:label {title}];"); + query.append(" sys:repositoryID {id} "); + query.append("USING NAMESPACE sys = "); + REPOSITORY_LIST_QUERY = query.toString(); + } + + private RepositoryManager repositoryManager; + + public RepositoryListController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_GET, METHOD_HEAD }); + } + + public void setRepositoryManager(RepositoryManager repMan) { + repositoryManager = repMan; + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + Map model = new HashMap(); + + if (METHOD_GET.equals(request.getMethod())) { + Repository systemRepository = repositoryManager.getSystemRepository(); + ValueFactory vf = systemRepository.getValueFactory(); + + try { + RepositoryConnection con = systemRepository.getConnection(); + try { + // FIXME: The query result is cached here as we need to close the + // connection before returning. Would be much better to stream + // the + // query result directly to the client. + + List bindingNames = new ArrayList(); + List bindingSets = new ArrayList(); + + TupleQueryResult queryResult = con.prepareTupleQuery(QueryLanguage.SERQL, + REPOSITORY_LIST_QUERY).evaluate(); + try { + // Determine the repository's URI + StringBuffer requestURL = request.getRequestURL(); + if (requestURL.charAt(requestURL.length() - 1) != '/') { + requestURL.append('/'); + } + String namespace = requestURL.toString(); + + while (queryResult.hasNext()) { + QueryBindingSet bindings = new QueryBindingSet(queryResult.next()); + + String id = bindings.getValue("id").stringValue(); + bindings.addBinding("uri", vf.createIRI(namespace, id)); + + bindingSets.add(bindings); + } + + bindingNames.add("uri"); + bindingNames.addAll(queryResult.getBindingNames()); + } + finally { + queryResult.close(); + } + model.put(QueryResultView.QUERY_RESULT_KEY, + new IteratingTupleQueryResult(bindingNames, bindingSets)); + + } + finally { + con.close(); + } + } + catch (RepositoryException e) { + throw new ServerHTTPException(e.getMessage(), e); + } + } + + TupleQueryResultWriterFactory factory = ProtocolUtil.getAcceptableService(request, response, + TupleQueryResultWriterRegistry.getInstance()); + + model.put(QueryResultView.FILENAME_HINT_KEY, "repositories"); + model.put(QueryResultView.FACTORY_KEY, factory); + model.put(QueryResultView.HEADERS_ONLY, METHOD_HEAD.equals(request.getMethod())); + + return new ModelAndView(TupleQueryResultView.getInstance(), model); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/TupleQueryResultView.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/TupleQueryResultView.java new file mode 100644 index 00000000000..db6e3e025bc --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/TupleQueryResultView.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository; + +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; +import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryInterruptedException; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; +import org.eclipse.rdf4j.query.resultio.BasicQueryWriterSettings; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriter; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * View used to render tuple query results. Renders results in a format + * specified using a parameter or Accept header. + * + * @author Herko ter Horst + * @author Arjohn Kampman + */ +public class TupleQueryResultView extends QueryResultView { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + protected static final String DEFAULT_JSONP_CALLBACK_PARAMETER = "callback"; + + protected static final Pattern JSONP_VALIDATOR = Pattern.compile("^[A-Za-z]\\w+$"); + + private static final TupleQueryResultView INSTANCE = new TupleQueryResultView(); + + public static TupleQueryResultView getInstance() { + return INSTANCE; + } + + private TupleQueryResultView() { + } + + public String getContentType() { + return null; + } + + @SuppressWarnings("rawtypes") + protected void renderInternal(Map model, HttpServletRequest request, HttpServletResponse response) + throws IOException + { + TupleQueryResultWriterFactory qrWriterFactory = (TupleQueryResultWriterFactory)model.get(FACTORY_KEY); + TupleQueryResultFormat qrFormat = qrWriterFactory.getTupleQueryResultFormat(); + + response.setStatus(SC_OK); + setContentType(response, qrFormat); + setContentDisposition(model, response, qrFormat); + + final Boolean headersOnly = (Boolean)model.get(HEADERS_ONLY); + if (headersOnly == null || !headersOnly.booleanValue()) { + OutputStream out = response.getOutputStream(); + try { + TupleQueryResultWriter qrWriter = qrWriterFactory.getWriter(out); + TupleQueryResult tupleQueryResult = (TupleQueryResult)model.get(QUERY_RESULT_KEY); + + if (qrWriter.getSupportedSettings().contains(BasicQueryWriterSettings.JSONP_CALLBACK)) { + String parameter = request.getParameter(DEFAULT_JSONP_CALLBACK_PARAMETER); + + if (parameter != null) { + parameter = parameter.trim(); + + if (parameter.isEmpty()) { + parameter = BasicQueryWriterSettings.JSONP_CALLBACK.getDefaultValue(); + } + + // check callback function name is a valid javascript function + // name + if (!JSONP_VALIDATOR.matcher(parameter).matches()) { + throw new IOException("Callback function name was invalid"); + } + + qrWriter.getWriterConfig().set(BasicQueryWriterSettings.JSONP_CALLBACK, parameter); + } + } + + QueryResults.report(tupleQueryResult, qrWriter); + } + catch (QueryInterruptedException e) { + logger.error("Query interrupted", e); + response.sendError(SC_SERVICE_UNAVAILABLE, "Query evaluation took too long"); + } + catch (QueryEvaluationException e) { + logger.error("Query evaluation error", e); + response.sendError(SC_INTERNAL_SERVER_ERROR, "Query evaluation error: " + e.getMessage()); + } + catch (TupleQueryResultHandlerException e) { + logger.error("Serialization error", e); + response.sendError(SC_INTERNAL_SERVER_ERROR, "Serialization error: " + e.getMessage()); + } + finally { + out.close(); + } + } + logEndOfRequest(request); + } +} \ No newline at end of file diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/contexts/ContextsController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/contexts/ContextsController.java new file mode 100644 index 00000000000..3951e35ae04 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/contexts/ContextsController.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.contexts; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.repository.QueryResultView; +import org.eclipse.rdf4j.http.server.repository.RepositoryInterceptor; +import org.eclipse.rdf4j.http.server.repository.TupleQueryResultView; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.impl.IteratingTupleQueryResult; +import org.eclipse.rdf4j.query.impl.ListBindingSet; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterFactory; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterRegistry; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles requests for the list of contexts in a repository. + * + * @author Herko ter Horst + */ +public class ContextsController extends AbstractController { + + public ContextsController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_GET, METHOD_HEAD }); + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + Map model = new HashMap(); + TupleQueryResultWriterFactory factory = ProtocolUtil.getAcceptableService(request, response, + TupleQueryResultWriterRegistry.getInstance()); + + if (METHOD_GET.equals(request.getMethod())) { + List columnNames = Arrays.asList("contextID"); + List contexts = new ArrayList(); + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized(repositoryCon) + { + try { + CloseableIteration contextIter = repositoryCon.getContextIDs(); + + try { + while (contextIter.hasNext()) { + BindingSet bindingSet = new ListBindingSet(columnNames, contextIter.next()); + contexts.add(bindingSet); + } + } + finally { + contextIter.close(); + } + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository error: " + e.getMessage(), e); + } + } + model.put(QueryResultView.QUERY_RESULT_KEY, new IteratingTupleQueryResult(columnNames, contexts)); + } + + model.put(QueryResultView.FILENAME_HINT_KEY, "contexts"); + model.put(QueryResultView.FACTORY_KEY, factory); + model.put(QueryResultView.HEADERS_ONLY, METHOD_HEAD.equals(request.getMethod())); + return new ModelAndView(TupleQueryResultView.getInstance(), model); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/graph/GraphController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/graph/GraphController.java new file mode 100644 index 00000000000..03abd5b7658 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/graph/GraphController.java @@ -0,0 +1,237 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.graph; + +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.webapp.util.HttpServerUtil; +import org.eclipse.rdf4j.common.webapp.views.EmptySuccessView; +import org.eclipse.rdf4j.http.protocol.error.ErrorInfo; +import org.eclipse.rdf4j.http.protocol.error.ErrorType; +import org.eclipse.rdf4j.http.server.ClientHTTPException; +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.repository.RepositoryInterceptor; +import org.eclipse.rdf4j.http.server.repository.statements.ExportStatementsView; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFWriterFactory; +import org.eclipse.rdf4j.rio.RDFWriterRegistry; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.UnsupportedRDFormatException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles requests for manipulating the named graphs in a repository. + * + * @author Jeen Broekstra + */ +public class GraphController extends AbstractController { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + public GraphController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_GET, METHOD_HEAD, METHOD_POST, "PUT", "DELETE" }); + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + ModelAndView result; + + Repository repository = RepositoryInterceptor.getRepository(request); + + String reqMethod = request.getMethod(); + + if (METHOD_GET.equals(reqMethod)) { + logger.info("GET graph"); + result = getExportStatementsResult(repository, request, response); + logger.info("GET graph request finished."); + } + else if (METHOD_HEAD.equals(reqMethod)) { + logger.info("HEAD graph"); + result = getExportStatementsResult(repository, request, response); + logger.info("HEAD graph request finished."); + } + else if (METHOD_POST.equals(reqMethod)) { + logger.info("POST data to graph"); + result = getAddDataResult(repository, request, response, false); + logger.info("POST data request finished."); + } + else if ("PUT".equals(reqMethod)) { + logger.info("PUT data in graph"); + result = getAddDataResult(repository, request, response, true); + logger.info("PUT data request finished."); + } + else if ("DELETE".equals(reqMethod)) { + logger.info("DELETE data from graph"); + result = getDeleteDataResult(repository, request, response); + logger.info("DELETE data request finished."); + } + else { + throw new ClientHTTPException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method not allowed: " + + reqMethod); + } + return result; + } + + private IRI getGraphName(HttpServletRequest request, ValueFactory vf) + throws ClientHTTPException + { + String requestURL = request.getRequestURL().toString(); + boolean isServiceRequest = requestURL.endsWith("/service"); + + String queryString = request.getQueryString(); + + if (isServiceRequest) { + if (!"default".equalsIgnoreCase(queryString)) { + IRI graph = ProtocolUtil.parseGraphParam(request, vf); + if (graph == null) { + throw new ClientHTTPException(HttpServletResponse.SC_BAD_REQUEST, + "Named or default graph expected for indirect reference request."); + } + return graph; + } + return null; + } + else { + if (queryString != null) { + throw new ClientHTTPException(HttpServletResponse.SC_BAD_REQUEST, + "No parameters epxected for direct reference request."); + } + return vf.createIRI(requestURL); + } + } + + /** + * Get all statements and export them as RDF. + * + * @return a model and view for exporting the statements. + */ + private ModelAndView getExportStatementsResult(Repository repository, HttpServletRequest request, + HttpServletResponse response) + throws ClientHTTPException + { + ProtocolUtil.logRequestParameters(request); + + ValueFactory vf = repository.getValueFactory(); + + IRI graph = getGraphName(request, vf); + + RDFWriterFactory rdfWriterFactory = ProtocolUtil.getAcceptableService(request, response, + RDFWriterRegistry.getInstance()); + + Map model = new HashMap(); + + model.put(ExportStatementsView.CONTEXTS_KEY, new Resource[] { graph }); + model.put(ExportStatementsView.FACTORY_KEY, rdfWriterFactory); + model.put(ExportStatementsView.USE_INFERENCING_KEY, true); + model.put(ExportStatementsView.HEADERS_ONLY, METHOD_HEAD.equals(request.getMethod())); + return new ModelAndView(ExportStatementsView.getInstance(), model); + } + + /** + * Upload data to the graph. + */ + private ModelAndView getAddDataResult(Repository repository, HttpServletRequest request, + HttpServletResponse response, boolean replaceCurrent) + throws IOException, ClientHTTPException, ServerHTTPException + { + ProtocolUtil.logRequestParameters(request); + + String mimeType = HttpServerUtil.getMIMEType(request.getContentType()); + + RDFFormat rdfFormat = Rio.getParserFormatForMIMEType(mimeType).orElseThrow( + () -> new ClientHTTPException(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported MIME type: " + mimeType)); + + ValueFactory vf = repository.getValueFactory(); + + IRI graph = getGraphName(request, vf); + + InputStream in = request.getInputStream(); + try { + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + if (repositoryCon.isAutoCommit()) { + repositoryCon.begin(); + } + + if (replaceCurrent) { + repositoryCon.clear(graph); + } + repositoryCon.add(in, graph.toString(), rdfFormat, graph); + + repositoryCon.commit(); + } + + return new ModelAndView(EmptySuccessView.getInstance()); + } + catch (UnsupportedRDFormatException e) { + throw new ClientHTTPException(SC_UNSUPPORTED_MEDIA_TYPE, "No RDF parser available for format " + + rdfFormat.getName()); + } + catch (RDFParseException e) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.MALFORMED_DATA, e.getMessage()); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + catch (IOException e) { + throw new ServerHTTPException("Failed to read data: " + e.getMessage(), e); + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository update error: " + e.getMessage(), e); + } + } + + /** + * Delete data from the graph. + */ + private ModelAndView getDeleteDataResult(Repository repository, HttpServletRequest request, + HttpServletResponse response) + throws ClientHTTPException, ServerHTTPException + { + ProtocolUtil.logRequestParameters(request); + + ValueFactory vf = repository.getValueFactory(); + + IRI graph = getGraphName(request, vf); + + try { + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + repositoryCon.clear(graph); + } + + return new ModelAndView(EmptySuccessView.getInstance()); + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository update error: " + e.getMessage(), e); + } + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/namespaces/NamespaceController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/namespaces/NamespaceController.java new file mode 100644 index 00000000000..98109ec6160 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/namespaces/NamespaceController.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.namespaces; + +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.common.webapp.views.EmptySuccessView; +import org.eclipse.rdf4j.common.webapp.views.SimpleResponseView; +import org.eclipse.rdf4j.http.server.ClientHTTPException; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.repository.RepositoryInterceptor; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles requests for manipulating a specific namespace definition in a + * repository. + * + * @author Herko ter Horst + * @author Arjohn Kampman + */ +public class NamespaceController extends AbstractController { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + public NamespaceController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_GET, METHOD_HEAD, "PUT", "DELETE" }); + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + String pathInfoStr = request.getPathInfo(); + String[] pathInfo = pathInfoStr.substring(1).split("/"); + String prefix = pathInfo[pathInfo.length - 1]; + + String reqMethod = request.getMethod(); + + if (METHOD_HEAD.equals(reqMethod)) { + logger.info("HEAD namespace for prefix {}", prefix); + + Map model = new HashMap(); + return new ModelAndView(SimpleResponseView.getInstance(), model); + } + + if (METHOD_GET.equals(reqMethod)) { + logger.info("GET namespace for prefix {}", prefix); + return getExportNamespaceResult(request, prefix); + } + + else if ("PUT".equals(reqMethod)) { + logger.info("PUT prefix {}", prefix); + return getUpdateNamespaceResult(request, prefix); + } + else if ("DELETE".equals(reqMethod)) { + logger.info("DELETE prefix {}", prefix); + return getRemoveNamespaceResult(request, prefix); + } + else { + throw new ServerHTTPException("Unexpected request method: " + reqMethod); + } + } + + private ModelAndView getExportNamespaceResult(HttpServletRequest request, String prefix) + throws ServerHTTPException, ClientHTTPException + { + try { + String namespace = null; + + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + namespace = repositoryCon.getNamespace(prefix); + } + + if (namespace == null) { + throw new ClientHTTPException(SC_NOT_FOUND, "Undefined prefix: " + prefix); + } + + Map model = new HashMap(); + model.put(SimpleResponseView.CONTENT_KEY, namespace); + + return new ModelAndView(SimpleResponseView.getInstance(), model); + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository error: " + e.getMessage(), e); + } + } + + private ModelAndView getUpdateNamespaceResult(HttpServletRequest request, String prefix) + throws IOException, ClientHTTPException, ServerHTTPException + { + String namespace = IOUtil.readString(request.getReader()); + namespace = namespace.trim(); + + if (namespace.length() == 0) { + throw new ClientHTTPException(SC_BAD_REQUEST, "No namespace name found in request body"); + } + // FIXME: perform some sanity checks on the namespace string + + try { + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + repositoryCon.setNamespace(prefix, namespace); + } + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository error: " + e.getMessage(), e); + } + + return new ModelAndView(EmptySuccessView.getInstance()); + } + + private ModelAndView getRemoveNamespaceResult(HttpServletRequest request, String prefix) + throws ServerHTTPException + { + try { + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + repositoryCon.removeNamespace(prefix); + } + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository error: " + e.getMessage(), e); + } + + return new ModelAndView(EmptySuccessView.getInstance()); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/namespaces/NamespacesController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/namespaces/NamespacesController.java new file mode 100644 index 00000000000..0e81c4d5039 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/namespaces/NamespacesController.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.namespaces; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.webapp.views.EmptySuccessView; +import org.eclipse.rdf4j.http.server.ClientHTTPException; +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.repository.QueryResultView; +import org.eclipse.rdf4j.http.server.repository.RepositoryInterceptor; +import org.eclipse.rdf4j.http.server.repository.TupleQueryResultView; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.impl.IteratingTupleQueryResult; +import org.eclipse.rdf4j.query.impl.ListBindingSet; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterFactory; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterRegistry; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles requests for the list of namespace definitions for a repository. + * + * @author Herko ter Horst + */ +public class NamespacesController extends AbstractController { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + public NamespacesController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_GET, METHOD_HEAD, "DELETE" }); + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + String reqMethod = request.getMethod(); + if (METHOD_GET.equals(reqMethod)) { + logger.info("GET namespace list"); + return getExportNamespacesResult(request, response); + } + if (METHOD_HEAD.equals(reqMethod)) { + logger.info("HEAD namespace list"); + return getExportNamespacesResult(request, response); + } + else if ("DELETE".equals(reqMethod)) { + logger.info("DELETE namespaces"); + return getClearNamespacesResult(request, response); + } + + throw new ClientHTTPException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, + "Method not allowed: " + reqMethod); + } + + private ModelAndView getExportNamespacesResult(HttpServletRequest request, HttpServletResponse response) + throws ClientHTTPException, ServerHTTPException + { + final boolean headersOnly = METHOD_HEAD.equals(request.getMethod()); + + Map model = new HashMap(); + if (!headersOnly) { + List columnNames = Arrays.asList("prefix", "namespace"); + List namespaces = new ArrayList(); + + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + final ValueFactory vf = repositoryCon.getValueFactory(); + try { + CloseableIteration iter = repositoryCon.getNamespaces(); + + try { + while (iter.hasNext()) { + Namespace ns = iter.next(); + + Literal prefix = vf.createLiteral(ns.getPrefix()); + Literal namespace = vf.createLiteral(ns.getName()); + + BindingSet bindingSet = new ListBindingSet(columnNames, prefix, namespace); + namespaces.add(bindingSet); + } + } + finally { + iter.close(); + } + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository error: " + e.getMessage(), e); + } + } + model.put(QueryResultView.QUERY_RESULT_KEY, new IteratingTupleQueryResult(columnNames, namespaces)); + } + + TupleQueryResultWriterFactory factory = ProtocolUtil.getAcceptableService(request, response, + TupleQueryResultWriterRegistry.getInstance()); + + model.put(QueryResultView.FILENAME_HINT_KEY, "namespaces"); + model.put(QueryResultView.HEADERS_ONLY, headersOnly); + model.put(QueryResultView.FACTORY_KEY, factory); + + return new ModelAndView(TupleQueryResultView.getInstance(), model); + } + + private ModelAndView getClearNamespacesResult(HttpServletRequest request, HttpServletResponse response) + throws ServerHTTPException + { + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + try { + repositoryCon.clearNamespaces(); + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository error: " + e.getMessage(), e); + } + } + + return new ModelAndView(EmptySuccessView.getInstance()); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/size/SizeController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/size/SizeController.java new file mode 100644 index 00000000000..3e6974e91a8 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/size/SizeController.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.size; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.webapp.views.SimpleResponseView; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.repository.RepositoryInterceptor; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles requests for the size of (set of contexts in) a repository. + * + * @author Herko ter Horst + */ +public class SizeController extends AbstractController { + + public SizeController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_GET, METHOD_HEAD }); + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + ProtocolUtil.logRequestParameters(request); + + Map model = new HashMap(); + final boolean headersOnly = METHOD_HEAD.equals(request.getMethod()); + + if (!headersOnly) { + Repository repository = RepositoryInterceptor.getRepository(request); + + ValueFactory vf = repository.getValueFactory(); + Resource[] contexts = ProtocolUtil.parseContextParam(request, Protocol.CONTEXT_PARAM_NAME, vf); + + long size = -1; + + try { + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + size = repositoryCon.size(contexts); + } + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository error: " + e.getMessage(), e); + } + model.put(SimpleResponseView.CONTENT_KEY, String.valueOf(size)); + } + + return new ModelAndView(SimpleResponseView.getInstance(), model); + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/statements/ExportStatementsView.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/statements/ExportStatementsView.java new file mode 100644 index 00000000000..71bd3b80707 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/statements/ExportStatementsView.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.statements; + +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.repository.RepositoryInterceptor; +import org.eclipse.rdf4j.http.server.repository.transaction.ActiveTransactionRegistry; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.RDFWriterFactory; +import org.springframework.web.servlet.View; + +/** + * View used to export statements. Renders the statements as RDF using a + * serialization specified using a parameter or Accept header. + * + * @author Herko ter Horst + */ +public class ExportStatementsView implements View { + + public static final String SUBJECT_KEY = "subject"; + + public static final String PREDICATE_KEY = "predicate"; + + public static final String OBJECT_KEY = "object"; + + public static final String CONTEXTS_KEY = "contexts"; + + public static final String USE_INFERENCING_KEY = "useInferencing"; + + public static final String CONNECTION_KEY = "connection"; + + public static final String TRANSACTION_ID_KEY = "transactionID"; + + public static final String FACTORY_KEY = "factory"; + + public static final String HEADERS_ONLY = "headersOnly"; + + private static final ExportStatementsView INSTANCE = new ExportStatementsView(); + + public static ExportStatementsView getInstance() { + return INSTANCE; + } + + private ExportStatementsView() { + } + + public String getContentType() { + return null; + } + + @SuppressWarnings("rawtypes") + public void render(Map model, HttpServletRequest request, HttpServletResponse response) + throws Exception + { + UUID txnId = null; + try { + txnId = (UUID)model.get(TRANSACTION_ID_KEY); + Resource subj = (Resource)model.get(SUBJECT_KEY); + IRI pred = (IRI)model.get(PREDICATE_KEY); + Value obj = (Value)model.get(OBJECT_KEY); + Resource[] contexts = (Resource[])model.get(CONTEXTS_KEY); + boolean useInferencing = (Boolean)model.get(USE_INFERENCING_KEY); + RepositoryConnection conn = (RepositoryConnection)model.get(CONNECTION_KEY); + + boolean headersOnly = (Boolean)model.get(HEADERS_ONLY); + + RDFWriterFactory rdfWriterFactory = (RDFWriterFactory)model.get(FACTORY_KEY); + + RDFFormat rdfFormat = rdfWriterFactory.getRDFFormat(); + + try { + OutputStream out = response.getOutputStream(); + RDFWriter rdfWriter = rdfWriterFactory.getWriter(out); + + response.setStatus(SC_OK); + + String mimeType = rdfFormat.getDefaultMIMEType(); + if (rdfFormat.hasCharset()) { + Charset charset = rdfFormat.getCharset(); + mimeType += "; charset=" + charset.name(); + } + response.setContentType(mimeType); + + String filename = "statements"; + if (rdfFormat.getDefaultFileExtension() != null) { + filename += "." + rdfFormat.getDefaultFileExtension(); + } + response.setHeader("Content-Disposition", "attachment; filename=" + filename); + + if (!headersOnly) { + if (conn == null) { + conn = RepositoryInterceptor.getRepositoryConnection(request); + } + synchronized (conn) { + conn.exportStatements(subj, pred, obj, useInferencing, rdfWriter, contexts); + } + } + out.close(); + } + catch (RDFHandlerException e) { + throw new ServerHTTPException("Serialization error: " + e.getMessage(), e); + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository error: " + e.getMessage(), e); + } + } + finally { + if (txnId != null) { + ActiveTransactionRegistry.INSTANCE.returnTransactionConnection(txnId); + } + } + } + +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/statements/StatementsController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/statements/StatementsController.java new file mode 100644 index 00000000000..d74a8203d50 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/statements/StatementsController.java @@ -0,0 +1,497 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.statements; + +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE; +import static org.eclipse.rdf4j.http.protocol.Protocol.BASEURI_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.BINDING_PREFIX; +import static org.eclipse.rdf4j.http.protocol.Protocol.CONTEXT_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.INCLUDE_INFERRED_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.INSERT_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.OBJECT_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.PREDICATE_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.QUERY_LANGUAGE_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.REMOVE_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.SUBJECT_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.USING_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.USING_NAMED_GRAPH_PARAM_NAME; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.eclipse.rdf4j.common.webapp.util.HttpServerUtil; +import org.eclipse.rdf4j.common.webapp.views.EmptySuccessView; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.protocol.error.ErrorInfo; +import org.eclipse.rdf4j.http.protocol.error.ErrorType; +import org.eclipse.rdf4j.http.protocol.transaction.TransactionReader; +import org.eclipse.rdf4j.http.protocol.transaction.operations.TransactionOperation; +import org.eclipse.rdf4j.http.server.ClientHTTPException; +import org.eclipse.rdf4j.http.server.HTTPException; +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.repository.RepositoryInterceptor; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.Update; +import org.eclipse.rdf4j.query.UpdateExecutionException; +import org.eclipse.rdf4j.query.impl.SimpleDataset; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFWriterFactory; +import org.eclipse.rdf4j.rio.RDFWriterRegistry; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.UnsupportedRDFormatException; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +/** + * Handles requests for manipulating the statements in a repository. + * + * @author Herko ter Horst + * @author Arjohn Kampman + */ +public class StatementsController extends AbstractController { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + public StatementsController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_GET, METHOD_POST, METHOD_HEAD, "PUT", "DELETE" }); + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + ModelAndView result; + + Repository repository = RepositoryInterceptor.getRepository(request); + + String reqMethod = request.getMethod(); + + if (METHOD_GET.equals(reqMethod)) { + logger.info("GET statements"); + result = getExportStatementsResult(repository, request, response); + } + else if (METHOD_HEAD.equals(reqMethod)) { + logger.info("HEAD statements"); + result = getExportStatementsResult(repository, request, response); + } + else if (METHOD_POST.equals(reqMethod)) { + String mimeType = HttpServerUtil.getMIMEType(request.getContentType()); + + if (Protocol.TXN_MIME_TYPE.equals(mimeType)) { + logger.info("POST transaction to repository"); + result = getTransactionResultResult(repository, request, response); + } + else if (Protocol.SPARQL_UPDATE_MIME_TYPE.equals(mimeType) + || request.getParameterMap().containsKey(Protocol.UPDATE_PARAM_NAME)) + { + logger.info("POST SPARQL update request to repository"); + result = getSparqlUpdateResult(repository, request, response); + } + else { + logger.info("POST data to repository"); + result = getAddDataResult(repository, request, response, false); + } + } + else if ("PUT".equals(reqMethod)) { + logger.info("PUT data in repository"); + result = getAddDataResult(repository, request, response, true); + } + else if ("DELETE".equals(reqMethod)) { + logger.info("DELETE data from repository"); + result = getDeleteDataResult(repository, request, response); + } + else { + throw new ClientHTTPException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method not allowed: " + + reqMethod); + } + + return result; + } + + private ModelAndView getSparqlUpdateResult(Repository repository, HttpServletRequest request, + HttpServletResponse response) + throws ServerHTTPException, ClientHTTPException, HTTPException + { + ProtocolUtil.logRequestParameters(request); + + String mimeType = HttpServerUtil.getMIMEType(request.getContentType()); + + String sparqlUpdateString; + if (Protocol.SPARQL_UPDATE_MIME_TYPE.equals(mimeType)) { + // The query should be the entire body + try { + sparqlUpdateString = IOUtils.toString(request.getReader()); + } + catch (IOException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Error reading request message body", e); + } + if (sparqlUpdateString.isEmpty()) + sparqlUpdateString = null; + } + else { + sparqlUpdateString = request.getParameterValues(Protocol.UPDATE_PARAM_NAME)[0]; + } + + // default query language is SPARQL + QueryLanguage queryLn = QueryLanguage.SPARQL; + + String queryLnStr = request.getParameter(QUERY_LANGUAGE_PARAM_NAME); + logger.debug("query language param = {}", queryLnStr); + + if (queryLnStr != null) { + queryLn = QueryLanguage.valueOf(queryLnStr); + + if (queryLn == null) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Unknown query language: " + queryLnStr); + } + } + + String baseURI = request.getParameter(Protocol.BASEURI_PARAM_NAME); + + // determine if inferred triples should be included in query evaluation + boolean includeInferred = ProtocolUtil.parseBooleanParam(request, INCLUDE_INFERRED_PARAM_NAME, true); + + // build a dataset, if specified + String[] defaultRemoveGraphURIs = request.getParameterValues(REMOVE_GRAPH_PARAM_NAME); + String[] defaultInsertGraphURIs = request.getParameterValues(INSERT_GRAPH_PARAM_NAME); + String[] defaultGraphURIs = request.getParameterValues(USING_GRAPH_PARAM_NAME); + String[] namedGraphURIs = request.getParameterValues(USING_NAMED_GRAPH_PARAM_NAME); + + SimpleDataset dataset = new SimpleDataset(); + + if (defaultRemoveGraphURIs != null) { + for (String graphURI : defaultRemoveGraphURIs) { + try { + IRI uri = createURIOrNull(repository, graphURI); + dataset.addDefaultRemoveGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Illegal URI for default remove graph: " + + graphURI); + } + } + } + + if (defaultInsertGraphURIs != null && defaultInsertGraphURIs.length > 0) { + String graphURI = defaultInsertGraphURIs[0]; + try { + IRI uri = createURIOrNull(repository, graphURI); + dataset.setDefaultInsertGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Illegal URI for default insert graph: " + graphURI); + } + } + + if (defaultGraphURIs != null) { + for (String defaultGraphURI : defaultGraphURIs) { + try { + IRI uri = createURIOrNull(repository, defaultGraphURI); + dataset.addDefaultGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Illegal URI for default graph: " + + defaultGraphURI); + } + } + } + + if (namedGraphURIs != null) { + for (String namedGraphURI : namedGraphURIs) { + try { + IRI uri = createURIOrNull(repository, namedGraphURI); + dataset.addNamedGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Illegal URI for named graph: " + namedGraphURI); + } + } + } + + try { + + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + Update update = repositoryCon.prepareUpdate(queryLn, sparqlUpdateString, baseURI); + + update.setIncludeInferred(includeInferred); + + if (dataset != null) { + update.setDataset(dataset); + } + + // determine if any variable bindings have been set on this update. + @SuppressWarnings("unchecked") + Enumeration parameterNames = request.getParameterNames(); + + while (parameterNames.hasMoreElements()) { + String parameterName = parameterNames.nextElement(); + + if (parameterName.startsWith(BINDING_PREFIX) + && parameterName.length() > BINDING_PREFIX.length()) + { + String bindingName = parameterName.substring(BINDING_PREFIX.length()); + Value bindingValue = ProtocolUtil.parseValueParam(request, parameterName, + repository.getValueFactory()); + update.setBinding(bindingName, bindingValue); + } + } + + update.execute(); + } + + return new ModelAndView(EmptySuccessView.getInstance()); + } + catch (UpdateExecutionException e) { + if (e.getCause() != null && e.getCause() instanceof HTTPException) { + // custom signal from the backend, throw as HTTPException directly + // (see SES-1016). + throw (HTTPException)e.getCause(); + } + else { + throw new ServerHTTPException("Repository update error: " + e.getMessage(), e); + } + } + catch (RepositoryException e) { + if (e.getCause() != null && e.getCause() instanceof HTTPException) { + // custom signal from the backend, throw as HTTPException directly + // (see SES-1016). + throw (HTTPException)e.getCause(); + } + else { + throw new ServerHTTPException("Repository update error: " + e.getMessage(), e); + } + } + catch (MalformedQueryException e) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.MALFORMED_QUERY, e.getMessage()); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + } + + private IRI createURIOrNull(Repository repository, String graphURI) { + if ("null".equals(graphURI)) + return null; + return repository.getValueFactory().createIRI(graphURI); + } + + /** + * Get all statements and export them as RDF. + * + * @return a model and view for exporting the statements. + */ + private ModelAndView getExportStatementsResult(Repository repository, HttpServletRequest request, + HttpServletResponse response) + throws ClientHTTPException + { + ProtocolUtil.logRequestParameters(request); + + ValueFactory vf = repository.getValueFactory(); + + Resource subj = ProtocolUtil.parseResourceParam(request, SUBJECT_PARAM_NAME, vf); + IRI pred = ProtocolUtil.parseURIParam(request, PREDICATE_PARAM_NAME, vf); + Value obj = ProtocolUtil.parseValueParam(request, OBJECT_PARAM_NAME, vf); + Resource[] contexts = ProtocolUtil.parseContextParam(request, CONTEXT_PARAM_NAME, vf); + boolean useInferencing = ProtocolUtil.parseBooleanParam(request, INCLUDE_INFERRED_PARAM_NAME, true); + + RDFWriterFactory rdfWriterFactory = ProtocolUtil.getAcceptableService(request, response, + RDFWriterRegistry.getInstance()); + + Map model = new HashMap(); + model.put(ExportStatementsView.SUBJECT_KEY, subj); + model.put(ExportStatementsView.PREDICATE_KEY, pred); + model.put(ExportStatementsView.OBJECT_KEY, obj); + model.put(ExportStatementsView.CONTEXTS_KEY, contexts); + model.put(ExportStatementsView.USE_INFERENCING_KEY, Boolean.valueOf(useInferencing)); + model.put(ExportStatementsView.FACTORY_KEY, rdfWriterFactory); + model.put(ExportStatementsView.HEADERS_ONLY, METHOD_HEAD.equals(request.getMethod())); + return new ModelAndView(ExportStatementsView.getInstance(), model); + } + + /** + * Process several actions as a transaction. + */ + private ModelAndView getTransactionResultResult(Repository repository, HttpServletRequest request, + HttpServletResponse response) + throws IOException, ClientHTTPException, ServerHTTPException, HTTPException + { + InputStream in = request.getInputStream(); + try { + logger.debug("Processing transaction..."); + + TransactionReader reader = new TransactionReader(); + Iterable txn = reader.parse(in); + + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + repositoryCon.begin(); + + for (TransactionOperation op : txn) { + op.execute(repositoryCon); + } + + repositoryCon.commit(); + } + logger.debug("Transaction processed "); + + return new ModelAndView(EmptySuccessView.getInstance()); + } + catch (SAXParseException e) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.MALFORMED_DATA, e.getMessage()); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + catch (SAXException e) { + throw new ServerHTTPException("Failed to parse transaction data: " + e.getMessage(), e); + } + catch (IOException e) { + throw new ServerHTTPException("Failed to read data: " + e.getMessage(), e); + } + catch (RepositoryException e) { + if (e.getCause() != null && e.getCause() instanceof HTTPException) { + // custom signal from the backend, throw as HTTPException directly + // (see SES-1016). + throw (HTTPException)e.getCause(); + } + else { + throw new ServerHTTPException("Repository update error: " + e.getMessage(), e); + } + } + } + + /** + * Upload data to the repository. + */ + private ModelAndView getAddDataResult(Repository repository, HttpServletRequest request, + HttpServletResponse response, boolean replaceCurrent) + throws IOException, ServerHTTPException, ClientHTTPException, HTTPException + { + ProtocolUtil.logRequestParameters(request); + + String mimeType = HttpServerUtil.getMIMEType(request.getContentType()); + + RDFFormat rdfFormat = Rio.getParserFormatForMIMEType(mimeType).orElseThrow( + () -> new ClientHTTPException(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported MIME type: " + mimeType)); + + ValueFactory vf = repository.getValueFactory(); + + Resource[] contexts = ProtocolUtil.parseContextParam(request, CONTEXT_PARAM_NAME, vf); + IRI baseURI = ProtocolUtil.parseURIParam(request, BASEURI_PARAM_NAME, vf); + final boolean preserveNodeIds = ProtocolUtil.parseBooleanParam(request, + Protocol.PRESERVE_BNODE_ID_PARAM_NAME, false); + + if (baseURI == null) { + baseURI = vf.createIRI("foo:bar"); + logger.info("no base URI specified, using dummy '{}'", baseURI); + } + + InputStream in = request.getInputStream(); + try { + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + if (!repositoryCon.isActive()) { + repositoryCon.begin(); + } + + if (preserveNodeIds) { + repositoryCon.getParserConfig().set(BasicParserSettings.PRESERVE_BNODE_IDS, true); + } + + if (replaceCurrent) { + repositoryCon.clear(contexts); + } + repositoryCon.add(in, baseURI.toString(), rdfFormat, contexts); + + repositoryCon.commit(); + } + + return new ModelAndView(EmptySuccessView.getInstance()); + } + catch (UnsupportedRDFormatException e) { + throw new ClientHTTPException(SC_UNSUPPORTED_MEDIA_TYPE, "No RDF parser available for format " + + rdfFormat.getName()); + } + catch (RDFParseException e) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.MALFORMED_DATA, e.getMessage()); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + catch (IOException e) { + throw new ServerHTTPException("Failed to read data: " + e.getMessage(), e); + } + catch (RepositoryException e) { + if (e.getCause() != null && e.getCause() instanceof HTTPException) { + // custom signal from the backend, throw as HTTPException directly + // (see SES-1016). + throw (HTTPException)e.getCause(); + } + else { + throw new ServerHTTPException("Repository update error: " + e.getMessage(), e); + } + } + } + + /** + * Delete data from the repository. + */ + private ModelAndView getDeleteDataResult(Repository repository, HttpServletRequest request, + HttpServletResponse response) + throws ServerHTTPException, ClientHTTPException, HTTPException + { + ProtocolUtil.logRequestParameters(request); + + ValueFactory vf = repository.getValueFactory(); + + Resource subj = ProtocolUtil.parseResourceParam(request, SUBJECT_PARAM_NAME, vf); + IRI pred = ProtocolUtil.parseURIParam(request, PREDICATE_PARAM_NAME, vf); + Value obj = ProtocolUtil.parseValueParam(request, OBJECT_PARAM_NAME, vf); + Resource[] contexts = ProtocolUtil.parseContextParam(request, CONTEXT_PARAM_NAME, vf); + + try { + RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); + synchronized (repositoryCon) { + repositoryCon.remove(subj, pred, obj, contexts); + } + + return new ModelAndView(EmptySuccessView.getInstance()); + } + catch (RepositoryException e) { + if (e.getCause() != null && e.getCause() instanceof HTTPException) { + // custom signal from the backend, throw as HTTPException directly + // (see SES-1016). + throw (HTTPException)e.getCause(); + } + else { + throw new ServerHTTPException("Repository update error: " + e.getMessage(), e); + } + } + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/ActiveTransactionRegistry.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/ActiveTransactionRegistry.java new file mode 100644 index 00000000000..986f77d458d --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/ActiveTransactionRegistry.java @@ -0,0 +1,233 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.transaction; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.RemovalCause; +import com.google.common.cache.RemovalListener; +import com.google.common.cache.RemovalNotification; + +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Registry keeping track of active transactions identified by a {@link UUID} + * and the {@link RepositoryConnection} that corresponds to the given + * transaction. + * + * @author Jeen Broekstra + * @since 2.8.0 + */ +public enum ActiveTransactionRegistry { + + /** + * Singleton instance + */ + INSTANCE; + + private final Logger logger = LoggerFactory.getLogger(ActiveTransactionRegistry.class); + + /** + * Configurable system property {@code sesame.server.txn.registry.timeout} + * for specifying the transaction cache timeout (in seconds). + */ + public static final String CACHE_TIMEOUT_PROPERTY = "sesame.server.txn.registry.timeout"; + + /** + * Default timeout setting for transaction cache entries (in seconds). + */ + public final static int DEFAULT_TIMEOUT = 60; + + private final Cache activeConnections; + + static class CacheEntry { + + private final RepositoryConnection connection; + + private final Lock lock = new ReentrantLock(); + + public CacheEntry(RepositoryConnection connection) { + this.connection = connection; + } + + /** + * @return Returns the connection. + */ + public RepositoryConnection getConnection() { + return connection; + } + + /** + * @return Returns the lock. + */ + public Lock getLock() { + return lock; + } + + } + + /** + * private constructor. Access via {@link ActiveTransactionRegistry#INSTANCE} + */ + private ActiveTransactionRegistry() { + int timeout = DEFAULT_TIMEOUT; + + final String configuredValue = System.getProperty(CACHE_TIMEOUT_PROPERTY); + if (configuredValue != null) { + try { + timeout = Integer.parseInt(configuredValue); + } + catch (NumberFormatException e) { + logger.warn("Expected integer value for property {}. Timeout will default to {} seconds. ", + CACHE_TIMEOUT_PROPERTY, DEFAULT_TIMEOUT); + } + } + + activeConnections = initializeCache(timeout, TimeUnit.SECONDS); + } + + private final Cache initializeCache(int timeout, TimeUnit unit) { + return CacheBuilder.newBuilder().removalListener(new RemovalListener() { + + @Override + public void onRemoval(RemovalNotification notification) { + if (RemovalCause.EXPIRED.equals(notification.getCause())) { + logger.warn("transaction registry item {} removed after expiry", notification.getKey()); + CacheEntry entry = notification.getValue(); + try { + entry.getConnection().close(); + } + catch (RepositoryException e) { + // fall through + } + } + else { + logger.debug("transaction {} removed from registry. cause: {}", notification.getKey(), + notification.getCause()); + } + } + }).expireAfterAccess(timeout, unit).build(); + } + + /** + * Register a new transaction with the given id and connection. + * + * @param transactionId + * the transaction id + * @param conn + * the {@link RepositoryConnection} to use for handling the + * transaction. + * @throws RepositoryException + * if a transaction is already registered with the given transaction + * id. + */ + public void register(UUID transactionId, RepositoryConnection conn) + throws RepositoryException + { + synchronized (activeConnections) { + if (activeConnections.getIfPresent(transactionId) == null) { + activeConnections.put(transactionId, new CacheEntry(conn)); + logger.debug("registered transaction {} ", transactionId); + } + else { + logger.error("transaction already registered: {}", transactionId); + throw new RepositoryException( + "transaction with id " + transactionId.toString() + " already registered."); + } + } + } + + /** + * Remove the given transaction from the registry + * + * @param transactionId + * the transaction id + * @throws RepositoryException + * if no registered transaction with the given id could be found. + */ + public void deregister(UUID transactionId) + throws RepositoryException + { + synchronized (activeConnections) { + CacheEntry entry = activeConnections.getIfPresent(transactionId); + if (entry == null) { + throw new RepositoryException( + "transaction with id " + transactionId.toString() + " not registered."); + } + else { + activeConnections.invalidate(transactionId); + final Lock txnLock = entry.getLock(); + txnLock.unlock(); + logger.debug("deregistered transaction {}", transactionId); + } + } + } + + /** + * Obtain the {@link RepositoryConnection} associated with the given + * transaction. This method will block if another thread currently has access + * to the connection. + * + * @param transactionId + * a transaction ID + * @return the RepositoryConnection belonging to this transaction. + * @throws RepositoryException + * if no transaction with the given id is registered. + * @throws InterruptedException + * if the thread is interrupted while acquiring a lock on the + * transaction. + */ + public RepositoryConnection getTransactionConnection(UUID transactionId) + throws RepositoryException, InterruptedException + { + Lock txnLock = null; + synchronized (activeConnections) { + CacheEntry entry = activeConnections.getIfPresent(transactionId); + if (entry == null) { + throw new RepositoryException( + "transaction with id " + transactionId.toString() + " not registered."); + } + + txnLock = entry.getLock(); + } + + txnLock.lockInterruptibly(); + /* Another thread might have deregistered the transaction while we were acquiring the lock */ + final CacheEntry entry = activeConnections.getIfPresent(transactionId); + if (entry == null) { + throw new RepositoryException("transaction with id " + transactionId + " is no longer registered!"); + } + return entry.getConnection(); + } + + /** + * Unlocks the {@link RepositoryConnection} associated with the given + * transaction for use by other threads. If the transaction is no longer + * registered, this will method will exit silently. + * + * @param transactionId + * a transaction identifier. + */ + public void returnTransactionConnection(UUID transactionId) { + + final CacheEntry entry = activeConnections.getIfPresent(transactionId); + + if (entry != null) { + final Lock txnLock = entry.getLock(); + txnLock.unlock(); + } + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionController.java new file mode 100644 index 00000000000..8cf925c7f31 --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionController.java @@ -0,0 +1,766 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.transaction; + +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE; +import static org.eclipse.rdf4j.http.protocol.Protocol.BINDING_PREFIX; +import static org.eclipse.rdf4j.http.protocol.Protocol.CONTEXT_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.DEFAULT_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.INCLUDE_INFERRED_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.INSERT_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.NAMED_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.OBJECT_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.PREDICATE_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.QUERY_LANGUAGE_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.QUERY_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.REMOVE_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.SUBJECT_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.USING_GRAPH_PARAM_NAME; +import static org.eclipse.rdf4j.http.protocol.Protocol.USING_NAMED_GRAPH_PARAM_NAME; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.eclipse.rdf4j.common.lang.FileFormat; +import org.eclipse.rdf4j.common.lang.service.FileFormatServiceRegistry; +import org.eclipse.rdf4j.common.webapp.views.EmptySuccessView; +import org.eclipse.rdf4j.common.webapp.views.SimpleResponseView; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.protocol.Protocol.Action; +import org.eclipse.rdf4j.http.protocol.error.ErrorInfo; +import org.eclipse.rdf4j.http.protocol.error.ErrorType; +import org.eclipse.rdf4j.http.server.ClientHTTPException; +import org.eclipse.rdf4j.http.server.HTTPException; +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.repository.BooleanQueryResultView; +import org.eclipse.rdf4j.http.server.repository.GraphQueryResultView; +import org.eclipse.rdf4j.http.server.repository.QueryResultView; +import org.eclipse.rdf4j.http.server.repository.RepositoryInterceptor; +import org.eclipse.rdf4j.http.server.repository.TupleQueryResultView; +import org.eclipse.rdf4j.http.server.repository.statements.ExportStatementsView; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.SESAME; +import org.eclipse.rdf4j.query.BooleanQuery; +import org.eclipse.rdf4j.query.GraphQuery; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.Query; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryInterruptedException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.query.Update; +import org.eclipse.rdf4j.query.UpdateExecutionException; +import org.eclipse.rdf4j.query.impl.SimpleDataset; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultWriterRegistry; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterRegistry; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriterFactory; +import org.eclipse.rdf4j.rio.RDFWriterRegistry; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.helpers.AbstractRDFHandler; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles requests for transaction creation on a repository. + * + * @since 2.8.0 + * @author Jeen Broekstra + */ +public class TransactionController extends AbstractController { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + public TransactionController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_POST, "PUT", "DELETE" }); + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + ModelAndView result; + + String reqMethod = request.getMethod(); + UUID transactionId = getTransactionID(request); + logger.debug("transaction id: {}", transactionId); + logger.debug("request content type: {}", request.getContentType()); + RepositoryConnection connection = ActiveTransactionRegistry.INSTANCE.getTransactionConnection( + transactionId); + + if (connection == null) { + logger.warn("could not find connection for transaction id {}", transactionId); + throw new ClientHTTPException(SC_BAD_REQUEST, + "unable to find registerd connection for transaction id '" + transactionId + "'"); + } + + // if no action is specified in the request, it's a rollback (since it's + // the only txn operation that does not require the action parameter). + final String actionParam = request.getParameter(Protocol.ACTION_PARAM_NAME); + final Action action = actionParam != null ? Action.valueOf(actionParam) : Action.ROLLBACK; + switch (action) { + case QUERY: + // TODO SES-2238 note that we allow POST requests for backward + // compatibility reasons with earlier + // 2.8.x releases, even though according to the protocol spec only + // PUT is allowed. + if ("PUT".equals(reqMethod) || METHOD_POST.equals(reqMethod)) { + logger.info("{} txn query request", reqMethod); + result = processQuery(connection, transactionId, request, response); + logger.info("{} txn query request finished", reqMethod); + } + else { + throw new ClientHTTPException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, + "Method not allowed: " + reqMethod); + } + break; + case GET: + if ("PUT".equals(reqMethod) || METHOD_POST.equals(reqMethod)) { + logger.info("{} txn get/export statements request", reqMethod); + result = getExportStatementsResult(connection, transactionId, request, response); + logger.info("{} txn get/export statements request finished", reqMethod); + } + else { + throw new ClientHTTPException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, + "Method not allowed: " + reqMethod); + } + break; + case SIZE: + if ("PUT".equals(reqMethod) || METHOD_POST.equals(reqMethod)) { + logger.info("{} txn size request", reqMethod); + result = getSize(connection, transactionId, request, response); + logger.info("{} txn size request finished", reqMethod); + } + else { + throw new ClientHTTPException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, + "Method not allowed: " + reqMethod); + } + break; + default: + // modification operations - we can process these and then + // immediately release the connection back to the registry. + try { + // TODO Action.ROLLBACK check is for backward compatibility with + // older 2.8.x releases only. It's not in the protocol spec. + if ("DELETE".equals(reqMethod) || (action.equals(Action.ROLLBACK) + && ("PUT".equals(reqMethod) || METHOD_POST.equals(reqMethod)))) + { + logger.info("transaction rollback"); + try { + connection.rollback(); + } + finally { + ActiveTransactionRegistry.INSTANCE.deregister(transactionId); + connection.close(); + } + result = new ModelAndView(EmptySuccessView.getInstance()); + logger.info("transaction rollback request finished."); + } + else if ("PUT".equals(reqMethod) || METHOD_POST.equals(reqMethod)) { + // TODO filter for appropriate PUT operations + logger.info("{} txn operation", reqMethod); + result = processModificationOperation(connection, action, request, response); + logger.info("PUT txn operation request finished."); + } + else { + throw new ClientHTTPException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, + "Method not allowed: " + reqMethod); + } + } + finally { + ActiveTransactionRegistry.INSTANCE.returnTransactionConnection(transactionId); + } + break; + } + return result; + } + + private UUID getTransactionID(HttpServletRequest request) + throws ClientHTTPException + { + String pathInfoStr = request.getPathInfo(); + + UUID txnID = null; + + if (pathInfoStr != null && !pathInfoStr.equals("/")) { + String[] pathInfo = pathInfoStr.substring(1).split("/"); + // should be of the form: //transactions/ + if (pathInfo.length == 3) { + try { + txnID = UUID.fromString(pathInfo[2]); + logger.debug("txnID is '{}'", txnID); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "not a valid transaction id: " + pathInfo[2]); + } + } + else { + logger.warn("could not determine transaction id from path info {} ", pathInfoStr); + } + } + + return txnID; + } + + private ModelAndView processModificationOperation(RepositoryConnection conn, Action action, + HttpServletRequest request, HttpServletResponse response) + throws IOException, HTTPException + { + ProtocolUtil.logRequestParameters(request); + + Map model = new HashMap(); + + String baseURI = request.getParameter(Protocol.BASEURI_PARAM_NAME); + if (baseURI == null) { + baseURI = ""; + } + + try { + switch (action) { + case ADD: + conn.add( + request.getInputStream(), + baseURI, + Rio.getParserFormatForMIMEType(request.getContentType()).orElseThrow( + Rio.unsupportedFormat(request.getContentType()))); + break; + case DELETE: + RDFParser parser = Rio.createParser( + Rio.getParserFormatForMIMEType(request.getContentType()).orElseThrow( + Rio.unsupportedFormat(request.getContentType())), conn.getValueFactory()); + parser.setRDFHandler(new WildcardRDFRemover(conn)); + parser.getParserConfig().set(BasicParserSettings.PRESERVE_BNODE_IDS, true); + parser.parse(request.getInputStream(), baseURI); + break; + case UPDATE: + return getSparqlUpdateResult(conn, request, response); + case COMMIT: + conn.commit(); + conn.close(); + ActiveTransactionRegistry.INSTANCE.deregister(getTransactionID(request)); + break; + default: + logger.warn("transaction modification action '{}' not recognized", action); + throw new ClientHTTPException("modification action not recognized: " + action); + } + + model.put(SimpleResponseView.SC_KEY, HttpServletResponse.SC_OK); + return new ModelAndView(SimpleResponseView.getInstance(), model); + } + catch (Exception e) { + if (e instanceof ClientHTTPException) { + throw (ClientHTTPException)e; + } + else { + throw new ServerHTTPException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Transaction handling error: " + e.getMessage(), e); + } + } + } + + private ModelAndView getSize(RepositoryConnection conn, UUID txnId, HttpServletRequest request, + HttpServletResponse response) + throws HTTPException + { + try { + ProtocolUtil.logRequestParameters(request); + + Map model = new HashMap(); + final boolean headersOnly = METHOD_HEAD.equals(request.getMethod()); + + if (!headersOnly) { + Repository repository = RepositoryInterceptor.getRepository(request); + + ValueFactory vf = repository.getValueFactory(); + Resource[] contexts = ProtocolUtil.parseContextParam(request, Protocol.CONTEXT_PARAM_NAME, vf); + + long size = -1; + + try { + size = conn.size(contexts); + } + catch (RepositoryException e) { + throw new ServerHTTPException("Repository error: " + e.getMessage(), e); + } + model.put(SimpleResponseView.CONTENT_KEY, String.valueOf(size)); + } + + return new ModelAndView(SimpleResponseView.getInstance(), model); + } + finally { + ActiveTransactionRegistry.INSTANCE.returnTransactionConnection(txnId); + } + } + + /** + * Get all statements and export them as RDF. + * + * @return a model and view for exporting the statements. + */ + private ModelAndView getExportStatementsResult(RepositoryConnection conn, UUID txnId, + HttpServletRequest request, HttpServletResponse response) + throws ClientHTTPException + { + ProtocolUtil.logRequestParameters(request); + + ValueFactory vf = conn.getValueFactory(); + + Resource subj = ProtocolUtil.parseResourceParam(request, SUBJECT_PARAM_NAME, vf); + IRI pred = ProtocolUtil.parseURIParam(request, PREDICATE_PARAM_NAME, vf); + Value obj = ProtocolUtil.parseValueParam(request, OBJECT_PARAM_NAME, vf); + Resource[] contexts = ProtocolUtil.parseContextParam(request, CONTEXT_PARAM_NAME, vf); + boolean useInferencing = ProtocolUtil.parseBooleanParam(request, INCLUDE_INFERRED_PARAM_NAME, true); + + RDFWriterFactory rdfWriterFactory = ProtocolUtil.getAcceptableService(request, response, + RDFWriterRegistry.getInstance()); + + Map model = new HashMap(); + model.put(ExportStatementsView.SUBJECT_KEY, subj); + model.put(ExportStatementsView.PREDICATE_KEY, pred); + model.put(ExportStatementsView.OBJECT_KEY, obj); + model.put(ExportStatementsView.CONTEXTS_KEY, contexts); + model.put(ExportStatementsView.USE_INFERENCING_KEY, Boolean.valueOf(useInferencing)); + model.put(ExportStatementsView.FACTORY_KEY, rdfWriterFactory); + model.put(ExportStatementsView.HEADERS_ONLY, METHOD_HEAD.equals(request.getMethod())); + model.put(ExportStatementsView.CONNECTION_KEY, conn); + model.put(ExportStatementsView.TRANSACTION_ID_KEY, txnId); + return new ModelAndView(ExportStatementsView.getInstance(), model); + } + + /** + * Evaluates a query on the given connection and returns the resulting + * {@link QueryResultView}. The {@link QueryResultView} will take care of + * correctly releasing the connection back to the + * {@link ActiveTransactionRegistry}, after fully rendering the query result + * for sending over the wire. + */ + private ModelAndView processQuery(RepositoryConnection conn, UUID txnId, HttpServletRequest request, + HttpServletResponse response) + throws IOException, HTTPException + { + String queryStr = null; + final String contentType = request.getContentType(); + if (contentType != null && contentType.contains(Protocol.SPARQL_QUERY_MIME_TYPE)) { + final String encoding = request.getCharacterEncoding() != null ? request.getCharacterEncoding() : "UTF-8"; + queryStr = IOUtils.toString(request.getInputStream(), encoding); + } + else { + queryStr = request.getParameter(QUERY_PARAM_NAME); + } + + Query query = getQuery(conn, queryStr, request, response); + + View view; + Object queryResult; + FileFormatServiceRegistry registry; + + try { + if (query instanceof TupleQuery) { + TupleQuery tQuery = (TupleQuery)query; + + queryResult = tQuery.evaluate(); + registry = TupleQueryResultWriterRegistry.getInstance(); + view = TupleQueryResultView.getInstance(); + } + else if (query instanceof GraphQuery) { + GraphQuery gQuery = (GraphQuery)query; + + queryResult = gQuery.evaluate(); + registry = RDFWriterRegistry.getInstance(); + view = GraphQueryResultView.getInstance(); + } + else if (query instanceof BooleanQuery) { + BooleanQuery bQuery = (BooleanQuery)query; + + queryResult = bQuery.evaluate(); + registry = BooleanQueryResultWriterRegistry.getInstance(); + view = BooleanQueryResultView.getInstance(); + } + else { + throw new ClientHTTPException(SC_BAD_REQUEST, + "Unsupported query type: " + query.getClass().getName()); + } + } + catch (QueryInterruptedException e) { + logger.info("Query interrupted", e); + ActiveTransactionRegistry.INSTANCE.returnTransactionConnection(txnId); + throw new ServerHTTPException(SC_SERVICE_UNAVAILABLE, "Query evaluation took too long"); + } + catch (QueryEvaluationException e) { + logger.info("Query evaluation error", e); + ActiveTransactionRegistry.INSTANCE.returnTransactionConnection(txnId); + if (e.getCause() != null && e.getCause() instanceof HTTPException) { + // custom signal from the backend, throw as HTTPException + // directly (see SES-1016). + throw (HTTPException)e.getCause(); + } + else { + throw new ServerHTTPException("Query evaluation error: " + e.getMessage()); + } + } + Object factory = ProtocolUtil.getAcceptableService(request, response, registry); + + Map model = new HashMap(); + model.put(QueryResultView.FILENAME_HINT_KEY, "query-result"); + model.put(QueryResultView.QUERY_RESULT_KEY, queryResult); + model.put(QueryResultView.FACTORY_KEY, factory); + model.put(QueryResultView.HEADERS_ONLY, false); // TODO needed for HEAD + // requests. + model.put(QueryResultView.TRANSACTION_ID_KEY, txnId); + return new ModelAndView(view, model); + } + + private Query getQuery(RepositoryConnection repositoryCon, String queryStr, HttpServletRequest request, + HttpServletResponse response) + throws IOException, ClientHTTPException + { + Query result = null; + + // default query language is SPARQL + QueryLanguage queryLn = QueryLanguage.SPARQL; + + String queryLnStr = request.getParameter(QUERY_LANGUAGE_PARAM_NAME); + logger.debug("query language param = {}", queryLnStr); + + if (queryLnStr != null) { + queryLn = QueryLanguage.valueOf(queryLnStr); + + if (queryLn == null) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Unknown query language: " + queryLnStr); + } + } + + String baseURI = request.getParameter(Protocol.BASEURI_PARAM_NAME); + + // determine if inferred triples should be included in query evaluation + boolean includeInferred = ProtocolUtil.parseBooleanParam(request, INCLUDE_INFERRED_PARAM_NAME, true); + + String timeout = request.getParameter(Protocol.TIMEOUT_PARAM_NAME); + int maxQueryTime = 0; + if (timeout != null) { + try { + maxQueryTime = Integer.parseInt(timeout); + } + catch (NumberFormatException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Invalid timeout value: " + timeout); + } + } + + // build a dataset, if specified + String[] defaultGraphURIs = request.getParameterValues(DEFAULT_GRAPH_PARAM_NAME); + String[] namedGraphURIs = request.getParameterValues(NAMED_GRAPH_PARAM_NAME); + + SimpleDataset dataset = null; + if (defaultGraphURIs != null || namedGraphURIs != null) { + dataset = new SimpleDataset(); + + if (defaultGraphURIs != null) { + for (String defaultGraphURI : defaultGraphURIs) { + try { + IRI uri = null; + if (!"null".equals(defaultGraphURI)) { + uri = repositoryCon.getValueFactory().createIRI(defaultGraphURI); + } + dataset.addDefaultGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, + "Illegal URI for default graph: " + defaultGraphURI); + } + } + } + + if (namedGraphURIs != null) { + for (String namedGraphURI : namedGraphURIs) { + try { + IRI uri = null; + if (!"null".equals(namedGraphURI)) { + uri = repositoryCon.getValueFactory().createIRI(namedGraphURI); + } + dataset.addNamedGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, + "Illegal URI for named graph: " + namedGraphURI); + } + } + } + } + + try { + result = repositoryCon.prepareQuery(queryLn, queryStr, baseURI); + + result.setIncludeInferred(includeInferred); + + if (maxQueryTime > 0) { + result.setMaxQueryTime(maxQueryTime); + } + + if (dataset != null) { + result.setDataset(dataset); + } + + // determine if any variable bindings have been set on this query. + @SuppressWarnings("unchecked") + Enumeration parameterNames = request.getParameterNames(); + + while (parameterNames.hasMoreElements()) { + String parameterName = parameterNames.nextElement(); + + if (parameterName.startsWith(BINDING_PREFIX) + && parameterName.length() > BINDING_PREFIX.length()) + { + String bindingName = parameterName.substring(BINDING_PREFIX.length()); + Value bindingValue = ProtocolUtil.parseValueParam(request, parameterName, + repositoryCon.getValueFactory()); + result.setBinding(bindingName, bindingValue); + } + } + } + catch (UnsupportedQueryLanguageException e) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.UNSUPPORTED_QUERY_LANGUAGE, queryLn.getName()); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + catch (MalformedQueryException e) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.MALFORMED_QUERY, e.getMessage()); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + catch (RepositoryException e) { + logger.error("Repository error", e); + response.sendError(SC_INTERNAL_SERVER_ERROR); + } + + return result; + } + + private ModelAndView getSparqlUpdateResult(RepositoryConnection conn, HttpServletRequest request, + HttpServletResponse response) + throws ServerHTTPException, ClientHTTPException, HTTPException + { + String sparqlUpdateString = null; + final String contentType = request.getContentType(); + if (contentType != null && contentType.contains(Protocol.SPARQL_UPDATE_MIME_TYPE)) { + try { + final String encoding = request.getCharacterEncoding() != null ? request.getCharacterEncoding() : "UTF-8"; + sparqlUpdateString = IOUtils.toString(request.getInputStream(), encoding); + } + catch (IOException e) { + logger.warn("error reading sparql update string from request body", e); + throw new ClientHTTPException(SC_BAD_REQUEST, + "could not read SPARQL update string from body: " + e.getMessage()); + } + } + else { + sparqlUpdateString = request.getParameter(Protocol.UPDATE_PARAM_NAME); + } + + logger.debug("SPARQL update string: {}", sparqlUpdateString); + + // default query language is SPARQL + QueryLanguage queryLn = QueryLanguage.SPARQL; + + String queryLnStr = request.getParameter(QUERY_LANGUAGE_PARAM_NAME); + logger.debug("query language param = {}", queryLnStr); + + if (queryLnStr != null) { + queryLn = QueryLanguage.valueOf(queryLnStr); + + if (queryLn == null) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Unknown query language: " + queryLnStr); + } + } + + String baseURI = request.getParameter(Protocol.BASEURI_PARAM_NAME); + + // determine if inferred triples should be included in query evaluation + boolean includeInferred = ProtocolUtil.parseBooleanParam(request, INCLUDE_INFERRED_PARAM_NAME, true); + + // build a dataset, if specified + String[] defaultRemoveGraphURIs = request.getParameterValues(REMOVE_GRAPH_PARAM_NAME); + String[] defaultInsertGraphURIs = request.getParameterValues(INSERT_GRAPH_PARAM_NAME); + String[] defaultGraphURIs = request.getParameterValues(USING_GRAPH_PARAM_NAME); + String[] namedGraphURIs = request.getParameterValues(USING_NAMED_GRAPH_PARAM_NAME); + + SimpleDataset dataset = new SimpleDataset(); + + if (defaultRemoveGraphURIs != null) { + for (String graphURI : defaultRemoveGraphURIs) { + try { + IRI uri = null; + if (!"null".equals(graphURI)) { + uri = conn.getValueFactory().createIRI(graphURI); + } + dataset.addDefaultRemoveGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, + "Illegal URI for default remove graph: " + graphURI); + } + } + } + + if (defaultInsertGraphURIs != null && defaultInsertGraphURIs.length > 0) { + String graphURI = defaultInsertGraphURIs[0]; + try { + IRI uri = null; + if (!"null".equals(graphURI)) { + uri = conn.getValueFactory().createIRI(graphURI); + } + dataset.setDefaultInsertGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, + "Illegal URI for default insert graph: " + graphURI); + } + } + + if (defaultGraphURIs != null) { + for (String defaultGraphURI : defaultGraphURIs) { + try { + IRI uri = null; + if (!"null".equals(defaultGraphURI)) { + uri = conn.getValueFactory().createIRI(defaultGraphURI); + } + dataset.addDefaultGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, + "Illegal URI for default graph: " + defaultGraphURI); + } + } + } + + if (namedGraphURIs != null) { + for (String namedGraphURI : namedGraphURIs) { + try { + IRI uri = null; + if (!"null".equals(namedGraphURI)) { + uri = conn.getValueFactory().createIRI(namedGraphURI); + } + dataset.addNamedGraph(uri); + } + catch (IllegalArgumentException e) { + throw new ClientHTTPException(SC_BAD_REQUEST, "Illegal URI for named graph: " + namedGraphURI); + } + } + } + + try { + Update update = conn.prepareUpdate(queryLn, sparqlUpdateString, baseURI); + + update.setIncludeInferred(includeInferred); + + if (dataset != null) { + update.setDataset(dataset); + } + + // determine if any variable bindings have been set on this update. + @SuppressWarnings("unchecked") + Enumeration parameterNames = request.getParameterNames(); + + while (parameterNames.hasMoreElements()) { + String parameterName = parameterNames.nextElement(); + + if (parameterName.startsWith(BINDING_PREFIX) + && parameterName.length() > BINDING_PREFIX.length()) + { + String bindingName = parameterName.substring(BINDING_PREFIX.length()); + Value bindingValue = ProtocolUtil.parseValueParam(request, parameterName, + conn.getValueFactory()); + update.setBinding(bindingName, bindingValue); + } + } + + update.execute(); + + return new ModelAndView(EmptySuccessView.getInstance()); + } + catch (UpdateExecutionException e) { + if (e.getCause() != null && e.getCause() instanceof HTTPException) { + // custom signal from the backend, throw as HTTPException directly + // (see SES-1016). + throw (HTTPException)e.getCause(); + } + else { + throw new ServerHTTPException("Repository update error: " + e.getMessage(), e); + } + } + catch (RepositoryException e) { + if (e.getCause() != null && e.getCause() instanceof HTTPException) { + // custom signal from the backend, throw as HTTPException directly + // (see SES-1016). + throw (HTTPException)e.getCause(); + } + else { + throw new ServerHTTPException("Repository update error: " + e.getMessage(), e); + } + } + catch (MalformedQueryException e) { + ErrorInfo errInfo = new ErrorInfo(ErrorType.MALFORMED_QUERY, e.getMessage()); + throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); + } + } + + private static class WildcardRDFRemover extends AbstractRDFHandler { + + private final RepositoryConnection conn; + + public WildcardRDFRemover(RepositoryConnection conn) { + super(); + this.conn = conn; + } + + @Override + public void handleStatement(Statement st) + throws RDFHandlerException + { + Resource subject = SESAME.WILDCARD.equals(st.getSubject()) ? null : st.getSubject(); + IRI predicate = SESAME.WILDCARD.equals(st.getPredicate()) ? null : st.getPredicate(); + Value object = SESAME.WILDCARD.equals(st.getObject()) ? null : st.getObject(); + Resource context = st.getContext(); + try { + if (context != null) { + conn.remove(subject, predicate, object, st.getContext()); + } + else { + conn.remove(subject, predicate, object); + } + } + catch (RepositoryException e) { + throw new RDFHandlerException(e); + } + } + + } +} diff --git a/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionStartController.java b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionStartController.java new file mode 100644 index 00000000000..b6a2e4de36b --- /dev/null +++ b/core/http/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionStartController.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server.repository.transaction; + +import static javax.servlet.http.HttpServletResponse.SC_CREATED; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.IsolationLevels; +import org.eclipse.rdf4j.common.webapp.views.SimpleResponseView; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.http.server.ClientHTTPException; +import org.eclipse.rdf4j.http.server.ProtocolUtil; +import org.eclipse.rdf4j.http.server.ServerHTTPException; +import org.eclipse.rdf4j.http.server.repository.RepositoryInterceptor; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.BindingAssigner; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.rio.ParserConfig; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.eclipse.rdf4j.rio.helpers.RioSettingImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +/** + * Handles requests for transaction creation on a repository. + * + * @since 2.8.0 + * @author Jeen Broekstra + */ +public class TransactionStartController extends AbstractController { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + public TransactionStartController() + throws ApplicationContextException + { + setSupportedMethods(new String[] { METHOD_POST }); + } + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) + throws Exception + { + ModelAndView result; + + Repository repository = RepositoryInterceptor.getRepository(request); + + String reqMethod = request.getMethod(); + + if (METHOD_POST.equals(reqMethod)) { + logger.info("POST transaction start"); + result = startTransaction(repository, request, response); + logger.info("transaction started"); + } + else { + throw new ClientHTTPException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method not allowed: " + + reqMethod); + } + return result; + } + + private ModelAndView startTransaction(Repository repository, HttpServletRequest request, + HttpServletResponse response) + throws IOException, ClientHTTPException, ServerHTTPException + { + ProtocolUtil.logRequestParameters(request); + Map model = new HashMap(); + + IsolationLevel isolationLevel = null; + final String isolationLevelString = request.getParameter(Protocol.ISOLATION_LEVEL_PARAM_NAME); + if (isolationLevelString != null) { + final IRI level = SimpleValueFactory.getInstance().createIRI(isolationLevelString); + + // FIXME this needs to be adapted to accommodate custom isolation levels + // from third party stores. + for (IsolationLevel standardLevel : IsolationLevels.values()) { + if (standardLevel.getURI().equals(level)) { + isolationLevel = standardLevel; + break; + } + } + } + + try { + RepositoryConnection conn = repository.getConnection(); + + ParserConfig config = conn.getParserConfig(); + config.set(BasicParserSettings.PRESERVE_BNODE_IDS, true); + config.addNonFatalError(BasicParserSettings.VERIFY_DATATYPE_VALUES); + config.addNonFatalError(BasicParserSettings.VERIFY_LANGUAGE_TAGS); + conn.begin(isolationLevel); + UUID txnId = UUID.randomUUID(); + + ActiveTransactionRegistry.INSTANCE.register(txnId, conn); + model.put(SimpleResponseView.SC_KEY, SC_CREATED); + final StringBuffer txnURL = request.getRequestURL(); + txnURL.append("/" + txnId.toString()); + Map customHeaders = new HashMap(); + customHeaders.put("Location", txnURL.toString()); + model.put(SimpleResponseView.CUSTOM_HEADERS_KEY, customHeaders); + return new ModelAndView(SimpleResponseView.getInstance(), model); + } + catch (RepositoryException e) { + throw new ServerHTTPException("Transaction start error: " + e.getMessage(), e); + } + } + +} diff --git a/core/http/server-spring/src/test/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationTest.java b/core/http/server-spring/src/test/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationTest.java new file mode 100644 index 00000000000..aca1eb6307b --- /dev/null +++ b/core/http/server-spring/src/test/java/org/eclipse/rdf4j/common/webapp/navigation/NavigationTest.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.navigation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.common.webapp.navigation.Group; +import org.eclipse.rdf4j.common.webapp.navigation.NavigationModel; +import org.eclipse.rdf4j.common.webapp.navigation.View; +import org.junit.Before; +import org.junit.Test; + +public class NavigationTest { + + private NavigationModel model = null; + + @Before + public void setUp() { + model = new NavigationModel(); + List navigationModelLocations = new ArrayList(); + navigationModelLocations.add("/navigation.xml"); + model.setNavigationModels(navigationModelLocations); + } + + @Test + public void testParse() { + assertNotNull("Parsed model is null", model); + assertEquals("Model should have one group", 1, model.getGroups().size()); + Group systemGroup = model.getGroups().get(0); + assertEquals("system group should have 1 subgroup", 1, systemGroup.getGroups().size()); + assertEquals("system group should have 2 views", 2, systemGroup.getViews().size()); + View loggingView = systemGroup.getViews().get(1); + assertFalse("logging view should not be hidden", loggingView.isHidden()); + assertTrue("logging view should be enabled", loggingView.isEnabled()); + assertEquals("Path for logging is not correct", "/system/logging.view", loggingView.getPath()); + assertEquals("Icon for logging is not correct", "/images/icons/system_logging.png", loggingView.getIcon()); + assertEquals("I18N for logging is not correct", "system.logging.title", loggingView.getI18n()); + Group loggingGroup = systemGroup.getGroups().get(0); + assertEquals("logging subgroup should have 1 views", 1, loggingGroup.getViews().size()); + assertTrue("logging subgroup should be hidden", loggingGroup.isHidden()); + assertTrue("logging subgroup should be enabled", loggingGroup.isEnabled()); + View loggingOverview = loggingGroup.getViews().get(0); + assertFalse("logging overview should be disabled", loggingOverview.isEnabled()); + } + + @Test + public void testFind() { + assertNotNull("Find should have succeeded", model.findView("/system/logging/overview.view")); + assertNull("Find should not have succeeded", model.findView("/system/logging/bogus.view")); + } +} diff --git a/core/http/server-spring/src/test/java/org/eclipse/rdf4j/common/webapp/util/HttpServerUtilTest.java b/core/http/server-spring/src/test/java/org/eclipse/rdf4j/common/webapp/util/HttpServerUtilTest.java new file mode 100644 index 00000000000..93f331f1c4f --- /dev/null +++ b/core/http/server-spring/src/test/java/org/eclipse/rdf4j/common/webapp/util/HttpServerUtilTest.java @@ -0,0 +1,423 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.webapp.util; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletInputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpSession; + +import org.eclipse.rdf4j.common.lang.FileFormat; +import org.eclipse.rdf4j.common.lang.service.FileFormatServiceRegistry; +import org.eclipse.rdf4j.common.webapp.util.HttpServerUtil; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterRegistry; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class HttpServerUtilTest { + + private ArrayList tupleQueryMimeTypes; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + FileFormatServiceRegistry registry = TupleQueryResultWriterRegistry.getInstance(); + + tupleQueryMimeTypes = new ArrayList(16); + for (FileFormat format : registry.getKeys()) { + tupleQueryMimeTypes.addAll(format.getMIMETypes()); + } + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.common.webapp.util.HttpServerUtil#selectPreferredMIMEType(java.util.Iterator, javax.servlet.http.HttpServletRequest)} + * . + */ + @Test + public void testSelectPreferredMIMEType1() { + + ServletRequestStub testRequest = new ServletRequestStub("application/sparql-results+json, */*"); + + String preferredType = HttpServerUtil.selectPreferredMIMEType(tupleQueryMimeTypes.iterator(), + testRequest); + + assertEquals("application/sparql-results+json", preferredType); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.common.webapp.util.HttpServerUtil#selectPreferredMIMEType(java.util.Iterator, javax.servlet.http.HttpServletRequest)} + * . + */ + @Test + public void testSelectPreferredMIMEType2() { + + ServletRequestStub testRequest = new ServletRequestStub("application/sparql-results+json, */*;q=0.9"); + + String preferredType = HttpServerUtil.selectPreferredMIMEType(tupleQueryMimeTypes.iterator(), + testRequest); + + assertEquals("application/sparql-results+json", preferredType); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.common.webapp.util.HttpServerUtil#selectPreferredMIMEType(java.util.Iterator, javax.servlet.http.HttpServletRequest)} + * . + */ + @Test + public void testSelectPreferredMIMEType3() { + + ServletRequestStub testRequest = new ServletRequestStub("application/xml"); + + String preferredType = HttpServerUtil.selectPreferredMIMEType(tupleQueryMimeTypes.iterator(), + testRequest); + + assertEquals("application/xml", preferredType); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.common.webapp.util.HttpServerUtil#selectPreferredMIMEType(java.util.Iterator, javax.servlet.http.HttpServletRequest)} + * . + */ + @Test + public void testSelectPreferredMIMEType4() { + + ServletRequestStub testRequest = new ServletRequestStub("*/*", "application/sparql-result+xml;q=0.9", + "application/sparql-results+json"); + + String preferredType = HttpServerUtil.selectPreferredMIMEType(tupleQueryMimeTypes.iterator(), + testRequest); + + assertEquals("application/sparql-results+json", preferredType); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.common.webapp.util.HttpServerUtil#selectPreferredMIMEType(java.util.Iterator, javax.servlet.http.HttpServletRequest)} + * . + */ + @Test + public void testSelectPreferredMIMEType5() { + + ServletRequestStub testRequest = new ServletRequestStub("application/*", "application/sparql-results+json"); + + String preferredType = HttpServerUtil.selectPreferredMIMEType(tupleQueryMimeTypes.iterator(), + testRequest); + + assertEquals("application/sparql-results+json", preferredType); + } + class ServletRequestStub implements javax.servlet.http.HttpServletRequest { + + private Enumeration testHeaders; + + public ServletRequestStub(String... testHeaders) { + this.testHeaders = Collections.enumeration(Arrays.asList(testHeaders)); + } + + public Object getAttribute(String name) { + // TODO Auto-generated method stub + return null; + } + + public Enumeration getAttributeNames() { + // TODO Auto-generated method stub + return null; + } + + public String getCharacterEncoding() { + // TODO Auto-generated method stub + return null; + } + + public void setCharacterEncoding(String env) + throws UnsupportedEncodingException + { + // TODO Auto-generated method stub + + } + + public int getContentLength() { + // TODO Auto-generated method stub + return 0; + } + + public String getContentType() { + // TODO Auto-generated method stub + return null; + } + + public ServletInputStream getInputStream() + throws IOException + { + // TODO Auto-generated method stub + return null; + } + + public String getParameter(String name) { + // TODO Auto-generated method stub + return null; + } + + public Enumeration getParameterNames() { + // TODO Auto-generated method stub + return null; + } + + public String[] getParameterValues(String name) { + // TODO Auto-generated method stub + return null; + } + + public Map getParameterMap() { + // TODO Auto-generated method stub + return null; + } + + public String getProtocol() { + // TODO Auto-generated method stub + return null; + } + + public String getScheme() { + // TODO Auto-generated method stub + return null; + } + + public String getServerName() { + // TODO Auto-generated method stub + return null; + } + + public int getServerPort() { + // TODO Auto-generated method stub + return 0; + } + + public BufferedReader getReader() + throws IOException + { + // TODO Auto-generated method stub + return null; + } + + public String getRemoteAddr() { + // TODO Auto-generated method stub + return null; + } + + public String getRemoteHost() { + // TODO Auto-generated method stub + return null; + } + + public void setAttribute(String name, Object o) { + // TODO Auto-generated method stub + + } + + public void removeAttribute(String name) { + // TODO Auto-generated method stub + + } + + public Locale getLocale() { + // TODO Auto-generated method stub + return null; + } + + public Enumeration getLocales() { + // TODO Auto-generated method stub + return null; + } + + public boolean isSecure() { + // TODO Auto-generated method stub + return false; + } + + public RequestDispatcher getRequestDispatcher(String path) { + // TODO Auto-generated method stub + return null; + } + + public String getRealPath(String path) { + // TODO Auto-generated method stub + return null; + } + + public int getRemotePort() { + // TODO Auto-generated method stub + return 0; + } + + public String getLocalName() { + // TODO Auto-generated method stub + return null; + } + + public String getLocalAddr() { + // TODO Auto-generated method stub + return null; + } + + public int getLocalPort() { + // TODO Auto-generated method stub + return 0; + } + + public String getAuthType() { + // TODO Auto-generated method stub + return null; + } + + public Cookie[] getCookies() { + // TODO Auto-generated method stub + return null; + } + + public long getDateHeader(String name) { + // TODO Auto-generated method stub + return 0; + } + + public String getHeader(String name) { + // TODO Auto-generated method stub + return null; + } + + public Enumeration getHeaders(String name) { + return testHeaders; + } + + public Enumeration getHeaderNames() { + // TODO Auto-generated method stub + return null; + } + + public int getIntHeader(String name) { + // TODO Auto-generated method stub + return 0; + } + + public String getMethod() { + // TODO Auto-generated method stub + return null; + } + + public String getPathInfo() { + // TODO Auto-generated method stub + return null; + } + + public String getPathTranslated() { + // TODO Auto-generated method stub + return null; + } + + public String getContextPath() { + // TODO Auto-generated method stub + return null; + } + + public String getQueryString() { + // TODO Auto-generated method stub + return null; + } + + public String getRemoteUser() { + // TODO Auto-generated method stub + return null; + } + + public boolean isUserInRole(String role) { + // TODO Auto-generated method stub + return false; + } + + public Principal getUserPrincipal() { + // TODO Auto-generated method stub + return null; + } + + public String getRequestedSessionId() { + // TODO Auto-generated method stub + return null; + } + + public String getRequestURI() { + // TODO Auto-generated method stub + return null; + } + + public StringBuffer getRequestURL() { + // TODO Auto-generated method stub + return null; + } + + public String getServletPath() { + // TODO Auto-generated method stub + return null; + } + + public HttpSession getSession(boolean create) { + // TODO Auto-generated method stub + return null; + } + + public HttpSession getSession() { + // TODO Auto-generated method stub + return null; + } + + public boolean isRequestedSessionIdValid() { + // TODO Auto-generated method stub + return false; + } + + public boolean isRequestedSessionIdFromCookie() { + // TODO Auto-generated method stub + return false; + } + + public boolean isRequestedSessionIdFromURL() { + // TODO Auto-generated method stub + return false; + } + + public boolean isRequestedSessionIdFromUrl() { + // TODO Auto-generated method stub + return false; + } + + } +} diff --git a/core/http/server-spring/src/test/resources/navigation.xml b/core/http/server-spring/src/test/resources/navigation.xml new file mode 100644 index 00000000000..b534e58fb40 --- /dev/null +++ b/core/http/server-spring/src/test/resources/navigation.xml @@ -0,0 +1,29 @@ + + + + + + + + / + .view + + + /images/icons/ + _ + .png + + + + . + .title + + + + + + + + diff --git a/core/http/server/.springBeans b/core/http/server/.springBeans new file mode 100644 index 00000000000..d78d5ca8c7e --- /dev/null +++ b/core/http/server/.springBeans @@ -0,0 +1,14 @@ + + + 1 + + + + + + + src/main/webapp/WEB-INF/openrdf-http-server-servlet.xml + + + + diff --git a/core/http/server/pom.xml b/core/http/server/pom.xml new file mode 100644 index 00000000000..a9c7aba6555 --- /dev/null +++ b/core/http/server/pom.xml @@ -0,0 +1,130 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-http + 4.1.0-SNAPSHOT + + + rdf4j-http-server + war + + RDF4J: HTTP server + HTTP server implementing a REST-style protocol + + + + ${project.groupId} + rdf4j-http-server-spring + ${project.version} + + + ${project.groupId} + rdf4j-config + ${project.version} + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + org.tuckey + urlrewritefilter + + + + com.github.ziplet + ziplet + 2.0.0 + runtime + + + org.slf4j + slf4j-nop + + + javax.servlet + servlet-api + + + + + + + ch.qos.logback + logback-classic + runtime + + + org.slf4j + jcl-over-slf4j + runtime + + + + junit + junit + + + + + + + org.apache.maven.plugins + maven-war-plugin + + openrdf-sesame + true + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + + ${project.build.directory}/${project.artifactId}.war + localhost + /openrdf-sesame + + + + + + + + spring.ide + + false + + + + + org.apache.maven.plugins + maven-eclipse-plugin + + 1.5 + openrdf-sesame + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + + org.springframework.ide.eclipse.core.springnature + + + + + + + + + + diff --git a/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/messages.properties b/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/messages.properties new file mode 100644 index 00000000000..89d7ef935ef --- /dev/null +++ b/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/messages.properties @@ -0,0 +1 @@ +form.submit=Submit \ No newline at end of file diff --git a/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/navigation.xml b/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/navigation.xml new file mode 100644 index 00000000000..903e980680d --- /dev/null +++ b/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/navigation.xml @@ -0,0 +1,20 @@ + + + + + + + + / + .view + + + /images/icons/ + _ + .png + + + + . + .title + diff --git a/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/system/messages.properties b/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/system/messages.properties new file mode 100644 index 00000000000..0caaef03161 --- /dev/null +++ b/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/system/messages.properties @@ -0,0 +1,46 @@ +system.title=System + +system.overview.title=System Information and Configuration +system.overview.application=Application Information +system.overview.application.name=Application name: +system.overview.application.version=Version: +system.overview.application.datadir=Data directory: +system.overview.runtime=Runtime Information +system.overview.runtime.os=Operating System: +system.overview.runtime.java=Java Runtime: +system.overview.runtime.user=Process User: +system.overview.memory=Memory +system.overview.memory.percentage=Percentage in use: +system.overview.memory.used=Used: +system.overview.memory.maximum=Maximum: +system.overview.memory.percentage.value={0, number, percent} +system.overview.memory.used.value={0, number} MB +system.overview.memory.maximum.value={0, number} MB + +system.logging.title=Logging +system.logging.overview.title=Overview +system.logging.overview.level=Level +system.logging.overview.date=Date +system.logging.overview.time=Time +system.logging.overview.thread=Thread +system.logging.overview.message=Message +system.logging.overview.after=After +system.logging.overview.before=Before +system.logging.overview.applyfilter=Apply Filter +system.logging.overview.pagination.txt1=Show +system.logging.overview.pagination.txt2=log entries +system.logging.overview.pagination.prev=Previous +system.logging.overview.pagination.next=Next + + +system.info.title=System Information + +system.info.overview.title=System Information (detailed) + +system.info.javaprops=Java System Properties +system.info.javaprops.property=Property +system.info.javaprops.value=Value + +system.info.envvars=Operating System Environment Variables +system.info.envvars.variable=Variable +system.info.envvars.value=Value diff --git a/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/system/navigation.xml b/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/system/navigation.xml new file mode 100644 index 00000000000..4b16100dec5 --- /dev/null +++ b/core/http/server/src/main/resources/org/eclipse/rdf4j/common/webapp/system/navigation.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/core/http/server/src/main/resources/org/eclipse/rdf4j/http/server/messages.properties b/core/http/server/src/main/resources/org/eclipse/rdf4j/http/server/messages.properties new file mode 100644 index 00000000000..a72e3ea31ed --- /dev/null +++ b/core/http/server/src/main/resources/org/eclipse/rdf4j/http/server/messages.properties @@ -0,0 +1,5 @@ +application.name=RDF4J Server + +home.title=Home +home.overview.title=Welcome +home.overview.text=You are currently accessing an RDF4J Server. This server is intended to be accessed by dedicated clients, using a specialized protocol. To access the information on this server through a browser, we recommend using the RDF4J Workbench software. \ No newline at end of file diff --git a/core/http/server/src/main/resources/org/eclipse/rdf4j/http/server/navigation.xml b/core/http/server/src/main/resources/org/eclipse/rdf4j/http/server/navigation.xml new file mode 100644 index 00000000000..820698a367c --- /dev/null +++ b/core/http/server/src/main/resources/org/eclipse/rdf4j/http/server/navigation.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/core/http/server/src/main/webapp/WEB-INF/classes/logback.xml b/core/http/server/src/main/webapp/WEB-INF/classes/logback.xml new file mode 100644 index 00000000000..44009f01f0f --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/classes/logback.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/core/http/server/src/main/webapp/WEB-INF/common-webapp-servlet.xml b/core/http/server/src/main/webapp/WEB-INF/common-webapp-servlet.xml new file mode 100644 index 00000000000..6a8629b18aa --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/common-webapp-servlet.xml @@ -0,0 +1,60 @@ + + + + + + + + org.eclipse.rdf4j.common.webapp.messages + + + + + + + + + + + + + + + + + + + + + + /org/eclipse/rdf4j/common/webapp/navigation.xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/http/server/src/main/webapp/WEB-INF/common-webapp-system-servlet.xml b/core/http/server/src/main/webapp/WEB-INF/common-webapp-system-servlet.xml new file mode 100644 index 00000000000..6af05087120 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/common-webapp-system-servlet.xml @@ -0,0 +1,66 @@ + + + + + + + + org.eclipse.rdf4j.common.webapp.system.messages + org.eclipse.rdf4j.common.webapp.messages + + + + + + + + + /org/eclipse/rdf4j/webapp/system/navigation.xml + /org/eclipse/rdf4j/webapp/navigation.xml + + + + + + + + + + + + commonWebappSystemOverviewController + commonWebappSystemInfoController + filenameViewController + commonWebappLoggingOverviewController + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/http/server/src/main/webapp/WEB-INF/glassfish-web.xml b/core/http/server/src/main/webapp/WEB-INF/glassfish-web.xml new file mode 100644 index 00000000000..5898d75e66c --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/glassfish-web.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/ContentHeader.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/ContentHeader.html.jspf new file mode 100644 index 00000000000..dcdfa8fc5f4 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/ContentHeader.html.jspf @@ -0,0 +1,4 @@ +
+

 

+<%@ include file="/WEB-INF/includes/components/tabs.html.jspf" %> +
diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/Footer.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/Footer.html.jspf new file mode 100644 index 00000000000..1b00330e8fc --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/Footer.html.jspf @@ -0,0 +1,2 @@ + diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/Header.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/Header.html.jspf new file mode 100644 index 00000000000..b8c712e60f1 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/Header.html.jspf @@ -0,0 +1,5 @@ + diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/Message.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/Message.html.jspf new file mode 100644 index 00000000000..081dd0e7638 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/Message.html.jspf @@ -0,0 +1,5 @@ + +
+

${message.type}

+
+
\ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/Navigation.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/Navigation.html.jspf new file mode 100644 index 00000000000..f8de5bcb436 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/Navigation.html.jspf @@ -0,0 +1,84 @@ + \ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/bodyStart.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/bodyStart.html.jspf new file mode 100644 index 00000000000..1e952ee24a4 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/bodyStart.html.jspf @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/bodyStop.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/bodyStop.html.jspf new file mode 100644 index 00000000000..5d5509f48a3 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/bodyStop.html.jspf @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/head.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/head.html.jspf new file mode 100644 index 00000000000..2d80f7b8d9c --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/head.html.jspf @@ -0,0 +1,12 @@ + + + + <fmt:message key="application.name" /> - <fmt:message key="${view.parent.i18n}" /> + + " /> + +<%@ include file="/WEB-INF/includes/stylesheets.html.jspf" %> + + + + diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/htmlStart.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/htmlStart.html.jspf new file mode 100644 index 00000000000..6558b3781f5 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/htmlStart.html.jspf @@ -0,0 +1 @@ + diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/htmlStop.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/htmlStop.html.jspf new file mode 100644 index 00000000000..62d09b8221f --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/htmlStop.html.jspf @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/logfilterform.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/logfilterform.html.jspf new file mode 100644 index 00000000000..3bb493e2e02 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/logfilterform.html.jspf @@ -0,0 +1,97 @@ + +
+ + + +
+ + :  + +    + + + :  + +    + + + + + + + + + + + +
+ + :  + +  -  +  -  +  /  +  :  + +
+ + :  + +  -  +  -  +  /  +  :  + +
  " />
+
+
\ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/logpaginationfooter.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/logpaginationfooter.html.jspf new file mode 100644 index 00000000000..3c6e0315783 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/logpaginationfooter.html.jspf @@ -0,0 +1,11 @@ +

+
+ + <<  ${count} +      + + +  ${count} >> + +
+

\ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/logpaginationheader.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/logpaginationheader.html.jspf new file mode 100644 index 00000000000..3982154a78a --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/logpaginationheader.html.jspf @@ -0,0 +1,14 @@ +

  + + + + ${item} + + + ${item} + + +   + + +

\ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/page.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/page.html.jspf new file mode 100644 index 00000000000..a441c973d88 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/page.html.jspf @@ -0,0 +1,4 @@ +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> + +<%@ include file="/WEB-INF/includes/taglibs.jspf" %> + diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/components/tabs.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/components/tabs.html.jspf new file mode 100644 index 00000000000..9fe0687dae4 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/components/tabs.html.jspf @@ -0,0 +1,21 @@ + +
+
    + + + + +
  • +
    + +
  • +
    + +
  • +
    +
    +
    +
    +
+
+
\ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/stylesheets.html.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/stylesheets.html.jspf new file mode 100644 index 00000000000..bca65a7fc7a --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/stylesheets.html.jspf @@ -0,0 +1,10 @@ + + + + + + diff --git a/core/http/server/src/main/webapp/WEB-INF/includes/taglibs.jspf b/core/http/server/src/main/webapp/WEB-INF/includes/taglibs.jspf new file mode 100644 index 00000000000..1b8dc1b30c7 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/includes/taglibs.jspf @@ -0,0 +1,10 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + +<%@ taglib prefix="u" tagdir="/WEB-INF/tags" %> + +<%@ taglib prefix="nav" uri="/WEB-INF/taglibs/navigation.tld" %> diff --git a/core/http/server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/core/http/server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml new file mode 100644 index 00000000000..aaece9c1865 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/core/http/server/src/main/webapp/WEB-INF/rdf4j-http-server-servlet.xml b/core/http/server/src/main/webapp/WEB-INF/rdf4j-http-server-servlet.xml new file mode 100644 index 00000000000..6da8b3f3ad2 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/rdf4j-http-server-servlet.xml @@ -0,0 +1,151 @@ + + + + + + + + org.openrdf.http.server.messages + info.aduna.webapp.system.messages + info.aduna.webapp.messages + + + + + + + + + + + + + + /org/openrdf/http/server/navigation.xml + /info/aduna/webapp/system/navigation.xml + /info/aduna/webapp/navigation.xml + + + + + + + + + + + + + + + + + + + + + + + openrdfProtocolController + + + + + + + + + + + + + + + openrdfRepositoryListController + + + + + + + + + + openrdfRepositoryNamespaceController + openrdfRepositoryNamespacesController + openrdfRepositoryContextsController + openrdfRepositoryStatementsController + openrdfRepositoryContextsController + openrdfRepositoryGraphController + openrdfRepositorySizeController + openrdfRepositoryTransactionStartController + openrdfRepositoryTransactionController + openrdfRepositoryController + + + + + + + + + + + + + + + filenameViewController + filenameViewController + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/http/server/src/main/webapp/WEB-INF/sample-web.xml b/core/http/server/src/main/webapp/WEB-INF/sample-web.xml new file mode 100644 index 00000000000..f3e3855c73d --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/sample-web.xml @@ -0,0 +1,64 @@ + + + + + Common webapp base + Common webapp base + + + PathFilter + + org.eclipse.rdf4j.common.webapp.filters.PathFilter + + + + + UrlRewriteFilter + + org.tuckey.web.filters.urlrewrite.UrlRewriteFilter + + + logLevel + commons + + + statusEnabled + false + + + + + UrlRewriteFilter + /* + + + + PathFilter + *.css + + + + common-webapp-base + + org.springframework.web.servlet.DispatcherServlet + + 100 + + + + common-webapp + *.view + + + + common-webapp-base + *.form + + + + overview.view + + diff --git a/core/http/server/src/main/webapp/WEB-INF/taglibs/navigation.tld b/core/http/server/src/main/webapp/WEB-INF/taglibs/navigation.tld new file mode 100644 index 00000000000..6816c22e740 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/taglibs/navigation.tld @@ -0,0 +1,17 @@ + + + Tag Library for webapp navigation + 1.0-SNAPSHOT + navigation + /info.aduna/webapp/navigation + + + isParent + info.aduna.webapp.navigation.functions.NavigationFunctions + + boolean isParent(info.aduna.webapp.navigation.NavigationNode, + info.aduna.webapp.navigation.NavigationNode) + + + \ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/tags/errors.tag b/core/http/server/src/main/webapp/WEB-INF/tags/errors.tag new file mode 100644 index 00000000000..75da84c764a --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/tags/errors.tag @@ -0,0 +1,15 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + +<%@ attribute name="errors" type="org.springframework.validation.Errors" required="true" %> +<%@ attribute name="errorstitle" required="true" %> + + +

+
    + +
  • +
    +
+
\ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/urlrewrite.xml b/core/http/server/src/main/webapp/WEB-INF/urlrewrite.xml new file mode 100644 index 00000000000..6f25b8a8412 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/urlrewrite.xml @@ -0,0 +1,14 @@ + + + + + + + + ^(.*)/$ + $1/overview.view + + + \ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/views/home/overview.jsp b/core/http/server/src/main/webapp/WEB-INF/views/home/overview.jsp new file mode 100644 index 00000000000..1831d4c6261 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/views/home/overview.jsp @@ -0,0 +1,23 @@ +<%@ include file="/WEB-INF/includes/components/page.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStart.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/head.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/bodyStart.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Header.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Navigation.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/ContentHeader.html.jspf" %> + +
+

+ +

+ +

+
+ +<%@ include file="/WEB-INF/includes/components/Footer.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/bodyStop.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStop.html.jspf" %> diff --git a/core/http/server/src/main/webapp/WEB-INF/views/overview.jsp b/core/http/server/src/main/webapp/WEB-INF/views/overview.jsp new file mode 100644 index 00000000000..ceb7b95bfea --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/views/overview.jsp @@ -0,0 +1,2 @@ +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + \ No newline at end of file diff --git a/core/http/server/src/main/webapp/WEB-INF/views/system/info/debug.jsp b/core/http/server/src/main/webapp/WEB-INF/views/system/info/debug.jsp new file mode 100644 index 00000000000..a39508ade0c --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/views/system/info/debug.jsp @@ -0,0 +1,22 @@ +<%@ include file="/WEB-INF/includes/components/page.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStart.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/head.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/bodyStart.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Header.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Navigation.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/ContentHeader.html.jspf" %> + +
+

+ +<%@ include file="/WEB-INF/includes/components/Message.html.jspf" %> + +
+ +<%@ include file="/WEB-INF/includes/components/Footer.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/bodyStop.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStop.html.jspf" %> diff --git a/core/http/server/src/main/webapp/WEB-INF/views/system/info/overview.jsp b/core/http/server/src/main/webapp/WEB-INF/views/system/info/overview.jsp new file mode 100644 index 00000000000..b316f621f51 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/views/system/info/overview.jsp @@ -0,0 +1,74 @@ +<%@ include file="/WEB-INF/includes/components/page.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStart.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/head.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/bodyStart.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Header.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Navigation.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/ContentHeader.html.jspf" %> + +
+

+ +<%@ include file="/WEB-INF/includes/components/Message.html.jspf" %> + +

+ + + + + + +
${appConfig.longName}
${appConfig.version}
${appConfig.dataDir}
+ +

+ + + + + + +
${server.os}
${server.java}
${server.user}
+ +

+ + + + + + +
+ +

+ + + + + + + + + +
${item.key}${item.value}
+ +

+ + + + + + + + + +
${item.key}${item.value}
+ + +
+ +<%@ include file="/WEB-INF/includes/components/Footer.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/bodyStop.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStop.html.jspf" %> diff --git a/core/http/server/src/main/webapp/WEB-INF/views/system/logging/overview.jsp b/core/http/server/src/main/webapp/WEB-INF/views/system/logging/overview.jsp new file mode 100644 index 00000000000..574f0599411 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/views/system/logging/overview.jsp @@ -0,0 +1,50 @@ +<%@ include file="/WEB-INF/includes/components/page.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStart.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/head.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/bodyStart.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Header.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Navigation.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/ContentHeader.html.jspf" %> + +
+

+ +<%@ include file="/WEB-INF/includes/components/Message.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/logfilterform.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/logpaginationheader.html.jspf" %> + + + + + + + + + + + + + + + +
${logrecord.level} + + +
+ +
+ +
+
+
+
+ <%@ include file="/WEB-INF/includes/components/logpaginationfooter.html.jspf" %> +
+ +<%@ include file="/WEB-INF/includes/components/Footer.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/bodyStop.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStop.html.jspf" %> diff --git a/core/http/server/src/main/webapp/WEB-INF/views/system/overview.jsp b/core/http/server/src/main/webapp/WEB-INF/views/system/overview.jsp new file mode 100644 index 00000000000..8511f0972fd --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/views/system/overview.jsp @@ -0,0 +1,48 @@ +<%@ include file="/WEB-INF/includes/components/page.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStart.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/head.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/bodyStart.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Header.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/Navigation.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/ContentHeader.html.jspf" %> + +
+

+ +<%@ include file="/WEB-INF/includes/components/Message.html.jspf" %> + +

+ + + + + + +
${appConfig.longName}
${appConfig.version}
${appConfig.dataDir}
+ +

+ + + + + + +
${server.os}
${server.java}
${server.user}
+ +

+ + + + + + +
+
+ +<%@ include file="/WEB-INF/includes/components/Footer.html.jspf" %> + +<%@ include file="/WEB-INF/includes/components/bodyStop.html.jspf" %> +<%@ include file="/WEB-INF/includes/components/htmlStop.html.jspf" %> diff --git a/core/http/server/src/main/webapp/WEB-INF/web.xml b/core/http/server/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..e2d16bdb7f6 --- /dev/null +++ b/core/http/server/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,125 @@ + + + + + RDF4J Server + RDF4J Server + + + CompressingFilter + + com.github.ziplet.filter.compression.CompressingFilter + + + excludeContentTypes + application/x-binary-rdf,application/x-binary-rdf-results-table + + + + + PathFilter + + org.eclipse.rdf4j.common.webapp.filters.PathFilter + + + + + UrlRewriteFilter + + org.tuckey.web.filters.urlrewrite.UrlRewriteFilter + + + logLevel + commons + + + statusEnabled + false + + + + + CompressingFilter + /* + + + + UrlRewriteFilter + / + /overview.view + + + + PathFilter + *.css + + + + rdf4j-http-server + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + /WEB-INF/common-webapp-servlet.xml, /WEB-INF/common-webapp-system-servlet.xml, /WEB-INF/rdf4j-http-server-servlet.xml + + 100 + + + + rdf4j-http-server + /protocol/* + + + + rdf4j-http-server + /repositories/* + + + + rdf4j-http-server + *.view + + + + rdf4j-http-server + *.form + + + + + + 30 + COOKIE + + + + + overview.view + + + diff --git a/core/http/server/src/main/webapp/favicon.ico b/core/http/server/src/main/webapp/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..03e5432589bfb886cee343d3f7877c12b25d8584 GIT binary patch literal 894 zcmZQzU<5(|0R|u`!H~hsz#zuJz@P!dKp_SNAO?xUfG{@$0|-+9ychj9o{B(@bN{cr z^dAC#{rx}x?El=&|7~ae2P%VD0%BC7po*PP^&h??#7EV`LuoX8fI)$r9+1hd%8G=RNP8RP!Kd=`uN}V9?$%E zg(Ev!Bzq=HmK=6?Q@>wQPcOZquJ7SXOEx~cV>{OB1h}3*w`hiPD$CUmucZ&)s#vjL zm-&PQrK_HcrQEvMBBCZ4xpfqNF!Ydex|tKh%}-rVGhy2eHu27v^IRVEUet4*0D QfL1ejy85}Sb4q9e09`ywmjD0& literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/images/DEBUG.png b/core/http/server/src/main/webapp/images/DEBUG.png new file mode 100644 index 0000000000000000000000000000000000000000..c7296e504f10ec8e9ec490763ccd69daefc14947 GIT binary patch literal 884 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLlFy4O|IZSYRWx*U_1i%r#hH?Cigh={y*@80FhmyhnBlB39G%Pelkz;_uwK zb8`RIjrFph59m4@@CSuN%$_}4KwS0zBh4+13^#AyTv5vK|31f~M~_}Sf1I0}`}om4 zXBXGY3mCRGGW`7f=F)5iZXvBN?_PZU`qk1Q;QSnh<5L)xG%=*Pb00i-ur-0<|0S-v z>e7W(ik==`2m2WMG8wuu<=^aLFf}#Zv}u#Gi_6`W475Kv?)A8QD{p7Oc!kKQVI_DN1-Z=5Lc@M9~0hNrP)qzjWUw9S1LRE}OWX1K; z=M(cDrl0s=mYrnIK0EPDq(Z>i2TL{bc}r)k+~F9i*_^U$sac3ZsJ+rW(}|&GHUdf$ zbXHA&D!639w9{9oF^E0r5N!O>J#)I`yJ!{$4g&_!8L_VOJDgI1K4S26^>bP0l+XkK D9iq?2 literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/images/ERROR.png b/core/http/server/src/main/webapp/images/ERROR.png new file mode 100644 index 0000000000000000000000000000000000000000..1ee93b64c5ca3c04341f2aa2b6e0add32510aa9d GIT binary patch literal 1122 zcmdUt`%jy76vhvuFP9fyDCOD>W|7&ob0xCk$_A5mw9w+XwX7SW;UcBO1&E4F+z$@7 znXw>7Nj8~@z;rAMRyGqZo#5sLP}~?$OA(}HEeO25P`R|F!q@s|c#`Kl`TTN{C+BI% z&CVe3-8cXc60uO~aq55a^Y&~OCs^h&ic*jz0QhEvhh1IvFug`}x<*!AUURPG4Fw3w zs!J6NNo9#rAyt%=)xG|UA_ZVqeC~;S5khDOA-mn~LZ~$W-`?5L(P5Gf#uEu-V&Fs= z%%ri$X@D{*qf{~n*8UAbxFqUk0P8b(8cW{tyXhk3Taz)Y`JHWVq8M{ z)L!_CMmQXfO_ytAf3RuzzCp0h!jG|~$85}MEnHvJBqtMK>ILQx`{`)Kfb<$NKj|Ox z36iqVOKf9Sf-5<&*AIRS2S=j!Mj~diSpVi?6VC^u`m8z9GPwuP+~Xzf1gcF%ot3Ik z+?vTWq%kHBhb-`;QN>}@_Hu6oJ`w@QpxzYiMPDeFSM75jHrNFb_T=EvPi|~jtxKOa zoAcwpr@@lC+sVV6(__eKYbS_S9G}nNY$^HZ7@!pB^arEKG%H}Q8}*}MV6<3=L!pC8 z%rLQb8m%XiXbmFPW;HsE&ZL|EG6bI&#;&fdSvX#{2i=Vz{FOtW?dw4|zF5eo9({-ada;1gA=YSfQw zp39RK-A`(|#|&dJOve7=l|vc9aRo&uTk81rM{k$+J`AV}2>+>q5oJ*~VXW>U#kG?aj6K)g=9?`NM*TbCM>e|>tG`_??38P&ym89X pmBp@BX6q4lM=I}pd@c|`i2`qVrH$vl{){I-NJQB})$!u@{spH}dx-!5 literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/images/INFO.png b/core/http/server/src/main/webapp/images/INFO.png new file mode 100644 index 0000000000000000000000000000000000000000..0170009122cdb00f34984d5f06074f52f0a60bd4 GIT binary patch literal 998 zcmd6l|5Fom9L66BJC8tik^;)mOXbE6lZ&$MqGYrwBbo5!~a6F#l~qUY}YJoozT{l528!R74r z^V#SFz>girO!6ePe##>>l;eJPNNz{toG zing$G1zDmbkszZ;(j$rnR!wjd_$&y!As<7|0P;*IvE$^E&i?6nmm3l@A!O3I7|Qv1 zRlX&Zr=ljRqOUEW!U@SkRL!HnR-^n2pLY;4w?0*Cn|eWSc&7V@2>&EFH5nxBLvs6u zWDSZZ!t0))WTLpqj4UHAEo*wG8#`yB3c4zrO}Mmzk6T&{4nmeuFm9V#+?@E!hPpY( ztnQho&u87i;x6j3VMdOYEKcth>#9s7;EOvDn?7xO`C5^ceQOC)OJKU*HRBAvys-b~ zixtOsn2I2KWNWzh&Q5D!BBkdS#)xi+1!KyF9cy}+YJ=j;-W3>7O(kc{G}C4_$?s?hMO;cwd#Q4Y_W z94p(-KF;VO+rP1M>#c6*M8x$K0u=P4%t||YGF^d1}XZmV|_c1_Y>kq{7rnM^!`lW*!es{xr|(^ zPwY=fXjK~=H6w%~?)5&9y-qAV^HyMjV)uQ0W?8}}ap>5gK9&6rPzqRtt zIvV9}+IGr^+AF;H>IU}PR9ZT{hu)F>o{7G*wkJPqGdJdH&1u$QyE@agNcWvBJLwfJ z8TeY&8X=Tc2FJ&;O1%zVhz{AcTKHXR{u}B|7RK6~`tL(ho1Zk92cs(d?6P+jFL>*o t_S_y5NA@-FFVAjNn_D}MpZA5AFTOpId1&ZIYK7-cuvr}DZ?WlR{{onkG${Z8 literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/images/WARN.png b/core/http/server/src/main/webapp/images/WARN.png new file mode 100644 index 0000000000000000000000000000000000000000..2a0897928ff02cff5971e950786b0dd99af2f22b GIT binary patch literal 814 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLlbm9L-g&v(ET$Metu#2``GB`SB8%d zr@Xyg_y0emgSp(t^R6ErPx<^({Ng%=@9%EBy%Tj{rpBM2U)0nszP)4n_et&7)AaAJ zPHyRuxVP2g?%~Wgx61aiL!OZ_nnQTw8m7t@@6+LZ6>6-7{U_&$p*PK5?I0 zW^!eX^@j%mub&y2n%V#V&-w9D&h9DF-`*+SI;ZgFcH-$}_8;zb{`>p={|on9$C!#r z9DaPb|KjF8sz?r`I>z_slc@|NsB2n(zt0sH!Uo@(TuX2M#ctv3pho zbjb!!7srr_TS+TinRx_Gxrh6+yDId=n#Id`F7RmyH?ZPT445IcSVnwK5SRD^^G^xM zTT<7yaH_1V&N5(sGOc>H1FOzz-tH?#AzO>H6qpnbCCNlBQ+13xc{DAdQEPg~o-HNX z3mwwia_Sc}q*OF6TF)C?)4Euuxl$+KfYQOxgZECxDqW6fXl!KFIIwo*eAQDc7d<(~ zz_QSRF|$xo&c5BldZmk=T{iQKc!Qd5VDe>SxTg|z*>!u?9-!M9JYD@<);T3K0RX+* B*j)es literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/images/productgroup.png b/core/http/server/src/main/webapp/images/productgroup.png new file mode 100644 index 0000000000000000000000000000000000000000..9b6d961caeb938676bc732af207aad6add6eee9e GIT binary patch literal 6236 zcmV-i7^CNjP)WM@mR=mYqb6Y~31@RUKOuWSb6K`?A#9JIN@fHV6yv17_F!2@#OuWSb6K`?A z#9JIN@fHV6yv19Lme`z|JRVP+Q-9%hAsf(%7f6`M@uH`pXQF4Jx0c`h=x5Pu(S7Lk z=s|!j@)u%k5<%>yQ6m|SbqNb=hnM-?@smm{lT6+dsdGaF`_&*HT9&|>#Zbk@LbdM z>C?jr2?;im*=e!#Z~d;8Owk?=hohhTUGLHB{O(56yw6Q@%rTtfJL#L(Wj<7tUg$kU zKp_#XDQLe4m`ZaB{Un7BI{q0mW<)}v(1p;UP*0;*p;v>3t%T1#_nh8)K03}85_$&& zj2Fix8TWQV?|1Cju^z9z_FB&`zWAcc$&)8j$iDUZv-x$@_WD1dbDA zI!|pf1{J3DxN+mI+rNK*b}ZB0p+kq7E?v5u96o$_(S!*TwzhBIKGLyc$GVqZddWX^ z>ePtRx&Hd=UFm3R)20o1dFZB_ZrTb(Eb899d!%*i*7dVz&khlMCY_R!l5D5KxHZhp z%FD|u`S|0H-^14mv4R%`Fl}gA0G8al@4kEF;lqbBF1ze9t5>gH78YR(4pzpht*vcc zRaG@&<;s;ki;9XC*Q2doy*dHH4e=gRu+HypR>Wx;oQ$AgMQdX|tH9L11A##FHW+K{c2PPeKa>}|mXniXH8nL+@kgO=xR`)xN6<{1IB{@gWo5?T!Go$@`m}|G@q7D0g9iNvtk4J7UVH6cOuX@_r=E(KF2S@ev0Q?A zztgp_o7P3Gg41Ft&`jX4k?Br%WLh$pz@HPT2c00n0xM#*ZQIt?+Vu2vn?Bc0K2%p% zTW8Lkp%UeTC-=>rJ9jyHDaHsZ9RN3&m6c^bPkIz4EVMl@D4qrDZPTf%t0Txq0XzZl z@QW2IR+Rtr(@#-4;6adJp#oERIhR(gT19!I>nFHLfA8MCsTxvTOqbLK+LEzv-@Yzz zHP+>qUv3dJm|&!|v@~2(Qxn025-`~WP88fE_=SHw71R#a3_n+`nt?6bcUmq4${9!cFKV9TR{~i)30W1)N$Q(-KizDIB;O3OWKM3XA26z+xow9x4)r z4?gsP@c(t^&YhowPN|Nmu9f%E$^bYv9X^A3L_jx@mX1Ou?aa)~tG8|2b`+gfq1ps9 z=Y!ahV_9%ryf?ZAQ$YzD06IYum5Um~BrRLEESE?YCfN*wPi_EW8F`<|&(E*B`R1F4 zzy#Y&;N)Os`T{WfaQ*lzue`#bElI}ph=v5jv?hvAPL$xRNv=g`nYdUn!?sWtELh-? ztRUHVE-1mGotbFdqzsd1&NqItd{;WbDO09I+yJO%{@}rbAq1inVk0wR3lbujTokz(gD9y3JVMW1%Nq*`S^4W3MXp_!xGPWy7C|UoI3dO|T?gXgY~_E@01|Jt2UFY2P07ACDeAT7`SMqUBIy zcn@NntS`U(l37)e2#BVzy&#+uJ|l~w%WEqFRSja6;hR5yz8?&*xdYI7WZq0Cv*o#T zq1PyBDAUFo0K`rm4S~0cF@8wsu%`%6I6gDIntAi)*_ocH(G<4EZE!;o0m2USvTwir zHV6y*?_>m(idF*r;MiTI6yY=DFMg5^t+YYs*RQ|+x(U3V(Wz6X6uK@dA{4f*WT^+- zfJb^l=algLxFh=tOBQ!rvagE=7-)Eyla}DtqWP4GZAYM63U`!!>#esoV8S-2=-P`d`b-%QGK& zG_g7+W-Dt5%2N+Bfz-Oq1P&aGP z3QPL@Bl_MJuk>mTucncmT1G!BT3rtfA}|uEEo7qjVT}WlM5Aq205>*L;~coQN?4&? zFTVKV6~)EHZ3#&BEnBt>{OF^P3c_MyH%t%ColOWU#&`4m=OQliQB}&uE86#;7V#If( zlL)Y-@;CBPV-(CeQRt*9V0ex5;dRbmGrUW-HDE4Kvkd`5#7H-3^F7YOo5T0p7Kwsl zU`A##b%Zd7!_;OX{;|PGz%@1!ht_2P-o0>rpFm*65E$c&Tx!@|cilA-8k{j?$Pf!D ztDREPk29-aM{3(20r#X?vt}*E{Rd@U_V@%UfMf%PDKNk?67y_x!woms%;xy)5LOQ8 zKLo&hjPZ9VU`&msVmLBAN-GU?lBw-nKLtq;3csVlCfBL}bpfEpXi>gv`Yv%+k{M5_ zOc)$piV6c#j*8lKKiFe8k3C;&^5!nBma zXTyC38#it&lZq*0jSRS#-pD#KuDtR}3n@FTiB(osW@l=!bY4C$seKLt(0k!(R$)GS zC8cekd1ov}cLDmT7(bQZg@y4$Ac=T3fqK>wZdGIn#{CjIbwTe48tt{7 z!|?#ju)%|^L5&!On%vP0R@DWtiwmYej>A3nWib^oOve8G`}0Vf=`F`W<`Ob8 zuRjzX*<%4lt(gMMHC_;FM@4~^@!o#>?IS+;;Dg}m)vF_HusUb)`{8%refM**Hi3%{ z7)}4QyMaMV_6jN&KOYqs@8Kc^ECKFhDdTH#fJ9W@E5InG677RT`=NcqW~K z;5F8O02ZHQ1PFb$RO7k-1jsU&`a|eRuv*;_pyq&SReVN;#JSOg&z?P-W8-M5XWCGoXXzuoH+qV4-K!maIGprc%9s}5E%)ZvFS<{Y!Bw#oO zG?yIQgDhqT?r)3Cs}Ia_9iQiX>Hc7i?DQM4O~eGPR%T`VAHVzVyFCD3gujutq4fzS zuQUy&peZB>C=KHkzWw&wg^L$29zeILRd7~=vChb6pM6#@wU5)$MHxwixhLkd#=L$m z1vFfhrtsE)0Rt>#i?+)iJ9e!732RI%*JQexo1_D@Ekh zUU9`0b|Fryw!Cgc{0U%ukSQ;pC2ax@f{NUB+ie-3c_p$cR#<6)($w0~wO~&4ooz}= zN<4I7%48!rC+JRJef8Cr2JYvI*UT73tE;pkszjVOHJVlm^N%3#t{06imby=dX=zp9 zv9=`ix^D2svg&l>w5noFqWe<(mgR9VDEzsO)j%9_6wA;)KJi0-s zn}mj+j_A%cf2WDYJX*m@U9oiOQd{deFEWj;#NjfNV4*x_OrYIuerD<3jSrgLsDKDe zrqSI0q1EAc2H_7r_#lj4E#s%3Sd5!8WlF$V(${LR+gQ!bUUeT$Txj@{Pd*6HW zSk92R#6XJx#!bUw5|)71EzWW747<@+P_eu1{mAyeZGH<13ZjB1J+0+X%V+@-e=~Cl z0AR$-;9?2L)b?1X4OMd~AdGDb2ta8>il2^Wyy9{_08|YCvqJ!L#%)aJ{#h)m?mTkg zmS~Xv(W6I0hzskaT7A|y3&Y=j6)V>=br=n>`01vds=azoER(L*C6%!7v~=9% zWwyk4hKw|0Dve(x2uyTKMPmU%*QuFDEDOnd_<7{Wkq|Nx3ZV$uNiW1LxqOxu5Sd)+ zfddEVlIp4LurRLH>|BbaE}UzQb)SNYR+cf7xWKocSJf}LM5${Gf0fJj`JNv(rW~b2#EVK-^0ovtU8@b zH$#`jy)-$c$k?IIsUYh1%w79)@f&ORxTVxeS9iLl)>1AO<tM372+3jqm8@4N0uyE(hV&W8tz}ee*JNLXJ+C<=8)=i z0d9a*0mRDk%-V@$gb}Hro~04hmOb)Wuz3%=&OIk@7%QOf%N>QdGqGox@gg&f2*jd_}l2wqdQ9}K4Oj^ z3lOFN+?a2c4meM#jo7>BH{N(-IrvgR{wR;~^Yc6Ffu;HL=X=aeOwFv+O&jimnO!hU_IB;N=04B?%!)FUyv1ws2v6SAudwcJ__uc_m zY@e^b`l6by<2F!{TD;ma) z8&^yr^LeJP5EdnR`mML#;%->e!=ra&;GX3m`H<0O&JWpE>rg)G)4 z2%0Thw)myG=`%H03vzTT06{PK`C9z#1+5;SmCR?!Bx)Bd134euv}scq%;QP3odC>W znscPA-ch4QT~0wETWK?W`t*DNHd>b7xpQYw;;dR`RL-FKT(uIFw z2@@uiB5P^{U{Y0>uypMY9z4jZVToHt#*T4QF~=JwPMjFQvq=C^I`^Y!sTr{Ipw{Ni zn;T>!wpJBh-I?>1nM(>7OoWp=g$0%1@7{W*wNs}~+#PO9!4DcV$ligbcC(_ob?esP zv17-W#vPKK+;mf5dMFttyThlSetP2@Z@gg(iA$GO;ol z3Sd1#;i!&Z+Ve1E$T#17^YsG{JkXiP5-1Q|GzCWhQ5$%4;LxE%VFY*#FpkJ^!g>Xa z7RD$*z8(QhY8XF$d@Hyjn^8P!K={uz#2<1mqP9*G5&xBNnN{kZ4W3=M*!jgcvXk>`Bgb+v5cbt*i$;{q)ljw@NVuws7G>KWH`FamO8*V6c}AVl83W zvSt1?Yu5P0j8~e)r{&9+ZvbPG#*Q7^8Jd`=n{@ny=?^bnyg0CO1#8Ngr z|NQf|HKglQFC(9IybfVRuZxM->-G5FIBC+P6j(a@x&)%pQ}|i}z_l`N`ca4s+^Hm3 zWA_g~{4f{KQ0ONfee}^3##p4|v~=VPcpcfeabpntZiKt7mvyjWd|LQt&*!nn9!nWI zbZB%w$B!TX({BZw*V8m71vC62C&Hs+-Q`eG9|)^6VvS@5bI_g;%hFO!q*d82^${Nd zgH)I2O4^MWG2%s(?(23{L*xhaZAsS$HP(AFQz;2n@&}a0U&X zWDYbf9YHf4Lh;CRdZu;1Fu3%YXP#-8J9n;Ep5segBjwmaSS--z0A6^eXGO z~iy<{cawD0w4HJG>>I?n=zlV z=4|y`ESIDw&Pyfm+KViRXDr&wd69tl*yD1#i*BIt@y8#JnCCdm7(vqF24Tpt;^N}V zWZ{0H!39@Aivp}^@G$qHMT_*BPb!%m5HDqmPY;M-DrFwk-0(AwXxcR!se-nWajN8d zbFSBlrk|8F-eVc3@G;NGtFOKq5LdiGK$a${uutZ#`#VY}%V80;LLCt0tCIWb^u20P z;`7euQd^im>?}*cE>#vBGHN0=VF)<-09=o4VGxwQ$kTE>GeSR&dkDZ!L{NzWKHCL8 z`Q(!!=i86wtF}@IGv80LK|OWq)Q|~K=c~4ETMll4ulcf_`Q7csfAhU@w~b7*_G8{} zW=!VWm*!lZ8=~ji)YUd;&K&DfS{Tbk3-n-d%w6kPue<6Vinhs?fBjP*BJQTU;@NBuJbiqJ(2IWf8_QyCFkqh=W`XmTeT z+i1}&gi$@~EW&87c|OHFD-%mVvEF-j`*$7YGdhMjmXooLeI47HIsXrh^TmF1j?QAB z^Z(np9o#Z$n{$fgIu%&wTl+s#4D)B&`LdL~R=l-%yAVs%(tz;@NLT>Lbz~t&q?#LV zalpjeUj;CU|JMZL?XTV9|ED+J;(&>_IAG%KpQQbd00RJAYTENRIW!;u000055l>h($ literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/styles/basic/all.css b/core/http/server/src/main/webapp/styles/basic/all.css new file mode 100644 index 00000000000..542578c6f4f --- /dev/null +++ b/core/http/server/src/main/webapp/styles/basic/all.css @@ -0,0 +1,5 @@ +@import url(../w3-html40-recommended.css); + +img { + border: 0; +} diff --git a/core/http/server/src/main/webapp/styles/default/images/bg_body.png b/core/http/server/src/main/webapp/styles/default/images/bg_body.png new file mode 100644 index 0000000000000000000000000000000000000000..27387791037336e34b55c98eff33f4faf2a26648 GIT binary patch literal 69413 zcmZsCby(Ej_O2))t-ye^Gz=*WNO#E4Inv!-(x9XcrNGc3-Js-vgn-o0F-U_nLpPF_ z^SfWq@80A2iw7Q_{n>l1cdhlVwcq_gT~z@ehXUupg9rGEuVghJJb1ME;K4(x#}DuS zf~q5aeE$R8MoLBM!Go&aml)8k``^hu(*x_`T&ifK~Yvp+h=B{MKOs=(H&Gi|Cl6_8FClVj8-*x-uvi~)bJzwksIrSo15u_ z2n{VO9_iklv^q%Qc5JR;_eyvu{6|CBK+I|4GqJdw0=umCQ_- zhu5lX`ulC$CWYniy(N2BemI38ekCR(w5%Pugi@K6>GoNe?;8-MD zwlLbOGg+v!u>p1?Kk_2CV&@bK*5xd$Yl ze8(nDS>uJ-vs|41|8Lm4o<1?0ZwEwm z;el3;H@}Nar57hYR|wW+0=UK3{#y3lM&Ptg^gE>>#$XN>kx3hZVUB0huQW1?u_9uP z#=COPrEef>`&`ARF7Ko{+u|CmdBK85(&Bl?!PnjeNkQA3QhXC~_bfDkS3lEng3LCVod*BWeeBYKr zZ1!s!V+}H#GH>tQ`2Tw~&(+JHBDXZVKGGC`a=0#1?Ue>g3B3P=6hV>vQitxbSD_u&J85beKV2I+ zoJpP8hZ%PaWjb7zL4)P{|KX`66dk-N@a7U=B(pL&VrS3QmTkCSH*zK0hEA+`GpNqx zcI~ZnoU7`p_kb{j{+;Z09z@~6%uny%b=J2c6pHO>1U|ja-*5>3g!7-%(}a|zS7jF% zIej&rio>h|i&ZSU{1Sodr<~*n&aQJSAMzR-jkX1>nB$m8>;k!U5xh`#H5RCDnJM*& zyL?0ZuF<@+H*sn zFgs@bU!0$L?41*oT2{5Vcc%S6u8u?&He`DX&LayK(K0L7yn&Ns&RPF$b%ScbyPpXk zkQ7>T>Td|BSykRAI)67v(ezeP;etAp4x^KtjmZ+-e6P1k?h8*nw`=Tv_(MZXB}&P? zpQ~vQywLOZ_I%M~8$m zbMjELUq0$t@vsdM)94B#zYBVUmR=gehZ<9T0t|4mv?zJ7hSNH1a%%~|=k`~eT)BBg z(f+t|Y_HnZ=u_io^Syx{*t`{9KN9#dWIFq;thOwMENG2J2fVKZ13QWpnKtF%xMD@< zZZEliSPmS!@fb7;@(cWZRG|E@QgGqwFH>mTWBl@DYb#joPE6h~h%A$Ehg?ZW7&`BQ z;yj95^_6w`AZ(WWR30n!Dx;$5-EKG!AY98n|9wCuj+PxWS)TlMxb^W;l!L!|=_Vm5 zBZv9qU!QmfZ@L-2yN=UrmF2;h_}yLkTi3VdB8mn-JOzdoQQ>(duGgni@eWq{1`W0j z2T-M1{du3V%Wtbtf8>0{!73|`$D1wq&6u6}UsYGqaGsPci}`syIa*%vK8rA6VEV*V zd_r}92+n7rml~|iyW(DdCjc4O z(~ac`-u~(C{p%-dhw7RWM;ViCNte-rdYE5>0`Om-rrIGrJdQCuq(8Y?^Nl@P4zyJX2{}R6c&4F5<$s2Y7fYq{ z)MtJrucU$wROGdRl3w-o_9RBmK-NeBVzkWVb+9-U8{rpK&Se)O0)dVWFYY*EbkOZuuksrr3WhzSoYd(8d|ZO}5ek5Rw^Njk)pEHcftk zs{`LVV_t(NYq-U+4}<5q9zaw6x#jO6RugBcmY(9dw-jNGXsa$_`Nv6M zd3DRk%@>8hyisyFq~=P0n!y3PKKj|y_wZk^DBo}Mm38>rgsu4v!vB3yx$IZJnKs8w z`DJpBiqV|D0@NMm`lwlVtOwR`A|B3J&?K=p<9vUb1|&4!qj%IYJTdq1k|URy6vcTW zqx0xHwy4NO?sAy_>x#b_H68p?qO--eBUw*SX+!f7|4X%ZAzlEIWM7u@Ly4Bgv_+bI zDsipNGmC9&WOH&nh6HCOo@$AU;O*9Uk=i!tQ3OZ&Y6sCA--VVK*^`sMs-?fHSDw2N zNJZw;JN$-`(B^AR#TXysGk=~i?X=J&?Q|$~C-h7N_rxW~N40i2B`GF(vUM$C3ISh{ z%%%>Id~s0%p#4vJY1EB$dg^_U)z2RbW7msVhE}xYzGCs}(w;u5$L4Vow)z4`_YR=9 zm}lN&*LDUrtb1u5{tN-UC)rHo=2H7=`FfM*zz}Y8(EC87p0-lZ*zGTHOH?}hcH1ei zE6bZSO($8xPqMoY1eR)qEV2V8xl9IG+ z{O~Wrf@r7Ya<7YCeFQQwj4QtuifzA~9P2iU)Uvg;^rVZUBK2B_?t2L;Tb0`7vY4<2 zJJ?;6O`3FLwTNCAj!6Z&)sg4@Zr>@uM?uDqt(^x>zkZjZ1VT&rX?>d zAEI02Wc^qbTzc+v<6 zpz+idnJd={HQD1(5%?tzvakMY(`~9^cVa0nD(Lc-cQ9k? z?;>%&f{KvNS!@mL_r(V%;N&!0jIp=wJqvugR(_H6B_)FAl$_*c&qkabTY`+42I#s3 zD`IoF=Db$hY|HKOT9rwgroK+w>0U{Dm3LO9Kgemw*?a@~*HJ{=ygC_s%}y!XHNYe7 zY~Q8Ey>>|qlko^t*NEyk0MCF4A*WcLVJOlsjJ{9PH%p({CpLL!Fr~Tn1qf=@xNj^S zE0Z$o-Tl4reXRBqH-PbD6VWaefpzcD1Nf{K#Gpn<4@~mvkmv@RTZ&<(uqVoE$9m#@ zMUKVUk-M%j+Yv8yz-kC)jUc+pqv>|qnhH-vk-ux)eau#Tv?~S$o=J=}@POEUq@v^v zNQuJb0FUc&)iKrgY;PJ&J^gWg@z&f^ilwpDE;-ZqJ5Q#UBQ@sf7r(u$boV$YD@lI} zwf`^SN(yNRh*9q2HfnX%sZZlC3uPyGIJ-cB0-SzSe}udWAPFgqcpm5Bj|)nu_Byhq z|FD;f_qizNvK|-cA718|A%To@(m1I!`a2PjLmK$K8zV_i1)wr-Z!_!#qFOC(*$Q~T zeBz}5-99X~mr(@F@hI^YH!s|RBFP{dToN3&nM}H@#D(ai574P zR=qLbf3?hRakdVxWU5}9Gjn=~RKKE#hCfm44mu6w@EY4g5`Y?Dg;7T-uU zjf1thID@?}M7F@LLjRP5tQ1}0aQl6Y1rc=9?wGV#|6>{#;-mwq?+;&!WRJTNbivB^fqnlgx5h`>Nqgyb$lcgV=fY@^OnM zY_1)JvlBhihOzPy;1VrtP;1Nx@l9UL2@u=~{0JduuM!C@dItRT;K%k~N4QUIR?IoeG0 zZ38uC8H|3oJ^R5ompWDf*902giAHKbH0^a0C!>rO+|b||{nVUr)iZ(2m;cEMnj*?( zO>U4T;gd%LA>tE__0d^55JhMKou1?JM%RQQ!VcO`)iCzB`t1&c6TqB? zL;=x@-Y6XTARslGb}}!=HrJj;BSz;BAZ<5g{wYlS{O_=+71@*=3wHK!{p^X zKyM0N<%ah<7AOr{qzu;z4(;47d#@We{tV6n9S!G;#jR8qM+&QQ_;(>%i`BW%Z5an> z3$eVSQsa^g9nH8rP!3SOp0>~d#w+>2RS}y0Nb5JR*8Ut@%J;ZaEH!VV_sg5j{(NvH zXV$y*dQax$cNV4(3_#;1-v>;mtnnRYG_vYFOIX30o@2`R;P>>;U?~OqIwF>6)>&&Ap9Z1CNA@W1}|s_kaB?Pj~}b~~Bd z1nL_$OQ=#j=lo!n>ND+o=H!O504iY-%C66lt(y4f{cmbe+5rI=nMg-&&GSBv7}Q|I zd=c{dfy(La8wbbjpn;{WF_(E4D0`YF2(Fpn$Q6S=DH< z%vtB9^Ra!A?W(Eqnf#x9W^Pp#**;gDJ)vyzz(qLo1Z8=@HgUQ=ek>7ud+i;3?j3y5 zNt^ZHnEURCJ0;x!4)i*yRi@Ok>n1N)C)1heD1cn#)YmO~`N&Za36xnln^A(Lhy@;r zL^j}K56|ThVkQPAzMQCQC&M?wPz6rt*f+a^7uhO9*y`?q2FQKp{15#KN{2UzwH&eB z9^A-ztes;;T&)HUFo4i3Kh98<4s&L-VAy|R=xjeRnZo2(lUoy6IX`^h*mKYjeARGw zYH|k{#{K$LJ@7{Q>$(Rqy5-6!w{vEO57$)U_FU*87cYAuIp^p64fm|(gYwg8l)Wq8_n(p0 z%RRPoiy}#8dv@fHuT`*}tmF0=6I(bGqD-T$cJ%-*{k(#IzGZ{^)Z+?~(Nom#zrk=c|x z*-sk+1gSiUdnP}pb`jw4glq!$C4f_o^HJW0%j0;%Sj*@0i)5$cG`-q;FNY6Mv}UCi zFTTIE`euEmJRKy|F|Y(MRB8Ouqtn~I2TWH@HNec4gign zjaywM?2)v!|Cl3xtX{#W%KrI3A$ZBTg3=Y947$3ViAYTcoh0KDB@0XQc_Xk;3G_56 zu2T#1Y;_a;1bt%DM6kt+`ytkFC;812TaQt{9kK!u}ZupkBt7Nt7YV+a%`mDHbOacObr`C3S1x>FO4z>NaV_ z!feJG_HpH+CqIW3I>ACBt{&|cT6eK7W>Sa>=WTc1=aYZshuAjjPB9RF2C728igtob z6Bfmdg{+vj9* zqDgYcx`DGf1+O!mHu?u00x+t8Vric5`D_ z(B`*Lw2^eN!k0EIgRNYI(aVyh%+wOp5ISu#V+x3M3r!UJfcT2V#Q}mQs%#gSO?~}O z(GPree}hzbwbXY(guZs*8#?TtKwWUDI%P0j4ur`>N|EJx;2Io~52q9j#b*yYIXrWL zn@~2>=Tb{KS3#_}WQ#Du%Z}2L{DqDb_4yVYMI@RRpk!|0tVo3+Lj95KwtpV~#qrdCeY1(?q& za+PyI3svKWmNlzg!FkI9oDTjW5vT30UhJbMhN-2>_9QQNw2Jq4+^jf8wbJ4i@O_pz zNsiP&o{C6;O~=Om)ViT1q=4XvZkmZEW;(aO`rhQ>;+Ue~XG%WIbih?iJ**2|_tsS$ z)WFFIX2oDa*_oJ?hN?2)OnA>Qt9=RdY~_k!FJIAFBW?jR$1lZjwU<&MfLK0cRnhE> zuvYX+^PfrAyp<29QVH7uGsGAWrJZFO!;;CYI?wHD|pr&o#eEtUC=$Ml5qs5Zx`Sa!Cgy^Op!5guQrDVj8}i2_Axg;Y(I zFP!Hh(pP)AVVzvVW(%Ezm+A38Si{le3SdKVVAmYt_fk=umD)oa-Uqplw0!vXFWRe= z7M&Xc>dg)2oP=3dO52pD0)FP7ron|fXfYud+9Kg)9T9V95`|@3$%Vb#&kO-HEL|{r zydAd!-A18{KUv}?>W^`VJWnzf9GMpmY(*( zy31*C`aoRXfIoUh%bF%T1=FkxFb-4Yu2_>QLSQ_U$u@7OL*m>E zw5^LIh5wkvW4A2ivC}2bmH~-G?l~Awx-;BDp&(y!hyiD~1H5BmL<|n(sP=bVOJ3)w zw0%k1$?mj_npu*0pG5G_71LE05`R#AMnLDO-q8)UeDz(-$5L=9iGq;lscWTp9|mE# ztg06J*92lYlc=M+M5zqoaQm{2awdF>GP$0ty6$lT0|Jw=G+>W(NrD5cp|txqnfio; zf~>NLu%Db3Q+dX0#WPo5KiEKF2MkP~*##3Ky7KG3ctAkMN0mz-zUSxF>eRJm8?Rn5 zU)Me!U;U5G{r2Ha)G;oTmsSmGr{S7=pR2v2$RV|xY{QCO9HFO0I^MHpq0e!<(61Ws z^`5?@7LZ$fr{_XbR=Dc@v1`IE2T2|vAXcIiC_BQ3fsxAB^{d;2PrRk{O;4F6E!%9J zZw+<$^UR1x6FXdcm8EFkkH}Ed7I%4LbaC4!q0m?;0f#Ifg#N5rDRnG~&?xq#y#L62HVzA$yQ z?8A5^naM;yYe1oXw2SMT15nrD)qYiO=c^WmuF9>6efmn0;nECT&!(g}voW$~c$kfk+9G>gW|*Fio;rCam{Kb@6=PA%?0o~`*@8^0_4P9z(oIqDVxnB zzO2kWAoJ}+J8Tj61T}5DnZHxN!kyHkXDIgO0GRs5tm{uDidjPGE*nq9kmByRihUHy zQ(h&491|s^EMwDAy!z&w8jU@8p`HhfVuu-QzG5H4|13MnW|ws&nQJt;%cfj}8Rr>$ z{nd(qlm+Y9wshr@igP(NOo;K-r~ss|p%6!gPZW_;g9jFkrhj31o%42Jedq854lwnYpw>h;S<4;GFri} zOqBRbBV;KYu(%AC!x=JOK&@u_P zIlGs#TCXCR^}m?o`enaHQVwJIjhOek6C1D_>ZCb4n7v4;Fzn_K%{{`5z}8yFDr2#0 z&D|lNDNR}sZ1r_I*c`FJFDbgaCp>6oEff$MU6z$sOq}-7d@(f8z z^}14{cAF>W*WxTTvD=lg)*yaMsJ?bZv@p}p781ts5RHs(O}(gNwHEa>8l7r6&z?0| z6Yov^e!2RI7v--L&z()pPcH`=w}IE_wtCsIfHal^QS zRgUn!0+1euDYDDsbZ;cQMd;181q!GehitB~Q;20#EyW-UK@%JUqTou+Cfv??BsjCYXmK`fJ5tI)$GyP9aX+B$}YrVD8rS*S-krL#F zZ1@kFg7GVDlaMQ@+ja*0XnCeTs-yXPWk$uXfu7S0{7}YDyu*pKLNFdaCOf^9;wF^` z%IYYZ&H*ecVjKf@c&20&{tI?)?H4a*c~BaBWL6(^bL)30bEbt`8Jn0YoHH4$6mCAH zI?A;AWMsO1&MxN*d(7P&A^A%oCz{$qx!vbX#*OYai8=4rR!*pLG(0?Z{I<#E7!O@P zhxSxE3j6FJ$(p(-3mKLpg-1vs@)=+ZX++6Xk4{kRIyR`WoVoJohQe^vJ~acp#}U&3 zVDiiALJH#>+a5S{9rp#>|2unC{6ZCOih$5ng(#VQ9Q~x6gapv)$hzT>8Mc#z3HhQr z0y7Z;)1}5IBPD9mMqCN5JoQQ-k~vy&pRTVt`C`Bj-+{YJMoz{-U<|NB#cr?YTCplm zjo%mX9ZKOW>he9zzZyiDTcK>hf@|gO)LNq%WMgI5-}>1eGeSJfEwMt=Qu5IIP;;RB z1swQz4!T>crvniJ6!GZQ1$fIzWxtWviYthxkZTxUDot?88-{(6E@FyCAqF`y~)rPIu-t> z!t6hWH0a1V?4)ZsiGS6Td>pROc{7FhL?L!WWTpL^1X8gJ4G2Amw5XVA!5o8gv28;MZquTTOLd3Q?x2?~mfTpx7fQ z9MjtLAM{+8hZ}O9Ij7Zw1SW~g@qO>Dq+&37nC!`W@GSuEc|=9>E;4G4J5O`E@BU_`(U8xp*{DDi_?LATX?SQE|#;OCRAo$yFg=x%*$+Az*?>tkX%xjL` z`wQ2kma?>y5px|7OH$tHbOoZpb#pqsJ@UzdCI)ta6}m3?`FKkxJK#Vau76%oAKC#M zbJGl5!>gQ7UCeq_HaWi4YBhFbPT^xXTOg(nynix zD{2+C1f6=Z1yn%k0hqK&dn~fHUr0ko3RGHbI2;2-7&KP>({dwi(mH@3(KiPL&UHRh z4YN*9=dz7U1tawDa28*)8RYJ0ui<>SW!8WNnyfgdHizZ1m|HyFKTMZ*0FPq_vuMSA zQJ2yf?$5OmGL9x@J!-jZ&mcYs?*~F=8*@7VDtW$!;p%F9NO2qpXbsi>Gi?{a_GxQp zjMb3tv}OrdyHEqPR50wS#JM|KvRf2h6n6cm(_X->bT(-X=zBv4RK#-Vq-kQotzd}G zJix6^RDLL3lJ4?B#j|i?j(m+FP4hsk+xFcT3W=cVkM!E_ska~RlQ+A6h04J@eqr_8 zTyUShELJx2Rrn1pUGkHAe!$V0tE`W!#0{Y^D1X&Bjq!WaaG_=&@5>BV*kl=R$un40 ze!EYpsg5w^GYyI~W*l9Z$+|@Lg!n~{_VbozvSq}khINXhz&RmkRA|$5i z@FIE|C%YtX;6z3}RS%Ur5^26!S&O*a$tW{3Q0b}sIG+u{fRF(jm6~_cM#rfF+F|=# z&hFxWh7H~K*DVxJp`JQa9N^MIq|eEWe9U{@CGu~RK1R&E_5yE#mHf9%NQj2=;yP!F ztnA?~^p^DY{-< zTDtfKr`ci^7t58yZFc-z(ud^WcE2A%wi^{rprM9}oC8gZP8Dh7T8p{Z=|lYOdB%?VvnSAB7ww|<2RF7-px#%-H#YfR z+A_tA5XDw?7?8^#Pf7KhJ2>4JbbdjkmWAtT=pM{U8LjcZ zU3v9l_^oO>k(cv@>HxLjXu6IYPB{C{U`}rk2qGWKHBr-L!1MIo?wDmA6E~r$a1~v? z2W6tuzI?V_v&}(b>X*UTKb<{g&%g9Q$9z{KN3)lTbgw5$zl;@W-~l!qyYoG5WPv=) zIJQLJi(dd8rY1r_obI)bNzXrhIC|40Fel;DO!}r)S3dm!NqG4P zF!kok%hN}nM&d%XlPdKl-5p*@_N+dNW#OB+;Y|4$koBEjFuW4CC6E6i*ZITV%Vop~ zu=``1Taswy!NpPCidCKyS?%yVNAmY~PH}K+15yen4JBe_=Z>&X^&Xn$XfzOU*3*ye z?1nj}hkqQweLrlg%0R~Tk?<;{e~g*8&oz>GS1pJ*J(2bwB;#z)Ux@PVZO)5UXT|v0 zOOa~?z2t1)BX1siazb5App@L?idHSq%UmQaobpU6HIq4*VKxnnD4ohnRPjW_{KzBT z5*B|U&29}Zj{a8ggRaOiC-GgSFZFzSSMzxncQn~ARw?R@J z0=1vDt(8_=C!Qp?ZIhZcqeG}Sxkd8#Tk-CUSB?3YMB#Ow`gFgYk2NaT_=eKuBH>{r1~si zJ&(h3kShMUTDC3*2#ZJSvXiZ&*i; z(H}J{PsA7E{P1zz$RhJR@Z`4HA7V@%3}iFZ*qFricT%JIq4UMs(u^_-iyfakw#j_E z#1qVNXOR?J^|@C0-I3+df=^DnOFH*8wqnDqefniT zcbg;iGZLL2ud7gFP|r+v*p4uFD5b%VQCloASXz}PW8!`-d=#9VurSnwk%v>2djwBL z_Gl+Cr=96&1lJU?Qp7nAX68~c5mpJx85oYPbk%aahU-g&!+{U9oNya9U~0)QYz{c@ zVu87iCEGyPL=M{+GT+^xuq&XK>lZG0g`yM3KhxmC-d{R^2n3e0xOWG$;Rxoy?ALm z?Qe3R+fvcCs-cs|HwS(7qjE-K-7H2ER__^T7;p(0EdzgHD2rdx2zb0cICB_Z6GA*zNZWG8<>9ZEIRF3AKs2;|7nsY9zh zlLWMb%+&g%gOaIf9`1@F(UA3Lujcp1y*_DMXh*0Hc9xjH&n`f{hk$F4kVP&fTKI5mQ^!VYsqoD|UxkXBVB|6!P{kErww| zg3BLAEd{)EKq8SZKU7sSOKZ&@GR0+9v~i1zQZLl|DEab(!ym9f#ivwHd*(wb`iONB z?uy&F4K-YR|8PXMO6N~g1d+%p?E@T@NKN19m-Uq)F^`nV3w}N=I`e+|PCoqem(txe zcf=IGih)Y`r=ZNVpIsC~c4WW=O{i{5>{e2LKBgMR#7`rtu0f0*tV#m)+Hr0U-hm67SOa!d!LE!}~(@-6bAyV$}`CV)F~Sx9oJQjg6i7 zLHgX?AGdwecmiVR1bYe*kKNo@#A`i?(}n}*+yBr;qZL&BxXHrkI7|Mx{+9HPH5uH3tAN?XK;-mm+*D=w#PjAE#}-@!?zr z7>eC!@w^FQk&>!&j2h#_H%jbhlNWLBmtm{B5bEJvl?c^w1iCuE^ zthjxpFQkJzJE+;+F@3C3ISWlpQjOry#hj))p!GpSVPN7j^Kmg;BWR^?j(IcVOhKPq z*$dEC#-6!FxC=&92hr-0QR0J84f$M9mf-lnzH}5epo4Yc=b4}|vi>8G&1&~zrhC4K6h|3ZK9 zu{_3%1~zi%Mb&YeoLZ5VKuA3Qjw`HhfmZY^ zqsM~D-wzs7;TmGD*g9Q(xQQ2<3ujWoLZiI&p00ju$|53$DwL?aBJzZ6AyNd4n|Db1!qINvy6n)!wNXd};#> zR%6l%(Lm~0#)_{D2C<&tt>CzP+Pz`1M9v!63O|$+2hp@-~%1gtMiz;ne&<#_jvE45fmTd@U)#f~|Ft zR^K1pI)l(FEVY}1Q#A$Hl$g-3KR617Hvy!j>E1-D+9a#j{w(9N_OzjE*)owY@VOCG zvE9o+1bRA>$t^0-#sZ0b$J{mib#swPsxsl8MlS*w&XB!V) z*-%Thn_ybsj+97L)STzrsEs*G-?Z}vcy64c4(m=)v5*Ezd%BQGr}FoNMkA-%K3=O9 zsoYvUm*F4n-@?6yyY^@DuNEIsxjcsG;eGXEl8Sfc-(gTO`}f6RZx^3|{YTZLe+gYI zyM_CkWZEf{Yw=!uY)`lSI=#_e+FVi#Y^_@T-m+~tRK4t!m#xK{@~m=*0YWQotmlE* zzW8D7iuEBEKB+Vbz!>qheH*Ak!>6CEn9qeJ41A?IQ)tp*Z%!dGhkFs0WUdb9WuliG zf;mgh%!Dj(Co%Gu#URHV`6#uslmI6#2|Tm8X;=iUj;MdUaQW;$n%&eZEyIa59pk4lAj+EAqDpPaiJgIvnkQo~*7u5m*LCgbE|%U3~Lr8$w~NUC)>UeqTV$u&}_{`F*()~_>bhL$hx^+5Hf z!%QNh*w{whONt_y&$TvWQDK_yZy!bFx|(LTPSZhGK3%GPbKrNAOYTNzGiUjcpXKpe zXbhtC*x<#RHwSA?@=I`r=s&L(T+ks6(hd41TsItfMkgo>YtJX|A5nB_FNZUF8xO~jX4@g7@nv900O%-1s z_21gO7XJIL3SoL9^?}_5>Cquz!r`HTV$oKWnx>!lqB|Z|M@F|wAi|~1l3+Tn1lEF6)LyJ%DDytGVzD)@QW_qGqCSZl{uX`i#Dw=?jv=JB|hXY-y z?5uljgI;09=KT&krWpfaJT&+VjNeop-H@tF{BSY;8r+Gt2GSg+8&9|wu<$T5K`Y81 z+T+#Fs1&*CM1W_lz4TL;#>yBCKr@VGk4J=)c^H$}sd#V`Hw|3 zQwxs|>TQuBZ(a3Hl&1k{>iTdhz)9$i- zWt+J`=%rCXu(4udstQ?jV(w}R4}NLyUZLDuie_%NzNpt_oYkMohkm`|mJl zz8HB z?32&wQGkNi@1P9BkBm(W_sO!sib&FEx*mC_W2d8^jGNN6Q>-jH3hM8nlj%V#I0@^c zuNS0V5|Sr*wz>Q^MLf1$kbaGDl#rB}4`R}o>HDPlIFmY{@3V8%A00g^=ALcc9&L@Y z0P{C(erzD@4w+z&b@o2TOSY5dgN+k)aVS*0o4xByPe=ox3U$c2hhmO|JZp-1yWy=X z0t#Qnw7xuMXb=;21q}N?$Uzm)FeW|;7vf**Cyf9(8S0ofF^$$!@Z}g~)y?9MmR(@a z?phRfB?c5LcCIX}qS@u6QFDfYjjhtI4?%&e)Icn|m@i9+A3hUVGl+%ArFCC3rtHz& zL&|~s0auH85zAt@0sOinuZq?(2cBCNAQh8t*r64@CpXohp0q4l^Tf!z8t?01GzV+5S{P(x&2Hu2VrF$ zkMeZlY8Q*3VkyqJ2=+Ybgv}OpDfYAx!I?sewiiL#+ve@x&i(skeMh|qM5+2cwJ|K) ztYX4=gIyPjKg7k@MeXj<5>A9j_^J8CJ?y+Ahh%D}pKBo56yo^P9H3cgNeJBvGNOiw zSO*ly+c}54un*4r?hzO=SYf8@K9@m*k}AVg+it7+x3c_S)#ZLZEX61H^qIEF^oaft z8WF4bC$oipk_w=K3L7$P(sCdJry#zuqDRLas=dtsqV1Dii*Zy3f$jz!^WZTh=RE|y4@k~MNw$)4~jnxrPwlRJ-fQ};FEZ% z9mRY;V{zl+r_@=lXPmw#R1CE_xK%S8u*PuamaOi!QD?3^ov?(VunSL}_rNVA01*5; zZmXcaeZQ?uI_m4H&Q!JSz#vy{ioKC+4Y~2dSI8W{1Yt=tVEQ@``9;*FiGdYAP^p6r zmDKB3G^OkQu^W&N>tT(|uKMVX&sTx5M)9li zA$CX-9CeDG?|l57^^(R5&jAIemO_4(80-ZFMH!`hTNw~)Lo33hqjBvIs(0_qD5TTZ zBz3f)?2ao9VpY|{^2FwY))dyT2D{njDwVd*KP2tGmF5)YNF(t?A1laPR(TcX(}+Z21-nqoXvc{{oaKAPgfe|sO>o^ z+y!mi&vr^)gfFC(3(ji-R9+PF;Z_8+)RM8{ZzvzdE|_k;sa?imos0F0Mc8sZ$}4C< zgTaM{KH1B7FGF1K@`Z^l8$^Pb9h?$qdA= zOe?J`Abd|~nbJweK*-j#>7-(^f$`;Tc~A2RYG+ziF=;bscwaoqEmLpQnk#!Ej6| zwW|!yte`I(PojPiXJlKeh*soqo4l}UpKW&C_?-wyIM|UkOtmEy zZka9mEHuLUAxfOi-Jrc$zL78OXv2<8w1VYu17>0s09qn?UfGPA`-4Q0`zMPG);Eaz zD?8;fj{?_*L3N)}>=}5XyDI`s(@gq@Nh1|0y`#vEI^R62YTCE&r13T-{Dab@mjtKv zxX#)R4Wa3$Ab*8-7|xir&vj6onvpy@k{?w64^d~~73Cjwdka)jIwS<78wqLYjv=KH zq`MoWySsCeuAw`myN3{v?#{uNd)NKF_iuRCv(H)k?EU!`%Pb2^dD?V8 zW(V1>O>Or_I4@LvwV9wlIa+xn74gjSiYUN z19G@Y;wPeu+R8Fov^2o>Lq zRbh|`xVyNVyD1h{(0v!8xiGVl4%(KvdJCzl1Xe2QOnFEpT__H{8$IF=QaDO{{!QdHU}(Sr-?!nNamic%+>wyk~L6%zkos8-4QC=He-3r zFvqy)IUC61?#*uKp5pDJXAzmE9ZuJ~>8`7h8GH^9sq*}!LfOf|8kgf-V|C~Ilt@b_ zq3)o!Q^dyax1#d>9SdWaTxLC9ewh-mqz~!r;jbi z+9Kf)|G@2+37TfQHzYqoYQc_gwGj;XSE5#^m9mvH$d)B4@Z;bx5#K2dp%PY9Iu(g>jK?7ZHVo&yf1~kRlF3 zw$T}%TrG?;6FBSvf4x4&4;*^s2sGznl_EX2Dh$0w7R7n4>djv7paK#6I*Y%G^huyW zgidONeJQn&T=5P~m@xqzwu?@rvfBFH3qpD59QN>z-q<%oEVrL5;L=~d3U25hpriJ) zY6xxu*<8$)qsa0+2Jlz&+&`fm`nv+g1R0UiZXf)%QjgMyZvVzdesq&;e%!Rq&b{%& z#TSj8>M5c!{x7`X@Z4|1y&L0c8k$v=${cl5J0W5uHagg@UZ@_()K_hML3m2sZ z9=cNeDg*|?>~YgdYX!YttFIdV{WN)`#rhti4BVf$(b5OF!ga9JTc*o0N{Z5$__Ry- zXCqAoNT6$%fDZvwE|zTB6nLcMW5jlx*~!GuSe`5{-QUM+X{{e|%#t^k(D<`wLPR-Y zCqm-GC-qMEF-O16z%8m&WVdM<+WH>@p>gsf)TF5U|4Em+ej=(O@GuE=-?vz|&Pp-( zMNYkc!z30S=?X@wa3P<~Q)*U{4p9zl)8jq?Afp<3-4G{o6eSfaE09M($44DWyQ}b# zgVm}#sP2k&_80W~HP8o8WjNF&*&FR;y=%F(3xIx;UsqiuFdHon62u*pFQQ@YdWdKr z;)lWQ>iWO+@!kVTMTm{4@0~zQD+6X}B3k{3Wz_zA`$0l&m`It6_*A`CtJpH!6(zAc z&B@H$=Pn{rzVNo|)`rJmx2$;Sq+RI03&ykK9-QIjo{FJHD`R{z>otZ^Mk3tZtka z?17&Dsh7cXw&yu!@yk4Oag1X-F6uhdUy))B@vB;X8ZxFdBhvplj;ZsiLXFEL|(lCBW{Syx2hg+kFXSoUcFxyd9V43c!8 z9goRnYxMkwyc5a*^aao)ZCbb|Ub zzrTCi{_M(cf8z&9aSu%82;(HiUI&`jIwUxyZk807*5UE zeC*CoXN>NzPGuttORhioBFnccm`K>E@ZMycOcgk*TSpgylxk&-N10fiIqYl4Z6@2A zL^25+#*gD_8ZRM7>2Y`7EPVmRHak|%i}nlhL16?hzO@r7feRewM!?fFPCg~mJEaaK z|D|D1@U;WfQU{0cF12Iqv&I^jCh_25vmrMcAKKypBYazKKrO*geBeY%RKMA<_s7!d z&k=0T!f39l+F^ni{$=8%w*xTgxio#wj|+sD1Iy=$=XNgJcCsN;jmLCRoXL>z8?w008*{=|1AqvS2&nUEg$?eu~d-|z$i#dQ%-hPn+HGZwd zZjYoXSq zAwKMHD452i^jnSP-O&C$dw!z$PWp(RDz@(T~dTw5OwY{3>;2?`{2h%0@gaO}5k z+`Wk=vI1LE_{RbX7LbogbH`ozAMVA0M0-5yU3`sr%%cO5CnDoZ2(g7_?%i_P z@3(jG$t@E+VpwFn^uru)p2Q&!gF^l%rt_7u{0P*Yw{K4#Fx>=R?0C96U1OCqtdkn;MS~`$G(39;+u3tXTn7)kCF+4~3BE|lw}~@-8ou`R z5ik8Tm8$q3A|_24S&G~jV5saLN=%v;2uR+~-5EhSyw;1>je-ff332c4&6Y;7gqt@) z3g$K5!MO(^~C!fA}|Gg~qv{P$+ zDg4-A^2r^bcdVJ z*Z5z3c^^TxPe^l@%^S%8AY|{0u>Tl4T6&H5qm+FjpXEJT$}ymZpAPsfV2BS=%t`xjklJbMSrZZOvJ zH*UE$7#Wd(BM|u`x;Zd3s|H`jlHi92qe2}AgFZP;Pj&f2ymuOk38<&72C@!R-Y`-# zlWMHg3aJiHYNL4#2n3!bvkqmVzU+g}=r92*m=d7p@42lcqD>k8#z3%g$!6clp|HYN zq1HP;?*$k|1Fva%u!+afj$%@2IY@iHn!d{e2MCm)p3Z6Uh*R_f49n(TWr~MILY77E z)q!`i5o6dHSrS=p~Up}7I@8QeZ5HrmaHE%4_pUpa? zA+!g-leu^~Z>6E{W)&$KMrc_Q;cn^Zy(XH`FLl8RpU6Y(i>-HOnjL)}Z%}%HJb|2h zP*xOCy}oyiliuX*_^>~@Tz!4a{iNs^8;6JU{Ou`@Rqb*IYYnyN?WbazE;B2@`j`2p zjiydav>Xt7k!?p#leC!_OZg({mUH74A#fDEz!hH9>YrkKJ@z0%lj+c1ZgdW-gkM@X zh)=GOY^57B&P`VaOyX0Ka&Jrj4qOtnhSI7*FVPfE)b1JfHA1~J%xu{IHTaqh(+T)Y z6iBLQ&HWau7{^EV|ER>?am{@+oWie6Tyk!~`bpzvTqoMMu)bjNxB3e`!c-=V@9Che zm$EN zr-|ktL2P@O1y}aYuJerUi@iZUd?o#4DeZS;UD-7Y@Fb*oG2yT39u4g@?s7U?uoh4n3yYy(oP& zm&3j1#cD5F@qqD3tzKrR)k&C*mM-ki;jZ*I32yX(hzx(@uZATn_3xzw>90{7Jq|2J z4Pwonrr0gz5k7omC@4`JP~XPz{9|yjLf#tU#fcvs?B0uAzVivuMBhrfJa{ zE7}J=Rg;LqXi|WkdFX+_M>Vmk=@=qGLC8>YSHKmCenI$h9DT>Jj}kU3hcaC*I7;9s%_{Y1|Z z^>rBQlOp_%a28hg`2C-E!C6%m`uN);PyBWaX|kaX2`ix{YMnD*jE1*L-|PP3&ok@! z)Ags3FQDH z{#Kg%_48!I99PL16moVeu=BAbUa?RCeyjYtG`hL#VkDJ&5))MV=aO-_E2ez>jek=_ zrF?t_!Hsdj+aMJs=BpzgVitA-`^%-U2kH!W(jnW;1NolMq`pS={0-KAqY00^^14a4 zKTtkcz38FD9I9ssji2c@9M*_4CD_y+qM$prpHa;IJ+XefW&a|hQKlh7zWd{>GB*^O zT#IR|%2oiS?JGtz?eUbMy)a}kM`M~%D-nN#!YiB2cB6JoH0$qcZk5^LWgLFi#_gNJ z^Q|XGKAv(jfO*E6jK9vz?Q;uqbO0YCKw7LIzanuxlywnaWR#{hBW+Dq1 z%14>iRpVB-2`FiFKtiZPSerGfv@+q4I$29i5#`KnQI(bB5dwD0Rw&1P~_=Z*cZhv6^Mx z%sY1S?NmMg1|AJ6VkA-=FOHvkVXPf}}Ow0Ye30@B`Vi~Q9ZaK>mrl*?9P4^>%UqO-?g1E$QWlLQv)R0@*WJ?xUEtffQW@mMyUZ|%V8{|_$_1J+mD4$9coRQ*rDbe;=%#ZzrUkx zK^3)@N3}Z4p=)@EcH=KXf15r0Z4t?aQWM9O;=WcAcT|ZF`4o8_!oo8Ozkb^I60cX8 z6x}s$h8~8U`(3PRk`WC;j{F{}lBzm2HtR?PCY((XJ`@BB| z*;QuFFM75+l|dij(cozQw=FJj41!#Y?`qY+YI= zIqfP)bF)8$!`reeWZjY~1yRzkNv-!_uGZXjTKF%9cA)QQM(-edJeV;7Fv~C4S zuQ9JJuyBEn6AR#|WugXaMqWai_Iy7Oz(o_Bz1hxfOPQt(l0UA}qH>{!xJp+sEf{C9 z>RbbalcEJBS#9@wy?H2>8ASp=6u1?ed|03-9&PNiDS9HHtJ#fWW{;+rfx(?I4?9&R zF=E5i#3SY~{Z?z`3L(Sg>x_{%$_4U;!tN+clMpaBEoB~`Cs?ZfNJ1vrc6CB%7STIw zB;C>-Sai%o(ACx;{T4d)s}K>vblz>Q+~!wgfxjU$*t1{T3N1DH9)6L?yFQ;9q}^9)<+)yYVBCP2hxc7Vty)^t6g|= z=ecrTpO%;#TnXYPykv*tiS1l2`)b zyx^evDC`01U8t^WDs`V!WLNnQ{7QhY@V`PuPbzi-hpv*=A>D~oH6466xJQ;9Pj=8v zn-P1+PGp4iah30{nwJE$27MmB*fo~uN4ZHf8t>wzE1S<*3U)r%FIE3s)P_nSIWx84jx&-E06)v zM>8%VkdSalT^3jKX@OQ@j-U_0RZFV_30baX^B`+$i=$7<81$_8N;)5Xc4nvJ&k|{% z%ZxwMk1>Ba%Y_PHVq=GfzP{a_-KpMH=P;QiDbcb>k?)9vTa-OWM*K@L7HotQu)kcA zay)@t(9G&f@TyuU=p|3(Gm)oPa8R}$byd|K!sWX8h034cwGodC`(SqM%=UIfKhZXu z6f7kbP&~QIqz762Y(OLxNX~LJs(4vc8f-}E4#4b>%4 zs{9{{s3vX7d}r*Jm=dQiJ%9f?U@+xH`M!rEU;F(gTsu}kC;Zn_r(=sXTB+7FB;6aK z-PGIf*+OW!1`k>!l!9n=wXcYQUABZT^YYCbclxQf8#QDkA}6w$2zjph!$8=?C;IIP z9e|*MCXOo>Nhazt7244?`dLVl^k4btle3Bw z5KE}Z#4Qym`okY$KavEAnrjeE9_es<(3TptLLaeUjkh$)O)r@=m3k@;j9d`Vq}dUS z6Xg$BenN-WW`|7dPYY!=3}sBS_)U%0b$?1kVzkzrJqk$#zD!E0m)KvQM+GtIzIqSP3iH)bC^ z(lKqu#dnJ{cj1wswZ(e6eIeg_>(ZJr|F&X6^7Q_GCXd&doB!OPc_b|(CzA4y&~58y z^KiwzajnV(0s4g$ro0Q#9G6{wqQVgQ#cP>l0Dc~GCT09O?)|8(?ab(a(pp++)nPY* z2iW9DA@Q`4M%P(YBR;OWTpFhFInVhqsQwgVGKGTj+AuX}?vTlw8+ZZOkg4_~NEGlm zJ!`^odB^-zIvJzh?*ZPjh(OJU<-JTaeRtDO0mRgQ;Ei%1S|IVVq;d~nbs^>EQEZLs zfx>I%Z4ZWH<>8_c0UU#91dW$w8~ZwIF>{kiyj%GmitkMQCpaFFxP0t@Y2S4jjetQ9 zQv3K|rsVuknNQ(S;;>gl7*VC_A{o+o-K9~rFq$dmo($7Tb+dc_+V}s~0?<=l*ahh! zbBqH{!?18fAzW`moQ>UnK=DP?^6F|{Z}<-Wo6{_Q^TKr<(iA-IKf4?PuNUue%C5e` z!OzMDDg788fU^Cl=J5UJt}F5pI&FO@Fgb;#Q&YH(Ge4f-+`3F{y1{yc?`smXNplNG`` zNh`%4EEw}K@ytZD?3OyZViXi+X~mava9gcD)}$2QyYuNz`9%iWx}PPfa?IU= zKN#UM4#OWz=t4oEicWYpnoBbHJ~n|-<(Vzvq%H6|G;vW!PIrh>#{y43!6L5XFm=U@ zYSsC1l`zRhOvKQ&PMlKNZX$v3b{($X#Sc2#I(fg3$)1ONY{2oZxJ8Q~E_s*!l-SUO z(ZTne)-NF7ku6o5T1G){8^7Y~a%fDxwWF8CBgK3J`{mv0Ajd;Q%igz{aXGJQ3w9LK zq+o=C2l3aZoTW5bBF$bb8`Ukt*(TEzyC}8u#X94|-j|Pm8Vu?zt5_TGv>|969hw8z8Z}KQuyF?ks5N7y(CXLo!*mcqUJXBs*;er zL-EX;-M%xHs{$@W7$0N4CE2le41aBdQ-v^h5eSWU<&9#H2Yca}u`;ViCNWkQC0;Kr z3+RGT1K_8|gOS@C8ZkQV%QoH&#)`uYmqXN%Ti3Hp#^f1Os>Sb&h=#DYyYZQZGPuW5 z7#|KUWG4rNd{vBn`bk7@j&H#T*INZCkXymx`ZD~^$YImTT zyx5<)5O6m$N9uE?8mY@1=Q_D|d>}eUHDnKX7{00FR&!#zs?@V`$v^YA{kfD9HZ61d zIvdvhygiY@xb6mBTUKJ`+}0lW%6&0@W4W~}fWhT5zy(|Bf(DmeTRbe{V;=QFCKJE; zl4Uo2&XZK^2}Wd>q-2~ZKzx;#$pI~^p|2O5)m`)>R*V!spR-v4-wjl2YB`m7##ZIC zOYOp*qzEu6jLu&Cs^N*x*w-W`c1^7Xp`Z`1`6n@8lmb`!y)Z-+ZIDO63vh3fO<}5t z21K!h!goo%w(_|$XBb9!==;~-=d$tjf&5-Nw06yQ=^wr#Y^hkJjQT?;4kRe${=w~mP1J9E8c$@2IG*3H!^QSe#nE+SJZq}!vIyjg|W45toCq=zW zvGN#jxYlt!lfmzn0a3kX1JZOwPBL-Ja1!|>`gxP^;;G1HebQ*U29hwd8|Lbi+b(r> zzqin9akyXnKSC4NYLN?-R1JxCs6L(w4`wWDbeODp-N$+1aH$4me-3`f6Z34~_+i$E zzm)1hR{k9Bti}x?X=E~B_zCCTayC-IBoD1(%rkwzzFf$!x3YEjirRvM_ldX1AF z|Cu$#O4#dFitorS4{^W5jGN)Ef=0FGKR|G^^|2+I1k^2*lxV+-!(HVa$W1F-=Sw^Y zW~CaGwan0w(P3gANcWP^3%MH+qb2LUGZ9??7CLH(>i2W!(qyUfe6{;TKwh|U^mB`P z2|HR^4LT)HoPYNw(L)vUri~=#a*iXazwA|{@ez8=>tI+4;+q3F(c-YV zl+=USy}3F!juKHc{#boDaUWiQgR%zKD>|NFyq}(v9YRcKC^7Kk$j_?BrR^vIu*KZo zErPzn%`-{wh8JDpV`;OuH^5V*>A?pgr59*n=cSrBk8gU~>IMdJZjMk@g)PU@`W<2w ztZlM_u#JWct~=1?NC}8Yx4COr$=^5>V>JmvBN=Q>Um&`6Tt$zF6uM4BavVer4+^CW zB3P%n=jBON0rzF#I}_8~3ABtpt3n)dDLHUMhri<>X_24@gh36j^-ssbJ(Ik5!rIU@ zUke#J;F-U_`PM?$#VO5s)I{foc0l${cKCb@rCu8HnLECACW9&a)0bKW!cgg~y<{tX zbB(d2S3Q>)*ZS$@$05}KAv2WOviTwgoSTJ2X^p9I^eE=wsgjOIPRsW8QE6TY_+_Wg zk9U>J9d4`eyg?+Wgk1~tGQz)U2Ble{_Pq_^^t*!FZqDA4Y6w-Is6NZLJRic z<&FApndHY7WD*S-a00`O{z-cO4)duNLi_Faapaoxod!LEh%qZ4mpvHC6youu$uV(`kdfM?RxGYhSJB%%WPQ~?*HVl-ud&GY zYt`;C%G{cZxs%0f52S@`7Q9TaakCjfJ!{QY0p*xASnw!ne$_`xMqlN;XC)rjBSG!S z9T*I}QhvXvhH!NAdmKl1h13N-R3)^1U|>w5s|oENCE;;+3kKdf9s7C zrWB6@eN%QD=r7GllI>7ckyBvLf-&ZG_>9(+unqAR{83^9T3f+Z77J`pM_P?)kTL4l_540zYzNm=MF1Fk4hb{gRX}#Ah{OU>L3X~+k^09{w zrC^}e&j{x3U|^=ZXMm3>X~*0jJ*|_=E7_4`ONx@^!#LV;ly9hJxG{EXBJZhW)r49> zxE@Bz;&)nb?=R)F0kow<6U|e$p_`^$dgGaE&W|G7nDXS;S!8v63MzBd0~sjR2{!hm zM7E*t2&f7}N;N44d*?YxmGqjkAUp8*wnXVgTvmZXr=NNTwY;qnXoMMA8%uFw@!3y9rWw$9!CBGl>?4GlS(Ur?*w*16RR1 z@b?Ks8#%UL#If`HEt642e@U(KEVr!|fu-z6#W222*hM{U{$MjUvCIyk!&BZoqPmr=DpUyXluZAw(Zye$BtC?s5@K zgi;Mb@{xm<<4_Bd;hGSnX4BF)IoMho9kmK>YR_nMBz$LHIP3WAGh*z3M z<1}@PX2AZ}ftZ286V zeZeLdhOWE{ajw)`x4L3VYf_3{b<&eSXtg>%D)Nz==9maqI=AcNQzV}jp&lI(Y8j`+ zufjzQ>d*zN97ARgaXXP2^v}D+IME+e88e@o4Bz^&<@!GbbJ6=Yp%J*p3x{e_7m#U-|o#fHAXDJ~hw zG#k6fl12M#3qC9ni;s?dNPiJmhcpd9q0F=(nzX~|Pf1%r2MzXnNp}pjFwMMcm+T{} z=5Grl3^Hdfxxa>Blwy`r0lx>a3!Mx}Ir=Ut1QvtF#gNNB1YcOAUMGJPUB{iSUiXFu zN8nmniWmGV;K`ix|ENIIaFXan<#>P?f+34cX3f$8R&>c$8g!q8t%Q|;G(z93ZVW5H zl-(zYpN4S;qt~wyebZmtaK8%Z^|)I@EZ*OQ@w;^4AL|uapbNp1P#xxemW;PNT(MDp zmu;)h5@^?=^glUsQJvifSuX}V_e9Bt*^x@cN?m~e~RZr zbbSzhvJYbY6{)1NrvPoCOSwG5-$aS=2R1HeIv=xELSlKd*9n)Hm678I+Vh;Lr2&T3|w2Sp84 zX{cN5v6%{(TC*Q4^jKFCc`ty2Uh(PTtH0=U`aydWKLiIAi#OvC@Dj=Uuym%Whzm8= z{#z}i>Sk+EG@9UeS(D@ zO2sbZc)tpqBJb%mT=bFZJF9_F+ZzRBiu>(c`{5zb-<%_ZyGFFI3NM+F@+^jLACa@c zW8(B#DQseD_UR8cBQ}j(m>)FF%R{z_s4#wH^xG7SpYTGr_!*(V{tWE43)??MPxqv1bgR8Cn3<28i^nW@5iT`o(ggf(2`Hk+p@-Ss zu3)m8W!DYc4@5FR4K2l53hPMow*|%H#De#>>Rh4sccJS?RvdI8lQCNkn}XQ$?v`<1 zytn-3Eie6iHu4g#(K$b8Xp~ON!0|4HA87WY<8hyu&7=?p*SIdq`6ytzlJ}GC=99t^ zN1yHdqxyWk-nOAXJi+(r;{Tmsl>fXFW}KpYr}t`tNVLtFgdFI1b{mwu&~1cl{lEY< zwT&bo`FFX)GC4hIN4n=BJ2Xb-2GV&~_JftmoqNj#?Ulq6^G17EHJWC;Vfg}>(a5Zx z2UD6ley1-~J|oGRXNs_#pGd6U20m$&`mK11v;DPYtz2kPiAR)jrew?uyY%RoTB^Ij1QA@1b|8V&zI_>V*gGVf^R~*n}q2N&jxKrb4rbY+L^Jr zR?}xW5o-OB$n2oO3}UOG7e_eiQ@R55=R{fPGp62^ zb}0G`a$v(0eY%RU*eR_H1HBC5a79hPFl8}kG3m#ikg2qigw=fi?r&_Fr3VU8i_w%8 z;!&MBY-rSX~6<*n@v&V2c8{z%pE|ixl4)e*T>c8c{11IQY($619vv< z^)Bvb>`bON{15p>2=lvk0u(hH#&PVnu7osiHGG>hVcrp=eseeinp=;P7&oDLJz8H) z91z*R?cl;enmO4)#MukX(P>i~&=gE1a@VnRoA-jciHo*%CC7CceZ<;`ePh?6R|n#j zFH4#GvF$s%)&{!wbwCLs4ZB(;)W68V0~4_+Y9F%HWe)WT=-=Q^!hCUHoJ=aOz1F{u zFSxhw@~Y+Xz(jNwWDfWgzIIgQ4J9}$&?#c6s;_=Lu1>CCqOwbg(r)FMPI!rK=eIvD zGo)FP>F%&nb2t){I#xi=E9Bl_hc=!&rGFBwaak@9@M_JpVA(312cclcpHPVCRqH00 z&0B-x3U2ub!S?^?Qj3Qo40S=sydO6w$RLi%#jswd{GoOStcwJWNB3G!hYRt5wfN^7 zOm0BPrEf@Qcw1}}UZ;YNxd-Q3^nO!euPq99mLVy*3%FI{2yw*9kZV=1-H@W=y?^(< zM1VLHo4jT2bE)Xqj~XKMRQRvLMsYJIm?3z?GA6IcRS`>ET?QbPSnC&K#}eI_gH8rL zaZ>G>7b^D4zv6}pOD5)TZoG_@Qb5r3Qt(O@;UG)o(wgjE8bQ3F$WTEsvse_I)C^{zbkx%2$Q+qI#<{Y`dh# zI@y^^Ub3fGeu|7rIoI*MlzWhGYMLjtrD{L-G`tzq1>reNIk7?xGm>MYk??rJrLpOS zUD>u3ED`M2S1U*YY?PZR*tEt_7=*1L(HIDsUc96ANxpc|$IeuCL*{LCA)yzOiu!6R z3fN`cB)L9F_74X6+XzyT5P%#>-LGJCy`4{AOWmv)s%9x6I!rH_;sSc7-oM~xQx?Xg zd7OH012D~Xw#^dt*NWBa8;6@$tDHdWM=g|GdM>=`cW#Pb{aw{4qOKyc%~dy_P}ub~ z+P3R(QV7+u2tE2|c8;KnnZ?-Qd5By+F%)sfGcaz==^Iyhi3^`>`%UgAbC{*aNnWEE zvY+c(SW8rI6*M?Mk!$)2v3*B`8F>A4yad8|+#Z)CFN^FYT~j}nk;}GqnC6aV?ErPZ z&>$VR49=Lw^CG|GQ%E$En{!|Wr&c`k8ol9u9ObEp9;`kdob#_C3sIR$E$c;h86OiX z6hw877$OY6Z-!1M#h%!HOaEB1RWjVG{d{=TVX_{3V@ga!^lAllNyds<-x6cluC(B5 zah@_VFzMYAMV@T17(IMb*;pL9=D0)gP)TXvAGu$h z85dRaK_g)SU6)pYI_{E)cS?|(z>^{wpjq|n-s5~qdSAd(j=+;{3lj7Ac*Ky zvOsGL(7x!fF@AhjIyu50Gf*4hkK$)JLIMZL?;Z8kabM^G%(S&H=Ccn64%uwe~O zCl*S-M@{JGx&X--2yQ07b?K|cl;n!CwJd}z?Qy#xWfJ3e2 zh`qXRytZyqTqTzW;X+s0cUh8D;#{Fyt72xZgZwWv>W&ys_bktf7;sz zR~5}3%c!7qe#p;*4lbL^QCJu}w6Uq?&6)1F?Z|L-bx^~mlxx|Y^8=_90Dk?dKQfqr zI5X;lM*rcPhn^Z^O%95WOkVqcsq=jw&V~&9g~%cLz=Q#b8J#JT{31jY9qgq{YmM*PSO;5;{W@@Y7Q*Bi1 z8!8^pWOA~4h-amgM0H^NMJ;9$Jd%gBc%S|_+srYSzVzR5abB@rU#eZyi+t4^NaR|k zONZm0dJsoPS30$8n{swZ`QTZa(zQ?6eWy7J!Ua2j%un>O8d&Er=E$D=j*-agV8%Nr zvC_hBjC5N#y9H(3zO0w;Ej4S#7tLT8e!pzFSqpgjLzHsmd#=nM6Ya~H`A3_fo`R*F zoB_D+w+xNn42p8ELN}n7VtIC3aRh2ZY@E2h#J^EA%!Iy=G>g>2I?<2xaC)mV2$YVx z!x`thzkP+Zf8qpHt=BHba_6D^(#QCwO~3O7f3t%mse}=|K4|p!_umwDyfdxl{|cpw zNby}UF3}Ii!_|4O~H*)%Oac zWJxZetLrDP(PeQVAe5<|=v=ne_{Anbt9qYBuTABa|3OkzQ_N>aqD_ae137f@Xd!ls=9jL>aqz0*c>FJM%X9|bB~tJJ)+R7Feq?u^R7Wi)%{wJJo@;YGEJybnSLN^u^kr+tWKA48hQ_LMR@qpQNt6iynIw{5 zBdd@SWwUmStxf4_P7l{D1gknMx6b4R_hW;Myb;wpn#%pj=j`khdD5sTV}(1; zhY~Ve7=fw(DDm`dyN5$JY|O`~Rn*gV!!*Z#KPLrVwpGO6A2W0?U{!oieAcQ{xl}3> zqpxGI|8BsG{!;kW6f~TU#_SD&0TD}!MhwlH_fe$~y#Z;jGd7MoBkF_dgIHamK$E#} z`=XNF6T`t?y#@02aHrr0_uvzbrG|d|Q;Jf&9iZvnw71@%j9>s#@+!tA@Gjp5Dmw8; zeY{sW!cQ-k0Pa21d+5h?O%)fb@_l7qf|UbdA}?>U>GcPOd7mfmv4zL&l~s&c>;*d0B5?URnb9 zbvF}OXRBGeK)tu{-UQikDF7;^#OM_I_M>8_t871_Y$&M`ID`>3nw1USMht3r<~&Np z7cNEDEhk5Trg>OrE_ens51^imIwPFK>7ayR%mC2$$M4ILCGL18*a^r*rdQ8~fvC@Iu&{$9?;ZtC! z#i+m%kx82o*1N0<#`q(E@sM^_`d1ss;~dMChj&K?aLXiKP)XkN zJ7AOtYYqg`R`?U5+ql$rQJ~p7XK%5o)1D5fH1CHfpi!fUcqBdOto7G1Ezg z0)X*OWc}T`bPZ4*! zzk7cur$R6N(I0d}8s$<1cxLI0E&~sa1l}{y2rS=xt{g2{|A+s=VHTlUY#xmVZ1KDP zYc)rv;)o=dSx#3)H4_cDjGM;5|6%K?0NcxfFWT{;SP9j70jbrvGJcVvE*t&Gqaolu7QY~BD4I$_^`64OulVNl>Z_9e?@`3U(`>d^H zSasGf41~wF#L_Xc{f}SUwttLJh(1WHQm*iluiis^OnM@lKlbUdLx=hy1d+S`ba!Df z?c(o)zs;Mxb$J58%C_-(6+i#;U8&8n2ThoUm8Dn9U2K53MHd<>k^0I zyKdZwBo?W4^~ySuC5T?Wdsy)CoDxF~_t>dAu8BgI28Ahnjj3r?8oMr9g)($1nB5m# zkE_HIqm|}6cRui8<9E%qV%%#+eBTCo)MJ$>9y` z5~A+x4I0PoKNud>?127M?uz9(B-eWEDQ)}pKB}bCE9TCrPoP2rH7xfsb z)H*HnD@%sFZ(tC%3|OY>NC8AWNuvU@u+j;|o}`GLdj zkyT~X^VMXRnuS>uVMdRyL_^hX*;=t7GM@cDf~H~9_O8uC&LjalrJNz?`)BL4R8+F~ zFpDhVuXx0LZ{J_5EvSjAdN;3h2vYHn5;9lSsE2V}V!$*ctO(r2rbL~YOzST;G!=(2 zC8RVSPurI&13eF(l2}UIJyY0?fljMqLv+bUNO^mFX}u<`utb*%QU8?SU0cMs-xLl$vndEG3DRRQ?ReS^9nK-c#?QOs>%D` z%6UC@MfyqC?c@8Nxa>pj=;1P{_jKWHj_Rc;>B^5iJAj|t<@9n$e!}gWho)`GSVI2#xx=}JpNKzdVFjxROU6L{`UOhe8DYq3yY)`R|6WHep~JQ9N8OBE z#${od{-E$vu@t<-}R#U4a2%EB+c+)7qtTR*!%<^4r6 zq2_Xli?8Ka9?R;M8jO`*K2U7;qMn{LAB#ClxhqsmCZ4xbMMnq~-&O4V6qmiz71eVg z9;LdCafI!&{Or@cFRN?{SRYFZ`7jYCLw1TgiUlv*LzfZTX?ps=mzNuV<=0C{*Iy8s z`6))NpO(k^51T)4KZ%`+R(T&wFlozGb^MjD zG`kh55;UWkXuyO*hqTM4>Ombq6h0>T!LK3nafFi>AEU9T)&1^dkD(A zrwU*P@2p&;^kfj9*&@%e@EnpaBJ0J7UsIGzOVNx*MaXQOXSn9yi6lN#q+{^+DJv!~ zVmz;Z#n!XA*AjM*ik-auL#!F!h4k`it7@~%$nSZ4o|2i1M=ML1?#rhvs%`H~6X|Fc zoON;zbhG=X&xM)%S&>&`?rhU9aY+v`-X6=@<4PgQKd;|TXn$*3>Puv)Z^1#gV(0NTSA2g>5_q>xIe9{=1_l``TMq1%pYCBAFKe<-f#z4+cYN2L5kRfywD+c9(5(E&iyyfjip=^n2wbLhth6NI6}cN1klRdR|o9^Q^uyQ5>cTvlUL z@~n4;Dqr*oLB%T`{xI(JvNf62ChHp2HnF`LK7CHnyWhSQQo2OHshZK3GXa|<9NNC) z?c3`rMsOh_fCp(uY5sxn@1I4#8ONg8$M(7+YC+N*NaxfpMn68D%Y7A= zOC){{wa)Y8P!SUBR9b@cv_iD7(ow6i80Bji*=jHEP(K9!wfGDH#irZRQuS!*6s8+P zyrTlyd51PqFgr!nG5a#Fts)`COn=yK?MYLbLUcMj^cUI$8n^KpQ;$RsG`xiu)unkg zlf_pey#n^`H>Z4CfKyhu!VD!zz9>oBN4U4`gwm-inX?R*!jA}UW{E!EMwW1v`Go67ScA=Gr`a`j<8tIWdKhONxs&S&7lnP?E@@Q z`7B1(b5J}p*RkZZyh)P`^i70uN8i19nx9grxctDr&sSJTEjjzrVN4(L($j}MYCej0IoTsiq3v5J?8~;?$md~ zh7ra?K<;udE@?myRHTo4zG*JFEUGeSK~mR6MKqP73-ZpX8Cs0mV#*hPtnkt4*E1_U zL@%WHp&i-LT*vS{4X6hbhBrM>J>A8Vkrbk+b8^|7y`N3)%THe|GJ2;0`anOY)6cwb zG2Bm~X$DR2zteaR>UeL#K%rc+*Ay8n51mt1!6_D26IY&abs5R;9gP!Tf76D$kzF^% zk=q?YpC4PoiSnDvChrIy=LmH9+2*sBhLQS$zNJPJQxpCeqPJX1MLQy8G=5eXJ7u9& zkw7rs3uaUnoq9`%$2dAwvX4XxSN@yv^o*g2?<~w5#PnsIKfQlwac0Sv;&@>Dq%zc1 zb-F&V+BTKhLpd7sC1~3wT574p9Jlh09i#uHrH&B^MwZlsD)A&yk?gb5-KT8#hcI-T z@y}uJ-c5wxlsVGpbp0%q6*Uq?NNes*pZqjuf~kM&D8uv*!?#?q@KN{3N4l?@ zXSUbhog-zKKZ5)^}Y z@jyC;FFp0J0^u--@#I3)_7KWK#_%dPWtxl@zB{VBAZet8z)P9wvUicuuHFn#c%-Zt zS}7Z#(N2Zui+2&C8YFgouM{SmbfEsTs{cqkb@(bT*VD#S8w#bhb>{=a^a?drSI6x? zYu+hEms8HeyvA60)UaQ!i*UzGdyK1{LT?;)xC z5uP$8;&C!?zGPX=d7haj>0+BTz5i5?cKPPK-s9_m$hjN^_+XaeY>oG4xF0RqX-%Pj z!W9lQ4VabZW%*>Lr+4JuwncK=il`9MG4Y&5Q~E}sS_{1eTG!j`o`}(C6)87=rTilG zfsWuk4N3YRJWSrBFH)I=&!0cj%6e0^jBXXuLJD{&c|CvN7+XA#b5pMQ!HrRJkU45j ze<~Z|%63<8QnotMW6)k##oycFRAn{#h!G{6yc~Jv6gmEZv943?Ao^zXDXnoM{q$3) zCZ^>5)l39c*IwL-k0+!!uQzMmj=laiowSc;xPSfnwHT(Q|9n_Aabu=$Lqtj}ToKd# z>f#`;C3Ckt7Q6*2!*>>-TLm=L5$SBbS7wt36SrAZ8A<^}etG<;D0q5(`}XY#QN@JK znm>rEV*D9vV0Ae~hbQZhV(BVvGKx$XtU5&@7uEfgc1Oz2KyIo^c`~YoRY|i4&}OJH zM`d=lPT-aW+w@4c$ZR$%_3|mr8W=O4ewcsz2z)rL|COcR-r!SzD;lH3eQBNsak^H30u1Plj7CqIL<*hUTmzcQ&5)Nu>`?MTp7&tkJD6z6sfH2J=mte^A@_ydb{lD$EUWf_a?t7gdrwIT#ZW(ua{bj6b2reXcdjhO zJb{bL9?$9Hbe4<&Vld%zY%f}j@ABbdVH*-lxnCMeFN%=GMyHbP!3aObf)C)ndqf!v zp1PE$9-kN3?Jsn&HV=pG`wx6DOhIR7-b{V-J+%|_`mNdS%2#jxar)Ny_^Er zJ9Pe=Q7F}IPJOr|_xbJHx5bt@>QI$hFoJ4Tg~oRsMx?}`*-GvHY_%W2#)1vRDhhfS zNtVK^DHeGSpJy@q>?#CHL{PT6p}DI+n*w6=rSG(d9@XOHrySp^8O7_{))O-xBV%5d zadNf_S;;ZckjJ}5<2xv8WoJ;rpXJ z(b`=emP_-vok>rzTC_qX1!<-nxLJ+0OZxB^|N85%KmYvmuYd9P-+zarlM+X-6|qc4 zpC;^wSByVBd;?LRbq>N9FFp4imr`pNuaze>y_1+vbv0qkDQmZ4mBWg{)5-;Z`Okhg z`>nUjs_y(ach!z&`t~O3BBO%vUGZK=cy`qmp%-B7yEk>^jJst@?zGFP&vu9N0}B=d zQO3-7%6HS`Zk707_H(wCNFdE{`@f=a$f%V;XTMSsz>BN=*s46M)rL9CFe6p=+p5Af zOyjIToohH&XfV)>XlBRFnMkHNa=)~aMk6D6@8cpL24LZ-cZ3{q!smys$HASfh$ z!3pU!*3?#sFSr1;%kNLi#cyc9|{JKnkt%_GdW-TiT&~8$M|k= z>YVQE!{6P&0VX8TD}{P$?-)|=Y4$yBiE3FxrE0MYXCr;5(<#;(=Bngwc*nj9mwz;N zCSU$1f*`zd0K+pNDh-On-G1jg$L##`&p-ZD2-TMSEJ>XT(crvFR;6Ne{6M93v8-0I zIWeau`u$PHr zo&IE{UfE(c zQZN;nknpCmW=}(xFx9DNC8pKq88tm&CK*lRKu=Zex1)=%BE^(*D%F_OcGCAb44#8B^(&dm0kGoYiwesoy5)nBvPIA_Io=S8z)xZc*OXq*6 zcYM+3a#P`Gh8M${-G6Lw`mz1@_xH3vly8}Yj25*hv+6X+%7YjzB+IA9J=Mm9a#d_H z6`W+|0MHAv(_hJI0~w4ns{@gKkrZl+wd)xy2!iey$D!;J$t;Mw?=kfG0$G%;O5&gYSXrp2<;F(z!>Z#m5_qaG>L3Cw96#xh<%GnzvUy6l@hp~BwxRrR)y=sXjMexU3@ z43i4qt6j#Rt7AiCy(Jx`*abll4olN7T=&1j$wRC?C+>lWk21S-qKO8B^!Gti@QQSj z!+;8Mqjuv<9X#<~#LFh_wYdxocr7e3-CK66osQ`#@l9vDn*7wB@|Q!np`_u{^kl@z zL8G3O^v~~pGHl-!b*A1!hbAlZC#Xk9Gnw&XoaaO4?o;(h&AnZW73us+B;(0C5yqsH zom8IKmTn`u%?W}a9GtI*2iz;qh7>Yu;y%-m>3pR=9!uf4tX*Q=10oXB6BT~U`|0Fp>gGe4D4iy{p@Bkq7dkO5kDhUXxq`tAefrTO-2){c>rVSJ_1`7x% zZBI{5e|8PojIWgSXJFv>KG%+Nd7qE3oFdUc#%Rmiu;b~p?7lbMo|P8_K@c8I*)NZW zrixy0O5dh~hpz?nBoC=}=cuF%IDIoX584(XJ3p3a1%oN-iq@wg2UqM^yTMAw8XqUT z`qAZYHH&o9-NCPW>qZh$jAZuIqRb73nu_to8BU}zn14N0={{#~ZgC^6PYnW?AdEpX z$56nUD%Vr*NaW}tj0yX-3@Nu-gUd=>5QO_uBJ|` zJ5D}M^wVO{iXU&HHOtJjA4%o&$m?h;1{``wb+Z0_`c7Np4Al zqmOPxvmueyizlAEdXvVm?1CWNF=3f@*(0~CI=YRkC=bw=I=Go#vP^OaDGSBt&v`)D= zKktLZco0kA)-V+2aX&VbLd%rYDATA)-mfH(E=ZUo_kJ(-uPr(+pG_ykzB)XnG?A1d zOsmI0ox|x7{xo=VI4IsX#z1>BiS_)UK(d1&x;d|yLB4&Ky-JzeS5dot&9(a^`dAIX zM85xBY_3#!v~#bRCW+tL3{?;WF?FGupME>`iYH(v#}}W~N3-@9*Jb^ms$rbCpA6~G zKmSY*0J`{fTKwP^_%RMW-p#3^(V+$H)%V?`(me|PEtQI<67HiviDhZ;erKz|3&ZU8z1h9rIwZlQ(;h$TZM0uy^zu9Lji+-c=~IdOfBy3y zPg`f_RHK&LmbrR!^+>h8k8g%_dsPp*^=e78<5+t-KQj`{w%rw;|0y)(Ng1=PY6F&z zoLlF=Gh?XN_v3m0jn7l)=g*%8LYIkPqJlxuocY1I=Q7Uc=Y7kh@lTWw*;nJm`I*^z z$@{WT);=@q_B(A)oZ78W*jp`z+2P2p+m;{*TkiuWx-*2V8K%RyIB+ZNUfM|Xi`jJh zy<;q-XWwSx9!#t~;o!xN+=ZQ==se?#8}FP4Rjn$wcwepq1Ytu{G3B_wR(u=it6M6jQuAW#8Q%RSyUo8h78yXR;O~ zrrg6Wh>xw^Y^b7)o0vK=j}MBP;4DszS<<||6~YoC2U=$9Nja}Mw;vSngsC7k12^81 zD%nramP}WfDKW<*GKYUq-XOhm3CG!(a9?@8qA$QY*XzsmY=Qn{stxmbf+DJuer_s61g*CBHGK$5CtFv_CH z-ED|uJ_q*sBDGub6|4TF^6yVU%RDV7(I4-RQrE%A$LsI`KQq%p-ivLlDA=7p7rY%& z5`)fw+N4c!UYO#a>2S{0WZ<&9jY+yFX<;<*M?d%}XWCh*xGT z)$3&%9$BERx*7ojhYoM3Bj) z?0Hkd3`H_a2{`Go%%AlBS5oiDz@oyQ63ITwU8>Y+=lwLiA!?%Zh#=J_%MMr-x~%>| zRT8cwjCA`af~n|KB6%nHAYw76TEVWR2GW%IS7P!Q#Ou>51~c*IGW3{Mw@eaaP-~kW zlvK^7JCV_4A|>4g@ee^b3!2q*w|jL6|3}=1|6_2}4uy}^q3U-JO%uRqkV2?!b?^e& z#RPWcJ#U$t4YE~(#RS}o&WY8RXLU3})9BE?njS9WrG29c+3wJpYkua}Z%k9sp*x=k zWkiW+5^vC-3!@tEFymSBr2alg^ZEN3krEj?T63Z#CKbtqLssS8@dl)uQPuLc|0ECu zk##}147u0k(bq@p+s&QQE3^De6X2%5H7LspXEO!)uyIT9#|C ztTV|tmuBHR20xPJX=p^2VuC6OBeYR(>Qn4<$EW|gcX%}CC*xD;!E@a!+GoI!`pKl- zRnt0DgUg&sTX88LX}lZCC1=6^7K@|@E|4PRs4`PDzaLFg1a;5X65=ae-wWr z1OUkGuqRP98$Rzohh&+|pi?|h4ZiAHM+yh=S3bw~{{H^YKmYhMYHZxc8$pXdBgTvTr4{YauP>2 zy%df5JT}kcH1J5xf0jF54W8Th1atSad=pI`(;W%b6rnGvxeRy6%Fkt@&|fL^T?)y2 zl6OZTd)TQCSx?jIRc*I$%WYi{#M%Ynk~eK#Q)}Xm$HNofs?m?teSgLa|3%UfDbS-T zkxbZp`l2c)lh6SC|`f*{H+ z2x9HJtnNnKL&|filT)($=-e3UMo7=jaIizxx#Jq?zY_R8i8MO?m8d7_PhCn4?{)S! z%{O`Mk#1xfL4Lw(+*6J_543k9^?&j?b^Ge}7LlOeteY=_ z6la<_hW1;tTN9elV~+pxyP-!x6&;~6XDe$b-A|Q+5d=|oL3p*xM6CUR#Qm?o{__9+ z`|rP}+F@C($UUv`V@91`QZi~iIe1{A#CfLL6!Ly<%T1IjWEYJ3;xEr&A5GyfNDg@4 z;L~oh=-_U@*J_5V%t*Rp%;rThcouom99&|2`=nq66B6wPJ($w3j8CE$WU7$q*tb{H z_zHKTP*qaZY74^IPj3+mLFh2@-PNeN%DTioBylIZs+zGk{m#Qtth6F2fldW2ol{|! z#&*at`7KZB_%2{~(xAGj=yGM^&bjq`bF#^_hg3Sw{@|-Ec$38Rh)?=E^X2x{&eFc- zv**5er}j|f8iX-k#co+c(?G1z^U*iz3SVD_J!pqYoMc|)21J~u1mV17-5M5Kf*{s@ zmn%+J**4-nUE8sLJ7MA2C&)mwfce^aY)~bFl((Zs2p=H4Gd=l2NZ@Ny3H7h~?D(&z z^H8xm%;qiw4=f!fkDuLxuN)_hq)2a4Zb_0csx5P2G%0X6OUfKE4x6vi$t%7hmYNGs~AS`*sU9LD?XxoT;@PQef zQ%SE-%;|di=#95;kJw0UA7+a!Gh6huzVbq`BEkGQ6-3?cXNC~ybQee)qd<}EtKAKf zLf&SzIry+j<;5^*ZEl)m{qI+V)5B9b-x4)7?4KHUei{rFd&;4MEh(n?{g$g9s1*@k zF6uq)9&`kLoa&~;-G!5q5>0|2?0fDkGmrQT)kU|HxX-lZ_^-Eh5A@dyQG&nw@(zfJ z?f!A?++mmL`K7yM#SyV_67EPR;hLJJR}?VS%Ou8BzvAuN$3KGyJleNc(stXTkZGQ@7ru#aHD3}0F?B(>-lbGA ztED_x*g)KU%6a;5Tf;XnjhrevNVFeSDI0H!#6Ou9dN%t&O>!TIESVOcw5~={k^7WM z^B%G3urY()+-n|Cp%Em>e`ED(S|9vLn#XE}*P5G4lZV!)_H}(=YU0B_hDN6t4-l@2 zwl?JCsS?c3zY`sS9H$ONV(r3%n87WlmRN!yJmR6#&$XKr?RO#W6>nZXhKa_#dHlH7 z3g&&$l`^H3fu-%caeM9c@{>drKx6~h-N{p19;%{^fyx|#BBOXrNq6DCr&f3(Y>f{^4g}#jtiAJK5^KLRarcLZEQJh4 z%ag|`jqBW1!%uTsjOvjpoZ#{mpT)-yZ|a{K2A`H+5EXU$^%UGp24fX6_)sPrwp>|K zrtff>W8SDfZf;mN%ufHyV6wSGmAICMpLSJdofFxLQZK^;L}+@It|cMMpZ+Z*#^8I6b+KWdLlLki=C8{V%{ja|lEI#blg#ITQI~=O^t4fHb-06~J#~8w29!RRPa?O2v`0NJ-^Eogad!dF z?H$*VSi2w`;l|EcyROiO5cet>Il5ZzICwlk;ve2=1(Mb2?a+}ld|;E#K6DytI*g_R zNYB@*Wob&F{a&YCX;Y>3WSo^D&$8Dn4z;=(JIe1+@#*_6jsL#Az2WCW-D;|AnO&BG z1v`2^rj@MIRNnj2gpqKOOtl`OTT=6?-;ucyUiR@X2*S~>(+*G2Mg2VDKIb~ftbL{v zMdaL|kRNqIwJSrw%4BBugMm9yri^y^6(5$M;2UFxY6hBCJn05Q7{D(uYs>NRw|w*! z>I6{K9y*xXZ%0T2{f|KdrYX4zA23?68rXlj*^v0Jj)KH__oeUmdVa`&@{$=lU1frB zWbUpj^eDtVP*QI&k~a9{$`hVj z<9D$3=4rpYE#Ru1Z~?yF{Hq`chrNE~=Jagh?wQl5?fdUnctUSITOVQ(K;$3Ghc_3= zaI^Vzt;e^F#f|iLp>LRjvsC5st7VPmf&+TI%xMgcjm^t-s@Qq`D^AD|tN1zp`1qKV z+JA92Pqp8<{NOWVnVF1z&D^7dyM5Kc<2{zsgBT2cL3<)l%MVOdj8Y@fMY+(~oiRbYU-fUYc6nl??< zlNqo~DKrm|72c6SokAMT&Z9iLO@(8%zp-& zjwBvcF;&FnXRNXndcix?p|aY2+9w?3%<&igrqD|VR}ch&5qB?%vCLA?6Ta~}7|x`s z8038D{Jo^_$nsN*$?#5do7FH#?18&b?Ju@=A~8ed>WH7mQr!?=E%o|g9*FWM9eMQ_ z_DcaHB|l<=*+kFcF5b%UOu^UKwXM- zGN%akD%qYUN)QBLKXD%n302gD4Rf=?iU9;)zx3*<$mf51tck(4{CLyKCsETBx^T$$xCzW?52EO(ayFqu&{BWgX`PMw z%aBp7Vil{6WiT)3$DhjaIaem}51QDd^N&wctR+}F1ywN&#zKKukDnWy+ZRrx#_edn zj-HRHP5T^GsBowXSh?XQuStCx?WlBL&nKGS&a|#ab327VC)$y;=|tzAEC|B60&?M4 z#2p!ffy6m2HtP36GEk^jDH&4Gneyh2Df_1LuT#v5yHGVTMJGG^T42iUarij7R0icV z6)mguIbjPk$4`#6Ppf0Ouzhu>8C9nv={|pYwraAkwXi97H*k(mr8||Po#)+Wp!ob- zSlX@ZTWIAs^1^Gd_T|ab6ucdZvInmMtk*y0NhJtEGhL#~_Rz%La~IE_Fu`0U-GfqM znX{~P;a;vYr4;)f^PToX{*xrZ*-@_Fg_rc1O7Mk5-F#rZ+~aadDR^Su^V-j!n~hFW zM;FUFG(B&kF{CXwwoYUq&o zW9~9qjiHCkjulZs5X9Pr4aD8^Kd-tDqLE5Kg6&bNr!V#dfL8+UW-#LH@bz%W(ugGuw}@*e8F?yTt$y)y7d}2d@DTWhvdg1spk0~OtCPEX zBlbYhLzdmgqQS^=8J>MF|2qO{KF)*Wu$0{%QwTx4ad{8BM@(9pR$s2yN#-sHr=#q; zNKZiAy?q`gx$kxN4?6YELjn~JgkF;#t4nE3FhM6W=p7G5OhHwv8CI_bcm~{Ag-AW@ z)9Nw4BbD4Gjbw%@{qw(XZ*SA`B@7_2ZFAj}#@Dfr(%f<|aSy&UA-`U|z!PkFpL)(M z3`0RBChhRK_UE+GO;Z52GO^t{b>#DCLXh5Mkj?8H7KGEWcHsoXefF>%NABm(p9Wp- zm$?&Sn?MBUy#CU9&C-`Wc=?klEo#J!GT((|vX=KcH|v{xf6g;Pcc9Y46W>K3_~l`}8tO4KaP&R0D|%3h@mVL;MSzt7RwPr_qk|5)4CapvvriLg!<7ECWrCTb-MLO@HuBJ@=0Oa;Q?K$m+&%R&3b(k_2i7vT+3M~g z2*LsH61qrFL)?cpX5ycJ{;4u0yFD&~^MFxBZ%8rr>z@KSOG{LV{;~>DhLotY3rpJ9 z`4d-b3?a(C`S0Ytcnc@)EdDuBpJV&^FNU8Z=GV<7)F<2a1N+>4v}S{zbF|Y83j2&_&I0$s||Hcd4{2RlN&>aIOnqx4|@Xpr(r_uBn^f2wjEJ3>%F z5Dt5b&?KCRxX*;;K*(SE*WC2FnZl{qbDCtGdh7HIBZR)=)tEk70_|JwLdDA~g1elq zS+8l?5;IcL9fyESV2B^^F+6PA(-UBLzYP5O=bzy`@#%KY+A9rAP{_=UPccl8$a{~- zB~4F*$wS>hc{>~N&K*x9J(-qwEmZxbd5yGpvP!E3K@grq+ygmI?GdXxKKEYavU2~v zAA?Wxp!H$UC6l}kaj@}io-8Y}Tm}Z6_qpuEvdk`LCmrv3tL-nnoq3b-kop8~Ml|Pb z3XQyp8VdNitmx%QW3?YB3d5_jwbKb0dplJeAz z%0DlZWfufNcm{DF2~?lq^EY3gd9B1Pp3-4IAWkdO8@*>;O}5&9T37v~(pV*ZAf+ZS z;c3@2ZYS9+vPYrKZTO*n0FYX>ET7iX(It4r_;h&acp3!mKCeGg>HdtujC6F8}M;f<>n?ssq*9j~Lg79$S9<&*FFGeno>gPar z(mQ_e6st^2!eFqkR@GI3( z3v9Uhd>CO!qK9HrzfBair#w5P?R}Fbb1hU+F;C_pR4^Y+EmP6f*CC^!?0ajov+oVP zPBF1OZsg4ktXMY0q9#EQ1mPjX{r&wtFw4|C#s8BxCrTUHR8P}%Q=zv`=czOP3h&R^+*>M|eeFD&Zy$uWB`AMQ#r@Gh`PkcgWO?1;>nKxK%_!v_`m! zoq9pwaa{Hm^>I-MrLYgwG-Wqu@))$~pD#Wm#*r)^q2niOACoX%*uN^Sbh^?LhBWuB z`Y}}mMa<(H86=)vP2MRqCmGisxdA}GBu0lr5Cq{F#NFFw`}F7hMB0I9Q~r+#MXFv) zRWg`!^p3Lu@BPFnAX#b%ivvj9`4k0jAEUaXO+|ZYD^~xG4+cWjZ`u*or^Cad`H-GZ z%NP4&H>>3RvPmay+^-neN|!?Z+OhFYcVX$~UUgTUFT!d- zIsl#?t|BY`^sTlqyP1Y>RefaBI4#Y!+wV1*x3{-x6k|@XZeOc!Cqb{YG(K_*c97Qd ztyjMAMD$(9=n->HQWcxZTVtc(3VMx zD|;5gFT)oD!A+wGG!FOQLPC$Ex!R`D&Qo5?o|eWg3tLkYo4{!*srsCM(lC{%ZZI~h z#_yLnEL%>otT$?~j2s#L&}MZgWacjhp}cpDNjW_+^i2IdtHW_#7Lr~RCqgKTCo!sU zm)YKT!jsEK5ClPZIB^em8L-PlCfH_yvcXn8v6011L1d>e813JPrQ)31rFvSmRWk}|5a29zYZ zxg~-X8d=g)X`t$>iYCX+^@?g=HgU~PjD)KSJOF4CL0`#=Cg_2YW6pl0)dLat+sBQB z=?%W`Rc0M?@ac|MQO(&YyA=f$XQ7hV>Pz?N@8$IAGMx^MAPB;D68EavP%|aT<<#ku zpt6m(I$usi*p)n>qOc*EmwH8W2lrHyW4~P;tJM1rDSy?O)xIuMq;C4iez2~f*~1k% zI#vUt=EuugcvY*nn(-?9ON=0-;EBz*m}1H+N5+Q-^i$=05*4U)xv9cKa%o3GbxF z?MupX$^7m~cSoe~8w0!xUk-vG2p1&oLF9mmXWoM|)i-lWjmc~jhoHn9)9QqdFQxOG z)nOB&qC->I zerUjigADdTX?S^=v^qbH`{%s)`pa^69ScDagi{jtz%tY9cwj%McBq`iNM+~N2Mm&F z{H^(OX+NWs-=w8iorX$VACufuJTx)2Os->4f>{~bkY8D@S72zAo)~GNCo0s#n<0H3 zf`qrXx0$W?o-=9KfEJL}t|B-KYrz1Fb8)F+gg(fUsg8~y2*PoRyVo&WRw`PtfwYE| zbHSyMeaW-^i^0P z{P}?~l2ImsVO2K2V+zevgNKZNKj3o*{RaQ% zE2>kgS$ld|nu0=PqTo6O#0U>~cBNsw=0^|&;kd*-aDw3Jkt%1lrgqZYb46{Dpa1wjywPTW)5 z!KIBLrf@3a$gLO&<4iZ61_K?sK&)v#K0cb=h^%nJ;iTC&d7ZCk0)FZ6kQzaxQO%~o zR}&I~jVkx=@#|mA*C7y^|NQ*ZnCfXaIoNq~NvBWBJB0Y)>?Dl|&y{W$|2y)jRb2}@ zYJwmLMsg@U0qPY-u$@M4)`OyHnnvp;_Ps1`%2+GzBaxf1P2 z?em|*+V7Ru7ymm&GX=XH~V|hX(F4Bq^a}q?|a%he+Ump z)jYNHqp48JcSH(DVOq*eF^msgd}Znk5eMD(;`MX|KRuKfDK&e9old{&m!uv&a=vcU zyd=c}PfFhfK@fx!5ciOAABu%Zj0OW6R)G9QpXQPY7vwy6Q&DV6fA^KuPGJUVDV5su zZIWoGD-tA(N!1`jVPb_%WR;3e3mmIz-BjZg1T$f@p&9Blz47dPY-HFzPM=55@6)6C zKY$QFRMhhVG=(@0Jt9ch6hEIjD0)q(Nva?S!ikA{FesdM-QLQBJjKJCeru!>wBq{K zHu59BlO1wH68}~>qo>>FU1QVnV^(rm1RN?^Ne0?_-XmO}gT9KP2m!hKd~>ARKQRNs zd6dUj(8)27^7+qY*CDLk3;_lPZ)efTaAy2yQL?}Mn`>XXlb#4VUVqlcU>L`Ma-SwYozVD*HG2 z+4ueLUlUvTx+YT)1VIpf_VFlW(Q7SA93k@XUNqa~Pj%x34`@Nh>7- z>-UgT4@vs)Eu(e4BAT~ACM1F&2!im<#2uMv+Uvfen1N_|R}ggIww3TYjRdT&rmEaF zZdt?+>FVZyJ0D2*qH^rvYaO97fvg5tk;U(KtqL2Qzcsong|4XfwR!FM*6ha=cD5=4 zp85D7Qm>XxI(C-gns=e>f*=TjAbclr58TKn;HS_9J;E(Zkye_GB?+jS7InBg_BrbO ziSX&vj;7fOJZ&MgWIvUP!@ob%?LN_-iWVxBPG|5PRZLpOI=}mQ{tTtN*Rq>4YftM? zy;{ao{E)B@iuS3l;q-l{1X?d4Q0$^;CdC#0*@08*CiI zkb=~n1OUAAROqQxRevstPRF088r$UVq*1G7_B4HEK$Oqd_D>NBLAs^8k&p)I4(Ud^ zJC;Veq*J8>TDM7mQ#x_9Z0_s0M8erIoH=Hy)GTxTfPEsanAi%(8GeX}ht#7@a&Re+gNEmhLoD5G+m9+Me+|g ze>TtdwpBjsytfId^-?E~oFV0op>EZn{mt#9VKDLy?DbHslwVSohOSx^f{y>GFgy0` ztslwozBS& z!NkN5nJ|)g+U3jlhm%S_sZ_2?hmtXDip{l)`A4W&GQArymp7<~PCwJRqlG2Z+pW#I zf#PVw8{YwSPi(LMkkH7X24n#~bjhZ}7L4ZrX7zd}Qn~YtMU}|r&)HN*F zGY}{kA@;cZ=Ci;EbYye_=#wSDTYkneb&DG5VMJiKFS7F0$)D3zS%=5elc0pRD1IcG zv{T56rsuP;x7EJTS4!@Mgzam8KlreDUbLQno#8o@r4^l}zv~^zLKaOQ=YAZ|LuePq zO5r0o{Zb3KgO zpEwUi8MYq?nPMuRl)3zgg?AO4J=}Tqd4JsAZ~yJU7(I&QTRk;N3w}BuUG$vKXz`yq zB|ws=5PGL&p>RMeiCR7m9rv2cJ>OqOH9U^d4zW(B1N@TN=in&xYv664R>G@1@sCJT z^frG8-xp@FrrPqWXMdfgY{KIzvqGvYnDXsY4_CY`c%EBkC;X*p&ZANO?e{o_rne}x zoIf5Ns*jA%gt z-KpqSy-t%kOx-RCpf8@I%kz)>GCkOUmw*GXVv3?sl|3`andB<_t~p@37y~q;vcpPn zvsWTt25bkG>?6dr4MOPW7ynP?gU>NQE)-{Z z)-_8Lz3%kCebagO+G`tTki*WB+|{-#Ge2r-AJ@G8_GSqg%(wnH+#zlAS&-;Fl+_XQR1pdC=pJxk6aiYLT1WNrb-$BT4?F7l9HsQ4FmFU!2%QGr%9onR z*nDigF_mE{|L@yEux5Lq6~@AdRKlv5M(OQjy5O<8S~5Z*%B+_SV&csP#b~FS02xn#+O3P@xuU$+rB>TnDW+u0USv-uC z6~FQFiim3xZ?c{?X}D&foel_mQ}y8q+f<;5F<`VH%GJZF#>frzKgG=vM@6$mOQLJbuRVULv=2%9J>b}QOg@0tQAJe@W#2K?P3Z}_nJ3$``#5??l6kmq|UZnAo^1 z2@WOLJ85P!F$zI`eVDTo5%iq4Jwg@xM@a6mX4EfoL4Pm195Ix?7*{7dbx$HVTve3O z$3dTLSZs^Rpq=Wok~q)rWs>OQh_m{Y{f~9I>;v+6|0i#0ZGEJ49k|8$xu!hy6wuBA zHnXc@sHVMMiN{NY3cU(w2>a!mi0WBZ1f}|YUqKNrGm(^aKj^r+W>uLERU9B)sXsr7 zBIdtB*GEVDumvT~lBwTid<#c8MQIl+8bIHql5Ut8+` zK4Ggy`#Yo6d$3hci`By{GEygpC`8Rzi1I^HPguM+W=>C?idw-cds`Zi`U2*}<0N&< zmDfZyY!HC$i`lcXNLFoeX%-*6S-g@obtMA<<>e3a%o5ip`7zEZx{BQO7}tD38ii9p zizMWPpvW9Dgjl#|h0m%7Jb`FM_9IcLYv{c2X&*Bm- zX5|RkYX!Ldo#tTf3bmz&d8XT zzb&3707|znid@m>yHnVa{pU~i5!vUy$yhC17Hx1N&Uw}hm&&+uD#3%&jz#;{igihU znG6=1@KpS`(;c2^is;JgoR4}&HOZ`_4d_|*7!Lr`{#R@tUPf`e5|4#)R#(zd7mv1P z1;vYR#-oK=g=NK%6mQ-N8gfRxYmE#-$(=euhhdXAs6B0DxW8JvNW#0WGA>G!lBKmx3pf>v{fLvevq8T(JMeeuJrB6Ma*t=Q0wm75 z&sLVL8bs%xO@;qAL?>`v;QV$6MeWyN?dU$Qi6JW8m#5C70`WN(wOWRkjr3r)i|wt4 zd-p#S)A1H1pDP9ZU}mIYOo`}0I^>c(R&|-_Rdb!YRzJQl*ZK6hF_hL^B1^DL;Z#zw z&s>O07R{8fUvaam>q%l^%%UC7e1Uf5*v5p$)$aPT0zz9!S^^+wFK#j((p5x5PCroD z;xYR$Md)dhaEe;#&ybLw9xcDRIG6;G53KmQHw|(bI#lwQ4wWOgsmD~@kTpt7c$V`l zap0wSzU&de_)FgEdovjAcII?`;zK-?nE0Q1;wg5otcm`)Epwkh9)9n@rE0b(_Q)9V z>O_i>P;k%;-O7W@GaMJuO0rn%7Sn4kjqjxJyMRwZ>9?8zhKLUpO$wPnU%=mKCL!zm z3OfD%uf1{$K>;HGwbFi8kNN_AJlB{1+J8%@AT?o#&g-9%X?mn}!WRoI9p)G$UP#5l*)N>|O*WKKB5eTR~WH^dHyh~>17z0YmunXe=(6@YGOVFCneqw7UsU}A|8%yTqE`Q--PgE7i1mlOxN}DHx~sk z7hN~?PIGkHDM=N!IdzrTIdx>NT?g~{BePtosor=mz?Eyed=EVxJ_~ZeiFjFg;E5^J zo)&wKM&$=*_sA``g_|TKQv;-S>?cq~cH6pJv3D*@AQkNA=)zC3*w+zS&P%d zOcZf-X?Dlt+*ZLSVp^F{CHk@RQJUaW><1o>_ik;oyAcFtWCc__-DripM;CalE0E?+ zBy;w2VilXHFM2vBfBpA1H#ZX@_rD7<--px^B;$9a6B@)vyeRAP8GfbL(udR*rRaP7 zi;GyoKs%%-$=1&FOIKxx) zBYiqf4nu)8r?VfOt{Gj}vn0o;kNIYy@Txq*XTB>z?pt}$+jX}S;6b2VTABwktxC-t z+DOM?ADGyNCjq{ieEP72Bf{w@=QPj)C~?gX3;RKZ>ACURYK*#m$^pLFn>`?4Pg4%} zsds&=w%R!rVDpf|KjS=9Pa0@eXVOkk{j=<7v}qUWm9;>$yQ3I_soH7Wl{%qwoNI+a zirtCd`>LHpO}NJYxmZUREs@ku;;3#xCblm2kK$Kq^SM;oKBR^Bf>GkoSC{o8!0szoX;o$pz0Teg>Shhl0ni`kcnPObg|ZY)VP$X(neb;;Q5h} z^wBm^`JotbfUG>L?mV&+OYUX}J#+y-x{IP0D*cUt@lpBeZ}ZL{fzdT;Crv5Ktw&PT z)!1XTe`bx&65G5E`}k4zZRIEHJ^?xQhFE;>ZqIWH)Gow95B7c-2ed zm*yzy-WX8LAw#T|UKYzA_c?JwIIf6Y2muHHU@DJl5>y$(jbR_Ek_!*@`t zMPE!EQ}SNKg((kPxRw4g-aA#U{R`fBhPA$^Coa1pcaEUE}=pFU*;b#g_;pg8?p4Fvh zQ+y-4!D~+g0|W9uG-u0q>h|}Qf>qRpt>2a@CG>)1q~};)4hb~yL(fd$9UzJ|G2t_KGz{jeXmIm{1VC;y;<3Ng-`8W`jcZ z%A!<$GYxfifUmPnYS9W6`;9D|s+*buC=%sYom<)kS9(D4C3tmU<#46ku}I0lP=tYU zj^$;=tP0D5`a~*Wog!2v%E{;QB|%nSi?Zk_ETOfJ%2KB)gKTlBns8#jw0Rj4a$lob zh#PKoFyV6U`(f_d}JU&X)2R9G*Chc zv^_n76F#k{p9@H4w|&;wiKR+i`uEqW>mSl!z_Z}V@_B_+MT2 zY{T7ta=_(LvcL5UHKsD}AveOHZ$J++-1>xi%1X(f4u)TT{E(6*d>E_tU}Sht7_4B3 z`~QEE`?tLAB&w?l_0hIWiwX54jUkdkNDBL%Z)3#%R|cd34R6_1k$EMzo0TC};nBUs zE_bgX_XS7l&t;K@quNbG6_LT;jO=Nd{T7VI{_lKyxFR6em`Kcr)9-WD4QC@2G;(N< zy_IW37Kk(zuWgjdJ-*)cULe%$H>VtbVYbmu*T5hvK_k+psd4gr4_= zuujde&O!fExXf47S{P-=CAWU=^7PRVs)Pm$hyCbC9dLX#vMh>-uTt;d>F#vS7$Ga4dYv}^QL3}qTtFY(*e8nOOb+T%}Hf=%1L zamw@T^D#he?u-zw+M%2Bu-y4^<2&u6fI6vhkn5^S!rjJe(Er^VR(-sPblo&Q1S%V_ zHjoun1>0z-r)|Nd!7CLJ%k5_7PIY&b&d`JTEa^9`tTlHIt>#)e3-p#;byoCJQ9-SGCqHakqPSgj^X&j`^C3Ml;pGVQwYo3`J z5?;iAC|)97LQ<9h>zj4HKHnyV$D5ndEec{7o-q}s^g8n@YjOh|5u6joZH%E*{}^XZ zt!U8-(#7E2f9?^o0~(99nvG@2P&&1}x07E^?8L|P8*NZ$U;DkY3Se3cQIrOIHvpk1 zitRFHH;ocJV2-bnyh5rxwU4VTl;hE7s8D1g&_36JI_k)8i~ynkq>nJ9FL z_X2zV-6XNp*tM>$RbBR5qb9wjNhTj+O zB`SZevf*B;r}xd8;(D5YDhfX%5xw!S(3tuWj*@_H7W#;~u1p;dqs5n2u%7i8w!{^l zNgfm6drL*dR{9>aZLzl8Xd{paP`E_U?@&6=Edkh8QGU6cMkrHNLsKI8S^>^jrCjzv zkMZEUI}6TccfjfQ`zaCjg+IC}<21rsZsMlby8{fET_o)8)MfP`1SEogV4NC`~$ci z_O>ln?f4HoT&0{k$Ap9041v#q4o5N@nAx1o6Xm(mqgBL!^f}6jpDcI`-? zhx>{ZCR@19sF?2X-P-U_c2bw-IKH9qQcEO&3!J|L$W!#r(q;-YXaZcCuLtubHOCe+ zrY#w=(vaL)NElJH%F1oRT0G0;a~yu~FmLS2=&IH|ZtwcuIylzR#>;eVCkCXv#X3o; zluMibRfy#AT}8!jjn^j&&X?M}8eIa=cX!zunI{&+FdFFjtYx-!u8tzsiTd=!Q~$57 zmXW&>@Z#9e=iNYy$95`v|SdPJ|uz=fdMpX3oi)C18)8xB5-+0tQ> zHqEwohY`U2^K0WzH&PfLfGA(*7LlN)i8}i(df3{mX4xWZo3oL~n1sefDt0KpW~Dlo z@ZH~yVav+MO)UD4Q(Zn0s-+D{ez=V&+iMX)s@|PWV^X44%F)I5ymlljTOgbLbAluT z?xK6ac+I{=l<8u(2RhmVsNGpCsj#iw>41jz>wVIO<*zzCL{;mYQvAYVuIpeIGo9pN z{xp`}47CB_P8_NoxvAwXfAFllHFv~o5T;kr=DJ;4&HPlc>Y>{fZ0Z!aE@)LVZx+KC zBq;PETVUbJjB7u)cgycEjg?5K`1bF!|61t%=Wd>a?>$B3TNa8_compN1u+ zSI_Dw@88`k{vxPbnawsf(P6dD!Hp|KwO$fv!|2UN!3MvITBoG-_W#G(}uj9j7sZMgTc@zL_6w0^WjLE zT7VpBAn@Q!?UkTtSU90N$j%{NKI%9nSobSZT;lW=FXD>EYg=o*sdEdrQwZyUwmaH2r66 zSifxUuz^CK6?c3IhzaEQk&4aDpTHK9Qyj4}- zy;He16x0Orq@!2+E-U&WjOZX|280r68*ZG9c>`5f5)=YPr?I&xfy*FnYqAil8_s@% zqN!9_S4_4-)s9&V%uR&xdAM;!5P?bP$IyvEF3VCHv+FDNbq*IBt5HU@5f-bC{M|?( zbF{AvRK~oH%LSszf-6B>ilFrG8u2=3Jupj?LVra-rA`41JUd0UOqqYl{W}B{_``K1 z>yPrCm@n+1<`a8<;LP&?(a}gR9{z)CTKCtVbxRvG&vSMF4`JPntg($Osc%KKs_Xgb z&osDFgQ3*z^ovNc*X}V}##sbSZTSIlgt(ux_F5XfZEypPLWEn_XAav}mvT>BO^$Wd z<c-ZaXZTqI(8l8e%i zX1K7=-;|J0;9hi=M|)hvxA_H(!Nze-#Z z3e5wZj)p)o$m2#~l1O51h(dpyo$Ea@B>{I8@5>4K`K~J=C|F#`wjKG_y}<%#CqOp{ zo{(E&Y3Fky-Prv4H~Lv#mtEbJ_mZ26b3XBRo(PPn?5jyZ4BMFh!m!^IiM&zu;3`3j zRxx~apB;^S5~;y63HDVfvO`(I1}DjRHd{bv7+m~PbK)S%`_qRe-PXHILfLmf-k_#* zTy~gG)=uZtT+KT+d2%M%Ba+7VMX|&z3cN&hTs#v$Uot8cziI4E`Jly@&DoCR6hB*3 z%1yJMk<+cAybv+yFu*u7NM%CFAm2cwHE^PQ(zA~x7!B+o9VE9x3%~x(>3U=eGUSRl zT}O?T%J&9|E1h}iDn^dn;=_Sut;F7g>YYpi+D@$q#~FCFPj^-g>$r4(%i!!hYC2x< zLz1;pFGC-8BN3DG*W{BJtR40rR^J_6X@MhJxTrW=WEZO}3IBY7Qst)7VZ} zU`?FpGasH^(R9dFO|gRVF6yW}m?v8^#9uGtW${h>7iaR|w7v0*CF%~9z2Y(xYW%pW zmaRsW$oEFCR)$M)*Q|r5BOeB+|JMF8C}Hwg?FD3RiWEoy{o3ao-FMkb;s&0o4ew(K zM|ZENE23XN$SUeG#ku{<>b^6;s5_-CkwfqxP%D9ELx!WkU1B&;EQcQ(FSrfq9nVQz z%}ULd2EP5eE}ocM>!lo2ou(~YsdCDfU@{dr^YeFz-VeHrQ+lKC{T6GbW(R_92}o7+ zR#+4dliLQIFcJKK+$1x;W^{}%3u8yOkr09*&!8z{5H2(SsM&_pR7bieRC9Wt-)6p2 za@ItWhfHS5ias-@@vsobAf_cz&WxVBdO?Ql(Ud>&N*$HwalpgCy?jN1uu5w#gTCl2 zd(u6VZn8tD<6cdJ&9Yr=SyN?_x6b_oug>(sJV_~!AB;RvR)nGc;oztK<=c*Gj&EcF ziR4z~(mdXZ;^+oZEud0Ni=1_aGF#N38vYigGfsg#ai7dShwL}_-L`&DAmDlX1!KRKRoZ2j~ph*%dIW( zuE#9G`>*_ZPFByfT1`|aFz8x$yCyoFdDTyW0^n-ggLJ4i08w5J^XT1b_Oerx8AlB)7! z*h;+Rxzt#~`DxGSb}|e?um0;8KVMCkCP#be7b|JoatS;rveZ?yGcywt99!sHsVmWG zKM~iM{-CJkT$RyC!rXH@*wzBcRSPG}OlZLxJ*BC?Iv5lgK}d}ys7RL2;RMeWQH;_@ z(`0`F6Ffwpk<{Tj4T#lLP$+PB3P`G(uSBXn>OIYrLSijPWYm|#XlT+Mm@xY^IIjN?*F6I)icm^g*&Qfu{d&?Oc7tueU4 zs{)BZ)uBsYgDzFKC2hO7Pm<_&prw2FbZiiwD?d)K82WWC$?fT;)HXrgr4Gf?#rr`6 zWI4XOvmuw7MI^3Ku1)}Q zPH@3NM4Rp2M@oSobs2ZPKq{q|+~Qq=9h8zOCvyi9%uK(qZ%Zqo!igRs60tz|g%E2@cL6*Z z)v^Pvlh`7zg5>M>Pt$mL?-fap$VRt!_|>sSkylh55om9YC#;;>wtGZX`nAr$!mk8ZVX@(DL^yIEcxsdIzs(ad$MPI zi%ne#aBMfUGM0QaFeDB#v^_<aFN2?YH}X{zNstW0hDum23b{7q+~7 zb}-!gZ^)kOn4l5E6CoWLp2H3En|$EKJ>nj<*5adLJ&J3qgqvB}yLvz7GN`SA;uc$NYbFIvc) zU>qyOS^2ZK9tBAAGMiICzsE%kJ`Jrp+5_118Eh-`yMl%$#zoD$`T5#en7w8uUm#LvjR&5li?3g+xF>?#{O>pBSYEBcW8ke@m1vj9{oq@gPKb?EDM^P>^U}nkLvvKAn;0?o{j2J7cBAkg!+T;Y ztzBo81~-@b|r+>S>Dywo=XnR&?x~;ESz8Z9$IcvZFLu#3$k&}RLOdoV_usC)SJ@N{n z%D*Z`F7N~q)3&jHt~kx`pX~Vh1RF&z95f=fc2)=;abd=Z#v$eM&xen@6UF+{g4ELo zD(no#x!M?~e^1$`cj*mD`9o0n^_{^wOz?bw_s=Y*R6v5``P)w!NFk8a$nBsZby!FB z?}R@CS6#JjPv_0(wC0ul<~up+57P1u{stNi$6Fz}^5E;? z!ZWbG3AL*X$KDepL(go?Y>mYl_-Y-i3xO0glHuQ1={7pCb(m~eDy5SWr2iV+&M0U< zE4+G}H@VMpMB~yPOMew0OG#SwOD4jtlmM}g08TdpAhCAh&z5#Wd`YKgDGkwWgyBX0 zC#p|QQo|DEj7+IC(9FoZBr~urd1C_o0QHZZqQQ@RzdZJTcj{|>il(5Hw=oS$qE_}) z8PZ_Ji(4`lE;H=%yDfb3IA%19MxK5IwT6AS19kWa^+^Xq>UI5y_Al&s%s=Euy+9Y) zeI4}XTJGXyOk{(G4z*?#6p=%?H2C@Fw9&0zqk}xn2V=Kz_}BS~M`)rh%RR;5^3H5` zWr{hz#G#V2G_%!?eFTO%7Cp4#8d8W@Cd;epnHLWy7~!3mt0@44yRQ+Z2dV~wVKv1Z zqaPi%wUQY+mbR^xreBpr7Sy~`PpkbP5P9_2!2L)qrXpO?pf(vJf=6W_{p~xc+?VDl zL&3|Ca*AU}<_^YT$ z(M2g_5}z;(K^4E6_D{jG@LDqit1Ja)gEbIsRj@$AoYK2yyBnlE#Pqg^N8C=2s(MT+ z!$2WHAhJb?zW&)|X=C-LK7Nj%uh+rsl!hEV!|o5WSz9yH2&JSQ3OI-3Bw5+tV%#`$ zM1_AIUm>F^Ob;Sq1kz5^8KH@Mk*yQ<$5ZDcCva$FjIS&_e(WVj+?7yga5;Viz*lr& zs!;?n)kmr7OjOX?T!g%tvig}!KH;ulVVszQwO8P}NaM~|&LC+0WhdR7-*9wzBSox? zBWU6?G1~SGzO_jUv{dDnt~q1GqhXOfoskY|I3LvH1G zS?;!$hLOFO^NDqhwGsIWeBsJD9M!d+KGLH`UEu;=So+T2>CyZY!DxhsF)x*Dcj4pe z4yHAX;CkT)19F#u5I@3V0uK9Q#FB64j}7v7H`4E!KOc1M*r=W}}hEb)M3W4d>}pBi{M z`mkSwD!}`uU9SZkEhp@fiEcRf)`%O@foU_Z4xl!jW=_mdf^&Nyt;u7kr7+E`EG9&8 zX7H%&SMlzMH9zK;Dqk&~Z4>#eC47g3$5*1!-g-b5g_^9qh)E@xtWcN}-5O6S>{n<) z6Zu@`xiuN7;TDET;`9y^XiQxf=dPORS3JK`+Yl-urrW>5p73k_CGY98bcVI>@b!QW zp=*W9D}U|vm7if^KHr~t-vtP{um$h-d6 z=8)aT@{gpSHmisdYc8K$ULB^H-2>QJ6<%hSD8XZEgg2RWH*N3-=_;LWPP?0Lvz4jt z=-?re)kx%F>P^FxL=DJK&0np5{RWL6^VT=zZ}0lP%R6RKWx^%D@=*`adBnN40gp@) zi}Sb*9kiF&t5>oB2>o*BODjE+q3$5{$Bg$rWgLslVh*9-pSr-1VfMr%2FdUMle?#4 zQG;c8l*kiCQz-zOo_a?wP}1x5`j;^AwpXJ{Hy*(jA>&@{b#%o_15oR3^F>0Sg3{fd zv?JqS<4|wIqc%;+1;5P~Z|^=dJ00DLz;_q6E1GHGlE+!^Y~Is9uq^-1e^Gh<9Uhi4spHXxBJQ{$u*AiO7uD6U{BS!kw+KT#^=SY4WKkfVuoLYAhvaN^&y+kAhMscm5;RZ($@bp616Mp@PZB3I)F7Z_lf04aEuV8&^2BVlIeWoK zA9O))I&L|=w0MC1p;x+}Sv{!a*0U@7ClWV32kQQ_pZcLj0J5j>Y-b{x?bIL>F|_Lu zd2&>GZ#UDvWGQyI?(i09B_c`EB!lK%Dw+M=GgJecQ5B1nt)7~q=t85GQg;=~#+1r6 zX@zLR#1WGUb)vC%Py@Dlk2+Mj-+Lb{Q4Jt|+_L)ZP z$dI#B>;1Zx+P%Ske9AD{(>#B%Lo#dQ8u;(UTG#JckPMGi!aj?@J;v_Bv`!Cz(1b&T zfksXuJ}XN@>c95`M^`~hz&-22O;&y8W^m}ycRHrf<&YlO5}25kasy5wO`H7b3T>fczp`H zC)7hRXHbcWj$`o4Ob99?u)e`1(HNO7+5Jy*#g*_=gf$|b`Ee|N$K;G05c7XDORacj zOD#{gUa^G9@p|0(P_QTa%}*tnxmU=2%CcTQ>i07Cr5b9fS1*D&XUx`;A)O7`2{PaI zI~2{d-{q$+$6*VNLxG;oo?54>XsaBoZgwxhmarFXUqx8d)vu2GTgV_hn}{-Ri=J7 z{NzkH&}MwAh1<^AQmV+HUW{yEacoLZ=~A1BS~k!EuxOLN@6`}09GOHwaJCbOpW0%P z;x9Oykd_~@moI!O%j8-e?w|ohM*mrzC(R|huWCcFkvd-2S9eN`__$9P>p%2>bL{S+ znpyC4FR*UR;8F;1PF0Ry${0d&~jNUi&ibvQO$+Yz6gRtERVBxS6z@AIrc8vAb%8quS;9v%WT5 z6m&iNBo4#Ue)PXoJHRiWdrb-5a?FSGx|1>R?e{iiQNV-&gT!)b<#H4|O|UO%kyumOnJ zNX<-U%SuYi(4DGALKZ_Wmc2anM*zY8Rgy+BPZQLt)M!7yz{yZ!9WSht> z>8(23e&Pw`iPW4syOF(qw_dmh5w%+peNF)G?H*5A3OsyHN@&(nbfQ#aAS-*X0p?se zK_$2nrDH(TF9-BsP8k>QDq5{~V4~uai;`vt;)!G_m=80cw-o z55!{`TymoUrg5}oWH=ITjOm-*6wr;TJ9t@gF*Y+WjNBt=ujen^UJ~U%(q?I{;O|8-m-#8vLRrG=UK$)l6_mZqX#C)JcC&{_#E*OH>RO?}Dsoj~= zgB%~cxjkOiXF4{^Yx(k0)j)M3EuCRke;!_GFJYDS94lyO1!Y`?;LX?{x5>_-^4&U2 zMbK9k9LwcB4Xj_mT_2Cg905Px1md82J!bk#y;`;a^K2;0xAO|_`)BnG_@w68rlDfp zERBJLtye8(-IQ|LcD-!@EMiHap;sYl=J&+!J3H zV*8Dk<0E>_ucF>tDsK|F?>&?aObWx2{yU(eA3a-qCg(JxEnUz4g4zK?Wa3-aHb_Mg zExWAGuYT65cD7bj9-XXMqomc-=2)d%2JE{|9(-6_M@?T^;#5lTorPa} z|F1`8{k3x2BT!Hf94Y+j8n(MBWIW>l6$_@zn7Q&TN&f~WC-3@0KB1SUnE7Fl-^y-p z$|S5MFa}o(n%`|5){C74>JzQ!;lbMY8P*$ZEwY z`nD&i2*aE9(;mtyqx*N<_A7r0yw?AkGM{qX+#qYo%q&h=pS+zao!RRNcQtSNI-ss4ccxpo4Nav&0<} z$Gj1^+xoX4gj%vnVtE!4)%-gbR)LG3BKIBEY+TQ}tz@L6nYKErvS5T56N!fZ8erFZ zfTZ`=)0+)NYf`CEYM5>0K!m034*yn#Y(`n}Y>Hg#RZO<{uubmbc%$rUN$YtLh~N3p z)jV8tbMAA#bCb+w4zHiel-B_MKkh^@T%9{GPs7*qs65z4VlK7yB<4Dt%Xxhbg6X=M zJdJ`cI)c8__ouByWTwu9aq_)q^G%G65YkBBBydvzHbo-6T%v#7;epSMLyj_gaO8)h zsYY-rv<_`{T zm?&Xip@)WIsfl?mAfu4y(WTA7rd}@{alKE)91E9I=$XG_y4RwtsrX9Wvagbe@ybxa z`I&K82I~dCLI(!r8WB0|hOI@_OmFlnCXW44s%to_Tl%d()seNHC*F7E9xCcEaH6QA zGbHyVA`WakE(d$Km~ha^YPnbW<(uay`m!AxyfN|RQ`$o0FQlPzQ^ zsBhd!c)WghvnD>yIbLnSWl!V#wGk+sQvPED^q9Ry65Jq_TV}+9LeQ6IK6kKV@814} zWOB<1U%u~Z@2EadF$V@V_*SeBuR0i7duL>%GkVvw`Q?ItVEkKuFr>y*p~nUTv`XH% zACo}S8Xr~C)pJb4Slz2uJSC8E|2hN0Fv18`6M&?0Htf_fR zG+*l61*jES_~{1kkwN`Mq%HV~b6CnR<2Jru%~u<0$nlg3G&?lue4PA~xUp~O;Gn&P z=U)Qp`c9F;-wAGLWZ~BW)wUN11~H@5g)Vcm$cD9N=~BR#$q9|~rCvO$YKk@Na|ZSthJDf{#L&Ed-%>$M zj6ySii};Ap@`(oJm#Sx-4LI4m{?+uWUZ)i^K*+(B6)OjBmk?nMDr-EHV=|bx&WC5J z!v>c+W;x`ncW&rrwuz?P9wS%^!_YUp{{E$9ch}$`{y|H9rI+*JuWlJW-*!#XkDb}Y zxF#Aenqp$Ej=ZZSR*x@C`mHH#EJ((I0v7Bc8RhyvM&R za_Wvmsi4H~uytEwX^&($9CF1A1m?G3IBe6_Umo=W3T+%rfO!o z)~|e4moa7vmrupVSWtenSE-xVls~q`6~OY_g0SA!GFbA9lrmEjR_$XfI+}Qa@wv|! zpaf5aZS*Iqa%qe03sCiW!pyM7kDD@GYwGq@YzbRIC&s7|UFWGS#~V=k`|teA9AakH zgtmLeFC;RSAgOvn5$SM#3zH`W+XjM>9!BbGj{PMXcESZyVcjmbZpL6#RrM)DKFd2^ z%)8D4D;u7>;i@XRd%_}w7b^zhLrZdt10O%*_?hoJ$uJ7L<$LGmZPj{*@>!On7M^c5 zh_eYjbKc5bvfcB`-sa#;2!$nL*g80jlxN?a|{lbeE#o%G67xMwuYTw!R?!_K@ zI&!}+^hVrkq&zTVS4P@*ecW0ZSi0}4)d~N5mCmn2+~Lg6y<+%sJa|42f&s)Yq~Hu& z1l70CnX0!x<_F)04Lq5rj>_&L_&whB6XT1Ob&iXG!sAa&Hs^iGN^Jh=8N4xoU;|r) zaR|8j9l1xvGb3Fo;}PC-p8ianK)`~Q=(_jS)%kw$Cx*E~l^YFy~bsE3> zEdLjnCgs(GRN$M`lyF8YwSuMU`lUSz&-9?M6D*<Bqx^1; zAy?OjF$S;H-s_$FrULV_d}F4VQzvQ;pN>mY5}yF)o^h=ZcLu6%Lr!0|@rd@G?_>Wh6>b^k4=T`Gv^%q|3M zt2d80hMFX3acu>h<=vXAc6I!w^=TRWvo|li!rrmsT`x|fr$>rZ|D_)wnboH zjyxMAds(#8XzX!T>9o)%H+$vH^SQJJMb(*WXG^P3>Xo4wpK#8g-6~mOW1aPw+Ej~F z+5eYZhZ@DL?w4)-avq1L2M+VC@6!fOWxwR#vMc;3gjT89Uz$CyQ2`4StYR`L9glum{S z0GCRoFmc5nOM}9$z-+zTYhl&drd2vd(es<2oWn>)U^RfaxShII^0y2!@2_(F#{Pny zhZ3is@q0(^CLtbrkqGZZ-SSpCF@TZMz)ewf86^D0osCxop;gBGF?#ti<(PH)8IAba zB}ud`KR9(`?`dQ}Q3xnYAq8 zN9^n?`VRa(al~nl`;Om{A32)9`S*8cwZ^U}t4evvKb&u~kLJ~A+4m~nJKgIp5ZAl@ z^Xkx^7*OD-7Jkos^Z#FWe&UUVD=*k>JH_6A+s00D-LPWh>F%x)1`T70T*48r@*E+sec<8m{+d|1M)j`dBO&)iR_OF5z1!Wj_DWId3=`v|rL$D;YJlD6-*!$o zJJ|l{seq+B3+mUazxWm|8Lm8j&{R`k9NHOKDTl0ZJvpTedgOAn(HQTD* z*J`w-H(bw@dHb`9YihB?lI^XED*poJIBancfE;0xF7Vw!(s^CgO}32Jhrd>*-gIBE z)7q})%ubtw%YK!}%6gxF-_6ft+Mif^zrL-$F0brg`M*@SgMM60IcPwI!RR-o7{Z`&}M#uNBeIGo}CQqV&McLJ0V0^@G z14=1@1}yILtKOP#c@?~lME#KbEGE#&$)*p1GKW5XTvpOupfB?+=8|XK&&?ihKD)hJ zmkk>9l{sQtn^m?-Yc~JgwR?Zf`@pcT`ziO!ja7@q|GnENSgw%ITrbYIC9}EdL%^k# zo&w+{6oP-wuaDnv!hLA(kIRhn|1MG%SDOXAuOWtDPGfiu?v`7cHGL1kt%nTaTQ3tz7%wEql`Sr z5QS^&G(q#lehi+eEtj2NI)C&|JbvfZA)sLvvQrAhUEZ_EUK5|2=nEW;0~!h>IF>T0 y0F%hWa{=tapmGd|EEs_*!7Sk7;0OOX4H(2?a&JcOoj8vH2s~Z=T-G@yGywolmP-== literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/styles/default/images/bg_header.png b/core/http/server/src/main/webapp/styles/default/images/bg_header.png new file mode 100644 index 0000000000000000000000000000000000000000..80cd16137ea4972db7a61f20ff3b072fb9034997 GIT binary patch literal 14711 zcmZX*Wl&pR)Gv${D^}bK!Hc#~pg?da?rz136nA%bcXzkq1b3I>?k>S4$j$$G-Vg8G z`z1Nao;Asw*=OyatuO^S33OCqR2Uc-bjhEhN-!|6R?urMFgz%dqCzUJ zD`#FvsVei!@0KP8%R##M8XE4(vBkeGg|`2haS&^J8eUUlM}>3r_#a3|`WyBTM@fe!&HQFDwEkNbG)MZMg=x4Vvj15SLQ8c1 z-#RJY|0@Q`K~F*Cax;>}x#QGnOBCS&KQ zI{W@9_D{U_^maG8$F?oUuE+;druKVJmF}Vy26>2(O_$PR?BOXNiZ$rZc$4h@_@vG& zq=KHN8heLc{n}D45lu=IB}$duJSne5y6AAYSyq;)JYD z73l&nB=g1fHhK0mLowgNEAnT*58 zcQ@yE2(Q0=b-z6_)3uEuWT#3u%XS(W;(u7X$;oRNz$r}0av5bP$?WiceJ1T#tTpIU zSgh9N>Uh0h#oV1@emw8Yux=aa!;jmgl8K`p7m4XmTy3&q1;3e1e|Fr9lL+2$JIoT; znYzQe|4P&FH4T*=+mdLy*eOwilatdfa^wl@zjKql_|%Fj3UPq!T_%mZB!=RBu=3`% zeUo>`oBeFP(ooiC6vMw@KAOl-<#M(ZH^6hE6A>QXMCx%?_YLVIAsfkKwByB^+j}4i zj)ismd6T;bo*E(9Bi|3lqv>t94S=l2?Gbi5hk3jN65-U>ULnsmTa6!0Hk)s7`zQ}j zZL@aOzO9>@+f5v?2T_~Vy6tGL0$;v-nd|U)nBE&n=(x%QjlLwt_~nFCLC*e8z0F+j zk7dkr%Fh-`r?BMNa=$!0Z2G)QudVR>9#6HU+Nc#DCZ1~B>$}bePMMBh?(Buwx|}XB zBfMR0k$*M*xr`|T{27wmq7~6e*>~RCC<(0C>hJHdI(|LKuo;|L<;=c|i+QJ(<A+ zi3uN0gVc*{u~3cXpB4g)CUigA6^8Eq0maIQXV zTQ1j|n5{IJ(}gwjV~!ff48&x)P;Hb-1J7Ej^WsfCuP}lBbi@^>`2$X>ZA9IKp`47nPN` zs}x3bQd4wAY>M=|yt4@yYS~m1L<}4an#~!D0Eg0@^h`{*xEZt94)<9pr$J=|BNgT4 zqY&!zsuZiFe8oMxU1i_(D`s!YaG|#;l(W9~zCDp0a@48zr4mNlENy4!rlE&_CGw_H z5!r6(JM`E#OLHpq4Sq>6qQ@vVASA9skyPC$?3&vUYKj-3+rLx5F~8k~B&oE9rDhxb z&c3$$6DeI$g{DLDR@WY<1(A1IbV>iffHX7Ck&qUjdZ7GOqf<<7N~HF7Xh7&IjH}qR9E(zj-Gh)d=W%iwO1>Hlnpx$l&VDM&9fdMZLQ~ zcV|NIt6Hq8=IMh&6JXffU> z^Mp4!`ujGc*=~1`+q==dFKYZWKIWafsKf2%fbUbPaCd}%f5gYg={7$mtXL11ij;oZ z2rHue!dV(nnM$zwSanL1$7P3ljx^Uiqd_axpmx>ND{iYk^TRC7c>;rv`p7;rSW}#i zG=}f`XZVdwIfT^VDVf3YjYS9r3nE!CBu>+#5VOsUzFVqTa1XGjjBY|FWc!SR+5sQL zCLoZ*ZQ&bRJ5{b)v5^0+JNqECi{b_5D%%~3$qAg=Ep!iJtLka&0D;zwoJF-HkIf94 zg)Kx>wu4jxB+ezS2wSfPNeaq!+!(qfe=ux6jtW%AHE*{}?6!pmKOAiXs2@7@TWk#; z7qo5GP4U;)#rs+j#hZ4rJuXJR^Qq~tg%n!Q6ZsU6J+=`N%p-~~YB#$6{)Zg!a1!7` zQg=nP{UmywVDTJw^rGTytXL=Kwrz9SehGZ7l2Gr)D#8x@yF(=VB7TVVfz;eLN3d8f zm8~a5zpMf8!wjY5_JMG_>Qa5MOSk)OyGj+QQV}zZ>nP&32O3q}liX)cxPxf89&=nQ z`pgeX#S5`gnf+Ll(ka)Z!7NYLTw_H|V~lpiBp)&s6tcfyQOC14DaDPHdo94O$tTS3 zD`ES4wh|-Hx+uZ4enS6UiXb8u881l?FsGAkPTgM_4{ZHekJd$_qpCw%Den}~P@eQf zy@^WiIPSVxVS%${X;D}whgG9Cm-u0b&9Q`wCZek2g z_@VlQF5A@*k}no9yw)DoQ=SlgVVLnfV2D(bVNY62DSg~7Mg=y}fDbdKT=Zm2qCC-R za*dTsN8Q5rWelsUvNBR&#qSSF^@JKz;C=hAU+Uh^$0b#W&1u)K7(M6SY1(a6`$|+L>0M`&cx8F5jI>>H-3qW@)uMdV_#Cx6FZb!8GT?O_Hxq40XMXJx^^UDX)d8CUU zcOSs|3>eb}4-LveS4z+`UQsY6b`%j6RNv6h@ZsHNJd?Qh>4Se_u%OxK-J(7Pp08vJ zKqLE`(O_h-@jw^Ps{sOte<*{;{TV|@ zbC>tq%hS6jcjsG;84jGk&t2@#Qb4LNQc9W=RX_rQa`(6I|YP0G4<@=ir%E4N= z8*qnY$`sl9uUJ_Bc3EMeG5^6y1YHgUHy9xBd<3`zYCXyOJpa2R<8|J9WlV{Fe>oK3 z{{gpd=eV~fDcw6Gw2AC*wGs#RYRmKA%{4yiAl0~|ffZ2^ zbN%;tflp>z-F|gf410SN`z5KW{hQVrXX=`{*^EB&8o5kV`M(ajA^K(}0#36#T5FGzU|&p|4lX^z*uI@>2supmHz!+=XH@59(ZGS2qv&6GgQ_G_ZD zTv#8kYghP8bdtb0|7hzjS4K_CPPqM6J7;Ftfp0te^I8;-+|cE{^=cDyRc>y#x}NVM z@vu6x8#cK$ng#^Ug{LJQhg_U*OBpjd=k?5#-}i6vG_QmA)0ncQb_xQLZhx{K&s>@xE>spAGxyLp=0u81wXKwRQZBa{0 zOL({MG4VG?L~Lcd8Wdc)?`c{mYUXt--BeBQcQrmn-p*05DR)K=Al#A19Ji6;aI(2_i&6lEK26qw~dQ>ymeNqP0~oZ;BUYgxVoxdH#XXBpNTsy%)Nznjn$H=br}q zfTK1oPY%<`%#9k*^{D-AYmZu?Mv&zVh#1y9n>Tvqip)n^uNEyfJ;mjVFrng%pi#AU z-p^-Y15R22Ng5Hn=X6AgBJgQV7Yl-Q%)fX(@MyNnrWe;o5Hq5@o9m&cW(T}U10tW! zONqd18O0;Jyu&>Bz@zhaR{C{2kq_h0{1SSnNZ@=1BcqBLtLp5pFy6RPQA?7VkKtTP zWPCCB-=L4u-)m!(#N$8RT_G-_yeI4)HvpC+wk<}UK)RNKjzRB3+=(m}La=wl1Ka15?ay+Ii8Qioo zgnwyB`;!YV$J4%%bcdxm9cH-TM%L4QfjqxN*7_T`YMBWB)|Sf*9GRN3K`5H2rB6_k=DS?G z+8t`v@APyd$3slQxT)6@t}QGi!BQT^^U+2%Mq?&)$2R}vSW_5=iXaj!GiasrvAjJPds10`?_08ujm|>uZe=B+iGZcBS4b%ysLd z6kGn+j%@-<;?N4>qgqRRTfZ1nDlz+oAnl~Meg+f_YzuwyF?)<(FM+|DviB(|RI-QF zj*LDFa0DnPM0cxFI$WOxgby-GskVLOV(qw{-R%MJC}5G3FC*C=ZpRVWu8;}ao$I=+ z-ywT<5kLM^1^N@ry=B;Rj-380iQxi1g+A^)x~$nrP(~3GjFjzFDlL$fFw09fTnV$@ zEjiT@pcb``SgECx9_o#|aSnPDjP6ri6Cx5j{J4SAf2|<1&+ju56joDC;cu^ykS+EQ z;0ss;xOkf7vY~0;ht74jl{vCmNMRd?zRZLFGQTGw@EphGa`)21Yjx#D^Jw|?(V>jd zs;bPH;1`WBOFmrtUc59P=_3;C5bGVUD0)`;H*S|}yhC+0 zwFRt(<7VsiHZ?}Heh8F|5g{@M+slR6vG%VST?6~u(=z=^vZf0sp41UABD!6wxmwE z2|jt)iZnBH4fM$B6>n_OWt;mChfnHX@Em6DUJ)Ksecd4aTIOD$k(t?7-q2w$;Hn;E z{Fy2~9Lc}~j~0X?dNMMij1?XpPQ2~XMo5&bqlRE0&jmMyPGGFHkO-&9Dd@~tslt*r zSPkZt@(@6g2+k8uo_{I+DqaPlF7(JjKJa41WBY@TKpo*D!lN?ND{`cS65xtc<@*A3 zwGMEtkAfb%CwfN!cmrc(%A`X{FX(>aG=^c*B2EhvMkK}UMr*~@n<4QvVh5F4xKPg4 zz;$;V&ds>{fZm=@b5OtGBI~FWe-SHF;3iTUlG=Cy_q!<(RoLIP%afiMmaf_4I%WdB z+_@HPDV*jMDH(O|;Q>nUJ(9YAf6GQj1F>=XHZ$`?LY#wg_cC2~!t$WVU;^hmA3=|U z;ue3DKQ+(z0oL=EZL*I0U5a;C_C)Q-m{PuB2^C;qf+vD|ac}7UwcG4UmF+b0kob>< zKTVs*){>~-sU(55_9RVxpt5qg{W%Bws_@G!euHUD030auzEc9~aMz13oq?3<>H^y$Logdgx~y(|GJ-*iR!}@2{5+0ddC+7lF3FeZyAF zTjSfMW$;KZ|F{`cp$IQulOO(;uBj|3@)zoz$l$6Wrrh>+MfcdUOMcm-6F8Qq5u@^B z|5i9TzZ!>FLy!1TUsS9Qtt;YfhoEaIL?O$1NnGPv_*Svoln1y~7}% zMi@M)u+mX1lP0{ICI=KAD^xU0?B0wd`bKN*>FRjys5n{EKhBKf#BZ(Yt+LdQ9msS3 z0)<)sHFdN;Gx46&#~sBustVhyhc^j9MOsn@OZultXLz}w^QUd2aZ z-fJMPGvS~wst@8Leg2DV+f8TSQxXoH9JTJ4LGEatZCk=6$~Oq&OV&0gYhdq^s3%Qq zOz9RssyC})7l&ge(gArNgvc}#oBw{vh*yaSWt~^h{2}q^iy;8#n#)|i58k^p{hO&= z>M8qryNi54-g-!D;#4|k1&?C@9jl{#?peOVAiG=ZQGP_Xa1f%_DMpbFhsV7oV>=is zML_VSA#5c8D7;?|;}bWD9B#c1BG4J%?;pNHJ6merTRP@^TcxT2+3X#5J%|Lirfp(UxvDlC{FTSpWu%k@ zg+1kavuL~2BVc4d#vYiADyI;^;~w5NEz&3GZ6%3Y{t5GmY}*Mvc4U5~NN3A$u@+~0 zT0_gID(+5s)NsNpDUSK@8qGrtrbAw90m}FlKf5~jOCWDbeYSlypCC$3tBuEDaD#TU zisQUY+g=p%ZNXbM!r1La)0W>NFfoHmDau4~alexO8q@G0^=}+3w6v*Gm(w#?5-*^^ zUw9nlh13tYm+ZVVwJMu*sw?5oH{nLH83H%AnGu(8mHEP*S-!LU~HZCLr6&)e!ZXCvES7mKncQOdU9f7;nqL2 zkVles$fSIl*?HNi(1~#5=FI}UNh;CvJqH`=GZog?(K;uzYI@b0Y8)tPLkR77?IA|}mX4EcTqz~KvFb&77fv2m=!2%!0bc%;aaA|xlk zWQ#}^95o~CSSyg|nz$rg(YXP>C|oCknh3h~k%+E5m%$evesNcyJSc_yr!3yGDOV04 z*4*5#sOi*-aPtx(2Y6GCW2I&CG0G6*xR%UUHsq$r(v)DJUX_7*aAUxS1Y3Q4& zQkCHZxBWG!1dMy&#Oxt?2Gh`Rn(ht9=|>Z?`$yc=CB_z;>bA_I(VoTbYT52C>-M8u z_5JL_wASUr+X(+hl35_`NcB*LRN;eZ;@)4OAgHmSSH*`i_H60y|Er%7>sO9@9qz}# zMnrJ0JvOQY_JY{?B#Y*Hw3LQ^^x;1zv|1KiO#_FdDAXMNXVFWDD&mpXu9X{S6R!9t z4VP=4UO5*owCowwzqz|^>W|e#y-z@70NR#G!-B2}t;C6{(b6}}wW_Y_l#;x5MvNWg z4Z#|&4cCGY?;+r$qzT;G-LEBj)Xx}dT@y4-a|-<51o-|m>=u^gJ98CvC&Werna6|v zoTrRq^n_;nygl&{ULthIMPH^-SQciN>=l>I+vgp9UsVZ4{!?|uIeX39F|q!7(0nZE zutKWuP!!pT`+Fzy#{Y0#LCJT69C0B*K9$XnOih?*!jJE^Kq(Jt@a@Q4*&D_*$Tji{ zjn=5M^nKxT!28+pVoi=U>I`BH_gmms=`s;u=mT-t_gVO?{CK4=P)Vgm?X#OvMGqe6 zu%|Xy4*0aEK|L(bj;hknS-fZy2|U~jk_ei6=@g$Q=g}^D z|Mpf*1~4%}daE+v(V;N7Y9>o9Mytc%=@ilcn8o=JXdsJ>ODB;}IagGhr~_4uo~8ue zU*xp(wcND62NG{M-~XxU_>P#TE2EeS-c%Fs-&b4@_`Rl6U|_L%8!DgWl1Y$uY7-TI9nL7zN)tsHgrbdrDO?7lD_UFB&MFx*P#2%q1BNMyDc(zvTd42?Og4t2{anSNf0^s@7(K7Edcn?w=>)CVVm_yjhwrsw z--@kQ^h@7*u>arC`x>cLZv2hlAJcRLqak74+`~ZEj(Is1wGt59P-U5@>@l^Lx}wM) zqlLQl>(<~Vwo`v$mzHh21mp07ooxjmR)+S|)jtE(mH*5Vz&A+^QmuC9^Jo(5mb~j! zqiCK_apFIEftco*+#oa?UfxR8;+$M+!yga1>4B{j6cxq8(ki1xqOu&`R0Wh3!$eBC zn~4642QFO@U6s~N#^(^KGFY!bf;73Y=Fus_m?ZSidvbFD) zOS!xV-*o#DBg1gz1o#%6YGd%yjb+Z12e3*wj_+myOjZODMGB~Q67m=Y{&giCaa6D+ z6uEGyZn+4iY`Tnm2V%=@wfx@c58F2+d>|gctyr@IFM*-h#LRtybCGGi)5`-%wu5av zq`6hyzI$9Xg^srmpy}XtrZ5u1NGHI`m8M)2oO*Z!wH99+_x9UPt4}fLSYu32bnHiH z$aT#Nt=2vA54cRbZnhJy{;GD4fa8%^Hhn(9~_}# zB$nQ-Cb)rt`dI5){2-8^banafT>5gR71iGIi%P!EAAfX4yD7+ebD(_x917ug>5~Xv z{-?c!b!<47!)@8XjJp!#n?HI!uXpu;Xl^QfqD_8C&!uRyD455KL!7YFd?KAwAGRh6 zo3VLxWW=DeMs9c4J)I?iMr&F&QO&MGY3-Zg2|#p(>nRkE{Zy+wk1fYX-VDu(Sly zrm8g0l3cXUKUuB;23bv8X+lXx{l}u*_>mCKLSRv9;~ro}*oP|Uf-gZuZ*+9j@VeLZ z(=q&?N1U_kN>%hE`d&3aN~k{P>$d5~Q}-*8da0_uee@q19B2Y z2KE_wc?A)L!0Wawer>A3A2%u^xaneA^|IJ^Le^9fr!M*F$aMV6-@)-(F(h2o1Q9n- zKD5Uy=LPOTn*YyyF^4+hT!IQWY4CR>-)2YzU#_R|<-9xW_earNQh6gkSH2)#nEVr@ zjrdu4Cy#5_!h85)k^X9b;eCkJ-Zc}uXyZ9CqGSiq+V&H=Fp$v_CP<3F`>LJxTVdc& zjHK*dTI-F=0!h5P^9eWDun_0j+4Mx*HU7)_G7ZoMIKvp~DVifO!)90APe<^t&G9&% z7b=^FP6W{^dOL|5-6dgu!MTH4eG({;tngB9U(Z4Z%U(jonnWaZ0wssO{gO3 zAdt*zXM`?Ysd0%C5?BXUOD?eObVp*Cu7XBp(n&@U+QCd z=^a!TSK)1-eU!yR@cH((f!MQ&xOS*5B!z$Q2M^IMSC*@|M8BHGMQGNnlH++520I>fu(+-pxnzC>DO zN=F*_5y(+OB1=VKEk&oiZ*qGy^QwV5gvk5jN9B;uZWPzfUQml9?WJ0mhSt&v+gQlt zT7i_rGT*MY>Th|cM2MX&orA*5!Lyg*N*WqI({RZ{Vf%RtxOjsc_BX>vOece~c(|YP zq=5#^$KGE)62k>&K3tZ$7+ow1SAUukif+!$HK32XY;GMaCi}$TMNu?~#Z5vkg8e+T z(404($&*0BoSO5pb5c?BhFg1|&G|=7SibvEMF8TWg8w&PZTY7r6>JsvCFq7&TBR>^ zXzbzox-a1_luTT@jy!wH`S6FsN?T~z4K8hsn8bSO4t~2sA^# zd4@V~sEuza=CM${UoC*WqLB&)c^MO~$X{@xAsGMt(D}ZYX`U*-A-@}|ORHDTy5GE1 z4ANFHZRM$UId8ZxlY{cb73?pc{uM zABNLtAEvw%_zE2MKiYz^pDm<=QM&iGFOm?$TiGy!9(5uA=Mk?_~&K-(b9=cOBGJ;kav*;s zJ7g@;yuKvX73scl|K2PiGMVxs{>Ze}txRM`LlgPqlDlQbh8Uu-zSV2>;6p7{u_Cs1 znH~XDk>WM!3r1%?ySIHI%l>AH;UdKR0wwsSy$-2xuv&vVJ~a83rZyk;CvPOn?;2PZ z4tIcu%{Nfz=wJ{9RoFwD^wO0}FD*LQ+cTR)b6P5oDeN)(bg|}A81~{;3yTOo6(p|mO088C)>x4TGN) z2)%<>pZNUoHdGqjS0hhe1{cv8ty{_&XilS^-S)mKQAXyv+(Fe~WxJ>S6bJS44)>7G zb)5t{a$14EIUX0S0CR=bVJR^ls321wgho)UZX$>XyVSPbCFb+kM{&#TPiVvD|2YP` zdb=+q1flvn8^Q!9T*O0(r!ovZ1)m8O|s+bL}(RGV@i#Ih%q zrKM<#rTehPs|I@`&&Uex{^!Qhgs*$+H&}(Dah@_{{&rGW+fAQDk{QIm;Cmfas|WoT z*wQO+Ab{6Lv+kr2C(+@PCDUfw^|Ye+ogpYBR! zKE+2O4cg3g`Mghl7KA|kkz%sLlGOs7qK}zkz|G9uZ%q=$C!YK>5$3rIRoYx_C*>7w zf>XePEjv)x#GP<7to^&gXOi>Q10li|BZm!;+Z?q%mAzR+XL_uJ;G*Yr z9*$WPSBVRRVA68PF=!s;F!|*~LY(;G+yPIkPN8 zY4=;2VQTM_vr^2vGeTVGXV=(`23=iC&Xl6J0*_aHolm|)M3VsNqwI=C3}8|qnc}YXn)q7{51nB$}rpY%i8|90rwKY*Sbh%>Tgovw3 z4C2Q$<;zdt*y4AW0rJ>m%7Y2N?<`Z@73T4|V~~6w@59Ma-%U0%ExSlm0hsffL^hLh zZwx3es4(naTJuRpO(}%M;d>u5j}M5TCf@4s{nM5+25f}G_+UqU%sISDUk~J(1rC}t#8$F~tueJw#Je@zVo1WcX!KC(yAGq6n9=Agx^7y_(L!UeY zor!*W6nl9CP?wJ<^ianEqyG!~_hY2z8xw^73G3{%>`M2&WNquR&W8;TfN7SK8vC!4 ziK{1)TV)RGwH7Mz>dY_l6nkPIfV&#VM*Rm=yVgLJ0!xyw`9aWNMd;q5pJ84JV3Hm5 z-H&PHB}cQ+$@awrUKOQxr~U@jM`Ag0UvYzGl2c}36MtvD^}4sk7u zLW3h5nAX4&+k{PAYjH=PQGR5$IiPQ~ zGFeA22-)#55Jye}o$`k7BYCNaKU9GV3F&Hno3HV1behf;a_|ckGIo3m&St+RfaEc!)~0gnkJsBDK8>IIuzAylOC{RutiufvvI9ZO} zN%j>&RjLqMJ#p^2g1Llwjuv_PEi z3X674I+V@}hsU7dVVTSAHq&7;Eus#|&XbXjQA1jS&H6{@)bID+etgX1Z>Ezvh=g6R zuRo5T4po){le|8?XF?Jgl*{wx?tfa{I+NviBIvk!ijvkPj)R4WV#f9!1N$cR`31O6 z*f+S`(rq|vsA8tOH8H1|8+RQ7J!bO7&RRG(SsIK-;^p`>WDYt0EHLdPwnmdFG&p?b zHMQ0A#8Cgz?ScRryep81iC%RS1$9er`aq?4F44z}C`r$Ffv^H33eRcjvY<|Wx{U&o z;{l!oT6}9a0mB2R-;%t=Rk5Aryl3MU$5m+7t<6Tgv5lynAdhg#OT7<$sFf-y6BaGq zuKnF!Fl}Q;4ok7jBP9WPi3G!v@RJEGFqLJ&Q;uZ6p}j|6)@VKQYmvS5D}0uHKlIVn z2K}B$j|vPxggcow6NtsZyoeEaORXRKJISk5H~Xk$@MSG93?%9e|Nh)NQK#FYs&`uo zKiLjbTG4GTbX6ijT<1=@}$e;a7jvi;7A`5bw)$pp+Ic8nk$Y zm-@T?$cIMxF!?|W+P#C1xjUo2=wncH0XH(J-AbB z0PNk4Z|a{62#6Am7-82SeD(1UC;%dj3lAx5?j@8RAGmy#8z3aV8HT&yvoj4S?Um{M zR~K#zjy#{D{!7~L&3Y^KRL;sBmajdg(9p=2EVajLHK@Rpqkcd@K{Tw#6t#W=iov05C z3~c)9k&{Uxb(0nV66F|)Qm2UdR)W^A{|g{_f&1J=u??=nv#(@&4o*8#mEbG)Sgjx4 zv_Pshp4T%_9Ng8zjlDB)4V#U2b1q4m(tGsHTPLfYxd4E9W6QQx42zDfthi^gqmM6U z^u8DYf`OML-h+k=DIcKee(PQiRD&G@t+8ZgBMW0PNHE-HPY^p$Bn1BJKnnbA+tWeD zzgwE#=L0uAO#WL1JSv`SZ%vVOwtcwN0(pT~$9-th>bAR#+0z{6SbW1|)bHgGzWMM9 z=TgD>)PTA#Q-DC4VbxJkV+8(LwHM9lDq9Bl;>_-G4Tt!M(pf=E0p_u;gq0uI3qlg9 zqnIR!vyjoVY^D6T(g4lHB`dOjD(NRVMAtMd5|VZu#tTeyR0`NZdT^NHKkPv#?Az1i z*UqqoC&2E+ysvJ*xDLty2@=_FH$Ax7d3(P&e`elquQm=JFgojV$dgYJBk+n~Z@!en z`|Omj!}bGZF)Yt!Di0$pg`H%Pk8*SdIai#OA%2I>wLvB{(iTJ=y2Y?ggnQUO@ z^ZCG)J_wGb-xF$W&&R*lPaXc4a){<@J#Cn7wlNs_M5CDlQ5N1Lhl~J;Ldekuk46dj z*~I*w{=8L*W;4Ve^01Ppe|sGyvC*-X9$2&IyHm-vouww5*96buxmpNuABPz-MOmv! zzcZ2iq3?x|i`YicvDtl;hh~O>xUO1Mw>Ei>2sbxNbGYO)S_EV^U9a~8SRdC7wCN+< z_}W`&5Zc(IqDe2yE{%0qJpYE9Is)qUgwL1cBQRt;-h4b4?QQGgkef*b)0xN1d)nFAT8&eb6RUa)2PRqChA(E#?d( zrjW>8KcBY`k3okqlKXxYA=|i6cW%{DAOIbLfYazLf_E$%>D7Gz;OPNQZSBw-_c;Us@HaZ@auQ1L8f?93(*nF_!k!y zgt90_Vm#sQPpzA4e9}Q(>lzs+Y(lBx`P+ZcQ3jjWN?@8EtCa1pSiX^G=YJzY8V_E+=NIkb|(e7o6ELoCjF^ zN^DuHDnwcS%MBwQ~zk|#Ca>D+jkAVh%yz&%H36f@yLtqwwc^CitQx>v4 zGoK#|=g4<7>VWl0<>=2`<*btk%>^oEv0aHtj3gD+VApmTHVfK7z1A$ z7X?XY*B0ARA3SL0o!c3*HWir0**Mejm1cbM6jgPxkP4O}K}{p4m@3Z(G+5@EH~c5M z56S~|$YmNBhKCJ=K@^dmElE7~Du0;Wh|g4 zBb2+&d+t5$1!6QOBktEn4w{iQQ?_S;y6zevQe>MJ&yQ1c$}7mr{6!NH5e~M-d`0Mp zT)eR{J~f`*yaG&85QQ$lwQo9}*+EGq-vyDdq#{ zU-^*60`XaR=^iXUJdg!CZFjH#u9>Qso&Lm8mDKcDAI_M@7MF)ZrlU%+)W}-B)Ba>| zI=^75=j@r4Qh|FO&2wLok#g3$=N-cJltr5Qv-IV_z`UYXd;ffA=(5tet7?Lpwrg2|8X?wYiDOIN$(xt-@{2h3L<^sKJ}uqd>d@Afbklrd zdJv>E!7$PB+F^+jF>=(%JMT`T1hsiiFl)ROWW4%FJ2` zys1ZBv{6p{GIwtyVDs-T^z~rBSbPm~ufn}Z-|E%=IKxBjjw0qCrCTXnO8V`0q&kX7 z5%X@brU>@%P?tOqL!GzsIPSlhzdLIuRR$&uh1)($fzr(XnG1Z5&?=2)41^JbP7wZo zlY(ATiO$bm9^L;tCAiYlJO_jLzXO8*_vGMtSNp3E><5@&L&g!&&*;0*$w?SVF*(s{ I;a~p$2UELCtpET3 literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/styles/default/images/bg_html.png b/core/http/server/src/main/webapp/styles/default/images/bg_html.png new file mode 100644 index 0000000000000000000000000000000000000000..d179af9f7eb6c6b3c9b729f8402f305f4aff61cd GIT binary patch literal 9739 zcmdsd_gfQ6(>Cf66-A^MY0^Pyq4y&o5K55VL3$OWh7Lys0f9&Ygcgtv2@rY-O$CHd z550qQLN%d;P(R=2$LBA2-|wf{y?5ric6Mg3>z>(-e+|;4q+p>SBO{{(YN;Fkk$q%j zw^{Gs{xedf2%7yP{&Ib(_mYeZ-6wN50rzLl9Pr9Kz{tlX0BrB)O!m^r$HAEs_}1Rl z+0fbEDa04+tVl-2ivX&>G!CBIL+C--T2elKcj+(c+MbgC=M?j43KKJk;nl0DBY&h3 zEX!p_@9Ona+3w#yhxU6sW4F4a!bt;m*R@mUgpGk6{AuS6X(Vdu(FH1!v;jXby4Z4G zXv)jZT*!kiyDOW25*rD;Azb%e$E;C=li0#oZmx-)hc%nKE-oE6wVlGkZ_e+kZ09PV*fh! zqGk2o+M%YFrTUVNP${Vo&cgUsUju-Xb+`<+CTU(QK>V(D?QXPvcK1bzu}6vNclP-8 z{k5%b_U|s&?=o@TTjZFHO4)T_w^#837Zo>UZ|1p}!vi5tsVXsT7cy5>%2nak%ym~| zafIT4R?9IFkudOrb<|lG$BswJg8~515B~dI#=LPsQ&!>3=87g_8 z8GO#^hvj;(YNgw282%ZDDL=e^8=Kb4R;RG?EYbuca~X%9?2alqTsC_d(X;5ks1l`8 zgA^N$2M|7H^!@E;u>OjZ__E1|3mXgJEN6(a+1A`_4&MMyw#?khDi#0xwL5CoLb#b_&-agE!x{B`~CMSrajYK+Unt_ z_UD^Lr`oe-mW%T4XG@PRs?iBrO|zHz*H!dWUDXoxkD3;(6IcL+3U?B_$J_55CFgmQ z`Hz^YK8jy@(5IOx)qdAK;fUWtscEpc_#kKBoNyc9p}O#|#Gq5f|&>pzB zFmanOb5#Cfrn@MDAYb7KUUh&f!-hXdw@hthb^K~hOt88{1oQO8K<5l6X^Hlv(-;F9 zK+r#xb>LjRkw&K#6vY=O5-)C+4MaHqO(c%e<|O7U4Opp+2?hjKuH}#IH^QY7mHr6^ zFk4tz=JHGywKqu+OdgZ&2vQuHK$17H$ux+^*9dchs(9|OCSTy%uf*&z*_Y$DI7J;u z4>e&Jxucu(e&9|e$_|af@Q+Iw1);aDMI%Npf&F!Wr`GpUGG=2L1}+kr%CU~K5wWmLO4hQp~7a{ky! zw(DO&OJ@Dzdkvv4{QW$}-eD|!EY@iWiJ?|^y>UM)^?iXo9V~Y-AGT6};{tq$XT!n5 zYlT^#T?G6GDSrTr--%vDJSh1ZeMR7V>?b(aPsKOxeIn06pDal#^}x;koh33&r@*^t z;>nNp<7ZRbPqx}_7MK3ixC^9kJ!#DP7;t{)g0l1a+|%-7(G~D+`16e2 z$&5Dnei?^-SQHn$=d)s!?jW<&D6=_nKT&3~f_~FD;3nZB};R$w8yV<&{sz51FiiW>)SU?We$YZsc>9NEfYT z)1JzZz9(DH;uUsJr}o;aXXFg|pvw!yf91%N$+L!M(^RX>IH>rkKC{pZd?XgJ^}TlE zrox*4yU$xDZiRr9S$QAgV8q~)CRXPV?gYLMne`Gwuj)l|z7K?8!(USgt5FwHt)N9j;o1=WG=JUL_C%#m8%t%^E&!RoMiFj{lO*!BzXI3Zw>DBpAED@2W zi2V+Y!3QmkPL6VAJ#x{A#tp{^0Xk?s=WD{>{JR9 zbYL&Oa9}rmwkgD&D@SPz(TW8#^NRM>c73_+Q+~~G6#2*4%`d4eN)pHPn6sQ4vEWyz zB?E%jjLS)GDc^`#PL~~A@Mu*ig}z&Rf(Vv>kfPPQHR@^|gUpcg<8hPee}?(~aMZw0 zWl5bQW#PF&!J6o76`$ym*K1}!|I`I|Lhs>mnxj{Z3`YcFZ}H1LK}rzmGAh&Q|Lu0vK+!pm%CghND@UxEYUR zNkYbhn!2=0BIWt3ZIQYYK+*Gy_%!vkGsUrgdGo3t=T%sr@F-}bd;c95xzXio*IEXx z{xf@y((gJPuAbal4n!^wz#ysv@4A~*d{7Y!#l8MK?5qUFs!Ml`;8OFx=W0UGUN@VT+r2YCcW~MI*FWE?!H3BuRGlkn-{Uzp!)tTM@<~tki zxQXLDPM);7OFLwI4ImB-!az@7C zmHnE442SU2w8|eg5SY+*;C(MM)3{gb5mTrZ=An1zV*3*l<{W|Q6KcamTMC@wX5gX` zU^5%kz8%g7;ZvEomhTC&i`k6RX7E8U!M0D6 zg3_51-_UKH#}K*!x5r)eY=z>RE}eKHS~ADE&!#cO^^*NEcgl?`AweK?Kjp^m6)~(( z{}MV1S$~_MOm>rU{USndN#M)zQ+KtL&DCi>j^}=_>LM$KQYLnUxJr+S>*kWPdV#4# z4+(#wDdmZb_|R_ZitSMD=E7VZI<#SA8y#|P!l|I~rC**S-lF(zA)mU|H`vV8) z`WkyB2H8(}g^roQ?2DMDs#cuD_c-$(#|_l%FU$waS&v}#9CTYSc|bNvLD2A2fJ)UC9#k>rI*{lt7$2=7 zECY1N7NtgCm1MWg(xocZR19uckx*kYlhAbaX2bfu1k@=w*scLb9ktxa|b z8i#)UNr_=mYM85W`c%gy1q<}&4q4ljF+Yh3Up|d#^RPbVov+0hC`#4VJc;4Kmpx#2E)2$FcUbt|wP@&OKq;3Q7{RDa(lG*1bylpvG9oQ=JBDFivt2u_(NNmjqqzuI^z7pT?BjQ9{l1ulRM}V>taEfEKW*v8hfB(2dDfSprlE@a~Hob6@Tqq^5BoS;V zyR;yxz#?I5i!(xG7*;Mp_@b!JPryv2Nvz^&_VT8NQvE{-2tmH@Vu9#04G^NH6ZJ(p zo+^GlU3|`l`5gExzdqU58EoDTzs2>`A)+kgP0s*qStaBtF=)8k(F?H3Mv>z8a9sh) zkQwmRdP#t{SniM}B^~Nk0tFq2RG%^FSWLHPiLKf>6_+_WEiBx5#_KRHsAj7xs;gY( z#Ap%1idWuGe5peb6zCb@8M2yGV8c)`O=0HFI6kzuU7v2HhmrEMJQshwSf(?H@H?g$ zpog`)h0nF(`oKBid)Zqkh9K^r+a7j1i;^W5K@OG54~#5d8op0OW z=#z_EOCDazl2c}f!U=VCxiLyA>lmjrVsX+d%S z&t(ga`utH|jh+;*faSl^F_?##EZt7<4fK6T!0Q+ElS1ubfQQA;e;XowEfRVbT6<+eQYzZY6?(Irdptqn}9r$-H zHT7ia_waF&^G%LODKhM1ymM4WvRPi)=WlyCV(#8pBf$}zHvy4tvguz+P4wHZO%c2Y zQchXuI_yp`w5{AZHY#-3`DfwoLXYL_TpX_PZ9=? zU=Zi*B=UWQhJdWE^<0z3L?WtsAnHbaByqY3*(!WKw?pE$8ST<+?o{F9BNhB`p)$s{ zAJmjBC&yGBgjd=in92$}WQmv6g@o3wD(me=TXy4>_JfvGHo zI?eXsg@_d;o!hli$_|Pd?i$)292JDF1F&cU|O?6_WHVW*bsLy zPP-xWM5#LI=iJE}YqEgZSLw*3k%j}h3#Ln-M#tJ@^`vu+D~VB(1HeKM{R0Q?W_!;V?0V~yuOj!l!Joy0cuCg2P_v0Tr@I-!UIAB$ zZ35icU(bsY3%RD~i*fx=d94O^Bq}$|@nmrx@I9f|<4@#`(tYPMIa30WrjyK^5Nb&hI+<@An z^{HKYgj8{nQ?zkAr|I%Fu52sFYISt|Fy#EcoJ7IOD!0N^D=jAbUmdP15RH)ID^lE`w>#lko+8=E< zqK<#U)F<};IqdkcC~vT1JrMLd9)fw>UCy*AZ*o!gY6htuHL}&{HjyQ5^T5op1@C>y zBO_FZeBF5^(`5N+#IS4slZnf+)T(>A0P2CezkBF+*qweCEn0Zz%3iPX1Z`4%+9 zT}X)9z2>#49^)FD9F-7B36QGbxCjQLUc^+2XzB;Gh!0^~{kBl{0l$O#XmEi*F8a@sm#<5#vC_ez_jfi{lKe%QvFEy+bXsM?~^FQI~Tc^ z!!G6@;(E@lr^V-jm4G`orSB&-jnKwVJvp=;QF|hn})Y$2%`Md8$<^zsK-@32bCO)cHc%Ox|1eh8ijX7Rq zA)vc5xK`~-6?cL-!KNQ*L+(I%u+PH9@99jFLiD$Zx?JN}GvjBQ{AfRMrzNzawF7F1 zRlz_`Z>Hvs0agPN^Aq^F-uS(d<=0-BY1K$jAfHYF2{&JRMareCP_Wshq zo;P-1?28}&@59U zDY;xxm3l=y_;o`_(5n|_<0s|mLXtt3Gd^wz`M(4E|G|r~P$M1N_P$z=TeLn#X};XY zt*hLZTP>8mZxnmAQ}*v7-6Sg%Ajc)a`NBa9Ift<{zi?crCl#zjqu+dBB--ETnb|@(wZ@{uj+ruM(Y3up@(ZMyHvOu;H zh|6Rl`Ug>u)VJQM!L;-yfKJ+J3Pu+h*-W93*J9SfZ_sCu1=AST%uPRtY8Ba->=U#? z24tT#^Wn5~60WMNaQvVS9ctL!7lUyn;|17SUC}G0tK9}bZbSaG?~3i`pp%Ve%w;q7 z!$g+y=HF8E;f5kW`BJ^SI{ln*4?c$<#G)o`229G8G554*dl8YYz9{^Phf$B_B__Of zEp6ovRJrGsV^v^O;FR+7P0UUCb@Ae|bFh3s;FhU7N6op{$?=irSf@$WkMPoIk$La5 zFQb!SQ|Y8=NN&MQlxNy{!Fjb>PY1cl0Np_RsmIQFry?mrCBPolyP<6-Fn|o}>Tcb* zqO3iBQ#-m}=|A6&{LM3~v^Swt59pTJvdOe*-RN^?#<;i1(~4VQDAqd&1y=*G&RvPA z`p}Tlu+F%8GwkD6hV#va0zDKlDTbN|*`gO>%$28z-hXp|qW5hVO?W2>bNLhU-2d@S2Q0KxioTKZWV6C4^l2+kLN5sJ*nylwAFwrYnJ&PW;j_ z6~I{fj_%%CwwBGJvh7BgEUC#?uOX&1HqdT)BMya%vlb2$6$roV#)2`i?K^ z(`>}BKS2Qj2MeeEpKo0CBE!OV4Z$HhwNK12`W*W!#6+59ph>#8WogA|=(=`SfN*@a z_km-41&Ft$m~!?^i2Z^#rjQ&}F@_Q-E(N_`Yx~Qc&nL^R`yG7ewrvC>Lbf1)rYJf( z-YI-iX6~e1UiyU?Sbd1I?BeU^@on!xN6iDEaID7<@q0+d=Y_@fC_b)+0Q9OBWmR^Y zF?oAKflf|pabPPLVf}OYBN({vt%Ai+(~`W+U#tuCGohWgM4{wJONRizC^nny+jh`vw~3;+PMdn;b3I44<{&>i{-WpU5+M54>1yIKTNe z1FPDX?{H*>S4K15pa#%+kc>fnn5R0e4tc_0G1npQ?^1XX;zi*&iJVVqATX3uH_-WZBtW|~-HUU=dsSeh5drwkoSa9#LX z**~=q``_;IvM#e6AGnnx2(@B1Tg7swk-OIVHjO=0SUMX|y>eRM@@u6pts4i!>~?!7 zfd1*$cGfe~PgyTIct_^eK!17-SDH0D9UZ?5v1X|C*H0AZ4DyzcW*)Re*uQB5Pz}05 z&wy5*5CcAjw&`3h`YgyP-py9KM-e0D<{okNYuyKupArq>o>Dc?zXC0X$4s8fB=$(B zqE*n^e=C8uu;V2;yJ8~s^Z1%El-Hzz&i$St&X7&YCxUSA8OUPUN>lG|ZtkF$JCGfH zo7!ZO$9tu4<{psop0;U_*>#PWi>`o8U6Bgu{*toyf!+A65rHEtpL@Va)x&{sg5efZ z@=Wmqwt;cYwF@bOuZh^1()=j~D!`Z8*n61_rq?Ta?+>6!0r?z>g0_@}<(<7W2^3b;2go99|QA*oS03hM6w|@Az;~FQrID?qv1d(!4kmd)~JDK$iM9 zL?@?2UQqw$$3ydo_PI4ikb{ukarK^`0DRY+W>0oiJm;Xy&>E09u0`H^5yoWMa^C&+ zCK#e>>x}#Ohq_LJW(N3zF4Wu#zJU5`vrmZ0pVsyj7oPb?{6?6A`Hn|7rZZg!6>>S= z_{9xJ+TWHNES4ZX?T^mW#GXk3E)4KFj^!BV)`2Y6;}ySRkql89)VNM-_j10Jo1a3! z`vD#|*V%~^o*>;UucvZ;GllbZQ)*GG9!T%A=M55(%51)$Gk)H6pbOW0p%2Jg_i?Dc zYH*EMb*F{j+Ka+6~TQ%h8yr~taiQT2& z)6H`Q{Ps0!cw%~3#nCSFIje?_m{}t@x?AlB4~*o!@4|xpDi2J+FO95;*BJB7Qgx_u zyR(lgCz-$53+y5c4s6z|6JPCjb(}NY!%;ge_j~I>T#v-_J!tNC{G^xkP(57-FfaWo z*Ln|O^|q0xHM5)y_WY&(mS!hDY5Wuc*<(JX1mm zw;I;Ik9!q(Q-K9XD}RfOcVb*W>$y8?L#F-U9<4Krb=QH~Q$g*dooDsvXMe8y<`^k8 zkwrG;8wPu!3q#IkcuTr;8z*-To1T6_$A}%91k*ipWc+ecZKyvjweCi3L-o08;si>5 zd-)6$dWBI&O)}xPBjFkpQBK-dqtgOnu|UTcsq=iXFTuM(Shu9STmBLy-5+g^y3ZKG zX;UT^Rt%bRsEkgf^I87(4B(bKia!Waq=rZ*%dZ;Tu2RHj#!h?sv&bh-amrY`*fQP0 z<7?J#8PR^>i&%klv<+99S`{)ouL?lGweC$S;8&gTzGqUn4qDJodC<_fDm&tBp5aQD zlgA*ur0$qK`!lOdG_wr@OgY_$wc~wNB+U5dC+-eY(P3-7X?2_uQY9}N=7!YEC67<~wSu0zJj5N%H8aEq*lto!zphh%Yg z{{#H};y=Kjh5rG_o;>^y@E^^%yZ_Pr1N`qb{j<^k;~xCik^diz!GC%1Ur7_!L-YSh ouKkyv|C=IpdGjsmff(7~!i5nT9Yyn>-&|zCS0ME&)i>||AI1UM+5i9m literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/styles/default/images/hr_menu.png b/core/http/server/src/main/webapp/styles/default/images/hr_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..1c4f27f0a2cfd21b3697e5d3b1a5afce7355ccb4 GIT binary patch literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^`+%5~ zn{IgdOvq`8oXt74-pqq+9xfqL!O6?SD_@+S{W7Pd-f~4{(SyZyaVa0t>}JirJ5TbC zN~3jDoban3i_gu@G~Kmd=!%W%hrszdMk&VfXLa-ZSBQExqQ&&R&05_W*;A XLsG}eYh^Qm_A_|8`njxgN@xNA?H^Mn literal 0 HcmV?d00001 diff --git a/core/http/server/src/main/webapp/styles/default/msie-minheight.css b/core/http/server/src/main/webapp/styles/default/msie-minheight.css new file mode 100644 index 00000000000..4d67c0b6f58 --- /dev/null +++ b/core/http/server/src/main/webapp/styles/default/msie-minheight.css @@ -0,0 +1,3 @@ +#content { + height: 350px; +} \ No newline at end of file diff --git a/core/http/server/src/main/webapp/styles/default/print.css b/core/http/server/src/main/webapp/styles/default/print.css new file mode 100644 index 00000000000..c22520f1a2e --- /dev/null +++ b/core/http/server/src/main/webapp/styles/default/print.css @@ -0,0 +1,27 @@ +@import url(../w3-html40-recommended.css); + +html, body { + color: #000; + background: #fff; + font-family: "Times New Roman", "Times", serif; + font-size: 100%; + line-height: 110%; +} + +h1 { + page-break-before: avoid; +} + +th,td { + vertical-align: top; + text-align: left; +} + +#header, #navigation, #contentheader { + display: none; +} + +#footer { + position: absolute; + bottom: 2em; +} \ No newline at end of file diff --git a/core/http/server/src/main/webapp/styles/default/screen.css b/core/http/server/src/main/webapp/styles/default/screen.css new file mode 100644 index 00000000000..0d9d4b962ff --- /dev/null +++ b/core/http/server/src/main/webapp/styles/default/screen.css @@ -0,0 +1,456 @@ +@import url(../w3-html40-recommended.css); + +html,body { + margin: 0; + border: 0; + padding: 0; + color: #000; + line-height: 100%; + font-size: 100%; + font-family: Georgia, Times New Roman, Times Roman, Times, serif; +} + +html { + background: #FFF url(images/bg_html.png); + background-repeat: repeat-x; + overflow: scroll; +} + +body { + background: url(images/bg_body.png); + background-repeat: no-repeat; +} + +a:link,a:active,a:visited,a:hover { + color: #0863AD; + text-decoration: underline; +} + +a:active { + outline: none; +} + +h1,h2,h3,h4 { + color: #000; + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-weight: bold; +} + +div,p,fieldset,img { + margin: 0; + border: 0; + padding: 0; + background: transparent; +} + +img { + vertical-align: middle; +} + +input,select { + display: inline; + vertical-align: middle; +} + +ul { + margin: 0; + margin-bottom: 10px; + padding: 0; + list-style-type: disc; +} + +li { + margin: 0; + margin-left: 16px; + padding: 0; +} + +table,th,td { + margin: 0; + border: 0; + padding: 0; + border-collapse: collapse; +} + +th,td { + vertical-align: top; + text-align: left; +} + +hr { + margin: 0; + border: 0; + padding: 0; + height: 1px; + color: #0863AD; + background-color: #0863AD; +} + +#header { + padding: 5px 0 0 5px; + height: 50px; +} + +.productgroup { + position: absolute; + right: 0; + margin-top: -8px; +} + +#search { + position: absolute; + margin-top: 34px; + width: 95%; + text-align: right; +} + +#search form,#search p { + margin: 0; + border: 0; + padding: 0; +} + +#search form { + margin: 7px; +} + +#search input { + font-size: 67%; + color: #000; +} + +#search img { + margin-top: 2px; +} + +#navigation { + position: absolute; + left: 0; + margin: 10px 0 0 5px; + padding: 0; + width: 190px; + background: url(images/hr_menu.png); + background-repeat: no-repeat; + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-weight: bold; + font-size: 83%;; + margin: 10px 0 0 5px; +} + +#navigation a:link,#navigation a:visited,#navigation a:active,#navigation a:hover { + color: #000; + text-decoration: none; +} + +#navigation a:hover { + color: #0863AD; + text-decoration: underline; +} + +#navigation ul { + margin: 2px 0 0 0; + list-style-type: none; +} + +#navigation li { + margin: 0; + padding: 3px 0px 6px 10px; + background: url(images/hr_menu.png); + background-repeat: no-repeat; + background-position: bottom; +} + +#navigation .current { + background: #DEDEDE url(images/hr_menu.png); + background-repeat: no-repeat; + background-position: bottom; +} + +#navigation ul.group { + margin: 1px 0 -4px -10px; + padding-bottom: 3px; + background: #EFEFEF; + background-repeat: no-repeat; + background-position: bottom; + font-size: 83%; +} + +#navigation .group li { + padding: 0px 0 1px 15px; + background: transparent; +} + +#navigation .group li.current,#navigation .group li.current a:link,#navigation .group li.current a:visited,#navigation .group li.current a:active,#navigation .group li.current a:hover + { + color: #0863AD; +} + +#navigation .group li.current .subgroup,#navigation .group li.current .subgroup a:link,#navigation .group li.current .subgroup a:visited,#navigation .group li.current .subgroup a:active,#navigation .group li.current .subgroup a:hover + { + color: #000; +} + +#navigation ul.subgroup { + margin: 3px 0 3px -15px; + background: transparent; +} + +#navigation .subgroup li { + padding: 0px 0 1px 20px; +} + +#navigation .subgroup li.current { + background: #DEDEDE; +} + +#contentheader { + margin-left: 200px; + padding: 10px 20px 10px 15px; + height: 55px; + color: #FFF; + font-weight: bold; + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-size: 67%; +} + +#contentheader h3,#contentheader p,#contentheader table,#contentheader ul { + margin: 0; + padding: 0; +} + +#contentheader td, #contentheader th { + margin: 0; + padding: 0 0 0 5px; +} + +#tabs { + float: right; + position: relative; + top: -15px; + text-align: right; +} + +#tabs ul { + list-style-type: none; +} + +#tabs a:link,#tabs a:visited,#tabs a:active { + color: #0863AD; + text-decoration: none; +} + +#tabs a:hover { + color: #FFF; + text-decoration: underline; +} + +#tabs li { + display: inline; + margin: 0 0 0 20px; + font-weight: bold; +} + +.disabled { + color: #666; +} + +#content { + position: relative; + top: 5px; + margin-left: 200px; + padding: 15px 20px 15px 15px; + min-height: 350px; + font-size: 67%; +} + +#content p { + margin: 0; + margin-bottom: 15px; +} + +#content h1,#content h2,#content h3 { + padding: 0; + font-weight: bold; +} + +#content h1 { + margin: 0 0 4px 0; + padding: 0 0 10px 0; + border-bottom: 1px solid #666; + font-size: 250%; +} + +#content h2 { + margin: 5px 0 5px 0; + padding-top: 10px; + font-size: 120%;; +} + +#content h2>a:link,#content h2>a:active,#content h2>a:hover,#content h2>a:visited { + text-decoration: none; +} + +#content h3 { + margin: 0; + margin-top: 5px; + color: #333; + font-size: 100%; +} + +#message { + margin: 5px 0; + padding: 5px; +} + +#message p { + margin: 0; + border: 0; + padding: 0; + color: #000; +} + +#message img { + float: left; + margin-right: 5px; +} + +.ERROR { + border: 2px solid #F00; + background: #FCC; +} + +.WARN { + border: 2px solid #FF0; + background: #FFC; +} + +.INFO { + border: 2px solid #0863AD; + background: #CCF; +} + +#footer { + clear: both; + margin-left: 200px; + padding: 0 20px 15px 15px; + color: #333; + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-size: 67%; +} + +#footer p { + border-top: 1px solid #666; + padding-top: 3px; +} + +#footer a:link,#footer a:active,#footer a:visited { + text-decoration: none; +} + +#footer a:hover { + text-decoration: underline; +} + +.simple th,.simple th { + padding-right: 5px; +} + +table.screenshots { + width: 100%; +} + +.screenshots td { + width: 50%; +} + +.captions td { + padding-bottom: 10px; +} + +.button { + float: right; + margin-left: 15px; + margin-bottom: 3px; +} + +.screenshot { + float: right; + margin-left: 15px; + margin-bottom: 5px; +} + +.introduction,.tagline { + color: #0863AD; +} + +.introduction { + clear: both; + margin-top: -5px; + margin-bottom: 0px; + padding: 5px 30px 10px 30px; + border-bottom: 1px solid #666; +} + +.data th,.data td,.dataentry th,.dataentry td { + padding: 2px 5px; +} + +.data th,.dataentry th { + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-weight: bold; +} + +td.input { + padding-top: 0; +} + +table.data,.data th,.data td { + border: 1px solid #999; + margin-bottom:10px; +} + +.data th { + background: #CCC; +} + +.data td { + background: #FFF; +} + +.dataentry th,.dataentry td { + vertical-align: middle; +} + +.data img,.dataentry img { + margin: -2px; +} + +fieldset, .fieldset { + border: 1px solid #CCC; + background: #EFEFEF; +} + +.error { + color: #F70008; + font-weight: bold; +} + +.product_overview { + width: 100%; +} + +table.product_overview,.product_overview th,.product_overview td { + border: 1px solid black; +} + +.product_overview th,.product_overview td { + padding: 1px 2px; +} + +.link { + text-align: center; +} + +.ad { + margin-bottom: 5px; +} diff --git a/core/http/server/src/main/webapp/styles/w3-html40-recommended.css b/core/http/server/src/main/webapp/styles/w3-html40-recommended.css new file mode 100644 index 00000000000..5f889ce63a8 --- /dev/null +++ b/core/http/server/src/main/webapp/styles/w3-html40-recommended.css @@ -0,0 +1,81 @@ +/* Source: http://www.w3.org/TR/CSS21/sample.html */ + +html, address, +blockquote, +body, dd, div, +dl, dt, fieldset, form, +frame, frameset, +h1, h2, h3, h4, +h5, h6, noframes, +ol, p, ul, center, +dir, hr, menu, pre { display: block } +li { display: list-item } +head { display: none } +table { display: table } +tr { display: table-row } +thead { display: table-header-group } +tbody { display: table-row-group } +tfoot { display: table-footer-group } +col { display: table-column } +colgroup { display: table-column-group } +td, th { display: table-cell } +caption { display: table-caption } +th { font-weight: bolder; text-align: center } +caption { text-align: center } +body { margin: 8px } +h1 { font-size: 2em; margin: .67em 0 } +h2 { font-size: 1.5em; margin: .75em 0 } +h3 { font-size: 1.17em; margin: .83em 0 } +h4, p, +blockquote, ul, +fieldset, form, +ol, dl, dir, +menu { margin: 1.12em 0 } +h5 { font-size: .83em; margin: 1.5em 0 } +h6 { font-size: .75em; margin: 1.67em 0 } +h1, h2, h3, h4, +h5, h6, b, +strong { font-weight: bolder } +blockquote { margin-left: 40px; margin-right: 40px } +i, cite, em, +var, address { font-style: italic } +pre, tt, code, +kbd, samp { font-family: monospace } +pre { white-space: pre } +button, textarea, +input, select { display: inline-block } +big { font-size: 1.17em } +small, sub, sup { font-size: .83em } +sub { vertical-align: sub } +sup { vertical-align: super } +table { border-spacing: 2px; } +thead, tbody, +tfoot { vertical-align: middle } +td, th { vertical-align: inherit } +s, strike, del { text-decoration: line-through } +hr { border: 1px inset } +ol, ul, dir, +menu, dd { margin-left: 40px } +ol { list-style-type: decimal } +ol ul, ul ol, +ul ul, ol ol { margin-top: 0; margin-bottom: 0 } +u, ins { text-decoration: underline } +br:before { content: "\A" } +:before, :after { white-space: pre-line } +center { text-align: center } +:link, :visited { text-decoration: underline } +:focus { outline: thin dotted invert } + +/* Begin bidirectionality settings (do not change) */ +BDO[DIR="ltr"] { direction: ltr; unicode-bidi: bidi-override } +BDO[DIR="rtl"] { direction: rtl; unicode-bidi: bidi-override } + +*[DIR="ltr"] { direction: ltr; unicode-bidi: embed } +*[DIR="rtl"] { direction: rtl; unicode-bidi: embed } + +@media print { + h1 { page-break-before: always } + h1, h2, h3, + h4, h5, h6 { page-break-after: avoid } + ul, ol, dl { page-break-before: avoid } +} \ No newline at end of file diff --git a/core/http/server/src/test/java/org/eclipse/rdf4j/http/server/WebXmlValidationTest.java b/core/http/server/src/test/java/org/eclipse/rdf4j/http/server/WebXmlValidationTest.java new file mode 100644 index 00000000000..02189a91f97 --- /dev/null +++ b/core/http/server/src/test/java/org/eclipse/rdf4j/http/server/WebXmlValidationTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; + +import javax.xml.XMLConstants; +import javax.xml.validation.SchemaFactory; + +import org.eclipse.rdf4j.common.xml.DocumentUtil; +import org.junit.Test; +import org.xml.sax.SAXException; + +/** + * @author Herko ter Horst + */ +public class WebXmlValidationTest { + + @Test + public void testValidXml() throws MalformedURLException, IOException, SAXException { + File webXml = new File("src/main/webapp/WEB-INF/web.xml"); + + DocumentUtil.getDocument(webXml.toURL(), SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema()); + } +} diff --git a/core/http/workbench/compileTypescript.sh b/core/http/workbench/compileTypescript.sh new file mode 100755 index 00000000000..677cb42ea78 --- /dev/null +++ b/core/http/workbench/compileTypescript.sh @@ -0,0 +1,14 @@ +#!/bin/bash +#******************************************************************************* +# Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Distribution License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +#******************************************************************************* +scriptdir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +destdir="$scriptdir/src/main/webapp/scripts" +srcdir=$destdir/ts +cd $srcdir +tsc --noImplicitAny --sourcemap --sourceRoot "/openrdf-workbench/scripts/ts" --outDir $destdir *.ts +echo 'Replaced repository JavaScript files with compiled TypeScript versions.' diff --git a/core/http/workbench/deployTypeScriptVersion b/core/http/workbench/deployTypeScriptVersion new file mode 100755 index 00000000000..fcbbe907a7d --- /dev/null +++ b/core/http/workbench/deployTypeScriptVersion @@ -0,0 +1,12 @@ +#!/bin/bash + +indir=~/Documents/git/sesame/core/http/workbench/src/main/webapp/scripts +srcdir=/tmp/tsout +mkdir -p $srcdir +rm -f $srcdir/*.js* +destdir=~/tomcat7/webapps/openrdf-workbench/scripts +cd $indir +tsc --noImplicitAny --sourcemap --sourceRoot "/openrdf-workbench/scripts" --outDir $srcdir *.ts +cp $srcdir/*.js* $destdir +cp *.ts $destdir +echo 'Replaced deployed JavaScript files with compiled TypeScript versions.' diff --git a/core/http/workbench/pom.xml b/core/http/workbench/pom.xml new file mode 100644 index 00000000000..3ddf49898e4 --- /dev/null +++ b/core/http/workbench/pom.xml @@ -0,0 +1,160 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-http + 4.1.0-SNAPSHOT + + + rdf4j-http-workbench + war + + RDF4J: HTTP workbench + Workbench to interact with RDF servers. Currently supports RDF4J 2 servers only. + + + + ${project.groupId} + rdf4j-util + ${project.version} + + + ${project.groupId} + rdf4j-model + ${project.version} + + + ${project.groupId} + rdf4j-query + ${project.version} + + + ${project.groupId} + rdf4j-runtime + ${project.version} + + + ${project.groupId} + rdf4j-http-protocol + ${project.version} + + + ${project.groupId} + rdf4j-repository-api + ${project.version} + + + ${project.groupId} + rdf4j-repository-manager + ${project.version} + + + ${project.groupId} + rdf4j-repository-http + ${project.version} + + + ${project.groupId} + rdf4j-repository-sail + ${project.version} + + + ${project.groupId} + rdf4j-queryparser-api + ${project.version} + + + ${project.groupId} + rdf4j-rio-api + ${project.version} + + + ${project.groupId} + rdf4j-sail-nativerdf + ${project.version} + + + ${project.groupId} + rdf4j-config + ${project.version} + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-classic + + + + + + javax.servlet + servlet-api + + + + + commons-fileupload + commons-fileupload + + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-jdk14 + runtime + + + org.slf4j + jcl-over-slf4j + runtime + + + + junit + junit + test + + + + org.mockito + mockito-core + test + + + + org.json + json + + + + + + + org.apache.maven.plugins + maven-war-plugin + + openrdf-workbench + true + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + + ${project.build.directory}/${project.artifactId}.war + localhost + /openrdf-workbench + + + + + + diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/RepositoryServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/RepositoryServlet.java new file mode 100644 index 00000000000..2e6d9673bac --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/RepositoryServlet.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench; + +import javax.servlet.Servlet; + +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.manager.RepositoryInfo; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; + +public interface RepositoryServlet extends Servlet { + + void setRepositoryManager(RepositoryManager manager); + + void setRepositoryInfo(RepositoryInfo info); + + void setRepository(Repository repository); +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/AbstractRepositoryServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/AbstractRepositoryServlet.java new file mode 100644 index 00000000000..73aa7be1b1c --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/AbstractRepositoryServlet.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.base; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.repository.manager.RepositoryInfo; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.workbench.RepositoryServlet; +import org.eclipse.rdf4j.workbench.exceptions.MissingInitParameterException; + +public abstract class AbstractRepositoryServlet extends AbstractServlet implements RepositoryServlet { + public static final String REPOSITORY_PARAM = "repository"; + public static final String MANAGER_PARAM = "repository-manager"; + protected RepositoryManager manager; + protected RepositoryInfo info; + protected Repository repository; + protected ValueFactory vf; + + public void setRepositoryManager(RepositoryManager manager) { + this.manager = manager; + } + + public void setRepositoryInfo(RepositoryInfo info) { + this.info = info; + } + + public void setRepository(Repository repository) { + if (repository == null) { + this.vf = SimpleValueFactory.getInstance(); + } else { + this.repository = repository; + this.vf = repository.getValueFactory(); + + if (this.repository instanceof HTTPRepository) { + ((HTTPRepository)this.repository).setPreferredRDFFormat(RDFFormat.BINARY); + } + } + } + + @Override + public void init(ServletConfig config) throws ServletException { + super.init(config); + if (repository == null) { + if (config.getInitParameter(REPOSITORY_PARAM) != null) + setRepository((Repository) lookup(config, REPOSITORY_PARAM)); + } + if (manager == null) { + if (config.getInitParameter(MANAGER_PARAM) == null) + throw new MissingInitParameterException(MANAGER_PARAM); + manager = (RepositoryManager) lookup(config, MANAGER_PARAM); + } + if (info == null) { + info = new RepositoryInfo(); + info.setId(config.getInitParameter("id")); + info.setDescription(config.getInitParameter("description")); + try { + if (repository == null) { + info.setReadable(false); + info.setWritable(false); + } else { + info.setReadable(true); + info.setWritable(repository.isWritable()); + } + String location = config.getInitParameter("location"); + if (location != null && location.trim().length() > 0) { + info.setLocation(new URL(location)); + } + } catch (MalformedURLException e) { + throw new ServletException(e); + } catch (RepositoryException e) { + throw new ServletException(e); + } + } + } + + private Object lookup(ServletConfig config, String name) throws ServletException { + String param = config.getInitParameter(name); + try { + InitialContext ctx = new InitialContext(); + return ctx.lookup(param); + } catch (NamingException e) { + throw new ServletException(e); + } + } +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/AbstractServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/AbstractServlet.java new file mode 100644 index 00000000000..9cf722438c3 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/AbstractServlet.java @@ -0,0 +1,346 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.base; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Optional; +import java.util.regex.Pattern; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.app.AppConfiguration; +import org.eclipse.rdf4j.common.app.AppVersion; +import org.eclipse.rdf4j.common.io.MavenUtil; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.resultio.BasicQueryWriterSettings; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.QueryResultFormat; +import org.eclipse.rdf4j.query.resultio.QueryResultIO; +import org.eclipse.rdf4j.query.resultio.QueryResultWriter; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.UnsupportedQueryResultFormatException; +import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractServlet implements Servlet { + + protected final Logger log = LoggerFactory.getLogger(this.getClass()); + + protected static final String SERVER_USER = "server-user"; + + protected static final String SERVER_PASSWORD = "server-password"; + + protected static final String ACCEPT = "Accept"; + + /** + * This response content type is always used for JSONP results. + */ + protected static final String APPLICATION_JAVASCRIPT = "application/javascript"; + + /** + * This response content type is used in cases where application/xml is + * explicitly requested, or in cases where the user agent is known to be a + * commonly available browser. + */ + protected static final String APPLICATION_XML = "application/xml"; + + /** + * This response content type is used for SPARQL Results XML results in + * non-browser user agents or other cases where application/xml is not + * specifically requested. + */ + protected static final String APPLICATION_SPARQL_RESULTS_XML = "application/sparql-results+xml"; + + protected static final String TEXT_HTML = "text/html"; + + protected static final String USER_AGENT = "User-Agent"; + + protected static final String MSIE = "MSIE"; + + protected static final String MOZILLA = "Mozilla"; + + /** + * JSONP property for enabling/disabling jsonp functionality. + */ + protected static final String JSONP_ENABLED = "org.eclipse.rdf4j.workbench.jsonp.enabled"; + + /** + * This query parameter is only used in cases where the configuration + * property is not setup explicitly. + */ + protected static final String DEFAULT_JSONP_CALLBACK_PARAMETER = "callback"; + + protected static final Pattern JSONP_VALIDATOR = Pattern.compile("^[A-Za-z]\\w+$"); + + protected static final String JSONP_CALLBACK_PARAMETER = "org.eclipse.rdf4j.workbench.jsonp.callbackparameter"; + + protected ServletConfig config; + + protected AppConfiguration appConfig; + + @Override + public ServletConfig getServletConfig() { + return config; + } + + @Override + public String getServletInfo() { + return getClass().getSimpleName(); + } + + @Override + public void init(final ServletConfig config) + throws ServletException + { + this.config = config; + this.appConfig = new AppConfiguration("openrdf-workbench", "OpenRDF Sesame Workbench"); + try { + // Suppress loading of log configuration. + this.appConfig.init(false); + } + catch (IOException e) { + throw new ServletException(e); + } + } + + @Override + public void destroy() { + } + + @Override + public final void service(final ServletRequest req, final ServletResponse resp) + throws ServletException, IOException + { + final HttpServletRequest hreq = (HttpServletRequest)req; + final HttpServletResponse hresp = (HttpServletResponse)resp; + service(hreq, hresp); + } + + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException + { + // default empty implementation + } + + protected QueryResultFormat getTupleResultFormat(final HttpServletRequest req, final ServletResponse resp) + { + String header = null; + if (req instanceof WorkbenchRequest) { + header = ((WorkbenchRequest)req).getParameter(ACCEPT); + } + if (null == header) { + header = req.getHeader(ACCEPT); + } + if (header != null) { + Optional tupleFormat = QueryResultIO.getParserFormatForMIMEType(header); + if (tupleFormat.isPresent()) { + return tupleFormat.get(); + } + } + + return null; + } + + protected QueryResultFormat getBooleanResultFormat(final HttpServletRequest req, final ServletResponse resp) + { + String header = req.getHeader(ACCEPT); + if (header != null) { + // Then try boolean format + Optional booleanFormat = QueryResultIO.getBooleanParserFormatForMIMEType(header); + if (booleanFormat.isPresent()) { + return booleanFormat.get(); + } + } + + return null; + } + + protected QueryResultFormat getJSONPResultFormat(final HttpServletRequest req, final ServletResponse resp) + { + String header = req.getHeader(ACCEPT); + if (header != null) { + if (header.equals(APPLICATION_JAVASCRIPT)) { + return TupleQueryResultFormat.JSON; + } + } + + return null; + } + + protected QueryResultWriter getResultWriter(final HttpServletRequest req, final ServletResponse resp, + final OutputStream outputStream) + throws UnsupportedQueryResultFormatException, IOException + { + QueryResultFormat resultFormat = getTupleResultFormat(req, resp); + + if (resultFormat == null) { + resultFormat = getBooleanResultFormat(req, resp); + } + + if (resultFormat == null) { + resultFormat = getJSONPResultFormat(req, resp); + } + + if (resultFormat == null) { + // This is safe with the current SPARQL Results XML implementation that + // is able to write out boolean results from the "Tuple" writer. + resultFormat = TupleQueryResultFormat.SPARQL; + } + + return QueryResultIO.createWriter(resultFormat, outputStream); + } + + /** + * Gets a {@link TupleResultBuilder} based on the Accept header, and sets the + * result content type to the best available match for that, returning a + * builder that can be used to write out the results. + * + * @param req + * the current HTTP request + * @param resp + * the current HTTP response + * @param outputStream + * TODO + * @return a builder that can be used to write out the results + * @throws IOException + * @throws UnsupportedQueryResultFormatException + */ + protected TupleResultBuilder getTupleResultBuilder(HttpServletRequest req, HttpServletResponse resp, + OutputStream outputStream) + throws UnsupportedQueryResultFormatException, IOException + { + String contentType = null; + QueryResultWriter resultWriter = checkJSONP(req, outputStream); + + if (resultWriter != null) { + // explicitly set the content type to "application/javascript" + // to fit JSONP best practices + contentType = APPLICATION_JAVASCRIPT; + } + else { + // If the JSON-P check above failed, use the normal methods to + // determine output format + resultWriter = getResultWriter(req, resp, resp.getOutputStream()); + contentType = resultWriter.getQueryResultFormat().getDefaultMIMEType(); + } + + // HACK: In order to make XSLT stylesheet driven user interface work, + // browser user agents must receive application/xml if they are going to + // actually get application/sparql-results+xml + // NOTE: This will test against both BooleanQueryResultsFormat and + // TupleQueryResultsFormat + if (contentType.equals(APPLICATION_SPARQL_RESULTS_XML)) { + String uaHeader = req.getHeader(USER_AGENT); + String acceptHeader = req.getHeader(ACCEPT); + + if (acceptHeader != null && acceptHeader.contains(APPLICATION_SPARQL_RESULTS_XML)) { + // Do nothing, leave the contentType as + // application/sparql-results+xml + } + // Switch back to application/xml for user agents who claim to be + // Mozilla compatible + else if (uaHeader != null && uaHeader.contains(MOZILLA)) { + contentType = APPLICATION_XML; + } + // Switch back to application/xml for user agents who accept either + // application/xml or text/html + else if (acceptHeader != null + && (acceptHeader.contains(APPLICATION_XML) || acceptHeader.contains(TEXT_HTML))) + { + contentType = APPLICATION_XML; + } + } + + // Setup qname support for result writers who declare that they support it + if (resultWriter.getSupportedSettings().contains(BasicQueryWriterSettings.ADD_SESAME_QNAME)) { + resultWriter.getWriterConfig().set(BasicQueryWriterSettings.ADD_SESAME_QNAME, true); + } + + resp.setContentType(contentType); + + // TODO: Make the following two settings configurable + + // Convert xsd:string back to plain literals where this behaviour is + // supported + if (resultWriter.getSupportedSettings().contains(BasicWriterSettings.XSD_STRING_TO_PLAIN_LITERAL)) { + resultWriter.getWriterConfig().set(BasicWriterSettings.XSD_STRING_TO_PLAIN_LITERAL, true); + } + + // Convert rdf:langString back to language literals where this behaviour + // is supported + if (resultWriter.getSupportedSettings().contains(BasicWriterSettings.RDF_LANGSTRING_TO_LANG_LITERAL)) { + resultWriter.getWriterConfig().set(BasicWriterSettings.RDF_LANGSTRING_TO_LANG_LITERAL, true); + } + + return new TupleResultBuilder(resultWriter, SimpleValueFactory.getInstance()); + } + + protected QueryResultWriter checkJSONP(HttpServletRequest req, OutputStream outputStream) + throws IOException + { + QueryResultWriter resultWriter = null; + // HACK : SES-2043 : Need to support Chrome who decide to send Accept: */* + // instead of application/javascript for JSONP queries, so need to check + // it first as other algorithm fails in this case. + // JSONP is enabled in the default properties, but if users setup their + // own application.properties file then it must be inserted explicitly + // to be enabled + if (appConfig != null && appConfig.getProperties().containsKey(JSONP_ENABLED)) { + + String jsonpEnabledProperty = appConfig.getProperties().getProperty(JSONP_ENABLED); + + // check if jsonp is a property and it is set to true + if (jsonpEnabledProperty != null && Boolean.parseBoolean(jsonpEnabledProperty)) { + String parameterName = null; + + // check whether they customised the parameter to use to identify + // the jsonp callback + if (appConfig.getProperties().containsKey(JSONP_CALLBACK_PARAMETER)) { + parameterName = appConfig.getProperties().getProperty(JSONP_CALLBACK_PARAMETER); + } + + // Use default parameter name if it was missing in the + // configuration after jsonp was enabled + if (parameterName == null || parameterName.trim().isEmpty()) { + parameterName = DEFAULT_JSONP_CALLBACK_PARAMETER; + } + + String parameter = req.getParameter(parameterName); + + if (parameter != null) { + parameter = parameter.trim(); + + if (parameter.isEmpty()) { + parameter = BasicQueryWriterSettings.JSONP_CALLBACK.getDefaultValue(); + } + + // check callback function name is a valid javascript function + // name + if (!JSONP_VALIDATOR.matcher(parameter).matches()) { + throw new IOException("Callback function name was invalid"); + } + + resultWriter = QueryResultIO.createWriter(TupleQueryResultFormat.JSON, outputStream); + + resultWriter.getWriterConfig().set(BasicQueryWriterSettings.JSONP_CALLBACK, parameter); + } + } + } + return resultWriter; + } +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/BaseRepositoryServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/BaseRepositoryServlet.java new file mode 100644 index 00000000000..b2d1851d29d --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/BaseRepositoryServlet.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.base; + +/** + * @deprecated since 4.0. Use {@link AbstractRepositoryServlet} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class BaseRepositoryServlet extends AbstractRepositoryServlet { + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/BaseServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/BaseServlet.java new file mode 100644 index 00000000000..a65f21efa4d --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/BaseServlet.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.base; + +/** + * @deprecated since 4.0. Use {@link AbstractServlet} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class BaseServlet extends AbstractServlet { + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/TransformationServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/TransformationServlet.java new file mode 100644 index 00000000000..4a111f1b45a --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/TransformationServlet.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.base; + +import java.io.IOException; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.rio.ParserConfig; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.eclipse.rdf4j.workbench.exceptions.MissingInitParameterException; +import org.eclipse.rdf4j.workbench.util.CookieHandler; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class TransformationServlet extends AbstractRepositoryServlet { + + protected static final ParserConfig NON_VERIFYING_PARSER_CONFIG; + + static { + NON_VERIFYING_PARSER_CONFIG = new ParserConfig(); + NON_VERIFYING_PARSER_CONFIG.set(BasicParserSettings.VERIFY_DATATYPE_VALUES, false); + NON_VERIFYING_PARSER_CONFIG.set(BasicParserSettings.VERIFY_LANGUAGE_TAGS, false); + NON_VERIFYING_PARSER_CONFIG.set(BasicParserSettings.VERIFY_RELATIVE_URIS, false); + } + + public static final String CONTEXT = "context"; + + protected static final String INFO = "info"; + + private static final String TRANSFORMATIONS = "transformations"; + + private static final Logger LOGGER = LoggerFactory.getLogger(TransformationServlet.class); + + private final Map defaults = new HashMap(); + + protected CookieHandler cookies; + + @Override + public void init(final ServletConfig config) + throws ServletException + { + super.init(config); + cookies = new CookieHandler(config, this); + if (config.getInitParameter(TRANSFORMATIONS) == null) { + throw new MissingInitParameterException(TRANSFORMATIONS); + } + if (config != null) { + final Enumeration names = config.getInitParameterNames(); + while (names.hasMoreElements()) { + final String name = (String)names.nextElement(); + if (name.startsWith("default-")) { + defaults.put(name.substring("default-".length()), config.getInitParameter(name)); + } + } + } + } + + public String[] getCookieNames() { + return new String[0]; + } + + @Override + public void service(final HttpServletRequest req, final HttpServletResponse resp) + throws ServletException, IOException + { + if (req.getCharacterEncoding() == null) { + req.setCharacterEncoding("UTF-8"); + } + resp.setCharacterEncoding("UTF-8"); + resp.setDateHeader("Expires", new Date().getTime() - 10000L); + resp.setHeader("Cache-Control", "no-cache, no-store"); + + final String contextPath = req.getContextPath(); + final String path = config.getInitParameter(TRANSFORMATIONS); + final String xslPath = contextPath + path; + try { + final WorkbenchRequest wreq = new WorkbenchRequest(repository, req, defaults); + + cookies.updateCookies(wreq, resp); + if ("POST".equals(req.getMethod())) { + doPost(wreq, resp, xslPath); + } + else { + service(wreq, resp, xslPath); + } + } + catch (RuntimeException e) { + throw e; + } + catch (Exception e) { + throw new ServletException(e); + } + } + + protected void doPost(final WorkbenchRequest wreq, final HttpServletResponse resp, final String xslPath) + throws Exception + { + service(wreq, resp, xslPath); + } + + protected void service(final WorkbenchRequest req, final HttpServletResponse resp, final String xslPath) + throws Exception + { + service(getTupleResultBuilder(req, resp, resp.getOutputStream()), xslPath); + } + + protected void service(final TupleResultBuilder writer, final String xslPath) + throws Exception + { + LOGGER.info("Call made to empty superclass implementation of service(PrintWriter,String) for path: {}", + xslPath); + } + +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/TupleServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/TupleServlet.java new file mode 100644 index 00000000000..0b0aad43e51 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/base/TupleServlet.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.base; + +import java.util.Arrays; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; + +public abstract class TupleServlet extends TransformationServlet { + + protected String xsl; + + protected String[] variables; + + public TupleServlet(String xsl, String... variables) { + super(); + this.xsl = xsl; + this.variables = variables; + } + + @Override + protected void service(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws Exception + { + TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + RepositoryConnection con = repository.getConnection(); + con.setParserConfig(NON_VERIFYING_PARSER_CONFIG); + try { + for (Namespace ns : Iterations.asList(con.getNamespaces())) { + builder.prefix(ns.getPrefix(), ns.getName()); + } + if (xsl != null) { + builder.transform(xslPath, xsl); + } + builder.start(variables); + builder.link(Arrays.asList("info")); + this.service(req, resp, builder, con); + builder.end(); + } + finally { + con.close(); + } + } + + protected void service(WorkbenchRequest req, HttpServletResponse resp, TupleResultBuilder builder, + RepositoryConnection con) + throws Exception + { + service(builder, con); + } + + protected void service(TupleResultBuilder builder, RepositoryConnection con) + throws Exception + { + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/AddServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/AddServlet.java new file mode 100644 index 00000000000..9530f1010f1 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/AddServlet.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.fileupload.FileUploadException; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AddServlet extends TransformationServlet { + + private static final String URL = "url"; + + private final Logger logger = LoggerFactory.getLogger(AddServlet.class); + + @Override + protected void doPost(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws IOException, RepositoryException, FileUploadException, QueryResultHandlerException + { + try { + String baseURI = req.getParameter("baseURI"); + String contentType = req.getParameter("Content-Type"); + if (req.isParameterPresent(CONTEXT)) { + Resource context = req.getResource(CONTEXT); + if (req.isParameterPresent(URL)) { + add(req.getUrl(URL), baseURI, contentType, context); + } + else { + add(req.getContentParameter(), baseURI, contentType, req.getContentFileName(), context); + } + } + else { + if (req.isParameterPresent(URL)) { + add(req.getUrl(URL), baseURI, contentType); + } + else { + add(req.getContentParameter(), baseURI, contentType, req.getContentFileName()); + } + } + resp.sendRedirect("summary"); + } + catch (BadRequestException exc) { + logger.warn(exc.toString(), exc); + TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(xslPath, "add.xsl"); + builder.start("error-message", "baseURI", CONTEXT, "Content-Type"); + builder.link(Arrays.asList(INFO)); + String baseURI = req.getParameter("baseURI"); + String context = req.getParameter(CONTEXT); + String contentType = req.getParameter("Content-Type"); + builder.result(exc.getMessage(), baseURI, context, contentType); + builder.end(); + } + } + + private void add(InputStream stream, String baseURI, String contentType, String contentFileName, + Resource... context) + throws BadRequestException, RepositoryException, IOException + { + if (contentType == null) { + throw new BadRequestException("No Content-Type provided"); + } + + RDFFormat format = null; + if ("autodetect".equals(contentType)) { + format = Rio.getParserFormatForFileName(contentFileName).orElseThrow( + () -> new BadRequestException("Could not automatically determine Content-Type for content: " + + contentFileName)); + } + else { + format = Rio.getParserFormatForMIMEType(contentType).orElseThrow( + () -> new BadRequestException("Unknown Content-Type: " + contentType)); + } + + RepositoryConnection con = repository.getConnection(); + try { + con.add(stream, baseURI, format, context); + } + catch (RDFParseException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + catch (IllegalArgumentException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + finally { + con.close(); + } + } + + private void add(URL url, String baseURI, String contentType, Resource... context) + throws BadRequestException, RepositoryException, IOException + { + if (contentType == null) { + throw new BadRequestException("No Content-Type provided"); + } + + RDFFormat format = null; + if ("autodetect".equals(contentType)) { + format = Rio.getParserFormatForFileName(url.getFile()).orElseThrow( + () -> new BadRequestException("Could not automatically determine Content-Type for content: " + + url.getFile())); + } + else { + format = Rio.getParserFormatForMIMEType(contentType).orElseThrow( + () -> new BadRequestException("Unknown Content-Type: " + contentType)); + } + + try { + RepositoryConnection con = repository.getConnection(); + try { + con.add(url, baseURI, format, context); + } + finally { + con.close(); + } + } + catch (RDFParseException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + catch (MalformedURLException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + catch (IllegalArgumentException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + } + + @Override + public void service(TupleResultBuilder builder, String xslPath) + throws RepositoryException, QueryResultHandlerException + { + // TupleResultBuilder builder = getTupleResultBuilder(req, resp); + builder.transform(xslPath, "add.xsl"); + builder.start(); + builder.link(Arrays.asList(INFO)); + builder.end(); + } + +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ClearServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ClearServlet.java new file mode 100644 index 00000000000..2407a1b9e38 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ClearServlet.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ClearServlet extends TransformationServlet { + + private final Logger logger = LoggerFactory.getLogger(ClearServlet.class); + + @Override + protected void doPost(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws IOException, RepositoryException, QueryResultHandlerException + { + try { + RepositoryConnection con = repository.getConnection(); + try { + if (req.isParameterPresent(CONTEXT)) { + con.clear(req.getResource(CONTEXT)); + } + else { + con.clear(); + } + } + catch (ClassCastException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + finally { + con.close(); + } + resp.sendRedirect("summary"); + } + catch (BadRequestException exc) { + logger.warn(exc.toString(), exc); + TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(xslPath, "clear.xsl"); + builder.start("error-message", CONTEXT); + builder.link(Arrays.asList(INFO)); + builder.result(exc.getMessage(), req.getParameter(CONTEXT)); + builder.end(); + } + } + + @Override + public void service(TupleResultBuilder builder, String xslPath) + throws RepositoryException, QueryResultHandlerException + { + // TupleResultBuilder builder = new TupleResultBuilder(out); + builder.transform(xslPath, "clear.xsl"); + builder.start(); + builder.link(Arrays.asList(INFO)); + builder.end(); + } + +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ContextsServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ContextsServlet.java new file mode 100644 index 00000000000..1db54dfe473 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ContextsServlet.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.workbench.base.TupleServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; + +public class ContextsServlet extends TupleServlet { + + public ContextsServlet() { + super("contexts.xsl", "context"); + } + + @Override + protected void service(TupleResultBuilder builder, RepositoryConnection con) + throws RepositoryException, QueryResultHandlerException + { + for (Resource ctx : Iterations.asList(con.getContextIDs())) { + builder.result(ctx); + } + } + +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/CreateServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/CreateServlet.java new file mode 100644 index 00000000000..3930b82cf57 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/CreateServlet.java @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.util.Arrays; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.util.Models; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.ConfigTemplate; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.config.RepositoryConfigSchema; +import org.eclipse.rdf4j.repository.config.RepositoryConfigUtil; +import org.eclipse.rdf4j.repository.manager.RepositoryInfo; +import org.eclipse.rdf4j.repository.manager.SystemRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; +import org.eclipse.rdf4j.runtime.RepositoryManagerFederator; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; + +public class CreateServlet extends TransformationServlet { + + private RepositoryManagerFederator rmf; + + @Override + public void init(final ServletConfig config) + throws ServletException + { + super.init(config); + this.rmf = new RepositoryManagerFederator(manager); + } + + /** + * POST requests to this servlet come from the various specific create-* form + * submissions. + */ + @Override + protected void doPost(final WorkbenchRequest req, final HttpServletResponse resp, final String xslPath) + throws ServletException + { + try { + resp.sendRedirect("../" + createRepositoryConfig(req) + "/summary"); + } + catch (Exception e) { + throw new ServletException(e); + } + } + + /** + * GET requests to this servlet come from the Workbench side bar or from + * create.xsl form submissions. + * + * @throws RepositoryException + * @throws QueryResultHandlerException + */ + @Override + protected void service(final WorkbenchRequest req, final HttpServletResponse resp, final String xslPath) + throws IOException, RepositoryException, QueryResultHandlerException + { + final TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + boolean federate; + if (req.isParameterPresent("type")) { + final String type = req.getTypeParameter(); + federate = "federate".equals(type); + builder.transform(xslPath, "create-" + type + ".xsl"); + } + else { + federate = false; + builder.transform(xslPath, "create.xsl"); + } + builder.start(federate ? new String[] { "id", "description", "location" } : new String[] {}); + builder.link(Arrays.asList(INFO)); + if (federate) { + for (RepositoryInfo info : manager.getAllRepositoryInfos()) { + String identity = info.getId(); + if (!SystemRepository.ID.equals(identity)) { + builder.result(identity, info.getDescription(), info.getLocation()); + } + } + } + builder.end(); + } + + private String createRepositoryConfig(final WorkbenchRequest req) + throws IOException, OpenRDFException + { + String type = req.getTypeParameter(); + String newID; + if ("federate".equals(type)) { + newID = req.getParameter("Local repository ID"); + rmf.addFed(newID, req.getParameter("Repository title"), + Arrays.asList(req.getParameterValues("memberID")), + Boolean.parseBoolean(req.getParameter("readonly")), + Boolean.parseBoolean(req.getParameter("distinct"))); + } + else { + newID = updateRepositoryConfig(getConfigTemplate(type).render(req.getSingleParameterMap())).getID(); + } + return newID; + } + + private RepositoryConfig updateRepositoryConfig(final String configString) + throws IOException, OpenRDFException + { + final Repository systemRepo = manager.getSystemRepository(); + final Model graph = new LinkedHashModel(); + final RDFParser rdfParser = Rio.createParser(RDFFormat.TURTLE, systemRepo.getValueFactory()); + rdfParser.setRDFHandler(new StatementCollector(graph)); + rdfParser.parse(new StringReader(configString), RepositoryConfigSchema.NAMESPACE); + + Resource res = Models.subject( + graph.filter(null, RDF.TYPE, RepositoryConfigSchema.REPOSITORY)).orElseThrow( + () -> new RepositoryException("could not find instance of Repository class in config")); + final RepositoryConfig repConfig = RepositoryConfig.create(graph, res); + repConfig.validate(); + RepositoryConfigUtil.updateRepositoryConfigs(systemRepo, repConfig); + return repConfig; + } + + private ConfigTemplate getConfigTemplate(final String type) + throws IOException + { + final InputStream ttlInput = RepositoryConfig.class.getResourceAsStream(type + ".ttl"); + try { + final String template = IOUtil.readString(new InputStreamReader(ttlInput, "UTF-8")); + return new ConfigTemplate(template); + } + finally { + ttlInput.close(); + } + } +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/DeleteServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/DeleteServlet.java new file mode 100644 index 00000000000..660fc96f884 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/DeleteServlet.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.manager.RepositoryInfo; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Servlet responsible for presenting the list of repositories, and deleting the + * chosen one. + */ +public class DeleteServlet extends TransformationServlet { + + /** + * Deletes the repository with the given ID, then redirects to the repository + * selection page. If given a "checkSafe" parameter, instead returns JSON + * response with safe field set to true if safe, false if not. + */ + @Override + protected void doPost(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws Exception + { + dropRepository(req.getParameter("id")); + resp.sendRedirect("../"); + } + + @Override + protected void service(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws Exception + { + String checkSafe = req.getParameter("checkSafe"); + if (null == checkSafe) { + // Display the form. + super.service(req, resp, xslPath); + } + else { + // Respond to 'checkSafe' XmlHttpRequest with JSON. + final PrintWriter writer = new PrintWriter(new BufferedWriter(resp.getWriter())); + writer.write(new JSONObject().put("safe", manager.isSafeToRemove(checkSafe)).toString()); + writer.flush(); + } + + } + + private void dropRepository(String identity) + throws RepositoryException, RepositoryConfigException + { + manager.removeRepository(identity); + } + + /** + * Presents a page where the user can choose a repository ID to delete. + */ + @Override + public void service(TupleResultBuilder builder, String xslPath) + throws RepositoryException, QueryResultHandlerException + { + builder.transform(xslPath, "delete.xsl"); + builder.start("readable", "writeable", "id", "description", "location"); + builder.link(Arrays.asList(INFO)); + for (RepositoryInfo info : manager.getAllRepositoryInfos()) { + builder.result(info.isReadable(), info.isWritable(), info.getId(), info.getDescription(), + info.getLocation()); + } + builder.end(); + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ExploreServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ExploreServlet.java new file mode 100644 index 00000000000..c5a9fc9b475 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ExploreServlet.java @@ -0,0 +1,305 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.util.Arrays; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryResult; +import org.eclipse.rdf4j.workbench.base.TupleServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ExploreServlet extends TupleServlet { + + private final Logger logger = LoggerFactory.getLogger(ExploreServlet.class); + + protected static final String LIMIT = "limit_explore"; + + protected static final int LIMIT_DEFAULT = 100; + + public ExploreServlet() { + super("explore.xsl", "subject", "predicate", "object", "context"); + } + + @Override + public String[] getCookieNames() { + return new String[] { LIMIT, "total_result_count", "show-datatypes" }; + } + + @Override + public void service(final WorkbenchRequest req, final HttpServletResponse resp, final String xslPath) + throws Exception + { + try { + super.service(req, resp, xslPath); + } + catch (BadRequestException exc) { + logger.warn(exc.toString(), exc); + final TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(xslPath, "explore.xsl"); + builder.start("error-message"); + builder.link(Arrays.asList(INFO)); + builder.result(exc.getMessage()); + builder.end(); + } + } + + @Override + protected void service(final WorkbenchRequest req, final HttpServletResponse resp, + final TupleResultBuilder builder, final RepositoryConnection con) + throws BadRequestException, OpenRDFException + { + final Value value = req.getValue("resource"); + logger.debug("resource = {}", value); + + // At worst, malicious parameter value could cause inaccurate + // reporting of count in page. + int count = req.getInt("know_total"); + if (count == 0) { + count = this.processResource(con, builder, value, 0, Integer.MAX_VALUE, false).getTotalResultCount(); + } + this.cookies.addTotalResultCountCookie(req, resp, (int)count); + final int offset = req.getInt("offset"); + int limit = LIMIT_DEFAULT; + if (req.isParameterPresent(LIMIT)) { + limit = req.getInt(LIMIT); + if (0 == limit) { + limit = Integer.MAX_VALUE; + } + } + this.processResource(con, builder, value, offset, limit, true); + } + + /** + * Query the repository for all instances of the given value, optionally + * writing the results into the HTTP response. + * + * @param con + * the connection to the repository + * @param builder + * used for writing to the HTTP response + * @param value + * the value to query the repository for + * @param offset + * The result at which to start rendering results. + * @param limit + * The limit on the number of results to render. + * @param render + * If false, suppresses output to the HTTP response. + * @throws OpenRDFException + * if there is an issue iterating through results + * @return The count of all triples in the repository using the given value. + */ + protected ResultCursor processResource(final RepositoryConnection con, final TupleResultBuilder builder, + final Value value, final int offset, final int limit, final boolean render) + throws OpenRDFException + { + final ResultCursor cursor = new ResultCursor(offset, limit, render); + boolean resource = value instanceof Resource; + if (resource) { + export(con, builder, cursor, (Resource)value, null, null); + logger.debug("After subject, total = {}", cursor.getTotalResultCount()); + } + if (value instanceof IRI) { + export(con, builder, cursor, null, (IRI)value, null); + logger.debug("After predicate, total = {}", cursor.getTotalResultCount()); + } + if (value != null) { + export(con, builder, cursor, null, null, value); + logger.debug("After object, total = {}", cursor.getTotalResultCount()); + } + if (resource) { + export(con, builder, cursor, null, null, null, (Resource)value); + logger.debug("After context, total = {}", cursor.getTotalResultCount()); + } + return cursor; + } + + /** + *

+ * Render statements in the repository matching the given pattern to the HTTP + * response. It is an implicit assumption when this calls + * {@link #isFirstTimeSeen} that {@link #processResource} 's calls into here + * have been made in the following order: + *

+ *
    + *
  1. export(*, subject, null, null, null)
  2. + *
  3. export(*, null, predicate, null, null)
  4. + *
  5. export(*, null, null, object, null)
  6. + *
  7. export(*, null, null, null, context)
  8. + *
+ * + * @param con + * the connection to the repository + * @param builder + * used for writing to the HTTP response + * @param cursor + * used for keeping track of our location in the result set + * @param subj + * the triple subject + * @param pred + * the triple predicate + * @param obj + * the triple object + * @param context + * the triple context + */ + private void export(RepositoryConnection con, TupleResultBuilder builder, ResultCursor cursor, + Resource subj, IRI pred, Value obj, Resource... context) + throws OpenRDFException, MalformedQueryException, QueryEvaluationException + { + RepositoryResult result = con.getStatements(subj, pred, obj, true, context); + try { + while (result.hasNext()) { + Statement statement = result.next(); + if (isFirstTimeSeen(statement, pred, obj, context)) { + if (cursor.mayRender()) { + builder.result(statement.getSubject(), statement.getPredicate(), statement.getObject(), + statement.getContext()); + } + cursor.advance(); + } + } + } + finally { + result.close(); + } + } + + /** + * Gets whether this is the first time the result quad has been seen. + * + * @param patternPredicate + * the predicate asked for, or null if another quad element was asked + * for + * @param patternObject + * the object asked for, or null if another quad element was asked for + * @param result + * the result statement to determine if we've already seen + * @param patternContext + * the context asked for, or null if another quad element was asked + * for + * @return true, if this is the first time the quad has been seen, false + * otherwise + */ + private boolean isFirstTimeSeen(Statement result, IRI patternPredicate, Value patternObject, + Resource... patternContext) + { + Resource resultSubject = result.getSubject(); + IRI resultPredicate = result.getPredicate(); + Value resultObject = result.getObject(); + boolean firstTimeSeen; + if (1 == patternContext.length) { + // I.e., when context matches explore value. + Resource ctx = patternContext[0]; + firstTimeSeen = !(ctx.equals(resultSubject) || ctx.equals(resultPredicate) || ctx.equals(resultObject)); + } + else if (null != patternObject) { + // I.e., when object matches explore value. + firstTimeSeen = !(resultObject.equals(resultSubject) || resultObject.equals(resultPredicate)); + } + else if (null != patternPredicate) { + // I.e., when predicate matches explore value. + firstTimeSeen = !(resultPredicate.equals(resultSubject)); + } + else { + // I.e., when subject matches explore value. + firstTimeSeen = true; + } + return firstTimeSeen; + } + + /** + * Class for keeping track of location within the result set, relative to + * offset and limit. + * + * @author Dale Visser + */ + protected class ResultCursor { + + private int untilFirst; + + private int totalResults = 0; + + private int renderedResults = 0; + + private final int limit; + + private final boolean render; + + /** + * @param offset + * the desired offset at which rendering should start + * @param limit + * the desired maximum number of results to render + * @param render + * if false, suppresses any rendering + */ + public ResultCursor(final int offset, final int limit, final boolean render) { + this.render = render; + this.limit = limit > 0 ? limit : Integer.MAX_VALUE; + this.untilFirst = offset >= 0 ? offset : 0; + } + + /** + * Gets the total number of results. Only meant to be called after + * advance() has been called for all results in the set. + * + * @return the number of times advance() has been called + */ + public int getTotalResultCount() { + return this.totalResults; + } + + /** + * Gets the number of results that were actually rendered. Only meant to + * be called after advance() has been called for all results in the set. + * + * @return the number of times advance() has been called when + * this.mayRender() evaluated to true + */ + public int getRenderedResultCount() { + return this.renderedResults; + } + + /** + * @return whether it is allowed to render the next result + */ + public boolean mayRender() { + return this.render && (this.untilFirst == 0 && this.renderedResults < this.limit); + } + + /** + * Advances the cursor, incrementing the total count, and moving other + * internal counters. + */ + public void advance() { + this.totalResults++; + if (this.mayRender()) { + this.renderedResults++; + } + + if (this.untilFirst > 0) { + this.untilFirst--; + } + } + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ExportServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ExportServlet.java new file mode 100644 index 00000000000..8d536dff10f --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/ExportServlet.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import static org.eclipse.rdf4j.rio.RDFWriterRegistry.getInstance; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryResult; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFWriterFactory; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.workbench.base.TupleServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; + +public class ExportServlet extends TupleServlet { + + public ExportServlet() { + super("export.xsl", "subject", "predicate", "object", "context"); + } + + @Override + public String[] getCookieNames() { + return new String[] { ExploreServlet.LIMIT, "Accept" }; + } + + @Override + protected void service(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws Exception + { + if (req.isParameterPresent("Accept")) { + String accept = req.getParameter("Accept"); + RDFFormat format = Rio.getWriterFormatForMIMEType(accept).orElseThrow(Rio.unsupportedFormat(accept)); + resp.setContentType(accept); + String ext = format.getDefaultFileExtension(); + String attachment = "attachment; filename=export." + ext; + resp.setHeader("Content-disposition", attachment); + RepositoryConnection con = repository.getConnection(); + con.setParserConfig(NON_VERIFYING_PARSER_CONFIG); + try { + RDFWriterFactory factory = getInstance().get(format).orElseThrow(Rio.unsupportedFormat(format)); + if (format.getCharset() != null) { + resp.setCharacterEncoding(format.getCharset().name()); + } + con.export(factory.getWriter(resp.getOutputStream())); + } + finally { + con.close(); + } + } + else { + super.service(req, resp, xslPath); + } + } + + @Override + protected void service(WorkbenchRequest req, HttpServletResponse resp, TupleResultBuilder builder, + RepositoryConnection con) + throws Exception + { + int limit = ExploreServlet.LIMIT_DEFAULT; + if (req.getInt(ExploreServlet.LIMIT) > 0) { + limit = req.getInt(ExploreServlet.LIMIT); + } + RepositoryResult result = con.getStatements(null, null, null, false); + try { + for (int i = 0; result.hasNext() && (i < limit || limit < 1); i++) { + Statement st = result.next(); + builder.result(st.getSubject(), st.getPredicate(), st.getObject(), st.getContext()); + } + } + finally { + result.close(); + } + } + +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/InfoServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/InfoServlet.java new file mode 100644 index 00000000000..dc5b0920c8b --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/InfoServlet.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import static org.eclipse.rdf4j.query.parser.QueryParserRegistry.getInstance; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.query.parser.QueryParserFactory; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultWriterFactory; +import org.eclipse.rdf4j.query.resultio.BooleanQueryResultWriterRegistry; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterFactory; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultWriterRegistry; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.rio.RDFParserFactory; +import org.eclipse.rdf4j.rio.RDFParserRegistry; +import org.eclipse.rdf4j.rio.RDFWriterFactory; +import org.eclipse.rdf4j.rio.RDFWriterRegistry; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; + +public class InfoServlet extends TransformationServlet { + + @Override + public String[] getCookieNames() { + return new String[] { "limit", "queryLn", "infer", "Accept", "Content-Type" }; + } + + protected void service(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws Exception + { + String id = info.getId(); + + // "Caching" of servlet instances can cause this request to succeed even + // if the repository has been deleted. Client-side code using InfoServlet + // for repository existential checks expects an error response when the id + // no longer exists. + if (null != id && !manager.hasRepositoryConfig(id)){ + throw new RepositoryConfigException(id + " does not exist."); + } + TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.start("id", "description", "location", "server", "readable", "writeable", "default-limit", + "default-queryLn", "default-infer", "default-Accept", "default-Content-Type", "upload-format", + "query-format", "graph-download-format", "tuple-download-format", "boolean-download-format"); + String desc = info.getDescription(); + URL loc = info.getLocation(); + URL server = getServer(); + builder.result(id, desc, loc, server, info.isReadable(), info.isWritable()); + builder.namedResult("default-limit", req.getParameter("limit")); + builder.namedResult("default-queryLn", req.getParameter("queryLn")); + builder.namedResult("default-infer", req.getParameter("infer")); + builder.namedResult("default-Accept", req.getParameter("Accept")); + builder.namedResult("default-Content-Type", req.getParameter("Content-Type")); + for (RDFParserFactory parser : RDFParserRegistry.getInstance().getAll()) { + String mimeType = parser.getRDFFormat().getDefaultMIMEType(); + String name = parser.getRDFFormat().getName(); + builder.namedResult("upload-format", mimeType + " " + name); + } + for (QueryParserFactory factory : getInstance().getAll()) { + String name = factory.getQueryLanguage().getName(); + builder.namedResult("query-format", name + " " + name); + } + for (RDFWriterFactory writer : RDFWriterRegistry.getInstance().getAll()) { + String mimeType = writer.getRDFFormat().getDefaultMIMEType(); + String name = writer.getRDFFormat().getName(); + builder.namedResult("graph-download-format", mimeType + " " + name); + } + for (TupleQueryResultWriterFactory writer : TupleQueryResultWriterRegistry.getInstance().getAll()) { + String mimeType = writer.getTupleQueryResultFormat().getDefaultMIMEType(); + String name = writer.getTupleQueryResultFormat().getName(); + builder.namedResult("tuple-download-format", mimeType + " " + name); + } + for (BooleanQueryResultWriterFactory writer : BooleanQueryResultWriterRegistry.getInstance().getAll()) { + String mimeType = writer.getBooleanQueryResultFormat().getDefaultMIMEType(); + String name = writer.getBooleanQueryResultFormat().getName(); + builder.namedResult("boolean-download-format", mimeType + " " + name); + } + builder.end(); + } + + private URL getServer() { + try { + return manager.getLocation(); + } + catch (MalformedURLException exc) { + return null; + } + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/InformationServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/InformationServlet.java new file mode 100644 index 00000000000..fbef748602e --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/InformationServlet.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.util.Arrays; + +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; + +public class InformationServlet extends TransformationServlet { + + @Override + public void service(final TupleResultBuilder builder, final String xslPath) + throws RepositoryException, QueryResultHandlerException + { + // final TupleResultBuilder builder = getTupleResultBuilder(req, resp); + builder.transform(xslPath, "information.xsl"); + builder.start("version", "os", "jvm", "user", "memory-used", "maximum-memory"); + builder.link(Arrays.asList(INFO)); + final String version = this.appConfig.getVersion().toString(); + final String osName = getOsName(); + final String jvm = getJvmName(); + final String user = System.getProperty("user.name"); + final long total = Runtime.getRuntime().totalMemory(); + final long free = Runtime.getRuntime().freeMemory(); + final String used = ((total - free) / 1024 / 1024) + " MB"; + final String max = (Runtime.getRuntime().maxMemory() / 1024 / 1024) + " MB"; + builder.result(version, osName, jvm, user, used, max); + builder.end(); + } + + private String getOsName() { + final StringBuilder builder = new StringBuilder(); + builder.append(System.getProperty("os.name")).append(" "); + builder.append(System.getProperty("os.version")).append(" ("); + builder.append(System.getProperty("os.arch")).append(")"); + return builder.toString(); + } + + private String getJvmName() { + final StringBuilder builder = new StringBuilder(); + builder.append(System.getProperty("java.vm.vendor")).append(" "); + builder.append(System.getProperty("java.vm.name")).append(" ("); + builder.append(System.getProperty("java.version")).append(")"); + return builder.toString(); + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/NamespacesServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/NamespacesServlet.java new file mode 100644 index 00000000000..ac0a87d3604 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/NamespacesServlet.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.util.Arrays; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; + +public class NamespacesServlet extends TransformationServlet { + + @Override + protected void doPost(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws Exception + { + RepositoryConnection con = repository.getConnection(); + try { + String prefix = req.getParameter("prefix"); + String namespace = req.getParameter("namespace"); + if (namespace.length() > 0) { + con.setNamespace(prefix, namespace); + } + else { + con.removeNamespace(prefix); + } + } + finally { + con.close(); + } + super.service(req, resp, xslPath); + } + + @Override + public void service(TupleResultBuilder builder, String xslPath) + throws RepositoryException, QueryResultHandlerException + { + // TupleResultBuilder builder = new TupleResultBuilder(out); + builder.transform(xslPath, "namespaces.xsl"); + RepositoryConnection con = repository.getConnection(); + con.setParserConfig(NON_VERIFYING_PARSER_CONFIG); + try { + builder.start("prefix", "namespace"); + builder.link(Arrays.asList(INFO)); + for (Namespace ns : Iterations.asList(con.getNamespaces())) { + builder.result(ns.getPrefix(), ns.getName()); + } + builder.end(); + } + finally { + con.close(); + } + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/QueryServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/QueryServlet.java new file mode 100644 index 00000000000..3112e98c411 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/QueryServlet.java @@ -0,0 +1,455 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.WeakHashMap; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.resultio.QueryResultFormat; +import org.eclipse.rdf4j.query.resultio.QueryResultIO; +import org.eclipse.rdf4j.query.resultio.UnsupportedQueryResultFormatException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.http.HTTPQueryEvaluationException; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.QueryEvaluator; +import org.eclipse.rdf4j.workbench.util.QueryStorage; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class QueryServlet extends TransformationServlet { + + protected static final String REF = "ref"; + + protected static final String LIMIT = "limit_query"; + + private static final String QUERY_LN = "queryLn"; + + private static final String INFER = "infer"; + + private static final String ACCEPT = "Accept"; + + protected static final String QUERY = "query"; + + private static final String[] EDIT_PARAMS = new String[] { QUERY_LN, QUERY, INFER, LIMIT }; + + private static final Logger LOGGER = LoggerFactory.getLogger(QueryServlet.class); + + private static final QueryEvaluator EVAL = QueryEvaluator.INSTANCE; + + private QueryStorage storage; + + protected boolean writeQueryCookie; + + // Poor Man's Cache: At the very least, garbage collection can clean up keys + // followed by values whenever the JVM faces memory pressure. + private static Map queryCache = Collections.synchronizedMap( + new WeakHashMap()); + + /** + * For testing purposes only. + * + * @param testQueryCache + * cache to use instead of the production cache instance + */ + protected static void substituteQueryCache(Map testQueryCache) { + queryCache = testQueryCache; + } + + protected void substituteQueryStorage(QueryStorage storage) { + this.storage = storage; + } + + /** + * @return the names of the cookies that will be retrieved from the request, + * and returned in the response + */ + @Override + public String[] getCookieNames() { + String[] result; + if (writeQueryCookie) { + result = new String[] { QUERY, REF, LIMIT, QUERY_LN, INFER, "total_result_count", "show-datatypes" }; + } + else { + result = new String[] { REF, LIMIT, QUERY_LN, INFER, "total_result_count", "show-datatypes" }; + } + return result; + } + + /** + * Initialize this instance of the servlet. + * + * @param config + * configuration passed in by the application container + */ + @Override + public void init(final ServletConfig config) + throws ServletException + { + super.init(config); + try { + this.storage = QueryStorage.getSingletonInstance(this.appConfig); + } + catch (RepositoryException e) { + throw new ServletException(e); + } + catch (IOException e) { + throw new ServletException(e); + } + } + + @Override + public void destroy() { + this.storage.shutdown(); + super.destroy(); + } + + /** + * Long query strings could blow past the Tomcat default 8k HTTP header limit + * if stuffed into a cookie. In this case, we need to set a flag to avoid + * this happening before + * {@link TransformationServlet#service(HttpServletRequest, HttpServletResponse)} + * is called. A much lower limit on the size of the query text is used to + * stay well below the Tomcat limitation. + */ + @Override + public final void service(final HttpServletRequest req, final HttpServletResponse resp) + throws ServletException, IOException + { + this.writeQueryCookie = shouldWriteQueryCookie(req.getParameter(QUERY)); + super.service(req, resp); + } + + /** + *

+ * Determines if the servlet should write out the query text into a cookie as + * received, or write it's hash instead. + *

+ *

+ * Note: This is a separate method for testing purposes. + *

+ * + * @param queryText + * the text received as the value for the parameter 'query' + */ + protected boolean shouldWriteQueryCookie(String queryText) { + return (null == queryText || queryText.length() <= 2048); + } + + @Override + protected void service(final WorkbenchRequest req, final HttpServletResponse resp, final String xslPath) + throws IOException, OpenRDFException, BadRequestException, JSONException + { + if (!writeQueryCookie) { + // If we suppressed putting the query text into the cookies before. + cookies.addCookie(req, resp, REF, "hash"); + String queryValue = req.getParameter(QUERY); + String hash = String.valueOf(queryValue.hashCode()); + queryCache.put(hash, queryValue); + cookies.addCookie(req, resp, QUERY, hash); + } + if ("get".equals(req.getParameter("action"))) { + JSONObject json = new JSONObject(); + json.put("queryText", getQueryText(req)); + PrintWriter writer = new PrintWriter(new BufferedWriter(resp.getWriter())); + try { + writer.write(json.toString()); + } + finally { + writer.flush(); + } + } + else { + handleStandardBrowserRequest(req, resp, xslPath); + } + } + + private void handleStandardBrowserRequest(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws IOException, OpenRDFException, QueryResultHandlerException + { + setContentType(req, resp); + OutputStream out = resp.getOutputStream(); + try { + service(req, resp, out, xslPath); + } + catch (BadRequestException exc) { + LOGGER.warn(exc.toString(), exc); + TupleResultBuilder builder = getTupleResultBuilder(req, resp, out); + builder.transform(xslPath, "query.xsl"); + builder.start("error-message"); + builder.link(Arrays.asList(INFO, "namespaces")); + builder.result(exc.getMessage()); + builder.end(); + } + catch (HTTPQueryEvaluationException exc) { + LOGGER.warn(exc.toString(), exc); + TupleResultBuilder builder = getTupleResultBuilder(req, resp, out); + builder.transform(xslPath, "query.xsl"); + builder.start("error-message"); + builder.link(Arrays.asList(INFO, "namespaces")); + builder.result(exc.getMessage()); + builder.end(); + } + finally { + out.flush(); + } + } + + @Override + protected void doPost(final WorkbenchRequest req, final HttpServletResponse resp, final String xslPath) + throws IOException, BadRequestException, OpenRDFException, JSONException + { + final String action = req.getParameter("action"); + if ("save".equals(action)) { + saveQuery(req, resp); + } + else if ("edit".equals(action)) { + if (canReadSavedQuery(req)) { + /* only need read access for edit action, since we are only reading the saved query text + to present it in the editor */ + final TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(xslPath, "query.xsl"); + builder.start(EDIT_PARAMS); + builder.link(Arrays.asList(INFO, "namespaces")); + final String queryLn = req.getParameter(EDIT_PARAMS[0]); + final String query = getQueryText(req); + final Boolean infer = Boolean.valueOf(req.getParameter(EDIT_PARAMS[2])); + final Literal limit = SimpleValueFactory.getInstance().createLiteral( + req.getParameter(EDIT_PARAMS[3]), XMLSchema.INTEGER); + builder.result(queryLn, query, infer, limit); + builder.end(); + } + else { + throw new BadRequestException("Current user may not read the given query."); + } + } + else if ("exec".equals(action)) { + if (canReadSavedQuery(req)) { + service(req, resp, xslPath); + } + else { + throw new BadRequestException("Current user may not read the given query."); + } + } + else { + throw new BadRequestException("POST with unexpected action parameter value: " + action); + } + } + + private void saveQuery(final WorkbenchRequest req, final HttpServletResponse resp) + throws IOException, BadRequestException, OpenRDFException, JSONException + { + resp.setContentType("application/json"); + final JSONObject json = new JSONObject(); + final HTTPRepository http = (HTTPRepository)repository; + final boolean accessible = storage.checkAccess(http); + json.put("accessible", accessible); + if (accessible) { + final String queryName = req.getParameter("query-name"); + String userName = getUserNameFromParameter(req, SERVER_USER); + final boolean existed = storage.askExists(http, queryName, userName); + json.put("existed", existed); + final boolean written = Boolean.valueOf(req.getParameter("overwrite")) || !existed; + if (written) { + final boolean shared = !Boolean.valueOf(req.getParameter("save-private")); + final QueryLanguage queryLanguage = QueryLanguage.valueOf(req.getParameter(QUERY_LN)); + final String queryText = req.getParameter(QUERY); + final boolean infer = req.isParameterPresent(INFER) ? Boolean.valueOf(req.getParameter(INFER)) + : false; + final int rowsPerPage = Integer.valueOf(req.getParameter(LIMIT)); + if (existed) { + final IRI query = storage.selectSavedQuery(http, userName, queryName); + storage.updateQuery(query, userName, shared, queryLanguage, queryText, infer, rowsPerPage); + } + else { + storage.saveQuery(http, queryName, userName, shared, queryLanguage, queryText, infer, + rowsPerPage); + } + } + json.put("written", written); + } + final PrintWriter writer = new PrintWriter(new BufferedWriter(resp.getWriter())); + writer.write(json.toString()); + writer.flush(); + } + + private String getUserNameFromParameter(WorkbenchRequest req, String parameter) { + String userName = req.getParameter(parameter); + if (null == userName) { + userName = ""; + } + return userName; + } + + private void setContentType(final WorkbenchRequest req, final HttpServletResponse resp) { + String result = "application/xml"; + String ext = "xml"; + if (req.isParameterPresent(ACCEPT)) { + final String accept = req.getParameter(ACCEPT); + final Optional format = Rio.getWriterFormatForMIMEType(accept); + if (format.isPresent()) { + result = format.get().getDefaultMIMEType(); + ext = format.get().getDefaultFileExtension(); + } + else { + final Optional tupleFormat = QueryResultIO.getWriterFormatForMIMEType(accept); + + if (tupleFormat.isPresent()) { + result = tupleFormat.get().getDefaultMIMEType(); + ext = tupleFormat.get().getDefaultFileExtension(); + } + else { + final Optional booleanFormat = QueryResultIO.getBooleanWriterFormatForMIMEType( + accept); + + if (booleanFormat.isPresent()) { + result = booleanFormat.get().getDefaultMIMEType(); + ext = booleanFormat.get().getDefaultFileExtension(); + } + } + } + } + + resp.setContentType(result); + if (!result.equals("application/xml")) { + final String attachment = "attachment; filename=query." + ext; + resp.setHeader("Content-disposition", attachment); + } + } + + private void service(final WorkbenchRequest req, final HttpServletResponse resp, final OutputStream out, + final String xslPath) + throws BadRequestException, OpenRDFException, UnsupportedQueryResultFormatException, IOException + { + final RepositoryConnection con = repository.getConnection(); + con.setParserConfig(NON_VERIFYING_PARSER_CONFIG); + try { + final TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + for (Namespace ns : Iterations.asList(con.getNamespaces())) { + builder.prefix(ns.getPrefix(), ns.getName()); + } + String query = getQueryText(req); + if (query.isEmpty()) { + builder.transform(xslPath, "query.xsl"); + builder.start(); + builder.link(Arrays.asList(INFO, "namespaces")); + builder.end(); + } + else { + try { + EVAL.extractQueryAndEvaluate(builder, resp, out, xslPath, con, query, req, this.cookies); + } + catch (MalformedQueryException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + catch (HTTPQueryEvaluationException exc) { + if (exc.getCause() instanceof MalformedQueryException) { + throw new BadRequestException(exc.getCause().getMessage(), exc); + } + throw exc; + } + } + } + finally { + con.close(); + } + } + + /** + * @param req + * for looking at the request parameters + * @return the query text, if it can somehow be retrieved from request + * parameters, otherwise an empty string + * @throws BadRequestException + * if a problem occurs grabbing the request from storage + * @throws OpenRDFException + * if a problem occurs grabbing the request from storage + */ + protected String getQueryText(WorkbenchRequest req) + throws BadRequestException, OpenRDFException + { + String result; + if (req.isParameterPresent(QUERY)) { + String query = req.getParameter(QUERY); + if (req.isParameterPresent(REF)) { + String ref = req.getParameter(REF); + if ("text".equals(ref)) { + result = query; + } + else if ("hash".equals(ref)) { + result = queryCache.get(query); + if (null == result) { + result = ""; + } + } + else if ("id".equals(ref)) { + result = storage.getQueryText((HTTPRepository)repository, + getUserNameFromParameter(req, "owner"), query); + } + else { + // if ref not recognized assume request meant "text" + result = query; + } + } + else { + result = query; + } + } + else { + result = ""; + } + return result; + } + + private boolean canReadSavedQuery(WorkbenchRequest req) + throws BadRequestException, OpenRDFException + { + if (req.isParameterPresent(REF)) { + return "id".equals(req.getParameter(REF)) + ? storage.canRead( + storage.selectSavedQuery((HTTPRepository)repository, + getUserNameFromParameter(req, "owner"), req.getParameter(QUERY)), + getUserNameFromParameter(req, SERVER_USER)) + : true; + } + else { + throw new BadRequestException("Expected 'ref' parameter in request."); + } + } + +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/RemoveServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/RemoveServlet.java new file mode 100644 index 00000000000..aef5e51509a --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/RemoveServlet.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.io.IOException; +import java.util.Arrays; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RemoveServlet extends TransformationServlet { + + private final Logger logger = LoggerFactory.getLogger(RemoveServlet.class); + + @Override + protected void doPost(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws IOException, RepositoryException, QueryResultHandlerException + { + String objectParameter = req.getParameter("obj"); + try { + RepositoryConnection con = repository.getConnection(); + try { + Resource subj = req.getResource("subj"); + IRI pred = req.getURI("pred"); + Value obj = req.getValue("obj"); + if (subj == null && pred == null && obj == null && !req.isParameterPresent(CONTEXT)) { + throw new BadRequestException("No values"); + } + remove(con, subj, pred, obj, req); + // HACK: HTML sends \r\n, but SAX strips out the \r, try both ways + if (obj instanceof Literal && obj.stringValue().contains("\r\n")) { + obj = Protocol.decodeValue(objectParameter.replace("\r\n", "\n"), con.getValueFactory()); + remove(con, subj, pred, obj, req); + } + } + catch (ClassCastException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + finally { + con.close(); + } + resp.sendRedirect("summary"); + } + catch (BadRequestException exc) { + logger.warn(exc.toString(), exc); + TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(xslPath, "remove.xsl"); + builder.start("error-message", "subj", "pred", "obj", CONTEXT); + builder.link(Arrays.asList(INFO)); + builder.result(exc.getMessage(), req.getParameter("subj"), req.getParameter("pred"), + objectParameter, req.getParameter(CONTEXT)); + builder.end(); + } + } + + private void remove(RepositoryConnection con, Resource subj, IRI pred, Value obj, WorkbenchRequest req) + throws BadRequestException, RepositoryException + { + if (req.isParameterPresent(CONTEXT)) { + Resource ctx = req.getResource(CONTEXT); + if (subj == null && pred == null && obj == null) { + con.clear(ctx); + } + else { + con.remove(subj, pred, obj, ctx); + } + } + else { + con.remove(subj, pred, obj); + } + } + + @Override + public void service(TupleResultBuilder builder, String xslPath) + throws RepositoryException, QueryResultHandlerException + { + builder.transform(xslPath, "remove.xsl"); + builder.start(); + builder.link(Arrays.asList(INFO)); + builder.end(); + } + +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/RepositoriesServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/RepositoriesServlet.java new file mode 100644 index 00000000000..b7a42f77b4a --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/RepositoriesServlet.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.util.Arrays; + +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.manager.RepositoryInfo; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; + +public class RepositoriesServlet extends TransformationServlet { + + @Override + public void service(TupleResultBuilder builder, String xslPath) + throws RepositoryException, QueryResultHandlerException + { + builder.transform(xslPath, "repositories.xsl"); + builder.start("readable", "writeable", "id", "description", "location"); + builder.link(Arrays.asList(INFO)); + for (RepositoryInfo info : manager.getAllRepositoryInfos()) { + builder.result(info.isReadable(), info.isWritable(), info.getId(), info.getDescription(), + info.getLocation().toString()); + } + builder.end(); + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/SavedQueriesServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/SavedQueriesServlet.java new file mode 100644 index 00000000000..98685fe0a39 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/SavedQueriesServlet.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.io.IOException; +import java.util.Arrays; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.QueryStorage; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; + +/** + * Servlet that provides a page to access saved queries. + * + * @author Dale Visser + */ +public class SavedQueriesServlet extends TransformationServlet { + + private QueryStorage storage; + + @Override + public String[] getCookieNames() { + return new String[] { QueryServlet.LIMIT, "queryLn", "infer", "total_result_count" }; + } + + @Override + public void init(final ServletConfig config) + throws ServletException + { + super.init(config); + try { + this.storage = QueryStorage.getSingletonInstance(this.appConfig); + } + catch (RepositoryException e) { + throw new ServletException(e); + } + catch (IOException e) { + throw new ServletException(e); + } + } + + @Override + protected void service(final WorkbenchRequest req, final HttpServletResponse resp, final String xslPath) + throws IOException, OpenRDFException, BadRequestException + { + final TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(xslPath, "saved-queries.xsl"); + builder.start(); + builder.link(Arrays.asList(INFO)); + this.getSavedQueries(req, builder); + builder.end(); + } + + @Override + protected void doPost(final WorkbenchRequest wreq, final HttpServletResponse resp, final String xslPath) + throws BadRequestException, IOException, OpenRDFException + { + final String urn = wreq.getParameter("delete"); + if (null == urn || urn.isEmpty()) { + throw new BadRequestException("Expected POST to contain a 'delete=' parameter."); + } + final boolean accessible = storage.checkAccess((HTTPRepository)this.repository); + if (accessible) { + String userName = wreq.getParameter(SERVER_USER); + if (null == userName) { + userName = ""; + } + final IRI queryURI = SimpleValueFactory.getInstance().createIRI(urn); + if (storage.canChange(queryURI, userName)) { + storage.deleteQuery(queryURI, userName); + } + else { + throw new BadRequestException("User '" + userName + "' may not delete query id " + urn); + } + } + this.service(wreq, resp, xslPath); + } + + private void getSavedQueries(final WorkbenchRequest req, final TupleResultBuilder builder) + throws OpenRDFException, BadRequestException + { + final HTTPRepository repo = (HTTPRepository)this.repository; + String user = req.getParameter(SERVER_USER); + if (null == user) { + user = ""; + } + if (!storage.checkAccess(repo)) { + throw new BadRequestException( + "User '" + user + "' not authorized to access repository '" + repo.getRepositoryURL() + "'"); + } + storage.selectSavedQueries(repo, user, builder); + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/SummaryServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/SummaryServlet.java new file mode 100644 index 00000000000..c8954241d11 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/SummaryServlet.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.manager.LocalRepositoryManager; +import org.eclipse.rdf4j.repository.manager.RemoteRepositoryManager; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SummaryServlet extends TransformationServlet { + + private final ExecutorService executorService = Executors.newCachedThreadPool(); + + private static final Logger LOGGER = LoggerFactory.getLogger(SummaryServlet.class); + + @Override + public void service(TupleResultBuilder builder, String xslPath) + throws RepositoryException, QueryEvaluationException, MalformedQueryException, + QueryResultHandlerException + { + builder.transform(xslPath, "summary.xsl"); + builder.start("id", "description", "location", "server", "size", "contexts"); + builder.link(Arrays.asList(INFO)); + final RepositoryConnection con = repository.getConnection(); + try { + String size = null; + String numContexts = null; + try { + List> futures = getRepositoryStatistics(con); + size = getResult("repository size.", futures.get(0)); + numContexts = getResult("labeled contexts.", futures.get(1)); + } + catch (InterruptedException e) { + LOGGER.warn("Interrupted while requesting repository statistics.", e); + } + builder.result(info.getId(), info.getDescription(), info.getLocation(), getServer(), size, + numContexts); + builder.end(); + } + finally { + con.close(); + } + } + + private String getResult(String itemRequested, Future future) { + String result = "Unexpected interruption while requesting " + itemRequested; + try { + if (future.isCancelled()) { + result = "Timed out while requesting " + itemRequested; + } + else { + try { + result = future.get(); + } + catch (ExecutionException e) { + LOGGER.warn("Exception occured during async request.", e); + result = "Exception occured while requesting " + itemRequested; + } + } + } + catch (InterruptedException e) { + LOGGER.error("Unexpected exception", e); + } + return result; + } + + @SuppressWarnings("unchecked") + private List> getRepositoryStatistics(final RepositoryConnection con) + throws InterruptedException + { + List> futures; + futures = executorService.invokeAll(Arrays.asList(new Callable() { + + @Override + public String call() + throws RepositoryException + { + return Long.toString(con.size()); + } + + }, new Callable() { + + @Override + public String call() + throws RepositoryException + { + return Integer.toString(Iterations.asList(con.getContextIDs()).size()); + } + + }), 2000, TimeUnit.MILLISECONDS); + return futures; + } + + private String getServer() { + String result = null; // gracefully ignored by builder.result(...) + if (manager instanceof LocalRepositoryManager) { + result = ((LocalRepositoryManager)manager).getBaseDir().toString(); + } + else if (manager instanceof RemoteRepositoryManager) { + result = ((RemoteRepositoryManager)manager).getServerURL(); + } + return result; + } +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/TypesServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/TypesServlet.java new file mode 100644 index 00000000000..fb952fe840b --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/TypesServlet.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import static org.eclipse.rdf4j.query.QueryLanguage.SPARQL; + +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.workbench.base.TupleServlet; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; + +public class TypesServlet extends TupleServlet { + + public TypesServlet() { + super("types.xsl", "type"); + } + + private static final String DISTINCT_TYPE = "SELECT DISTINCT ?type WHERE { ?subj a ?type }"; + + @Override + protected void service(TupleResultBuilder builder, RepositoryConnection con) + throws Exception { + TupleQuery query = con.prepareTupleQuery(SPARQL, DISTINCT_TYPE); + TupleQueryResult result = query.evaluate(); + try { + while (result.hasNext()) { + builder.result(result.next().getValue("type")); + } + } finally { + result.close(); + } + } + +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/UpdateServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/UpdateServlet.java new file mode 100644 index 00000000000..956affa157b --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/commands/UpdateServlet.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import java.io.IOException; +import java.util.Arrays; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.Update; +import org.eclipse.rdf4j.query.UpdateExecutionException; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UpdateServlet extends TransformationServlet { + + private final Logger logger = LoggerFactory.getLogger(UpdateServlet.class); + + @Override + public String[] getCookieNames() { + return new String[] { "Content-Type" }; + } + + @Override + protected void doPost(WorkbenchRequest req, HttpServletResponse resp, String xslPath) + throws Exception, IOException + { + // All POST requests are expected to contain a SPARQL/Update 'update' parameter. + try { + String updateString = req.getParameter("update"); + executeUpdate(updateString); + resp.sendRedirect("summary"); + } + catch (BadRequestException exc) { + logger.warn(exc.toString(), exc); + TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(xslPath, "update.xsl"); + builder.start("error-message", "update"); + builder.link(Arrays.asList(INFO, "namespaces")); + + String updateString = req.getParameter("update"); + builder.result(exc.getMessage(), updateString); + builder.end(); + } + } + + private void executeUpdate(String updateString) + throws Exception + { + RepositoryConnection con = repository.getConnection(); + Update update; + try { + update = con.prepareUpdate(QueryLanguage.SPARQL, updateString); + update.execute(); + } + catch (RepositoryException e) { + throw new BadRequestException(e.getMessage()); + } + catch (MalformedQueryException e) { + throw new BadRequestException(e.getMessage()); + } + catch (UpdateExecutionException e) { + throw new BadRequestException(e.getMessage()); + } + finally { + con.close(); + } + } + + @Override + public void service(TupleResultBuilder builder, String xslPath) + throws RepositoryException, QueryResultHandlerException + { + // All GET requests are assumed to be to present the update editor page. + builder.transform(xslPath, "update.xsl"); + builder.start(); + builder.link(Arrays.asList(INFO, "namespaces")); + builder.end(); + } + +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/exceptions/BadRequestException.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/exceptions/BadRequestException.java new file mode 100644 index 00000000000..0624b3d050d --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/exceptions/BadRequestException.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.exceptions; + +import javax.servlet.ServletException; + +public class BadRequestException extends ServletException { + private static final long serialVersionUID = -6227037493079059474L; + + public BadRequestException(String message) { + super(message); + } + + public BadRequestException(String message, Throwable rootCause) { + super(message, rootCause); + } +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/exceptions/MissingInitParameterException.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/exceptions/MissingInitParameterException.java new file mode 100644 index 00000000000..3a0156c26f5 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/exceptions/MissingInitParameterException.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.exceptions; + +import javax.servlet.ServletException; + +public class MissingInitParameterException extends ServletException { + private static final long serialVersionUID = 8543657273860596921L; + + public MissingInitParameterException(String parameter) { + super("Missing parameter: " + parameter); + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CacheFilter.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CacheFilter.java new file mode 100644 index 00000000000..f8deaf65ac6 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CacheFilter.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.proxy; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Resource cache expiry filter for Tomcat 6, based on code authored by Saket + * Kumar. + * + * @see Enable Caching in Tomcat 6 + * @author Dale Visser + */ +public class CacheFilter implements Filter { + + private static final Logger LOGGER = LoggerFactory.getLogger(CacheFilter.class); + + /** + * HTTP header key for controlling caching of resources. + */ + private final static String CACHE_CONTROL = "Cache-Control"; + + /** + * Maximum allowed expiry lifetime in seconds, set to one year according to + * the advice in RFC 2616. + * + * @see RFC 2616: HTTP/1.1 + */ + public final static long MAX_EXPIRY = (365 * 24 + 6) * 60 * 60; + + /** + * Minimum allowed expiry lifetime, zero, which corresponds to not caching at + * all. + */ + public final static long MIN_EXPIRY = 0; + + private Long expiry = null; + + /** + * Set a maximum expiry Cache-Control header applicable to the client and to + * intermediate caching servers. + */ + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) + throws IOException, ServletException + { + if (null != expiry) { + ((HttpServletResponse)res).setHeader(CACHE_CONTROL, "max-age=" + expiry + ", public"); + } + chain.doFilter(req, res); + } + + /** + * Parse the Cache-Control configuration parameter as a long integer, and set + * the filter expiry value, modulo the minimum and maximum expiry + * constraints. If the configuration parameter is not present, or not a valid + * long integer value, then no Cache-Control headers will be applied by the + * filter. + * + * @see #MIN_EXPIRY + * @see #MAX_EXPIRY + */ + @Override + public void init(FilterConfig config) + throws ServletException + { + try { + expiry = Math.min(Math.max(MIN_EXPIRY, Long.parseLong(config.getInitParameter(CACHE_CONTROL))), + MAX_EXPIRY); + } + catch (NumberFormatException nfe) { + LOGGER.warn("Failed to parse " + CACHE_CONTROL + " value.", nfe); + expiry = null; + } + } + + /** + * Make stored references available for garbage collection. + */ + @Override + public void destroy() { + expiry = null; + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CookieCacheControlFilter.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CookieCacheControlFilter.java new file mode 100644 index 00000000000..068bbea26e3 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CookieCacheControlFilter.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.proxy; + +import static java.lang.System.currentTimeMillis; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +/** + * Browsers do not expire cache if Cookies have changed. Even if "Vary: Cookie" + * header is set. This filter intercepts the Last-Modified and If-Modified-Since + * headers to include modification of browser cookies. + * + * @author James Leigh + */ +public class CookieCacheControlFilter implements Filter { + + private static final String LAST_MODIFIED_COOKIE = "Last-Modified"; + + private static final String HEADER_IFMODSINCE = "If-Modified-Since"; + + private static final String HEADER_LASTMOD = "Last-Modified"; + + public void init(FilterConfig config) + throws ServletException + { + } + + public void destroy() { + } + + public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) + throws IOException, ServletException + { + CacheAwareRequest request = new CacheAwareRequest(req); + CacheAwareResponse response = new CacheAwareResponse(req, resp); + chain.doFilter(request, response); + } + + private class CacheAwareRequest extends HttpServletRequestWrapper { + + public CacheAwareRequest(ServletRequest request) { + this((HttpServletRequest)request); + } + + public CacheAwareRequest(HttpServletRequest request) { + super(request); + } + + /** + * This method hides the If-Modified-Since header if the browser's cookies + * have changed since this page was cached. + */ + @Override + public long getDateHeader(String name) { + long value = super.getDateHeader(name); + if (HEADER_IFMODSINCE.equals(name)) { + Cookie[] cookies = getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (LAST_MODIFIED_COOKIE.equals(cookie.getName())) { + long lastModified = Long.parseLong(cookie.getValue()); + if (lastModified > value) { + // cookies have changed since this cache + return -1; + } + } + } + } + } + return value; + } + + } + + private class CacheAwareResponse extends HttpServletResponseWrapper { + + private HttpServletRequest req; + + private boolean controlCookieAdded; + + public CacheAwareResponse(ServletRequest req, ServletResponse response) { + this((HttpServletRequest)req, (HttpServletResponse)response); + } + + public CacheAwareResponse(HttpServletRequest req, HttpServletResponse response) { + super(response); + this.req = req; + } + + /** + * This method tells the browser to track the last time the cookies + * changed. + */ + @Override + public void addCookie(Cookie c) { + boolean changed = true; + Cookie existing = getCookie(c.getName()); + if (existing != null) { + changed = !c.getValue().equals(existing.getValue()); + } + super.addCookie(c); + if (!controlCookieAdded && changed) { + long date = currentTimeMillis() / 1000 * 1000; + String value = String.valueOf(date); + Cookie cookie = new Cookie(LAST_MODIFIED_COOKIE, value); + String contextPath = req.getContextPath(); + if (contextPath == null) { + cookie.setPath("/"); + } + else { + cookie.setPath(contextPath); + } + super.addCookie(cookie); + super.setDateHeader(HEADER_LASTMOD, date); + } + } + + /** + * The Last-Modified will include the last time the cookies changed for + * this browser. + */ + @Override + public void setDateHeader(String name, long date) { + if (HEADER_LASTMOD.equals(name)) { + Cookie cookie = getCookie(LAST_MODIFIED_COOKIE); + if (cookie != null) { + long lastModified = Long.parseLong(cookie.getValue()); + if (lastModified > date) { + // cookies have changed since, use that instead + super.setDateHeader(name, lastModified); + return; + } + } + } + super.setDateHeader(name, date); + } + + private Cookie getCookie(String name) { + Cookie[] cookies = req.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (name.equals(cookie.getName())) { + return cookie; + } + } + } + return null; + } + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CookieHandler.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CookieHandler.java new file mode 100644 index 00000000000..a2b20d07e41 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/CookieHandler.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.proxy; + +import javax.servlet.ServletConfig; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Handles cookies for proxy servlets. + */ +public class CookieHandler { + protected static final String COOKIE_AGE_PARAM = "cookie-max-age"; + + private final String maxAge; + + protected CookieHandler(final String maxAge) { + this.maxAge = maxAge; + } + + protected CookieHandler(final ServletConfig config) { + this(config.getInitParameter(COOKIE_AGE_PARAM)); + } + + protected String getCookieNullIfEmpty(final HttpServletRequest req, + final HttpServletResponse resp, final String name){ + String value = this.getCookie(req, resp, name); + if (null !=value && value.isEmpty()){ + value = null; + } + return value; + } + + protected String getCookie(final HttpServletRequest req, + final HttpServletResponse resp, final String name) { + String value = null; + final Cookie[] cookies = req.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (name.equals(cookie.getName())) { + resp.addHeader("Vary", "Cookie"); + initCookie(cookie, req); + resp.addCookie(cookie); + value = cookie.getValue(); + break; + } + } + } + return value; + } + + private void initCookie(final Cookie cookie, + final HttpServletRequest req) { + final String context = req.getContextPath(); + cookie.setPath(null == context ? "/" : context); + if (maxAge != null) { + cookie.setMaxAge(Integer.parseInt(maxAge)); + } + } + + /** + * @param req servlet request + * @param resp servlet response + * @param name cookie name + * @param value cookie value + */ + protected void addNewCookie(final HttpServletRequest req, final HttpServletResponse resp, final String name, final String value) + { + final Cookie cookie = new Cookie(name, value); + initCookie(cookie, req); + resp.addCookie(cookie); + } + + /** + * @return the maximum age allowed for cookies + */ + public String getMaxAge() { + return maxAge; + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/ProxyRepositoryServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/ProxyRepositoryServlet.java new file mode 100644 index 00000000000..1d8ceb72fa2 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/ProxyRepositoryServlet.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.proxy; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.workbench.RepositoryServlet; +import org.eclipse.rdf4j.workbench.base.AbstractRepositoryServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.exceptions.MissingInitParameterException; +import org.eclipse.rdf4j.workbench.util.BasicServletConfig; +import org.eclipse.rdf4j.workbench.util.DynamicHttpRequest; + +public class ProxyRepositoryServlet extends AbstractRepositoryServlet { + private static final String HEADER_IFMODSINCE = "If-Modified-Since"; + private static final String HEADER_LASTMOD = "Last-Modified"; + private static final String DEFAULT_PATH_PARAM = "default-command"; + private Map servlets = new HashMap(); + private long lastModified; + + @Override + @SuppressWarnings("unchecked") + public void init(ServletConfig config) throws ServletException { + super.init(config); + lastModified = System.currentTimeMillis(); + if (config.getInitParameter(DEFAULT_PATH_PARAM) == null) + throw new MissingInitParameterException(DEFAULT_PATH_PARAM); + Enumeration names = config.getInitParameterNames(); + while (names.hasMoreElements()) { + String path = names.nextElement(); + if (path.startsWith("/")) { + try { + servlets.put(path, createServlet(path)); + } catch (InstantiationException e) { + throw new ServletException(e); + } catch (IllegalAccessException e) { + throw new ServletException(e); + } catch (ClassNotFoundException e) { + throw new ServletException(e); + } + } + } + } + + @Override + public void destroy() { + for (RepositoryServlet servlet : servlets.values()) { + servlet.destroy(); + } + } + + public void resetCache() { + lastModified = System.currentTimeMillis(); + } + + @Override + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + if (isCachable(req)) { + long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); + if (ifModifiedSince < lastModified) { + resp.setDateHeader(HEADER_LASTMOD, lastModified); + } else { + resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + return; + } + } + String pathInfo = req.getPathInfo(); + if (pathInfo == null) { + String defaultPath = config.getInitParameter(DEFAULT_PATH_PARAM); + resp.sendRedirect(req.getRequestURI() + defaultPath); + } else if ("/".equals(pathInfo)) { + String defaultPath = config.getInitParameter(DEFAULT_PATH_PARAM); + resp.sendRedirect(req.getRequestURI() + defaultPath.substring(1)); + } else { + RepositoryServlet servlet = servlets.get(pathInfo); + if (servlet == null) + throw new BadRequestException("Unconfigured path: " + pathInfo); + DynamicHttpRequest hreq = new DynamicHttpRequest(req); + hreq.setServletPath(hreq.getServletPath() + hreq.getPathInfo()); + hreq.setPathInfo(null); + servlet.service(hreq, resp); + } + if ("POST".equals(req.getMethod())) { + lastModified = System.currentTimeMillis(); + } else if (lastModified % 1000 != 0) { + long modified = System.currentTimeMillis() / 1000 * 1000; + if (lastModified < modified) { + lastModified = modified; + } + } + } + + private boolean isCachable(HttpServletRequest req) { + if (!"GET".equals(req.getMethod())) + return false; + // MSIE does not cache different url parameters separately + return req.getRequestURL().toString().indexOf(';') < 0; + } + + private RepositoryServlet createServlet(String path) + throws ClassNotFoundException, InstantiationException, + IllegalAccessException, ServletException { + Class klass = Class.forName(config.getInitParameter(path)); + RepositoryServlet servlet = (RepositoryServlet) klass.newInstance(); + servlet.setRepositoryManager(manager); + servlet.setRepositoryInfo(info); + servlet.setRepository(repository); + servlet.init(new BasicServletConfig(path, config)); + return servlet; + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/RedirectFilter.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/RedirectFilter.java new file mode 100644 index 00000000000..a85dc989fc5 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/RedirectFilter.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.proxy; + +import java.io.IOException; +import java.util.Enumeration; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class RedirectFilter implements Filter { + private FilterConfig config; + + public void init(FilterConfig config) throws ServletException { + this.config = config; + } + + public void destroy() { + } + + @SuppressWarnings("unchecked") + public void doFilter(ServletRequest req, ServletResponse resp, + FilterChain chain) throws IOException, ServletException { + HttpServletRequest hreq = (HttpServletRequest) req; + HttpServletResponse hresp = (HttpServletResponse) resp; + Enumeration names = config.getInitParameterNames(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + String pathInfo = hreq.getPathInfo(); + String servletPath = hreq.getServletPath(); + if (pathInfo == null && name.equals(servletPath) + || name.equals(pathInfo)) { + if (hreq.getContextPath() != null) { + hresp.sendRedirect(hreq.getContextPath() + + config.getInitParameter(name)); + return; + } else { + hresp.sendRedirect(config.getInitParameter(name)); + return; + } + } + } + chain.doFilter(req, resp); + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/ServerValidator.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/ServerValidator.java new file mode 100644 index 00000000000..825f1c9f737 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/ServerValidator.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.proxy; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; + +import javax.servlet.ServletConfig; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Validates a server + */ +class ServerValidator { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServerValidator.class); + private static final String ACCEPTED_SERVER = "accepted-server-prefixes"; + private final String prefixes; + + protected ServerValidator(final ServletConfig config) { + this.prefixes = config.getInitParameter(ACCEPTED_SERVER); + } + + private boolean isDirectory(final String server) { + boolean isDir = false; + try { + final URL url = new URL(server); + isDir = asLocalFile(url).isDirectory(); + } + catch (MalformedURLException e) { + LOGGER.warn(e.toString(), e); + } + catch (IOException e) { + LOGGER.warn(e.toString(), e); + } + return isDir; + } + + /** + * Returns whether the given server can be connected to. + * + * @param server + * the server path + * @param password + * the optional password + * @param user + * the optional username + * @return true, if the given server can be connected to + */ + protected boolean isValidServer(final String server) { + boolean isValid = checkServerPrefixes(server); + if (isValid) { + if (server.startsWith("http")) { + isValid = canConnect(server); + } + else if (server.startsWith("file:")) { + isValid = isDirectory(server); + } + } + return isValid; + } + + /** + * Returns whether the server prefix is in the list of acceptable prefixes, + * as given by the space-separated configuration parameter value for + * 'accepted-server-prefixes'. + * + * @param server + * the server for which to check the prefix + * @return whether the server prefix is in the list of acceptable prefixes + */ + private boolean checkServerPrefixes(final String server) { + boolean accept = false; + if (prefixes == null) { + accept = true; + } + else { + for (String prefix : prefixes.split(" ")) { + if (server.startsWith(prefix)) { + accept = true; + break; + } + } + } + if (!accept) { + LOGGER.warn("server URL {} does not have a prefix {}", server, prefixes); + } + return accept; + } + + /** + * Assumption: server won't require credentials to access the + * protocol path. + */ + private boolean canConnect(final String server) { + boolean success = false; + try { + final URL url = new URL(server + "/protocol"); + final BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); + try { + Integer.parseInt(reader.readLine()); + success = true; + } + finally { + reader.close(); + } + } + catch (MalformedURLException e) { + LOGGER.warn(e.toString(), e); + } + catch (IOException e) { + LOGGER.warn(e.toString(), e); + } + return success; + } + + private File asLocalFile(final URL rdf) + throws UnsupportedEncodingException + { + return new File(URLDecoder.decode(rdf.getFile(), "UTF-8")); + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/WorkbenchGateway.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/WorkbenchGateway.java new file mode 100644 index 00000000000..9919607837f --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/WorkbenchGateway.java @@ -0,0 +1,311 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.proxy; + +import static org.eclipse.rdf4j.workbench.proxy.WorkbenchServlet.SERVER_PARAM; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.workbench.base.AbstractServlet; +import org.eclipse.rdf4j.workbench.exceptions.MissingInitParameterException; +import org.eclipse.rdf4j.workbench.util.BasicServletConfig; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; + +/** + * All requests are serviced by this Servlet, though it usually delegates to + * other Servlets. + */ +public class WorkbenchGateway extends AbstractServlet { + + private static final String DEFAULT_SERVER = "default-server"; + + private static final String CHANGE_SERVER = "change-server-path"; + + private static final String SERVER_COOKIE = "workbench-server"; + + protected static final String TRANSFORMATIONS = "transformations"; + + /** + * Thread-safe map of server paths to their WorkbenchServlet instances. + */ + private final Map servlets = new ConcurrentHashMap(); + + private CookieHandler cookies; + + private ServerValidator serverValidator; + + @Override + public void init(final ServletConfig config) + throws ServletException + { + super.init(config); + if (getDefaultServerPath() == null) { + throw new MissingInitParameterException(DEFAULT_SERVER); + } + if (config.getInitParameter(TRANSFORMATIONS) == null) { + throw new MissingInitParameterException(TRANSFORMATIONS); + } + this.cookies = new CookieHandler(config); + this.serverValidator = new ServerValidator(config); + } + + @Override + public void destroy() { + for (WorkbenchServlet servlet : servlets.values()) { + servlet.destroy(); + } + } + + public String getChangeServerPath() { + return config.getInitParameter(CHANGE_SERVER); + } + + /** + * Returns the value of the default-server configuration variable. Often, + * this is simply a relative path on the same HTTP server. + * + * @return the path to the default Sesame server instance + */ + public String getDefaultServerPath() { + return config.getInitParameter(DEFAULT_SERVER); + } + + /** + * Whether the server path is fixed, which is when the change-server-path + * configuration value is not set. + * + * @return true, if the change-server-path configuration variable is not set, + * meaning that changing the server is blocked + */ + public boolean isServerFixed() { + return getChangeServerPath() == null; + } + + @Override + public void service(final HttpServletRequest req, final HttpServletResponse resp) + throws ServletException, IOException + { + final String change = getChangeServerPath(); + if (change != null && change.equals(req.getPathInfo())) { + try { + changeServer(req, resp); + } + catch (QueryResultHandlerException e) { + throw new IOException(e); + } + } + else { + final WorkbenchServlet servlet = findWorkbenchServlet(req, resp); + if (servlet == null) { + // Redirect to change-server-path + final StringBuilder uri = new StringBuilder(req.getRequestURI()); + if (req.getPathInfo() != null) { + uri.setLength(uri.length() - req.getPathInfo().length()); + } + resp.sendRedirect(uri.append(getChangeServerPath()).toString()); + } + else { + servlet.service(req, resp); + } + } + } + + private void resetCache() { + for (WorkbenchServlet servlet : servlets.values()) { + // inform browser that server changed and cache is invalid + servlet.resetCache(); + } + } + + /** + * Handles requests to the "change server" page. + * + * @param req + * the servlet request object + * @param resp + * the servlet response object + * @throws IOException + * if an issue occurs writing to the response + * @throws QueryResultHandlerException + */ + private void changeServer(final HttpServletRequest req, final HttpServletResponse resp) + throws IOException, QueryResultHandlerException + { + final String server = req.getParameter(SERVER_COOKIE); + if (server == null) { + // Server parameter was not present, so present entry form. + final TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(getTransformationUrl(req), "server.xsl"); + builder.start(); + builder.end(); + } + else if (this.serverValidator.isValidServer(server)) { + // Valid server was submitted by form. Set cookie and redirect to + // repository selection page. + this.cookies.addNewCookie(req, resp, SERVER_COOKIE, server); + final String user = getOptionalParameter(req, SERVER_USER); + this.cookies.addNewCookie(req, resp, SERVER_USER, user); + final String password = getOptionalParameter(req, SERVER_PASSWORD); + this.cookies.addNewCookie(req, resp, SERVER_PASSWORD, password); + final StringBuilder uri = new StringBuilder(req.getRequestURI()); + uri.setLength(uri.length() - req.getPathInfo().length()); + resetCache(); + resp.sendRedirect(uri.toString()); + } + else { + // Invalid server was submitted by form. Present entry form again + // with error message. + final TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(getTransformationUrl(req), "server.xsl"); + builder.start("error-message"); + builder.result("Invalid Server URL"); + builder.end(); + } + } + + /** + * @param req + * the servlet request + * @param name + * the name of the optional parameter + * @return the value of the parameter, or an empty String if it is not + * present. + */ + private String getOptionalParameter(final HttpServletRequest req, final String name) { + String value = req.getParameter(name); + if (value == null) { + value = ""; + } + return value; + } + + /** + * Returns the user requested server, if valid, or the default server. + * + * @param req + * the request + * @param resp + * the response + * @return the user's requested server, if valid, or the default server + */ + private String findServer(final HttpServletRequest req, final HttpServletResponse resp) { + final StringBuilder value = new StringBuilder(); + if (isServerFixed()) { + value.append(getDefaultServer(req)); + } + else { + value.append(cookies.getCookie(req, resp, SERVER_COOKIE)); + if (0 == value.length()) { + value.append(getDefaultServer(req)); + } + else if (!this.serverValidator.isValidServer(value.toString())) { + value.replace(0, value.length(), getDefaultServer(req)); + } + } + return value.toString(); + } + + /** + * Returns a WorkbenchServlet instance allocated for the requested server. + * + * @param req + * the current request + * @param resp + * the current response + * @return a WorkbenchServlet instance allocated for the requested server + * @throws ServletException + * if a problem occurs initializing a new servlet + */ + private WorkbenchServlet findWorkbenchServlet(final HttpServletRequest req, final HttpServletResponse resp) + throws ServletException + { + WorkbenchServlet servlet = null; + final String server = findServer(req, resp); + if (servlets.containsKey(server)) { + servlet = servlets.get(server); + } + else { + if (isServerFixed() || this.serverValidator.isValidServer(server)) { + synchronized (servlets) { + // Even though the map is thread-safe, we only wish one + // thread to be in this block at a time, to avoid abandoning + // a WorkbenchServlet instance to the garbage collector. + if (servlets.containsKey(server)) { + servlet = servlets.get(server); + } + else { + final Map params = new HashMap(3); + params.put(SERVER_PARAM, server); + params.put(CookieHandler.COOKIE_AGE_PARAM, this.cookies.getMaxAge()); + params.put(TRANSFORMATIONS, this.config.getInitParameter(TRANSFORMATIONS)); + final ServletConfig cfg = new BasicServletConfig(server, config, params); + servlet = new WorkbenchServlet(); + servlet.init(cfg); + servlets.put(server, servlet); + } + } + } + } + return servlet; + } + + /** + * Returns the full URL to the default server on the same server as the given + * request. + * + * @param req + * the request to find the default server relative to + * @return the full URL to the default server on the same server as the given + * request + */ + private String getDefaultServer(final HttpServletRequest req) { + String server = getDefaultServerPath(); + if ('/' == server.charAt(0)) { + final StringBuffer url = req.getRequestURL(); + final StringBuilder path = getServerPath(req); + url.setLength(url.indexOf(path.toString())); + server = url.append(server).toString(); + } + return server; + } + + /** + * Returns the full path for the given request. + * + * @param req + * the request for which the path is sought + * @return the full path for the given request + */ + private StringBuilder getServerPath(final HttpServletRequest req) { + final StringBuilder path = new StringBuilder(); + if (req.getContextPath() != null) { + path.append(req.getContextPath()); + } + if (req.getServletPath() != null) { + path.append(req.getServletPath()); + } + if (req.getPathInfo() != null) { + path.append(req.getPathInfo()); + } + return path; + } + + private String getTransformationUrl(final HttpServletRequest req) { + final String contextPath = req.getContextPath(); + return contextPath + config.getInitParameter(TRANSFORMATIONS); + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/WorkbenchServlet.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/WorkbenchServlet.java new file mode 100644 index 00000000000..b2104747f39 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/proxy/WorkbenchServlet.java @@ -0,0 +1,265 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.proxy; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.http.protocol.UnauthorizedException; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.manager.LocalRepositoryManager; +import org.eclipse.rdf4j.repository.manager.RemoteRepositoryManager; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.eclipse.rdf4j.workbench.base.AbstractServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.exceptions.MissingInitParameterException; +import org.eclipse.rdf4j.workbench.util.BasicServletConfig; +import org.eclipse.rdf4j.workbench.util.DynamicHttpRequest; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WorkbenchServlet extends AbstractServlet { + + private static final Logger LOGGER = LoggerFactory.getLogger(WorkbenchServlet.class); + + private static final String DEFAULT_PATH = "default-path"; + + private static final String NO_REPOSITORY = "no-repository-id"; + + public static final String SERVER_PARAM = "server"; + + private RepositoryManager manager; + + private final ConcurrentMap repositories = new ConcurrentHashMap(); + + @Override + public void init(final ServletConfig config) + throws ServletException + { + this.config = config; + if (config.getInitParameter(DEFAULT_PATH) == null) { + throw new MissingInitParameterException(DEFAULT_PATH); + } + final String param = config.getInitParameter(SERVER_PARAM); + if (param == null || param.trim().isEmpty()) { + throw new MissingInitParameterException(SERVER_PARAM); + } + try { + manager = createRepositoryManager(param); + } + catch (IOException e) { + throw new ServletException(e); + } + catch (RepositoryException e) { + throw new ServletException(e); + } + } + + @Override + public void destroy() { + for (Servlet servlet : repositories.values()) { + servlet.destroy(); + } + manager.shutDown(); + } + + public void resetCache() { + for (ProxyRepositoryServlet proxy : repositories.values()) { + // inform browser that server changed and cache is invalid + proxy.resetCache(); + } + } + + @Override + public void service(final HttpServletRequest req, final HttpServletResponse resp) + throws ServletException, IOException + { + final String pathInfo = req.getPathInfo(); + if (pathInfo == null) { + final String defaultPath = config.getInitParameter(DEFAULT_PATH); + resp.sendRedirect(req.getRequestURI() + defaultPath); + } + else if ("/".equals(pathInfo)) { + final String defaultPath = config.getInitParameter(DEFAULT_PATH); + resp.sendRedirect(req.getRequestURI() + defaultPath.substring(1)); + } + else if ('/' == pathInfo.charAt(0)) { + try { + handleRequest(req, resp, pathInfo); + } + catch (QueryResultHandlerException e) { + throw new IOException(e); + } + } + else { + throw new BadRequestException("Request path must contain a repository ID"); + } + } + + /** + * @param req + * the servlet request + * @param resp + * the servlet response + * @param pathInfo + * the path info from the request + * @throws IOException + * @throws ServletException + * @throws QueryResultHandlerException + */ + private void handleRequest(final HttpServletRequest req, final HttpServletResponse resp, + final String pathInfo) + throws IOException, ServletException, QueryResultHandlerException + { + int idx = pathInfo.indexOf('/', 1); + if (idx < 0) { + idx = pathInfo.length(); + } + final String repoID = pathInfo.substring(1, idx); + try { + service(repoID, req, resp); + } + catch (RepositoryConfigException e) { + throw new ServletException(e); + } + catch (UnauthorizedException e) { + handleUnauthorizedException(req, resp); + } + catch (ServletException e) { + if (e.getCause() instanceof UnauthorizedException) { + handleUnauthorizedException(req, resp); + } + else { + throw e; + } + } + catch (RepositoryException e) { + throw new ServletException(e); + } + } + + /** + * @param req + * @param resp + * @throws IOException + * @throws QueryResultHandlerException + */ + private void handleUnauthorizedException(final HttpServletRequest req, final HttpServletResponse resp) + throws IOException, QueryResultHandlerException + { + // Invalid credentials or insufficient authorization. Present + // entry form again with error message. + final TupleResultBuilder builder = getTupleResultBuilder(req, resp, resp.getOutputStream()); + builder.transform(this.getTransformationUrl(req), "server.xsl"); + builder.start("error-message"); + builder.result("The entered credentials entered either failed to authenticate to the Sesame server, or were unauthorized for the requested operation."); + builder.end(); + } + + private RepositoryManager createRepositoryManager(final String param) + throws IOException, RepositoryException + { + RepositoryManager manager; + if (param.startsWith("file:")) { + manager = new LocalRepositoryManager(asLocalFile(new URL(param))); + } + else { + manager = new RemoteRepositoryManager(param); + } + manager.initialize(); + return manager; + } + + private File asLocalFile(final URL rdf) + throws UnsupportedEncodingException + { + return new File(URLDecoder.decode(rdf.getFile(), "UTF-8")); + } + + private void service(final String repoID, final HttpServletRequest req, final HttpServletResponse resp) + throws RepositoryConfigException, RepositoryException, ServletException, IOException + { + LOGGER.info("Servicing repository: {}", repoID); + setCredentials(req, resp); + final DynamicHttpRequest http = new DynamicHttpRequest(req); + final String path = req.getPathInfo(); + final int idx = path.indexOf(repoID) + repoID.length(); + http.setServletPath(http.getServletPath() + path.substring(0, idx)); + final String pathInfo = path.substring(idx); + http.setPathInfo(pathInfo.length() == 0 ? null : pathInfo); + if (repositories.containsKey(repoID)) { + repositories.get(repoID).service(http, resp); + } + else { + final Repository repository = manager.getRepository(repoID); + if (repository == null) { + final String noId = config.getInitParameter(NO_REPOSITORY); + if (noId == null || !noId.equals(repoID)) { + throw new BadRequestException("No such repository: " + repoID); + } + } + final ProxyRepositoryServlet servlet = new ProxyRepositoryServlet(); + servlet.setRepositoryManager(manager); + if (repository != null) { + servlet.setRepositoryInfo(manager.getRepositoryInfo(repoID)); + servlet.setRepository(repository); + } + servlet.init(new BasicServletConfig(repoID, config)); + repositories.putIfAbsent(repoID, servlet); + repositories.get(repoID).service(http, resp); + } + } + + private String getTransformationUrl(final HttpServletRequest req) { + final String contextPath = req.getContextPath(); + return contextPath + config.getInitParameter(WorkbenchGateway.TRANSFORMATIONS); + } + + /** + * Set the username and password for all requests to the repository. + * + * @param req + * the servlet request + * @param resp + * the servlet response + * @throws MalformedURLException + * if the repository location is malformed + */ + private void setCredentials(final HttpServletRequest req, final HttpServletResponse resp) + throws MalformedURLException, RepositoryException + { + if (manager instanceof RemoteRepositoryManager) { + final RemoteRepositoryManager rrm = (RemoteRepositoryManager)manager; + LOGGER.info("RemoteRepositoryManager URL: {}", rrm.getLocation()); + final CookieHandler cookies = new CookieHandler(config); + final String user = cookies.getCookieNullIfEmpty(req, resp, WorkbenchGateway.SERVER_USER); + final String password = cookies.getCookieNullIfEmpty(req, resp, WorkbenchGateway.SERVER_PASSWORD); + LOGGER.info("Setting user '{}' and password '{}'.", user, password); + rrm.setUsernameAndPassword(user, password); + // initialize() required to push credentials to internal HTTP + // client. + rrm.initialize(); + } + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/BasicServletConfig.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/BasicServletConfig.java new file mode 100644 index 00000000000..33784d0554d --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/BasicServletConfig.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Map; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; + +public class BasicServletConfig implements ServletConfig { + private String name; + private ServletContext context; + private Hashtable params; + + public BasicServletConfig(String name, ServletContext context) { + this.name = name; + this.context = context; + params = new Hashtable(); + } + + @SuppressWarnings("unchecked") + public BasicServletConfig(String name, ServletConfig config) { + this(name, config.getServletContext()); + Enumeration e = config.getInitParameterNames(); + while (e.hasMoreElements()) { + String param = e.nextElement(); + params.put(param, config.getInitParameter(param)); + } + } + + public BasicServletConfig(String name, ServletConfig config, + Map params) { + this(name, config); + this.params.putAll(params); + } + + public BasicServletConfig(String name, ServletContext context, + Map params) { + this.name = name; + this.context = context; + this.params = new Hashtable(params); + } + + public String getServletName() { + return name; + } + + public ServletContext getServletContext() { + return context; + } + + public Enumeration getInitParameterNames() { + return params.keys(); + } + + public String getInitParameter(String name) { + return params.get(name); + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/CookieHandler.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/CookieHandler.java new file mode 100644 index 00000000000..525e2602fd4 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/CookieHandler.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import static java.lang.Integer.parseInt; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +import javax.servlet.ServletConfig; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.workbench.base.TransformationServlet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handles cookies for TransformationServlet. + * + * @author Dale Visser + */ +public class CookieHandler { + + private static final String COOKIE_AGE_PARAM = "cookie-max-age"; + + private static final Logger LOGGER = LoggerFactory.getLogger(CookieHandler.class); + + private final ServletConfig config; + + private final TransformationServlet servlet; + + public CookieHandler(final ServletConfig config, final TransformationServlet servlet) { + this.config = config; + this.servlet = servlet; + } + + public void updateCookies(final WorkbenchRequest req, final HttpServletResponse resp) + throws UnsupportedEncodingException + { + for (String name : this.servlet.getCookieNames()) { + if (req.isParameterPresent(name)) { + addCookie(req, resp, name); + } + } + } + + private void addCookie(final WorkbenchRequest req, final HttpServletResponse resp, final String name) + throws UnsupportedEncodingException + { + final String raw = req.getParameter(name); + final String value = URLEncoder.encode(raw, "UTF-8"); + LOGGER.info("name: {}\nvalue: {}", name, value); + LOGGER.info("un-encoded value: {}\n--", raw); + final Cookie cookie = new Cookie(name, value); + if (null == req.getContextPath()) { + cookie.setPath("/"); + } + else { + cookie.setPath(req.getContextPath()); + } + cookie.setMaxAge(parseInt(config.getInitParameter(COOKIE_AGE_PARAM))); + addCookie(req, resp, cookie); + } + + private void addCookie(final WorkbenchRequest req, final HttpServletResponse resp, final Cookie cookie) { + final Cookie[] cookies = req.getCookies(); + if (cookies != null) { + for (Cookie c : cookies) { + if (cookie.getName().equals(c.getName()) && cookie.getValue().equals(c.getValue())) { + // Cookie already exists. Tell the browser we are using it. + resp.addHeader("Vary", "Cookie"); + } + } + } + resp.addCookie(cookie); + } + + /** + * Add a 'total_result_count' cookie. Used by both QueryServlet and + * ExploreServlet. + * + * @param req + * the request object + * @param resp + * the response object + * @value the value to give the cookie + */ + public void addTotalResultCountCookie(WorkbenchRequest req, HttpServletResponse resp, + int value) + { + addCookie(req, resp, "total_result_count", String.valueOf(value)); + } + + public void addCookie(WorkbenchRequest req, HttpServletResponse resp, + String name, String value){ + final Cookie cookie = new Cookie(name, value); + if (null == req.getContextPath()) { + cookie.setPath("/"); + } + else { + cookie.setPath(req.getContextPath()); + } + cookie.setMaxAge(Integer.parseInt(config.getInitParameter(COOKIE_AGE_PARAM))); + this.addCookie(req, resp, cookie); + } +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/DynamicHttpRequest.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/DynamicHttpRequest.java new file mode 100644 index 00000000000..76d8074674b --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/DynamicHttpRequest.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import java.util.Locale; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +public class DynamicHttpRequest extends HttpServletRequestWrapper { + private String contextPath; + private String method; + private String pathInfo; + private String queryString; + private String servletPath; + private Locale locale; + + public DynamicHttpRequest(ServletRequest request) { + super((HttpServletRequest) request); + contextPath = super.getContextPath(); + method = super.getMethod(); + pathInfo = super.getPathInfo(); + queryString = super.getQueryString(); + servletPath = super.getServletPath(); + locale = super.getLocale(); + } + + @Override + public String getContextPath() { + return contextPath; + } + + public void setContextPath(String contextPath) { + this.contextPath = contextPath; + } + + @Override + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + @Override + public String getPathInfo() { + return pathInfo; + } + + public void setPathInfo(String pathInfo) { + this.pathInfo = pathInfo; + } + + @Override + public String getQueryString() { + return queryString; + } + + public void setQueryString(String queryString) { + this.queryString = queryString; + } + + @Override + public String getServletPath() { + return servletPath; + } + + public void setServletPath(String servletPath) { + this.servletPath = servletPath; + } + + @Override + public Locale getLocale() { + return locale; + } + + public void setLocale(Locale locale) { + this.locale = locale; + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/PagedQuery.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/PagedQuery.java new file mode 100644 index 00000000000..720ce53094a --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/PagedQuery.java @@ -0,0 +1,250 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.rdf4j.query.QueryLanguage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dale Visser + */ +public class PagedQuery { + + private static final Logger LOGGER = LoggerFactory.getLogger(PagedQuery.class); + + private static final int FLAGS = Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL; + + private static final Pattern LIMIT_OR_OFFSET = Pattern.compile("((limit)|(offset))\\s+\\d+", FLAGS); + + private static final Pattern SPLITTER = Pattern.compile("\\s"); + + private static final Pattern OFFSET_PATTERN = Pattern.compile("\\boffset\\s+\\d+\\b", FLAGS); + + private static final Pattern LIMIT_PATTERN = Pattern.compile("\\blimit\\s+\\d+\\b", FLAGS); + + private static final Pattern SERQL_NAMESPACE = Pattern.compile("\\busing namespace\\b", FLAGS); + + private final String modifiedQuery; + + private final boolean hasLimitAndOffset; + + private int limitSubstitute, offsetSubstitute; + + /*** + *

+ * Creates an object that adds or modifies the limit and offset clauses of + * the query to be executed so that only those results to be displayed are + * requested from the query engine. + *

+ *

+ * Implementation note: The new object contains the user's query with + * appended or modified LIMIT and OFFSET clauses. + *

+ * + * @param query + * as it was specified by the user + * @param language + * SPARQL or SeRQL, as specified by the user + * @param requestLimit + * maximum number of results to return, as specified by the URL query + * parameters or cookies + * @param requestOffset + * which result to start at when populating the result set + */ + public PagedQuery(final String query, final QueryLanguage language, final int requestLimit, + final int requestOffset) + { + LOGGER.debug("Query Language: {}, requestLimit: " + requestLimit + ", requestOffset: " + requestOffset, + language); + LOGGER.debug("Query: {}", query); + + String rval = query; + + // requestLimit <= 0 actually means don't limit display + hasLimitAndOffset = requestLimit > 0; + if (hasLimitAndOffset) { + /* the matcher on the pattern will have a group for "limit l#" as + well as a group for l#, similarly for "offset o#" and o#. If + either doesn't exist, it can be appended at the end. */ + int queryLimit = -1; + int queryOffset = -1; + final Matcher matcher = LIMIT_OR_OFFSET.matcher(query); + while (matcher.find()) { + final String clause = matcher.group().toLowerCase(); + final int value = Integer.parseInt(SPLITTER.split(clause)[1]); + if (clause.startsWith("limit")) { + if (query.indexOf('}', matcher.end()) < 0) { + queryLimit = value; + } + } + else { + queryOffset = value; + } + } + + final boolean queryLimitExists = (queryLimit >= 0); + final boolean queryOffsetExists = (queryOffset >= 0); + final int maxQueryCount = getMaxQueryResultCount(queryLimit, queryOffset, queryLimitExists, + queryOffsetExists); + // gracefully handle malicious value + final int offset = (requestOffset < 0) ? 0 : requestOffset; + final int maxRequestCount = requestLimit + offset; + limitSubstitute = (maxRequestCount < maxQueryCount) ? requestLimit : queryLimit - offset; + offsetSubstitute = queryOffsetExists ? queryOffset + offset : offset; + rval = modifyLimit(language, rval, queryLimit, queryLimitExists, queryOffsetExists, limitSubstitute); + rval = modifyOffset(language, offset, rval, queryOffsetExists); + LOGGER.debug("Modified Query: {}", rval); + } + + this.modifiedQuery = rval; + } + + public boolean isPaged() { + return this.hasLimitAndOffset; + } + + public int getLimit() { + return this.limitSubstitute; + } + + public int getOffset() { + return this.offsetSubstitute; + } + + @Override + public String toString() { + return this.modifiedQuery; + } + + private static int getMaxQueryResultCount(final int queryLimit, final int queryOffset, + final boolean queryLimitExists, final boolean queryOffsetExists) + { + final int maxQueryCount = queryLimitExists ? (queryLimit + (queryOffsetExists ? queryOffset : 0)) + : Integer.MAX_VALUE; + return maxQueryCount; + } + + private String modifyOffset(final QueryLanguage language, final int offset, final String query, + final boolean queryOffsetExists) + { + String rval = query; + if (queryOffsetExists) { + if (offsetSubstitute != offset) { + // do a clause replacement + final Matcher offsetMatcher = OFFSET_PATTERN.matcher(rval); + final StringBuffer buffer = new StringBuffer(); + offsetMatcher.find(); + offsetMatcher.appendReplacement(buffer, "offset " + offsetSubstitute); + offsetMatcher.appendTail(buffer); + rval = buffer.toString(); + } + } + else { + final String newOffsetClause = "offset " + offset; + if (QueryLanguage.SPARQL == language) { + if (offset > 0) { + rval = ensureNewlineAndAppend(rval, newOffsetClause); + } + } + else { + /* SeRQL, add the clause before before the namespace + * section + */ + rval = insertAtMatchOnOwnLine(SERQL_NAMESPACE, rval, newOffsetClause); + } + } + return rval; + } + + private static String ensureNewlineAndAppend(final String original, final String append) { + final StringBuffer buffer = new StringBuffer(original.length() + append.length() + 1); + buffer.append(original); + if (buffer.charAt(buffer.length() - 1) != '\n') { + buffer.append('\n'); + } + + return buffer.append(append).toString(); + } + + private static String modifyLimit(final QueryLanguage language, final String query, final int queryLimit, + final boolean queryLimitExists, final boolean queryOffsetExists, final int limitSubstitute) + { + String rval = query; + + /* In SPARQL, LIMIT and/or OFFSET can occur at the end, in + * either order. In SeRQL, LIMIT and/or OFFSET must be + * immediately prior to the *optional* namespace declaration + * section (which is itself last), and LIMIT must precede OFFSET. + * This code makes no attempt to correct if the user places them + * out of order in the query. + */ + if (queryLimitExists) { + if (limitSubstitute != queryLimit) { + // do a clause replacement + final Matcher limitMatcher = LIMIT_PATTERN.matcher(rval); + final StringBuffer buffer = new StringBuffer(); + limitMatcher.find(); + limitMatcher.appendReplacement(buffer, "limit " + limitSubstitute); + limitMatcher.appendTail(buffer); + rval = buffer.toString(); + } + } + else { + final String newLimitClause = "limit " + limitSubstitute; + if (QueryLanguage.SPARQL == language) { + rval = ensureNewlineAndAppend(rval, newLimitClause); + } + else { + /* SeRQL, add the clause before any offset clause or the + * namespace section + */ + final Pattern pattern = queryOffsetExists ? OFFSET_PATTERN : SERQL_NAMESPACE; + rval = insertAtMatchOnOwnLine(pattern, rval, newLimitClause); + } + } + return rval; + } + + /** + * Insert a given string into another string at the point at which the given + * matcher matches, making sure to place the insertion string on its own + * line. If there is no match, appends to end on own line. + * + * @param pattern + * pattern to search for insertion location + * @param orig + * string to perform insertion on + * @param insert + * string to insert on own line + * @returns result of inserting text + */ + private static String insertAtMatchOnOwnLine(final Pattern pattern, final String orig, final String insert) + { + final Matcher matcher = pattern.matcher(orig); + final boolean found = matcher.find(); + final int location = found ? matcher.start() : orig.length(); + final StringBuilder builder = new StringBuilder(orig.length() + insert.length() + 2); + builder.append(orig.substring(0, location)); + if (builder.charAt(builder.length() - 1) != '\n') { + builder.append('\n'); + } + + builder.append(insert); + final String end = orig.substring(location); + if (!end.startsWith("\n")) { + builder.append('\n'); + } + + builder.append(end); + return builder.toString(); + } +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryEvaluator.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryEvaluator.java new file mode 100644 index 00000000000..b551aefe51a --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryEvaluator.java @@ -0,0 +1,306 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.BooleanQuery; +import org.eclipse.rdf4j.query.GraphQuery; +import org.eclipse.rdf4j.query.Query; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.RDFWriterRegistry; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; + +/** + * Evaluates queries for QueryServlet. + */ +public final class QueryEvaluator { + + private static final String INFO = "info"; + + public static final QueryEvaluator INSTANCE = new QueryEvaluator(); + + private static final String ACCEPT = "Accept"; + + private QueryEvaluator() { + // do nothing + } + + /** + * Evaluates the query submitted with the given request. + * + * @param builder + * used to build the response + * @param resp + * the response object + * @param out + * the output writer + * @param xslPath + * style sheet path + * @param con + * connection to repository + * @param queryText + * the query text, having been pulled using + * {@link org.eclipse.rdf4j.workbench.commands.QueryServlet} from one of + * three request parameters: "query", "queryhash" or "saved" + * @param req + * the request object + * @param cookies + * used to deal with browser cookies + * @throws BadRequestException + * if there's a problem getting request parameters or issuing the + * repository query + * @throws OpenRDFException + * if there's a problem preparing the query + */ + public void extractQueryAndEvaluate(final TupleResultBuilder builder, final HttpServletResponse resp, + final OutputStream out, final String xslPath, final RepositoryConnection con, String queryText, + final WorkbenchRequest req, final CookieHandler cookies) + throws BadRequestException, OpenRDFException + { + final QueryLanguage queryLn = QueryLanguage.valueOf(req.getParameter("queryLn")); + Query query = QueryFactory.prepareQuery(con, queryLn, queryText); + boolean evaluateCookie = false; + int offset = req.getInt("offset"); + int limit = req.getInt("limit_query"); + boolean paged = limit > 0; + if (query instanceof GraphQuery || query instanceof TupleQuery) { + final int know_total = req.getInt("know_total"); + evaluateCookie = know_total <= 0; + if (!evaluateCookie) { + cookies.addTotalResultCountCookie(req, resp, know_total); + } + if (paged) { + PagedQuery pagedQuery = new PagedQuery(queryText, queryLn, limit, offset); + if (pagedQuery.isPaged()) { + offset = pagedQuery.getOffset(); + limit = pagedQuery.getLimit(); + } + if (!evaluateCookie) { + query = QueryFactory.prepareQuery(con, queryLn, pagedQuery.toString()); + } + } + } + if (req.isParameterPresent("infer")) { + final boolean infer = Boolean.parseBoolean(req.getParameter("infer")); + query.setIncludeInferred(infer); + } + this.evaluate(builder, out, xslPath, req, resp, cookies, query, evaluateCookie, paged, offset, limit); + } + + /*** + * Evaluate a tuple query, and create an XML results document. This method + * completes writing of the response. !paged means use all results. + * + * @param builder + * response builder helper for generating the XML response to the + * client, which must not have had start() called on it + * @param xslPath + * needed to begin writing response body after writing result count + * cookie + * @param req + * needed to write result count cookie + * @param resp + * needed to write result count cookie + * @param cookies + * needed to write result count cookie + * @param query + * the query to be evaluated + * @param writeCookie + * whether to write the total result count cookie + * @param paged + * whether to display a limited subset + * @throws QueryResultHandlerException + */ + public void evaluateTupleQuery(final TupleResultBuilder builder, String xslPath, WorkbenchRequest req, + HttpServletResponse resp, CookieHandler cookies, final TupleQuery query, boolean writeCookie, + boolean paged, int offset, int limit) + throws QueryEvaluationException, QueryResultHandlerException + { + final TupleQueryResult result = query.evaluate(); + final String[] names = result.getBindingNames().toArray(new String[0]); + List bindings = Iterations.asList(result); + if (writeCookie) { + cookies.addTotalResultCountCookie(req, resp, bindings.size()); + } + builder.transform(xslPath, "tuple.xsl"); + builder.start(); + builder.variables(names); + builder.link(Arrays.asList(INFO)); + final List values = new ArrayList(names.length); + if (paged && writeCookie) { + // Only in this case do we have paged results, but were given the full + // query. Just-in-case parameter massaging below to avoid array index + // issues. + int fromIndex = Math.min(0, offset); + bindings = bindings.subList(fromIndex, + Math.max(fromIndex, Math.min(offset + limit, bindings.size()))); + } + for (BindingSet set : bindings) { + addResult(builder, names, values, set); + } + builder.end(); + } + + private void addResult(final TupleResultBuilder builder, final String[] names, final List values, + BindingSet set) + throws QueryResultHandlerException + { + values.clear(); + for (int i = 0; i < names.length; i++) { + values.add(set.getValue(names[i])); + } + builder.result(values.toArray()); + } + + /*** + * Evaluate a tuple query, and create an XML results document. It is still + * necessary to call end() on the builder after calling this method. + * + * @param builder + * response builder helper for generating the XML response to the + * client, which must have had start() called on it + * @param query + * the query to be evaluated + * @throws QueryResultHandlerException + */ + public void evaluateTupleQuery(final TupleResultBuilder builder, final TupleQuery query) + throws QueryEvaluationException, QueryResultHandlerException + { + final TupleQueryResult result = query.evaluate(); + try { + final String[] names = result.getBindingNames().toArray(new String[0]); + builder.variables(names); + builder.link(Arrays.asList(INFO)); + final List values = new ArrayList(); + while (result.hasNext()) { + final BindingSet set = result.next(); + addResult(builder, names, values, set); + } + } + finally { + result.close(); + } + } + + /*** + * Evaluate a graph query, and create an XML results document. + * + * @param builder + * response builder helper for generating the XML response to the + * client, which must not have had start() called on it + * @param xslPath + * needed to begin writing response body after writing result count + * cookie + * @param req + * needed to write result count cookie + * @param resp + * needed to write result count cookie + * @param cookies + * needed to write result count cookie + * @param query + * the query to be evaluated + * @param writeCookie + * whether to write the total result count cookie + * @throws QueryResultHandlerException + */ + private void evaluateGraphQuery(final TupleResultBuilder builder, String xslPath, WorkbenchRequest req, + HttpServletResponse resp, CookieHandler cookies, final GraphQuery query, boolean writeCookie, + boolean paged, int offset, int limit) + throws QueryEvaluationException, QueryResultHandlerException + { + List statements = Iterations.asList(query.evaluate()); + if (writeCookie) { + cookies.addTotalResultCountCookie(req, resp, statements.size()); + } + builder.transform(xslPath, "graph.xsl"); + builder.start(); + builder.variables("subject", "predicate", "object"); + builder.link(Arrays.asList(INFO)); + if (paged && writeCookie) { + // Only in this case do we have paged results, but were given the full + // query. Just-in-case parameter massaging below to avoid array index + // issues. + int fromIndex = Math.min(0, offset); + statements = statements.subList(fromIndex, + Math.max(fromIndex, Math.min(offset + limit, statements.size()))); + } + for (Statement statement : statements) { + builder.result(statement.getSubject(), statement.getPredicate(), statement.getObject(), + statement.getContext()); + } + builder.end(); + } + + private void evaluateGraphQuery(final RDFWriter writer, final GraphQuery query) + throws QueryEvaluationException, RDFHandlerException + { + query.evaluate(writer); + } + + private void evaluateBooleanQuery(final TupleResultBuilder builder, final BooleanQuery query) + throws QueryEvaluationException, QueryResultHandlerException + { + final boolean result = query.evaluate(); + builder.link(Arrays.asList(INFO)); + builder.bool(result); + } + + private void evaluate(final TupleResultBuilder builder, final OutputStream out, final String xslPath, + final WorkbenchRequest req, HttpServletResponse resp, CookieHandler cookies, final Query query, + boolean writeCookie, boolean paged, int offset, int limit) + throws OpenRDFException, BadRequestException + { + if (query instanceof TupleQuery) { + this.evaluateTupleQuery(builder, xslPath, req, resp, cookies, (TupleQuery)query, writeCookie, paged, + offset, limit); + } + else { + final RDFFormat format = req.isParameterPresent(ACCEPT) ? Rio.getWriterFormatForMIMEType( + req.getParameter(ACCEPT)).orElse(null) : null; + if (query instanceof GraphQuery) { + GraphQuery graphQuery = (GraphQuery)query; + if (null == format) { + this.evaluateGraphQuery(builder, xslPath, req, resp, cookies, graphQuery, writeCookie, paged, + offset, limit); + } + else { + this.evaluateGraphQuery(Rio.createWriter(format, out), graphQuery); + } + } + else if (query instanceof BooleanQuery) { + builder.transform(xslPath, "boolean.xsl"); + builder.startBoolean(); + this.evaluateBooleanQuery(builder, (BooleanQuery)query); + builder.endBoolean(); + } + else { + throw new BadRequestException("Unknown query type: " + query.getClass().getSimpleName()); + } + } + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryFactory.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryFactory.java new file mode 100644 index 00000000000..942241530aa --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryFactory.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.query.Query; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.repository.RepositoryConnection; + +/** + * Utility class for generating query objects. + */ +public class QueryFactory { + + public static Query prepareQuery(final RepositoryConnection con, final QueryLanguage queryLn, final String query) + throws OpenRDFException + { + Query rval = null; + try { + rval = con.prepareQuery(queryLn, query); + } + catch (UnsupportedOperationException exc) { + // TODO must be an HTTP repository + try { + con.prepareTupleQuery(queryLn, query).evaluate().close(); + rval = con.prepareTupleQuery(queryLn, query); + } + catch (Exception e1) { + // guess its not a tuple query + try { + con.prepareGraphQuery(queryLn, query).evaluate().close(); + rval = con.prepareGraphQuery(queryLn, query); + } + catch (Exception e2) { + // guess its not a graph query + try { + con.prepareBooleanQuery(queryLn, query).evaluate(); + rval = con.prepareBooleanQuery(queryLn, query); + } + catch (Exception e3) { + // guess its not a boolean query + // let's assume it is an malformed tuple query + rval = con.prepareTupleQuery(queryLn, query); + } + } + } + } + return rval; + } +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryStorage.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryStorage.java new file mode 100644 index 00000000000..cecbcd5e5a7 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryStorage.java @@ -0,0 +1,517 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import java.io.File; +import java.io.IOException; +import java.util.UUID; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.app.AppConfiguration; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.UpdateExecutionException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides an interface to the private repository with the saved queries. + * + * @author Dale Visser + */ +public class QueryStorage { + + private static final Object LOCK = new Object(); + + private static final QueryEvaluator EVAL = QueryEvaluator.INSTANCE; + + private static QueryStorage instance; + + public static QueryStorage getSingletonInstance(final AppConfiguration config) + throws RepositoryException, IOException + { + synchronized (LOCK) { + if (instance == null || instance.isShutdown()) { + instance = new QueryStorage(config); + } + return instance; + } + } + + private boolean isShutdown() { + return queries == null || !queries.isInitialized(); + } + + private static final Logger LOGGER = LoggerFactory.getLogger(QueryStorage.class); + + private static final String PRE = "PREFIX : \n"; + + // SAVE needs xsd: prefix since explicit XSD data types will be substituted. + private static final String SAVE = "PREFIX xsd:\n" + + PRE + + "INSERT DATA { $ :userName $ ; :queryName $ ; " + + ":repository $ ; :shared $ ; :queryLanguage $ ; :query $ ; " + + ":infer $ ; :rowsPerPage $ . }"; + + private static final String ASK_EXISTS = PRE + + "ASK { [] :userName $ ; :queryName $ ; :repository $ . }"; + + private static final String UPDATE_FILTER = "FILTER (?user = $ || ?user = \"\" ) } "; + + private static final String READ_FILTER = "FILTER (?user = $ || ?user = \"\" || ?shared) } "; + + private static final String ASK_UPDATABLE = PRE + "ASK { $ :userName ?user . " + UPDATE_FILTER; + + private static final String ASK_READABLE = PRE + "ASK { $ :userName ?user ; :shared ?shared . " + + READ_FILTER; + + private static final String DELETE = PRE + "DELETE WHERE { $ :userName ?user ; ?p ?o . }"; + + private static final String MATCH = ":shared ?s ; :queryLanguage ?ql ; :query ?q ; :rowsPerPage ?rpp .\n"; + + private static final String UPDATE = PRE + + "DELETE { $ " + + MATCH + + "}\nINSERT { $ :shared $ ; :queryLanguage $ ; :query $ ; " + + ":infer $ ; :rowsPerPage $ . } WHERE { $ :userName ?user ; " + MATCH + + UPDATE_FILTER; + + private static final String SELECT_URI = PRE + + "SELECT ?query { ?query :repository $ ; :userName $ ; :queryName $ . } "; + + private static final String SELECT_TEXT = PRE + + "SELECT ?queryText { [] :repository $ ; :userName $ ; :queryName $ ; :query ?queryText . } "; + + private static final String SELECT = PRE + + "SELECT ?query ?user ?queryName ?shared ?queryLn ?queryText ?infer ?rowsPerPage " + + "{ ?query :repository $ ; :userName ?user ; :queryName ?queryName ; :shared ?shared ; " + + ":queryLanguage ?queryLn ; :query ?queryText ; :infer ?infer ; :rowsPerPage ?rowsPerPage .\n" + + READ_FILTER + "ORDER BY ?user ?queryName"; + + private final Repository queries; + + private static final String USER_NAME = "$"; + + private static final String REPOSITORY = "$"; + + private static final String QUERY = "$"; + + private static final String QUERY_NAME = "$"; + + /** + * Create a new object for accessing the store of user queries. + * + * @param appConfig + * the application configuration, for obtaining the data directory + * @throws RepositoryException + * if there is an issue creating the object to access the repository + * @throws IOException + */ + protected QueryStorage(final AppConfiguration appConfig) + throws RepositoryException, IOException + { + queries = new SailRepository(new NativeStore(new File(appConfig.getDataDir(), "queries"))); + queries.initialize(); + } + + public void shutdown() { + try { + if (queries != null && queries.isInitialized()) { + queries.shutDown(); + } + } + catch (RepositoryException e) { + LOGGER.warn(e.getMessage()); + } + } + + /** + * Checks whether the current user/password credentials can really access the + * current repository. + * + * @param repository + * the current repository + * @return true, if it is possible to request a statement from the repository + * with the given credentials + * @throws RepositoryException + * if there is an issue closing the connection + */ + public boolean checkAccess(final HTTPRepository repository) + throws RepositoryException + { + LOGGER.info("repository: {}", repository.getRepositoryURL()); + boolean rval = true; + RepositoryConnection con = repository.getConnection(); + try { + // Manufacture an unlikely unique statement to check. + IRI uri = con.getValueFactory().createIRI("urn:uuid:" + UUID.randomUUID()); + con.hasStatement(uri, uri, uri, false, uri); + } + catch (RepositoryException re) { + rval = false; + } + finally { + con.close(); + } + return rval; + } + + /** + * Save a query. UNSAFE from an injection point of view. It is the + * responsibility of the calling code to call checkAccess() with the full + * credentials first. + * + * @param repository + * the repository the query is associated with + * @param queryName + * the name for the query + * @param userName + * the user saving the query + * @param shared + * whether the query is to be shared with other users + * @param queryLanguage + * the language, SeRQL or SPARQL, of the query + * @param queryText + * the actual query text + * @param infer + * @param rowsPerPage + * rows to display per page, may be 0 (all), 10, 50, 100, or 200) + * @throws OpenRDFException + */ + public void saveQuery(final HTTPRepository repository, final String queryName, final String userName, + final boolean shared, final QueryLanguage queryLanguage, final String queryText, + final boolean infer, final int rowsPerPage) + throws OpenRDFException + { + if (QueryLanguage.SPARQL != queryLanguage && QueryLanguage.SERQL != queryLanguage) { + throw new RepositoryException("May only save SPARQL or SeRQL queries, not" + + queryLanguage.toString()); + } + if (0 != rowsPerPage && 10 != rowsPerPage && 20 != rowsPerPage && 50 != rowsPerPage + && 100 != rowsPerPage && 200 != rowsPerPage) + { + throw new RepositoryException("Illegal value for rows per page: " + rowsPerPage); + } + this.checkQueryText(queryText); + final QueryStringBuilder save = new QueryStringBuilder(SAVE); + save.replaceURI(REPOSITORY, repository.getRepositoryURL()); + save.replaceURI(QUERY, "urn:uuid:" + UUID.randomUUID()); + save.replaceQuote(QUERY_NAME, queryName); + this.replaceUpdateFields(save, userName, shared, queryLanguage, queryText, infer, rowsPerPage); + updateQueryRepository(save.toString()); + } + + /** + * Determines whether the user with the given userName is allowed to update + * or delete the given query. + * + * @param query + * the node identifying the query of interest + * @param currentUser + * the user to check access for + * @return true if the given query was saved by the given user or + * the anonymous user + */ + public boolean canChange(final IRI query, final String currentUser) + throws RepositoryException, QueryEvaluationException, MalformedQueryException + { + return performAccessQuery(ASK_UPDATABLE, query, currentUser); + } + + /** + * Determines whether the user with the given userName is allowed to read the + * given query. + * + * @param query + * the node identifying the query of interest + * @param currentUser + * the user to check access for + * @return true if the given query was saved by either the given + * user or the anonymous user, or is shared + */ + public boolean canRead(IRI query, String currentUser) + throws RepositoryException, QueryEvaluationException, MalformedQueryException + { + return performAccessQuery(ASK_READABLE, query, currentUser); + } + + private boolean performAccessQuery(String accessSPARQL, IRI query, String currentUser) + throws RepositoryException, QueryEvaluationException, MalformedQueryException + { + final QueryStringBuilder canDelete = new QueryStringBuilder(accessSPARQL); + canDelete.replaceURI(QUERY, query.toString()); + canDelete.replaceQuote(USER_NAME, currentUser); + LOGGER.info("{}", canDelete); + final RepositoryConnection connection = this.queries.getConnection(); + try { + return connection.prepareBooleanQuery(QueryLanguage.SPARQL, canDelete.toString()).evaluate(); + } + finally { + connection.close(); + } + } + + public boolean askExists(final HTTPRepository repository, final String queryName, final String userName) + throws QueryEvaluationException, RepositoryException, MalformedQueryException + { + final QueryStringBuilder ask = new QueryStringBuilder(ASK_EXISTS); + ask.replaceURI(REPOSITORY, repository.getRepositoryURL()); + ask.replaceQuote(QUERY_NAME, queryName); + ask.replaceQuote(USER_NAME, userName); + LOGGER.info("{}", ask); + final RepositoryConnection connection = this.queries.getConnection(); + try { + return connection.prepareBooleanQuery(QueryLanguage.SPARQL, ask.toString()).evaluate(); + } + finally { + connection.close(); + } + } + + /** + * Delete the given query for the given user. It is the responsibility of the + * calling code to call checkAccess() and canDelete() with the full + * credentials first. + * + * @param query + * @param userName + * @throws RepositoryException + * @throws UpdateExecutionException + * @throws MalformedQueryException + */ + public void deleteQuery(final IRI query, final String userName) + throws RepositoryException, UpdateExecutionException, MalformedQueryException + { + final QueryStringBuilder delete = new QueryStringBuilder(DELETE); + delete.replaceQuote(QueryStorage.USER_NAME, userName); + delete.replaceURI(QUERY, query.toString()); + updateQueryRepository(delete.toString()); + } + + /** + * Update the entry for the given query. It is the responsibility of the + * calling code to call checkAccess() with the full credentials first. + * + * @param query + * the query to update + * @param userName + * the user name + * @param shared + * whether to share with other users + * @param queryLanguage + * the query language + * @param queryText + * the text of the query + * @param infer + * @param rowsPerPage + * the rows per page to display of the query + * @throws RepositoryException + * if a problem occurs during the update + * @throws UpdateExecutionException + * if a problem occurs during the update + * @throws MalformedQueryException + * if a problem occurs during the update + */ + public void updateQuery(final IRI query, final String userName, final boolean shared, + final QueryLanguage queryLanguage, final String queryText, final boolean infer, final int rowsPerPage) + throws RepositoryException, UpdateExecutionException, MalformedQueryException + { + final QueryStringBuilder update = new QueryStringBuilder(UPDATE); + update.replaceURI(QUERY, query); + this.replaceUpdateFields(update, userName, shared, queryLanguage, queryText, infer, rowsPerPage); + this.updateQueryRepository(update.toString()); + } + + /** + * Prepares a query to retrieve the queries accessible to the given user in + * the given repository. When evaluated, the query result will have the + * following binding names: query, user, queryName, shared, queryLn, + * queryText, rowsPerPage. It is the responsibility of the calling code to + * call checkAccess() with the full credentials first. + * + * @param repository + * that the saved queries run against + * @param userName + * that is requesting the saved queries + * @param builder + * receives a list of all the saved queries against the given + * repository and accessible to the given user + * @throws RepositoryException + * if there's a problem connecting to the saved queries repository + * @throws MalformedQueryException + * if the query is not legal SPARQL + * @throws QueryEvaluationException + * if there is a problem while attempting to evaluate the query + * @throws QueryResultHandlerException + */ + public void selectSavedQueries(final HTTPRepository repository, final String userName, + final TupleResultBuilder builder) + throws RepositoryException, MalformedQueryException, QueryEvaluationException, + QueryResultHandlerException + { + final QueryStringBuilder select = new QueryStringBuilder(SELECT); + select.replaceQuote(USER_NAME, userName); + select.replaceURI(REPOSITORY, repository.getRepositoryURL()); + final RepositoryConnection connection = this.queries.getConnection(); + try { + EVAL.evaluateTupleQuery(builder, + connection.prepareTupleQuery(QueryLanguage.SPARQL, select.toString())); + } + finally { + connection.close(); + } + } + + /** + * Returns the URI for the saved query in the given repository with the given + * name, owned by the given owner. + * + * @param repository + * The repository the query is associated with. + * @param owner + * The user that saved the query. + * @param queryName + * The name given to the query. + * @return if it exists, the URI referring to the specified saved query. + * @throws OpenRDFException + * if issues occur performing the necessary queries. + * @throws BadRequestException + * if the the specified stored query doesn't exist + */ + public IRI selectSavedQuery(final HTTPRepository repository, final String owner, final String queryName) + throws OpenRDFException, BadRequestException + { + final QueryStringBuilder select = new QueryStringBuilder(SELECT_URI); + select.replaceQuote(QueryStorage.USER_NAME, owner); + select.replaceURI(REPOSITORY, repository.getRepositoryURL()); + select.replaceQuote(QUERY_NAME, queryName); + final RepositoryConnection connection = this.queries.getConnection(); + final TupleQuery query = connection.prepareTupleQuery(QueryLanguage.SPARQL, select.toString()); + try { + final TupleQueryResult result = query.evaluate(); + if (result.hasNext()) { + return (IRI)(result.next().getValue("query")); + } + else { + throw new BadRequestException("Could not find query entry in storage."); + } + } + finally { + connection.close(); + } + } + + /** + * Retrieves the specified query text. No security checks are done here. If + * the saved query exists, its text is returned. + * + * @param repository + * Repository that the saved query is associated with. + * @param owner + * The user that saved the query. + * @param queryName + * The name given to the saved query. + * @return the text of the saved query, if it exists + * @throws OpenRDFException + * if a problem occurs accessing storage + * @throws BadRequestException + * if the specified query doesn't exist + */ + public String getQueryText(final HTTPRepository repository, final String owner, final String queryName) + throws OpenRDFException, BadRequestException + { + final QueryStringBuilder select = new QueryStringBuilder(SELECT_TEXT); + select.replaceQuote(QueryStorage.USER_NAME, owner); + select.replaceURI(REPOSITORY, repository.getRepositoryURL()); + select.replaceQuote(QUERY_NAME, queryName); + final RepositoryConnection connection = this.queries.getConnection(); + final TupleQuery query = connection.prepareTupleQuery(QueryLanguage.SPARQL, select.toString()); + try { + final TupleQueryResult result = query.evaluate(); + if (result.hasNext()) { + return result.next().getValue("queryText").stringValue(); + } + else { + throw new BadRequestException("Could not find query entry in storage."); + } + } + finally { + connection.close(); + } + } + + private void updateQueryRepository(final String update) + throws RepositoryException, UpdateExecutionException, MalformedQueryException + { + LOGGER.info("SPARQL/Update of Query Storage:\n--\n{}\n--", update); + final RepositoryConnection connection = this.queries.getConnection(); + try { + connection.prepareUpdate(QueryLanguage.SPARQL, update).execute(); + } + finally { + connection.close(); + } + } + + /** + * Perform replacement on several common fields for update operations. + * + * @param userName + * the name of the current user + * @param shared + * whether the saved query is to be shared with other users + * @param queryLanguage + * the language of the saved query + * @param queryText + * the actual text of the query to save + * @param infer + * @param rowsPerPage + * the rows per page to display for results + */ + private void replaceUpdateFields(final QueryStringBuilder builder, final String userName, + final boolean shared, final QueryLanguage queryLanguage, final String queryText, + final boolean infer, final int rowsPerPage) + { + builder.replaceQuote(USER_NAME, userName); + builder.replace("$", QueryStringBuilder.xsdQuote(String.valueOf(shared), "boolean")); + builder.replaceQuote("$", queryLanguage.toString()); + checkQueryText(queryText); + builder.replace("$", QueryStringBuilder.quote(queryText, "'''", "'''")); + builder.replace("$", QueryStringBuilder.xsdQuote(String.valueOf(infer), "boolean")); + builder.replace("$", + QueryStringBuilder.xsdQuote(String.valueOf(rowsPerPage), "unsignedByte")); + } + + /** + * Imposes the rule that the query may not contain '''-quoted string, since + * that is how we'll be quoting it in our SPARQL/Update statements. Quoting + * the query with ''' assuming all string literals in the query are of the + * STRING_LITERAL1, STRING_LITERAL2 or STRING_LITERAL_LONG2 types. + * + * @param queryText + * the query text + */ + private void checkQueryText(final String queryText) { + if (queryText.indexOf("'''") > 0) { + throw new IllegalArgumentException("queryText may not contain '''-quoted strings."); + } + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryStringBuilder.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryStringBuilder.java new file mode 100644 index 00000000000..02c953599c7 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/QueryStringBuilder.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import java.util.regex.Pattern; + +/** + * Helper class for substituting in variables to query templates for the purpose + * of saving and retrieving user queries to a repository local to the workbench. + * + * @author Dale Visser + */ +public class QueryStringBuilder { + + private final StringBuilder builder; + + private static final Pattern VAR_PATTERN = Pattern.compile("\\$<\\w+>"); + + /** + * Creates a new builder from the given template. + * + * @param template + */ + public QueryStringBuilder(final String template) { + if (null == template || template.isEmpty()) { + throw new IllegalArgumentException("Template is null or length is zero."); + } + if (!VAR_PATTERN.matcher(template).find()) { + throw new IllegalArgumentException("Template did not contain variables."); + } + this.builder = new StringBuilder(template); + } + + /** + * Returns the internal string being constructed. + */ + @Override + public String toString() { + return this.builder.toString(); + } + + /** + * Replace the repository variable with the current repository URL. + * + * @param paramText + * the $<...> formatted parameter name + * @param uri + * any object who's toString() returns a valid URI + */ + protected void replaceURI(final String paramText, final Object uri) { + replace(paramText, QueryStringBuilder.uriQuote(uri.toString())); + } + + /** + * Replace instances of the old text with a copy of the new text. + * + * @param paramText + * parameter in the form "$" + * @param newText + * the new text + */ + protected void replace(final String paramText, final String newText) { + int loc = builder.indexOf(paramText); + while (loc >= 0) { + builder.replace(loc, loc + paramText.length(), newText); + loc = builder.indexOf(paramText); + } + } + + protected void replaceQuote(final String paramText, final String newText) { + this.replace(paramText, quote(newText)); + } + + /** + * Place double quotes around the given string. + * + * @param value + * the string to add quotes to + * @return a copy of the given strings quoted with double quotes + */ + private static String quote(final String value) { + return quote(value, "\"", "\""); + } + + /** + * Place double quotes around the given string and append an XSD data type. + * + * @param value + * the value to quote + * @param type + * the XSD data type name + * @return a copy of the given string quoted with XSD data type appended + */ + protected static String xsdQuote(final String value, final String type) { + return quote(value, "\"", "\"^^xsd:" + type); + } + + /** + * Place angle brackets around a URI or URL. + * + * @param uri + * an object whose toString() returns a URI or URL + * @return a string quoting the given URI with angle brackets + */ + private static String uriQuote(final Object uri) { + return quote(uri.toString(), "<", ">"); + } + + protected static String quote(final String value, final String left, final String right) { + return left + value + right; + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/TupleResultBuilder.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/TupleResultBuilder.java new file mode 100644 index 00000000000..384495cbf19 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/TupleResultBuilder.java @@ -0,0 +1,188 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.util.LiteralUtilException; +import org.eclipse.rdf4j.model.util.Literals; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.impl.SimpleBinding; +import org.eclipse.rdf4j.query.resultio.QueryResultWriter; + +/** + * A small wrapper around {@link QueryResultWriter} to make it easier to + * generate results in servlets. + * + * @author peter + */ +public class TupleResultBuilder { + + private final QueryResultWriter out; + + private final ValueFactory vf; + + private List variables = new ArrayList(); + + public TupleResultBuilder(QueryResultWriter writer, ValueFactory valueFactory) { + this.out = writer; + this.vf = valueFactory; + } + + public void prefix(String prefix, String namespace) + throws QueryResultHandlerException + { + out.handleNamespace(prefix, namespace); + } + + public TupleResultBuilder transform(String path, String xsl) + throws QueryResultHandlerException + { + out.handleStylesheet(path + "/" + xsl); + return this; + } + + /** + * This must be called before calling {@link #namedResult(String, Object)} or + * {@link #result(Object...)}. + * + * @param variables + * one or more variable names + * @return this builder, for the convenience of chaining calls + * @throws QueryResultHandlerException + */ + public TupleResultBuilder start(String... variables) + throws QueryResultHandlerException + { + variables(variables); + return this; + } + + public TupleResultBuilder startBoolean() { + // Do not need to do anything here currently + return this; + } + + public TupleResultBuilder variables(String... names) + throws QueryResultHandlerException + { + variables = Arrays.asList(names); + out.startQueryResult(variables); + return this; + } + + public TupleResultBuilder link(List url) + throws QueryResultHandlerException + { + out.handleLinks(url); + return this; + } + + public TupleResultBuilder bool(boolean result) + throws QueryResultHandlerException + { + out.handleBoolean(result); + return this; + } + + /** + * {@link #start(String...)} must be called before using this method. + * + * @param result + * a single result, one value for each variable, in the same order as + * the variable names were provided + * @return this builder, for the convenience of chaining calls + * @throws QueryResultHandlerException + */ + public TupleResultBuilder result(Object... result) + throws QueryResultHandlerException + { + QueryBindingSet bindingSet = new QueryBindingSet(); + for (int i = 0; i < result.length; i++) { + if (result[i] == null) + continue; + bindingSet.addBinding(outputNamedResult(variables.get(i), result[i])); + } + out.handleSolution(bindingSet); + return this; + } + + /** + * {@link #start(String...)} must be called before using this method. + * + * @param name + * the variable name, from the set of provided variable names + * @param result + * the result value associated with the given variable name + * @return this builder, for the convenience of chaining calls + * @throws QueryResultHandlerException + */ + public TupleResultBuilder namedResult(String name, Object result) + throws QueryResultHandlerException + { + QueryBindingSet bindingSet = new QueryBindingSet(); + bindingSet.addBinding(outputNamedResult(name, result)); + out.handleSolution(bindingSet); + return this; + } + + private Binding outputNamedResult(String name, Object result) + throws QueryResultHandlerException + { + final Value nextValue; + if (result instanceof Value) { + nextValue = (Value)result; + } + else if (result instanceof URL) { + nextValue = vf.createIRI(result.toString()); + } + else { + try { + nextValue = Literals.createLiteralOrFail(vf, result); + } + catch (LiteralUtilException e) { + throw new QueryResultHandlerException("Could not convert an object to a Value", e); + } + } + return new SimpleBinding(name, nextValue); + } + + /** + * This must be called if {@link #start(String...)} is used, after all + * results are generated using either {@link #namedResult(String, Object)} or + * {@link #result(Object...)}. + *

+ * This must not be called if {@link #bool(boolean)} or {@link #endBoolean()} + * have been called. + * + * @return This object, for chaining with other calls. + * @throws QueryResultHandlerException + */ + public TupleResultBuilder end() + throws QueryResultHandlerException + { + out.endQueryResult(); + return this; + } + + public TupleResultBuilder endBoolean() { + // do nothing, as the call to handleBoolean always ends the document + return this; + } + + public void flush() { + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/ValueDecoder.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/ValueDecoder.java new file mode 100644 index 00000000000..804d15997c3 --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/ValueDecoder.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Decodes strings into values for {@link WorkbenchRequst}. + */ +class ValueDecoder { + + private static final Logger LOGGER = LoggerFactory.getLogger(ValueDecoder.class); + + private final ValueFactory factory; + + private final Repository repository; + + /** + * Creates an instance of ValueDecoder. + * + * @param repository + * to get namespaces from + * @param factory + * to generate values + */ + protected ValueDecoder(Repository repository, ValueFactory factory) { + this.repository = repository; + this.factory = factory; + } + + /** + * Decode the given string into a {@link org.eclipse.rdf4j.model.Value}. + * + * @param string + * representation of an RDF value + * @return the parsed value, or null if the string is null, empty, only + * whitespace, or {@link java.lang.String#equals(Object)} "null". + * @throws BadRequestException + * if a problem occurs during parsing + */ + protected Value decodeValue(String string) + throws BadRequestException + { + Value result = null; + try { + if (string != null) { + String value = string.trim(); + if (!value.isEmpty() && !"null".equals(value)) { + if (value.startsWith("_:")) { + String label = value.substring("_:".length()); + result = factory.createBNode(label); + } + else { + if (value.charAt(0) == '<' && value.endsWith(">")) { + result = factory.createIRI(value.substring(1, value.length() - 1)); + } + else { + if (value.charAt(0) == '"') { + result = parseLiteral(value); + } + else { + result = parseURI(value); + } + } + } + } + } + } + catch (Exception exc) { + LOGGER.warn(exc.toString(), exc); + throw new BadRequestException("Malformed value: " + string, exc); + } + return result; + } + + private Value parseURI(String value) + throws RepositoryException, BadRequestException + { + String prefix = value.substring(0, value.indexOf(':')); + String localPart = value.substring(prefix.length() + 1); + String namespace = getNamespace(prefix); + if (namespace == null) { + throw new BadRequestException("Undefined prefix: " + value); + } + return factory.createIRI(namespace, localPart); + } + + private Value parseLiteral(String value) + throws BadRequestException + { + String label = value.substring(1, value.lastIndexOf('"')); + Value result; + if (value.length() == (label.length() + 2)) { + result = factory.createLiteral(label); + } + else { + String rest = value.substring(label.length() + 2); + if (rest.startsWith("^^")) { + Value datatype = decodeValue(rest.substring(2)); + if (datatype instanceof IRI) { + result = factory.createLiteral(label, (IRI)datatype); + } + else { + throw new BadRequestException("Malformed datatype: " + value); + } + } + else if (rest.charAt(0) == '@') { + result = factory.createLiteral(label, rest.substring(1)); + } + else { + throw new BadRequestException("Malformed language tag or datatype: " + value); + } + } + return result; + } + + private String getNamespace(String prefix) + throws RepositoryException + { + RepositoryConnection con = repository.getConnection(); + try { + return con.getNamespace(prefix); + } + finally { + con.close(); + } + } + +} diff --git a/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/WorkbenchRequest.java b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/WorkbenchRequest.java new file mode 100644 index 00000000000..b31b6d0810c --- /dev/null +++ b/core/http/workbench/src/main/java/org/eclipse/rdf4j/workbench/util/WorkbenchRequest.java @@ -0,0 +1,357 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import static java.net.URLDecoder.decode; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +import org.apache.commons.fileupload.FileItemIterator; +import org.apache.commons.fileupload.FileItemStream; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; + +/** + * Request wrapper used by {@link org.eclipse.rdf4j.workbench.base + * TransformationServlet}. + */ +public class WorkbenchRequest extends HttpServletRequestWrapper { + + private static final String UTF_8 = "UTF-8"; + + private Map parameters; + + private final Map defaults; + + private InputStream content; + + private String contentFileName; + + private final ValueDecoder decoder; + + /** + * Wrap a request with an object aware of the current repository and + * application defaults. + * + * @param repository + * currently connected repository + * @param request + * current request + * @param defaults + * application default parameter values + * @throws RepositoryException + * if there is an issue retrieving the parameter map + * @throws IOException + * if there is an issue retrieving the parameter map + * @throws FileUploadException + * if there is an issue retrieving the parameter map + */ + public WorkbenchRequest(Repository repository, HttpServletRequest request, Map defaults) + throws RepositoryException, IOException, FileUploadException + { + super(request); + this.defaults = defaults; + this.decoder = new ValueDecoder(repository, (repository == null) ? SimpleValueFactory.getInstance() + : repository.getValueFactory()); + String url = request.getRequestURL().toString(); + if (ServletFileUpload.isMultipartContent(this)) { + parameters = getMultipartParameterMap(); + } + else if (request.getQueryString() == null && url.contains(";")) { + parameters = getUrlParameterMap(url); + } + } + + /** + * Get the content of any uploaded file that is part of this request. + * + * @return the uploaded file contents, or null if not applicable + */ + public InputStream getContentParameter() { + return content; + } + + /** + * Get the name of any uploaded file that is part of this request. + * + * @return the uploaded file name, or null if not applicable + */ + public String getContentFileName() { + return contentFileName; + } + + /*** + * Get the integer value associated with the given parameter name. Internally + * uses getParameter(String), so looks in this order: 1. the query parameters + * that were parsed at construction, using the last value if multiple exist. + * 2. Request cookies. 3. The defaults. + * + * @return the value of the parameter, or zero if it is not present + * @throws BadRequestException + * if the parameter is present but does not parse as an integer + */ + public int getInt(String name) + throws BadRequestException + { + int result = 0; + String limit = getParameter(name); + if (limit != null && !limit.isEmpty()) { + try { + result = Integer.parseInt(limit); + } + catch (NumberFormatException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + } + return result; + } + + @Override + public String getParameter(String name) { + String result = null; + if (parameters != null && parameters.containsKey(name)) { + result = parameters.get(name); + } + else { + String[] values = super.getParameterValues(name); + if (values != null && values.length > 0) { + // use the last one as it may be appended in JavaScript + result = values[values.length - 1]; + } + else { + result = getCookie(name); + if (result == null && defaults != null && defaults.containsKey(name)) { + result = defaults.get(name); + } + } + } + return result; + } + + private String getCookie(String name) { + String result = null; + Cookie[] cookies = getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (name.equals(cookie.getName())) { + result = cookie.getValue(); + break; + } + } + } + return result; + } + + @Override + public String[] getParameterValues(String name) { + return (parameters != null && parameters.containsKey(name)) ? new String[] { parameters.get(name) } + : super.getParameterValues(name); + } + + /** + * Returns whether a non-null, non-empty value is available for the given + * parameter name. + * + * @param name + * parameter name to check + * @return true if a non-null, non-empty value exists, false otherwise + */ + public boolean isParameterPresent(String name) { + boolean result = false; + if (parameters == null || parameters.get(name) == null) { + String[] values = super.getParameterValues(name); + if (values != null && values.length > 0) { + // use the last one as it may be appended in JavaScript + result = !values[values.length - 1].isEmpty(); + } + } + else { + result = !parameters.get(name).isEmpty(); + } + return result; + } + + /** + * Returns a {@link org.eclipse.rdf4j.model.Resource} corresponding to the value of + * the given parameter name. + * + * @param name + * of parameter to retrieve resource from + * @return value corresponding to the given parameter name + * @throws BadRequestException + * if a problem occurs parsing the parameter value + */ + public Resource getResource(String name) + throws BadRequestException, RepositoryException + { + Value value = getValue(name); + if (value == null || value instanceof Resource) { + return (Resource)value; + } + throw new BadRequestException("Not a BNode or URI: " + value); + } + + /** + * Gets a map of the all parameters with values, also caching them in this + * {@link WorkbenchRequest}. + * + * @return a map of all parameters with values + */ + public Map getSingleParameterMap() { + @SuppressWarnings("unchecked") + Map map = super.getParameterMap(); + Map parameters = new HashMap(map.size()); + for (String name : map.keySet()) { + if (isParameterPresent(name)) { + parameters.put(name, getParameter(name)); + } + } + if (this.parameters != null) { + parameters.putAll(this.parameters); + } + return parameters; + } + + /** + * Gets the value of the 'type' parameter. + * + * @return the value of the 'type' parameter + */ + public String getTypeParameter() { + return getParameter("type"); + } + + /** + * Gets the URI referred to by the parameter value. + * + * @param name + * of the parameter to check + * @return the URI, or null if the parameter has no value, is only + * whitespace, or equals "null" + * @throws BadRequestException + * if the value doesn't parse as a URI + * @throws RepositoryException + * if the name space prefix is not resolvable + */ + public IRI getURI(String name) + throws BadRequestException, RepositoryException + { + Value value = getValue(name); + if (value == null || value instanceof IRI) { + return (IRI)value; + } + throw new BadRequestException("Not a URI: " + value); + } + + /** + * Gets the URL referred to by the parameter value. + * + * @param name + * of the parameter to check + * @return the URL + * @throws BadRequestException + * if the value doesn't parse as a URL + */ + public URL getUrl(String name) + throws BadRequestException + { + String url = getParameter(name); + try { + return new URL(url); + } + catch (MalformedURLException exc) { + throw new BadRequestException(exc.getMessage(), exc); + } + } + + /** + * Gets the {@link org.eclipse.rdf4j.model.Value} referred to by the parameter + * value. + * + * @param name + * of the parameter to check + * @return the value, or null if the parameter has no value, is only + * whitespace, or equals "null" + * @throws BadRequestException + * if the value doesn't parse as a URI + * @throws RepositoryException + * if any name space prefix is not resolvable + */ + public Value getValue(String name) + throws BadRequestException, RepositoryException + { + return decoder.decodeValue(getParameter(name)); + } + + private String firstLine(FileItemStream item) + throws IOException + { + InputStream stream = item.openStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + try { + return reader.readLine(); + } + finally { + reader.close(); + } + } + + private Map getMultipartParameterMap() + throws RepositoryException, IOException, FileUploadException + { + Map parameters = new HashMap(); + ServletFileUpload upload = new ServletFileUpload(); + FileItemIterator iter = upload.getItemIterator(this); + while (iter.hasNext()) { + FileItemStream item = iter.next(); + String name = item.getFieldName(); + if ("content".equals(name)) { + content = item.openStream(); + contentFileName = item.getName(); + break; + } + else { + parameters.put(name, firstLine(item)); + } + } + return parameters; + } + + private Map getUrlParameterMap(String url) + throws UnsupportedEncodingException + { + String qry = url.substring(url.indexOf(';') + 1); + Map parameters = new HashMap(); + for (String param : qry.split("&")) { + int idx = param.indexOf('='); + String name = decode(param.substring(0, idx), UTF_8); + String value = decode(param.substring(idx + 1), UTF_8); + parameters.put(name, value); + } + return parameters; + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/WEB-INF/glassfish-web.xml b/core/http/workbench/src/main/webapp/WEB-INF/glassfish-web.xml new file mode 100644 index 00000000000..5898d75e66c --- /dev/null +++ b/core/http/workbench/src/main/webapp/WEB-INF/glassfish-web.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/WEB-INF/web.xml b/core/http/workbench/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..3dad306266f --- /dev/null +++ b/core/http/workbench/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,197 @@ + + + + RDF4J Workbench + RDF4J Workbench + + + redirect + + org.eclipse.rdf4j.workbench.proxy.RedirectFilter + + + / + /repositories + + + + + cache + + org.eclipse.rdf4j.workbench.proxy.CookieCacheControlFilter + + + + + CacheFilter + org.eclipse.rdf4j.workbench.proxy.CacheFilter + + Cache-Control + 600 + + + + + redirect + / + + + + cache + /repositories/* + + + + CacheFilter + * + + + + workbench + + org.eclipse.rdf4j.workbench.proxy.WorkbenchGateway + + + transformations + /transformations + + + default-server + /rdf4j-server + + + accepted-server-prefixes + file: http: https: + + + change-server-path + /NONE/server + + + cookie-max-age + 2592000 + + + no-repository-id + NONE + + + default-path + /NONE/repositories + + + default-command + /summary + + + default-limit + 100 + + + default-queryLn + SPARQL + + + default-infer + true + + + default-Accept + application/rdf+xml + + + default-Content-Type + application/rdf+xml + + + /summary + org.eclipse.rdf4j.workbench.commands.SummaryServlet + + + + /info + org.eclipse.rdf4j.workbench.commands.InfoServlet + + + /information + org.eclipse.rdf4j.workbench.commands.InformationServlet + + + + /repositories + org.eclipse.rdf4j.workbench.commands.RepositoriesServlet + + + + /create + org.eclipse.rdf4j.workbench.commands.CreateServlet + + + + /delete + org.eclipse.rdf4j.workbench.commands.DeleteServlet + + + + /namespaces + org.eclipse.rdf4j.workbench.commands.NamespacesServlet + + + + /contexts + org.eclipse.rdf4j.workbench.commands.ContextsServlet + + + + /types + org.eclipse.rdf4j.workbench.commands.TypesServlet + + + + /explore + org.eclipse.rdf4j.workbench.commands.ExploreServlet + + + + /query + org.eclipse.rdf4j.workbench.commands.QueryServlet + + + + /saved-queries + org.eclipse.rdf4j.workbench.commands.SavedQueriesServlet + + + + /export + org.eclipse.rdf4j.workbench.commands.ExportServlet + + + + /add + org.eclipse.rdf4j.workbench.commands.AddServlet + + + /remove + org.eclipse.rdf4j.workbench.commands.RemoveServlet + + + + /clear + org.eclipse.rdf4j.workbench.commands.ClearServlet + + + + /update + org.eclipse.rdf4j.workbench.commands.UpdateServlet + + + + + + workbench + /repositories/* + + + + diff --git a/core/http/workbench/src/main/webapp/favicon.ico b/core/http/workbench/src/main/webapp/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..03e5432589bfb886cee343d3f7877c12b25d8584 GIT binary patch literal 894 zcmZQzU<5(|0R|u`!H~hsz#zuJz@P!dKp_SNAO?xUfG{@$0|-+9ychj9o{B(@bN{cr z^dAC#{rx}x?El=&|7~ae2P%VD0%BC7po*PP^&h??#7EV`LuoX8fI)$r9+1hd%8G=RNP8RP!Kd=`uN}V9?$%E zg(Ev!Bzq=HmK=6?Q@>wQPcOZquJ7SXOEx~cV>{OB1h}3*w`hiPD$CUmucZ&)s#vjL zm-&PQrK_HcrQEvMBBCZ4xpfqNF!Ydex|tKh%}-rVGhy2eHu27v^IRVEUet4*0D QfL1ejy85}Sb4q9e09`ywmjD0& literal 0 HcmV?d00001 diff --git a/core/http/workbench/src/main/webapp/images/affirmative.png b/core/http/workbench/src/main/webapp/images/affirmative.png new file mode 100644 index 0000000000000000000000000000000000000000..e250606d9ecc9fef1a63930cca7594c1808e3463 GIT binary patch literal 607 zcmV-l0-*hgP)WdKcYATuCMa(W;#FfcP9GBP?eGCDCZAS*C2FfjinReJyc00(qQO+^RO z1OgB-7AaV}`2YX_32;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yPFq^aw?)g93+^)i5Xf{t`iChDky{;3Zd1^qBi}5en8MV ztQ0Lt94+mGprxR@pmL_SG)APxalX#`)jNVkq@b(lIdB%|+}Ghg&vV1SF0n23eGUl4 zQ^VIyRd9N_!>rsgJj6cD71Os*+&JFd*%6f{59-JImf&GpS!6n$NJb{VJi(U&>C09R zk6#Yj=bEF3Uxvuj!Q=}heDyya?Qf<%&vS- zIZQWiDKU|XUyHx~mcbS_^Yg`8*-#hgC$nyF?E!VBdP>M@1R-dY2D*~5?}b`lD$y5t zvowJURyJEyB|}~0CS!k(@i99oFdl0QpWdNsDAys}co1vV3Q&h!u4tEZbvb}XHqXH* zyRjIL?%#V-(*-r##n*j4=Za2AQ&$3baH9eJ?)W)Y*+b7-s tC-E*#RCs8ZTFjPinp+HPE3N-u{RDx@pJr`);)DPI002ovPDHLkV1nLg0BisN literal 0 HcmV?d00001 diff --git a/core/http/workbench/src/main/webapp/images/bookmark.png b/core/http/workbench/src/main/webapp/images/bookmark.png new file mode 100644 index 0000000000000000000000000000000000000000..69d31f245092934a164ee6b789e88f859eeae2e8 GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`6FprVLn`8)1{~yNQWQvWtcd1x z=MGz>8quYip&ri2UuU!S!8(Q$C;xB=I&I>YpX8%vd~@y@r5*iIhb_xh7p0dsW_-OD zzl-tOt>l0QVonuTkFA`0!m?j#{enaXua&!HlWUqSd0AF79?1LfTln7_;qOh=2NyrE znY&`E9hX`187AJgHhWQprFW(TdB1f${NL<9<9lWE2U!ctq=1fN@O1TaS?83{1OT}I BO(OsR literal 0 HcmV?d00001 diff --git a/core/http/workbench/src/main/webapp/images/cancel.png b/core/http/workbench/src/main/webapp/images/cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..8fad9e425d0df0e6bfaf1032181eb1f8a97085b1 GIT binary patch literal 686 zcmV;f0#W^mP)gl6LP*ng5RfVdm*4qARH3w=H z$iGRh#`z(M6C(kTAPH9D0RQjTyjs1F!aU;??x9-!8u?6ubBUb@X-Bj4uq2SYLb8i|OXN3}AaP>pV~GdZ2e9{${j$VJT(PvVLb8oUWik4R0fiF? zt^n8svKrv?*mES?)!KjK-;8JyZ;J%U$Cp>Y-v1Q&g2=y@+H6|7C}}G4(2_DlZa0x% zNsP#YB)57Wz&@b&;VRirvUh3Z{FLo;l3rbE@ROwN$=crCH)FqPyCpen=`)FUA|vq) z$9Li!i(Rn~#NLS{vENJb{bX&=?!RoU#@VtxOY#zu+p>O+9oyd_*-E_s-v7t`5y+_| zsz*20kz^YC0)pc~3PA!a0Q?4EtqL=YaRGqq)!Najx`irCX1jI)iQ-&zOxsT+nJ#Nz zk{uag$LCRa1;`%&5CrweLl0t17LcS8&yu_tU=Cm>fC0d@s=8EF*Q+YEj6SMx7h1J^ UEtmmUi~s-t07*qoM6N<$g0~AoWdKcYAT}URYjhwoFfcP9FfckXFgh?eAS*C2Fffw<8#Vv{00(qQO+^RO z3I!GlA&Wf=qyPW_32;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yPN5KaT? z>K;8e8V!!w*&!<-a-k048AE{QsljA2@v^EtyI*sZnY&t>b9Otqq26)KPltN00;h~A zKuO7=ljRkfBkSD?zY zF?{v<+LMjA{{J4NGa!VBoT|d2<2cHomyW{=PISH)Kv%B|%>A~40G=y*AUis7?3?`%igxnaFeQvQ0Im@a`aO%x;7G!ltO?(FQm*PE0;mPbdv#iysd^WH^^+u(ZT=2-GWI9&LpqvJH$>W|&@ Z`~)c|L~VLIvZeq4002ovPDHLkV1mnzZ7=`; literal 0 HcmV?d00001 diff --git a/core/http/workbench/src/main/webapp/images/external.png b/core/http/workbench/src/main/webapp/images/external.png new file mode 100644 index 0000000000000000000000000000000000000000..f51d3b8bbd5c6da6df949fdcecbb13870a91979a GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;V{wqX6T`Z5GB1G~wg8_HR|bPz zg}}5=W(W8|(j`HD!3+-1ZlnP@oCO|{#S9GG!XV7ZFl&wkP>{XE)7O>#F3?Oz z74bV~i1GsM^MA5YqaV38WdKBJATux^Q)O@&l1qU%EbBxo5uSZ0`6poC!r6&bMa@1V8c%;iN38>C1FXaWgG+w_K|C7k zHy2j`!$5WG9$4iiy~DssR#`T9)Z5^Ox&h5F5t@oe?ZDjvf->Os(%7toqz9ehu(z?Y zxWYZs*40!6H37jb%zRgc+YmR-0crukK43OBF*gp&1WXGKmjmrx2NkF^%T0tM8WNG@ zvlGCFO-wSf@mVNq+ytDSbWb zJ+YC*!0@s)zogMyIAJ*nvS3#vI$DaWN#BE91`eCjySuKGe5SMDRW%9U*lJ8_W=9~X zK3|AZT?j~0!ARNUJOiDzml>=*b4zhK%C(I{hD$-1hJQ}0(ICMfJ@I}CxeWS%ic)9Mps*`ddWyfG6nbuvmi)Be0*~kuI^DplD?n)5{@%Zh WJ}STSwfcAf0000zg6 literal 0 HcmV?d00001 diff --git a/core/http/workbench/src/main/webapp/images/productgroup.png b/core/http/workbench/src/main/webapp/images/productgroup.png new file mode 100644 index 0000000000000000000000000000000000000000..9b6d961caeb938676bc732af207aad6add6eee9e GIT binary patch literal 6236 zcmV-i7^CNjP)WM@mR=mYqb6Y~31@RUKOuWSb6K`?A#9JIN@fHV6yv17_F!2@#OuWSb6K`?A z#9JIN@fHV6yv19Lme`z|JRVP+Q-9%hAsf(%7f6`M@uH`pXQF4Jx0c`h=x5Pu(S7Lk z=s|!j@)u%k5<%>yQ6m|SbqNb=hnM-?@smm{lT6+dsdGaF`_&*HT9&|>#Zbk@LbdM z>C?jr2?;im*=e!#Z~d;8Owk?=hohhTUGLHB{O(56yw6Q@%rTtfJL#L(Wj<7tUg$kU zKp_#XDQLe4m`ZaB{Un7BI{q0mW<)}v(1p;UP*0;*p;v>3t%T1#_nh8)K03}85_$&& zj2Fix8TWQV?|1Cju^z9z_FB&`zWAcc$&)8j$iDUZv-x$@_WD1dbDA zI!|pf1{J3DxN+mI+rNK*b}ZB0p+kq7E?v5u96o$_(S!*TwzhBIKGLyc$GVqZddWX^ z>ePtRx&Hd=UFm3R)20o1dFZB_ZrTb(Eb899d!%*i*7dVz&khlMCY_R!l5D5KxHZhp z%FD|u`S|0H-^14mv4R%`Fl}gA0G8al@4kEF;lqbBF1ze9t5>gH78YR(4pzpht*vcc zRaG@&<;s;ki;9XC*Q2doy*dHH4e=gRu+HypR>Wx;oQ$AgMQdX|tH9L11A##FHW+K{c2PPeKa>}|mXniXH8nL+@kgO=xR`)xN6<{1IB{@gWo5?T!Go$@`m}|G@q7D0g9iNvtk4J7UVH6cOuX@_r=E(KF2S@ev0Q?A zztgp_o7P3Gg41Ft&`jX4k?Br%WLh$pz@HPT2c00n0xM#*ZQIt?+Vu2vn?Bc0K2%p% zTW8Lkp%UeTC-=>rJ9jyHDaHsZ9RN3&m6c^bPkIz4EVMl@D4qrDZPTf%t0Txq0XzZl z@QW2IR+Rtr(@#-4;6adJp#oERIhR(gT19!I>nFHLfA8MCsTxvTOqbLK+LEzv-@Yzz zHP+>qUv3dJm|&!|v@~2(Qxn025-`~WP88fE_=SHw71R#a3_n+`nt?6bcUmq4${9!cFKV9TR{~i)30W1)N$Q(-KizDIB;O3OWKM3XA26z+xow9x4)r z4?gsP@c(t^&YhowPN|Nmu9f%E$^bYv9X^A3L_jx@mX1Ou?aa)~tG8|2b`+gfq1ps9 z=Y!ahV_9%ryf?ZAQ$YzD06IYum5Um~BrRLEESE?YCfN*wPi_EW8F`<|&(E*B`R1F4 zzy#Y&;N)Os`T{WfaQ*lzue`#bElI}ph=v5jv?hvAPL$xRNv=g`nYdUn!?sWtELh-? ztRUHVE-1mGotbFdqzsd1&NqItd{;WbDO09I+yJO%{@}rbAq1inVk0wR3lbujTokz(gD9y3JVMW1%Nq*`S^4W3MXp_!xGPWy7C|UoI3dO|T?gXgY~_E@01|Jt2UFY2P07ACDeAT7`SMqUBIy zcn@NntS`U(l37)e2#BVzy&#+uJ|l~w%WEqFRSja6;hR5yz8?&*xdYI7WZq0Cv*o#T zq1PyBDAUFo0K`rm4S~0cF@8wsu%`%6I6gDIntAi)*_ocH(G<4EZE!;o0m2USvTwir zHV6y*?_>m(idF*r;MiTI6yY=DFMg5^t+YYs*RQ|+x(U3V(Wz6X6uK@dA{4f*WT^+- zfJb^l=algLxFh=tOBQ!rvagE=7-)Eyla}DtqWP4GZAYM63U`!!>#esoV8S-2=-P`d`b-%QGK& zG_g7+W-Dt5%2N+Bfz-Oq1P&aGP z3QPL@Bl_MJuk>mTucncmT1G!BT3rtfA}|uEEo7qjVT}WlM5Aq205>*L;~coQN?4&? zFTVKV6~)EHZ3#&BEnBt>{OF^P3c_MyH%t%ColOWU#&`4m=OQliQB}&uE86#;7V#If( zlL)Y-@;CBPV-(CeQRt*9V0ex5;dRbmGrUW-HDE4Kvkd`5#7H-3^F7YOo5T0p7Kwsl zU`A##b%Zd7!_;OX{;|PGz%@1!ht_2P-o0>rpFm*65E$c&Tx!@|cilA-8k{j?$Pf!D ztDREPk29-aM{3(20r#X?vt}*E{Rd@U_V@%UfMf%PDKNk?67y_x!woms%;xy)5LOQ8 zKLo&hjPZ9VU`&msVmLBAN-GU?lBw-nKLtq;3csVlCfBL}bpfEpXi>gv`Yv%+k{M5_ zOc)$piV6c#j*8lKKiFe8k3C;&^5!nBma zXTyC38#it&lZq*0jSRS#-pD#KuDtR}3n@FTiB(osW@l=!bY4C$seKLt(0k!(R$)GS zC8cekd1ov}cLDmT7(bQZg@y4$Ac=T3fqK>wZdGIn#{CjIbwTe48tt{7 z!|?#ju)%|^L5&!On%vP0R@DWtiwmYej>A3nWib^oOve8G`}0Vf=`F`W<`Ob8 zuRjzX*<%4lt(gMMHC_;FM@4~^@!o#>?IS+;;Dg}m)vF_HusUb)`{8%refM**Hi3%{ z7)}4QyMaMV_6jN&KOYqs@8Kc^ECKFhDdTH#fJ9W@E5InG677RT`=NcqW~K z;5F8O02ZHQ1PFb$RO7k-1jsU&`a|eRuv*;_pyq&SReVN;#JSOg&z?P-W8-M5XWCGoXXzuoH+qV4-K!maIGprc%9s}5E%)ZvFS<{Y!Bw#oO zG?yIQgDhqT?r)3Cs}Ia_9iQiX>Hc7i?DQM4O~eGPR%T`VAHVzVyFCD3gujutq4fzS zuQUy&peZB>C=KHkzWw&wg^L$29zeILRd7~=vChb6pM6#@wU5)$MHxwixhLkd#=L$m z1vFfhrtsE)0Rt>#i?+)iJ9e!732RI%*JQexo1_D@Ekh zUU9`0b|Fryw!Cgc{0U%ukSQ;pC2ax@f{NUB+ie-3c_p$cR#<6)($w0~wO~&4ooz}= zN<4I7%48!rC+JRJef8Cr2JYvI*UT73tE;pkszjVOHJVlm^N%3#t{06imby=dX=zp9 zv9=`ix^D2svg&l>w5noFqWe<(mgR9VDEzsO)j%9_6wA;)KJi0-s zn}mj+j_A%cf2WDYJX*m@U9oiOQd{deFEWj;#NjfNV4*x_OrYIuerD<3jSrgLsDKDe zrqSI0q1EAc2H_7r_#lj4E#s%3Sd5!8WlF$V(${LR+gQ!bUUeT$Txj@{Pd*6HW zSk92R#6XJx#!bUw5|)71EzWW747<@+P_eu1{mAyeZGH<13ZjB1J+0+X%V+@-e=~Cl z0AR$-;9?2L)b?1X4OMd~AdGDb2ta8>il2^Wyy9{_08|YCvqJ!L#%)aJ{#h)m?mTkg zmS~Xv(W6I0hzskaT7A|y3&Y=j6)V>=br=n>`01vds=azoER(L*C6%!7v~=9% zWwyk4hKw|0Dve(x2uyTKMPmU%*QuFDEDOnd_<7{Wkq|Nx3ZV$uNiW1LxqOxu5Sd)+ zfddEVlIp4LurRLH>|BbaE}UzQb)SNYR+cf7xWKocSJf}LM5${Gf0fJj`JNv(rW~b2#EVK-^0ovtU8@b zH$#`jy)-$c$k?IIsUYh1%w79)@f&ORxTVxeS9iLl)>1AO<tM372+3jqm8@4N0uyE(hV&W8tz}ee*JNLXJ+C<=8)=i z0d9a*0mRDk%-V@$gb}Hro~04hmOb)Wuz3%=&OIk@7%QOf%N>QdGqGox@gg&f2*jd_}l2wqdQ9}K4Oj^ z3lOFN+?a2c4meM#jo7>BH{N(-IrvgR{wR;~^Yc6Ffu;HL=X=aeOwFv+O&jimnO!hU_IB;N=04B?%!)FUyv1ws2v6SAudwcJ__uc_m zY@e^b`l6by<2F!{TD;ma) z8&^yr^LeJP5EdnR`mML#;%->e!=ra&;GX3m`H<0O&JWpE>rg)G)4 z2%0Thw)myG=`%H03vzTT06{PK`C9z#1+5;SmCR?!Bx)Bd134euv}scq%;QP3odC>W znscPA-ch4QT~0wETWK?W`t*DNHd>b7xpQYw;;dR`RL-FKT(uIFw z2@@uiB5P^{U{Y0>uypMY9z4jZVToHt#*T4QF~=JwPMjFQvq=C^I`^Y!sTr{Ipw{Ni zn;T>!wpJBh-I?>1nM(>7OoWp=g$0%1@7{W*wNs}~+#PO9!4DcV$ligbcC(_ob?esP zv17-W#vPKK+;mf5dMFttyThlSetP2@Z@gg(iA$GO;ol z3Sd1#;i!&Z+Ve1E$T#17^YsG{JkXiP5-1Q|GzCWhQ5$%4;LxE%VFY*#FpkJ^!g>Xa z7RD$*z8(QhY8XF$d@Hyjn^8P!K={uz#2<1mqP9*G5&xBNnN{kZ4W3=M*!jgcvXk>`Bgb+v5cbt*i$;{q)ljw@NVuws7G>KWH`FamO8*V6c}AVl83W zvSt1?Yu5P0j8~e)r{&9+ZvbPG#*Q7^8Jd`=n{@ny=?^bnyg0CO1#8Ngr z|NQf|HKglQFC(9IybfVRuZxM->-G5FIBC+P6j(a@x&)%pQ}|i}z_l`N`ca4s+^Hm3 zWA_g~{4f{KQ0ONfee}^3##p4|v~=VPcpcfeabpntZiKt7mvyjWd|LQt&*!nn9!nWI zbZB%w$B!TX({BZw*V8m71vC62C&Hs+-Q`eG9|)^6VvS@5bI_g;%hFO!q*d82^${Nd zgH)I2O4^MWG2%s(?(23{L*xhaZAsS$HP(AFQz;2n@&}a0U&X zWDYbf9YHf4Lh;CRdZu;1Fu3%YXP#-8J9n;Ep5segBjwmaSS--z0A6^eXGO z~iy<{cawD0w4HJG>>I?n=zlV z=4|y`ESIDw&Pyfm+KViRXDr&wd69tl*yD1#i*BIt@y8#JnCCdm7(vqF24Tpt;^N}V zWZ{0H!39@Aivp}^@G$qHMT_*BPb!%m5HDqmPY;M-DrFwk-0(AwXxcR!se-nWajN8d zbFSBlrk|8F-eVc3@G;NGtFOKq5LdiGK$a${uutZ#`#VY}%V80;LLCt0tCIWb^u20P z;`7euQd^im>?}*cE>#vBGHN0=VF)<-09=o4VGxwQ$kTE>GeSR&dkDZ!L{NzWKHCL8 z`Q(!!=i86wtF}@IGv80LK|OWq)Q|~K=c~4ETMll4ulcf_`Q7csfAhU@w~b7*_G8{} zW=!VWm*!lZ8=~ji)YUd;&K&DfS{Tbk3-n-d%w6kPue<6Vinhs?fBjP*BJQTU;@NBuJbiqJ(2IWf8_QyCFkqh=W`XmTeT z+i1}&gi$@~EW&87c|OHFD-%mVvEF-j`*$7YGdhMjmXooLeI47HIsXrh^TmF1j?QAB z^Z(np9o#Z$n{$fgIu%&wTl+s#4D)B&`LdL~R=l-%yAVs%(tz;@NLT>Lbz~t&q?#LV zalpjeUj;CU|JMZL?XTV9|ED+J;(&>_IAG%KpQQbd00RJAYTENRIW!;u0000WdKcSATc)}L3L*!GB7YTATcyLFgQ9hG9W83F)%O{3H|l}000McNliru z(*hU)2LoW4MSB1M010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00j9- zL_t(|+Qn5{h*eb>{`T!$=FFKh7e||zNz=wJf z8bJ}mw|bkPAWI3n6-byfDI{3USX!nzb8d5H&ShWLW%sRp9MR6yTeRS3t-aS?-}nFD z|L=bR|M9RE7NesdKJL1DNNZhC3I)FEkrD-CTE~2L3y$OVSe93?ZLeTiZlPAIU-$j! zsN=*(!m#h#0|#Cb|46WJ-=Ud8VPNU-@WU7!%)zp3#BnN_2@0)&Fq9BNa@LSiajj9Q z%;Ng>85E0^8uyQBZ6Edh>{ka5ZYddDcYz?E@5biMn=m~cpxNv}I<1h+`Xp%sMo~;q zhh`_FS}VSb;5fY)7)T+L8R#vSD)x(bI&BfiO}y^vQj8?FTCGb2 z^^*vMFkb6BX2pa7G0iq^@+=Zt81}-V5dn3ks4L^Zu`GJiCZ!7W+z^|CR+5Xh#kauP z7AI!iI{P<*RuJR0Pn$S&W*#ZWqH&YECaK0-DRq)mBc)bEB!NXhhu%A!U9zUky6p)% zBpS>DZ?1N+>u?zdzAj_Wa|Jxw*9|vT^g=;f1h8W$N5LmSL&hit4l1FGYUE&+$*<8W zGL2R8r%r-dAJ{VF;@FOUy!y!uHtxNG?avAnZ=~>NgCL>JZ!EL~Lt_=e<57=VczkB= zl5kBfY=wugNCfrJ!rR9~jI4-o>B$q+MgkqEjig&}VqyT6aIiBgSi$m8Vi z9xhD&fPRAXyAnA^A~t1eq%vh2wIvg>-J5&~6m=FYsX7TFZa$g!;od9o?zq6I%Np-L z(GM$APe9n`a4m3ImPTt26-}Ag469ZK6N4Vs7&97B7vd3cJp=2DN~-*oKf|70t0B_eld$~(LydVQq>m8K_Ei*_9XlQYk6#) zhy9lrwhpj5E6_)odM$w-&IJV2Tp(sg70sB@>!g*0{OgTeCHAfk0>?>jJ$-uO=$bXF z`i!SBPwX1b;(X(3qOa!fui1;Fijy*(rz28X$y#w1BBF_QOOZimFWS3z`xzj&eti6V ziP0cnQtE-ioUbq+Xf${yH2Ca?ihImSWbO!cvsZ;|(c-2_l0=;ZW{i%$c%JpNZen6$ z+IV8RqXB6Hshcg^G(GcPCLWu6q1l{6t5u}^!RJYH_g(F{GH)L{cYd_e_bVsXu6^d7 zvuDQ>Agv|Z7msf|jBQ)jq-WdKcSATc)}L3L*!GB7YTATcyLFgQ9hG9W83F)%O{3H|l}000McNliru z(+Cp~A`F;--s%7V010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00b;a zL_t(|+OKlz4IqEQG@Zx}UZES4}ikDH7c^?+^y+zdlrFQvr9#LPw4 z73U2jbK%5^{Ud84=U@Vm~=eTSCf>B|Y~>P)n?wV+t^Fg&agU`$1k&%%%)2tcU_Jb-1*p;WS9+cu)e zW67jwEtM8p2x4`D7+2t&h*Au?E~q+QBVxC0Y^b55C(2_f+W{);q^4$JF|!lZ~cz9U)+RT zK7~0M!<4IG*4H3N1z3zqj{`NN#Gt!EQl3(S)d_}XBD{LW!TS%_;o#1D@y>Z0WAng< zx&T`mLS&2p4Kay&s@_ySQqqMXJUDb7c~X6;8o`5Ug+2F6w4E&A&7C?DC!?i>X%{2-QbZre4 zB9I{@8BUTPN;L???s=${D2b*ksY6(2>iGz>!WUxT{d&#M#Eio`jhdqM? zEUkuCQ^rXdc?LxM$nBb?q$I3d<^AL|W)X1<6te59p^ zI>$lMcPoXB&Hs(d)d(!he>eNOO6~2E|!@$5#;ChUl${-_Z71V=dNS>hd z$k7YbKFU4HiNp#8E1cZb)&BX^l>PG6+;!I}8^{SUvB*%c8KxXy)?ru>42y(S@*=vP z0UT-{u2*g$YcN_ljvagcY)8je&)IhF?5r&3; zrL^*#+qvaf46DR}10OsTkL%ye&K4J`ndNuvXnrA^%@P@ZTGtc#{{9cg={L0+#;OEM zqrd;g{&d>t8yqZmR@r{|@M~YJWu3N`p9s8MW#9Jgjaawt?($UMsZ&3wwXD6Zg08Nv zn*gS{4SV-K^PlfWj~>F-t#?(%`FtMT-QBmu(r-sFG&EFMSdQJh88Vq|NG5AWdKBJATc%|L3L*!GB7YTATcvKH8(mnFd!>1F)%REhL}eH000McNliru z(*hb7Hw>M^c~AfV010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00K2h zL_t(|+NF|9NK{c6$Ny)%o+<&ql*F};V>5pg@#wx?rGe*b2}s* zh-pAFE>UcxC#p+{x?8vJe9Z;$%$1L!(blq>-Hmnboiil`gB2RKQ{uOd`mc zIfw(p1rjq+vUU?or&62UqtToIQ%Q@{DwWPyCOmE`8JmzX9LVlkDR`hNG8kiGUJGh; za#);^AnFWB#YRfA-98KEFzDc+MS@?R^bL&X1)#{=p}y^n$)<Dk#T!?eWU`wyd+uif--qlxCD2h+f~8$*9+1fj$U_6(jwAme*IM#iMqRBiun2W925v48q$582M+Hj3f!NP;?eGcEi9&AoY@IncmBRp P00000NkvXXu0mjfy^BaS literal 0 HcmV?d00001 diff --git a/core/http/workbench/src/main/webapp/locale/messages.xsl b/core/http/workbench/src/main/webapp/locale/messages.xsl new file mode 100644 index 00000000000..fafafb5fcb5 --- /dev/null +++ b/core/http/workbench/src/main/webapp/locale/messages.xsl @@ -0,0 +1,224 @@ + + + + + RDF4J Workbench + System Information + + Detail System Information + + + List of Repositories + + Summary + Explore + + Namespaces In Repository + + Contexts In Repository + Types In Repository + Query Repository + Saved Queries + Query Result + Export Repository + Execute SPARQL Update on Repository + Add RDF + Remove Statements + Clear Repository + Change Server + Current Selections + New Repository + + Delete Repository + + + Repository Location + + Repository Size + Bad Request + Super Classes + Sub Classes + Individuals + Properties + Domain + Range + Super Properties + Sub Properties + + + RDF4J Workbench + Repositories + System + Information + + Detail Information + + Summary + Explore + Namespaces + Contexts + Types + Query + Rule Query + Matcher Query (Optional) + Saved Queries + Export + Modify + Update + SPARQL Update + Add + Remove + Delete + Create + Next + Previous + Cancel + Show + Clear + Execute + Change Server + Change + RDF4J Server + User (optional) + Password (optional) + Repository + Download + Download format + i.e. http://localhost:8080/rdf4j-server + New repository + + Delete repository + + Show data types & language tags + + + + Copyright © 2015 Eclipse RDF4J Contributors, Aduna, and others + + Yes + No + None + All + Readable + Writeable + + + Base URI + + WARNING: Clearing the repository will remove all statements. + This operation cannot be undone. + + + WARNING: Specifying only a context will remove all statements belonging to that context. + This operation cannot be undone. + + + WARNING: Modifying the SYSTEM repository directly is not + advised. + + Clear Context(s) + Context + Data format + + Include inferred statements + + Save privately (do not share) + Save query + Object + Predicate + Action Options + Actions + Query Language + Query + Update + Subject + + Select the file containing the RDF data you wish to upload + + RDF Data File + + Enter the RDF data you wish to upload + + RDF Content + + Location of the RDF data you wish to upload + + RDF Data URL + + Please specify subject, predicate, object and/or context of the + statements that should be removed. Empty fields match with any + subject, predicate, object or context. URIs, bNodes and literals should + be entered using the N-Triples encoding. Example values in + N-Triples encoding are: + + Results per page + Results offset + 10 + 50 + 100 + 200 + + The results shown maybe truncated. + + Prefix + Namespace + Type + ID + Title + Persist + Sync delay + Triple indexes + + RDF4J Server locations + + + Remote repository ID + + SPARQL query endpoint URL + SPARQL update endpoint URL (optional) + Federation members + Distinct + Read-only + Member type + JDBC Driver + Host + Port + Database + + Connection properties + + User Name + Password + + Maximum number of triple tables + + Resource + + + + + Application Information + + Application Name + Version + Data Directory + Java Runtime + Maximum + Memory + Used + Operating System + Process User + + Runtime Information + + + System and Environment Properties + + Location + Number of Statements + Number of Labeled Contexts + Namespaces + Contexts + + diff --git a/core/http/workbench/src/main/webapp/scripts/add.js b/core/http/workbench/src/main/webapp/scripts/add.js new file mode 100644 index 00000000000..b584048de30 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/add.js @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +var workbench; +(function (workbench) { + var add; + (function (add) { + function handleFormatSelection(selected) { + if (selected == 'application/x-trig' || selected == 'application/trix' + || selected == 'text/x-nquads') { + $('#useForContext').prop('checked', false); + $('#context').val('').prop('readonly', false); + } + } + add.handleFormatSelection = handleFormatSelection; + function setContextFromBaseURI() { + var baseURI = $('#baseURI').val(); + $('#context').val(baseURI == '' ? '' : '<' + baseURI + '>'); + } + function handleBaseURIUse() { + if ($('#useForContext').prop('checked')) { + setContextFromBaseURI(); + } + } + add.handleBaseURIUse = handleBaseURIUse; + function enabledInput(selected) { + var istext = (selected == 'text'); + $('#text').prop('disabled', !istext); + var contentType = $('#Content-Type'); + var firstType = contentType.find('option:first'); + firstType.prop('disabled', true); + $('#source-' + selected).prop('checked', true); + var isfile = (selected == 'file'); + var file = $('#file'); + file.prop('disabled', !isfile); + var isurl = (selected == 'url'); + var url = $('#url'); + url.prop('disabled', !isurl); + if (istext) { + var turtle = contentType.find("option[value='application/x-turtle']"); + if (turtle.length == 0) { + turtle = contentType.find("option[value='text/turtle']"); + } + if (turtle.length > 0) { + turtle.prop('selected', true); + } + } + else { + firstType.prop('selected', true); + var baseURI = $('#baseURI'); + var checked = $('#useForContext').prop('checked'); + if (isfile) { + baseURI.val(file.val() == '' ? '' : encodeURI('file://' + + file.val().replace(/\\/g, '/'))); + if (checked) { + setContextFromBaseURI(); + } + } + else if (isurl) { + baseURI.val(url.val()); + if (checked) { + setContextFromBaseURI(); + } + } + } + } + add.enabledInput = enabledInput; + })(add = workbench.add || (workbench.add = {})); +})(workbench || (workbench = {})); +//# sourceMappingURL=add.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/add.js.map b/core/http/workbench/src/main/webapp/scripts/add.js.map new file mode 100644 index 00000000000..b59f3322566 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/add.js.map @@ -0,0 +1 @@ +{"version":3,"file":"add.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["add.ts"],"names":["workbench","workbench.add","workbench.add.handleFormatSelection","workbench.add.setContextFromBaseURI","workbench.add.handleBaseURIUse","workbench.add.enabledInput"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AAEpC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,IAAO,SAAS,CAiEf;AAjED,WAAO,SAAS,EAAC,CAAC;IAEdA,IAAcA,GAAGA,CA8DhBA;IA9DDA,WAAcA,GAAGA,EAACA,CAACA;QAEfC,+BAAsCA,QAAgBA;YAClDC,EAAEA,CAACA,CAACA,QAAQA,IAAIA,oBAAoBA,IAAIA,QAAQA,IAAIA,kBAAkBA;mBAC/DA,QAAQA,IAAIA,eAAeA,CAACA,CAACA,CAACA;gBACjCA,CAACA,CAACA,gBAAgBA,CAACA,CAACA,IAAIA,CAACA,SAASA,EAAEA,KAAKA,CAACA,CAACA;gBAC3CA,CAACA,CAACA,UAAUA,CAACA,CAACA,GAAGA,CAACA,EAAEA,CAACA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,KAAKA,CAACA,CAACA;YAClDA,CAACA;QACLA,CAACA;QANeD,yBAAqBA,wBAMpCA,CAAAA;QAEDA;YACIE,IAAIA,OAAOA,GAAGA,CAACA,CAACA,UAAUA,CAACA,CAACA,GAAGA,EAAEA,CAACA;YAClCA,CAACA,CAACA,UAAUA,CAACA,CAACA,GAAGA,CAACA,OAAOA,IAAIA,EAAEA,GAAGA,EAAEA,GAAGA,GAAGA,GAAGA,OAAOA,GAAGA,GAAGA,CAACA,CAACA;QAChEA,CAACA;QAEDF;YACIG,EAAEA,CAACA,CAACA,CAACA,CAACA,gBAAgBA,CAACA,CAACA,IAAIA,CAACA,SAASA,CAACA,CAACA,CAACA,CAACA;gBACtCA,qBAAqBA,EAAEA,CAACA;YAC5BA,CAACA;QACLA,CAACA;QAJeH,oBAAgBA,mBAI/BA,CAAAA;QAEDA,sBAA6BA,QAAgBA;YACzCI,IAAIA,MAAMA,GAAGA,CAACA,QAAQA,IAAIA,MAAMA,CAACA,CAACA;YAClCA,CAACA,CAACA,OAAOA,CAACA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,CAACA,MAAMA,CAACA,CAACA;YACrCA,IAAIA,WAAWA,GAAGA,CAACA,CAACA,eAAeA,CAACA,CAACA;YACrCA,IAAIA,SAASA,GAAGA,WAAWA,CAACA,IAAIA,CAACA,cAAcA,CAACA,CAACA;YACjDA,SAASA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,IAAIA,CAACA,CAACA;YACjCA,CAACA,CAACA,UAAUA,GAAGA,QAAQA,CAACA,CAACA,IAAIA,CAACA,SAASA,EAAEA,IAAIA,CAACA,CAACA;YAC/CA,IAAIA,MAAMA,GAAGA,CAACA,QAAQA,IAAIA,MAAMA,CAACA,CAACA;YAClCA,IAAIA,IAAIA,GAAGA,CAACA,CAACA,OAAOA,CAACA,CAACA;YACtBA,IAAIA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,CAACA,MAAMA,CAACA,CAACA;YAC/BA,IAAIA,KAAKA,GAAGA,CAACA,QAAQA,IAAIA,KAAKA,CAACA,CAACA;YAChCA,IAAIA,GAAGA,GAAGA,CAACA,CAACA,MAAMA,CAACA,CAACA;YACpBA,GAAGA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,CAACA,KAAKA,CAACA,CAACA;YAC7BA,EAAEA,CAACA,CAACA,MAAMA,CAACA,CAACA,CAACA;gBACTA,IAAIA,MAAMA,GAAGA,WAAWA,CAACA,IAAIA,CAACA,sCAAsCA,CAACA,CAACA;gBACtEA,EAAEA,CAACA,CAACA,MAAMA,CAACA,MAAMA,IAAIA,CAACA,CAACA,CAACA,CAACA;oBACrBA,MAAMA,GAAGA,WAAWA,CAACA,IAAIA,CAACA,6BAA6BA,CAACA,CAACA;gBAC7DA,CAACA;gBACDA,EAAEA,CAACA,CAACA,MAAMA,CAACA,MAAMA,GAAGA,CAACA,CAACA,CAACA,CAACA;oBACpBA,MAAMA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,IAAIA,CAACA,CAACA;gBAClCA,CAACA;YACLA,CAACA;YACDA,IAAIA,CAACA,CAACA;gBACFA,SAASA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,IAAIA,CAACA,CAACA;gBACjCA,IAAIA,OAAOA,GAAGA,CAACA,CAACA,UAAUA,CAACA,CAACA;gBAC5BA,IAAIA,OAAOA,GAAGA,CAACA,CAACA,gBAAgBA,CAACA,CAACA,IAAIA,CAACA,SAASA,CAACA,CAACA;gBAClDA,EAAEA,CAACA,CAACA,MAAMA,CAACA,CAACA,CAACA;oBACTA,OAAOA,CAACA,GAAGA,CAACA,IAAIA,CAACA,GAAGA,EAAEA,IAAIA,EAAEA,GAAGA,EAAEA,GAAGA,SAASA,CAACA,SAASA;0BACjDA,IAAIA,CAACA,GAAGA,EAAEA,CAACA,OAAOA,CAACA,KAAKA,EAAEA,GAAGA,CAACA,CAACA,CAACA,CAACA;oBACvCA,EAAEA,CAACA,CAACA,OAAOA,CAACA,CAACA,CAACA;wBACVA,qBAAqBA,EAAEA,CAACA;oBAC5BA,CAACA;gBACLA,CAACA;gBACDA,IAAIA,CAACA,EAAEA,CAACA,CAACA,KAAKA,CAACA,CAACA,CAACA;oBACbA,OAAOA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,EAAEA,CAACA,CAACA;oBACvBA,EAAEA,CAACA,CAACA,OAAOA,CAACA,CAACA,CAACA;wBACVA,qBAAqBA,EAAEA,CAACA;oBAC5BA,CAACA;gBACLA,CAACA;YACLA,CAACA;QACLA,CAACA;QAxCeJ,gBAAYA,eAwC3BA,CAAAA;IACLA,CAACA,EA9DaD,GAAGA,GAAHA,aAAGA,KAAHA,aAAGA,QA8DhBA;AACLA,CAACA,EAjEM,SAAS,KAAT,SAAS,QAiEf"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/cookies.html b/core/http/workbench/src/main/webapp/scripts/cookies.html new file mode 100644 index 00000000000..6bfc7988e12 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/cookies.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/create-federate.js b/core/http/workbench/src/main/webapp/scripts/create-federate.js new file mode 100644 index 00000000000..436e22407c7 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/create-federate.js @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +workbench.addLoad(function createFederatePageLoaded() { + function respondToFormState() { + var memberID = $('input.memberID'); + var enoughMembers = memberID.filter(':checked').length >= 2; + if (enoughMembers) { + $('#create-feedback').hide(); + } + else { + $('#create-feedback').show(); + } + var fedID = $('#id').val(); + var validID = /.+/.test(fedID); + var disable = !(validID && enoughMembers); + var matchExisting = false; + // test that fedID not equal any existing id + memberID.each(function () { + if (fedID == $(this).attr('value')) { + disable = true; + matchExisting = true; + return false; + } + }); + var recurseMessage = $('#recurse-message'); + if (matchExisting) { + recurseMessage.show(); + } + else { + recurseMessage.hide(); + } + $('input#create').prop('disabled', disable); + } + /** + * Calls another function with a delay of 0 msec. (Workaround for annoying + * browser behavior.) + */ + function timeoutRespond() { + setTimeout(respondToFormState, 0); + } + respondToFormState(); + $('input.memberID').on('change', respondToFormState); + $("input[name='type']").on('change', respondToFormState); + $('#id').off().on('keydown paste cut', timeoutRespond); +}); +//# sourceMappingURL=create-federate.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/create-federate.js.map b/core/http/workbench/src/main/webapp/scripts/create-federate.js.map new file mode 100644 index 00000000000..4d4d81194c4 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/create-federate.js.map @@ -0,0 +1 @@ +{"version":3,"file":"create-federate.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["create-federate.ts"],"names":["createFederatePageLoaded","createFederatePageLoaded.respondToFormState","createFederatePageLoaded.timeoutRespond"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AAEpC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,SAAS,CAAC,OAAO,CAAC;IACdA;QACCC,IAAIA,QAAQA,GAAGA,CAACA,CAACA,gBAAgBA,CAACA,CAACA;QACnCA,IAAIA,aAAaA,GAAGA,QAAQA,CAACA,MAAMA,CAACA,UAAUA,CAACA,CAACA,MAAMA,IAAIA,CAACA,CAACA;QAC5DA,EAAEA,CAACA,CAACA,aAAaA,CAACA,CAACA,CAACA;YACnBA,CAACA,CAACA,kBAAkBA,CAACA,CAACA,IAAIA,EAAEA,CAACA;QAC9BA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACPA,CAACA,CAACA,kBAAkBA,CAACA,CAACA,IAAIA,EAAEA,CAACA;QAC9BA,CAACA;QACDA,IAAIA,KAAKA,GAAGA,CAACA,CAACA,KAAKA,CAACA,CAACA,GAAGA,EAAEA,CAACA;QAC3BA,IAAIA,OAAOA,GAAGA,IAAIA,CAACA,IAAIA,CAACA,KAAKA,CAACA,CAACA;QAC/BA,IAAIA,OAAOA,GAAGA,CAACA,CAACA,OAAOA,IAAIA,aAAaA,CAACA,CAACA;QAC1CA,IAAIA,aAAaA,GAAGA,KAAKA,CAACA;QAE1BA,4CAA4CA;QAC5CA,QAAQA,CAACA,IAAIA,CAACA;YACb,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACpC,OAAO,GAAG,IAAI,CAAC;gBACf,aAAa,GAAG,IAAI,CAAC;gBACrB,MAAM,CAAC,KAAK,CAAC;YACd,CAAC;QACF,CAAC,CAACA,CAACA;QACHA,IAAIA,cAAcA,GAAGA,CAACA,CAACA,kBAAkBA,CAACA,CAACA;QAC3CA,EAAEA,CAACA,CAACA,aAAaA,CAACA,CAACA,CAACA;YACnBA,cAAcA,CAACA,IAAIA,EAAEA,CAACA;QACvBA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACPA,cAAcA,CAACA,IAAIA,EAAEA,CAACA;QACvBA,CAACA;QACDA,CAACA,CAACA,cAAcA,CAACA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,OAAOA,CAACA,CAACA;IAC7CA,CAACA;IAEDD;;;OAGGA;IACHA;QACCE,UAAUA,CAACA,kBAAkBA,EAAEA,CAACA,CAACA,CAACA;IACnCA,CAACA;IAEJF,kBAAkBA,EAAEA,CAACA;IACrBA,CAACA,CAACA,gBAAgBA,CAACA,CAACA,EAAEA,CAACA,QAAQA,EAAEA,kBAAkBA,CAACA,CAACA;IACrDA,CAACA,CAACA,oBAAoBA,CAACA,CAACA,EAAEA,CAACA,QAAQA,EAAEA,kBAAkBA,CAACA,CAACA;IACzDA,CAACA,CAACA,KAAKA,CAACA,CAACA,GAAGA,EAAEA,CAACA,EAAEA,CAACA,mBAAmBA,EAAEA,cAAcA,CAACA,CAACA;AACxDA,CAACA,CAAC,CAAC"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/create.js b/core/http/workbench/src/main/webapp/scripts/create.js new file mode 100644 index 00000000000..b19f12f2174 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/create.js @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +var workbench; +(function (workbench) { + var create; + (function (create) { + create.id = $('#id'); + })(create = workbench.create || (workbench.create = {})); +})(workbench || (workbench = {})); +/** + * Invoked by the "Create" button on the form for all but + * create-federate.xsl. Checks with the InfoServlet for the user-provided id + * for the existence of the id already, giving a chance to back out if it + * does. Depends on the current behavior of getting a failure response (500 + * Internal Server Error at present), when the ID does not exist. + */ +function checkOverwrite() { + var submit = false; + $.ajax({ + url: '../' + workbench.create.id.val() + '/info', + async: false, + success: function () { + submit = confirm('WARNING: You are about to overwrite the ' + + 'configuration of an existing repository!'); + }, + statusCode: { + 500: function () { + submit = true; + } + } + }); + if (submit) { + $("form[action='create']").submit(); + } +} +workbench.addLoad(function createPageLoaded() { + /** + * Disables the create button if the id field doesn't have any text. + */ + function disableCreateIfEmptyId() { + $('input#create').prop('disabled', !(/.+/.test($('#id').val()))); + } + // Populate parameters + var elements = workbench.getQueryStringElements(); + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + var value = decodeURIComponent(pair[1]).replace(/\+/g, ' '); + if (pair[0] == 'id') { + workbench.create.id.val(value); + } + if (pair[0] == 'title') { + $('#title').val(value); + } + } + disableCreateIfEmptyId(); + // Calls another function with a delay of 0 msec. (Workaround for + // annoying browser behavior.) + $('#id').on('keydown paste cut', function () { + setTimeout(disableCreateIfEmptyId, 0); + }); +}); +//# sourceMappingURL=create.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/create.js.map b/core/http/workbench/src/main/webapp/scripts/create.js.map new file mode 100644 index 00000000000..d25523bdd16 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/create.js.map @@ -0,0 +1 @@ +{"version":3,"file":"create.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["create.ts"],"names":["workbench","workbench.create","checkOverwrite","createPageLoaded","createPageLoaded.disableCreateIfEmptyId"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AAEpC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,IAAO,SAAS,CAKf;AALD,WAAO,SAAS,EAAC,CAAC;IAEdA,IAAcA,MAAMA,CAEnBA;IAFDA,WAAcA,MAAMA,EAACA,CAACA;QACPC,SAAEA,GAAGA,CAACA,CAACA,KAAKA,CAACA,CAACA;IAC7BA,CAACA,EAFaD,MAAMA,GAANA,gBAAMA,KAANA,gBAAMA,QAEnBA;AACLA,CAACA,EALM,SAAS,KAAT,SAAS,QAKf;AAED;;;;;;GAMG;AACH;IACIE,IAAIA,MAAMA,GAAGA,KAAKA,CAACA;IACnBA,CAACA,CAACA,IAAIA,CAACA;QACHA,GAAGA,EAAEA,KAAKA,GAAGA,SAASA,CAACA,MAAMA,CAACA,EAAEA,CAACA,GAAGA,EAAEA,GAAGA,OAAOA;QAChDA,KAAKA,EAAEA,KAAKA;QACZA,OAAOA,EAAEA;YACL,MAAM,GAAG,OAAO,CACZ,0CAA0C;gBAC1C,0CAA0C,CAAC,CAAC;QACpD,CAAC;QACDA,UAAUA,EAAEA;YACRA,GAAGA,EACHA;gBACI,MAAM,GAAG,IAAI,CAAC;YAClB,CAAC;SACJA;KACJA,CAACA,CAACA;IACHA,EAAEA,CAACA,CAACA,MAAMA,CAACA,CAACA,CAACA;QACTA,CAACA,CAACA,uBAAuBA,CAACA,CAACA,MAAMA,EAAEA,CAACA;IACxCA,CAACA;AACLA,CAACA;AAED,SAAS,CAAC,OAAO,CAAC;IACdC;;OAEGA;IACHA;QACIC,CAACA,CAACA,cAAcA,CAACA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,CAACA,CAACA,IAAIA,CAACA,IAAIA,CAACA,CAACA,CAACA,KAAKA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA,CAACA;IACrEA,CAACA;IAEDD,sBAAsBA;IACtBA,IAAIA,QAAQA,GAAGA,SAASA,CAACA,sBAAsBA,EAAEA,CAACA;IAClDA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,QAAQA,CAACA,MAAMA,GAAGA,CAACA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;QACvCA,IAAIA,IAAIA,GAAGA,QAAQA,CAACA,CAACA,CAACA,CAACA,KAAKA,CAACA,GAAGA,CAACA,CAACA;QAClCA,IAAIA,KAAKA,GAAGA,kBAAkBA,CAACA,IAAIA,CAACA,CAACA,CAACA,CAACA,CAACA,OAAOA,CAACA,KAAKA,EAAEA,GAAGA,CAACA,CAACA;QAC5DA,EAAEA,CAACA,CAACA,IAAIA,CAACA,CAACA,CAACA,IAAIA,IAAIA,CAACA,CAACA,CAACA;YAClBA,SAASA,CAACA,MAAMA,CAACA,EAAEA,CAACA,GAAGA,CAACA,KAAKA,CAACA,CAACA;QACnCA,CAACA;QACDA,EAAEA,CAACA,CAACA,IAAIA,CAACA,CAACA,CAACA,IAAIA,OAAOA,CAACA,CAACA,CAACA;YACrBA,CAACA,CAACA,QAAQA,CAACA,CAACA,GAAGA,CAACA,KAAKA,CAACA,CAACA;QAC3BA,CAACA;IACLA,CAACA;IAEDA,sBAAsBA,EAAEA,CAACA;IAEzBA,kEAAkEA;IAClEA,8BAA8BA;IAC9BA,CAACA,CAACA,KAAKA,CAACA,CAACA,EAAEA,CAACA,mBAAmBA,EAAEA;QAC7B,UAAU,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC,CAACA,CAACA;AACPA,CAACA,CAAC,CAAC"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/delete.js b/core/http/workbench/src/main/webapp/scripts/delete.js new file mode 100644 index 00000000000..386f708f4db --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/delete.js @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +/** + * Invoked by the "Delete" button on the form in delete.xsl. Checks with the + * DeleteServlet whether the given ID has been proxied, giving a chance to back + * out if it is. + */ +function checkIsSafeToDelete() { + var id = $('#id').val(); + var submitForm = false; + var feedback = $('#delete-feedback'); + $ + .ajax({ + dataType: 'json', + url: 'delete', + async: false, + timeout: 5000, + data: { + checkSafe: id + }, + error: function (jqXHR, textStatus, errorThrown) { + if (textStatus == 'timeout') { + feedback + .text('The server seems unresponsive. Delete request not sent.'); + } + else { + feedback + .text('There is a problem with the server. Delete request not sent. Error Type = ' + + textStatus + + ', HTTP Status Text = "' + + errorThrown + '"'); + } + }, + success: function (data) { + feedback.text(''); + submitForm = data.safe; + if (!submitForm) { + submitForm = confirm('WARNING: You are about to delete a repository that has been proxied by another repository!'); + } + } + }); + return submitForm; +} +//# sourceMappingURL=delete.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/delete.js.map b/core/http/workbench/src/main/webapp/scripts/delete.js.map new file mode 100644 index 00000000000..92a1059e06f --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/delete.js.map @@ -0,0 +1 @@ +{"version":3,"file":"delete.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["delete.ts"],"names":["checkIsSafeToDelete"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AAEpC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E;;;;GAIG;AACH;IACCA,IAAIA,EAAEA,GAAGA,CAACA,CAACA,KAAKA,CAACA,CAACA,GAAGA,EAAEA,CAACA;IACxBA,IAAIA,UAAUA,GAAGA,KAAKA,CAACA;IACpBA,IAAIA,QAAQA,GAAGA,CAACA,CAACA,kBAAkBA,CAACA,CAACA;IACxCA,CAACA;SACEA,IAAIA,CAACA;QACLA,QAAQA,EAAGA,MAAMA;QACjBA,GAAGA,EAAGA,QAAQA;QACdA,KAAKA,EAAGA,KAAKA;QACbA,OAAOA,EAAGA,IAAIA;QACdA,IAAIA,EAAGA;YACNA,SAASA,EAAGA,EAAEA;SACdA;QACDA,KAAKA,EAAGA,UAASA,KAAKA,EAAEA,UAAUA,EAAEA,WAAWA;YAC9C,EAAE,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC,CAAC;gBAC7B,QAAQ;qBACL,IAAI,CAAC,yDAAyD,CAAC,CAAC;YACpE,CAAC;YAAC,IAAI,CAAC,CAAC;gBACP,QAAQ;qBACL,IAAI,CAAC,4EAA4E;sBAC9E,UAAU;sBACV,wBAAwB;sBACxB,WAAW,GAAG,GAAG,CAAC,CAAC;YAC1B,CAAC;QACF,CAAC;QACDA,OAAOA,EAAGA,UAASA,IAAIA;YACP,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC;YACvB,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;gBACjB,UAAU,GAAG,OAAO,CAAC,4FAA4F,CAAC,CAAC;YACpH,CAAC;QACF,CAAC;KACDA,CAACA,CAACA;IACLA,MAAMA,CAACA,UAAUA,CAACA;AACnBA,CAACA"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/explore.js b/core/http/workbench/src/main/webapp/scripts/explore.js new file mode 100644 index 00000000000..c94dc14e832 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/explore.js @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +workbench.addLoad(function () { + function removeDuplicates(self) { + function textContent(element) { + return $.trim(element.innerText || element.textContent); + } + var lists = document.getElementsByTagName('ul'); + for (var i = lists.length - 1; i + 1; i--) { + var items = lists[i].getElementsByTagName('li'); + for (var j = items.length - 1; j; j--) { + var text = textContent(items[j]); + if (items[j].innerHTML == items[j - 1].innerHTML || text == self) { + items[j].parentNode.removeChild(items[j]); + } + } + text = textContent(items[0]); + if (text == self) { + items[0].parentNode.removeChild(items[0]); + } + if (items.length == 0) { + lists[i].parentNode.parentNode.removeChild(lists[i].parentNode); + } + } + } + // Populate parameters + var elements = workbench.getQueryStringElements(); + var resource = $('#resource'); + var suffix = '_explore'; + var limit_param = workbench.paging.LIMIT + suffix; + var limit_id = workbench.paging.LIM_ID + suffix; + var limit_param_found = false; + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + var value = decodeURIComponent(pair[1]).replace(/\+/g, ' '); + if ('resource' == pair[0]) { + resource.val(value); + } + else if (limit_param == pair[0]) { + $(limit_id).val(value); + limit_param_found = true; + } + } + if (!limit_param_found) { + var limit_cookie = workbench.getCookie(limit_param); + if (limit_cookie) { + $(limit_id).val(limit_cookie); + } + } + var explore = 'explore'; + workbench.paging.correctButtons(explore); + var content = document.getElementById('content'); + var h1 = content.getElementsByTagName('h1')[0]; + var rvalue = resource.val(); + if (rvalue) { + h1.appendChild(document.createTextNode(' (' + rvalue + ')')); + removeDuplicates(rvalue); + var limit = workbench.paging.getLimit(explore); + // Modify title to reflect total_result_count cookie + var total_result_count = workbench.paging.getTotalResultCount(); + var have_total_count = (total_result_count > 0); + var offset = limit == 0 ? 0 : workbench.paging.getOffset(); + var first = offset + 1; + var last = limit == 0 ? total_result_count : offset + limit; + // Truncate range if close to end. + last = have_total_count ? Math.min(total_result_count, last) : last; + var newHTML = '(' + first + '-' + last; + if (have_total_count) { + newHTML = newHTML + ' of ' + total_result_count; + } + h1.appendChild(document.createTextNode(newHTML + ')')); + } + workbench.paging.setShowDataTypesCheckboxAndSetChangeEvent(); +}); +//# sourceMappingURL=explore.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/explore.js.map b/core/http/workbench/src/main/webapp/scripts/explore.js.map new file mode 100644 index 00000000000..d865adb9df0 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/explore.js.map @@ -0,0 +1 @@ +{"version":3,"file":"explore.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["explore.ts"],"names":["removeDuplicates","removeDuplicates.textContent"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AACpC,kCAAkC;AAElC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,SAAS,CAAC,OAAO,CAAC;IACd,0BAA0B,IAAW;QACjCA,qBAAqBA,OAAmBA;YACpCC,MAAMA,CAACA,CAACA,CAACA,IAAIA,CAACA,OAAOA,CAACA,SAASA,IAAIA,OAAOA,CAACA,WAAWA,CAACA,CAACA;QAC5DA,CAACA;QAEDD,IAAIA,KAAKA,GAAGA,QAAQA,CAACA,oBAAoBA,CAACA,IAAIA,CAACA,CAACA;QAChDA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,KAAKA,CAACA,MAAMA,GAAGA,CAACA,EAAEA,CAACA,GAAGA,CAACA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;YACxCA,IAAIA,KAAKA,GAAGA,KAAKA,CAACA,CAACA,CAACA,CAACA,oBAAoBA,CAACA,IAAIA,CAACA,CAACA;YAChDA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,KAAKA,CAACA,MAAMA,GAAGA,CAACA,EAAEA,CAACA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;gBACpCA,IAAIA,IAAIA,GAAGA,WAAWA,CAACA,KAAKA,CAACA,CAACA,CAACA,CAACA,CAACA;gBACjCA,EAAEA,CAACA,CAACA,KAAKA,CAACA,CAACA,CAACA,CAACA,SAASA,IAAIA,KAAKA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,SAASA,IAAIA,IAAIA,IAAIA,IAAIA,CAACA,CAACA,CAACA;oBAC/DA,KAAKA,CAACA,CAACA,CAACA,CAACA,UAAUA,CAACA,WAAWA,CAACA,KAAKA,CAACA,CAACA,CAACA,CAACA,CAACA;gBAC9CA,CAACA;YACLA,CAACA;YAEDA,IAAIA,GAAGA,WAAWA,CAACA,KAAKA,CAACA,CAACA,CAACA,CAACA,CAACA;YAC7BA,EAAEA,CAACA,CAACA,IAAIA,IAAIA,IAAIA,CAACA,CAACA,CAACA;gBACfA,KAAKA,CAACA,CAACA,CAACA,CAACA,UAAUA,CAACA,WAAWA,CAACA,KAAKA,CAACA,CAACA,CAACA,CAACA,CAACA;YAC9CA,CAACA;YAEDA,EAAEA,CAACA,CAACA,KAAKA,CAACA,MAAMA,IAAIA,CAACA,CAACA,CAACA,CAACA;gBACpBA,KAAKA,CAACA,CAACA,CAACA,CAACA,UAAUA,CAACA,UAAUA,CAACA,WAAWA,CAACA,KAAKA,CAACA,CAACA,CAACA,CAACA,UAAUA,CAACA,CAACA;YACpEA,CAACA;QACLA,CAACA;IACLA,CAACA;IAED,sBAAsB;IACtB,IAAI,QAAQ,GAAG,SAAS,CAAC,sBAAsB,EAAE,CAAC;IAClD,IAAI,QAAQ,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC;IAC9B,IAAI,MAAM,GAAG,UAAU,CAAC;IACxB,IAAI,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC;IAClD,IAAI,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;IAChD,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAC9B,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC5D,EAAE,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxB,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACvB,iBAAiB,GAAG,IAAI,CAAC;QAC7B,CAAC;IACL,CAAC;IACD,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAA,CAAC;QACpB,IAAI,YAAY,GAAG,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACpD,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;YACf,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAClC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,GAAG,SAAS,CAAC;IACxB,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACjD,IAAI,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,IAAI,MAAM,GAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;IAC1B,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACT,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,GAAG,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC;QAC7D,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACzB,IAAI,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAE/C,oDAAoD;QACpD,IAAI,kBAAkB,GAAG,SAAS,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAChE,IAAI,gBAAgB,GAAG,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC;QAChD,IAAI,MAAM,GAAG,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QAC3D,IAAI,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;QACvB,IAAI,IAAI,GAAG,KAAK,IAAI,CAAC,GAAG,kBAAkB,GAAG,MAAM,GAAG,KAAK,CAAC;QAE5D,kCAAkC;QAClC,IAAI,GAAG,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC;QACpE,IAAI,OAAO,GAAG,GAAG,GAAG,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC;QACvC,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;YACnB,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,kBAAkB,CAAC;QACpD,CAAC;QACD,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,SAAS,CAAC,MAAM,CAAC,yCAAyC,EAAE,CAAC;AACjE,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/export.js b/core/http/workbench/src/main/webapp/scripts/export.js new file mode 100644 index 00000000000..5b89c86d062 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/export.js @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit +// the corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +workbench.addLoad(function () { + var suffix = '_explore'; + var limitParam = workbench.paging.LIMIT + suffix; + var limitElement = $(workbench.paging.LIM_ID + suffix); + function setElement(num) { + limitElement.val(String(parseInt(0 + num, 10))); + } + setElement(workbench.paging.hasQueryParameter(limitParam) ? + workbench.paging.getQueryParameter(limitParam) : + workbench.getCookie(limitParam)); +}); +//# sourceMappingURL=export.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/export.js.map b/core/http/workbench/src/main/webapp/scripts/export.js.map new file mode 100644 index 00000000000..860625e1c65 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/export.js.map @@ -0,0 +1 @@ +{"version":3,"file":"export.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["export.ts"],"names":["setElement"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AACpC,kCAAkC;AAElC,2EAA2E;AAC3E,yEAAyE;AACzE,4EAA4E;AAE5E,SAAS,CAAC,OAAO,CAAC;IACd,IAAI,MAAM,GAAG,UAAU,CAAC;IACxB,IAAI,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC;IACjD,IAAI,YAAY,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAEvD,oBAAoB,GAAW;QAC3BA,YAAYA,CAACA,GAAGA,CAACA,MAAMA,CAACA,QAAQA,CAACA,CAACA,GAAGA,GAAGA,EAAEA,EAAEA,CAACA,CAACA,CAACA,CAACA;IACpDA,CAACA;IAED,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC;QACjD,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC;QAC9C,SAAS,CAAC,SAAS,CAAC,UAAU,CAAC,CACtC,CAAC;AACN,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/namespaces.js b/core/http/workbench/src/main/webapp/scripts/namespaces.js new file mode 100644 index 00000000000..932aae8d33b --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/namespaces.js @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +var workbench; +(function (workbench) { + var namespaces; + (function (namespaces) { + /** + * Invoked by #prefix-select element in namespaces.xsl. + */ + function updatePrefix() { + var select = $('#prefix-select'); + $('#prefix').val(select.find('option:selected').text()); + $('#namespace').val(select.val()); + } + namespaces.updatePrefix = updatePrefix; + })(namespaces = workbench.namespaces || (workbench.namespaces = {})); +})(workbench || (workbench = {})); +//# sourceMappingURL=namespaces.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/namespaces.js.map b/core/http/workbench/src/main/webapp/scripts/namespaces.js.map new file mode 100644 index 00000000000..e78b81524da --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/namespaces.js.map @@ -0,0 +1 @@ +{"version":3,"file":"namespaces.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["namespaces.ts"],"names":["workbench","workbench.namespaces","workbench.namespaces.updatePrefix"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AAEpC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,IAAO,SAAS,CAaf;AAbD,WAAO,SAAS,EAAC,CAAC;IAEdA,IAAcA,UAAUA,CAUvBA;IAVDA,WAAcA,UAAUA,EAACA,CAACA;QAEtBC;;WAEGA;QACHA;YACIC,IAAIA,MAAMA,GAAGA,CAACA,CAACA,gBAAgBA,CAACA,CAACA;YACjCA,CAACA,CAACA,SAASA,CAACA,CAACA,GAAGA,CAACA,MAAMA,CAACA,IAAIA,CAACA,iBAAiBA,CAACA,CAACA,IAAIA,EAAEA,CAACA,CAACA;YACxDA,CAACA,CAACA,YAAYA,CAACA,CAACA,GAAGA,CAACA,MAAMA,CAACA,GAAGA,EAAEA,CAACA,CAACA;QACtCA,CAACA;QAJeD,uBAAYA,eAI3BA,CAAAA;IACLA,CAACA,EAVaD,UAAUA,GAAVA,oBAAUA,KAAVA,oBAAUA,QAUvBA;AACLA,CAACA,EAbM,SAAS,KAAT,SAAS,QAaf"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/paging.js b/core/http/workbench/src/main/webapp/scripts/paging.js new file mode 100644 index 00000000000..64704be4850 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/paging.js @@ -0,0 +1,286 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +var workbench; +(function (workbench) { + var paging; + (function (paging) { + var KT = 'know_total'; + var OFFSET = 'offset'; + paging.LIMIT = 'limit'; + paging.LIM_ID = '#' + paging.LIMIT; + var AMP = decodeURIComponent('%26'); + function addCookieToUrlQueryIfPresent(url, name) { + var value = workbench.getCookie(name); + if (value) { + url = url + AMP + name + '=' + value; + } + return url; + } + /** + * Invoked in graph.xsl and tuple.xsl for download functionality. Takes a + * document element by name, and creates a request with it as a parameter. + */ + function addGraphParam(name) { + var value = encodeURIComponent($('#' + name).val()); + var url = document.location.href; + var ref = workbench.getCookie('ref'); + if (url.match(/query$/)) { + if ('id' == ref) { + url = url + ';ref=id' + AMP + 'action=exec'; + url = addCookieToUrlQueryIfPresent(url, 'query'); + url = addCookieToUrlQueryIfPresent(url, 'queryLn'); + url = addCookieToUrlQueryIfPresent(url, 'infer'); + url = addCookieToUrlQueryIfPresent(url, 'limit_query'); + } + else { + alert("Can't put query in URL, since it might be too long for your browser.\n" + + "Save your query on the server, then execute it from the 'Saved Queries' page."); + return; + } + } + if (url.indexOf('?') + 1 || url.indexOf(';') + 1) { + document.location.href = url + AMP + name + '=' + value; + } + else { + document.location.href = url + ';' + name + '=' + value; + } + } + paging.addGraphParam = addGraphParam; + var StringMap = (function () { + function StringMap() { + } + return StringMap; + })(); + /** + * Scans the given URI for duplicate query parameter names, and removes + * all but the last occurrence for any duplicate case. + * + * @param {String} href The URI to simplify. + * @returns {String} The URI with only the last occurrence of any + * given parameter name remaining. + */ + function simplifyParameters(href) { + var params = {}; + var rval = ''; + var queryString = getQueryString(href); + var start = href.substring(0, href.indexOf(queryString)); + var elements = queryString.split(decodeURIComponent('%26')); + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + params[pair[0]] = pair[1]; + } + for (var name in params) { + // use hasOwnProperty to filter out keys from the + // Object.prototype + if (params.hasOwnProperty(name)) { + rval += name + '=' + params[name] + AMP; + } + } + rval = start + rval.substring(0, rval.length - 1); + return rval; + } + /** + * First, adds the given parameter to the URL query string. Second, + * adds a 'know_total' parameter if its current value is 'false' or + * non-existent. Third, simplifies the URL. Fourth, sends the browser + * to the modified URL. + * + * @param {String} name The name of the query parameter. + * @param {number} value The value of the query parameter. + */ + function addPagingParam(name, value) { + var url = document.location.href; + var hasParams = (url.indexOf('?') + 1 || url.indexOf(';') + 1); + var sep = hasParams ? AMP : ';'; + url = url + sep + name + '=' + value; + if (!hasQueryParameter(KT) || 'false' == getQueryParameter(KT)) { + url += AMP + KT + '=' + getTotalResultCount(); + } + if (!hasQueryParameter('query')) { + url += AMP + 'query=' + workbench.getCookie('query'); + url += AMP + 'ref=' + workbench.getCookie('ref'); + } + document.location.href = simplifyParameters(url); + } + paging.addPagingParam = addPagingParam; + /** + * Invoked in tuple.xsl and explore.xsl. Changes the limit query + * parameter and navigates to the new URL. + */ + function addLimit(page) { + var suffix = '_' + page; + addPagingParam(paging.LIMIT + suffix, $(paging.LIM_ID + suffix).val()); + } + paging.addLimit = addLimit; + /** + * Invoked in tuple.xsl and explore.xsl. Increments the offset query + * parameter, and navigates to the new URL. + */ + function nextOffset(page) { + addPagingParam(OFFSET, getOffset() + getLimit(page)); + } + paging.nextOffset = nextOffset; + /** + * Invoked in tuple.xsl and explore.xsl. Decrements the offset query + * parameter and navigates to the new URL. + */ + function previousOffset(page) { + addPagingParam(OFFSET, Math.max(0, getOffset() - getLimit(page))); + } + paging.previousOffset = previousOffset; + /** + * @returns {number} The value of the offset query parameter. + */ + function getOffset() { + var offset = getQueryParameter(OFFSET); + return ('' == offset) ? 0 : parseInt(offset, 10); + } + paging.getOffset = getOffset; + /** + * @returns {number} The value of the limit query parameter. + */ + function getLimit(page) { + return parseInt($(paging.LIM_ID + '_' + page).val(), 10); + } + paging.getLimit = getLimit; + /** + * Retrieves the URL query parameter with the given name. + * + * @param {String} name The name of the parameter to retrieve. + * @returns {String} The value of the given parameter, or an empty + * string if it doesn't exist. + */ + function getQueryParameter(name) { + var rval = ''; + var elements = getQueryString(document.location.href).split(decodeURIComponent('%26')); + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + if (name != pair[0]) { + continue; + } + rval = pair[1]; + } + return rval; + } + paging.getQueryParameter = getQueryParameter; + /** + * Gets whether a URL query parameter with the given name is present. + * + * @param {String} name The name of the parameter to retrieve. + * @returns {Boolean} True, if a parameter with the given name is in + * the URL. Otherwise, false. + */ + function hasQueryParameter(name) { + var rval = false; + var elements = getQueryString(document.location.href).split(decodeURIComponent('%26')); + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + if (name == pair[0]) { + rval = true; + break; + } + } + return rval; + } + paging.hasQueryParameter = hasQueryParameter; + /** + * Convenience function for returning the tail of a string after a + * given character. + * + * @param {String} value The string to get the tail of. + * @param split + * character to give tail after + * @returns The substring after the 'split' character, or the original + * string if 'split' is not found. + */ + function tailAfter(value, split) { + return value.substring(value.indexOf(split) + 1); + } + function getQueryString(href) { + return tailAfter(tailAfter(href, '?'), ';'); + } + paging.getQueryString = getQueryString; + /** + * Using the value of the 'limit' query parameter, correct the text of the + * Next and Previous buttons. Makes use of RegExp to preserve any + * localization. + */ + function correctButtons(page) { + var buttonWordPattern = /^[A-z]+\s+/; + var nextButton = $('#nextX'); + var oldNext = nextButton.val(); + var count = parseInt(/\d+$/.exec(oldNext)[0], 10); + var limit = workbench.paging.getLimit(page); + nextButton.val(buttonWordPattern.exec(oldNext)[0] + limit); + var previousButton = $('#previousX'); + previousButton + .val(buttonWordPattern.exec(previousButton.val())[0] + limit); + var offset = workbench.paging.getOffset(); + previousButton.prop('disabled', (offset <= 0 || limit <= 0)); + nextButton.prop('disabled', (count < limit || limit <= 0 || (offset + count) >= getTotalResultCount())); + } + paging.correctButtons = correctButtons; + /** + * Gets the total result count, preferably from the 'know_total' query + * parameter. If the parameter doesn't exist, get it from the + * 'total_result_count' cookie. + * + * @returns {Number} The given total result count, or zero if it isn't + * given. + */ + function getTotalResultCount() { + var total_result_count = 0; + var s_trc = workbench.paging.getQueryParameter(KT); + if (s_trc.length == 0) { + s_trc = workbench.getCookie('total_result_count'); + } + if (s_trc.length > 0) { + total_result_count = parseInt(s_trc, 10); + } + return total_result_count; + } + paging.getTotalResultCount = getTotalResultCount; + var DataTypeVisibility; + (function (DataTypeVisibility) { + function setCookie(c_name, value, exdays) { + var exdate = new Date(); + exdate.setDate(exdate.getDate() + exdays); + document.cookie = c_name + "=" + value + + ((exdays == null) ? "" : + "; expires=" + exdate.toUTCString()); + } + function setShow(show) { + setCookie('show-datatypes', show, 365); + var data = show ? 'data-longform' : 'data-shortform'; + $('div.resource[' + data + ']').each(function () { + var me = $(this); + me.find('a:first').text(decodeURIComponent(me.attr(data))); + }); + } + DataTypeVisibility.setShow = setShow; + })(DataTypeVisibility || (DataTypeVisibility = {})); + function setShowDataTypesCheckboxAndSetChangeEvent() { + var hideDataTypes = (workbench.getCookie('show-datatypes') == 'false'); + var showDTcb = $("input[name='show-datatypes']"); + if (hideDataTypes) { + showDTcb.prop('checked', false); + DataTypeVisibility.setShow(false); + } + showDTcb.on('change', function () { + DataTypeVisibility.setShow(showDTcb.prop('checked')); + }); + } + paging.setShowDataTypesCheckboxAndSetChangeEvent = setShowDataTypesCheckboxAndSetChangeEvent; + })(paging = workbench.paging || (workbench.paging = {})); +})(workbench || (workbench = {})); +//# sourceMappingURL=paging.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/paging.js.map b/core/http/workbench/src/main/webapp/scripts/paging.js.map new file mode 100644 index 00000000000..08d74ed6b73 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/paging.js.map @@ -0,0 +1 @@ +{"version":3,"file":"paging.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["paging.ts"],"names":["workbench","workbench.paging","workbench.paging.addCookieToUrlQueryIfPresent","workbench.paging.addGraphParam","workbench.paging.StringMap","workbench.paging.StringMap.constructor","workbench.paging.simplifyParameters","workbench.paging.addPagingParam","workbench.paging.addLimit","workbench.paging.nextOffset","workbench.paging.previousOffset","workbench.paging.getOffset","workbench.paging.getLimit","workbench.paging.getQueryParameter","workbench.paging.hasQueryParameter","workbench.paging.tailAfter","workbench.paging.getQueryString","workbench.paging.correctButtons","workbench.paging.getTotalResultCount","workbench.paging.DataTypeVisibility","workbench.paging.DataTypeVisibility.setCookie","workbench.paging.DataTypeVisibility.setShow","workbench.paging.setShowDataTypesCheckboxAndSetChangeEvent"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AAEpC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,IAAO,SAAS,CA0Rf;AA1RD,WAAO,SAAS,EAAC,CAAC;IAEdA,IAAcA,MAAMA,CAuRnBA;IAvRDA,WAAcA,MAAMA,EAACA,CAACA;QAElBC,IAAIA,EAAEA,GAAGA,YAAYA,CAACA;QAEtBA,IAAIA,MAAMA,GAAGA,QAAQA,CAACA;QAEXA,YAAKA,GAAGA,OAAOA,CAACA;QAEhBA,aAAMA,GAAGA,GAAGA,GAAGA,YAAKA,CAACA;QAEhCA,IAAIA,GAAGA,GAAGA,kBAAkBA,CAACA,KAAKA,CAACA,CAACA;QAEpCA,sCAAsCA,GAAWA,EAAEA,IAAYA;YAC3DC,IAAIA,KAAKA,GAAGA,SAASA,CAACA,SAASA,CAACA,IAAIA,CAACA,CAACA;YACtCA,EAAEA,CAACA,CAACA,KAAKA,CAACA,CAACA,CAACA;gBACRA,GAAGA,GAAGA,GAAGA,GAAGA,GAAGA,GAAGA,IAAIA,GAAGA,GAAGA,GAAGA,KAAKA,CAACA;YACzCA,CAACA;YACDA,MAAMA,CAACA,GAAGA,CAACA;QACfA,CAACA;QAEDD;;;WAGGA;QACHA,uBAA8BA,IAAYA;YACtCE,IAAIA,KAAKA,GAAGA,kBAAkBA,CAACA,CAACA,CAACA,GAAGA,GAAGA,IAAIA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA;YACpDA,IAAIA,GAAGA,GAAGA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,CAACA;YACjCA,IAAIA,GAAGA,GAAGA,SAASA,CAACA,SAASA,CAACA,KAAKA,CAACA,CAACA;YACrCA,EAAEA,CAACA,CAACA,GAAGA,CAACA,KAAKA,CAACA,QAAQA,CAACA,CAACA,CAACA,CAACA;gBACtBA,EAAEA,CAACA,CAACA,IAAIA,IAAIA,GAAGA,CAACA,CAACA,CAACA;oBACdA,GAAGA,GAAGA,GAAGA,GAAGA,SAASA,GAAGA,GAAGA,GAAGA,aAAaA,CAACA;oBAC5CA,GAAGA,GAAGA,4BAA4BA,CAACA,GAAGA,EAAEA,OAAOA,CAACA,CAACA;oBACjDA,GAAGA,GAAGA,4BAA4BA,CAACA,GAAGA,EAAEA,SAASA,CAACA,CAACA;oBACnDA,GAAGA,GAAGA,4BAA4BA,CAACA,GAAGA,EAAEA,OAAOA,CAACA,CAACA;oBACjDA,GAAGA,GAAGA,4BAA4BA,CAACA,GAAGA,EAAEA,aAAaA,CAACA,CAACA;gBAC3DA,CAACA;gBAACA,IAAIA,CAACA,CAACA;oBACJA,KAAKA,CAACA,wEAAwEA;wBAC9EA,+EAA+EA,CAACA,CAACA;oBACjFA,MAAMA,CAACA;gBACXA,CAACA;YACLA,CAACA;YACDA,EAAEA,CAACA,CAACA,GAAGA,CAACA,OAAOA,CAACA,GAAGA,CAACA,GAAGA,CAACA,IAAIA,GAAGA,CAACA,OAAOA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA;gBAC/CA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,GAAGA,GAAGA,GAAGA,GAAGA,GAAGA,IAAIA,GAAGA,GAAGA,GAAGA,KAAKA,CAACA;YAC5DA,CAACA;YAACA,IAAIA,CAACA,CAACA;gBACJA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,GAAGA,GAAGA,GAAGA,GAAGA,GAAGA,IAAIA,GAAGA,GAAGA,GAAGA,KAAKA,CAACA;YAC5DA,CAACA;QACLA,CAACA;QAtBeF,oBAAaA,gBAsB5BA,CAAAA;QAEDA;YAAAG;YAEAC,CAACA;YAADD,gBAACA;QAADA,CAACA,AAFDH,IAECA;QAEDA;;;;;;;WAOGA;QACHA,4BAA4BA,IAAYA;YACpCK,IAAIA,MAAMA,GAAaA,EAAEA,CAACA;YAC1BA,IAAIA,IAAIA,GAAGA,EAAEA,CAACA;YACdA,IAAIA,WAAWA,GAAGA,cAAcA,CAACA,IAAIA,CAACA,CAACA;YACvCA,IAAIA,KAAKA,GAAGA,IAAIA,CAACA,SAASA,CAACA,CAACA,EAAEA,IAAIA,CAACA,OAAOA,CAACA,WAAWA,CAACA,CAACA,CAACA;YACzDA,IAAIA,QAAQA,GAAGA,WAAWA,CAACA,KAAKA,CAACA,kBAAkBA,CAACA,KAAKA,CAACA,CAACA,CAACA;YAC5DA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,QAAQA,CAACA,MAAMA,GAAGA,CAACA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;gBACvCA,IAAIA,IAAIA,GAAGA,QAAQA,CAACA,CAACA,CAACA,CAACA,KAAKA,CAACA,GAAGA,CAACA,CAACA;gBAClCA,MAAMA,CAACA,IAAIA,CAACA,CAACA,CAACA,CAACA,GAAGA,IAAIA,CAACA,CAACA,CAACA,CAACA;YAE9BA,CAACA;YACDA,GAAGA,CAACA,CAACA,GAAGA,CAACA,IAAIA,IAAIA,MAAMA,CAACA,CAACA,CAACA;gBACtBA,iDAAiDA;gBACjDA,mBAAmBA;gBACnBA,EAAEA,CAACA,CAACA,MAAMA,CAACA,cAAcA,CAACA,IAAIA,CAACA,CAACA,CAACA,CAACA;oBAC9BA,IAAIA,IAAIA,IAAIA,GAAGA,GAAGA,GAAGA,MAAMA,CAACA,IAAIA,CAACA,GAAGA,GAAGA,CAACA;gBAC5CA,CAACA;YACLA,CAACA;YACDA,IAAIA,GAAGA,KAAKA,GAAGA,IAAIA,CAACA,SAASA,CAACA,CAACA,EAAEA,IAAIA,CAACA,MAAMA,GAAGA,CAACA,CAACA,CAACA;YAClDA,MAAMA,CAACA,IAAIA,CAACA;QAChBA,CAACA;QAGDL;;;;;;;;WAQGA;QACHA,wBAA+BA,IAAYA,EAAEA,KAAaA;YACtDM,IAAIA,GAAGA,GAAGA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,CAACA;YACjCA,IAAIA,SAASA,GAAGA,CAACA,GAAGA,CAACA,OAAOA,CAACA,GAAGA,CAACA,GAAGA,CAACA,IAAIA,GAAGA,CAACA,OAAOA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA,CAACA;YAC/DA,IAAIA,GAAGA,GAAGA,SAASA,GAAGA,GAAGA,GAAGA,GAAGA,CAACA;YAChCA,GAAGA,GAAGA,GAAGA,GAAGA,GAAGA,GAAGA,IAAIA,GAAGA,GAAGA,GAAGA,KAAKA,CAACA;YACrCA,EAAEA,CAACA,CAACA,CAACA,iBAAiBA,CAACA,EAAEA,CAACA,IAAIA,OAAOA,IAAIA,iBAAiBA,CAACA,EAAEA,CAACA,CAACA,CAACA,CAACA;gBAC7DA,GAAGA,IAAIA,GAAGA,GAAGA,EAAEA,GAAGA,GAAGA,GAAGA,mBAAmBA,EAAEA,CAACA;YAClDA,CAACA;YACDA,EAAEA,CAACA,CAACA,CAACA,iBAAiBA,CAACA,OAAOA,CAACA,CAACA,CAACA,CAACA;gBAC9BA,GAAGA,IAAIA,GAAGA,GAAGA,QAAQA,GAAGA,SAASA,CAACA,SAASA,CAACA,OAAOA,CAACA,CAACA;gBACrDA,GAAGA,IAAIA,GAAGA,GAAGA,MAAMA,GAAGA,SAASA,CAACA,SAASA,CAACA,KAAKA,CAACA,CAACA;YACrDA,CAACA;YACDA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,GAAGA,kBAAkBA,CAACA,GAAGA,CAACA,CAACA;QACrDA,CAACA;QAbeN,qBAAcA,iBAa7BA,CAAAA;QAEDA;;;WAGGA;QACHA,kBAAyBA,IAAYA;YACjCO,IAAIA,MAAMA,GAAGA,GAAGA,GAAGA,IAAIA,CAACA;YACxBA,cAAcA,CAACA,YAAKA,GAAGA,MAAMA,EAAEA,CAACA,CAACA,aAAMA,GAAGA,MAAMA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA;QAC7DA,CAACA;QAHeP,eAAQA,WAGvBA,CAAAA;QAEDA;;;WAGGA;QACHA,oBAA2BA,IAAYA;YACnCQ,cAAcA,CAACA,MAAMA,EAAEA,SAASA,EAAEA,GAAGA,QAAQA,CAACA,IAAIA,CAACA,CAACA,CAACA;QACzDA,CAACA;QAFeR,iBAAUA,aAEzBA,CAAAA;QAEDA;;;WAGGA;QACHA,wBAA+BA,IAAYA;YACvCS,cAAcA,CAACA,MAAMA,EAAEA,IAAIA,CAACA,GAAGA,CAACA,CAACA,EAAEA,SAASA,EAAEA,GAAGA,QAAQA,CAACA,IAAIA,CAACA,CAACA,CAACA,CAACA;QACtEA,CAACA;QAFeT,qBAAcA,iBAE7BA,CAAAA;QAEDA;;WAEGA;QACHA;YACIU,IAAIA,MAAMA,GAAGA,iBAAiBA,CAACA,MAAMA,CAACA,CAACA;YACvCA,MAAMA,CAACA,CAACA,EAAEA,IAAIA,MAAMA,CAACA,GAAGA,CAACA,GAAGA,QAAQA,CAACA,MAAMA,EAAEA,EAAEA,CAACA,CAACA;QACrDA,CAACA;QAHeV,gBAASA,YAGxBA,CAAAA;QAEDA;;WAEGA;QACHA,kBAAyBA,IAAYA;YACjCW,MAAMA,CAACA,QAAQA,CAACA,CAACA,CAACA,aAAMA,GAAGA,GAAGA,GAAGA,IAAIA,CAACA,CAACA,GAAGA,EAAEA,EAAEA,EAAEA,CAACA,CAACA;QACtDA,CAACA;QAFeX,eAAQA,WAEvBA,CAAAA;QAEDA;;;;;;WAMGA;QACHA,2BAAkCA,IAAYA;YAC1CY,IAAIA,IAAIA,GAAGA,EAAEA,CAACA;YACdA,IAAIA,QAAQA,GAAGA,cAAcA,CAACA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,CAACA,CAACA,KAAKA,CAACA,kBAAkBA,CAACA,KAAKA,CAACA,CAACA,CAACA;YACvFA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,QAAQA,CAACA,MAAMA,GAAGA,CAACA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;gBACvCA,IAAIA,IAAIA,GAAGA,QAAQA,CAACA,CAACA,CAACA,CAACA,KAAKA,CAACA,GAAGA,CAACA,CAACA;gBAClCA,EAAEA,CAACA,CAACA,IAAIA,IAAIA,IAAIA,CAACA,CAACA,CAACA,CAACA,CAACA,CAACA;oBAClBA,QAAQA,CAACA;gBACbA,CAACA;gBACDA,IAAIA,GAAGA,IAAIA,CAACA,CAACA,CAACA,CAACA;YAEnBA,CAACA;YACDA,MAAMA,CAACA,IAAIA,CAACA;QAChBA,CAACA;QAZeZ,wBAAiBA,oBAYhCA,CAAAA;QAEDA;;;;;;WAMGA;QACHA,2BAAkCA,IAAYA;YAC1Ca,IAAIA,IAAIA,GAAGA,KAAKA,CAACA;YACjBA,IAAIA,QAAQA,GAAGA,cAAcA,CAACA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,CAACA,CAACA,KAAKA,CAACA,kBAAkBA,CAACA,KAAKA,CAACA,CAACA,CAACA;YACvFA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,QAAQA,CAACA,MAAMA,GAAGA,CAACA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;gBACvCA,IAAIA,IAAIA,GAAGA,QAAQA,CAACA,CAACA,CAACA,CAACA,KAAKA,CAACA,GAAGA,CAACA,CAACA;gBAClCA,EAAEA,CAACA,CAACA,IAAIA,IAAIA,IAAIA,CAACA,CAACA,CAACA,CAACA,CAACA,CAACA;oBAClBA,IAAIA,GAAGA,IAAIA,CAACA;oBACZA,KAAKA,CAACA;gBACVA,CAACA;YACLA,CAACA;YACDA,MAAMA,CAACA,IAAIA,CAACA;QAChBA,CAACA;QAXeb,wBAAiBA,oBAWhCA,CAAAA;QAEDA;;;;;;;;;WASGA;QACHA,mBAAmBA,KAAaA,EAAEA,KAAaA;YAC3Cc,MAAMA,CAACA,KAAKA,CAACA,SAASA,CAACA,KAAKA,CAACA,OAAOA,CAACA,KAAKA,CAACA,GAAGA,CAACA,CAACA,CAACA;QACrDA,CAACA;QAEDd,wBAA+BA,IAAYA;YACvCe,MAAMA,CAACA,SAASA,CAACA,SAASA,CAACA,IAAIA,EAAEA,GAAGA,CAACA,EAAEA,GAAGA,CAACA,CAACA;QAChDA,CAACA;QAFef,qBAAcA,iBAE7BA,CAAAA;QAEDA;;;;WAIGA;QACHA,wBAA+BA,IAAYA;YACvCgB,IAAIA,iBAAiBA,GAAGA,YAAYA,CAACA;YACrCA,IAAIA,UAAUA,GAAGA,CAACA,CAACA,QAAQA,CAACA,CAACA;YAC7BA,IAAIA,OAAOA,GAAGA,UAAUA,CAACA,GAAGA,EAAEA,CAACA;YAC/BA,IAAIA,KAAKA,GAAGA,QAAQA,CAACA,MAAMA,CAACA,IAAIA,CAACA,OAAOA,CAACA,CAACA,CAACA,CAACA,EAAEA,EAAEA,CAACA,CAACA;YAClDA,IAAIA,KAAKA,GAAGA,SAASA,CAACA,MAAMA,CAACA,QAAQA,CAACA,IAAIA,CAACA,CAACA;YAC5CA,UAAUA,CAACA,GAAGA,CAACA,iBAAiBA,CAACA,IAAIA,CAACA,OAAOA,CAACA,CAACA,CAACA,CAACA,GAAGA,KAAKA,CAACA,CAACA;YAC3DA,IAAIA,cAAcA,GAAGA,CAACA,CAACA,YAAYA,CAACA,CAACA;YACrCA,cAAcA;iBACTA,GAAGA,CAACA,iBAAiBA,CAACA,IAAIA,CAACA,cAAcA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA,CAACA,GAAGA,KAAKA,CAACA,CAACA;YAClEA,IAAIA,MAAMA,GAAGA,SAASA,CAACA,MAAMA,CAACA,SAASA,EAAEA,CAACA;YAC1CA,cAAcA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,CAACA,MAAMA,IAAIA,CAACA,IAAIA,KAAKA,IAAIA,CAACA,CAACA,CAACA,CAACA;YAC7DA,UAAUA,CAACA,IAAIA,CAACA,UAAUA,EACtBA,CAACA,KAAKA,GAAGA,KAAKA,IAAIA,KAAKA,IAAIA,CAACA,IAAIA,CAACA,MAAMA,GAAGA,KAAKA,CAACA,IAAIA,mBAAmBA,EAAEA,CAACA,CAACA,CAACA;QACpFA,CAACA;QAdehB,qBAAcA,iBAc7BA,CAAAA;QAEDA;;;;;;;WAOGA;QACHA;YACIiB,IAAIA,kBAAkBA,GAAGA,CAACA,CAACA;YAC3BA,IAAIA,KAAKA,GAAGA,SAASA,CAACA,MAAMA,CAACA,iBAAiBA,CAACA,EAAEA,CAACA,CAACA;YACnDA,EAAEA,CAACA,CAACA,KAAKA,CAACA,MAAMA,IAAIA,CAACA,CAACA,CAACA,CAACA;gBACpBA,KAAKA,GAAGA,SAASA,CAACA,SAASA,CAACA,oBAAoBA,CAACA,CAACA;YACtDA,CAACA;YAEDA,EAAEA,CAACA,CAACA,KAAKA,CAACA,MAAMA,GAAGA,CAACA,CAACA,CAACA,CAACA;gBACnBA,kBAAkBA,GAAGA,QAAQA,CAACA,KAAKA,EAAEA,EAAEA,CAACA,CAACA;YAC7CA,CAACA;YAEDA,MAAMA,CAACA,kBAAkBA,CAACA;QAC9BA,CAACA;QAZejB,0BAAmBA,sBAYlCA,CAAAA;QAEDA,IAAOA,kBAAkBA,CAiBxBA;QAjBDA,WAAOA,kBAAkBA,EAACA,CAACA;YACvBkB,mBAAmBA,MAAcA,EAAEA,KAAcA,EAAEA,MAAcA;gBAC7DC,IAAIA,MAAMA,GAAGA,IAAIA,IAAIA,EAAEA,CAACA;gBACxBA,MAAMA,CAACA,OAAOA,CAACA,MAAMA,CAACA,OAAOA,EAAEA,GAAGA,MAAMA,CAACA,CAACA;gBAC1CA,QAAQA,CAACA,MAAMA,GAAGA,MAAMA,GAAGA,GAAGA,GAAGA,KAAKA;oBAClCA,CAACA,CAACA,MAAMA,IAAIA,IAAIA,CAACA,GAAGA,EAAEA;wBACtBA,YAAYA,GAAGA,MAAMA,CAACA,WAAWA,EAAEA,CAACA,CAACA;YAC7CA,CAACA;YAEDD,iBAAwBA,IAAaA;gBACjCE,SAASA,CAACA,gBAAgBA,EAAEA,IAAIA,EAAEA,GAAGA,CAACA,CAACA;gBACvCA,IAAIA,IAAIA,GAAGA,IAAIA,GAAGA,eAAeA,GAAGA,gBAAgBA,CAACA;gBACrDA,CAACA,CAACA,eAAeA,GAAGA,IAAIA,GAAGA,GAAGA,CAACA,CAACA,IAAIA,CAACA;oBACjC,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;oBACjB,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC/D,CAAC,CAACA,CAACA;YACPA,CAACA;YAPeF,0BAAOA,UAOtBA,CAAAA;QACLA,CAACA,EAjBMlB,kBAAkBA,KAAlBA,kBAAkBA,QAiBxBA;QAEDA;YACIqB,IAAIA,aAAaA,GAAGA,CAACA,SAASA,CAACA,SAASA,CAACA,gBAAgBA,CAACA,IAAIA,OAAOA,CAACA,CAACA;YACvEA,IAAIA,QAAQA,GAAGA,CAACA,CAACA,8BAA8BA,CAACA,CAACA;YACjDA,EAAEA,CAACA,CAACA,aAAaA,CAACA,CAACA,CAACA;gBAChBA,QAAQA,CAACA,IAAIA,CAACA,SAASA,EAAEA,KAAKA,CAACA,CAACA;gBAChCA,kBAAkBA,CAACA,OAAOA,CAACA,KAAKA,CAACA,CAACA;YACtCA,CAACA;YACDA,QAAQA,CAACA,EAAEA,CAACA,QAAQA,EAAEA;gBAClB,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YACzD,CAAC,CAACA,CAACA;QACPA,CAACA;QAVerB,gDAAyCA,4CAUxDA,CAAAA;IACLA,CAACA,EAvRaD,MAAMA,GAANA,gBAAMA,KAANA,gBAAMA,QAuRnBA;AACLA,CAACA,EA1RM,SAAS,KAAT,SAAS,QA0Rf"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/query.js b/core/http/workbench/src/main/webapp/scripts/query.js new file mode 100644 index 00000000000..fcbe5d1ebaf --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/query.js @@ -0,0 +1,323 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +var workbench; +(function (workbench) { + var query; + (function (query_1) { + /** + * Holds the current selected query language. + */ + var currentQueryLn = ''; + var yasqe = null; + /** + * Populate reasonable default name space declarations into the query text area. + * The server has provided the declaration text in hidden elements. + */ + function loadNamespaces() { + function toggleNamespaces() { + workbench.query.setQueryValue(namespaces.text()); + currentQueryLn = queryLn; + } + var query = workbench.query.getQueryValue(); + var queryLn = $('#queryLn').val(); + var namespaces = $('#' + queryLn + '-namespaces'); + var last = $('#' + currentQueryLn + '-namespaces'); + if (namespaces.length) { + if (!query || query.trim().length == 0) { + toggleNamespaces(); + } + if (last.length && (query == last.text())) { + toggleNamespaces(); + } + } + } + query_1.loadNamespaces = loadNamespaces; + /** + *Fires when the query language is changed + */ + function onQlChange() { + workbench.query.loadNamespaces(); + workbench.query.updateYasqe(); + } + query_1.onQlChange = onQlChange; + /** + * Invoked by the "clear" button. After confirming with the user, + * clears the query text and loads the current repository and query + * language name space declarations. + */ + function resetNamespaces() { + if (confirm('Click OK to clear the current query text and replace' + + 'it with the ' + $('#queryLn').val() + + ' namespace declarations.')) { + workbench.query.setQueryValue(''); + workbench.query.loadNamespaces(); + } + } + query_1.resetNamespaces = resetNamespaces; + /** + * Clear any contents of the save feedback field. + */ + function clearFeedback() { + $('#save-feedback').removeClass().text(''); + } + query_1.clearFeedback = clearFeedback; + /** + * Clear the save feedback field, and look at the contents of the query name + * field. Disables the save button if the field doesn't satisfy a given regular + * expression. With a delay of 200 msec, to give enough time after + * the event for the document to have changed. (Workaround for annoying browser + * behavior.) + */ + function handleNameChange() { + setTimeout(function disableSaveIfNotValidName() { + $('#save').prop('disabled', !/^[- \w]{1,32}$/.test($('#query-name').val())); + workbench.query.clearFeedback(); + }, 0); + } + query_1.handleNameChange = handleNameChange; + /** + * Send a background HTTP request to save the query, and handle the + * response asynchronously. + * + * @param overwrite + * if true, add a URL parameter that tells the server we wish + * to overwrite any already saved query + */ + function ajaxSave(overwrite) { + var feedback = $('#save-feedback'); + var url = []; + url[url.length] = 'query'; + if (overwrite) { + url[url.length] = document.all ? ';' : '?'; + url[url.length] = 'overwrite=true&'; + } + var href = url.join(''); + var form = $('form[action="query"]'); + $.ajax({ + url: href, + type: 'POST', + dataType: 'json', + data: form.serialize(), + timeout: 5000, + error: function (jqXHR, textStatus, errorThrown) { + feedback.removeClass().addClass('error'); + if (textStatus == 'timeout') { + feedback.text('Timed out waiting for response. Uncertain if save occured.'); + } + else { + feedback.text('Save Request Failed: Error Type = ' + + textStatus + ', HTTP Status Text = "' + errorThrown + '"'); + } + }, + success: function (response) { + if (response.accessible) { + if (response.written) { + feedback.removeClass().addClass('success'); + feedback.text('Query saved.'); + } + else { + if (response.existed) { + if (confirm('Query name exists. Click OK to overwrite.')) { + ajaxSave(true); + } + else { + feedback.removeClass().addClass('error'); + feedback.text('Cancelled overwriting existing query.'); + } + } + } + } + else { + feedback.removeClass().addClass('error'); + feedback.text('Repository was not accessible (check your permissions).'); + } + } + }); + } + /** + * Invoked by form submission. + * + * @returns {boolean} true if a form POST is performed, false if + * a GET is instead performed + */ + function doSubmit() { + //if yasqe is instantiated, make sure we save the value to the textarea + if (yasqe) + yasqe.save(); + var allowPageToSubmitForm = false; + var save = ($('#action').val() == 'save'); + if (save) { + ajaxSave(false); + } + else { + var url = []; + url[url.length] = 'query'; + if (document.all) { + url[url.length] = ';'; + } + else { + url[url.length] = '?'; + } + workbench.addParam(url, 'action'); + workbench.addParam(url, 'queryLn'); + workbench.addParam(url, 'query'); + workbench.addParam(url, 'limit_query'); + workbench.addParam(url, 'infer'); + var href = url.join(''); + var loc = document.location; + var currentBaseLength = loc.href.length - loc.pathname.length + - loc.search.length; + var pathLength = href.length; + var urlLength = pathLength + currentBaseLength; + // Published Internet Explorer restrictions on URL length, which are the + // most restrictive of the major browsers. + if (pathLength > 2048 || urlLength > 2083) { + alert("Due to its length, your query will be posted in the request body. " + + "It won't be possible to use a bookmark for the results page."); + allowPageToSubmitForm = true; + } + else { + // GET using the constructed URL, method exits here + document.location.href = href; + } + } + // Value returned to form submit event. If not true, prevents normal form + // submission. + return allowPageToSubmitForm; + } + query_1.doSubmit = doSubmit; + function setQueryValue(queryString) { + yasqe.setValue(queryString.trim()); + } + query_1.setQueryValue = setQueryValue; + function getQueryValue() { + return yasqe.getValue().trim(); + } + query_1.getQueryValue = getQueryValue; + function getYasqe() { + return yasqe; + } + query_1.getYasqe = getYasqe; + function updateYasqe() { + if ($("#queryLn").val() == "SPARQL") { + initYasqe(); + } + else { + closeYasqe(); + } + } + query_1.updateYasqe = updateYasqe; + function initYasqe() { + workbench.yasqeHelper.setupCompleters(sparqlNamespaces); + yasqe = YASQE.fromTextArea(document.getElementById('query'), { + consumeShareLink: null //don't try to parse the url args. this is already done by the addLoad function below + }); + //some styling conflicts. Could add my own css file, but not a lot of things need changing, so just do this programmatically + //first, set the font size (otherwise font is as small as menu, which is too small) + //second, set the width. YASQE normally expands to 100%, but the use of a table requires us to set a fixed width + $(yasqe.getWrapperElement()).css({ "fontSize": "14px", "width": "900px" }); + //we made a change to the css wrapper element (and did so after initialization). So, force a manual update of the yasqe instance + yasqe.refresh(); + } + function closeYasqe() { + if (yasqe) { + //store yasqe value in text area (not sure whether this is desired, but it mimics current behavior) + //it closes the yasqe instance as well + yasqe.toTextArea(); + yasqe = null; + } + } + })(query = workbench.query || (workbench.query = {})); +})(workbench || (workbench = {})); +workbench.addLoad(function queryPageLoaded() { + /** + * Gets a parameter from the URL or the cookies, preferentially in that + * order. + * + * @param param + * the name of the parameter + * @returns the value of the given parameter, or something that evaluates + as false, if the parameter was not found + */ + function getParameterFromUrlOrCookie(param) { + var href = document.location.href; + var elements = href.substring(href.indexOf('?') + 1).substring(href.indexOf(';') + 1).split(decodeURIComponent('%26')); + var result = ''; + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + var value = decodeURIComponent(pair[1]).replace(/\+/g, ' '); + if (pair[0] == param) { + result = value; + } + } + if (!result) { + result = workbench.getCookie(param); + } + return result; + } + function getQueryTextFromServer(queryParam, refParam) { + $.getJSON('query', { + action: "get", + query: queryParam, + ref: refParam + }, function (response) { + if (response.queryText) { + workbench.query.setQueryValue(response.queryText); + } + }); + } + //Start with initializing our YASQE instance, given that 'SPARQL' is the selected query language + //(all the following 'set' and 'get' SPARQL query functions require an instantiated yasqe instance + workbench.query.updateYasqe(); + // Populate the query text area with the value of the URL query parameter, + // only if it is present. If it is not present in the URL query, then + // looks for the 'query' cookie, and sets it from that. (The cookie + // enables re-populating the text field with the previous query when the + // user returns via the browser back button.) + var query = getParameterFromUrlOrCookie('query'); + if (query) { + var ref = getParameterFromUrlOrCookie('ref'); + if (ref == 'id' || ref == 'hash') { + getQueryTextFromServer(query, ref); + } + else { + workbench.query.setQueryValue(query); + } + } + workbench.query.loadNamespaces(); + // Trim the query text area contents of any leading and/or trailing + // whitespace. + workbench.query.setQueryValue($.trim(workbench.query.getQueryValue())); + // Add click handlers identifying the clicked element in a hidden 'action' + // form field. + var addHandler = function (id) { + $('#' + id).click(function setAction() { $('#action').val(id); }); + }; + addHandler('exec'); + addHandler('save'); + // Add event handlers to the save name field to react to changes in it. + $('#query-name').bind('keydown cut paste', workbench.query.handleNameChange); + // Add event handlers to the query text area to react to changes in it. + $('#query').bind('keydown cut paste', workbench.query.clearFeedback); + if (workbench.query.getYasqe()) { + workbench.query.getYasqe().on('change', workbench.query.clearFeedback); + } + // Detect if there is no current authenticated user, and if so, disable + // the 'save privately' option. + if ($('#selected-user>span').is('.disabled')) { + $('#save-private').prop('checked', false).prop('disabled', true); + } +}); +//# sourceMappingURL=query.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/query.js.map b/core/http/workbench/src/main/webapp/scripts/query.js.map new file mode 100644 index 00000000000..3fe33d1c319 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/query.js.map @@ -0,0 +1 @@ +{"version":3,"file":"query.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["query.ts"],"names":["workbench","workbench.query","workbench.query.loadNamespaces","workbench.query.loadNamespaces.toggleNamespaces","workbench.query.onQlChange","workbench.query.resetNamespaces","workbench.query.clearFeedback","workbench.query.handleNameChange","workbench.query.handleNameChange.disableSaveIfNotValidName","workbench.query.ajaxSave","workbench.query.doSubmit","workbench.query.setQueryValue","workbench.query.getQueryValue","workbench.query.getYasqe","workbench.query.updateYasqe","workbench.query.initYasqe","workbench.query.closeYasqe","queryPageLoaded","queryPageLoaded.getParameterFromUrlOrCookie","queryPageLoaded.getQueryTextFromServer","setAction"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AACpC,mCAAmC;AACnC,uCAAuC;AAEvC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,IAAO,SAAS,CA8Of;AA9OD,WAAO,SAAS,EAAC,CAAC;IAEdA,IAAcA,KAAKA,CA2OlBA;IA3ODA,WAAcA,OAAKA,EAACA,CAACA;QAOjBC;;WAEGA;QACHA,IAAIA,cAAcA,GAAGA,EAAEA,CAACA;QACxBA,IAAIA,KAAKA,GAAmBA,IAAIA,CAACA;QAEjCA;;;WAGGA;QACHA;YACIC;gBACIC,SAASA,CAACA,KAAKA,CAACA,aAAaA,CAACA,UAAUA,CAACA,IAAIA,EAAEA,CAACA,CAACA;gBACjDA,cAAcA,GAAGA,OAAOA,CAACA;YAC7BA,CAACA;YAEDD,IAAIA,KAAKA,GAAWA,SAASA,CAACA,KAAKA,CAACA,aAAaA,EAAEA,CAACA;YACpDA,IAAIA,OAAOA,GAAGA,CAACA,CAACA,UAAUA,CAACA,CAACA,GAAGA,EAAEA,CAACA;YAClCA,IAAIA,UAAUA,GAAGA,CAACA,CAACA,GAAGA,GAAGA,OAAOA,GAAGA,aAAaA,CAACA,CAACA;YAClDA,IAAIA,IAAIA,GAAGA,CAACA,CAACA,GAAGA,GAAGA,cAAcA,GAAGA,aAAaA,CAACA,CAACA;YACnDA,EAAEA,CAACA,CAACA,UAAUA,CAACA,MAAMA,CAACA,CAACA,CAACA;gBACpBA,EAAEA,CAACA,CAACA,CAACA,KAAKA,IAAIA,KAAKA,CAACA,IAAIA,EAAEA,CAACA,MAAMA,IAAIA,CAACA,CAACA,CAACA,CAACA;oBACrCA,gBAAgBA,EAAEA,CAACA;gBACvBA,CAACA;gBACDA,EAAEA,CAACA,CAACA,IAAIA,CAACA,MAAMA,IAAIA,CAACA,KAAKA,IAAIA,IAAIA,CAACA,IAAIA,EAAEA,CAACA,CAACA,CAACA,CAACA;oBACxCA,gBAAgBA,EAAEA,CAACA;gBACvBA,CAACA;YACLA,CAACA;QACLA,CAACA;QAlBeD,sBAAcA,iBAkB7BA,CAAAA;QAEDA;;WAEGA;QACHA;YACIG,SAASA,CAACA,KAAKA,CAACA,cAAcA,EAAEA,CAACA;YACjCA,SAASA,CAACA,KAAKA,CAACA,WAAWA,EAAEA,CAACA;QAClCA,CAACA;QAHeH,kBAAUA,aAGzBA,CAAAA;QACDA;;;;WAIGA;QACHA;YACII,EAAEA,CAACA,CAACA,OAAOA,CAACA,sDAAsDA;gBAC9DA,cAAcA,GAAGA,CAACA,CAACA,UAAUA,CAACA,CAACA,GAAGA,EAAEA;gBACpCA,0BAA0BA,CAACA,CAACA,CAACA,CAACA;gBAC9BA,SAASA,CAACA,KAAKA,CAACA,aAAaA,CAACA,EAAEA,CAACA,CAACA;gBAClCA,SAASA,CAACA,KAAKA,CAACA,cAAcA,EAAEA,CAACA;YACrCA,CAACA;QACLA,CAACA;QAPeJ,uBAAeA,kBAO9BA,CAAAA;QAEDA;;WAEGA;QACHA;YACIK,CAACA,CAACA,gBAAgBA,CAACA,CAACA,WAAWA,EAAEA,CAACA,IAAIA,CAACA,EAAEA,CAACA,CAACA;QAC/CA,CAACA;QAFeL,qBAAaA,gBAE5BA,CAAAA;QAEDA;;;;;;WAMGA;QACHA;YACIM,UAAUA,CAACA;gBACPC,CAACA,CAACA,OAAOA,CAACA,CAACA,IAAIA,CAACA,UAAUA,EACtBA,CAACA,gBAAgBA,CAACA,IAAIA,CAACA,CAACA,CAACA,aAAaA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA;gBACpDA,SAASA,CAACA,KAAKA,CAACA,aAAaA,EAAEA,CAACA;YACpCA,CAACA,EAAED,CAACA,CAACA,CAACA;QACVA,CAACA;QANeN,wBAAgBA,mBAM/BA,CAAAA;QAQDA;;;;;;;WAOGA;QACHA,kBAAkBA,SAAkBA;YAChCQ,IAAIA,QAAQA,GAAGA,CAACA,CAACA,gBAAgBA,CAACA,CAACA;YACnCA,IAAIA,GAAGA,GAAaA,EAAEA,CAACA;YACvBA,GAAGA,CAACA,GAAGA,CAACA,MAAMA,CAACA,GAAGA,OAAOA,CAACA;YAC1BA,EAAEA,CAACA,CAACA,SAASA,CAACA,CAACA,CAACA;gBACZA,GAAGA,CAACA,GAAGA,CAACA,MAAMA,CAACA,GAAGA,QAAQA,CAACA,GAAGA,GAAGA,GAAGA,GAAGA,GAAGA,CAACA;gBAC3CA,GAAGA,CAACA,GAAGA,CAACA,MAAMA,CAACA,GAAGA,iBAAiBA,CAAAA;YAC1CA,CAACA;YACEA,IAAIA,IAAIA,GAAGA,GAAGA,CAACA,IAAIA,CAACA,EAAEA,CAACA,CAACA;YACxBA,IAAIA,IAAIA,GAAGA,CAACA,CAACA,sBAAsBA,CAACA,CAACA;YACrCA,CAACA,CAACA,IAAIA,CAACA;gBACHA,GAAGA,EAAEA,IAAIA;gBACTA,IAAIA,EAAEA,MAAMA;gBACZA,QAAQA,EAAEA,MAAMA;gBAChBA,IAAIA,EAAEA,IAAIA,CAACA,SAASA,EAAEA;gBACtBA,OAAOA,EAAEA,IAAIA;gBACbA,KAAKA,EAAEA,UAASA,KAAgBA,EAAEA,UAAkBA,EAAEA,WAAmBA;oBACrE,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBACzC,EAAE,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC,CAAC;wBAC1B,QAAQ,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;oBAChF,CAAC;oBAAC,IAAI,CAAC,CAAC;wBACJ,QAAQ,CAAC,IAAI,CAAC,oCAAoC;4BAC9C,UAAU,GAAG,wBAAwB,GAAG,WAAW,GAAG,GAAG,CAAC,CAAC;oBACnE,CAAC;gBACL,CAAC;gBACDA,OAAOA,EAAEA,UAASA,QAA0BA;oBACxC,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;wBACtB,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;4BACnB,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;4BAC3C,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;wBAClC,CAAC;wBAAC,IAAI,CAAC,CAAC;4BACJ,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;gCACnB,EAAE,CAAC,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,CAAC,CAAC;oCACvD,QAAQ,CAAC,IAAI,CAAC,CAAC;gCACnB,CAAC;gCAAC,IAAI,CAAC,CAAC;oCACJ,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oCACzC,QAAQ,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;gCAC3D,CAAC;4BACL,CAAC;wBACL,CAAC;oBACL,CAAC;oBAAC,IAAI,CAAC,CAAC;wBACJ,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;wBACzC,QAAQ,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;oBAC7E,CAAC;gBACL,CAAC;aACJA,CAACA,CAACA;QACPA,CAACA;QAEDR;;;;;WAKGA;QACHA;YACIS,uEAAuEA;YACvEA,EAAEA,CAACA,CAACA,KAAKA,CAACA;gBAACA,KAAKA,CAACA,IAAIA,EAAEA,CAACA;YACxBA,IAAIA,qBAAqBA,GAAGA,KAAKA,CAACA;YAClCA,IAAIA,IAAIA,GAAGA,CAACA,CAACA,CAACA,SAASA,CAACA,CAACA,GAAGA,EAAEA,IAAIA,MAAMA,CAACA,CAACA;YAC1CA,EAAEA,CAACA,CAACA,IAAIA,CAACA,CAACA,CAACA;gBACPA,QAAQA,CAACA,KAAKA,CAACA,CAACA;YACpBA,CAACA;YAACA,IAAIA,CAACA,CAACA;gBACJA,IAAIA,GAAGA,GAAaA,EAAEA,CAACA;gBACvBA,GAAGA,CAACA,GAAGA,CAACA,MAAMA,CAACA,GAAGA,OAAOA,CAACA;gBAC1BA,EAAEA,CAACA,CAACA,QAAQA,CAACA,GAAGA,CAACA,CAACA,CAACA;oBACfA,GAAGA,CAACA,GAAGA,CAACA,MAAMA,CAACA,GAAGA,GAAGA,CAACA;gBAC1BA,CAACA;gBAACA,IAAIA,CAACA,CAACA;oBACJA,GAAGA,CAACA,GAAGA,CAACA,MAAMA,CAACA,GAAGA,GAAGA,CAACA;gBAC1BA,CAACA;gBACDA,SAASA,CAACA,QAAQA,CAACA,GAAGA,EAAEA,QAAQA,CAACA,CAACA;gBAClCA,SAASA,CAACA,QAAQA,CAACA,GAAGA,EAAEA,SAASA,CAACA,CAACA;gBACnCA,SAASA,CAACA,QAAQA,CAACA,GAAGA,EAAEA,OAAOA,CAACA,CAACA;gBACjCA,SAASA,CAACA,QAAQA,CAACA,GAAGA,EAAEA,aAAaA,CAACA,CAACA;gBACvCA,SAASA,CAACA,QAAQA,CAACA,GAAGA,EAAEA,OAAOA,CAACA,CAACA;gBACjCA,IAAIA,IAAIA,GAAGA,GAAGA,CAACA,IAAIA,CAACA,EAAEA,CAACA,CAACA;gBACxBA,IAAIA,GAAGA,GAAGA,QAAQA,CAACA,QAAQA,CAACA;gBAC5BA,IAAIA,iBAAiBA,GAAGA,GAAGA,CAACA,IAAIA,CAACA,MAAMA,GAAGA,GAAGA,CAACA,QAAQA,CAACA,MAAMA;sBACvDA,GAAGA,CAACA,MAAMA,CAACA,MAAMA,CAACA;gBACxBA,IAAIA,UAAUA,GAAGA,IAAIA,CAACA,MAAMA,CAACA;gBAC7BA,IAAIA,SAASA,GAAGA,UAAUA,GAAGA,iBAAiBA,CAACA;gBAE/CA,wEAAwEA;gBACxEA,0CAA0CA;gBAC1CA,EAAEA,CAACA,CAACA,UAAUA,GAAGA,IAAIA,IAAIA,SAASA,GAAGA,IAAIA,CAACA,CAACA,CAACA;oBACxCA,KAAKA,CAACA,oEAAoEA;0BACpEA,8DAA8DA,CAACA,CAACA;oBACtEA,qBAAqBA,GAAGA,IAAIA,CAACA;gBACjCA,CAACA;gBAACA,IAAIA,CAACA,CAACA;oBACJA,mDAAmDA;oBACnDA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,GAAGA,IAAIA,CAACA;gBAClCA,CAACA;YACLA,CAACA;YAEDA,yEAAyEA;YACzEA,cAAcA;YACdA,MAAMA,CAACA,qBAAqBA,CAACA;QACjCA,CAACA;QA1CeT,gBAAQA,WA0CvBA,CAAAA;QAEDA,uBAA8BA,WAAmBA;YAC7CU,KAAKA,CAACA,QAAQA,CAACA,WAAWA,CAACA,IAAIA,EAAEA,CAACA,CAACA;QACvCA,CAACA;QAFeV,qBAAaA,gBAE5BA,CAAAA;QAEDA;YACIW,MAAMA,CAACA,KAAKA,CAACA,QAAQA,EAAEA,CAACA,IAAIA,EAAEA,CAACA;QACnCA,CAACA;QAFeX,qBAAaA,gBAE5BA,CAAAA;QAEDA;YACIY,MAAMA,CAACA,KAAKA,CAACA;QACjBA,CAACA;QAFeZ,gBAAQA,WAEvBA,CAAAA;QAEDA;YACIa,EAAEA,CAACA,CAACA,CAACA,CAACA,UAAUA,CAACA,CAACA,GAAGA,EAAEA,IAAIA,QAAQA,CAACA,CAACA,CAACA;gBAClCA,SAASA,EAAEA,CAACA;YAChBA,CAACA;YAACA,IAAIA,CAACA,CAACA;gBACJA,UAAUA,EAAEA,CAACA;YACjBA,CAACA;QACLA,CAACA;QANeb,mBAAWA,cAM1BA,CAAAA;QAEDA;YACIc,SAASA,CAACA,WAAWA,CAACA,eAAeA,CAACA,gBAAgBA,CAACA,CAACA;YAExDA,KAAKA,GAAGA,KAAKA,CAACA,YAAYA,CAAsBA,QAAQA,CAACA,cAAcA,CAACA,OAAOA,CAACA,EAAEA;gBAC9EA,gBAAgBA,EAAEA,IAAIA,CAAAA,qFAAqFA;aAC9GA,CAACA,CAACA;YACHA,4HAA4HA;YAC5HA,mFAAmFA;YACnFA,gHAAgHA;YAChHA,CAACA,CAACA,KAAKA,CAACA,iBAAiBA,EAAEA,CAACA,CAACA,GAAGA,CAACA,EAACA,UAAUA,EAAEA,MAAMA,EAAEA,OAAOA,EAAEA,OAAOA,EAACA,CAACA,CAACA;YACzEA,gIAAgIA;YAChIA,KAAKA,CAACA,OAAOA,EAAEA,CAACA;QACpBA,CAACA;QAEDd;YACIe,EAAEA,CAACA,CAACA,KAAKA,CAACA,CAACA,CAACA;gBACRA,mGAAmGA;gBACnGA,sCAAsCA;gBACtCA,KAAKA,CAACA,UAAUA,EAAEA,CAACA;gBACnBA,KAAKA,GAAGA,IAAIA,CAACA;YACjBA,CAACA;QACLA,CAACA;IAELf,CAACA,EA3OaD,KAAKA,GAALA,eAAKA,KAALA,eAAKA,QA2OlBA;AACLA,CAACA,EA9OM,SAAS,KAAT,SAAS,QA8Of;AAMD,SAAS,CAAC,OAAO,CAAC;IACdiB;;;;;;;;OAQGA;IACHA,qCAAqCA,KAAaA;QAC9CC,IAAIA,IAAIA,GAAGA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,CAACA;QAClCA,IAAIA,QAAQA,GAAGA,IAAIA,CAACA,SAASA,CAACA,IAAIA,CAACA,OAAOA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA,CAACA,SAASA,CAC1DA,IAAIA,CAACA,OAAOA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA,CAACA,KAAKA,CAACA,kBAAkBA,CAACA,KAAKA,CAACA,CAACA,CAACA;QAC5DA,IAAIA,MAAMA,GAAGA,EAAEA,CAACA;QAChBA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,QAAQA,CAACA,MAAMA,GAAGA,CAACA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;YACvCA,IAAIA,IAAIA,GAAGA,QAAQA,CAACA,CAACA,CAACA,CAACA,KAAKA,CAACA,GAAGA,CAACA,CAACA;YAClCA,IAAIA,KAAKA,GAAGA,kBAAkBA,CAACA,IAAIA,CAACA,CAACA,CAACA,CAACA,CAACA,OAAOA,CAACA,KAAKA,EAAEA,GAAGA,CAACA,CAACA;YAC5DA,EAAEA,CAACA,CAACA,IAAIA,CAACA,CAACA,CAACA,IAAIA,KAAKA,CAACA,CAACA,CAACA;gBACnBA,MAAMA,GAAGA,KAAKA,CAACA;YACnBA,CAACA;QACLA,CAACA;QACDA,EAAEA,CAACA,CAACA,CAACA,MAAMA,CAACA,CAACA,CAACA;YACVA,MAAMA,GAAGA,SAASA,CAACA,SAASA,CAACA,KAAKA,CAACA,CAACA;QACxCA,CAACA;QACDA,MAAMA,CAACA,MAAMA,CAACA;IAClBA,CAACA;IAEDD,gCAAgCA,UAAkBA,EAAEA,QAAgBA;QAChEE,CAACA,CAACA,OAAOA,CAACA,OAAOA,EAAEA;YACfA,MAAMA,EAAEA,KAAKA;YACbA,KAAKA,EAAEA,UAAUA;YACjBA,GAAGA,EAAEA,QAAQA;SAChBA,EAAEA,UAASA,QAA2BA;YAC/B,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;gBACrB,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YACtD,CAAC;QACL,CAAC,CAACA,CAACA;IACXA,CAACA;IAEDF,gGAAgGA;IAChGA,kGAAkGA;IAClGA,SAASA,CAACA,KAAKA,CAACA,WAAWA,EAAEA,CAACA;IAE9BA,0EAA0EA;IAC1EA,sEAAsEA;IACtEA,mEAAmEA;IACnEA,wEAAwEA;IACxEA,6CAA6CA;IAC7CA,IAAIA,KAAKA,GAAGA,2BAA2BA,CAACA,OAAOA,CAACA,CAACA;IACjDA,EAAEA,CAACA,CAACA,KAAKA,CAACA,CAACA,CAACA;QACRA,IAAIA,GAAGA,GAAGA,2BAA2BA,CAACA,KAAKA,CAACA,CAACA;QAC7CA,EAAEA,CAACA,CAACA,GAAGA,IAAIA,IAAIA,IAAIA,GAAGA,IAAIA,MAAMA,CAACA,CAACA,CAACA;YAC/BA,sBAAsBA,CAACA,KAAKA,EAAEA,GAAGA,CAACA,CAACA;QACvCA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACJA,SAASA,CAACA,KAAKA,CAACA,aAAaA,CAACA,KAAKA,CAACA,CAACA;QACzCA,CAACA;IACLA,CAACA;IACDA,SAASA,CAACA,KAAKA,CAACA,cAAcA,EAAEA,CAACA;IAEjCA,oEAAoEA;IACpEA,cAAcA;IACdA,SAASA,CAACA,KAAKA,CAACA,aAAaA,CAACA,CAACA,CAACA,IAAIA,CAACA,SAASA,CAACA,KAAKA,CAACA,aAAaA,EAAEA,CAACA,CAACA,CAACA;IAEvEA,2EAA2EA;IAC3EA,cAAcA;IACdA,IAAIA,UAAUA,GAAGA,UAASA,EAAUA;QAChC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,uBAAuBG,CAACA,CAACA,SAASA,CAACA,CAACA,GAAGA,CAACA,EAAEA,CAACA,CAACA,CAACA,CAACA,CAAC,CAAC;IACtE,CAAC,CAACH;IACFA,UAAUA,CAACA,MAAMA,CAACA,CAACA;IACnBA,UAAUA,CAACA,MAAMA,CAACA,CAACA;IAEnBA,uEAAuEA;IACvEA,CAACA,CAACA,aAAaA,CAACA,CAACA,IAAIA,CAACA,mBAAmBA,EAAEA,SAASA,CAACA,KAAKA,CAACA,gBAAgBA,CAACA,CAACA;IAE7EA,uEAAuEA;IACvEA,CAACA,CAACA,QAAQA,CAACA,CAACA,IAAIA,CAACA,mBAAmBA,EAAEA,SAASA,CAACA,KAAKA,CAACA,aAAaA,CAACA,CAACA;IACrEA,EAAEA,CAACA,CAACA,SAASA,CAACA,KAAKA,CAACA,QAAQA,EAAEA,CAACA,CAACA,CAACA;QAC7BA,SAASA,CAACA,KAAKA,CAACA,QAAQA,EAAEA,CAACA,EAAEA,CAACA,QAAQA,EAClCA,SAASA,CAACA,KAAKA,CAACA,aAAaA,CAACA,CAACA;IACvCA,CAACA;IAEDA,uEAAuEA;IACvEA,+BAA+BA;IAC/BA,EAAEA,CAACA,CAACA,CAACA,CAACA,qBAAqBA,CAACA,CAACA,EAAEA,CAACA,WAAWA,CAACA,CAACA,CAACA,CAACA;QAC3CA,CAACA,CAACA,eAAeA,CAACA,CAACA,IAAIA,CAACA,SAASA,EAAEA,KAAKA,CAACA,CAACA,IAAIA,CAACA,UAAUA,EAAEA,IAAIA,CAACA,CAACA;IACrEA,CAACA;AACLA,CAACA,CAAC,CAAC"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/saved-queries.js b/core/http/workbench/src/main/webapp/scripts/saved-queries.js new file mode 100644 index 00000000000..e62855cef90 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/saved-queries.js @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +var workbench; +(function (workbench) { + var savedQueries; + (function (savedQueries) { + function deleteQuery(savedBy, name, urn) { + var currentUser = workbench.getCookie("server-user"); + if ((!savedBy || currentUser == savedBy)) { + if (confirm("'" + + name + + "' will no longer be accessible, even using your browser's history. " + + "Do you really wish to delete it?")) { + document.forms.namedItem(urn).submit(); + } + } + else { + alert("'" + name + "' was saved by user '" + savedBy + "'.\nUser '" + + currentUser + "' is not allowed do delete it."); + } + } + savedQueries.deleteQuery = deleteQuery; + function toggleElement(urn, suffix) { + var htmlElement = document.getElementById(urn + suffix); + htmlElement.style.display = (htmlElement.style.display == 'none') ? '' : 'none'; + } + var yasqeInstances = {}; + function toggleYasqe(urn) { + if (yasqeInstances[urn]) { + //hide it + if (yasqeInstances[urn]) { + yasqeInstances[urn].toTextArea(); //simple way to close instances + yasqeInstances[urn] = null; + } + //now we only have the text-area. Hide that element as well + document.getElementById(urn + '-text').style.display = 'none'; + } + else { + //show it + var el = document.getElementById(urn + '-text'); + //but: somehow the xsl adds lots of spaces before/after the saved query. Couldnt figure out why, so just trim the string before initialization + el.value = el.value.trim(); + yasqeInstances[urn] = YASQE.fromTextArea(el, { readOnly: 'nocursor', createShareLink: null }); //initialize as read-only + $(yasqeInstances[urn].getWrapperElement()).css({ "fontSize": "14px", "height": "auto" }); //set height to auto, i.e. resize to fit content + //we made a change to the css wrapper element (and did so after initialization). So, force a manual update of the yasqe instance + yasqeInstances[urn].refresh(); + } + } + function toggle(urn) { + toggleElement(urn, '-metadata'); + toggleYasqe(urn); + var toggle = document.getElementById(urn + '-toggle'); + var attr = 'value'; + var show = 'Show'; + var text = toggle.getAttribute(attr) == show ? 'Hide' : show; + toggle.setAttribute(attr, text); + } + savedQueries.toggle = toggle; + })(savedQueries = workbench.savedQueries || (workbench.savedQueries = {})); +})(workbench || (workbench = {})); +workbench + .addLoad(function () { + // not using jQuery.html(...) for this since it doesn't do the + // whitespace correctly + var queries = document.getElementsByTagName('pre'); + for (var i = 0; i < queries.length; i++) { + queries[i].innerHTML = queries[i].innerHTML.trim(); + } + $('[name="edit-query"]').find('[name="query"]').each(function () { + $(this).attr('value', $(this).attr('value').trim()); + }); +}); +//# sourceMappingURL=saved-queries.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/saved-queries.js.map b/core/http/workbench/src/main/webapp/scripts/saved-queries.js.map new file mode 100644 index 00000000000..e5ef29450e8 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/saved-queries.js.map @@ -0,0 +1 @@ +{"version":3,"file":"saved-queries.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["saved-queries.ts"],"names":["workbench","workbench.savedQueries","workbench.savedQueries.deleteQuery","workbench.savedQueries.toggleElement","workbench.savedQueries.toggleYasqe","workbench.savedQueries.toggle"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AAEpC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,IAAO,SAAS,CA4Df;AA5DD,WAAO,SAAS,EAAC,CAAC;IAEdA,IAAcA,YAAYA,CAyDzBA;IAzDDA,WAAcA,YAAYA,EAACA,CAACA;QAIxBC,qBAA4BA,OAAeA,EAAEA,IAAYA,EAAEA,GAAWA;YAClEC,IAAIA,WAAWA,GAAGA,SAASA,CAACA,SAASA,CAACA,aAAaA,CAACA,CAACA;YACrDA,EAAEA,CAACA,CAACA,CAACA,CAACA,OAAOA,IAAIA,WAAWA,IAAIA,OAAOA,CAACA,CAACA,CAACA,CAACA;gBACvCA,EAAEA,CAACA,CAACA,OAAOA,CAACA,GAAGA;sBACTA,IAAIA;sBACJA,qEAAqEA;sBACrEA,kCAAkCA,CAACA,CAACA,CAACA,CAACA;oBACtBA,QAAQA,CAACA,KAAKA,CAACA,SAASA,CAACA,GAAGA,CAAEA,CAACA,MAAMA,EAAEA,CAACA;gBAC9DA,CAACA;YACLA,CAACA;YAACA,IAAIA,CAACA,CAACA;gBACJA,KAAKA,CAACA,GAAGA,GAAGA,IAAIA,GAAGA,uBAAuBA,GAAGA,OAAOA,GAAGA,YAAYA;sBAC7DA,WAAWA,GAAGA,gCAAgCA,CAACA,CAACA;YAC1DA,CAACA;QACLA,CAACA;QAbeD,wBAAWA,cAa1BA,CAAAA;QAEDA,uBAAuBA,GAAWA,EAAEA,MAAcA;YAC/CE,IAAIA,WAAWA,GAAGA,QAAQA,CAACA,cAAcA,CAACA,GAAGA,GAAGA,MAAMA,CAACA,CAACA;YAC3DA,WAAWA,CAACA,KAAKA,CAACA,OAAOA,GAAGA,CAACA,WAAWA,CAACA,KAAKA,CAACA,OAAOA,IAAIA,MAAMA,CAACA,GAAGA,EAAEA,GAAGA,MAAMA,CAACA;QAChFA,CAACA;QACDF,IAAIA,cAAcA,GAA4BA,EAAEA,CAACA;QACjDA,qBAAqBA,GAAWA;YAC5BG,EAAEA,CAACA,CAACA,cAAcA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA;gBACtBA,SAASA;gBACTA,EAAEA,CAACA,CAACA,cAAcA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA;oBACtBA,cAAcA,CAACA,GAAGA,CAACA,CAACA,UAAUA,EAAEA,CAACA,CAAAA,+BAA+BA;oBAChEA,cAAcA,CAACA,GAAGA,CAACA,GAAGA,IAAIA,CAACA;gBAC/BA,CAACA;gBACDA,2DAA2DA;gBAC3DA,QAAQA,CAACA,cAAcA,CAACA,GAAGA,GAAGA,OAAOA,CAACA,CAACA,KAAKA,CAACA,OAAOA,GAAGA,MAAMA,CAACA;YAClEA,CAACA;YAACA,IAAIA,CAACA,CAACA;gBACJA,SAASA;gBACTA,IAAIA,EAAEA,GAAqBA,QAAQA,CAACA,cAAcA,CAACA,GAAGA,GAAGA,OAAOA,CAACA,CAACA;gBAClEA,8IAA8IA;gBAC9IA,EAAEA,CAACA,KAAKA,GAAGA,EAAEA,CAACA,KAAKA,CAACA,IAAIA,EAAEA,CAACA;gBAC3BA,cAAcA,CAACA,GAAGA,CAACA,GAAGA,KAAKA,CAACA,YAAYA,CAACA,EAAEA,EAAEA,EAACA,QAAQA,EAAEA,UAAUA,EAAEA,eAAeA,EAAEA,IAAIA,EAACA,CAACA,CAACA,CAAAA,yBAAyBA;gBACrHA,CAACA,CAACA,cAAcA,CAACA,GAAGA,CAACA,CAACA,iBAAiBA,EAAEA,CAACA,CAACA,GAAGA,CAACA,EAACA,UAAUA,EAAEA,MAAMA,EAAEA,QAAQA,EAAEA,MAAMA,EAACA,CAACA,CAACA,CAAAA,gDAAgDA;gBACvIA,gIAAgIA;gBAChIA,cAAcA,CAACA,GAAGA,CAACA,CAACA,OAAOA,EAAEA,CAACA;YAClCA,CAACA;QACLA,CAACA;QAGDH,gBAAuBA,GAAWA;YAC9BI,aAAaA,CAACA,GAAGA,EAAEA,WAAWA,CAACA,CAACA;YAChCA,WAAWA,CAACA,GAAGA,CAACA,CAACA;YAEjBA,IAAIA,MAAMA,GAAGA,QAAQA,CAACA,cAAcA,CAACA,GAAGA,GAAGA,SAASA,CAACA,CAACA;YACtDA,IAAIA,IAAIA,GAAGA,OAAOA,CAACA;YACnBA,IAAIA,IAAIA,GAAGA,MAAMA,CAACA;YAClBA,IAAIA,IAAIA,GAAGA,MAAMA,CAACA,YAAYA,CAACA,IAAIA,CAACA,IAAIA,IAAIA,GAAGA,MAAMA,GAAGA,IAAIA,CAACA;YAC7DA,MAAMA,CAACA,YAAYA,CAACA,IAAIA,EAAEA,IAAIA,CAACA,CAACA;QAEpCA,CAACA;QAVeJ,mBAAMA,SAUrBA,CAAAA;IACLA,CAACA,EAzDaD,YAAYA,GAAZA,sBAAYA,KAAZA,sBAAYA,QAyDzBA;AACLA,CAACA,EA5DM,SAAS,KAAT,SAAS,QA4Df;AAED,SAAS;KACJ,OAAO,CAAC;IACL,+DAA+D;IAC/D,uBAAuB;IACvB,IAAI,OAAO,GAAG,QAAQ,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;IACnD,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACvD,CAAC;IAED,CAAC,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC;QACjD,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/template.js b/core/http/workbench/src/main/webapp/scripts/template.js new file mode 100644 index 00000000000..6ab1ed6e5f6 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/template.js @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +var workbench; +(function (workbench) { + // The following is to allow composed XSLT style sheets to each add + // functions to the window.onload event. + function chain(args) { + return function () { + for (var i = 0; i < args.length; i++) { + args[i](); + } + }; + } + // Note that the way this is currently constructed, functions added with + // addLoad() will be executed in the order that they were added. + // + // @see + // http://onwebdevelopment.blogspot.com/2008/07/chaining-functions-in-javascript.html + // @param fn + // function to add + function addLoad(fn) { + window.onload = typeof (window.onload) == 'function' ? chain([ + window.onload, fn]) : fn; + } + workbench.addLoad = addLoad; + /** + * Retrieves the value of the cookie with the given name. + * + * @param {String} name The name of the cookie to retrieve. + * @returns {String} The value of the given cookie, or an empty string if it + * doesn't exist. + */ + function getCookie(name) { + var cookies = document.cookie.split(';'); + var rval = ''; + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i]; + var eq = cookie.indexOf('='); + if (name == cookie.substr(0, eq).replace(/^\s+|\s+$/g, '')) { + rval = decodeURIComponent(cookie.substr(eq + 1).replace(/\+/g, '%20')); + break; + } + } + return rval; + } + workbench.getCookie = getCookie; + /** + * Parses workbench URL query strings into processable arrays. + * + * @returns an array of the 'name=value' substrings of the URL query string + */ + function getQueryStringElements() { + var href = document.location.href; + return href.substring(href.indexOf('?') + 1).split(decodeURIComponent('%26')); + } + workbench.getQueryStringElements = getQueryStringElements; + /** + * Utility method for assembling the query string for a request URL. + * + * @param sb + * string buffer, actually an array of strings to be joined later + * @param id + * name of parameter to add, also the id of the document element + * to get the value from + */ + function addParam(sb, id) { + sb[sb.length] = id + '='; + var tag = document.getElementById(id); + sb[sb.length] = tag.type == 'checkbox' ? String(tag.checked) : + encodeURIComponent(tag.value); + sb[sb.length] = '&'; + } + workbench.addParam = addParam; +})(workbench || (workbench = {})); +/** + * Code to run when the document loads: eliminate the 'noscript' warning + * message, and display an unauthenticated user properly. + */ +workbench + .addLoad(function () { + document.getElementById('noscript-message').style.display = 'none'; + var user = workbench.getCookie('server-user'); + if (user.length == 0 || user == '""') { + user = 'None'; + } + var selectedUser = document.getElementById('selected-user'); + selectedUser.innerHTML = user; +}); +//# sourceMappingURL=template.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/template.js.map b/core/http/workbench/src/main/webapp/scripts/template.js.map new file mode 100644 index 00000000000..8bee1f0b9bb --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/template.js.map @@ -0,0 +1 @@ +{"version":3,"file":"template.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["template.ts"],"names":["workbench","workbench.chain","workbench.addLoad","workbench.getCookie","workbench.getQueryStringElements","workbench.addParam"],"mappings":"AAAA,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,IAAO,SAAS,CA6Ef;AA7ED,WAAO,SAAS,EAAC,CAAC;IAMdA,mEAAmEA;IACnEA,wCAAwCA;IACxCA,eAAeA,IAAmBA;QAC1BC,MAAMA,CAACA;YACP,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACnC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACd,CAAC;QACL,CAAC,CAAAA;IACLA,CAACA;IAEDD,wEAAwEA;IACxEA,gEAAgEA;IAChEA,EAAEA;IACFA,OAAOA;IACPA,qFAAqFA;IACrFA,YAAYA;IACZA,kBAAkBA;IAClBA,iBAAwBA,EAAeA;QACnCE,MAAMA,CAACA,MAAMA,GAAGA,OAAOA,CAACA,MAAMA,CAACA,MAAMA,CAACA,IAAIA,UAAUA,GAAGA,KAAKA,CAACA;YACzDA,MAAMA,CAACA,MAAMA,EAAEA,EAAEA,CAACA,CAACA,GAAGA,EAAEA,CAACA;IACjCA,CAACA;IAHeF,iBAAOA,UAGtBA,CAAAA;IAEDA;;;;;;OAMGA;IACHA,mBAA0BA,IAAYA;QAClCG,IAAIA,OAAOA,GAAGA,QAAQA,CAACA,MAAMA,CAACA,KAAKA,CAACA,GAAGA,CAACA,CAACA;QACzCA,IAAIA,IAAIA,GAAGA,EAAEA,CAACA;QACdA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,CAACA,GAAGA,OAAOA,CAACA,MAAMA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;YACtCA,IAAIA,MAAMA,GAAGA,OAAOA,CAACA,CAACA,CAACA,CAACA;YACxBA,IAAIA,EAAEA,GAAGA,MAAMA,CAACA,OAAOA,CAACA,GAAGA,CAACA,CAACA;YAC7BA,EAAEA,CAACA,CAACA,IAAIA,IAAIA,MAAMA,CAACA,MAAMA,CAACA,CAACA,EAAEA,EAAEA,CAACA,CAACA,OAAOA,CAACA,YAAYA,EAAEA,EAAEA,CAACA,CAACA,CAACA,CAACA;gBACzDA,IAAIA,GAAGA,kBAAkBA,CAACA,MAAMA,CAACA,MAAMA,CAACA,EAAEA,GAAGA,CAACA,CAACA,CAACA,OAAOA,CAACA,KAAKA,EACzDA,KAAKA,CAACA,CAACA,CAACA;gBACZA,KAAKA,CAACA;YACVA,CAACA;QACLA,CAACA;QACDA,MAAMA,CAACA,IAAIA,CAACA;IAChBA,CAACA;IAbeH,mBAASA,YAaxBA,CAAAA;IAEDA;;;;OAIGA;IACHA;QACII,IAAIA,IAAIA,GAAGA,QAAQA,CAACA,QAAQA,CAACA,IAAIA,CAACA;QAClCA,MAAMA,CAACA,IAAIA,CAACA,SAASA,CAACA,IAAIA,CAACA,OAAOA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA,CAACA,KAAKA,CAC9CA,kBAAkBA,CAACA,KAAKA,CAACA,CAACA,CAACA;IACnCA,CAACA;IAJeJ,gCAAsBA,yBAIrCA,CAAAA;IAEDA;;;;;;;;OAQGA;IACHA,kBAAyBA,EAAYA,EAAEA,EAAUA;QAC7CK,EAAEA,CAACA,EAAEA,CAACA,MAAMA,CAACA,GAAGA,EAAEA,GAAGA,GAAGA,CAACA;QACzBA,IAAIA,GAAGA,GAAqBA,QAAQA,CAACA,cAAcA,CAACA,EAAEA,CAACA,CAACA;QACxDA,EAAEA,CAACA,EAAEA,CAACA,MAAMA,CAACA,GAAGA,GAAGA,CAACA,IAAIA,IAAIA,UAAUA,GAAGA,MAAMA,CAACA,GAAGA,CAACA,OAAOA,CAACA;YAC5DA,kBAAkBA,CAACA,GAAGA,CAACA,KAAKA,CAACA,CAACA;QAC9BA,EAAEA,CAACA,EAAEA,CAACA,MAAMA,CAACA,GAAGA,GAAGA,CAACA;IACxBA,CAACA;IANeL,kBAAQA,WAMvBA,CAAAA;AACLA,CAACA,EA7EM,SAAS,KAAT,SAAS,QA6Ef;AAED;;;GAGG;AACH,SAAS;KACJ,OAAO,CAAC;IACL,QAAQ,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IACnE,IAAI,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IAC9C,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC;QACnC,IAAI,GAAG,oCAAoC,CAAC;IAChD,CAAC;IACD,IAAI,YAAY,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;IAC5D,YAAY,CAAC,SAAS,GAAG,IAAI,CAAC;AAClC,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/ts/add.ts b/core/http/workbench/src/main/webapp/scripts/ts/add.ts new file mode 100644 index 00000000000..eb51d3b9723 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/add.ts @@ -0,0 +1,73 @@ +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +module workbench { + + export module add { + + export function handleFormatSelection(selected: string) { + if (selected == 'application/x-trig' || selected == 'application/trix' + || selected == 'text/x-nquads') { + $('#useForContext').prop('checked', false); + $('#context').val('').prop('readonly', false); + } + } + + function setContextFromBaseURI() { + var baseURI = $('#baseURI').val(); + $('#context').val(baseURI == '' ? '' : '<' + baseURI + '>'); + } + + export function handleBaseURIUse() { + if ($('#useForContext').prop('checked')) { + setContextFromBaseURI(); + } + } + + export function enabledInput(selected: string) { + var istext = (selected == 'text'); + $('#text').prop('disabled', !istext); + var contentType = $('#Content-Type'); + var firstType = contentType.find('option:first'); + firstType.prop('disabled', true); + $('#source-' + selected).prop('checked', true); + var isfile = (selected == 'file'); + var file = $('#file'); + file.prop('disabled', !isfile); + var isurl = (selected == 'url'); + var url = $('#url'); + url.prop('disabled', !isurl); + if (istext) { + var turtle = contentType.find("option[value='application/x-turtle']"); + if (turtle.length == 0) { + turtle = contentType.find("option[value='text/turtle']"); + } + if (turtle.length > 0) { + turtle.prop('selected', true); + } + } + else { + firstType.prop('selected', true); + var baseURI = $('#baseURI'); + var checked = $('#useForContext').prop('checked'); + if (isfile) { + baseURI.val(file.val() == '' ? '' : encodeURI('file://' + + file.val().replace(/\\/g, '/'))); + if (checked) { + setContextFromBaseURI(); + } + } + else if (isurl) { + baseURI.val(url.val()); + if (checked) { + setContextFromBaseURI(); + } + } + } + } + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/ts/create-federate.ts b/core/http/workbench/src/main/webapp/scripts/ts/create-federate.ts new file mode 100644 index 00000000000..b54e292d365 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/create-federate.ts @@ -0,0 +1,51 @@ +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +workbench.addLoad(function createFederatePageLoaded() { + function respondToFormState() { + var memberID = $('input.memberID'); + var enoughMembers = memberID.filter(':checked').length >= 2; + if (enoughMembers) { + $('#create-feedback').hide(); + } else { + $('#create-feedback').show(); + } + var fedID = $('#id').val(); + var validID = /.+/.test(fedID); + var disable = !(validID && enoughMembers); + var matchExisting = false; + + // test that fedID not equal any existing id + memberID.each(function() { + if (fedID == $(this).attr('value')) { + disable = true; + matchExisting = true; + return false; + } + }); + var recurseMessage = $('#recurse-message'); + if (matchExisting) { + recurseMessage.show(); + } else { + recurseMessage.hide(); + } + $('input#create').prop('disabled', disable); + } + + /** + * Calls another function with a delay of 0 msec. (Workaround for annoying + * browser behavior.) + */ + function timeoutRespond() { + setTimeout(respondToFormState, 0); + } + + respondToFormState(); + $('input.memberID').on('change', respondToFormState); + $("input[name='type']").on('change', respondToFormState); + $('#id').off().on('keydown paste cut', timeoutRespond); +}); diff --git a/core/http/workbench/src/main/webapp/scripts/ts/create.ts b/core/http/workbench/src/main/webapp/scripts/ts/create.ts new file mode 100644 index 00000000000..eb354631462 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/create.ts @@ -0,0 +1,72 @@ +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +module workbench { + + export module create { + export var id = $('#id'); + } +} + +/** + * Invoked by the "Create" button on the form for all but + * create-federate.xsl. Checks with the InfoServlet for the user-provided id + * for the existence of the id already, giving a chance to back out if it + * does. Depends on the current behavior of getting a failure response (500 + * Internal Server Error at present), when the ID does not exist. + */ +function checkOverwrite() { + var submit = false; + $.ajax({ + url: '../' + workbench.create.id.val() + '/info', + async: false, + success: function() { + submit = confirm( + 'WARNING: You are about to overwrite the ' + + 'configuration of an existing repository!'); + }, + statusCode: { + 500: + function() { + submit = true; + } + } + }); + if (submit) { + $("form[action='create']").submit(); + } +} + +workbench.addLoad(function createPageLoaded() { + /** + * Disables the create button if the id field doesn't have any text. + */ + function disableCreateIfEmptyId() { + $('input#create').prop('disabled', !(/.+/.test($('#id').val()))); + } + + // Populate parameters + var elements = workbench.getQueryStringElements(); + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + var value = decodeURIComponent(pair[1]).replace(/\+/g, ' '); + if (pair[0] == 'id') { + workbench.create.id.val(value); + } + if (pair[0] == 'title') { + $('#title').val(value); + } + } + + disableCreateIfEmptyId(); + + // Calls another function with a delay of 0 msec. (Workaround for + // annoying browser behavior.) + $('#id').on('keydown paste cut', function() { + setTimeout(disableCreateIfEmptyId, 0); + }); +}); diff --git a/core/http/workbench/src/main/webapp/scripts/ts/delete.ts b/core/http/workbench/src/main/webapp/scripts/ts/delete.ts new file mode 100644 index 00000000000..3366c8c5a3c --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/delete.ts @@ -0,0 +1,47 @@ +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +/** + * Invoked by the "Delete" button on the form in delete.xsl. Checks with the + * DeleteServlet whether the given ID has been proxied, giving a chance to back + * out if it is. + */ +function checkIsSafeToDelete() { + var id = $('#id').val(); + var submitForm = false; + var feedback = $('#delete-feedback'); + $ + .ajax({ + dataType : 'json', + url : 'delete', + async : false, + timeout : 5000, + data : { + checkSafe : id + }, + error : function(jqXHR, textStatus, errorThrown) { + if (textStatus == 'timeout') { + feedback + .text('The server seems unresponsive. Delete request not sent.'); + } else { + feedback + .text('There is a problem with the server. Delete request not sent. Error Type = ' + + textStatus + + ', HTTP Status Text = "' + + errorThrown + '"'); + } + }, + success : function(data) { + feedback.text(''); + submitForm = data.safe; + if (!submitForm) { + submitForm = confirm('WARNING: You are about to delete a repository that has been proxied by another repository!'); + } + } + }); + return submitForm; +} diff --git a/core/http/workbench/src/main/webapp/scripts/ts/explore.ts b/core/http/workbench/src/main/webapp/scripts/ts/explore.ts new file mode 100644 index 00000000000..062d2991139 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/explore.ts @@ -0,0 +1,86 @@ +/// +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +workbench.addLoad(function() { + function removeDuplicates(self:string) { + function textContent(element:HTMLElement) { + return $.trim(element.innerText || element.textContent); + } + + var lists = document.getElementsByTagName('ul'); + for (var i = lists.length - 1; i + 1; i--) { + var items = lists[i].getElementsByTagName('li'); + for (var j = items.length - 1; j; j--) { + var text = textContent(items[j]); + if (items[j].innerHTML == items[j - 1].innerHTML || text == self) { + items[j].parentNode.removeChild(items[j]); + } + } + + text = textContent(items[0]); + if (text == self) { + items[0].parentNode.removeChild(items[0]); + } + + if (items.length == 0) { + lists[i].parentNode.parentNode.removeChild(lists[i].parentNode); + } + } + } + + // Populate parameters + var elements = workbench.getQueryStringElements(); + var resource = $('#resource'); + var suffix = '_explore'; + var limit_param = workbench.paging.LIMIT + suffix; + var limit_id = workbench.paging.LIM_ID + suffix; + var limit_param_found = false; + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + var value = decodeURIComponent(pair[1]).replace(/\+/g, ' '); + if ('resource' == pair[0]) { + resource.val(value); + } + else if (limit_param == pair[0]) { + $(limit_id).val(value); + limit_param_found = true; + } + } + if (!limit_param_found){ + var limit_cookie = workbench.getCookie(limit_param); + if (limit_cookie) { + $(limit_id).val(limit_cookie); + } + } + var explore = 'explore'; + workbench.paging.correctButtons(explore); + var content = document.getElementById('content'); + var h1 = content.getElementsByTagName('h1')[0]; + var rvalue=resource.val(); + if (rvalue) { + h1.appendChild(document.createTextNode(' (' + rvalue + ')')); + removeDuplicates(rvalue); + var limit = workbench.paging.getLimit(explore); + + // Modify title to reflect total_result_count cookie + var total_result_count = workbench.paging.getTotalResultCount(); + var have_total_count = (total_result_count > 0); + var offset = limit == 0 ? 0 : workbench.paging.getOffset(); + var first = offset + 1; + var last = limit == 0 ? total_result_count : offset + limit; + + // Truncate range if close to end. + last = have_total_count ? Math.min(total_result_count, last) : last; + var newHTML = '(' + first + '-' + last; + if (have_total_count) { + newHTML = newHTML + ' of ' + total_result_count; + } + h1.appendChild(document.createTextNode(newHTML + ')')); + } + workbench.paging.setShowDataTypesCheckboxAndSetChangeEvent(); +}); \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/ts/export.ts b/core/http/workbench/src/main/webapp/scripts/ts/export.ts new file mode 100644 index 00000000000..9ad7cf90a1b --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/export.ts @@ -0,0 +1,22 @@ +/// +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit +// the corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +workbench.addLoad(function () { + var suffix = '_explore'; + var limitParam = workbench.paging.LIMIT + suffix; + var limitElement = $(workbench.paging.LIM_ID + suffix); + + function setElement(num: string) { + limitElement.val(String(parseInt(0 + num, 10))); + } + + setElement(workbench.paging.hasQueryParameter(limitParam) ? + workbench.paging.getQueryParameter(limitParam) : + workbench.getCookie(limitParam) + ); +}); \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/ts/namespaces.ts b/core/http/workbench/src/main/webapp/scripts/ts/namespaces.ts new file mode 100644 index 00000000000..dc26c1d44fe --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/namespaces.ts @@ -0,0 +1,21 @@ +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +module workbench { + + export module namespaces { + + /** + * Invoked by #prefix-select element in namespaces.xsl. + */ + export function updatePrefix() { + var select = $('#prefix-select'); + $('#prefix').val(select.find('option:selected').text()); + $('#namespace').val(select.val()); + } + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/ts/paging.ts b/core/http/workbench/src/main/webapp/scripts/ts/paging.ts new file mode 100644 index 00000000000..888520967d7 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/paging.ts @@ -0,0 +1,290 @@ +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +module workbench { + + export module paging { + + var KT = 'know_total'; + + var OFFSET = 'offset'; + + export var LIMIT = 'limit'; + + export var LIM_ID = '#' + LIMIT; + + var AMP = decodeURIComponent('%26'); + + function addCookieToUrlQueryIfPresent(url: string, name: string){ + var value = workbench.getCookie(name); + if (value) { + url = url + AMP + name + '=' + value; + } + return url; + } + + /** + * Invoked in graph.xsl and tuple.xsl for download functionality. Takes a + * document element by name, and creates a request with it as a parameter. + */ + export function addGraphParam(name: string) { + var value = encodeURIComponent($('#' + name).val()); + var url = document.location.href; + var ref = workbench.getCookie('ref'); + if (url.match(/query$/)) { // looking at POST query results? + if ('id' == ref) { + url = url + ';ref=id' + AMP + 'action=exec'; + url = addCookieToUrlQueryIfPresent(url, 'query'); + url = addCookieToUrlQueryIfPresent(url, 'queryLn'); + url = addCookieToUrlQueryIfPresent(url, 'infer'); + url = addCookieToUrlQueryIfPresent(url, 'limit_query'); + } else { + alert("Can't put query in URL, since it might be too long for your browser.\n" + + "Save your query on the server, then execute it from the 'Saved Queries' page."); + return; + } + } + if (url.indexOf('?') + 1 || url.indexOf(';') + 1) { + document.location.href = url + AMP + name + '=' + value; + } else { + document.location.href = url + ';' + name + '=' + value; + } + } + + class StringMap { + [key: string]: string; + } + + /** + * Scans the given URI for duplicate query parameter names, and removes + * all but the last occurrence for any duplicate case. + * + * @param {String} href The URI to simplify. + * @returns {String} The URI with only the last occurrence of any + * given parameter name remaining. + */ + function simplifyParameters(href: string) { + var params:StringMap = {}; + var rval = ''; + var queryString = getQueryString(href); + var start = href.substring(0, href.indexOf(queryString)); + var elements = queryString.split(decodeURIComponent('%26')); + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + params[pair[0]] = pair[1]; + // Keep looping. We are interested in the last value. + } + for (var name in params) { + // use hasOwnProperty to filter out keys from the + // Object.prototype + if (params.hasOwnProperty(name)) { + rval += name + '=' + params[name] + AMP; + } + } + rval = start + rval.substring(0, rval.length - 1); + return rval; + } + + + /** + * First, adds the given parameter to the URL query string. Second, + * adds a 'know_total' parameter if its current value is 'false' or + * non-existent. Third, simplifies the URL. Fourth, sends the browser + * to the modified URL. + * + * @param {String} name The name of the query parameter. + * @param {number} value The value of the query parameter. + */ + export function addPagingParam(name: string, value: number) { + var url = document.location.href; + var hasParams = (url.indexOf('?') + 1 || url.indexOf(';') + 1); + var sep = hasParams ? AMP : ';'; + url = url + sep + name + '=' + value; + if (!hasQueryParameter(KT) || 'false' == getQueryParameter(KT)) { + url += AMP + KT + '=' + getTotalResultCount(); + } + if (!hasQueryParameter('query')) { + url += AMP + 'query=' + workbench.getCookie('query'); + url += AMP + 'ref=' + workbench.getCookie('ref'); + } + document.location.href = simplifyParameters(url); + } + + /** + * Invoked in tuple.xsl and explore.xsl. Changes the limit query + * parameter and navigates to the new URL. + */ + export function addLimit(page: string) { + var suffix = '_' + page; + addPagingParam(LIMIT + suffix, $(LIM_ID + suffix).val()); + } + + /** + * Invoked in tuple.xsl and explore.xsl. Increments the offset query + * parameter, and navigates to the new URL. + */ + export function nextOffset(page: string) { + addPagingParam(OFFSET, getOffset() + getLimit(page)); + } + + /** + * Invoked in tuple.xsl and explore.xsl. Decrements the offset query + * parameter and navigates to the new URL. + */ + export function previousOffset(page: string) { + addPagingParam(OFFSET, Math.max(0, getOffset() - getLimit(page))); + } + + /** + * @returns {number} The value of the offset query parameter. + */ + export function getOffset() { + var offset = getQueryParameter(OFFSET); + return ('' == offset) ? 0 : parseInt(offset, 10); + } + + /** + * @returns {number} The value of the limit query parameter. + */ + export function getLimit(page: string): number { + return parseInt($(LIM_ID + '_' + page).val(), 10); + } + + /** + * Retrieves the URL query parameter with the given name. + * + * @param {String} name The name of the parameter to retrieve. + * @returns {String} The value of the given parameter, or an empty + * string if it doesn't exist. + */ + export function getQueryParameter(name: string): string { + var rval = ''; + var elements = getQueryString(document.location.href).split(decodeURIComponent('%26')); + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + if (name != pair[0]) { + continue; + } + rval = pair[1]; + // Keep looping. We are interested in the last value. + } + return rval; + } + + /** + * Gets whether a URL query parameter with the given name is present. + * + * @param {String} name The name of the parameter to retrieve. + * @returns {Boolean} True, if a parameter with the given name is in + * the URL. Otherwise, false. + */ + export function hasQueryParameter(name: string) { + var rval = false; + var elements = getQueryString(document.location.href).split(decodeURIComponent('%26')); + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + if (name == pair[0]) { + rval = true; + break; + } + } + return rval; + } + + /** + * Convenience function for returning the tail of a string after a + * given character. + * + * @param {String} value The string to get the tail of. + * @param split + * character to give tail after + * @returns The substring after the 'split' character, or the original + * string if 'split' is not found. + */ + function tailAfter(value: string, split: string): string { + return value.substring(value.indexOf(split) + 1); + } + + export function getQueryString(href: string) { + return tailAfter(tailAfter(href, '?'), ';'); + } + + /** + * Using the value of the 'limit' query parameter, correct the text of the + * Next and Previous buttons. Makes use of RegExp to preserve any + * localization. + */ + export function correctButtons(page: string) { + var buttonWordPattern = /^[A-z]+\s+/; + var nextButton = $('#nextX'); + var oldNext = nextButton.val(); + var count = parseInt(/\d+$/.exec(oldNext)[0], 10); + var limit = workbench.paging.getLimit(page); + nextButton.val(buttonWordPattern.exec(oldNext)[0] + limit); + var previousButton = $('#previousX'); + previousButton + .val(buttonWordPattern.exec(previousButton.val())[0] + limit); + var offset = workbench.paging.getOffset(); + previousButton.prop('disabled', (offset <= 0 || limit <= 0)); + nextButton.prop('disabled', + (count < limit || limit <= 0 || (offset + count) >= getTotalResultCount())); + } + + /** + * Gets the total result count, preferably from the 'know_total' query + * parameter. If the parameter doesn't exist, get it from the + * 'total_result_count' cookie. + * + * @returns {Number} The given total result count, or zero if it isn't + * given. + */ + export function getTotalResultCount() { + var total_result_count = 0; + var s_trc = workbench.paging.getQueryParameter(KT); + if (s_trc.length == 0) { + s_trc = workbench.getCookie('total_result_count'); + } + + if (s_trc.length > 0) { + total_result_count = parseInt(s_trc, 10); + } + + return total_result_count; + } + + module DataTypeVisibility { + function setCookie(c_name: string, value: boolean, exdays: number) { + var exdate = new Date(); + exdate.setDate(exdate.getDate() + exdays); + document.cookie = c_name + "=" + value + + ((exdays == null) ? "" : + "; expires=" + exdate.toUTCString()); + } + + export function setShow(show: boolean) { + setCookie('show-datatypes', show, 365); + var data = show ? 'data-longform' : 'data-shortform'; + $('div.resource[' + data + ']').each(function() { + var me = $(this); + me.find('a:first').text(decodeURIComponent(me.attr(data))); + }); + } + } + + export function setShowDataTypesCheckboxAndSetChangeEvent() { + var hideDataTypes = (workbench.getCookie('show-datatypes') == 'false'); + var showDTcb = $("input[name='show-datatypes']"); + if (hideDataTypes) { + showDTcb.prop('checked', false); + DataTypeVisibility.setShow(false); + } + showDTcb.on('change', function() { + DataTypeVisibility.setShow(showDTcb.prop('checked')); + }); + } + } +} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/ts/query.ts b/core/http/workbench/src/main/webapp/scripts/ts/query.ts new file mode 100644 index 00000000000..f1ce519a7e5 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/query.ts @@ -0,0 +1,341 @@ +/// +/// +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +module workbench { + + export module query { + + /** + * JSON value provided by script element in document (see query.xsl). + */ + declare var sparqlNamespaces: any; + + /** + * Holds the current selected query language. + */ + var currentQueryLn = ''; + var yasqe: YASQE_Instance = null; + + /** + * Populate reasonable default name space declarations into the query text area. + * The server has provided the declaration text in hidden elements. + */ + export function loadNamespaces() { + function toggleNamespaces() { + workbench.query.setQueryValue(namespaces.text()); + currentQueryLn = queryLn; + } + + var query: string = workbench.query.getQueryValue(); + var queryLn = $('#queryLn').val(); + var namespaces = $('#' + queryLn + '-namespaces'); + var last = $('#' + currentQueryLn + '-namespaces'); + if (namespaces.length) { + if (!query || query.trim().length == 0) { + toggleNamespaces(); + } + if (last.length && (query == last.text())) { + toggleNamespaces(); + } + } + } + + /** + *Fires when the query language is changed + */ + export function onQlChange() { + workbench.query.loadNamespaces(); + workbench.query.updateYasqe(); + } + /** + * Invoked by the "clear" button. After confirming with the user, + * clears the query text and loads the current repository and query + * language name space declarations. + */ + export function resetNamespaces() { + if (confirm('Click OK to clear the current query text and replace' + + 'it with the ' + $('#queryLn').val() + + ' namespace declarations.')) { + workbench.query.setQueryValue(''); + workbench.query.loadNamespaces(); + } + } + + /** + * Clear any contents of the save feedback field. + */ + export function clearFeedback() { + $('#save-feedback').removeClass().text(''); + } + + /** + * Clear the save feedback field, and look at the contents of the query name + * field. Disables the save button if the field doesn't satisfy a given regular + * expression. With a delay of 200 msec, to give enough time after + * the event for the document to have changed. (Workaround for annoying browser + * behavior.) + */ + export function handleNameChange() { + setTimeout(function disableSaveIfNotValidName() { + $('#save').prop('disabled', + !/^[- \w]{1,32}$/.test($('#query-name').val())); + workbench.query.clearFeedback(); + }, 0); + } + + interface AjaxSaveResponse { + accessible: boolean; + existed: boolean; + written: boolean; + } + + /** + * Send a background HTTP request to save the query, and handle the + * response asynchronously. + * + * @param overwrite + * if true, add a URL parameter that tells the server we wish + * to overwrite any already saved query + */ + function ajaxSave(overwrite: boolean) { + var feedback = $('#save-feedback'); + var url: string[] = []; + url[url.length] = 'query'; + if (overwrite) { + url[url.length] = document.all ? ';' : '?'; + url[url.length] = 'overwrite=true&' + } + var href = url.join(''); + var form = $('form[action="query"]'); + $.ajax({ + url: href, + type: 'POST', + dataType: 'json', + data: form.serialize(), + timeout: 5000, + error: function(jqXHR: JQueryXHR, textStatus: string, errorThrown: string) { + feedback.removeClass().addClass('error'); + if (textStatus == 'timeout') { + feedback.text('Timed out waiting for response. Uncertain if save occured.'); + } else { + feedback.text('Save Request Failed: Error Type = ' + + textStatus + ', HTTP Status Text = "' + errorThrown + '"'); + } + }, + success: function(response: AjaxSaveResponse) { + if (response.accessible) { + if (response.written) { + feedback.removeClass().addClass('success'); + feedback.text('Query saved.'); + } else { + if (response.existed) { + if (confirm('Query name exists. Click OK to overwrite.')) { + ajaxSave(true); + } else { + feedback.removeClass().addClass('error'); + feedback.text('Cancelled overwriting existing query.'); + } + } + } + } else { + feedback.removeClass().addClass('error'); + feedback.text('Repository was not accessible (check your permissions).'); + } + } + }); + } + + /** + * Invoked by form submission. + * + * @returns {boolean} true if a form POST is performed, false if + * a GET is instead performed + */ + export function doSubmit() { + //if yasqe is instantiated, make sure we save the value to the textarea + if (yasqe) yasqe.save(); + var allowPageToSubmitForm = false; + var save = ($('#action').val() == 'save'); + if (save) { + ajaxSave(false); + } else { + var url: string[] = []; + url[url.length] = 'query'; + if (document.all) { + url[url.length] = ';'; + } else { + url[url.length] = '?'; + } + workbench.addParam(url, 'action'); + workbench.addParam(url, 'queryLn'); + workbench.addParam(url, 'query'); + workbench.addParam(url, 'limit_query'); + workbench.addParam(url, 'infer'); + var href = url.join(''); + var loc = document.location; + var currentBaseLength = loc.href.length - loc.pathname.length + - loc.search.length; + var pathLength = href.length; + var urlLength = pathLength + currentBaseLength; + + // Published Internet Explorer restrictions on URL length, which are the + // most restrictive of the major browsers. + if (pathLength > 2048 || urlLength > 2083) { + alert("Due to its length, your query will be posted in the request body. " + + "It won't be possible to use a bookmark for the results page."); + allowPageToSubmitForm = true; + } else { + // GET using the constructed URL, method exits here + document.location.href = href; + } + } + + // Value returned to form submit event. If not true, prevents normal form + // submission. + return allowPageToSubmitForm; + } + + export function setQueryValue(queryString: string): void { + yasqe.setValue(queryString.trim()); + } + + export function getQueryValue(): string { + return yasqe.getValue().trim(); + } + + export function getYasqe(): YASQE_Instance { + return yasqe; + } + + export function updateYasqe() { + if ($("#queryLn").val() == "SPARQL") { + initYasqe(); + } else { + closeYasqe(); + } + } + + function initYasqe() { + workbench.yasqeHelper.setupCompleters(sparqlNamespaces); + + yasqe = YASQE.fromTextArea(document.getElementById('query'), { + consumeShareLink: null//don't try to parse the url args. this is already done by the addLoad function below + }); + //some styling conflicts. Could add my own css file, but not a lot of things need changing, so just do this programmatically + //first, set the font size (otherwise font is as small as menu, which is too small) + //second, set the width. YASQE normally expands to 100%, but the use of a table requires us to set a fixed width + $(yasqe.getWrapperElement()).css({"fontSize": "14px", "width": "900px"}); + //we made a change to the css wrapper element (and did so after initialization). So, force a manual update of the yasqe instance + yasqe.refresh(); + } + + function closeYasqe() { + if (yasqe) { + //store yasqe value in text area (not sure whether this is desired, but it mimics current behavior) + //it closes the yasqe instance as well + yasqe.toTextArea(); + yasqe = null; + } + } + + } +} + +interface QueryTextResponse { + queryText: string; +} + +workbench.addLoad(function queryPageLoaded() { + /** + * Gets a parameter from the URL or the cookies, preferentially in that + * order. + * + * @param param + * the name of the parameter + * @returns the value of the given parameter, or something that evaluates + as false, if the parameter was not found + */ + function getParameterFromUrlOrCookie(param: string) { + var href = document.location.href; + var elements = href.substring(href.indexOf('?') + 1).substring( + href.indexOf(';') + 1).split(decodeURIComponent('%26')); + var result = ''; + for (var i = 0; elements.length - i; i++) { + var pair = elements[i].split('='); + var value = decodeURIComponent(pair[1]).replace(/\+/g, ' '); + if (pair[0] == param) { + result = value; + } + } + if (!result) { + result = workbench.getCookie(param); + } + return result; + } + + function getQueryTextFromServer(queryParam: string, refParam: string) { + $.getJSON('query', { + action: "get", + query: queryParam, + ref: refParam + }, function(response: QueryTextResponse) { + if (response.queryText) { + workbench.query.setQueryValue(response.queryText); + } + }); + } + + //Start with initializing our YASQE instance, given that 'SPARQL' is the selected query language + //(all the following 'set' and 'get' SPARQL query functions require an instantiated yasqe instance + workbench.query.updateYasqe(); + + // Populate the query text area with the value of the URL query parameter, + // only if it is present. If it is not present in the URL query, then + // looks for the 'query' cookie, and sets it from that. (The cookie + // enables re-populating the text field with the previous query when the + // user returns via the browser back button.) + var query = getParameterFromUrlOrCookie('query'); + if (query) { + var ref = getParameterFromUrlOrCookie('ref'); + if (ref == 'id' || ref == 'hash') { + getQueryTextFromServer(query, ref); + } else { + workbench.query.setQueryValue(query); + } + } + workbench.query.loadNamespaces(); + + // Trim the query text area contents of any leading and/or trailing + // whitespace. + workbench.query.setQueryValue($.trim(workbench.query.getQueryValue())); + + // Add click handlers identifying the clicked element in a hidden 'action' + // form field. + var addHandler = function(id: string) { + $('#' + id).click(function setAction() { $('#action').val(id); }); + }; + addHandler('exec'); + addHandler('save'); + + // Add event handlers to the save name field to react to changes in it. + $('#query-name').bind('keydown cut paste', workbench.query.handleNameChange); + + // Add event handlers to the query text area to react to changes in it. + $('#query').bind('keydown cut paste', workbench.query.clearFeedback); + if (workbench.query.getYasqe()) { + workbench.query.getYasqe().on('change', + workbench.query.clearFeedback); + } + + // Detect if there is no current authenticated user, and if so, disable + // the 'save privately' option. + if ($('#selected-user>span').is('.disabled')) { + $('#save-private').prop('checked', false).prop('disabled', true); + } +}); diff --git a/core/http/workbench/src/main/webapp/scripts/ts/saved-queries.ts b/core/http/workbench/src/main/webapp/scripts/ts/saved-queries.ts new file mode 100644 index 00000000000..56b7dd42a24 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/saved-queries.ts @@ -0,0 +1,82 @@ +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +module workbench { + + export module savedQueries { + //need to declar YASQE library for typescript compilation + declare var YASQE: any; + + export function deleteQuery(savedBy: string, name: string, urn: string) { + var currentUser = workbench.getCookie("server-user"); + if ((!savedBy || currentUser == savedBy)) { + if (confirm("'" + + name + + "' will no longer be accessible, even using your browser's history. " + + "Do you really wish to delete it?")) { + (document.forms.namedItem(urn)).submit(); + } + } else { + alert("'" + name + "' was saved by user '" + savedBy + "'.\nUser '" + + currentUser + "' is not allowed do delete it."); + } + } + + function toggleElement(urn: string, suffix: string) { + var htmlElement = document.getElementById(urn + suffix); + htmlElement.style.display = (htmlElement.style.display == 'none') ? '' : 'none'; + } + var yasqeInstances: { [index:string]: any } = {}; + function toggleYasqe(urn: string) { + if (yasqeInstances[urn]) { + //hide it + if (yasqeInstances[urn]) { + yasqeInstances[urn].toTextArea();//simple way to close instances + yasqeInstances[urn] = null; + } + //now we only have the text-area. Hide that element as well + document.getElementById(urn + '-text').style.display = 'none'; + } else { + //show it + var el = document.getElementById(urn + '-text'); + //but: somehow the xsl adds lots of spaces before/after the saved query. Couldnt figure out why, so just trim the string before initialization + el.value = el.value.trim(); + yasqeInstances[urn] = YASQE.fromTextArea(el, {readOnly: 'nocursor', createShareLink: null});//initialize as read-only + $(yasqeInstances[urn].getWrapperElement()).css({"fontSize": "14px", "height": "auto"});//set height to auto, i.e. resize to fit content + //we made a change to the css wrapper element (and did so after initialization). So, force a manual update of the yasqe instance + yasqeInstances[urn].refresh(); + } + } + + + export function toggle(urn: string) { + toggleElement(urn, '-metadata'); + toggleYasqe(urn); + + var toggle = document.getElementById(urn + '-toggle'); + var attr = 'value'; + var show = 'Show'; + var text = toggle.getAttribute(attr) == show ? 'Hide' : show; + toggle.setAttribute(attr, text); + + } + } +} + +workbench + .addLoad(function() { + // not using jQuery.html(...) for this since it doesn't do the + // whitespace correctly + var queries = document.getElementsByTagName('pre'); + for (var i = 0; i < queries.length; i++) { + queries[i].innerHTML = queries[i].innerHTML.trim(); + } + + $('[name="edit-query"]').find('[name="query"]').each(function() { + $(this).attr('value', $(this).attr('value').trim()); + }); + }); diff --git a/core/http/workbench/src/main/webapp/scripts/ts/template.ts b/core/http/workbench/src/main/webapp/scripts/ts/template.ts new file mode 100644 index 00000000000..bf5d4c265d6 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/template.ts @@ -0,0 +1,97 @@ +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +module workbench { + + export interface LoadRoutine { + (ev?: Event): void; + } + + // The following is to allow composed XSLT style sheets to each add + // functions to the window.onload event. + function chain(args: LoadRoutine[]): LoadRoutine { + return function() { + for (var i = 0; i < args.length; i++) { + args[i](); + } + } + } + + // Note that the way this is currently constructed, functions added with + // addLoad() will be executed in the order that they were added. + // + // @see + // http://onwebdevelopment.blogspot.com/2008/07/chaining-functions-in-javascript.html + // @param fn + // function to add + export function addLoad(fn: LoadRoutine) { + window.onload = typeof (window.onload) == 'function' ? chain([ + window.onload, fn]) : fn; + } + + /** + * Retrieves the value of the cookie with the given name. + * + * @param {String} name The name of the cookie to retrieve. + * @returns {String} The value of the given cookie, or an empty string if it + * doesn't exist. + */ + export function getCookie(name: string) { + var cookies = document.cookie.split(';'); + var rval = ''; + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i]; + var eq = cookie.indexOf('='); + if (name == cookie.substr(0, eq).replace(/^\s+|\s+$/g, '')) { + rval = decodeURIComponent(cookie.substr(eq + 1).replace(/\+/g, + '%20')); + break; + } + } + return rval; + } + + /** + * Parses workbench URL query strings into processable arrays. + * + * @returns an array of the 'name=value' substrings of the URL query string + */ + export function getQueryStringElements() { + var href = document.location.href; + return href.substring(href.indexOf('?') + 1).split( + decodeURIComponent('%26')); + } + + /** + * Utility method for assembling the query string for a request URL. + * + * @param sb + * string buffer, actually an array of strings to be joined later + * @param id + * name of parameter to add, also the id of the document element + * to get the value from + */ + export function addParam(sb: string[], id: string) { + sb[sb.length] = id + '='; + var tag = document.getElementById(id); + sb[sb.length] = tag.type == 'checkbox' ? String(tag.checked) : + encodeURIComponent(tag.value); + sb[sb.length] = '&'; + } +} + +/** + * Code to run when the document loads: eliminate the 'noscript' warning + * message, and display an unauthenticated user properly. + */ +workbench + .addLoad(function() { + document.getElementById('noscript-message').style.display = 'none'; + var user = workbench.getCookie('server-user'); + if (user.length == 0 || user == '""') { + user = 'None'; + } + var selectedUser = document.getElementById('selected-user'); + selectedUser.innerHTML = user; + }); diff --git a/core/http/workbench/src/main/webapp/scripts/ts/tuple.ts b/core/http/workbench/src/main/webapp/scripts/ts/tuple.ts new file mode 100644 index 00000000000..8dc5271207d --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/tuple.ts @@ -0,0 +1,44 @@ +/// +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit +// the corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +workbench.addLoad(function () { + + var query = 'query'; + var suffix = '_' + query; + var limitParam = workbench.paging.LIMIT + suffix; + var limitElement = $(workbench.paging.LIM_ID + suffix); + + function setElement(num: string) { + limitElement.val(String(parseInt(0 + num, 10))); + } + + setElement(workbench.paging.hasQueryParameter(limitParam) ? + workbench.paging.getQueryParameter(limitParam) : + workbench.getCookie(limitParam) + ); + workbench.paging.correctButtons(query); + var limit = workbench.paging.getLimit(query); // Number + + // Modify title to reflect total_result_count cookie + if (limit > 0) { + var h1 = document.getElementById('title_heading'); + var total_result_count = workbench.paging.getTotalResultCount(); + var have_total_count = (total_result_count > 0); + var offset = workbench.paging.getOffset(); + var first = offset + 1; + var last = offset + limit; + last = have_total_count ? Math.min(total_result_count, last) : last; + var newHTML = /^.*\(/.exec(h1.innerHTML)[0] + first + '-' + last; + if (have_total_count) { + newHTML = newHTML + ' of ' + total_result_count; + } + newHTML = newHTML + ')'; + h1.innerHTML = newHTML; + } + workbench.paging.setShowDataTypesCheckboxAndSetChangeEvent(); +}); diff --git a/core/http/workbench/src/main/webapp/scripts/ts/update.ts b/core/http/workbench/src/main/webapp/scripts/ts/update.ts new file mode 100644 index 00000000000..228b75095e9 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/ts/update.ts @@ -0,0 +1,76 @@ +/// +/// +/// + +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. + +module workbench { + + export module update { + + // Need to declare YASQE library for typescript compilation. + declare var YASQE:any; + declare var namespaces:{string:string}; + var yasqe:any = null; + + export function initYasqe() { + workbench.yasqeHelper.setupCompleters(namespaces); + yasqe = YASQE.fromTextArea(document.getElementById('update'), { + createShareLink: function () { + return {update: yasqe.getValue()}; + }, + consumeShareLink: function (yasqe:any, args:any) { + if (args.update) yasqe.setValue(args.update) + }, + + // This way, we don't conflict with the YASQE editor of the + // regular query interface, and we show the most recent + // -update- query. + persistent: "update" + + }); + + // Some styling conflicts. Could add my own css file, but not a + // lot of things need changing, so just do this programmatically. + // First, set the font size (otherwise font is as small as menu, + // which is too small). Second, set the width. YASQE normally + // expands to 100%, but the use of a table requires us to set a + // fixed width. + $(yasqe.getWrapperElement()).css({ + "fontSize": "14px", + "width": "900px" + }); + + // We made a change to the css wrapper element (and did so after + // initialization). So, force a manual update of the yasqe + // instance. + yasqe.refresh(); + + // If the text area we instantiated YASQE on has no query val, + // then show a regular default update query. + if (yasqe.getValue().trim().length == 0) { + yasqe.setValue('INSERT DATA {\n\t '+ + ' .\n}'); + } + } + + /** + * Invoked upon form submission. + * + * @returns {boolean} true, always + */ + export function doSubmit() { + // Save yasqe content to text area. + if (yasqe) { + yasqe.save(); + } + return true; + } + } +} + +workbench.addLoad(function updatePageLoaded() { + workbench.update.initYasqe(); +}); diff --git a/core/http/workbench/src/main/webapp/scripts/tuple.js b/core/http/workbench/src/main/webapp/scripts/tuple.js new file mode 100644 index 00000000000..1f5cee98b85 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/tuple.js @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit +// the corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +workbench.addLoad(function () { + var query = 'query'; + var suffix = '_' + query; + var limitParam = workbench.paging.LIMIT + suffix; + var limitElement = $(workbench.paging.LIM_ID + suffix); + function setElement(num) { + limitElement.val(String(parseInt(0 + num, 10))); + } + setElement(workbench.paging.hasQueryParameter(limitParam) ? + workbench.paging.getQueryParameter(limitParam) : + workbench.getCookie(limitParam)); + workbench.paging.correctButtons(query); + var limit = workbench.paging.getLimit(query); // Number + // Modify title to reflect total_result_count cookie + if (limit > 0) { + var h1 = document.getElementById('title_heading'); + var total_result_count = workbench.paging.getTotalResultCount(); + var have_total_count = (total_result_count > 0); + var offset = workbench.paging.getOffset(); + var first = offset + 1; + var last = offset + limit; + last = have_total_count ? Math.min(total_result_count, last) : last; + var newHTML = /^.*\(/.exec(h1.innerHTML)[0] + first + '-' + last; + if (have_total_count) { + newHTML = newHTML + ' of ' + total_result_count; + } + newHTML = newHTML + ')'; + h1.innerHTML = newHTML; + } + workbench.paging.setShowDataTypesCheckboxAndSetChangeEvent(); +}); +//# sourceMappingURL=tuple.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/tuple.js.map b/core/http/workbench/src/main/webapp/scripts/tuple.js.map new file mode 100644 index 00000000000..2f54d4e481e --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/tuple.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tuple.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["tuple.ts"],"names":["setElement"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AACpC,kCAAkC;AAElC,2EAA2E;AAC3E,yEAAyE;AACzE,4EAA4E;AAE5E,SAAS,CAAC,OAAO,CAAC;IAEd,IAAI,KAAK,GAAG,OAAO,CAAC;IACpB,IAAI,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC;IACzB,IAAI,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC;IACjD,IAAI,YAAY,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAEvD,oBAAoB,GAAW;QAC3BA,YAAYA,CAACA,GAAGA,CAACA,MAAMA,CAACA,QAAQA,CAACA,CAACA,GAAGA,GAAGA,EAAEA,EAAEA,CAACA,CAACA,CAACA,CAACA;IACpDA,CAACA;IAED,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC;QACrD,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC;QAC9C,SAAS,CAAC,SAAS,CAAC,UAAU,CAAC,CAClC,CAAC;IACF,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;IAEvD,oDAAoD;IACpD,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;QACZ,IAAI,EAAE,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAClD,IAAI,kBAAkB,GAAG,SAAS,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAChE,IAAI,gBAAgB,GAAG,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC;QAChD,IAAI,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QAC1C,IAAI,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;QACvB,IAAI,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC;QAC1B,IAAI,GAAG,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC;QACpE,IAAI,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC;QACjE,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;YACnB,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,kBAAkB,CAAC;QACpD,CAAC;QACD,OAAO,GAAG,OAAO,GAAG,GAAG,CAAC;QACxB,EAAE,CAAC,SAAS,GAAG,OAAO,CAAC;IAC3B,CAAC;IACD,SAAS,CAAC,MAAM,CAAC,yCAAyC,EAAE,CAAC;AACjE,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/update.js b/core/http/workbench/src/main/webapp/scripts/update.js new file mode 100644 index 00000000000..8cd8262ed79 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/update.js @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/// +/// +/// +// WARNING: Do not edit the *.js version of this file. Instead, always edit the +// corresponding *.ts source in the ts subfolder, and then invoke the +// compileTypescript.sh bash script to generate new *.js and *.js.map files. +var workbench; +(function (workbench) { + var update; + (function (update) { + var yasqe = null; + function initYasqe() { + workbench.yasqeHelper.setupCompleters(namespaces); + yasqe = YASQE.fromTextArea(document.getElementById('update'), { + createShareLink: function () { + return { update: yasqe.getValue() }; + }, + consumeShareLink: function (yasqe, args) { + if (args.update) + yasqe.setValue(args.update); + }, + // This way, we don't conflict with the YASQE editor of the + // regular query interface, and we show the most recent + // -update- query. + persistent: "update" + }); + // Some styling conflicts. Could add my own css file, but not a + // lot of things need changing, so just do this programmatically. + // First, set the font size (otherwise font is as small as menu, + // which is too small). Second, set the width. YASQE normally + // expands to 100%, but the use of a table requires us to set a + // fixed width. + $(yasqe.getWrapperElement()).css({ + "fontSize": "14px", + "width": "900px" + }); + // We made a change to the css wrapper element (and did so after + // initialization). So, force a manual update of the yasqe + // instance. + yasqe.refresh(); + // If the text area we instantiated YASQE on has no query val, + // then show a regular default update query. + if (yasqe.getValue().trim().length == 0) { + yasqe.setValue('INSERT DATA {\n\t ' + + ' .\n}'); + } + } + update.initYasqe = initYasqe; + /** + * Invoked upon form submission. + * + * @returns {boolean} true, always + */ + function doSubmit() { + // Save yasqe content to text area. + if (yasqe) { + yasqe.save(); + } + return true; + } + update.doSubmit = doSubmit; + })(update = workbench.update || (workbench.update = {})); +})(workbench || (workbench = {})); +workbench.addLoad(function updatePageLoaded() { + workbench.update.initYasqe(); +}); +//# sourceMappingURL=update.js.map \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/scripts/update.js.map b/core/http/workbench/src/main/webapp/scripts/update.js.map new file mode 100644 index 00000000000..6b7aa221664 --- /dev/null +++ b/core/http/workbench/src/main/webapp/scripts/update.js.map @@ -0,0 +1 @@ +{"version":3,"file":"update.js","sourceRoot":"/openrdf-workbench/scripts/ts/","sources":["update.ts"],"names":["workbench","workbench.update","workbench.update.initYasqe","workbench.update.doSubmit","updatePageLoaded"],"mappings":"AAAA,oCAAoC;AACpC,oCAAoC;AACpC,uCAAuC;AAEvC,+EAA+E;AAC/E,qEAAqE;AACrE,4EAA4E;AAE5E,IAAO,SAAS,CA+Df;AA/DD,WAAO,SAAS,EAAC,CAAC;IAEdA,IAAcA,MAAMA,CA4DnBA;IA5DDA,WAAcA,MAAMA,EAACA,CAACA;QAKlBC,IAAIA,KAAKA,GAAOA,IAAIA,CAACA;QAErBA;YACIC,SAASA,CAACA,WAAWA,CAACA,eAAeA,CAACA,UAAUA,CAACA,CAACA;YAClDA,KAAKA,GAAGA,KAAKA,CAACA,YAAYA,CAACA,QAAQA,CAACA,cAAcA,CAACA,QAAQA,CAACA,EAAEA;gBAC1DA,eAAeA,EAAEA;oBACb,MAAM,CAAC,EAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAC,CAAC;gBACtC,CAAC;gBACDA,gBAAgBA,EAAEA,UAAUA,KAASA,EAAEA,IAAQA;oBAC3C,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;wBAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBAChD,CAAC;gBAEDA,2DAA2DA;gBAC3DA,uDAAuDA;gBACvDA,kBAAkBA;gBAClBA,UAAUA,EAAEA,QAAQA;aAEvBA,CAACA,CAACA;YAEHA,+DAA+DA;YAC/DA,iEAAiEA;YACjEA,gEAAgEA;YAChEA,6DAA6DA;YAC7DA,+DAA+DA;YAC/DA,eAAeA;YACfA,CAACA,CAACA,KAAKA,CAACA,iBAAiBA,EAAEA,CAACA,CAACA,GAAGA,CAACA;gBAC7BA,UAAUA,EAAEA,MAAMA;gBAClBA,OAAOA,EAAEA,OAAOA;aACnBA,CAACA,CAACA;YAEHA,gEAAgEA;YAChEA,0DAA0DA;YAC1DA,YAAYA;YACZA,KAAKA,CAACA,OAAOA,EAAEA,CAACA;YAEhBA,8DAA8DA;YAC9DA,4CAA4CA;YAC5CA,EAAEA,CAACA,CAACA,KAAKA,CAACA,QAAQA,EAAEA,CAACA,IAAIA,EAAEA,CAACA,MAAMA,IAAIA,CAACA,CAACA,CAACA,CAACA;gBACtCA,KAAKA,CAACA,QAAQA,CAACA,uCAAuCA;oBAClDA,+CAA+CA,CAACA,CAACA;YACzDA,CAACA;QACLA,CAACA;QAvCeD,gBAASA,YAuCxBA,CAAAA;QAEDA;;;;WAIGA;QACHA;YACIE,mCAAmCA;YACnCA,EAAEA,CAACA,CAACA,KAAKA,CAACA,CAACA,CAACA;gBACRA,KAAKA,CAACA,IAAIA,EAAEA,CAACA;YACjBA,CAACA;YACDA,MAAMA,CAACA,IAAIA,CAACA;QAChBA,CAACA;QANeF,eAAQA,WAMvBA,CAAAA;IACLA,CAACA,EA5DaD,MAAMA,GAANA,gBAAMA,KAANA,gBAAMA,QA4DnBA;AACLA,CAACA,EA/DM,SAAS,KAAT,SAAS,QA+Df;AAED,SAAS,CAAC,OAAO,CAAC;IACdI,SAASA,CAACA,MAAMA,CAACA,SAASA,EAAEA,CAACA;AACjCA,CAACA,CAAC,CAAC"} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/styles/basic/all.css b/core/http/workbench/src/main/webapp/styles/basic/all.css new file mode 100644 index 00000000000..542578c6f4f --- /dev/null +++ b/core/http/workbench/src/main/webapp/styles/basic/all.css @@ -0,0 +1,5 @@ +@import url(../w3-html40-recommended.css); + +img { + border: 0; +} diff --git a/core/http/workbench/src/main/webapp/styles/default/images/hr_menu.png b/core/http/workbench/src/main/webapp/styles/default/images/hr_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..1c4f27f0a2cfd21b3697e5d3b1a5afce7355ccb4 GIT binary patch literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^`+%5~ zn{IgdOvq`8oXt74-pqq+9xfqL!O6?SD_@+S{W7Pd-f~4{(SyZyaVa0t>}JirJ5TbC zN~3jDoban3i_gu@G~Kmd=!%W%hrszdMk&VfXLa-ZSBQExqQ&&R&05_W*;A XLsG}eYh^Qm_A_|8`njxgN@xNA?H^Mn literal 0 HcmV?d00001 diff --git a/core/http/workbench/src/main/webapp/styles/default/print.css b/core/http/workbench/src/main/webapp/styles/default/print.css new file mode 100644 index 00000000000..c22520f1a2e --- /dev/null +++ b/core/http/workbench/src/main/webapp/styles/default/print.css @@ -0,0 +1,27 @@ +@import url(../w3-html40-recommended.css); + +html, body { + color: #000; + background: #fff; + font-family: "Times New Roman", "Times", serif; + font-size: 100%; + line-height: 110%; +} + +h1 { + page-break-before: avoid; +} + +th,td { + vertical-align: top; + text-align: left; +} + +#header, #navigation, #contentheader { + display: none; +} + +#footer { + position: absolute; + bottom: 2em; +} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/styles/default/screen.css b/core/http/workbench/src/main/webapp/styles/default/screen.css new file mode 100644 index 00000000000..360887e3b35 --- /dev/null +++ b/core/http/workbench/src/main/webapp/styles/default/screen.css @@ -0,0 +1,539 @@ +@import url(../w3-html40-recommended.css); + +html,body { + margin: 0; + border: 0; + padding: 0; + color: #000; + line-height: 100%; + font-size: 100%; + font-family: Georgia, Times New Roman, Times Roman, Times, serif; +} + +html { + overflow: scroll; +} + +body { + background: linear-gradient(#757575, #D0D0D0 150px, #FFFFFF); + filter: progid:DXImageTransform.Microsoft.gradient( + startColorstr='#757575', endColorstr='#ffffff',GradientType=0 ); /* IE6-9 */ + background-repeat: no-repeat; +} + +a:link,a:active,a:visited,a:hover { + color: #0863AD; + text-decoration: underline; +} + +a:active { + outline: none; +} + +h1,h2,h3,h4 { + color: #000; + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-weight: bold; + white-space: nowrap; +} + +div,p,fieldset,img { + margin: 0; + border: 0; + padding: 0; + background: transparent; +} + +img { + vertical-align: middle; +} + +input,select { + display: inline; + vertical-align: middle; + margin: 1pt; +} + +ul { + margin: 0; + margin-bottom: 10px; + padding: 0; + list-style-type: disc; +} + +li { + margin: 0; + margin-left: 16px; + padding: 0; +} + +table,th,td { + margin: 0; + border: 0; + padding: 0; + border-collapse: collapse; +} + +th,td { + vertical-align: top; + text-align: left; +} + +hr { + margin: 0; + border: 0; + padding: 0; + height: 1px; + color: #0863AD; + background-color: #0863AD; +} + +a.resourceURL { + margin-left: 8px; + visibility: hidden; +} + +div.resource:hover > a.resourceURL { + visibility: visible; +} + +#header { + padding: 5px 0 0 5px; + height: 50px; +} + +.productgroup { + position: absolute; + right: 0; + margin-top: -8px; +} + +#search { + position: absolute; + margin-top: 34px; + width: 95%; + text-align: right; +} + +#search form,#search p { + margin: 0; + border: 0; + padding: 0; +} + +#search form { + margin: 7px; +} + +#search input { + font-size: 83%; + color: #000; +} + +#search img { + margin-top: 2px; +} + +#navigation { + position: absolute; + left: 0; + margin: 10px 0 0 5px; + padding: 0; + width: 190px; + background: url(images/hr_menu.png); + background: #D0D0D0; + background-repeat: no-repeat; + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-weight: bold; + font-size: 83%;; + margin: 10px 0 0 5px; +} + +#navigation a:link,#navigation a:visited,#navigation a:active,#navigation a:hover { + color: #000; + text-decoration: none; +} + +#navigation a:hover { + color: #0863AD; + text-decoration: underline; +} + +#navigation ul { + margin: 2px 0 0 0; + list-style-type: none; +} + +#navigation li { + margin: 0; + padding: 3px 0px 6px 10px; + background: url(images/hr_menu.png); + background-repeat: no-repeat; + background-position: bottom; +} + +#navigation .current { + background: #DEDEDE url(images/hr_menu.png); + background-repeat: no-repeat; + background-position: bottom; +} + +#navigation ul.group { + margin: 1px 0 -4px -10px; + padding-bottom: 3px; + background: #EFEFEF; + background-repeat: no-repeat; + background-position: bottom; + font-size: 83%; +} + +#navigation .group li { + padding: 0px 0 1px 15px; + background: transparent; +} + +#navigation .group li.current,#navigation .group li.current a:link,#navigation .group li.current a:visited,#navigation .group li.current a:active,#navigation .group li.current a:hover + { + color: #0863AD; +} + +#navigation .group li.current .subgroup,#navigation .group li.current .subgroup a:link,#navigation .group li.current .subgroup a:visited,#navigation .group li.current .subgroup a:active,#navigation .group li.current .subgroup a:hover + { + color: #000; +} + +#navigation ul.subgroup { + margin: 3px 0 3px -15px; + background: transparent; +} + +#navigation .subgroup li { + padding: 0px 0 1px 20px; +} + +#navigation .subgroup li.current { + background: #DEDEDE; +} + +#contentheader { + margin-left: 200px; + padding: 10px 20px 10px 15px; + height: 55px; + color: #FFF; + font-weight: bold; + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-size: 83%; +} + +#contentheader hr { + color: #666; + background-color: #666; + height: 1px; +} + +#contentheader th, #contentheader td { + color: #FFF; + font-weight: bold; + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-size: 83%; +} + +#contentheader h3,#contentheader p,#contentheader table,#contentheader ul { + margin: 0; + padding: 0; +} + +#contentheader td, #contentheader th { + margin: 0; + padding: 0 0 0 5px; +} + +#contentheader th:after { + content: ':'; +} + +#contentheader .change,#contentheader .disabled { + text-transform: lowercase; +} + +#contentheader .change:before { + content: '['; +} + +#contentheader .change:after { + content: ']'; +} + +#contentheader .disabled:before { + content: '- '; +} + +#contentheader .disabled:after { + content: ' -'; +} + +#tabs { + float: right; + position: relative; + top: -15px; + text-align: right; +} + +#tabs ul { + list-style-type: none; +} + +#tabs a:link,#tabs a:visited,#tabs a:active { + color: #0863AD; + text-decoration: none; +} + +#tabs a:hover { + color: #FFF; + text-decoration: underline; +} + +#tabs li { + display: inline; + margin: 0 0 0 20px; + font-weight: bold; +} + +.disabled { + color: #666; +} + +#content { + position: relative; + top: 5px; + margin-left: 200px; + padding: 15px 20px 15px 15px; + min-height: 350px; + font-size: 83%; +} + +#content th, #content td { + font-size: 83%; +} + +#content p { + margin: 0; + margin-bottom: 15px; +} + +#content h1,#content h2,#content h3 { + padding: 0; + font-weight: bold; +} + +#content h1 { + margin: 0 0 4px 0; + padding: 0 0 10px 0; + border-bottom: 1px solid #666; + font-size: 250%; +} + +#content h2 { + margin: 5px 0 5px 0; + padding-top: 10px; + font-size: 120%;; +} + +#content h2>a:link,#content h2>a:active,#content h2>a:hover,#content h2>a:visited { + text-decoration: none; +} + +#content h3 { + margin: 0; + margin-top: 5px; + color: #333; + font-size: 100%; +} + +.queryResult { + margin: 6em 6em; + font-size: 200%; +} + +#message { + margin: 5px 0; + padding: 5px; +} + +#message p { + margin: 0; + border: 0; + padding: 0; + color: #000; +} + +#message img { + float: left; + margin-right: 5px; +} + +.ERROR { + border: 2px solid #F00; + background: #FCC; +} + +.WARN { + border: 2px solid #FF0; + background: #FFC; +} + +.INFO { + border: 2px solid #0863AD; + background: #CCF; +} + +#footer { + clear: both; + margin-left: 200px; + padding: 0 20px 15px 15px; + color: #333; + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-size: 83%; +} + +#footer p { + border-top: 1px solid #666; + padding-top: 3px; +} + +#footer a:link,#footer a:active,#footer a:visited { + text-decoration: none; +} + +#footer a:hover { + text-decoration: underline; +} + +.simple th:after { + content: ':'; +} + +.simple th,.simple td { + padding-right: 5px; +} + +table.screenshots { + width: 100%; +} + +.screenshots td { + width: 50%; +} + +.captions td { + padding-bottom: 10px; +} + +.button { + float: right; + margin-left: 15px; + margin-bottom: 3px; +} + +.screenshot { + float: right; + margin-left: 15px; + margin-bottom: 5px; +} + +.sidebar { + float: right; + margin-left: 15px; + margin-bottom: 5px; +} + +.introduction,.tagline { + color: #0863AD; +} + +.introduction { + clear: both; + margin-top: -5px; + margin-bottom: 0px; + padding: 5px 30px 10px 30px; + border-bottom: 1px solid #666; +} + +.data th,.data td,.dataentry th,.dataentry td { + padding: 2px 5px; +} + +.data th,.dataentry th { + font-family: Trebuchet MS, Arial, Helvetica, sans-serif; + font-weight: bold; +} + +td.input { + padding-top: 0; +} + +.action { + text-align: center; +} + +table.data,.data th,.data td { + border: 1px solid #999; +} + +.data th { + background: #CCC; + text-transform: capitalize; +} + +.data td { + background: #FFF; +} + +.dataentry th:after { + content: ':'; +} + +.dataentry th,.dataentry td { + vertical-align: middle; +} + +.data img,.dataentry img { + margin: -2px; +} + +fieldset, .fieldset { + border: 1px solid #CCC; + background: #EFEFEF; +} + +.error { + color: #F70008; + font-weight: bold; + font-style: normal; +} + +.success { + color: green; + font-weight: normal; + font-style: italic; +} + +.product_overview { + width: 100%; +} + +table.product_overview,.product_overview th,.product_overview td { + border: 1px solid black; +} + +.product_overview th,.product_overview td { + padding: 1px 2px; +} + +.link { + text-align: center; +} + +.ad { + margin-bottom: 5px; +} diff --git a/core/http/workbench/src/main/webapp/styles/w3-html40-recommended.css b/core/http/workbench/src/main/webapp/styles/w3-html40-recommended.css new file mode 100644 index 00000000000..be9157d5776 --- /dev/null +++ b/core/http/workbench/src/main/webapp/styles/w3-html40-recommended.css @@ -0,0 +1,81 @@ +/* Source: http://www.w3.org/TR/CSS21/sample.html */ + +html, address, +blockquote, +body, dd, div, +dl, dt, fieldset, form, +frame, frameset, +h1, h2, h3, h4, +h5, h6, noframes, +ol, p, ul, center, +dir, hr, menu, pre { display: block } +li { display: list-item } +head { display: none } +table { display: table } +tr { display: table-row } +thead { display: table-header-group } +tbody { display: table-row-group } +tfoot { display: table-footer-group } +col { display: table-column } +colgroup { display: table-column-group } +td, th { display: table-cell } +caption { display: table-caption } +th { font-weight: bolder; text-align: center } +caption { text-align: center } +body { margin: 8px } +h1 { font-size: 2em; margin: .67em 0 } +h2 { font-size: 1.5em; margin: .75em 0 } +h3 { font-size: 1.17em; margin: .83em 0 } +h4, p, +blockquote, ul, +fieldset, form, +ol, dl, dir, +menu { margin: 1.12em 0 } +h5 { font-size: .83em; margin: 1.5em 0 } +h6 { font-size: .75em; margin: 1.67em 0 } +h1, h2, h3, h4, +h5, h6, b, +strong { font-weight: bolder } +blockquote { margin-left: 40px; margin-right: 40px } +i, cite, em, +var, address { font-style: italic } +pre, tt, code, +kbd, samp { font-family: monospace } +pre { white-space: pre } +button, textarea, +input, select { display: inline-block } +big { font-size: 1.17em } +small, sub, sup { font-size: .83em } +sub { vertical-align: sub } +sup { vertical-align: super } +table { border-spacing: 2px; } +thead, tbody, +tfoot { vertical-align: middle } +td, th { vertical-align: inherit } +s, strike, del { text-decoration: line-through } +hr { border: 1px inset } +ol, ul, dir, +menu, dd { margin-left: 40px } +ol { list-style-type: decimal } +ol ul, ul ol, +ul ul, ol ol { margin-top: 0; margin-bottom: 0 } +u, ins { text-decoration: underline } +br:before { content: "\A" } +:before, :after { white-space: pre-line } +center { text-align: center } +:link, :visited { text-decoration: underline } +:focus { outline: thin dotted black } + +/* Begin bidirectionality settings (do not change) */ +BDO[DIR="ltr"] { direction: ltr; unicode-bidi: bidi-override } +BDO[DIR="rtl"] { direction: rtl; unicode-bidi: bidi-override } + +*[DIR="ltr"] { direction: ltr; unicode-bidi: embed } +*[DIR="rtl"] { direction: rtl; unicode-bidi: embed } + +@media print { + h1 { page-break-before: always } + h1, h2, h3, + h4, h5, h6 { page-break-after: avoid } + ul, ol, dl { page-break-before: avoid } +} diff --git a/core/http/workbench/src/main/webapp/styles/yasqe.min.css b/core/http/workbench/src/main/webapp/styles/yasqe.min.css new file mode 100644 index 00000000000..b12af688cab --- /dev/null +++ b/core/http/workbench/src/main/webapp/styles/yasqe.min.css @@ -0,0 +1 @@ +.yasqe{position:relative;@-moz-keyframes blink{0%{background:#7e7}50%{background:0 0}100%{background:#7e7}}@-webkit-keyframes blink{0%{background:#7e7}50%{background:0 0}100%{background:#7e7}}@keyframes blink{0%{background:#7e7}50%{background:0 0}100%{background:#7e7}}}.yasqe .CodeMirror{font-family:monospace;height:300px}.yasqe .CodeMirror-lines{padding:4px 0}.yasqe .CodeMirror pre{padding:0 4px}.yasqe .CodeMirror-scrollbar-filler,.yasqe .CodeMirror-gutter-filler{background-color:#fff}.yasqe .CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.yasqe .CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;-moz-box-sizing:content-box;box-sizing:content-box}.yasqe .CodeMirror-guttermarker{color:#000}.yasqe .CodeMirror-guttermarker-subtle{color:#999}.yasqe .CodeMirror div.CodeMirror-cursor{border-left:1px solid #000}.yasqe .CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.yasqe .CodeMirror.cm-fat-cursor div.CodeMirror-cursor{width:auto;border:0;background:#7e7}.yasqe .CodeMirror.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.yasqe .cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.yasqe .cm-tab{display:inline-block;text-decoration:inherit}.yasqe .CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.yasqe .cm-s-default .cm-keyword{color:#708}.yasqe .cm-s-default .cm-atom{color:#219}.yasqe .cm-s-default .cm-number{color:#164}.yasqe .cm-s-default .cm-def{color:#00f}.yasqe .cm-s-default .cm-variable-2{color:#05a}.yasqe .cm-s-default .cm-variable-3{color:#085}.yasqe .cm-s-default .cm-comment{color:#a50}.yasqe .cm-s-default .cm-string{color:#a11}.yasqe .cm-s-default .cm-string-2{color:#f50}.yasqe .cm-s-default .cm-meta{color:#555}.yasqe .cm-s-default .cm-qualifier{color:#555}.yasqe .cm-s-default .cm-builtin{color:#30a}.yasqe .cm-s-default .cm-bracket{color:#997}.yasqe .cm-s-default .cm-tag{color:#170}.yasqe .cm-s-default .cm-attribute{color:#00c}.yasqe .cm-s-default .cm-header{color:#00f}.yasqe .cm-s-default .cm-quote{color:#090}.yasqe .cm-s-default .cm-hr{color:#999}.yasqe .cm-s-default .cm-link{color:#00c}.yasqe .cm-negative{color:#d44}.yasqe .cm-positive{color:#292}.yasqe .cm-header,.yasqe .cm-strong{font-weight:700}.yasqe .cm-em{font-style:italic}.yasqe .cm-link{text-decoration:underline}.yasqe .cm-strikethrough{text-decoration:line-through}.yasqe .cm-s-default .cm-error{color:red}.yasqe .cm-invalidchar{color:red}.yasqe div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}.yasqe div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.yasqe .CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.yasqe .CodeMirror-activeline-background{background:#e8f2ff}.yasqe .CodeMirror{line-height:1;position:relative;overflow:hidden;background:#fff;color:#000}.yasqe .CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative;-moz-box-sizing:content-box;box-sizing:content-box}.yasqe .CodeMirror-sizer{position:relative;border-right:30px solid transparent;-moz-box-sizing:content-box;box-sizing:content-box}.yasqe .CodeMirror-vscrollbar,.yasqe .CodeMirror-hscrollbar,.yasqe .CodeMirror-scrollbar-filler,.yasqe .CodeMirror-gutter-filler{position:absolute;z-index:6;display:none}.yasqe .CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.yasqe .CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.yasqe .CodeMirror-scrollbar-filler{right:0;bottom:0}.yasqe .CodeMirror-gutter-filler{left:0;bottom:0}.yasqe .CodeMirror-gutters{position:absolute;left:0;top:0;z-index:3}.yasqe .CodeMirror-gutter{white-space:normal;height:100%;-moz-box-sizing:content-box;box-sizing:content-box;display:inline-block;margin-bottom:-30px;;}.yasqe .CodeMirror-gutter-wrapper{position:absolute;z-index:4;height:100%}.yasqe .CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.yasqe .CodeMirror-lines{cursor:text;min-height:1px}.yasqe .CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible}.yasqe .CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.yasqe .CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.yasqe .CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.yasqe .CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.yasqe .CodeMirror-measure pre{position:static}.yasqe .CodeMirror div.CodeMirror-cursor{position:absolute;border-right:none;width:0}.yasqe div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.yasqe .CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.yasqe .CodeMirror-selected{background:#d9d9d9}.yasqe .CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.yasqe .CodeMirror-crosshair{cursor:crosshair}.yasqe .cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.yasqe .cm-force-border{padding-right:.1px}@media print{.yasqe .CodeMirror div.CodeMirror-cursors{visibility:hidden}}.yasqe .cm-tab-wrap-hack:after{content:''}.yasqe span.CodeMirror-selectedtext{background:0 0}.yasqe .CodeMirror-fullscreen{position:fixed;top:0;left:0;right:0;bottom:0;height:auto;z-index:9}.yasqe .CodeMirror-foldmarker{color:#00f;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.yasqe .CodeMirror-foldgutter{width:.7em}.yasqe .CodeMirror-foldgutter-open,.yasqe .CodeMirror-foldgutter-folded{cursor:pointer}.yasqe .CodeMirror-foldgutter-open:after{content:"\25BE"}.yasqe .CodeMirror-foldgutter-folded:after{content:"\25B8"}.yasqe .backdrop{background-color:#000;opacity:.5;position:absolute;top:0;left:0;right:0;bottom:0;z-index:5;display:none}.yasqe .svgImg{display:inline-block}.yasqe .CodeMirror{line-height:1.5em;border:1px solid #d1d1d1}.yasqe pre{font-size:13px}.yasqe span.cm-error{border-bottom:2px dotted red}.yasqe .gutterErrorBar{width:4px}.yasqe .yasqe_buttons{position:absolute;top:5px;right:5px;z-index:5}.yasqe .yasqe_buttons div{vertical-align:top;margin-left:5px}.yasqe .yasqe_queryButton{display:inline-block;cursor:pointer;width:40px;height:40px}.yasqe .yasqe_queryButton .svgImg{display:block}.yasqe .yasqe_share{cursor:pointer;height:20px;width:20px;margin-top:3px}.yasqe .yasqe_sharePopup{position:absolute;padding:6px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);width:400px;height:auto}.yasqe .yasqe_sharePopup textarea{width:100%}.yasqe .completionNotification{color:#999;background-color:#f7f7f7;position:absolute;padding:0 5px;right:0;bottom:0;font-size:90%}.yasqe .CodeMirror-fullscreen .fullscreenToggleBtns .yasqe_smallscreenBtn{display:inline-block}.yasqe .CodeMirror-fullscreen .fullscreenToggleBtns .yasqe_fullscreenBtn{display:none}.yasqe .fullscreenToggleBtns{display:inline-block;margin-top:3px}.yasqe .fullscreenToggleBtns div{cursor:pointer;width:20px;height:20px}.yasqe .fullscreenToggleBtns .yasqe_smallscreenBtn{display:none}.yasqe .parseErrorIcon{width:15px;height:15px}.yasqe .yasqe_tooltip{display:inline;position:absolute;background:#333;background:rgba(0,0,0,.8);border-radius:5px;bottom:26px;color:#fff;left:20%;padding:5px 15px;position:absolute;width:220px;white-space:-moz-pre-wrap!important;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;white-space:normal}.yasqe .notificationLoader{width:18px;height:18px;vertical-align:middle}.CodeMirror-hints{position:absolute;z-index:10;overflow:hidden;list-style:none;margin:0;padding:2px;-webkit-box-shadow:2px 3px 5px rgba(0,0,0,.2);-moz-box-shadow:2px 3px 5px rgba(0,0,0,.2);box-shadow:2px 3px 5px rgba(0,0,0,.2);border-radius:3px;border:1px solid silver;background:#fff;font-size:90%;font-family:monospace;max-height:20em;overflow-y:auto}.CodeMirror-hint{margin:0;padding:0 4px;border-radius:2px;max-width:19em;overflow:hidden;white-space:pre;color:#000;cursor:pointer}li.CodeMirror-hint-active{background:#08f;color:#fff}.CodeMirror-hint{max-width:30em} \ No newline at end of file diff --git a/core/http/workbench/src/main/webapp/transformations/add.xsl b/core/http/workbench/src/main/webapp/transformations/add.xsl new file mode 100644 index 00000000000..a91743dfeb1 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/add.xsl @@ -0,0 +1,148 @@ + + + + + + + + + + + + + +

+ +

+ + +

+ +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + use base URI as context identifier +
+ + + +
+ + + +
+ + +
+ + + +
+ + +
+ + + +
+ + +
+ + + +
+ +
+
+ + + + diff --git a/core/http/workbench/src/main/webapp/transformations/boolean.xsl b/core/http/workbench/src/main/webapp/transformations/boolean.xsl new file mode 100644 index 00000000000..e9863b84ac3 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/boolean.xsl @@ -0,0 +1,32 @@ + + + + + + + + + + + + +
+ + + {$true.label} + + + + {$false.label} + + + +
+
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/clear.xsl b/core/http/workbench/src/main/webapp/transformations/clear.xsl new file mode 100644 index 00000000000..f3c91fa8fcb --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/clear.xsl @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + +

+ +

+
+

+ +

+ +

+ +

+
+ +
+ + + + + + + + + + + + + + +
+ + + +
+ +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/contexts.xsl b/core/http/workbench/src/main/webapp/transformations/contexts.xsl new file mode 100644 index 00000000000..c9029623064 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/contexts.xsl @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/core/http/workbench/src/main/webapp/transformations/create-federate.xsl b/core/http/workbench/src/main/webapp/transformations/create-federate.xsl new file mode 100644 index 00000000000..1d530a20cce --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-federate.xsl @@ -0,0 +1,112 @@ + + + ]> + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + Select at least two federation + members. + +
+ + + +
+ + + +
+ + +
+
+ + +
+ + + + +
+
+ + + +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-memory-customrule.xsl b/core/http/workbench/src/main/webapp/transformations/create-memory-customrule.xsl new file mode 100644 index 00000000000..5979b8fda1c --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-memory-customrule.xsl @@ -0,0 +1,133 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + + + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-memory-rdfs-dt.xsl b/core/http/workbench/src/main/webapp/transformations/create-memory-rdfs-dt.xsl new file mode 100644 index 00000000000..6bf8af3d8f3 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-memory-rdfs-dt.xsl @@ -0,0 +1,94 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + + + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-memory-rdfs.xsl b/core/http/workbench/src/main/webapp/transformations/create-memory-rdfs.xsl new file mode 100644 index 00000000000..694e7a1a6a7 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-memory-rdfs.xsl @@ -0,0 +1,92 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + + + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-memory.xsl b/core/http/workbench/src/main/webapp/transformations/create-memory.xsl new file mode 100644 index 00000000000..7180ac7c852 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-memory.xsl @@ -0,0 +1,93 @@ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + + + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-native-customrule.xsl b/core/http/workbench/src/main/webapp/transformations/create-native-customrule.xsl new file mode 100644 index 00000000000..0b5cf7470ae --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-native-customrule.xsl @@ -0,0 +1,120 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-native-rdfs-dt.xsl b/core/http/workbench/src/main/webapp/transformations/create-native-rdfs-dt.xsl new file mode 100644 index 00000000000..2103017de3b --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-native-rdfs-dt.xsl @@ -0,0 +1,80 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-native-rdfs.xsl b/core/http/workbench/src/main/webapp/transformations/create-native-rdfs.xsl new file mode 100644 index 00000000000..964cd6f834e --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-native-rdfs.xsl @@ -0,0 +1,78 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-native.xsl b/core/http/workbench/src/main/webapp/transformations/create-native.xsl new file mode 100644 index 00000000000..161662bfd61 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-native.xsl @@ -0,0 +1,78 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-remote.xsl b/core/http/workbench/src/main/webapp/transformations/create-remote.xsl new file mode 100644 index 00000000000..db367f2977c --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-remote.xsl @@ -0,0 +1,88 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create-sparql.xsl b/core/http/workbench/src/main/webapp/transformations/create-sparql.xsl new file mode 100644 index 00000000000..526231b0d68 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create-sparql.xsl @@ -0,0 +1,88 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/create.xsl b/core/http/workbench/src/main/webapp/transformations/create.xsl new file mode 100644 index 00000000000..183e1705846 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/create.xsl @@ -0,0 +1,100 @@ + + + ]> + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + +
+
+
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/delete.xsl b/core/http/workbench/src/main/webapp/transformations/delete.xsl new file mode 100644 index 00000000000..e7e2f02b2ee --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/delete.xsl @@ -0,0 +1,57 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + + +
+ +
+ +
+
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/explore.xsl b/core/http/workbench/src/main/webapp/transformations/explore.xsl new file mode 100644 index 00000000000..e7a649bc917 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/explore.xsl @@ -0,0 +1,215 @@ + + + ]> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ +

+
    + + +
  • + +
  • +
    +
+
+
+ + + +

+ +

+
+ + +

+ +

+
+
+ + +

+ +

+
+
+
+ + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + workbench.paging.addLimit('explore'); + limit_explore + +
+ + + + + +
+ + + +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/export.xsl b/core/http/workbench/src/main/webapp/transformations/export.xsl new file mode 100644 index 00000000000..32e32430b84 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/export.xsl @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + +
+
+
+ + + + + + + + +
+ + + + this.form.submit(); + limit_explore + + + + + +
+
+ + +
+ + +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/graph.xsl b/core/http/workbench/src/main/webapp/transformations/graph.xsl new file mode 100644 index 00000000000..81c7e627eb9 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/graph.xsl @@ -0,0 +1,81 @@ + + + + + + + + ( + + ) + + + + + + + +
+ + + + + + + + +
+ + + + + +
+
+
+ + + + + + + + +
+ + + + + workbench.paging.addGraphParam('limit_query'); + + limit_query + + + + + +
+
+ + +
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/information.xsl b/core/http/workbench/src/main/webapp/transformations/information.xsl new file mode 100644 index 00000000000..a0f901e33ec --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/information.xsl @@ -0,0 +1,113 @@ + + + + + + + + + + + + + +

+ +

+ + + + + + + + + + + + +
+ + + +
+ + + +
+ +

+ +

+ + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ +

+ +

+ + + + + + + + + + + + +
+ + + +
+ + + +
+
+ + + + + +
diff --git a/core/http/workbench/src/main/webapp/transformations/list.xsl b/core/http/workbench/src/main/webapp/transformations/list.xsl new file mode 100644 index 00000000000..ae077d305d7 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/list.xsl @@ -0,0 +1,36 @@ + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + +
diff --git a/core/http/workbench/src/main/webapp/transformations/namespaces.xsl b/core/http/workbench/src/main/webapp/transformations/namespaces.xsl new file mode 100644 index 00000000000..eee5d33bdb8 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/namespaces.xsl @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+ + + +
+ + +
+
+ + +
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/query.xsl b/core/http/workbench/src/main/webapp/transformations/query.xsl new file mode 100644 index 00000000000..9da45835253 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/query.xsl @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + limit_query + +
+ + + + + true + + + + + +
+ + + + + + + +
+
+ + + + + + + +
+
diff --git a/core/http/workbench/src/main/webapp/transformations/remove.xsl b/core/http/workbench/src/main/webapp/transformations/remove.xsl new file mode 100644 index 00000000000..8d9f686b261 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/remove.xsl @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + +

+ +

+
+

+ +

+

+ +

+ +
    +
  • + URI: + <http://foo.com/bar> +
  • +
  • + BNode: + _:nodeID +
  • +
  • + Literal: + "Hello" + , + "Hello"@en + and + "Hello"^^<http://bar.com/foo> +
  • + +
+ +

+ +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + explore?resource= + + + + + + + + + web + + +
+
+ + + + + + explore?resource= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+			
+		
+
+ + + + + + + + + + + +
+					
+				
+
+ + + + + +
+
+ + + + + + + + + + + + + + + diff --git a/core/http/workbench/src/main/webapp/transformations/template.xsl b/core/http/workbench/src/main/webapp/transformations/template.xsl new file mode 100644 index 00000000000..b504b971674 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/template.xsl @@ -0,0 +1,334 @@ + + + + + + + + + + + + + <xsl:value-of select="$workbench.title" /> + - + <xsl:value-of select="$title" /> + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + + + + + + + + diff --git a/core/http/workbench/src/main/webapp/transformations/server.xsl b/core/http/workbench/src/main/webapp/transformations/server.xsl new file mode 100644 index 00000000000..aaade2da677 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/server.xsl @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ +
+ + + +
+ + + +
+ +
+ +
+ +
diff --git a/core/http/workbench/src/main/webapp/transformations/summary.xsl b/core/http/workbench/src/main/webapp/transformations/summary.xsl new file mode 100644 index 00000000000..522c35a4846 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/summary.xsl @@ -0,0 +1,83 @@ + + + + + + + + + + + + +

+ +

+ + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+

+ +

+ + + + + + + + + + + +
+ + + +
+ + + +
+
+ + + + + +
diff --git a/core/http/workbench/src/main/webapp/transformations/table.xsl b/core/http/workbench/src/main/webapp/transformations/table.xsl new file mode 100644 index 00000000000..5ce8b52826f --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/table.xsl @@ -0,0 +1,234 @@ + + + + ]> + + + + + + + +
+
+ + +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + +
+ + + + + + ( + + ) + + + + + + + + + + + +
+ + + + + +
+
+ +
+

+ +

+

Scripting is not enabled. The + OpenRDF Sesame Workbench + application requires scripting to be + enabled in order to work + properly. +

+ + + + +
+ + + + + + +
  • + + + +
  • +
  • + + + + +
  • +
  • + +
      + +
    +
  • +
  • + +
      + +
    +
  • +
  • + + +
  • +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  • + + + + + + + + + + + + +
  • +
    + + + + + + + + diff --git a/core/http/workbench/src/main/webapp/transformations/tuple.xsl b/core/http/workbench/src/main/webapp/transformations/tuple.xsl new file mode 100644 index 00000000000..f2b6c6d8748 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/tuple.xsl @@ -0,0 +1,117 @@ + + + + + + + + ( + + ) + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + +
    + + + + + +
    +
    +
    + + + + + + + + + + + + + + + + + +
    + + + + + workbench.paging.addLimit('query'); + + limit_query + + + + + +
    + + + + + +
    + + + +
    +
    + + +
    + + +
    + +
    diff --git a/core/http/workbench/src/main/webapp/transformations/types.xsl b/core/http/workbench/src/main/webapp/transformations/types.xsl new file mode 100644 index 00000000000..a3f6fc7ca2e --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/types.xsl @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/core/http/workbench/src/main/webapp/transformations/update.xsl b/core/http/workbench/src/main/webapp/transformations/update.xsl new file mode 100644 index 00000000000..e994c017db2 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/update.xsl @@ -0,0 +1,62 @@ + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + +
    + + + +
    + + + +
    + +
    +
    + + + + + +
    + +
    diff --git a/core/http/workbench/src/main/webapp/transformations/url-encode.xsl b/core/http/workbench/src/main/webapp/transformations/url-encode.xsl new file mode 100644 index 00000000000..8122b6ab539 --- /dev/null +++ b/core/http/workbench/src/main/webapp/transformations/url-encode.xsl @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + + + !'()*-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~ + + 0123456789ABCDEF + + + + + + + + + + + + + + + + + + + Warning: string contains a character that is out of range! Substituting "?". + 63 + + + + + + + + + + + + + + + + + diff --git a/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestCreateServlet.java b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestCreateServlet.java new file mode 100644 index 00000000000..370f8184999 --- /dev/null +++ b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestCreateServlet.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; + +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.junit.Test; + +/** + * @author Dale Visser + */ +public class TestCreateServlet { + + /** + * Regression test for SES-1907. + */ + @Test + public final void testExpectedTemplatesCanBeResolved() { + String[] expectedTemplates = { + "memory-customrule", + "memory-rdfs-dt", + "memory-rdfs", + "memory", + "native-customrule", + "native-rdfs-dt", + "native-rdfs", + "native", + "remote", + "sparql" }; + for (String template : expectedTemplates) { + String resource = template + ".ttl"; + assertThat(resource, RepositoryConfig.class.getResourceAsStream(resource), is(notNullValue())); + } + } +} diff --git a/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestExploreServlet.java b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestExploreServlet.java new file mode 100644 index 00000000000..34be1123266 --- /dev/null +++ b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestExploreServlet.java @@ -0,0 +1,217 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.UpdateExecutionException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.eclipse.rdf4j.workbench.commands.ExploreServlet; +import org.eclipse.rdf4j.workbench.commands.ExploreServlet.ResultCursor; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author Dale Visser + */ +public class TestExploreServlet { + + private RepositoryConnection connection; + + private ExploreServlet servlet; + + private IRI foo, bar, bang, foos[]; + + private static final String PREFIX = "PREFIX : \nINSERT DATA { GRAPH :foo { "; + + private static final String SUFFIX = " . } }"; + + private TupleResultBuilder builder; + + /** + * @throws RepositoryException + * if an issue occurs making the connection + * @throws MalformedQueryException + * if an issue occurs inserting data + * @throws UpdateExecutionException + * if an issue occurs inserting data + */ + @Before + public void setUp() + throws RepositoryException, MalformedQueryException, UpdateExecutionException + { + Repository repo = new SailRepository(new MemoryStore()); + repo.initialize(); + connection = repo.getConnection(); + servlet = new ExploreServlet(); + ValueFactory factory = connection.getValueFactory(); + foo = factory.createIRI("http://www.test.com/foo"); + bar = factory.createIRI("http://www.test.com/bar"); + bang = factory.createIRI("http://www.test.com/bang"); + foos = new IRI[128]; + for (int i = 0; i < foos.length; i++) { + foos[i] = factory.createIRI("http://www.test.com/foo/" + i); + } + builder = mock(TupleResultBuilder.class); + } + + @After + public void tearDown() + throws RepositoryException + { + connection.close(); + servlet.destroy(); + } + + @Test + public final void testRegressionSES1748() + throws OpenRDFException + { + for (int i = 0; i < foos.length; i++) { + connection.add(foo, bar, foos[i]); + } + assertStatementCount(foo, 10, foos.length, 10); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.workbench.commands.ExploreServlet#processResource(org.eclipse.rdf4j.repository.RepositoryConnection, org.eclipse.rdf4j.workbench.util.TupleResultBuilder, org.eclipse.rdf4j.model.Value, int, int, boolean)} + * + * @throws RepositoryException + * if a problem occurs executing the method under test + */ + @Test + public final void testSubjectSameAsContext() + throws OpenRDFException + { + addToFooContext(":foo a :bar"); + assertStatementCount(foo, 1, 1); + verify(builder).result(foo, RDF.TYPE, bar, foo); + } + + @Test + public final void testPredicateSameAsContext() + throws OpenRDFException + { + addToFooContext(":bar :foo :bar"); + assertStatementCount(foo, 1, 1); + verify(builder).result(bar, foo, bar, foo); + } + + @Test + public final void testObjectSameAsContext() + throws OpenRDFException + { + addToFooContext(":bar a :foo"); + assertStatementCount(foo, 1, 1); + verify(builder).result(bar, RDF.TYPE, foo, foo); + } + + @Test + public final void testNoValueSameAsContext() + throws OpenRDFException + { + addToFooContext(":bar a :bar"); + assertStatementCount(foo, 1, 1); + verify(builder).result(bar, RDF.TYPE, bar, foo); + } + + @Test + public final void testOneObjectSameAsContext() + throws OpenRDFException + { + addToFooContext(":bar a :bar , :foo"); + assertStatementCount(foo, 2, 2); + verify(builder).result(bar, RDF.TYPE, bar, foo); + verify(builder).result(bar, RDF.TYPE, foo, foo); + } + + @Test + public final void testSubjectSameAsPredicate() + throws OpenRDFException + { + addToFooContext(":bar :bar :bang"); + assertStatementCount(bar, 1, 1); + verify(builder).result(bar, bar, bang, foo); + } + + @Test + public final void testSubjectSameAsObject() + throws OpenRDFException + { + addToFooContext(":bar a :bar"); + assertStatementCount(bar, 1, 1); + verify(builder).result(bar, RDF.TYPE, bar, foo); + } + + @Test + public final void testPredicateSameAsObject() + throws OpenRDFException + { + addToFooContext(":bar :bang :bang"); + assertStatementCount(bang, 1, 1); + verify(builder).result(bar, bang, bang, foo); + } + + @Test + public final void testWorstCaseDuplication() + throws OpenRDFException + { + addToFooContext(":foo :foo :foo"); + assertStatementCount(foo, 1, 1); + verify(builder).result(foo, foo, foo, foo); + } + + @Test + public final void testSES1723regression() + throws OpenRDFException + { + addToFooContext(":foo :foo :foo"); + connection.add(foo, foo, foo); + assertStatementCount(foo, 2, 2); + verify(builder).result(foo, foo, foo, foo); + verify(builder).result(foo, foo, foo, null); + } + + private void addToFooContext(String pattern) + throws UpdateExecutionException, RepositoryException, MalformedQueryException + { + connection.prepareUpdate(QueryLanguage.SPARQL, PREFIX + pattern + SUFFIX).execute(); + } + + private void assertStatementCount(IRI uri, int expectedTotal, int expectedRendered) + throws OpenRDFException + { + // limit = 0 means render all + assertStatementCount(uri, 0, expectedTotal, expectedRendered); + } + + private void assertStatementCount(IRI uri, int limit, int expectedTotal, int expectedRendered) + throws OpenRDFException + { + ResultCursor cursor = servlet.processResource(connection, builder, uri, 0, limit, true); + assertThat(cursor.getTotalResultCount(), is(equalTo(expectedTotal))); + assertThat(cursor.getRenderedResultCount(), is(equalTo(expectedRendered))); + } +} diff --git a/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestInfoServlet.java b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestInfoServlet.java new file mode 100644 index 00000000000..0c455bbecc5 --- /dev/null +++ b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestInfoServlet.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import static org.junit.Assert.fail; +import static org.mockito.Mockito.*; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.model.vocabulary.SESAME; +import org.eclipse.rdf4j.repository.manager.RepositoryInfo; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.eclipse.rdf4j.workbench.commands.InfoServlet; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.junit.Before; +import org.junit.Test; + +/** + * @author dale + */ +public class TestInfoServlet { + + private final InfoServlet servlet = new InfoServlet(); + + private RepositoryManager manager; + + private final RepositoryInfo info = new RepositoryInfo(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + servlet.setRepositoryInfo(info); + manager = mock(RepositoryManager.class); + servlet.setRepositoryManager(manager); + } + + /** + * Throwing exceptions for invalid repository ID's results in a 500 response + * code to the client. As seen in the bug report, some versions of Internet + * Explorer don't gracefully handle error responses during XSLT parsing. + * + * @see SES-1770 + */ + @Test + public final void testSES1770regression() + throws Exception + { + when(manager.hasRepositoryConfig(null)).thenThrow(new NullPointerException()); + WorkbenchRequest req = mock(WorkbenchRequest.class); + when(req.getParameter(anyString())).thenReturn(SESAME.NIL.toString()); + HttpServletResponse resp = mock(HttpServletResponse.class); + when(resp.getOutputStream()).thenReturn(mock(ServletOutputStream.class)); + servlet.service(req, resp, ""); + } + +} diff --git a/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestQueryServlet.java b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestQueryServlet.java new file mode 100644 index 00000000000..9d0e7a91a5d --- /dev/null +++ b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestQueryServlet.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.Collections; + +import javax.servlet.ServletException; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.io.ResourceUtil; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.workbench.commands.QueryServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.QueryStorage; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.junit.Before; +import org.junit.Test; + +/** + * @author Dale Visser + */ +public class TestQueryServlet { + + private static final String SHORT_QUERY = "select * {?s ?p ?o .}"; + + private final QueryServlet servlet = new QueryServlet(); + + private String longQuery; + + @Before + public void setUp() + throws IOException + { + longQuery = ResourceUtil.getString("long.rq"); + } + + @Test + public final void testLongQuery() + throws ServletException, IOException + { + assertThat(servlet.shouldWriteQueryCookie(longQuery), is(equalTo(false))); + } + + @Test + public final void testShortQuery() + throws ServletException, IOException + { + assertThat(servlet.shouldWriteQueryCookie(SHORT_QUERY), is(equalTo(true))); + } + + @Test + public final void testNoQuery() + throws ServletException, IOException + { + assertThat(servlet.shouldWriteQueryCookie(null), is(equalTo(true))); + } + + @Test + public void testGetQueryTextRefText() + throws BadRequestException, OpenRDFException + { + WorkbenchRequest request = mock(WorkbenchRequest.class); + when(request.isParameterPresent(QueryServlet.QUERY)).thenReturn(true); + when(request.getParameter(QueryServlet.QUERY)).thenReturn(SHORT_QUERY); + when(request.isParameterPresent(QueryServlet.REF)).thenReturn(true); + when(request.getParameter(QueryServlet.REF)).thenReturn("text"); + assertThat(servlet.getQueryText(request), is(equalTo(SHORT_QUERY))); + } + + @Test + public void testGetQueryNoQuery() + throws BadRequestException, OpenRDFException + { + WorkbenchRequest request = mock(WorkbenchRequest.class); + when(request.isParameterPresent(QueryServlet.QUERY)).thenReturn(false); + assertThat(servlet.getQueryText(request), is(equalTo(""))); + } + + @Test + public void testGetQueryTextUnrecognizedRef() + throws BadRequestException, OpenRDFException + { + WorkbenchRequest request = mock(WorkbenchRequest.class); + when(request.isParameterPresent(QueryServlet.QUERY)).thenReturn(true); + when(request.getParameter(QueryServlet.QUERY)).thenReturn(SHORT_QUERY); + when(request.isParameterPresent(QueryServlet.REF)).thenReturn(true); + when(request.getParameter(QueryServlet.REF)).thenReturn("junk"); + assertThat(servlet.getQueryText(request), is(equalTo(SHORT_QUERY))); + } + + @Test + public void testGetQueryTextNoRef() + throws BadRequestException, OpenRDFException + { + WorkbenchRequest request = mock(WorkbenchRequest.class); + when(request.isParameterPresent(QueryServlet.QUERY)).thenReturn(true); + when(request.getParameter(QueryServlet.QUERY)).thenReturn(SHORT_QUERY); + when(request.isParameterPresent(QueryServlet.REF)).thenReturn(false); + assertThat(servlet.getQueryText(request), is(equalTo(SHORT_QUERY))); + } + + @Test + public void testGetQueryTextRefHash() + throws BadRequestException, OpenRDFException + { + WorkbenchRequest request = mock(WorkbenchRequest.class); + when(request.isParameterPresent(QueryServlet.QUERY)).thenReturn(true); + String hash = String.valueOf(longQuery.hashCode()); + when(request.getParameter(QueryServlet.QUERY)).thenReturn(hash); + when(request.isParameterPresent(QueryServlet.REF)).thenReturn(true); + when(request.getParameter(QueryServlet.REF)).thenReturn("hash"); + QueryServlet.substituteQueryCache(Collections.singletonMap(hash, longQuery)); + assertThat(servlet.getQueryText(request), is(equalTo(longQuery))); + } + + @Test + public void testGetQueryTextRefHashNoEntry() + throws BadRequestException, OpenRDFException + { + WorkbenchRequest request = mock(WorkbenchRequest.class); + when(request.isParameterPresent(QueryServlet.QUERY)).thenReturn(true); + String hash = String.valueOf(longQuery.hashCode()); + when(request.getParameter(QueryServlet.QUERY)).thenReturn(hash); + when(request.isParameterPresent(QueryServlet.REF)).thenReturn(true); + when(request.getParameter(QueryServlet.REF)).thenReturn("hash"); + QueryServlet.substituteQueryCache(Collections. emptyMap()); + assertThat(servlet.getQueryText(request), is(equalTo(""))); + } + + @Test + public void testGetQueryTextRefId() + throws BadRequestException, OpenRDFException + { + WorkbenchRequest request = mock(WorkbenchRequest.class); + when(request.isParameterPresent(QueryServlet.QUERY)).thenReturn(true); + when(request.getParameter(QueryServlet.QUERY)).thenReturn("test save name"); + when(request.isParameterPresent(QueryServlet.REF)).thenReturn(true); + when(request.getParameter(QueryServlet.REF)).thenReturn("id"); + QueryStorage storage = mock(QueryStorage.class); + when(storage.getQueryText(any(HTTPRepository.class), anyString(), eq("test save name"))).thenReturn( + longQuery); + servlet.substituteQueryStorage(storage); + assertThat(servlet.getQueryText(request), is(equalTo(longQuery))); + } +} diff --git a/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestRemoveServlet.java b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestRemoveServlet.java new file mode 100644 index 00000000000..c68cb7219b5 --- /dev/null +++ b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/commands/TestRemoveServlet.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.commands; + +import static org.eclipse.rdf4j.workbench.base.TransformationServlet.CONTEXT; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.workbench.commands.RemoveServlet; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.WorkbenchRequest; +import org.junit.Test; + +/** + * Unit and regression tests for {@link RemoteServlet}. + * + * @author Dale Visser + */ +public class TestRemoveServlet { + + private final RemoveServlet servlet = new RemoveServlet(); + + @Test + public void testSES1958regression() + throws RepositoryException, QueryResultHandlerException, IOException, BadRequestException + { + WorkbenchRequest request = mock(WorkbenchRequest.class); + when(request.isParameterPresent(CONTEXT)).thenReturn(true); + IRI context = SimpleValueFactory.getInstance().createIRI(""); + when(request.getResource(CONTEXT)).thenReturn(context); + Repository repository = mock(Repository.class); + servlet.setRepository(repository); + RepositoryConnection connection = mock(RepositoryConnection.class); + when(repository.getConnection()).thenReturn(connection); + servlet.doPost(request, mock(HttpServletResponse.class), ""); + verify(connection).clear(eq(context)); + } +} \ No newline at end of file diff --git a/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestPagedQuery.java b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestPagedQuery.java new file mode 100644 index 00000000000..4695ea978d9 --- /dev/null +++ b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestPagedQuery.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; + +import java.io.IOException; + +import org.eclipse.rdf4j.common.io.ResourceUtil; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.workbench.util.PagedQuery; +import org.junit.Test; + +/** + * Regression test suite for {@link org.eclipse.rdf4j.workbench.util.PagedQuery + * PagedQuery}. + * + * @author Dale Visser + */ +public class TestPagedQuery { + + @Test + public final void testSES1895regression() { + PagedQuery pagedQuery = new PagedQuery( + "select * {?s ?p ?o } LIMIT 10", + QueryLanguage.SPARQL, + 100, + 0); + assertThat(pagedQuery.toString().toLowerCase(), + is(equalTo("select * {?s ?p ?o } limit 10"))); + } + + /** + * Check that inner query limits do not affect the paging parameters. + * @throws IOException + */ + @Test + public final void testSES2307regression() throws IOException{ + PagedQuery pagedQuery = new PagedQuery( + ResourceUtil.getString("ses2307.rq"), + QueryLanguage.SPARQL, + 100, + 0); + assertThat(pagedQuery.getLimit(), is(equalTo(100))); + } +} diff --git a/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestTupleResultBuilder.java b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestTupleResultBuilder.java new file mode 100644 index 00000000000..be5fe7ced05 --- /dev/null +++ b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestTupleResultBuilder.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import static org.junit.Assert.*; + +import java.io.ByteArrayOutputStream; +import java.net.URL; + +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.resultio.sparqljson.SPARQLResultsJSONWriter; +import org.eclipse.rdf4j.query.resultio.sparqlxml.SPARQLBooleanXMLWriter; +import org.eclipse.rdf4j.workbench.util.TupleResultBuilder; +import org.junit.Test; + +/** + * @author Dale Visser + */ +public class TestTupleResultBuilder { + + @Test + public final void testSES1780regression() + throws Exception + { + TupleResultBuilder builder = new TupleResultBuilder(new SPARQLResultsJSONWriter( + new ByteArrayOutputStream()), SimpleValueFactory.getInstance()); + builder.start("test"); + builder.namedResult("test", new URL("http://www.foo.org/bar#")); + builder.end(); + } + + @Test + public final void testSES1726regression() + throws Exception + { + TupleResultBuilder builder = new TupleResultBuilder(new SPARQLResultsJSONWriter( + new ByteArrayOutputStream()), SimpleValueFactory.getInstance()); + try { + builder.namedResult("test", new URL("http://www.foo.org/bar#")); + fail("Did not receive expected exception for calling namedResult before start"); + } + catch (IllegalStateException ise) { + // Expected exception + } + } + + @Test + public final void testSES1846Normal() + throws Exception + { + TupleResultBuilder builder = new TupleResultBuilder(new SPARQLBooleanXMLWriter( + new ByteArrayOutputStream()), SimpleValueFactory.getInstance()); + builder.startBoolean(); + builder.bool(true); + builder.endBoolean(); + } + + @Test + public final void testSES1846regression() + throws Exception + { + TupleResultBuilder builder = new TupleResultBuilder(new SPARQLBooleanXMLWriter( + new ByteArrayOutputStream()), SimpleValueFactory.getInstance()); + try { + builder.start(); + builder.bool(true); + fail("Did not receive expected exception for calling bool after start"); + } + catch (QueryResultHandlerException qrhe) { + // Expected exception + } + } + +} diff --git a/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestValueDecoder.java b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestValueDecoder.java new file mode 100644 index 00000000000..90a077b3d84 --- /dev/null +++ b/core/http/workbench/src/test/java/org/eclipse/rdf4j/workbench/util/TestValueDecoder.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.workbench.util; + +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.workbench.exceptions.BadRequestException; +import org.eclipse.rdf4j.workbench.util.ValueDecoder; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * @author dale + */ +public class TestValueDecoder { + + private ValueDecoder decoder; + + private ValueFactory factory; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + factory = SimpleValueFactory.getInstance(); + + // Build a mock repository instance that provides 'decoder' with all + // it would ever ask for a connection with an associated prefix-namespace + // mapping. + RepositoryConnection connection = mock(RepositoryConnection.class); + when(connection.getNamespace(RDFS.PREFIX)).thenReturn(RDFS.NAMESPACE); + when(connection.getNamespace(XMLSchema.PREFIX)).thenReturn(XMLSchema.NAMESPACE); + Repository repository = mock(Repository.class); + when(repository.getConnection()).thenReturn(connection); + decoder = new ValueDecoder(repository, factory); + } + + @Test + public final void testQnamePropertyValue() + throws BadRequestException + { + Value value = decoder.decodeValue("rdfs:label"); + assertThat(value, is(instanceOf(IRI.class))); + assertThat((IRI)value, is(equalTo(RDFS.LABEL))); + } + + @Test + public final void testPlainStringLiteral() + throws BadRequestException + { + Value value = decoder.decodeValue("\"plain string\""); + assertThat(value, is(instanceOf(Literal.class))); + assertThat((Literal)value, is(equalTo(factory.createLiteral("plain string")))); + } + + @Test + public final void testUnexpectedLiteralAttribute() + throws BadRequestException + { + try { + decoder.decodeValue("\"datatype oops\"^rdfs:label"); + fail("Expected BadRequestException."); + } + catch (BadRequestException bre) { + Throwable rootCause = bre.getRootCause(); + assertThat(rootCause, is(instanceOf(BadRequestException.class))); + assertThat(rootCause.getMessage(), startsWith("Malformed language tag or datatype: ")); + } + } + + @Test + public final void testLiteralWithQNameType() + throws BadRequestException + { + Value value = decoder.decodeValue("\"1\"^^xsd:int"); + assertThat(value, is(instanceOf(Literal.class))); + assertThat((Literal)value, is(equalTo(factory.createLiteral(1)))); + } + + @Test + public final void testLiteralWithURIType() + throws BadRequestException + { + Value value = decoder.decodeValue("\"1\"^^<" + XMLSchema.INT + ">"); + assertThat(value, is(instanceOf(Literal.class))); + assertThat((Literal)value, is(equalTo(factory.createLiteral(1)))); + } + + @Test + public final void testLanguageLiteral() + throws BadRequestException + { + Value value = decoder.decodeValue("\"color\"@en-US"); + assertThat(value, is(instanceOf(Literal.class))); + assertThat((Literal)value, is(equalTo(factory.createLiteral("color", "en-US")))); + } +} diff --git a/core/http/workbench/src/test/resources/long.rq b/core/http/workbench/src/test/resources/long.rq new file mode 100644 index 00000000000..94a5eb0c730 --- /dev/null +++ b/core/http/workbench/src/test/resources/long.rq @@ -0,0 +1,51 @@ +PREFIX dc1: +PREFIX dc2: +PREFIX dc3: +PREFIX dc4: +PREFIX dc5: +PREFIX dc6: +PREFIX dc7: +PREFIX dc8: +PREFIX dc9: +PREFIX dc10: +PREFIX dc11: +PREFIX dc12: +PREFIX dc13: +PREFIX dc14: +PREFIX dc15: +PREFIX dc16: +PREFIX dc17: +PREFIX dc18: +PREFIX dc19: +PREFIX dc20: +PREFIX dc21: +PREFIX dc22: +PREFIX dc23: +PREFIX dc24: +PREFIX dc25: +PREFIX dc26: +PREFIX dc27: +PREFIX dc28: +PREFIX dc29: +PREFIX dc30: +PREFIX dc31: +PREFIX dc32: +PREFIX dc33: +PREFIX dc34: +PREFIX dc35: +PREFIX dc36: +PREFIX dc37: +PREFIX dc38: +PREFIX dc39: +PREFIX dc40: +PREFIX dc41: +PREFIX dc42: +PREFIX dc43: +PREFIX dc44: +PREFIX dc45: +PREFIX dc46: +PREFIX dc47: +PREFIX dc48: +PREFIX dc49: + +select * where {?s ?p ?o} diff --git a/core/http/workbench/src/test/resources/ses2307.rq b/core/http/workbench/src/test/resources/ses2307.rq new file mode 100644 index 00000000000..32a6e640bb7 --- /dev/null +++ b/core/http/workbench/src/test/resources/ses2307.rq @@ -0,0 +1,8 @@ +prefix : +SELECT ?s ?p ?o +WHERE { + { SELECT ?s + WHERE { ?s a :AClass } + LIMIT 2 } + ?s ?p ?o +} \ No newline at end of file diff --git a/core/model/pom.xml b/core/model/pom.xml new file mode 100644 index 00000000000..e9eba3dd3fb --- /dev/null +++ b/core/model/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-core + 4.1.0-SNAPSHOT + + + rdf4j-model + + RDF4J: Model + RDF model interfaces and implementations. + + + + ${project.groupId} + rdf4j-util + ${project.version} + + + junit + junit + + + + diff --git a/core/model/src/main/java/org/eclipse/rdf4j/IsolationLevel.java b/core/model/src/main/java/org/eclipse/rdf4j/IsolationLevel.java new file mode 100644 index 00000000000..7bb4e826b63 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/IsolationLevel.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j; + +import org.eclipse.rdf4j.model.IRI; + +/** + * A Transaction Isolation Level. Defaul levels supported by Sesame are provided + * by {@link IsolationLevels}, third-party triplestore implementors may choose + * to add additional IsolationLevel implementations if their triplestore's + * isolation contract is different from what is provided by default. + * + * @author Jeen Broekstra + * @since 2.8 + */ +public interface IsolationLevel { + + /** + * Verifies if this transaction isolation level is compatible with the + * supplied other isolation level - that is, if this transaction isolation + * level offers at least the same guarantees as the other level. By + * definition, every transaction isolation level is compatible with itself. + * + * @param otherLevel + * an other isolation level to check compatibility against. + * @return true iff this isolation level is compatible with the supplied + * other isolation level, false otherwise. + */ + boolean isCompatibleWith(IsolationLevel otherLevel); + + /** + * Get a URI uniquely representing this isolation level. + * + * @return a URI that uniquely represents this isolation level. + */ + IRI getURI(); + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/IsolationLevels.java b/core/model/src/main/java/org/eclipse/rdf4j/IsolationLevels.java new file mode 100644 index 00000000000..3cc35f0a992 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/IsolationLevels.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.SESAME; + +/** + * Enumeration of Transaction {@link IsolationLevel}s supported by Sesame. Note + * that Sesame stores are not required to support all levels, consult the + * documentatation for the specific SAIL implementation you are using to find + * out which levels are supported. + * + * @author Jeen Broekstra + * @author James Leigh + * @since 2.8.0 + */ +public enum IsolationLevels implements IsolationLevel { + + /** + * None: the lowest isolation level; transactions can see their own changes, + * but may not be able to roll them back and no support for isolation among + * transactions is guaranteed + */ + NONE, + + /** + * Read Uncommitted: transactions can be rolled back, but not necessarily + * isolated: concurrent transactions might see each other's uncommitted data + * (so-called 'dirty reads') + */ + READ_UNCOMMITTED(NONE), + + /** + * Read Committed: in this isolation level only statements from other + * transactions that have been committed (at some point) can be seen by this + * transaction. + */ + READ_COMMITTED(READ_UNCOMMITTED, NONE), + + /** + * Snapshot Read: in addition to {@link #READ_COMMITTED}, query results in + * this isolation level that are observed within a successful transaction + * will observe a consistent snapshot. Changes to the data occurring while a + * query is evaluated will not affect that query result. + */ + SNAPSHOT_READ(READ_COMMITTED, READ_UNCOMMITTED, NONE), + + /** + * Snapshot: in addition to {@link #SNAPSHOT_READ}, successful transactions + * in this isolation level will operate against a particular dataset + * snapshot. Transactions in this isolation level will see either the + * complete effects of other transactions (consistently throughout) or not at + * all. + */ + SNAPSHOT(SNAPSHOT_READ, READ_COMMITTED, READ_UNCOMMITTED, NONE), + + /** + * Serializable: in addition to {@link #SNAPSHOT}, this isolation level + * requires that all other successful transactions must appear to occur + * either completely before or completely after a successful serializable + * transaction. + */ + SERIALIZABLE(SNAPSHOT, SNAPSHOT_READ, READ_COMMITTED, READ_UNCOMMITTED, NONE); + + private final List compatibleLevels; + + private IsolationLevels(IsolationLevels... compatibleLevels) { + this.compatibleLevels = Arrays.asList(compatibleLevels); + } + + @Override + public boolean isCompatibleWith(IsolationLevel otherLevel) { + return this.equals(otherLevel) || compatibleLevels.contains(otherLevel); + } + + /** + * Determines the first compatible isolation level in the list of supported + * levels, for the given level. Returns the level itself if it is in the list + * of supported levels. Returns null if no compatible level can be found. + * + * @param level + * the {@link IsolationLevel} for which to determine a compatible + * level. + * @param supportedLevels + * a list of supported isolation levels from which to select the + * closest compatible level. + * @return the given level if it occurs in the list of supported levels. + * Otherwise, the first compatible level in the list of supported + * isolation levels, or null if no compatible level can + * be found. + * @since 2.8.0 + * @throws IllegalArgumentException + * if either one of the input parameters is null. + */ + public static IsolationLevel getCompatibleIsolationLevel(IsolationLevel level, + List supportedLevels) + { + if (supportedLevels == null) { + throw new IllegalArgumentException("list of supported levels may not be null"); + } + if (level == null) { + throw new IllegalArgumentException("level may not be null"); + } + if (!supportedLevels.contains(level)) { + IsolationLevel compatibleLevel = null; + // see we if we can find a compatible level that is supported + for (IsolationLevel supportedLevel : supportedLevels) { + if (supportedLevel.isCompatibleWith(level)) { + compatibleLevel = supportedLevel; + break; + } + } + + return compatibleLevel; + } + else { + return level; + } + } + + public IRI getURI() { + final ValueFactory f = SimpleValueFactory.getInstance(); + return f.createIRI(SESAME.NAMESPACE, this.name()); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/OpenRDFException.java b/core/model/src/main/java/org/eclipse/rdf4j/OpenRDFException.java new file mode 100644 index 00000000000..8378e2a5bfb --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/OpenRDFException.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j; + +/** + * General superclass of all unchecked exceptions that parts of OpenRDF Sesame + * can throw. + * + * @author jeen + */ +public abstract class OpenRDFException extends RuntimeException { + + private static final long serialVersionUID = 8913366826930181397L; + + public OpenRDFException() { + super(); + } + + public OpenRDFException(String msg) { + super(msg); + } + + public OpenRDFException(Throwable t) { + super(t); + } + + public OpenRDFException(String msg, Throwable t) { + super(msg, t); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/OpenRDFUtil.java b/core/model/src/main/java/org/eclipse/rdf4j/OpenRDFUtil.java new file mode 100644 index 00000000000..3edba3d2449 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/OpenRDFUtil.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j; + +import org.eclipse.rdf4j.model.Resource; + +/** + * General utility methods for OpenRDF/Sesame modules. + * + * @author Arjohn Kampman + */ +public class OpenRDFUtil { + + /** + * Verifies that the supplied contexts parameter is not null, + * throwing an {@link IllegalArgumentException} if it is. + *

    + * The semantics of supplying null as the value of the + * contexts vararg is not completely clear; it can either be + * equivalent to supplying an empty array (i.e.: matching all statements + * disregarding context), or to supplying a null-Resource value + * (e.g.: matching all statements with no associated context). As we so far + * haven't been able to prefer one over the other, methods operating on + * contexts currently throw {@link IllegalArgumentException}s. + * + * @param contexts + * The parameter to check. + * @throws IllegalArgumentException + * If the supplied contexts parameter is null. + */ + public static void verifyContextNotNull(Resource... contexts) { + if (contexts == null) { + throw new IllegalArgumentException( + "Illegal value null array for contexts argument; either the value should be cast to Resource or an empty array should be supplied"); + } + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/BNode.java b/core/model/src/main/java/org/eclipse/rdf4j/model/BNode.java new file mode 100644 index 00000000000..27361602459 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/BNode.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +/** + * A blank node (aka bnode, aka anonymous node). A blank node + * has an identifier to be able to compare it to other blank nodes internally. + * Please note that, conceptually, blank node equality can only be determined by + * examining the statements that refer to them. + */ +public interface BNode extends Resource { + + /** + * retrieves this blank node's identifier. + * + * @return A blank node identifier. + */ + public String getID(); + + /** + * Compares a blank node object to another object. + * + * @param o The object to compare this blank node to. + * @return true if the other object is an instance of {@link BNode} + * and their IDs are equal, false otherwise. + */ + public boolean equals(Object o); + + /** + * The hash code of a blank node is defined as the hash code of its + * identifier: id.hashCode(). + * + * @return A hash code for the blank node. + */ + public int hashCode(); +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/Graph.java b/core/model/src/main/java/org/eclipse/rdf4j/model/Graph.java new file mode 100644 index 00000000000..cd78da7a519 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/Graph.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Iterator; + +/** + * An RDF graph, represented as a collection of {@link Statement}s. + * + * @see GraphUtil + * @author Arjohn Kampman + * @deprecated Use {@link Model} instead. + */ +@Deprecated +public interface Graph extends Collection, Serializable { + + /** + * Gets the value factory for this graph. + * + * @deprecated {@link org.eclipse.rdf4j.model.impl.SimpleValueFactory#getInstance} + * will obtain a default value factory implementation. If you are + * working with the Repository API, then Repository + * instances also supply a getValueFactory() method. + */ + @Deprecated + public ValueFactory getValueFactory(); + + /** + * Adds one or more statements to the graph. This method creates a statement + * for each specified context and adds those to the graph. If no contexts are + * specified, a single statement with no associated context is added. + * + * @param subj + * The statement's subject, must not be null. + * @param pred + * The statement's predicate, must not be null. + * @param obj + * The statement's object, must not be null. + * @param contexts + * The contexts to add statements to. + */ + public boolean add(Resource subj, IRI pred, Value obj, Resource... contexts); + + /** + * Gets the statements with the specified subject, predicate, object and + * (optionally) context. The subject, predicate and + * object parameters can be null to indicate wildcards. The + * contexts parameter is a wildcard and accepts zero or more values. + * If no contexts are specified, statements will match disregarding their + * context. If one or more contexts are specified, statements with a context + * matching one of these will match. Note: to match statements without an + * associated context, specify the value null and explicitly cast it + * to type Resource. + *

    + * Examples: graph.match(s1, null, null) matches all statements that + * have subject s1,
    + * graph.match(null, null, null, c1) matches all statements that + * have context c1,
    + * graph.match(null, null, null, (Resource)null) matches all + * statements that have no associated context,
    + * graph.match(null, null, null, c1, c2, c3) matches all statements + * that have context c1, c2 or c3. + * + * @deprecated The preferred alternative is + * {@link org.eclipse.rdf4j.model.Model#filter}.iterator(). + * @param subj + * The subject of the statements to match, null to match + * statements with any subject. + * @param pred + * The predicate of the statements to match, null to match + * statements with any predicate. + * @param obj + * The object of the statements to match, null to match + * statements with any object. + * @param contexts + * The contexts of the statements to match. If no contexts are + * specified, statements will match disregarding their context. If one + * or more contexts are specified, statements with a context matching + * one of these will match. + * @return The statements that match the specified pattern. + * @throws IllegalArgumentException + * If a null-array is specified as the value for + * contexts. See + * {@link OpenRDFUtil#verifyContextNotNull(Resource[])} for more + * info. + */ + @Deprecated + public Iterator match(Resource subj, IRI pred, Value obj, Resource... contexts); +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/IRI.java b/core/model/src/main/java/org/eclipse/rdf4j/model/IRI.java new file mode 100644 index 00000000000..ca7f4cb0b95 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/IRI.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +/** + * An Internationalized Resource Identifier (IRI). IRIs are an extension of the + * existing {@link URI}: while URIs are limited to a subset of the ASCII + * character set, IRIs may contain characters from the Universal Character Set + * (Unicode/ISO 10646), including Chinese or Japanese kanji, Korean, Cyrillic + * characters, and so forth. It is defined by RFC 3987. + *

    + * An IRI can be split into a namespace part and a local name part, which are + * derived from an IRI string by splitting it in two using the following + * algorithm: + *

      + *
    • Split after the first occurrence of the '#' character, + *
    • If this fails, split after the last occurrence of the '/' character, + *
    • If this fails, split after the last occurrence of the ':' character. + *
    + * The last step should never fail as every legal (full) IRI contains at least + * one ':' character to seperate the scheme from the rest of the IRI. The + * implementation should check this upon object creation. + * + * @see RFC 3987 + * @since 4.0.0 + * @author Jeen Broekstra + */ +@SuppressWarnings("deprecation") +public interface IRI extends URI, Resource { + + /** + * Returns the String-representation of this IRI. + * + * @return The String-representation of this IRI. + */ + public String toString(); + + /** + * Gets the namespace part of this IRI. The namespace is defined as per the + * algorithm described in the class documentation. + * + * @return The IRI's namespace. + */ + public String getNamespace(); + + /** + * Gets the local name part of this IRI. The local name is defined as per the + * algorithm described in the class documentation. + * + * @return The IRI's local name. + */ + public String getLocalName(); + + /** + * Compares a IRI object to another object. + * + * @param o + * The object to compare this IRI to. + * @return true if the other object is an instance of {@link IRI} + * and their String-representations are equal, false + * otherwise. + */ + public boolean equals(Object o); + + /** + * The hash code of an IRI is defined as the hash code of its + * String-representation: toString().hashCode. + * + * @return A hash code for the IRI. + */ + public int hashCode(); +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/Literal.java b/core/model/src/main/java/org/eclipse/rdf4j/model/Literal.java new file mode 100644 index 00000000000..d0ae4899ec4 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/Literal.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Optional; + +import javax.xml.datatype.XMLGregorianCalendar; + +/** + * An RDF literal consisting of a label (the lexical value), a datatype, and optionally a language + * tag. + * + * @author Arjohn Kampman + */ +public interface Literal extends Value { + + /** + * Gets the label (the lexical value) of this literal. + * + * @return The literal's label. + */ + public String getLabel(); + + /** + * Gets the language tag for this literal, normalized to lower case. + * + * @return The language tag for this literal, or {@link Optional#empty()} if + * it doesn't have one. + */ + public Optional getLanguage(); + + /** + * Gets the datatype for this literal. + * + * @return The datatype for this literal. If {@link #getLanguage()} returns a + * non-empty value than this must return {@link RDF#LANGSTRING}. + */ + public IRI getDatatype(); + + /** + * Compares a literal object to another object. + * + * @param other + * The object to compare this literal to. + * @return true if the other object is an instance of + * {@link Literal} and if their labels, language tags and datatypes + * are equal. + */ + @Override + public boolean equals(Object other); + + /** + * Returns the literal's hash code. The hash code of a literal is defined as + * the hash code of its label: label.hashCode(). + * + * @return A hash code for the literal. + */ + @Override + public int hashCode(); + + /** + * Returns the byte value of this literal. + * + * @return The byte value of the literal. + * @throws NumberFormatException + * If the literal cannot be represented by a byte. + */ + public byte byteValue(); + + /** + * Returns the short value of this literal. + * + * @return The short value of the literal. + * @throws NumberFormatException + * If the literal's label cannot be represented by a short. + */ + public short shortValue(); + + /** + * Returns the int value of this literal. + * + * @return The int value of the literal. + * @throws NumberFormatException + * If the literal's label cannot be represented by a int. + */ + public int intValue(); + + /** + * Returns the long value of this literal. + * + * @return The long value of the literal. + * @throws NumberFormatException + * If the literal's label cannot be represented by to a long + * . + */ + public long longValue(); + + /** + * Returns the integer value of this literal. + * + * @return The integer value of the literal. + * @throws NumberFormatException + * If the literal's label is not a valid integer. + */ + public BigInteger integerValue(); + + /** + * Returns the decimal value of this literal. + * + * @return The decimal value of the literal. + * @throws NumberFormatException + * If the literal's label is not a valid decimal. + */ + public BigDecimal decimalValue(); + + /** + * Returns the float value of this literal. + * + * @return The float value of the literal. + * @throws NumberFormatException + * If the literal's label cannot be represented by a float. + */ + public float floatValue(); + + /** + * Returns the double value of this literal. + * + * @return The double value of the literal. + * @throws NumberFormatException + * If the literal's label cannot be represented by a double. + */ + public double doubleValue(); + + /** + * Returns the boolean value of this literal. + * + * @return The long value of the literal. + * @throws IllegalArgumentException + * If the literal's label cannot be represented by a boolean + * . + */ + public boolean booleanValue(); + + /** + * Returns the {@link XMLGregorianCalendar} value of this literal. A calendar + * representation can be given for literals whose label conforms to the + * syntax of the following XML + * Schema datatypes: dateTime, time, date, + * gYearMonth, gMonthDay, gYear, gMonth + * or gDay. + * + * @return The calendar value of the literal. + * @throws IllegalArgumentException + * If the literal cannot be represented by a + * {@link XMLGregorianCalendar}. + */ + public XMLGregorianCalendar calendarValue(); +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/Model.java b/core/model/src/main/java/org/eclipse/rdf4j/model/Model.java new file mode 100644 index 00000000000..8ebe3b7a343 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/Model.java @@ -0,0 +1,647 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import java.io.Serializable; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.util.ModelException; +import org.eclipse.rdf4j.model.util.Models; + +/** + * An RDF Model, represented as a {@link java.util.Set} of {@link Statement}s + * with predictable iteration order. + *

    + * Additional utility functionality for working with Model objects is available + * in the {@link org.eclipse.rdf4j.model.util.Models Models} utility class. + * + * @since 2.7.0 + * @author James Leigh + * @author Jeen Broekstra + * @see org.eclipse.rdf4j.model.util.Models the Models utility class + */ +@SuppressWarnings("deprecation") +public interface Model extends Graph, Set, Serializable { + + /** + * Returns an unmodifiable view of this model. This method provides + * "read-only" access to this model. Query operations on the returned model + * "read through" to this model, and attempts to modify the returned model, + * whether direct or via its iterator, result in an + * {@link UnsupportedOperationException}. + *

    + * + * @return an unmodifiable view of the specified set. + */ + public Model unmodifiable(); + + /** + * Gets the map that contains the assigned namespaces. + * + * @return Map of prefix to namespace + */ + public Set getNamespaces(); + + /** + * Gets the namespace that is associated with the specified prefix, if any. + * + * @param prefix + * A namespace prefix. + * @return The namespace name that is associated with the specified prefix, + * or {@link Optional#empty()} if there is no such namespace. + */ + public default Optional getNamespace(String prefix) { + return getNamespaces().stream().filter(t -> t.getPrefix().equals(prefix)).findAny(); + } + + /** + * Sets the prefix for a namespace. This will replace any existing namespace + * associated to the prefix. + * + * @param prefix + * The new prefix. + * @param name + * The namespace name that the prefix maps to. + * @return The {@link Namespace} object for the given namespace. + */ + public default Namespace setNamespace(String prefix, String name) { + Optional result = getNamespace(prefix); + if (!result.isPresent() || !result.get().getName().equals(name)) { + result = Optional.of(new SimpleNamespace(prefix, name)); + setNamespace(result.get()); + } + return result.get(); + } + + /** + * Sets the prefix for a namespace. This will replace any existing namespace + * associated to the prefix. + * + * @param namespace + * A {@link Namespace} object to use in this Model. + */ + public void setNamespace(Namespace namespace); + + /** + * Removes a namespace declaration by removing the association between a + * prefix and a namespace name. + * + * @param prefix + * The namespace prefix of which the assocation with a namespace name + * is to be removed. + * @return the previous namespace bound to the prefix or + * {@link Optional#empty()} + */ + public Optional removeNamespace(String prefix); + + /** + * Determines if statements with the specified subject, predicate, object and + * (optionally) context exist in this model. The {@code subject}, + * {@code predicate} and {@code object} parameters can be {@code null} to + * indicate wildcards. The {@code contexts} parameter is a wildcard and + * accepts zero or more values. If no contexts are specified, statements will + * match disregarding their context. If one or more contexts are specified, + * statements with a context matching one of these will match. Note: to match + * statements without an associated context, specify the value {@code null} + * and explicitly cast it to type {@code Resource}. + *

    + * Examples: {@code model.contains(s1, null, null)} is true if any statements + * in this model have subject {@code s1},
    + * {@code model.contains(null, null, null, c1)} is true if any statements in + * this model have context {@code c1},
    + * {@code model.contains(null, null, null, (Resource)null)} is true if any + * statements in this model have no associated context,
    + * {@code model.contains(null, null, null, c1, c2, c3)} is true if any + * statements in this model have context {@code c1}, {@code c2} or {@code c3} + * . + * + * @param subj + * The subject of the statements to match, {@code null} to match + * statements with any subject. + * @param pred + * The predicate of the statements to match, {@code null} to match + * statements with any predicate. + * @param obj + * The object of the statements to match, {@code null} to match + * statements with any object. + * @param contexts + * The contexts of the statements to match. If no contexts are + * specified, statements will match disregarding their context. If one + * or more contexts are specified, statements with a context matching + * one of these will match. + * @return true if statements match the specified pattern. + */ + public boolean contains(Resource subj, IRI pred, Value obj, Resource... contexts); + + /** + * @deprecated since 4.0. Use + * {@link #contains(Resource, IRI, Value, Resource...)} instead. + */ + @Deprecated + public default boolean contains(Resource subj, URI pred, Value obj, Resource... contexts) { + return contains(subj, (IRI)pred, obj, contexts); + } + + /** + * Adds one or more statements to the model. This method creates a statement + * for each specified context and adds those to the model. If no contexts are + * specified, a single statement with no associated context is added. If this + * Model is a filtered Model then null (if context empty) values are + * permitted and will use the corresponding filtered values. + * + * @param subj + * The statement's subject. + * @param pred + * The statement's predicate. + * @param obj + * The statement's object. + * @param contexts + * The contexts to add statements to. + * @throws IllegalArgumentException + * If This Model cannot store the given statement, because it is + * filtered out of this view. + * @throws UnsupportedOperationException + * If this Model cannot accept any statements, because it is filtered + * to the empty set. + */ + @Override + public boolean add(Resource subj, IRI pred, Value obj, Resource... contexts); + + /** + * @deprecated since 4.0. Use {@link #add(Resource, IRI, Value, Resource...)} + * instead. + */ + @Deprecated + public default boolean add(Resource subj, URI pred, Value obj, Resource... contexts) { + return add(subj, (IRI)pred, obj, contexts); + } + + /** + * Removes statements with the specified context exist in this model. + * + * @param context + * The context of the statements to remove. + * @return true if one or more statements have been removed. + */ + public boolean clear(Resource... context); + + /** + * Removes statements with the specified subject, predicate, object and + * (optionally) context exist in this model. The {@code subject}, + * {@code predicate} and {@code object} parameters can be {@code null} to + * indicate wildcards. The {@code contexts} parameter is a wildcard and + * accepts zero or more values. If no contexts are specified, statements will + * be removed disregarding their context. If one or more contexts are + * specified, statements with a context matching one of these will be + * removed. Note: to remove statements without an associated context, specify + * the value {@code null} and explicitly cast it to type {@code Resource}. + *

    + * Examples: {@code model.remove(s1, null, null)} removes any statements in + * this model have subject {@code s1},
    + * {@code model.remove(null, null, null, c1)} removes any statements in this + * model have context {@code c1},
    + * {@code model.remove(null, null, null, (Resource)null)} removes any + * statements in this model have no associated context,
    + * {@code model.remove(null, null, null, c1, c2, c3)} removes any statements + * in this model have context {@code c1}, {@code c2} or {@code c3}. + * + * @param subj + * The subject of the statements to remove, {@code null} to remove + * statements with any subject. + * @param pred + * The predicate of the statements to remove, {@code null} to remove + * statements with any predicate. + * @param obj + * The object of the statements to remove, {@code null} to remove + * statements with any object. + * @param contexts + * The contexts of the statements to remove. If no contexts are + * specified, statements will be removed disregarding their context. + * If one or more contexts are specified, statements with a context + * matching one of these will be removed. + * @return true if one or more statements have been removed. + */ + public boolean remove(Resource subj, IRI pred, Value obj, Resource... contexts); + + /** + * @deprecated since 4.0. Use + * {@link #remove(Resource, IRI, Value, Resource...)} instead. + */ + @Deprecated + public default boolean remove(Resource subj, URI pred, Value obj, Resource... contexts) { + return remove(subj, (IRI)pred, obj, contexts); + } + + // Views + + /** + * Returns a view of the statements with the specified subject, predicate, + * object and (optionally) context. The {@code subject}, {@code predicate} + * and {@code object} parameters can be {@code null} to indicate wildcards. + * The {@code contexts} parameter is a wildcard and accepts zero or more + * values. If no contexts are specified, statements will match disregarding + * their context. If one or more contexts are specified, statements with a + * context matching one of these will match. Note: to match statements + * without an associated context, specify the value {@code null} and + * explicitly cast it to type {@code Resource}. + *

    + * The returned model is backed by this Model, so changes to this Model are + * reflected in the returned model, and vice-versa. If this Model is modified + * while an iteration over the returned model is in progress (except through + * the iterator's own {@code remove} operation), the results of the iteration + * are undefined. The model supports element removal, which removes the + * corresponding statement from this Model, via the {@code Iterator.remove}, + * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and + * {@code clear} operations. The statements passed to the {@code add} and + * {@code addAll} operations must match the parameter pattern. + *

    + * Examples: {@code model.filter(s1, null, null)} matches all statements that + * have subject {@code s1},
    + * {@code model.filter(null, null, null, c1)} matches all statements that + * have context {@code c1},
    + * {@code model.filter(null, null, null, (Resource)null)} matches all + * statements that have no associated context,
    + * {@code model.filter(null, null, null, c1, c2, c3)} matches all statements + * that have context {@code c1}, {@code c2} or {@code c3}. + * + * @param subj + * The subject of the statements to match, {@code null} to match + * statements with any subject. + * @param pred + * The predicate of the statements to match, {@code null} to match + * statements with any predicate. + * @param obj + * The object of the statements to match, {@code null} to match + * statements with any object. + * @param contexts + * The contexts of the statements to match. If no contexts are + * specified, statements will match disregarding their context. If one + * or more contexts are specified, statements with a context matching + * one of these will match. + * @return The statements that match the specified pattern. + */ + public Model filter(Resource subj, IRI pred, Value obj, Resource... contexts); + + @Deprecated + public default Model filter(Resource subj, URI pred, Value obj, Resource... contexts) { + return filter(subj, (IRI)pred, obj, contexts); + } + + /** + * Returns a {@link Set} view of the subjects contained in this model. The + * set is backed by the model, so changes to the model are reflected in the + * set, and vice-versa. If the model is modified while an iteration over the + * set is in progress (except through the iterator's own {@code remove} + * operation), the results of the iteration are undefined. The set supports + * element removal, which removes all statements from the model for which + * that element is a subject value, via the {@code Iterator.remove}, + * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and + * {@code clear} operations. It does not support the {@code add} or + * {@code addAll} operations if the parameters {@code pred} or {@code obj} + * are null. + * + * @return a set view of the subjects contained in this model + */ + public Set subjects(); + + /** + * Gets the subject of the statement(s). If the model contains one or more + * statements, all these statements should have the same subject. A + * {@link ModelException} is thrown if this is not the case. + * + * @return The subject of the matched statement(s), or + * {@link Optional#empty()} if no matching statements were found. + * @throws ModelException + * If the statements matched by the specified parameters have more + * than one unique subject. + * @since 2.8.0 + * @deprecated since 4.0. Instead, use {@link Models#subject(Model)} to + * retrieve a subject Resource, and/or use the size of the set + * returned by {@link #subjects()} to verify if the subject is + * unique. + */ + @Deprecated + public default Optional subjectResource() + throws ModelException + { + Set result = stream().map(st -> st.getSubject()).distinct().limit(2).collect( + Collectors.toSet()); + if (result.isEmpty()) { + return Optional.empty(); + } + else if (result.size() > 1) { + throw new ModelException("Did not find a unique subject resource"); + } + else { + return Optional.of(result.iterator().next()); + } + } + + /** + * Utility method that casts the return value of {@link #subjectResource()} + * to a IRI, or throws a ModelException if that value is not an IRI. + * + * @return The subject of the matched statement(s), or {@code null} if no + * matching statements were found. + * @throws ModelException + * If such an exception is thrown by {@link #subjectResource()} or if + * its return value is not a IRI. + * @since 2.8.0 + * @deprecated since 4.0. Instead, use {@link Models#subjectURI(Model)} to + * retrieve a subject URI, and/or use the size of the set + * returned by {@link #subjects()} to verify if the subject is + * unique. + */ + @Deprecated + public default Optional subjectIRI() + throws ModelException + { + Optional subjectResource = subjectResource(); + if (subjectResource.isPresent()) { + if (subjectResource.get() instanceof IRI) { + return Optional.of((IRI)subjectResource.get()); + } + else { + throw new ModelException("Did not find a unique subject URI"); + } + } + else { + return Optional.empty(); + } + } + + /** + * Provided for backward-compatibility purposes only, this method executes + * {@link #subjectIRI} instead. + * + * @deprecated use {@link #subjectIRI()} instead. + */ + @Deprecated + public default Optional subjectURI() + throws ModelException + { + return subjectIRI(); + } + + /** + * Utility method that casts the return value of {@link #subjectResource()} + * to a BNode, or throws a ModelException if that value is not a BNode. + * + * @return The subject of the matched statement(s), or {@code null} if no + * matching statements were found. + * @throws ModelException + * If such an exception is thrown by {@link #subjectResource()} or if + * its return value is not a BNode. + * @since 2.8.0 + * @deprecated since 4.0. Instead, use {@link Models#subjectBNode(Model)} to + * retrieve a subject BNode, and/or use the size of the set + * returned by {@link #subjects()} to verify if the subject is + * unique. + */ + @Deprecated + public default Optional subjectBNode() + throws ModelException + { + Optional subjectResource = subjectResource(); + if (subjectResource.isPresent()) { + if (subjectResource.get() instanceof BNode) { + return Optional.of((BNode)subjectResource.get()); + } + else { + throw new ModelException("Did not find a unique subject URI"); + } + } + else { + return Optional.empty(); + } + } + + /** + * Returns a {@link Set} view of the predicates contained in this model. The + * set is backed by the model, so changes to the model are reflected in the + * set, and vice-versa. If the model is modified while an iteration over the + * set is in progress (except through the iterator's own {@code remove} + * operation), the results of the iteration are undefined. The set supports + * element removal, which removes all statements from the model for which + * that element is a predicate value, via the {@code Iterator.remove}, + * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and + * {@code clear} operations. It does not support the {@code add} or + * {@code addAll} operations if the parameters {@code subj} or {@code obj} + * are null. + * + * @return a set view of the predicates contained in this model + */ + public Set predicates(); + + /** + * Returns a {@link Set} view of the objects contained in this model. The set + * is backed by the model, so changes to the model are reflected in the set, + * and vice-versa. If the model is modified while an iteration over the set + * is in progress (except through the iterator's own {@code remove} + * operation), the results of the iteration are undefined. The set supports + * element removal, which removes all statements from the model for which + * that element is an object value, via the {@code Iterator.remove}, + * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and + * {@code clear} operations. It does not support the {@code add} or + * {@code addAll} operations if the parameters {@code subj} or {@code pred} + * are null. + * + * @return a set view of the objects contained in this model + */ + public Set objects(); + + /** + * Returns a {@link Set} view of the contexts contained in this model. The + * set is backed by the model, so changes to the model are reflected in the + * set, and vice-versa. If the model is modified while an iteration over the + * set is in progress (except through the iterator's own {@code remove} + * operation), the results of the iteration are undefined. The set supports + * element removal, which removes all statements from the model for which + * that element is a context value, via the {@code Iterator.remove}, + * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and + * {@code clear} operations. It does not support the {@code add} or + * {@code addAll} operations if the parameters {@code subj} , {@code pred} or + * {@code obj} are null. + * + * @return a set view of the contexts contained in this model + */ + public default Set contexts() { + Set subjects = stream().map(st -> st.getContext()).collect(Collectors.toSet()); + return subjects; + }; + + /** + * Gets the object of the statement(s). If the model contains one or more + * statements, all these statements should have the same object. A + * {@link ModelException} is thrown if this is not the case. + * + * @return The object of the matched statement(s), or + * {@link Optional#empty()} if no matching statements were found. + * @throws ModelException + * If the statements matched by the specified parameters have more + * than one unique object. + * @deprecated since 4.0. Instead, use {@link Models#object(Model)} to + * retrieve an object value, and/or use the size of the set + * returned by {@link #objects()} to verify if the object is + * unique. + */ + @Deprecated + public default Optional objectValue() + throws ModelException + { + Set result = stream().map(st -> st.getObject()).distinct().limit(2).collect(Collectors.toSet()); + if (result.isEmpty()) { + return Optional.empty(); + } + else if (result.size() > 1) { + throw new ModelException("Did not find a unique object value"); + } + else { + return Optional.of(result.iterator().next()); + } + }; + + /** + * Utility method that casts the return value of {@link #objectValue()} to a + * Literal, or throws a ModelUtilException if that value is not a Literal. + * + * @return The object of the matched statement(s), or + * {@link Optional#empty()} if no matching statements were found. + * @throws ModelException + * If such an exception is thrown by {@link #objectValue()} or if its + * return value is not a Literal. + * @deprecated since 4.0. Instead, use {@link Models#objectLiteral(Model)} to + * retrieve an object Literal value, and/or use the size of the + * set returned by {@link #objects()} to verify if the object is + * unique. + */ + @Deprecated + public default Optional objectLiteral() + throws ModelException + { + Optional objectValue = objectValue(); + if (objectValue.isPresent()) { + if (objectValue.get() instanceof Literal) { + return Optional.of((Literal)objectValue.get()); + } + else { + throw new ModelException("Did not find a unique object literal"); + } + } + else { + return Optional.empty(); + } + } + + /** + * Utility method that casts the return value of {@link #objectValue()} to a + * Resource, or throws a ModelUtilException if that value is not a Resource. + * + * @return The object of the matched statement(s), or + * {@link Optional#empty()} if no matching statements were found. + * @throws ModelException + * If such an exception is thrown by {@link #objectValue()} or if its + * return value is not a Resource. + * @deprecated since 4.0. Instead, use {@link Models#objectResource(Model)} + * to retrieve an object Resource value, and/or use the size of + * the set returned by {@link #objects()} to verify if the object + * is unique. + */ + @Deprecated + public default Optional objectResource() + throws ModelException + { + Optional objectValue = objectValue(); + if (objectValue.isPresent()) { + if (objectValue.get() instanceof Resource) { + return Optional.of((Resource)objectValue.get()); + } + else { + throw new ModelException("Did not find a unique object resource"); + } + } + else { + return Optional.empty(); + } + } + + /** + * Utility method that casts the return value of {@link #objectValue()} to an + * IRI, or throws a ModelUtilException if that value is not an IRI. + * + * @return The object of the matched statement(s), or + * {@link Optional#empty()} if no matching statements were found. + * @throws ModelException + * If such an exception is thrown by {@link #objectValue()} or if its + * return value is not an IRI. + * @deprecated since 4.0. Instead, use {@link Models#objectURI(Model)} to + * retrieve an object URI value, and/or use the size of the set + * returned by {@link #objects()} to verify if the object is + * unique. + */ + @Deprecated + public default Optional objectIRI() + throws ModelException + { + Optional objectValue = objectValue(); + if (objectValue.isPresent()) { + if (objectValue.get() instanceof IRI) { + return Optional.of((IRI)objectValue.get()); + } + else { + throw new ModelException("Did not find a unique object URI"); + } + } + else { + return Optional.empty(); + } + } + + /** + * Provided for backward-compatibility purposes only, this method executes + * {@link #objectIRI} instead. + * + * @deprecated use {@link #objectIRI()} instead. + */ + @Deprecated + public default Optional objectURI() + throws ModelException + { + return objectIRI(); + } + + /** + * Utility method that returns the string value of {@link #objectValue()}. + * + * @return The object string value of the matched statement(s), or + * {@link Optional#empty()} if no matching statements were found. + * @throws ModelException + * If the statements matched by the specified parameters have more + * than one unique object. + * @deprecated since 4.0. Instead, use {@link Models#objectString(Model)} to + * retrieve an object string value, and/or use the size of the + * set returned by {@link #objects()} to verify if the object is + * unique. + */ + @Deprecated + public default Optional objectString() + throws ModelException + { + Optional objectValue = objectValue(); + if (objectValue.isPresent()) { + return Optional.of(objectValue.get().stringValue()); + } + else { + return Optional.empty(); + } + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/ModelFactory.java b/core/model/src/main/java/org/eclipse/rdf4j/model/ModelFactory.java new file mode 100644 index 00000000000..0335a044d7e --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/ModelFactory.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +/** + * Factory to create empty {@link Model} implementations. + * + * @author James Leigh + */ +public interface ModelFactory { + + /** + * @return a newly created {@link Model} + */ + Model createEmptyModel(); + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/Namespace.java b/core/model/src/main/java/org/eclipse/rdf4j/model/Namespace.java new file mode 100644 index 00000000000..791c6ca477d --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/Namespace.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import java.io.Serializable; + +/** + * A namespace, consisting of a namespace name and a prefix that has been + * assigned to it. + */ +public interface Namespace extends Serializable, Comparable { + + /** + * Gets the name of the current namespace (i.e. its IRI). + * + * @return name of namespace + */ + public String getName(); + + /** + * Gets the prefix of the current namespace. The default namespace is + * represented by an empty prefix string. + * + * @return prefix of namespace, or an empty string in case of the default + * namespace. + */ + public String getPrefix(); +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/Resource.java b/core/model/src/main/java/org/eclipse/rdf4j/model/Resource.java new file mode 100644 index 00000000000..6ed3bb28496 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/Resource.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + + +/** + * The supertype of all RDF resources (IRIs and blank nodes). + */ +public interface Resource extends Value { + // Empty place holder as common supertype of IRI and BNode +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/Statement.java b/core/model/src/main/java/org/eclipse/rdf4j/model/Statement.java new file mode 100644 index 00000000000..5a493a10e19 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/Statement.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import java.io.Serializable; + +/** + * An RDF statement, with optional associated context. A statement can have an + * associated context in specific cases, for example when fetched from a + * repository. The context field does not influence statement equality; a + * statement is equal to another statement if the subjects, predicates and + * objects are equal. + */ +public interface Statement extends Serializable { + + /** + * Gets the subject of this statement. + * + * @return The statement's subject. + */ + public Resource getSubject(); + + /** + * Gets the predicate of this statement. + * + * @return The statement's predicate. + */ + public IRI getPredicate(); + + /** + * Gets the object of this statement. + * + * @return The statement's object. + */ + public Value getObject(); + + /** + * Gets the context of this statement. + * + * @return The statement's context, or null in case of the null + * context or if not applicable. + */ + public Resource getContext(); + + /** + * Compares a statement object to another object. + * + * @param other + * The object to compare this statement to. + * @return true if the other object is an instance of + * {@link Statement} and if their subjects, predicates, objects and + * contexts are equal. + */ + public boolean equals(Object other); + + /** + * The hash code of a statement. + * + * @return A hash code for the statement. + */ + public int hashCode(); +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/URI.java b/core/model/src/main/java/org/eclipse/rdf4j/model/URI.java new file mode 100644 index 00000000000..fe91792a987 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/URI.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +/** + * A Uniform Resource Identifier (URI). + * + * @deprecated Since 4.0. Use {@link IRI} instead. + * @author Jeen Broekstra + * @author Arjohn Kampman + * @see RFC 3986 + */ +@Deprecated +public interface URI extends Resource { + + /** + * Returns the String-representation of this URI. + * + * @return The String-representation of this URI. + */ + @Override + public String toString(); + + /** + * Gets the namespace part of this URI. The namespace is defined as per the + * algorithm described in the class documentation. + * + * @return The URI's namespace. + */ + public String getNamespace(); + + /** + * Gets the local name part of this URI. The local name is defined as per the + * algorithm described in the class documentation. + * + * @return The URI's local name. + */ + public String getLocalName(); + + /** + * Compares a URI object to another object. + * + * @param o + * The object to compare this URI to. + * @return true if the other object is an instance of {@link URI} + * and their String-representations are equal, false + * otherwise. + */ + @Override + public boolean equals(Object o); + + /** + * The hash code of an URI is defined as the hash code of its + * String-representation: toString().hashCode. + * + * @return A hash code for the URI. + */ + @Override + public int hashCode(); + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/Value.java b/core/model/src/main/java/org/eclipse/rdf4j/model/Value.java new file mode 100644 index 00000000000..d5a0a80449d --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/Value.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import java.io.Serializable; + +/** + * The supertype of all RDF model objects (URIs, blank nodes and literals). + */ +public interface Value extends Serializable { + + /** + * Returns the String-value of a Value object. This returns either + * a {@link Literal}'s label, a {@link IRI}'s URI or a {@link BNode}'s ID. + */ + public String stringValue(); +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/ValueFactory.java b/core/model/src/main/java/org/eclipse/rdf4j/model/ValueFactory.java new file mode 100644 index 00000000000..ff3fa0ce0a3 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/ValueFactory.java @@ -0,0 +1,315 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; + +import javax.xml.datatype.XMLGregorianCalendar; + +/** + * A factory for creating {@link IRI IRIs}, {@link BNode blank nodes}, + * {@link Literal literals} and {@link Statement statements}. + * + * @author Arjohn Kampman + */ +public interface ValueFactory { + + /** + * Creates a new IRI from the supplied string-representation. + * + * @param iri + * A string-representation of a IRI. + * @return An object representing the IRI. + * @throws IlllegalArgumentException + * If the supplied string does not resolve to a legal (absolute) IRI. + */ + public IRI createIRI(String iri); + + /** + * Creates a new URI from the supplied string-representation. + * + * @param uri + * A string-representation of a URI. + * @return An object representing the URI. + * @throws IlllegalArgumentException + * If the supplied string does not resolve to a legal (absolute) URI. + * @deprecated since 4.0. Use {{@link #createIRI(String)} instead. + */ + @Deprecated + public default URI createURI(String uri) { + return createIRI(uri); + } + + /** + * Creates a new IRI from the supplied namespace and local name. Calling this + * method is funtionally equivalent to calling {@link #createIRI(String) + * createIRI(namespace+localName)}, but allows the ValueFactory to reuse + * supplied namespace and local name strings whenever possible. Note that the + * values returned by {@link IRI#getNamespace()} and + * {@link IRI#getLocalName()} are not necessarily the same as the values that + * are supplied to this method. + * + * @param namespace + * The IRI's namespace. + * @param localName + * The IRI's local name. + * @throws IllegalArgumentException + * If the supplied namespace and localname do not resolve to a legal + * (absolute) IRI. + */ + public IRI createIRI(String namespace, String localName); + + /** + * Creates a new URI from the supplied namespace and local name. + * + * @param uri + * A string-representation of a URI. + * @return An object representing the URI. + * @throws IlllegalArgumentException + * If the supplied string does not resolve to a legal (absolute) URI. + * @deprecated since 4.0. Use {{@link #createIRI(String, String)} instead. + */ + @Deprecated + public default URI createURI(String namespace, String localName) { + return createIRI(namespace, localName); + } + + /** + * Creates a new bNode. + * + * @return An object representing the bNode. + */ + public BNode createBNode(); + + /** + * Creates a new blank node with the given node identifier. + * + * @param nodeID + * The blank node identifier. + * @return An object representing the blank node. + */ + public BNode createBNode(String nodeID); + + /** + * Creates a new literal with the supplied label. + * + * @param label + * The literal's label. + */ + public Literal createLiteral(String label); + + /** + * Creates a new literal with the supplied label and language attribute. + * + * @param label + * The literal's label. + * @param language + * The literal's language attribute, or null if the literal + * doesn't have a language. + */ + public Literal createLiteral(String label, String language); + + /** + * Creates a new literal with the supplied label and datatype. + * + * @param label + * The literal's label. + * @param datatype + * The literal's datatype, or null if the literal doesn't + * have a datatype. + */ + public Literal createLiteral(String label, IRI datatype); + + /** + * Creates a new literal with the supplied label and datatype. + * + * @param label + * The literal's label. + * @param datatype + * The literal's datatype, or null if the literal doesn't + * have a datatype. + * @deprecated since 4.0. Use {@link #createLiteral(String, IRI)} instead. + */ + @Deprecated + public default Literal createLiteral(String label, URI datatype) { + return createLiteral(label, (IRI)datatype); + } + + /** + * Creates a new xsd:boolean-typed literal representing the + * specified value. + * + * @param value + * The value for the literal. + * @return An xsd:boolean-typed literal for the specified value. + */ + public Literal createLiteral(boolean value); + + /** + * Creates a new xsd:byte-typed literal representing the specified + * value. + * + * @param value + * The value for the literal. + * @return An xsd:byte-typed literal for the specified value. + */ + public Literal createLiteral(byte value); + + /** + * Creates a new xsd:short-typed literal representing the specified + * value. + * + * @param value + * The value for the literal. + * @return An xsd:short-typed literal for the specified value. + */ + public Literal createLiteral(short value); + + /** + * Creates a new xsd:int-typed literal representing the specified + * value. + * + * @param value + * The value for the literal. + * @return An xsd:int-typed literal for the specified value. + */ + public Literal createLiteral(int value); + + /** + * Creates a new xsd:long-typed literal representing the specified + * value. + * + * @param value + * The value for the literal. + * @return An xsd:long-typed literal for the specified value. + */ + public Literal createLiteral(long value); + + /** + * Creates a new xsd:float-typed literal representing the specified + * value. + * + * @param value + * The value for the literal. + * @return An xsd:float-typed literal for the specified value. + */ + public Literal createLiteral(float value); + + /** + * Creates a new xsd:double-typed literal representing the specified + * value. + * + * @param value + * The value for the literal. + * @return An xsd:double-typed literal for the specified value. + */ + public Literal createLiteral(double value); + + /** + * Creates a new literal representing the specified bigDecimal that is typed + * using the appropriate XML Schema date/time datatype. + * + * @since 4.0 + */ + public Literal createLiteral(BigDecimal bigDecimal); + + /** + * Creates a new literal representing the specified bigInteger that is typed + * using the appropriate XML Schema date/time datatype. + * + * @since 4.0 + */ + public Literal createLiteral(BigInteger bigInteger); + + /** + * Creates a new literal representing the specified calendar that is typed + * using the appropriate XML Schema date/time datatype. + * + * @param calendar + * The value for the literal. + * @return An typed literal for the specified calendar. + */ + public Literal createLiteral(XMLGregorianCalendar calendar); + + /** + * Creates a new literal representing the specified date that is typed using + * the appropriate XML Schema date/time datatype. + * + * @since 2.7.0 + */ + public Literal createLiteral(Date date); + + /** + * Creates a new statement with the supplied subject, predicate and object. + * + * @param subject + * The statement's subject. + * @param predicate + * The statement's predicate. + * @param object + * The statement's object. + * @return The created statement. + */ + public Statement createStatement(Resource subject, IRI predicate, Value object); + + /** + * Creates a new statement with the supplied subject, predicate and object. + * + * @param subject + * The statement's subject. + * @param predicate + * The statement's predicate. + * @param object + * The statement's object. + * @return The created statement. + * @deprecated since 4.0. Use {@link #createStatement(Resource, IRI, Value)} + * instead. + */ + @Deprecated + public default Statement createStatement(Resource subject, URI predicate, Value object) { + return createStatement(subject, (IRI)predicate, object); + } + + /** + * Creates a new statement with the supplied subject, predicate and object + * and associated context. + * + * @param subject + * The statement's subject. + * @param predicate + * The statement's predicate. + * @param object + * The statement's object. + * @param context + * The statement's context. + * @return The created statement. + */ + public Statement createStatement(Resource subject, IRI predicate, Value object, Resource context); + + /** + * Creates a new statement with the supplied subject, predicate and object + * and associated context. + * + * @param subject + * The statement's subject. + * @param predicate + * The statement's predicate. + * @param object + * The statement's object. + * @return The created statement. + * @deprecated since 4.0. Use + * {@link #createStatement(Resource, IRI, Value, Resource)} + * instead. + */ + @Deprecated + public default Statement createStatement(Resource subject, URI predicate, Value object, Resource context) { + return createStatement(subject, (IRI)predicate, object, context); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtil.java b/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtil.java new file mode 100644 index 00000000000..9e96976fb51 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtil.java @@ -0,0 +1,1987 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.datatypes; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.StringTokenizer; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import org.eclipse.rdf4j.common.text.ASCIIUtil; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; + +/** + * Provides methods for handling the standard XML Schema datatypes. + * + * @author Arjohn Kampman + */ +public class XMLDatatypeUtil { + + private static DatatypeFactory dtFactory; + + static { + try { + dtFactory = DatatypeFactory.newInstance(); + } + catch (DatatypeConfigurationException e) { + throw new RuntimeException(e); + } + } + + /*-------------------* + * Datatype checking * + *-------------------*/ + + /** + * Checks whether the supplied datatype is a primitive XML Schema datatype. + */ + public static boolean isPrimitiveDatatype(IRI datatype) { + return datatype.equals(XMLSchema.DURATION) || datatype.equals(XMLSchema.DATETIME) + || datatype.equals(XMLSchema.TIME) || datatype.equals(XMLSchema.DATE) + || datatype.equals(XMLSchema.GYEARMONTH) || datatype.equals(XMLSchema.GYEAR) + || datatype.equals(XMLSchema.GMONTHDAY) || datatype.equals(XMLSchema.GDAY) + || datatype.equals(XMLSchema.GMONTH) || datatype.equals(XMLSchema.STRING) + || datatype.equals(XMLSchema.BOOLEAN) || datatype.equals(XMLSchema.BASE64BINARY) + || datatype.equals(XMLSchema.HEXBINARY) || datatype.equals(XMLSchema.FLOAT) + || datatype.equals(XMLSchema.DECIMAL) || datatype.equals(XMLSchema.DOUBLE) + || datatype.equals(XMLSchema.ANYURI) || datatype.equals(XMLSchema.QNAME) + || datatype.equals(XMLSchema.NOTATION); + } + + /** + * Checks whether the supplied datatype is a derived XML Schema datatype. + */ + public static boolean isDerivedDatatype(IRI datatype) { + return datatype.equals(XMLSchema.NORMALIZEDSTRING) || datatype.equals(XMLSchema.TOKEN) + || datatype.equals(XMLSchema.LANGUAGE) || datatype.equals(XMLSchema.NMTOKEN) + || datatype.equals(XMLSchema.NMTOKENS) || datatype.equals(XMLSchema.NAME) + || datatype.equals(XMLSchema.NCNAME) || datatype.equals(XMLSchema.ID) + || datatype.equals(XMLSchema.IDREF) || datatype.equals(XMLSchema.IDREFS) + || datatype.equals(XMLSchema.ENTITY) || datatype.equals(XMLSchema.ENTITIES) + || datatype.equals(XMLSchema.INTEGER) || datatype.equals(XMLSchema.LONG) + || datatype.equals(XMLSchema.INT) || datatype.equals(XMLSchema.SHORT) + || datatype.equals(XMLSchema.BYTE) || datatype.equals(XMLSchema.NON_POSITIVE_INTEGER) + || datatype.equals(XMLSchema.NEGATIVE_INTEGER) || datatype.equals(XMLSchema.NON_NEGATIVE_INTEGER) + || datatype.equals(XMLSchema.POSITIVE_INTEGER) || datatype.equals(XMLSchema.UNSIGNED_LONG) + || datatype.equals(XMLSchema.UNSIGNED_INT) || datatype.equals(XMLSchema.UNSIGNED_SHORT) + || datatype.equals(XMLSchema.UNSIGNED_BYTE); + } + + /** + * Checks whether the supplied datatype is a built-in XML Schema datatype. + */ + public static boolean isBuiltInDatatype(IRI datatype) { + return isPrimitiveDatatype(datatype) || isDerivedDatatype(datatype); + } + + /** + * Checks whether the supplied datatype is a numeric datatype, i.e. if it is + * equal to xsd:float, xsd:double, xsd:decimal or one of the datatypes + * derived from xsd:decimal. + */ + public static boolean isNumericDatatype(IRI datatype) { + return isDecimalDatatype(datatype) || isFloatingPointDatatype(datatype); + } + + /** + * Checks whether the supplied datatype is equal to xsd:decimal or one of the + * built-in datatypes that is derived from xsd:decimal. + */ + public static boolean isDecimalDatatype(IRI datatype) { + return datatype.equals(XMLSchema.DECIMAL) || isIntegerDatatype(datatype); + } + + /** + * Checks whether the supplied datatype is equal to xsd:integer or one of the + * built-in datatypes that is derived from xsd:integer. + */ + public static boolean isIntegerDatatype(IRI datatype) { + return datatype.equals(XMLSchema.INTEGER) || datatype.equals(XMLSchema.LONG) + || datatype.equals(XMLSchema.INT) || datatype.equals(XMLSchema.SHORT) + || datatype.equals(XMLSchema.BYTE) || datatype.equals(XMLSchema.NON_POSITIVE_INTEGER) + || datatype.equals(XMLSchema.NEGATIVE_INTEGER) || datatype.equals(XMLSchema.NON_NEGATIVE_INTEGER) + || datatype.equals(XMLSchema.POSITIVE_INTEGER) || datatype.equals(XMLSchema.UNSIGNED_LONG) + || datatype.equals(XMLSchema.UNSIGNED_INT) || datatype.equals(XMLSchema.UNSIGNED_SHORT) + || datatype.equals(XMLSchema.UNSIGNED_BYTE); + } + + /** + * Checks whether the supplied datatype is equal to xsd:float or xsd:double. + */ + public static boolean isFloatingPointDatatype(IRI datatype) { + return datatype.equals(XMLSchema.FLOAT) || datatype.equals(XMLSchema.DOUBLE); + } + + /** + * Checks whether the supplied datatype is equal to xsd:dateTime, xsd:date, + * xsd:time, xsd:gYearMonth, xsd:gMonthDay, xsd:gYear, xsd:gMonth or + * xsd:gDay. These are the primitive datatypes that represent dates and/or + * times. + * + * @see XMLGregorianCalendar + */ + public static boolean isCalendarDatatype(IRI datatype) { + return datatype.equals(XMLSchema.DATETIME) || datatype.equals(XMLSchema.DATE) + || datatype.equals(XMLSchema.TIME) || datatype.equals(XMLSchema.GYEARMONTH) + || datatype.equals(XMLSchema.GMONTHDAY) || datatype.equals(XMLSchema.GYEAR) + || datatype.equals(XMLSchema.GMONTH) || datatype.equals(XMLSchema.GDAY); + + } + + /** + * Checks whether the supplied datatype is ordered. The values of an ordered + * datatype can be compared to eachother using operators like < + * and >. + */ + public static boolean isOrderedDatatype(IRI datatype) { + return isNumericDatatype(datatype) || isCalendarDatatype(datatype); + } + + /*----------------* + * Value checking * + *----------------*/ + + /** + * Verifies if the supplied lexical value is valid for the given datatype. + * + * @param value + * a lexical value + * @param datatype + * an XML Schema datatatype. + * @return true if the supplied lexical value is valid, false otherwise. + */ + public static boolean isValidValue(String value, IRI datatype) { + boolean result = true; + + if (datatype.equals(XMLSchema.DECIMAL)) { + result = isValidDecimal(value); + } + else if (datatype.equals(XMLSchema.INTEGER)) { + result = isValidInteger(value); + } + else if (datatype.equals(XMLSchema.NEGATIVE_INTEGER)) { + result = isValidNegativeInteger(value); + } + else if (datatype.equals(XMLSchema.NON_POSITIVE_INTEGER)) { + result = isValidNonPositiveInteger(value); + } + else if (datatype.equals(XMLSchema.NON_NEGATIVE_INTEGER)) { + result = isValidNonNegativeInteger(value); + } + else if (datatype.equals(XMLSchema.POSITIVE_INTEGER)) { + result = isValidPositiveInteger(value); + } + else if (datatype.equals(XMLSchema.LONG)) { + result = isValidLong(value); + } + else if (datatype.equals(XMLSchema.INT)) { + result = isValidInt(value); + } + else if (datatype.equals(XMLSchema.SHORT)) { + result = isValidShort(value); + } + else if (datatype.equals(XMLSchema.BYTE)) { + result = isValidByte(value); + } + else if (datatype.equals(XMLSchema.UNSIGNED_LONG)) { + result = isValidUnsignedLong(value); + } + else if (datatype.equals(XMLSchema.UNSIGNED_INT)) { + result = isValidUnsignedInt(value); + } + else if (datatype.equals(XMLSchema.UNSIGNED_SHORT)) { + result = isValidUnsignedShort(value); + } + else if (datatype.equals(XMLSchema.UNSIGNED_BYTE)) { + result = isValidUnsignedByte(value); + } + else if (datatype.equals(XMLSchema.FLOAT)) { + result = isValidFloat(value); + } + else if (datatype.equals(XMLSchema.DOUBLE)) { + result = isValidDouble(value); + } + else if (datatype.equals(XMLSchema.BOOLEAN)) { + result = isValidBoolean(value); + } + else if (datatype.equals(XMLSchema.DATETIME)) { + result = isValidDateTime(value); + } + else if (datatype.equals(XMLSchema.DATE)) { + result = isValidDate(value); + } + else if (datatype.equals(XMLSchema.TIME)) { + result = isValidTime(value); + } + else if (datatype.equals(XMLSchema.GDAY)) { + result = isValidGDay(value); + } + else if (datatype.equals(XMLSchema.GMONTH)) { + result = isValidGMonth(value); + } + else if (datatype.equals(XMLSchema.GMONTHDAY)) { + result = isValidGMonthDay(value); + } + else if (datatype.equals(XMLSchema.GYEAR)) { + result = isValidGYear(value); + } + else if (datatype.equals(XMLSchema.GYEARMONTH)) { + result = isValidGYearMonth(value); + } + else if (datatype.equals(XMLSchema.DURATION)) { + result = isValidDuration(value); + } + else if (datatype.equals(XMLSchema.DAYTIMEDURATION)) { + result = isValidDayTimeDuration(value); + } + else if (datatype.equals(XMLSchema.QNAME)) { + result = isValidQName(value); + } + + return result; + } + + public static boolean isValidDecimal(String value) { + try { + normalizeDecimal(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidInteger(String value) { + try { + normalizeInteger(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidNegativeInteger(String value) { + try { + normalizeNegativeInteger(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidNonPositiveInteger(String value) { + try { + normalizeNonPositiveInteger(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidNonNegativeInteger(String value) { + try { + normalizeNonNegativeInteger(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidPositiveInteger(String value) { + try { + normalizePositiveInteger(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidLong(String value) { + try { + normalizeLong(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidInt(String value) { + try { + normalizeInt(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidShort(String value) { + try { + normalizeShort(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidByte(String value) { + try { + normalizeByte(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidUnsignedLong(String value) { + try { + normalizeUnsignedLong(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidUnsignedInt(String value) { + try { + normalizeUnsignedInt(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidUnsignedShort(String value) { + try { + normalizeUnsignedShort(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidUnsignedByte(String value) { + try { + normalizeUnsignedByte(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidFloat(String value) { + try { + normalizeFloat(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidDouble(String value) { + try { + normalizeDouble(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidBoolean(String value) { + try { + normalizeBoolean(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isValidDuration(String value) { + + // voodoo regex for checking valid xsd:duration string. See + // http://www.w3.org/TR/xmlschema-2/#duration for details. + String regex = "-?P((\\d)+Y)?((\\d)+M)?((\\d)+D)?((T(\\d)+H((\\d)+M)?((\\d)+(\\.(\\d)+)?S)?)|(T(\\d)+M((\\d)+(\\.(\\d)+)?S)?)|(T(\\d)+(\\.(\\d)+)?S))?"; + return value.length() > 1 && value.matches(regex); + } + + public static boolean isValidDayTimeDuration(String value) { + + // regex for checking valid xsd:dayTimeDuration string. See + // http://www.schemacentral.com/sc/xsd/t-xsd_dayTimeDuration.html + String regex = "-?P((\\d)+D)?((T(\\d)+H((\\d)+M)?((\\d)+(\\.(\\d)+)?S)?)|(T(\\d)+M((\\d)+(\\.(\\d)+)?S)?)|(T(\\d)+(\\.(\\d)+)?S))?"; + return value.length() > 1 && value.matches(regex); + } + + public static boolean isValidDateTime(String value) { + try { + @SuppressWarnings("unused") + XMLDateTime dt = new XMLDateTime(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + /** + * Determines if the supplied value is a valid xsd:date string. + * + * @param value + * @return true if valid, false otherwise + */ + public static boolean isValidDate(String value) { + + String regex = "-?\\d\\d\\d\\d-\\d\\d-\\d\\d(Z|(\\+|-)\\d\\d:\\d\\d)?"; + + if (value.matches(regex)) { + return isValidCalendarValue(value); + } + else { + return false; + } + } + + /** + * Determines if the supplied value is a valid xsd:time string. + * + * @param value + * @return true if valid, false otherwise + */ + public static boolean isValidTime(String value) { + + String regex = "\\d\\d:\\d\\d:\\d\\d(\\.\\d+)?(Z|(\\+|-)\\d\\d:\\d\\d)?"; + + if (value.matches(regex)) { + return isValidCalendarValue(value); + } + else { + return false; + } + } + + /** + * Determines if the supplied value is a valid xsd:gDay string. + * + * @param value + * @return true if valid, false otherwise + */ + public static boolean isValidGDay(String value) { + + String regex = "---\\d\\d(Z|(\\+|-)\\d\\d:\\d\\d)?"; + + if (value.matches(regex)) { + return isValidCalendarValue(value); + } + else { + return false; + } + } + + /** + * Determines if the supplied value is a valid xsd:gMonth string. + * + * @param value + * @return true if valid, false otherwise + */ + public static boolean isValidGMonth(String value) { + + String regex = "--\\d\\d(Z|(\\+|-)\\d\\d:\\d\\d)?"; + + if (value.matches(regex)) { + return isValidCalendarValue(value); + } + else { + return false; + } + } + + /** + * Determines if the supplied value is a valid xsd:gMonthDay string. + * + * @param value + * @return true if valid, false otherwise + */ + public static boolean isValidGMonthDay(String value) { + + String regex = "--\\d\\d-\\d\\d(Z|(\\+|-)\\d\\d:\\d\\d)?"; + + if (value.matches(regex)) { + return isValidCalendarValue(value); + } + else { + return false; + } + } + + /** + * Determines if the supplied value is a valid xsd:gYear string. + * + * @param value + * @return true if valid, false otherwise + */ + public static boolean isValidGYear(String value) { + + String regex = "-?\\d\\d\\d\\d(Z|(\\+|-)\\d\\d:\\d\\d)?"; + + if (value.matches(regex)) { + return isValidCalendarValue(value); + } + else { + return false; + } + } + + /** + * Determines if the supplied value is a valid xsd:gYearMonth string. + * + * @param value + * @return true if valid, false otherwise + */ + public static boolean isValidGYearMonth(String value) { + + String regex = "-?\\d\\d\\d\\d-\\d\\d(Z|(\\+|-)\\d\\d:\\d\\d)?"; + + if (value.matches(regex)) { + return isValidCalendarValue(value); + } + else { + return false; + } + } + + /** + * Determines if the supplied value is a valid xsd:QName string. Note that + * this method only checks for syntax errors in the supplied string itself. + * It does not validate that the prefix is a declared and in-scope namespace + * prefix. + * + * @param value + * @return true if valid, false otherwise + */ + public static boolean isValidQName(String value) { + + String[] split = value.split(":", -2); + + if (split.length != 2) { + return false; + } + + // check prefix + String prefix = split[0]; + if (!"".equals(prefix)) { + if (!isPrefixStartChar(prefix.charAt(0))) { + return false; + } + + for (int i = 1; i < prefix.length(); i++) { + if (!isNameChar(prefix.charAt(i))) { + return false; + } + } + } + + String name = split[1]; + + if (!"".equals(name)) { + // check name + if (!isNameStartChar(name.charAt(0))) { + return false; + } + + for (int i = 1; i < name.length(); i++) { + if (!isNameChar(name.charAt(i))) { + return false; + } + } + } + + return true; + } + + private static boolean isPrefixStartChar(int c) { + return ASCIIUtil.isLetter(c) || c >= 0x00C0 && c <= 0x00D6 || c >= 0x00D8 && c <= 0x00F6 || c >= 0x00F8 + && c <= 0x02FF || c >= 0x0370 && c <= 0x037D || c >= 0x037F && c <= 0x1FFF || c >= 0x200C + && c <= 0x200D || c >= 0x2070 && c <= 0x218F || c >= 0x2C00 && c <= 0x2FEF || c >= 0x3001 + && c <= 0xD7FF || c >= 0xF900 && c <= 0xFDCF || c >= 0xFDF0 && c <= 0xFFFD || c >= 0x10000 + && c <= 0xEFFFF; + } + + private static boolean isNameStartChar(int c) { + return c == '_' || isPrefixStartChar(c); + } + + private static boolean isNameChar(int c) { + return isNameStartChar(c) || ASCIIUtil.isNumber(c) || c == '-' || c == 0x00B7 || c >= 0x0300 + && c <= 0x036F || c >= 0x203F && c <= 0x2040; + } + + /** + * Determines if the supplied string can be parsed to a valid + * XMLGregorianCalendar value. + * + * @param value + * @return true if the supplied string is a parsable calendar value, false + * otherwise. + */ + private static boolean isValidCalendarValue(String value) { + try { + XMLDatatypeUtil.parseCalendar(value); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + /*---------------------* + * Value normalization * + *---------------------*/ + + /** + * Normalizes the supplied value according to the normalization rules for the + * supplied datatype. + * + * @param value + * The value to normalize. + * @param datatype + * The value's datatype. + * @return The normalized value if there are any (supported) normalization + * rules for the supplied datatype, or the original supplied value + * otherwise. + * @throws IllegalArgumentException + * If the supplied value is illegal considering the supplied + * datatype. + */ + public static String normalize(String value, IRI datatype) { + String result = value; + + if (datatype.equals(XMLSchema.DECIMAL)) { + result = normalizeDecimal(value); + } + else if (datatype.equals(XMLSchema.INTEGER)) { + result = normalizeInteger(value); + } + else if (datatype.equals(XMLSchema.NEGATIVE_INTEGER)) { + result = normalizeNegativeInteger(value); + } + else if (datatype.equals(XMLSchema.NON_POSITIVE_INTEGER)) { + result = normalizeNonPositiveInteger(value); + } + else if (datatype.equals(XMLSchema.NON_NEGATIVE_INTEGER)) { + result = normalizeNonNegativeInteger(value); + } + else if (datatype.equals(XMLSchema.POSITIVE_INTEGER)) { + result = normalizePositiveInteger(value); + } + else if (datatype.equals(XMLSchema.LONG)) { + result = normalizeLong(value); + } + else if (datatype.equals(XMLSchema.INT)) { + result = normalizeInt(value); + } + else if (datatype.equals(XMLSchema.SHORT)) { + result = normalizeShort(value); + } + else if (datatype.equals(XMLSchema.BYTE)) { + result = normalizeByte(value); + } + else if (datatype.equals(XMLSchema.UNSIGNED_LONG)) { + result = normalizeUnsignedLong(value); + } + else if (datatype.equals(XMLSchema.UNSIGNED_INT)) { + result = normalizeUnsignedInt(value); + } + else if (datatype.equals(XMLSchema.UNSIGNED_SHORT)) { + result = normalizeUnsignedShort(value); + } + else if (datatype.equals(XMLSchema.UNSIGNED_BYTE)) { + result = normalizeUnsignedByte(value); + } + else if (datatype.equals(XMLSchema.FLOAT)) { + result = normalizeFloat(value); + } + else if (datatype.equals(XMLSchema.DOUBLE)) { + result = normalizeDouble(value); + } + else if (datatype.equals(XMLSchema.BOOLEAN)) { + result = normalizeBoolean(value); + } + else if (datatype.equals(XMLSchema.DATETIME)) { + result = normalizeDateTime(value); + } + + return result; + } + + /** + * Normalizes a boolean value to its canonical representation. More + * specifically, the values 1 and 0 will be normalized to + * the canonical values true and false, respectively. + * Supplied canonical values will remain as is. + * + * @param value + * The boolean value to normalize. + * @return The normalized value. + * @throws IllegalArgumentException + * If the supplied value is not a legal boolean. + */ + public static String normalizeBoolean(String value) { + value = collapseWhiteSpace(value); + + if (value.equals("1")) { + return "true"; + } + else if (value.equals("0")) { + return "false"; + } + else if (value.equals("true") || value.equals("false")) { + return value; + } + else { + throw new IllegalArgumentException("Not a legal boolean value: " + value); + } + } + + /** + * Normalizes a decimal to its canonical representation. For example: + * 120 becomes 120.0, +.3 becomes 0.3, + * 00012.45000 becomes 12.45 and -.0 becomes + * 0.0. + * + * @param decimal + * The decimal to normalize. + * @return The canonical representation of decimal. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal decimal. + */ + public static String normalizeDecimal(String decimal) { + decimal = collapseWhiteSpace(decimal); + + int decLength = decimal.length(); + StringBuilder result = new StringBuilder(decLength + 2); + + if (decLength == 0) { + throwIAE("Not a legal decimal: " + decimal); + } + + boolean isZeroPointZero = true; + + // process any sign info + int idx = 0; + if (decimal.charAt(idx) == '-') { + result.append('-'); + idx++; + } + else if (decimal.charAt(idx) == '+') { + idx++; + } + + if (idx == decLength) { + throwIAE("Not a legal decimal: " + decimal); + } + + // skip any leading zeros + while (idx < decLength && decimal.charAt(idx) == '0') { + idx++; + } + + // Process digits before the dot + if (idx == decLength) { + // decimal consists of zeros only + result.append('0'); + } + else if (idx < decLength && decimal.charAt(idx) == '.') { + // no non-zero digit before the dot + result.append('0'); + } + else { + isZeroPointZero = false; + + // Copy any digits before the dot + while (idx < decLength) { + char c = decimal.charAt(idx); + if (c == '.') { + break; + } + if (!isDigit(c)) { + throwIAE("Not a legal decimal: " + decimal); + } + result.append(c); + idx++; + } + } + + result.append('.'); + + // Process digits after the dot + if (idx == decLength) { + // No dot was found in the decimal + result.append('0'); + } + else { + idx++; + + // search last non-zero digit + int lastIdx = decLength - 1; + while (lastIdx >= 0 && decimal.charAt(lastIdx) == '0') { + lastIdx--; + } + + if (idx > lastIdx) { + // No non-zero digits found + result.append('0'); + } + else { + isZeroPointZero = false; + + while (idx <= lastIdx) { + char c = decimal.charAt(idx); + if (!isDigit(c)) { + throwIAE("Not a legal decimal: " + decimal); + } + result.append(c); + idx++; + } + } + } + + if (isZeroPointZero) { + // Make sure we don't return "-0.0" + return "0.0"; + } + else { + return result.toString(); + } + } + + /** + * Normalizes an integer to its canonical representation. For example: + * +120 becomes 120 and 00012 becomes 12. + * + * @param value + * The value to normalize. + * @return The canonical representation of value. + * @throws IllegalArgumentException + * If the supplied value is not a legal integer. + */ + public static String normalizeInteger(String value) { + return normalizeIntegerValue(value, null, null); + } + + /** + * Normalizes an xsd:negativeInteger. + */ + public static String normalizeNegativeInteger(String value) { + return normalizeIntegerValue(value, null, "-1"); + } + + /** + * Normalizes an xsd:nonPositiveInteger. + */ + public static String normalizeNonPositiveInteger(String value) { + return normalizeIntegerValue(value, null, "0"); + } + + /** + * Normalizes an xsd:nonNegativeInteger. + */ + public static String normalizeNonNegativeInteger(String value) { + return normalizeIntegerValue(value, "0", null); + } + + /** + * Normalizes an xsd:positiveInteger. + */ + public static String normalizePositiveInteger(String value) { + return normalizeIntegerValue(value, "1", null); + } + + /** + * Normalizes an xsd:long. + */ + public static String normalizeLong(String value) { + return normalizeIntegerValue(value, "-9223372036854775808", "9223372036854775807"); + } + + /** + * Normalizes an xsd:int. + */ + public static String normalizeInt(String value) { + return normalizeIntegerValue(value, "-2147483648", "2147483647"); + } + + /** + * Normalizes an xsd:short. + */ + public static String normalizeShort(String value) { + return normalizeIntegerValue(value, "-32768", "32767"); + } + + /** + * Normalizes an xsd:byte. + */ + public static String normalizeByte(String value) { + return normalizeIntegerValue(value, "-128", "127"); + } + + /** + * Normalizes an xsd:unsignedLong. + */ + public static String normalizeUnsignedLong(String value) { + return normalizeIntegerValue(value, "0", "18446744073709551615"); + } + + /** + * Normalizes an xsd:unsignedInt. + */ + public static String normalizeUnsignedInt(String value) { + return normalizeIntegerValue(value, "0", "4294967295"); + } + + /** + * Normalizes an xsd:unsignedShort. + */ + public static String normalizeUnsignedShort(String value) { + return normalizeIntegerValue(value, "0", "65535"); + } + + /** + * Normalizes an xsd:unsignedByte. + */ + public static String normalizeUnsignedByte(String value) { + return normalizeIntegerValue(value, "0", "255"); + } + + /** + * Normalizes an integer to its canonical representation and checks that the + * value is in the range [minValue, maxValue]. + */ + private static String normalizeIntegerValue(String integer, String minValue, String maxValue) { + integer = collapseWhiteSpace(integer); + + int intLength = integer.length(); + + if (intLength == 0) { + throwIAE("Not a legal integer: " + integer); + } + + int idx = 0; + + // process any sign info + boolean isNegative = false; + if (integer.charAt(idx) == '-') { + isNegative = true; + idx++; + } + else if (integer.charAt(idx) == '+') { + idx++; + } + + if (idx == intLength) { + throwIAE("Not a legal integer: " + integer); + } + + if (integer.charAt(idx) == '0' && idx < intLength - 1) { + // integer starts with a zero followed by more characters, + // skip any leading zeros + idx++; + while (idx < intLength - 1 && integer.charAt(idx) == '0') { + idx++; + } + } + + String norm = integer.substring(idx); + + // Check that all characters in 'norm' are digits + for (int i = 0; i < norm.length(); i++) { + if (!isDigit(norm.charAt(i))) { + throwIAE("Not a legal integer: " + integer); + } + } + + if (isNegative && norm.charAt(0) != '0') { + norm = "-" + norm; + } + + // Check lower and upper bounds, if applicable + if (minValue != null) { + if (compareCanonicalIntegers(norm, minValue) < 0) { + throwIAE("Value smaller than minimum value"); + } + } + if (maxValue != null) { + if (compareCanonicalIntegers(norm, maxValue) > 0) { + throwIAE("Value larger than maximum value"); + } + } + + return norm; + } + + /** + * Normalizes a float to its canonical representation. + * + * @param value + * The value to normalize. + * @return The canonical representation of value. + * @throws IllegalArgumentException + * If the supplied value is not a legal float. + */ + public static String normalizeFloat(String value) { + return normalizeFPNumber(value, "-16777215.0", "16777215.0", "-149", "104"); + } + + /** + * Normalizes a double to its canonical representation. + * + * @param value + * The value to normalize. + * @return The canonical representation of value. + * @throws IllegalArgumentException + * If the supplied value is not a legal double. + */ + public static String normalizeDouble(String value) { + return normalizeFPNumber(value, "-9007199254740991.0", "9007199254740991.0", "-1075", "970"); + } + + /** + * Normalizes a floating point number to its canonical representation. + * + * @param value + * The value to normalize. + * @return The canonical representation of value. + * @throws IllegalArgumentException + * If the supplied value is not a legal floating point number. + */ + public static String normalizeFPNumber(String value) { + return normalizeFPNumber(value, null, null, null, null); + } + + /** + * Normalizes a floating point lexical value to its canonical representation. + * + * @param value + * The lexical value to normalize. + * @param minMantissa + * A normalized decimal indicating the lowest value that the mantissa + * may have. + * @param maxMantissa + * A normalized decimal indicating the highest value that the mantissa + * may have. + * @param minExponent + * A normalized integer indicating the lowest value that the exponent + * may have. + * @param maxExponent + * A normalized integer indicating the highest value that the exponent + * may have. + * @return The canonical representation of value. + * @throws IllegalArgumentException + * If the supplied value is not a legal floating point lexical value. + */ + private static String normalizeFPNumber(String value, String minMantissa, String maxMantissa, + String minExponent, String maxExponent) + { + value = collapseWhiteSpace(value); + + if (value.contains(" ")) { + // floating point lexical value can not contain spaces after collapse + throwIAE("No space allowed in floating point lexical value (" + value + ")"); + } + + // handle special values + if (value.equals("INF") || value.equals("-INF") || value.equals("NaN")) { + return value; + } + + // Search for the exponent character E or e + int eIdx = value.indexOf('E'); + if (eIdx == -1) { + // try lower case + eIdx = value.indexOf('e'); + } + + // Extract mantissa and exponent + String mantissa, exponent; + if (eIdx == -1) { + mantissa = normalizeDecimal(value); + exponent = "0"; + } + else { + mantissa = normalizeDecimal(value.substring(0, eIdx)); + exponent = normalizeInteger(value.substring(eIdx + 1)); + } + + // Normalize mantissa to one non-zero digit before the dot + int shift = 0; + + int dotIdx = mantissa.indexOf('.'); + int digitCount = dotIdx; + if (mantissa.charAt(0) == '-') { + digitCount--; + } + + if (digitCount > 1) { + // more than one digit before the dot, e.g 123.45, -10.0 or 100.0 + StringBuilder sb = new StringBuilder(mantissa.length()); + int firstDigitIdx = 0; + if (mantissa.charAt(0) == '-') { + sb.append('-'); + firstDigitIdx = 1; + } + sb.append(mantissa.charAt(firstDigitIdx)); + sb.append('.'); + sb.append(mantissa.substring(firstDigitIdx + 1, dotIdx)); + sb.append(mantissa.substring(dotIdx + 1)); + + mantissa = sb.toString(); + + // Check if the mantissa has excessive trailing zeros. + // For example, 100.0 will be normalize to 1.000 and + // -10.0 to -1.00. + int nonZeroIdx = mantissa.length() - 1; + while (nonZeroIdx >= 3 && mantissa.charAt(nonZeroIdx) == '0') { + nonZeroIdx--; + } + + if (nonZeroIdx < 3 && mantissa.charAt(0) == '-') { + nonZeroIdx++; + } + + if (nonZeroIdx < mantissa.length() - 1) { + mantissa = mantissa.substring(0, nonZeroIdx + 1); + } + + shift = 1 - digitCount; + } + else if (mantissa.startsWith("0.") || mantissa.startsWith("-0.")) { + // Example mantissas: 0.0, -0.1, 0.00345 and 0.09 + // search first non-zero digit + int nonZeroIdx = 2; + while (nonZeroIdx < mantissa.length() && mantissa.charAt(nonZeroIdx) == '0') { + nonZeroIdx++; + } + + // 0.0 does not need any normalization: + if (nonZeroIdx < mantissa.length()) { + StringBuilder sb = new StringBuilder(mantissa.length()); + sb.append(mantissa.charAt(nonZeroIdx)); + sb.append('.'); + if (nonZeroIdx == mantissa.length() - 1) { + // There was only one non-zero digit, e.g. as in 0.09 + sb.append('0'); + } + else { + sb.append(mantissa.substring(nonZeroIdx + 1)); + } + + mantissa = sb.toString(); + shift = nonZeroIdx - 1; + } + } + + if (shift != 0) { + try { + int exp = Integer.parseInt(exponent); + exponent = String.valueOf(exp - shift); + } + catch (NumberFormatException e) { + throw new RuntimeException("NumberFormatException: " + e.getMessage()); + } + } + + // Check lower and upper bounds of canonicalized representation, if + // applicable + if (minMantissa != null) { + if (compareCanonicalDecimals(mantissa, minMantissa) < 0) { + throwIAE("Mantissa smaller than minimum value (" + minMantissa + ")"); + } + } + if (maxMantissa != null) { + if (compareCanonicalDecimals(mantissa, maxMantissa) > 0) { + throwIAE("Mantissa larger than maximum value (" + maxMantissa + ")"); + } + } + if (minExponent != null) { + if (compareCanonicalIntegers(exponent, minExponent) < 0) { + throwIAE("Exponent smaller than minimum value (" + minExponent + ")"); + } + } + if (maxExponent != null) { + if (compareCanonicalIntegers(exponent, maxExponent) > 0) { + throwIAE("Exponent larger than maximum value (" + maxExponent + ")"); + } + } + + return mantissa + "E" + exponent; + } + + /** + * Normalizes an xsd:dateTime. + * + * @param value + * The value to normalize. + * @return The normalized value. + * @throws IllegalArgumentException + * If the supplied value is not a legal xsd:dateTime value. + */ + public static String normalizeDateTime(String value) { + XMLDateTime dt = new XMLDateTime(value); + dt.normalize(); + return dt.toString(); + } + + /** + * Replaces all occurences of #x9 (tab), #xA (line feed) and #xD (carriage + * return) with #x20 (space), as specified for whiteSpace facet + * replace. + */ + // private static String replaceWhiteSpace(String s) { + // s = StringUtil.gsub("\t", " ", s); + // s = StringUtil.gsub("\r", " ", s); + // s = StringUtil.gsub("\n", " ", s); + // return s; + // } + + /** + * Replaces all contiguous sequences of #x9 (tab), #xA (line feed) and #xD + * (carriage return) with a single #x20 (space) character, and removes any + * leading and trailing whitespace characters, as specified for whiteSpace + * facet collapse. + */ + public static String collapseWhiteSpace(String s) { + StringBuilder sb = new StringBuilder(s.length()); + + StringTokenizer st = new StringTokenizer(s, "\t\r\n "); + + if (st.hasMoreTokens()) { + sb.append(st.nextToken()); + } + + while (st.hasMoreTokens()) { + sb.append(' ').append(st.nextToken()); + } + + return sb.toString(); + } + + /*------------------* + * Value comparison * + *------------------*/ + + public static int compare(String value1, String value2, IRI datatype) { + if (datatype.equals(XMLSchema.DECIMAL)) { + return compareDecimals(value1, value2); + } + else if (datatype.equals(XMLSchema.INTEGER)) { + return compareIntegers(value1, value2); + } + else if (datatype.equals(XMLSchema.NEGATIVE_INTEGER)) { + return compareNegativeIntegers(value1, value2); + } + else if (datatype.equals(XMLSchema.NON_POSITIVE_INTEGER)) { + return compareNonPositiveIntegers(value1, value2); + } + else if (datatype.equals(XMLSchema.NON_NEGATIVE_INTEGER)) { + return compareNonNegativeIntegers(value1, value2); + } + else if (datatype.equals(XMLSchema.POSITIVE_INTEGER)) { + return comparePositiveIntegers(value1, value2); + } + else if (datatype.equals(XMLSchema.LONG)) { + return compareLongs(value1, value2); + } + else if (datatype.equals(XMLSchema.INT)) { + return compareInts(value1, value2); + } + else if (datatype.equals(XMLSchema.SHORT)) { + return compareShorts(value1, value2); + } + else if (datatype.equals(XMLSchema.BYTE)) { + return compareBytes(value1, value2); + } + else if (datatype.equals(XMLSchema.UNSIGNED_LONG)) { + return compareUnsignedLongs(value1, value2); + } + else if (datatype.equals(XMLSchema.UNSIGNED_INT)) { + return compareUnsignedInts(value1, value2); + } + else if (datatype.equals(XMLSchema.UNSIGNED_SHORT)) { + return compareUnsignedShorts(value1, value2); + } + else if (datatype.equals(XMLSchema.UNSIGNED_BYTE)) { + return compareUnsignedBytes(value1, value2); + } + else if (datatype.equals(XMLSchema.FLOAT)) { + return compareFloats(value1, value2); + } + else if (datatype.equals(XMLSchema.DOUBLE)) { + return compareDoubles(value1, value2); + } + else if (datatype.equals(XMLSchema.DATETIME)) { + return compareDateTime(value1, value2); + } + else { + throw new IllegalArgumentException("datatype is not ordered"); + } + } + + /** + * Compares two decimals to eachother. + * + * @return A negative number if dec1 is smaller than dec2, + * 0 if they are equal, or positive (>0) if dec1 + * is larger than dec2. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal decimal. + */ + public static int compareDecimals(String dec1, String dec2) { + dec1 = normalizeDecimal(dec1); + dec2 = normalizeDecimal(dec2); + + return compareCanonicalDecimals(dec1, dec2); + } + + /** + * Compares two canonical decimals to eachother. + * + * @return A negative number if dec1 is smaller than dec2, + * 0 if they are equal, or positive (>0) if dec1 + * is larger than dec2. The result is undefined when one or + * both of the arguments is not a canonical decimal. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal decimal. + */ + public static int compareCanonicalDecimals(String dec1, String dec2) { + if (dec1.equals(dec2)) { + return 0; + } + + // Check signs + if (dec1.charAt(0) == '-' && dec2.charAt(0) != '-') { + // dec1 is negative, dec2 is not + return -1; + } + if (dec2.charAt(0) == '-' && dec1.charAt(0) != '-') { + // dec2 is negative, dec1 is not + return 1; + } + + int dotIdx1 = dec1.indexOf('.'); + int dotIdx2 = dec2.indexOf('.'); + + // The decimal with the most digits before the dot is the largest + int result = dotIdx1 - dotIdx2; + + if (result == 0) { + // equal number of digits before the dot, compare them + for (int i = 0; result == 0 && i < dotIdx1; i++) { + result = dec1.charAt(i) - dec2.charAt(i); + } + + // Continue comparing digits after the dot if necessary + int dec1Length = dec1.length(); + int dec2Length = dec2.length(); + int lastIdx = dec1Length <= dec2Length ? dec1Length : dec2Length; + + for (int i = dotIdx1 + 1; result == 0 && i < lastIdx; i++) { + result = dec1.charAt(i) - dec2.charAt(i); + } + + // Still equal? The decimal with the most digits is the largest + if (result == 0) { + result = dec1Length - dec2Length; + } + } + + if (dec1.charAt(0) == '-') { + // reverse result for negative values + result = -result; + } + + return result; + } + + /** + * Compares two integers to eachother. + * + * @return A negative number if int1 is smaller than int2, + * 0 if they are equal, or positive (>0) if int1 + * is larger than int2. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal integer. + */ + public static int compareIntegers(String int1, String int2) { + int1 = normalizeInteger(int1); + int2 = normalizeInteger(int2); + + return compareCanonicalIntegers(int1, int2); + } + + /** + * Compares two canonical integers to eachother. + * + * @return A negative number if int1 is smaller than int2, + * 0 if they are equal, or positive (>0) if int1 + * is larger than int2. The result is undefined when one or + * both of the arguments is not a canonical integer. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal integer. + */ + public static int compareCanonicalIntegers(String int1, String int2) { + if (int1.equals(int2)) { + return 0; + } + + // Check signs + if (int1.charAt(0) == '-' && int2.charAt(0) != '-') { + // int1 is negative, int2 is not + return -1; + } + if (int2.charAt(0) == '-' && int1.charAt(0) != '-') { + // int2 is negative, int1 is not + return 1; + } + + // The integer with the most digits is the largest + int result = int1.length() - int2.length(); + + if (result == 0) { + // equal number of digits, compare them + for (int i = 0; result == 0 && i < int1.length(); i++) { + result = int1.charAt(i) - int2.charAt(i); + } + } + + if (int1.charAt(0) == '-') { + // reverse result for negative values + result = -result; + } + + return result; + } + + public static int compareNegativeIntegers(String int1, String int2) { + int1 = normalizeNegativeInteger(int1); + int2 = normalizeNegativeInteger(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareNonPositiveIntegers(String int1, String int2) { + int1 = normalizeNonPositiveInteger(int1); + int2 = normalizeNonPositiveInteger(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareNonNegativeIntegers(String int1, String int2) { + int1 = normalizeNonNegativeInteger(int1); + int2 = normalizeNonNegativeInteger(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int comparePositiveIntegers(String int1, String int2) { + int1 = normalizePositiveInteger(int1); + int2 = normalizePositiveInteger(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareLongs(String int1, String int2) { + int1 = normalizeLong(int1); + int2 = normalizeLong(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareInts(String int1, String int2) { + int1 = normalizeInt(int1); + int2 = normalizeInt(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareShorts(String int1, String int2) { + int1 = normalizeShort(int1); + int2 = normalizeShort(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareBytes(String int1, String int2) { + int1 = normalizeByte(int1); + int2 = normalizeByte(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareUnsignedLongs(String int1, String int2) { + int1 = normalizeUnsignedLong(int1); + int2 = normalizeUnsignedLong(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareUnsignedInts(String int1, String int2) { + int1 = normalizeUnsignedInt(int1); + int2 = normalizeUnsignedInt(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareUnsignedShorts(String int1, String int2) { + int1 = normalizeUnsignedShort(int1); + int2 = normalizeUnsignedShort(int2); + + return compareCanonicalIntegers(int1, int2); + } + + public static int compareUnsignedBytes(String int1, String int2) { + int1 = normalizeUnsignedByte(int1); + int2 = normalizeUnsignedByte(int2); + + return compareCanonicalIntegers(int1, int2); + } + + /** + * Compares two floats to eachother. + * + * @return A negative number if float1 is smaller than + * float2, 0 if they are equal, or positive (>0) + * if float1 is larger than float2. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal float or if + * NaN is compared to a float other than NaN. + */ + public static int compareFloats(String float1, String float2) { + float1 = normalizeFloat(float1); + float2 = normalizeFloat(float2); + + return compareCanonicalFloats(float1, float2); + } + + /** + * Compares two canonical floats to eachother. + * + * @return A negative number if float1 is smaller than + * float2, 0 if they are equal, or positive (>0) + * if float1 is larger than float2. The result is + * undefined when one or both of the arguments is not a canonical + * float. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal float or if + * NaN is compared to a float other than NaN. + */ + public static int compareCanonicalFloats(String float1, String float2) { + return compareCanonicalFPNumbers(float1, float2); + } + + /** + * Compares two doubles to eachother. + * + * @return A negative number if double1 is smaller than + * double2, 0 if they are equal, or positive + * (>0) if double1 is larger than double2. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal double or if + * NaN is compared to a double other than NaN. + */ + public static int compareDoubles(String double1, String double2) { + double1 = normalizeDouble(double1); + double2 = normalizeDouble(double2); + + return compareCanonicalDoubles(double1, double2); + } + + /** + * Compares two canonical doubles to eachother. + * + * @return A negative number if double1 is smaller than + * double2, 0 if they are equal, or positive + * (>0) if double1 is larger than double2. The + * result is undefined when one or both of the arguments is not a + * canonical double. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal double or if + * NaN is compared to a double other than NaN. + */ + public static int compareCanonicalDoubles(String double1, String double2) { + return compareCanonicalFPNumbers(double1, double2); + } + + /** + * Compares two floating point numbers to eachother. + * + * @return A negative number if float1 is smaller than + * float2, 0 if they are equal, or positive (>0) + * if float1 is larger than float2. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal floating point + * number or if NaN is compared to a floating point number + * other than NaN. + */ + public static int compareFPNumbers(String fp1, String fp2) { + fp1 = normalizeFPNumber(fp1); + fp2 = normalizeFPNumber(fp2); + + return compareCanonicalFPNumbers(fp1, fp2); + } + + /** + * Compares two canonical floating point numbers to eachother. + * + * @return A negative number if float1 is smaller than + * float2, 0 if they are equal, or positive (>0) + * if float1 is larger than float2. The result is + * undefined when one or both of the arguments is not a canonical + * floating point number. + * @throws IllegalArgumentException + * If one of the supplied strings is not a legal floating point + * number or if NaN is compared to a floating point number + * other than NaN. + */ + public static int compareCanonicalFPNumbers(String float1, String float2) { + // Handle special case NaN + if (float1.equals("NaN") || float2.equals("NaN")) { + if (float1.equals(float2)) { + // NaN is equal to itself + return 0; + } + else { + throwIAE("NaN cannot be compared to other floats"); + } + } + + // Handle special case INF + if (float1.equals("INF")) { + return (float2.equals("INF")) ? 0 : 1; + } + else if (float2.equals("INF")) { + return -1; + } + + // Handle special case -INF + if (float1.equals("-INF")) { + return (float2.equals("-INF")) ? 0 : -1; + } + else if (float2.equals("-INF")) { + return 1; + } + + // Check signs + if (float1.charAt(0) == '-' && float2.charAt(0) != '-') { + // float1 is negative, float2 is not + return -1; + } + if (float2.charAt(0) == '-' && float1.charAt(0) != '-') { + // float2 is negative, float1 is not + return 1; + } + + int eIdx1 = float1.indexOf('E'); + String mantissa1 = float1.substring(0, eIdx1); + String exponent1 = float1.substring(eIdx1 + 1); + + int eIdx2 = float2.indexOf('E'); + String mantissa2 = float2.substring(0, eIdx2); + String exponent2 = float2.substring(eIdx2 + 1); + + // Compare exponents + int result = compareCanonicalIntegers(exponent1, exponent2); + + if (result != 0 && float1.charAt(0) == '-') { + // reverse result for negative values + result = -result; + } + + if (result == 0) { + // Equal exponents, compare mantissas + result = compareCanonicalDecimals(mantissa1, mantissa2); + } + + return result; + } + + /** + * Compares two dateTime objects. Important: The comparison only works + * if both values have, or both values don't have specified a valid value for + * the timezone. + * + * @param value1 + * An xsd:dateTime value. + * @param value2 + * An xsd:dateTime value. + * @return -1 if value1 is before value2 (i.e. if + * the dateTime object represented by value1 is before the dateTime + * object represented by value2), 0 if both are equal and + * 1 if value2 is before value1
    + * . + */ + public static int compareDateTime(String value1, String value2) { + XMLDateTime dateTime1 = new XMLDateTime(value1); + XMLDateTime dateTime2 = new XMLDateTime(value2); + + dateTime1.normalize(); + dateTime2.normalize(); + + return dateTime1.compareTo(dateTime2); + } + + /*---------------* + * Value parsing * + *---------------*/ + + /** + * Parses the supplied xsd:boolean string and returns its value. + * + * @param s + * A string representation of an xsd:boolean value. + * @return The boolean value represented by the supplied string + * argument. + * @throws NumberFormatException + * If the supplied string is not a valid xsd:boolean value. + */ + public static boolean parseBoolean(String s) { + return normalizeBoolean(s).equals("true"); + } + + /** + * Parses the supplied xsd:byte string and returns its value. + * + * @param s + * A string representation of an xsd:byte value. + * @return The byte value represented by the supplied string + * argument. + * @throws NumberFormatException + * If the supplied string is not a valid xsd:byte value. + */ + public static byte parseByte(String s) { + s = trimPlusSign(s); + return Byte.parseByte(s); + } + + /** + * Parses the supplied xsd:short string and returns its value. + * + * @param s + * A string representation of an xsd:short value. + * @return The short value represented by the supplied string + * argument. + * @throws NumberFormatException + * If the supplied string is not a valid xsd:short value. + */ + public static short parseShort(String s) { + s = trimPlusSign(s); + return Short.parseShort(s); + } + + /** + * Parses the supplied xsd:int strings and returns its value. + * + * @param s + * A string representation of an xsd:int value. + * @return The int value represented by the supplied string + * argument. + * @throws NumberFormatException + * If the supplied string is not a valid xsd:int value. + */ + public static int parseInt(String s) { + s = trimPlusSign(s); + return Integer.parseInt(s); + } + + /** + * Parses the supplied xsd:long string and returns its value. + * + * @param s + * A string representation of an xsd:long value. + * @return The long value represented by the supplied string + * argument. + * @throws NumberFormatException + * If the supplied string is not a valid xsd:long value. + */ + public static long parseLong(String s) { + s = trimPlusSign(s); + return Long.parseLong(s); + } + + /** + * Parses the supplied xsd:float string and returns its value. + * + * @param s + * A string representation of an xsd:float value. + * @return The float value represented by the supplied string + * argument. + * @throws NumberFormatException + * If the supplied string is not a valid xsd:float value. + */ + public static float parseFloat(String s) { + s = trimPlusSign(s); + return Float.parseFloat(s); + } + + /** + * Parses the supplied xsd:double string and returns its value. + * + * @param s + * A string representation of an xsd:double value. + * @return The double value represented by the supplied string + * argument. + * @throws NumberFormatException + * If the supplied string is not a valid xsd:double value. + */ + public static double parseDouble(String s) { + s = trimPlusSign(s); + return Double.parseDouble(s); + } + + /** + * Parses the supplied xsd:integer string and returns its value. + * + * @param s + * A string representation of an xsd:integer value. + * @return The integer value represented by the supplied string argument. + * @throws NumberFormatException + * If the supplied string is not a valid xsd:integer value. + */ + public static BigInteger parseInteger(String s) { + s = trimPlusSign(s); + return new BigInteger(s); + } + + /** + * Parses the supplied decimal/floating point string and returns its value. + * + * @param s + * A string representation of an xsd:decimal or xsd:double value. + * @return The decimal/floating point value represented by the supplied + * string argument. + * @throws NumberFormatException + * If the supplied string is not a valid xsd:decimal or xsd:double + * value. + */ + public static BigDecimal parseDecimal(String s) { + // Note: BigDecimal can handle leading plus signs itself + return new BigDecimal(s); + } + + /** + * Parses the supplied calendar value string and returns its value. + * + * @param s + * A string representation of an xsd:dateTime, xsd:time, xsd:date, + * xsd:gYearMonth, xsd:gMonthDay, xsd:gYear, xsd:gMonth or xsd:gDay + * value. + * @return The calendar value represented by the supplied string argument. + * @throws NumberFormatException + * If the supplied string is not a valid calendar value. + */ + public static XMLGregorianCalendar parseCalendar(String s) { + return dtFactory.newXMLGregorianCalendar(s); + } + + /** + * Removes the first character from the supplied string if this is a plus + * sign ('+'). Number strings with leading plus signs cannot be parsed by + * methods such as {@link Integer#parseInt(String)}. + */ + private static String trimPlusSign(String s) { + if (s.length() > 0 && s.charAt(0) == '+') { + return s.substring(1); + } + else { + return s; + } + } + + /** + * Maps a datatype QName from the javax.xml.namespace package to an XML + * Schema URI for the corresponding datatype. This method recognizes the XML + * Schema qname mentioned in {@link DatatypeConstants}. + * + * @param qname + * One of the XML Schema qnames from {@link DatatypeConstants}. + * @return A URI for the specified datatype. + * @throws IllegalArgumentException + * If the supplied qname was not recognized by this method. + * @see DatatypeConstants + */ + public static IRI qnameToURI(QName qname) { + if (DatatypeConstants.DATETIME.equals(qname)) { + return XMLSchema.DATETIME; + } + else if (DatatypeConstants.DATE.equals(qname)) { + return XMLSchema.DATE; + } + else if (DatatypeConstants.TIME.equals(qname)) { + return XMLSchema.TIME; + } + else if (DatatypeConstants.GYEARMONTH.equals(qname)) { + return XMLSchema.GYEARMONTH; + } + else if (DatatypeConstants.GMONTHDAY.equals(qname)) { + return XMLSchema.GMONTHDAY; + } + else if (DatatypeConstants.GYEAR.equals(qname)) { + return XMLSchema.GYEAR; + } + else if (DatatypeConstants.GMONTH.equals(qname)) { + return XMLSchema.GMONTH; + } + else if (DatatypeConstants.GDAY.equals(qname)) { + return XMLSchema.GDAY; + } + else if (DatatypeConstants.DURATION.equals(qname)) { + return XMLSchema.DURATION; + } + else { + throw new IllegalArgumentException("QName cannot be mapped to an XML Schema URI: " + + qname.toString()); + } + } + + /*-----------------* + * Utility methods * + *-----------------*/ + + /** + * Checks whether the supplied character is a digit. + */ + private static final boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + + /** + * Throws an IllegalArgumentException that contains the supplied message. + */ + private static final void throwIAE(String msg) { + throw new IllegalArgumentException(msg); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDateTime.java b/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDateTime.java new file mode 100644 index 00000000000..36f3c64d039 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDateTime.java @@ -0,0 +1,539 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.datatypes; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.NoSuchElementException; +import java.util.StringTokenizer; + +/** + * This class provides utility functions for comparisons operating on + * xml:dateTime datatypes as specified in + * W3C XML Schema + * Definition Language (XSD) 1.1 Part 2: Datatypes. + *

    + * Known deviations from the standard: - the range of years in this + * implementation is limited to Integer.MIN_VALUE to Integer.MAX_VALUE for + * practical reasons. + * + * @author Arjohn Kampman + * @author Jeen Broekstra + * @see W3C XML Schema Definition + * Language (XSD) 1.1 Part 2: Datatypes + */ +public class XMLDateTime implements Cloneable, Comparable { + + /*-----------* + * Variables * + *-----------*/ + + /** The raw dateTime string that was used to initialize this object. */ + private String dateTimeString; + + /** Flag indicating whether the year is positive or negative. */ + private boolean isNegativeYear; + + /** year part of the dateTime object as String */ + private String year; + + /** month part of the dateTime object as String */ + private String months; + + /** day part of the dateTime object as String */ + private String days; + + /** hour part of the dateTime object as String */ + private String hours; + + /** minutes part of the dateTime object as String */ + private String minutes; + + /** seconds part of the dateTime object as String */ + private String seconds; + + /** fractional seconds part of the dateTime object as String */ + private String fractionalSeconds; + + /** Flag indicating whether the timezone, if any, is positive or negative. */ + private boolean isNegativeTimezone; + + /** hours part of the optional timezone as String */ + private String hoursTimezone; + + /** minutes part of the optional timezone as String */ + private String minutesTimezone; + + /** year part of the dateTime object as int */ + private int iYear; + + /** month part of the dateTime object as int */ + private int iMonths; + + /** day part of the dateTime object as int */ + private int iDays; + + /** hour part of the dateTime object as int */ + private int iHours; + + /** minute part of the dateTime object as int */ + private int iMinutes; + + /** second part of the dateTime object as int */ + private int iSeconds; + + /** fractional seconds part of the dateTime object as int */ + private double iFractionalSeconds; + + /** hours part of the optional timezone as int */ + private int iHoursTimezone; + + /** minutes part of the optional timezone as int */ + private int iMinutesTimezone; + + /** Flag indicating whether the values have been normalized. */ + private boolean isNormalized = false; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new XMLDateTime object for the supplied xsd:dateTime string value. + * + * @param dateTimeString + * An xsd:dateTime lexical value, for example + * 1999-05-31T13:20:00-05:00. + * @throws IllegalArgumentException + * if the supplied lexical value does not constitute a valid + * xsd:dateTime. + */ + public XMLDateTime(String dateTimeString) { + this.dateTimeString = XMLDatatypeUtil.collapseWhiteSpace(dateTimeString); + parseDateTimeString(); + setNumericFields(); + validateFieldValues(); + } + + /*---------* + * Methods * + *---------*/ + + private void parseDateTimeString() { + if (dateTimeString.length() < 19) { + throw new IllegalArgumentException( + "String value too short to be a valid xsd:dateTime value: " + dateTimeString); + } + + String errMsg = "Invalid xsd:dateTime value: " + dateTimeString; + + StringTokenizer st = new StringTokenizer(dateTimeString, "+-:.TZ", true); + try { + year = st.nextToken(); + isNegativeYear = year.equals("-"); + if (isNegativeYear) { + year = st.nextToken(); + } + verifyTokenValue(st.nextToken(), "-", errMsg); + months = st.nextToken(); + verifyTokenValue(st.nextToken(), "-", errMsg); + days = st.nextToken(); + verifyTokenValue(st.nextToken(), "T", errMsg); + hours = st.nextToken(); + verifyTokenValue(st.nextToken(), ":", errMsg); + minutes = st.nextToken(); + verifyTokenValue(st.nextToken(), ":", errMsg); + seconds = st.nextToken(); + + String token = st.hasMoreTokens() ? st.nextToken() : null; + + if (".".equals(token)) { + fractionalSeconds = st.nextToken(); + token = st.hasMoreTokens() ? st.nextToken() : null; + } + + if ("+".equals(token) || "-".equals(token)) { + isNegativeTimezone = "-".equals(token); + hoursTimezone = st.nextToken(); + verifyTokenValue(st.nextToken(), ":", errMsg); + minutesTimezone = st.nextToken(); + } + else if ("Z".equals(token)) { + isNegativeTimezone = false; + hoursTimezone = minutesTimezone = "00"; + } + + if (st.hasMoreTokens()) { + throw new IllegalArgumentException(errMsg); + } + } + catch (NoSuchElementException e) { + throw new IllegalArgumentException(errMsg); + } + } + + private void verifyTokenValue(String token, String expected, String errMsg) { + if (!token.equals(expected)) { + throw new IllegalArgumentException(errMsg); + } + } + + private void setNumericFields() { + try { + // FIXME: the following statement fails when the year is + // outside the range of integers (comment by Arjohn) + iYear = Integer.parseInt(year); + iMonths = Integer.parseInt(months); + iDays = Integer.parseInt(days); + iHours = Integer.parseInt(hours); + iMinutes = Integer.parseInt(minutes); + iSeconds = Integer.parseInt(seconds); + + if (fractionalSeconds != null) { + // FIXME: the following statement fails when the fractional + // seconds are outside the range of doubles (comment by Arjohn) + iFractionalSeconds = Double.parseDouble("0." + fractionalSeconds); + } + if (hoursTimezone != null) { + iHoursTimezone = Integer.parseInt(hoursTimezone); + } + if (minutesTimezone != null) { + iMinutesTimezone = Integer.parseInt(minutesTimezone); + } + } + catch (NumberFormatException e) { + throw new IllegalArgumentException("All fields must be numbers: " + dateTimeString); + } + } + + private void validateFieldValues() { + if (year.length() < 4) { + throw new IllegalArgumentException("Year field requires at least 4 digits: " + dateTimeString); + } + if (months.length() != 2) { + throw new IllegalArgumentException("Month field must be two digits: " + dateTimeString); + } + if (days.length() != 2) { + throw new IllegalArgumentException("Days field must be two digits: " + dateTimeString); + } + if (hours.length() != 2) { + throw new IllegalArgumentException("Hours field must be two digits: " + dateTimeString); + } + if (minutes.length() != 2) { + throw new IllegalArgumentException("Minutes field must be two digits: " + dateTimeString); + } + if (seconds.length() != 2) { + throw new IllegalArgumentException("Seconds field must be two digits: " + dateTimeString); + } + if (hoursTimezone != null) { + if (hoursTimezone.length() != 2) { + throw new IllegalArgumentException("Timezone-hours field must be two digits: " + dateTimeString); + } + if (minutesTimezone.length() != 2) { + throw new IllegalArgumentException( + "Timezone-minutes field must be two digits: " + dateTimeString); + } + } + + if (year.length() > 4 && year.charAt(0) == '0') { + throw new IllegalArgumentException( + "Leading zeros in years with more than 4 digits are prohibited: " + dateTimeString); + } + if (iYear == 0) { + throw new IllegalArgumentException("0000 is not a valid year: " + dateTimeString); + } + if (iDays < 1 || iDays > 31) { + throw new IllegalArgumentException("invalid day value: " + dateTimeString); + } + if (iMonths < 1 || iMonths > 12) { + throw new IllegalArgumentException("invalid month value: " + dateTimeString); + } + if (iDays == 31 && is30DayMonth(iMonths)) { + throw new IllegalArgumentException("invalid dateTime value: " + dateTimeString); + } + + if (iMonths == 2 && iDays > 28) { + if (iDays == 29) { + if (!isLeapYear(iYear)) { + throw new IllegalArgumentException("invalid dateTime value: " + dateTimeString); + } + } + else { + throw new IllegalArgumentException("invalid dateTime value: " + dateTimeString); + } + + } + + if (iHours > 24) { + throw new IllegalArgumentException("Invalid hour value: " + dateTimeString); + } + if (iMinutes > 59) { + throw new IllegalArgumentException("Invalid minute value: " + dateTimeString); + } + if (iSeconds > 59) { + throw new IllegalArgumentException("Invalid second value: " + dateTimeString); + } + if (iHours == 24 && (iMinutes != 0 || iSeconds != 0)) { + throw new IllegalArgumentException("Invalid time: " + dateTimeString); + } + if (iHoursTimezone > 14 || iMinutesTimezone > 59 || iHoursTimezone == 14 && iMinutesTimezone != 0) { + throw new IllegalArgumentException("Invalid timezone: " + dateTimeString); + } + } + + /** + * Checks if the supplied month is a month with exactly 30 days. + * + * @param month + * the month + * @return {@code true} iff the supplied month has exactly 30 days. + */ + private boolean is30DayMonth(int month) { + return month == 4 || month == 6 || month == 9 || month == 11; + } + + /** + * Checks if the supplied year is a leap year (one in which February 29 + * occurs) according to the definition in + * the XML Schema XSD + * definition + * + * @param year + * the year. + * @return {@code true} if the supplied year is a leap year according to the + * XSD definition. + */ + private boolean isLeapYear(int year) { + return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); + } + + /** + * Checks whether this object has already been normalized. + */ + public boolean isNormalized() { + return isNormalized; + } + + /** + * Normalizes this dateTime object. + */ + public void normalize() { + if (isNormalized) { + // Values already normalized + return; + } + + if (iHours == 24 || hoursTimezone != null && (iHoursTimezone != 0 || iMinutesTimezone != 0)) { + // Normalize the timezone to Coordinated Universal Time (UTC) + + // Insert values into a GregorianCalendar object. + // Note: GregorianCalendar uses 0-based months + Calendar cal = new GregorianCalendar(iYear, iMonths - 1, iDays, iHours, iMinutes, iSeconds); + if (isNegativeYear) { + cal.set(Calendar.ERA, GregorianCalendar.BC); + } + + // Add/subtract the timezone + if (isNegativeTimezone) { + cal.add(Calendar.HOUR_OF_DAY, iHoursTimezone); + cal.add(Calendar.MINUTE, iMinutesTimezone); + } + else { + cal.add(Calendar.HOUR_OF_DAY, -iHoursTimezone); + cal.add(Calendar.MINUTE, -iMinutesTimezone); + } + + // Get the updated fields + if (cal.get(Calendar.ERA) == GregorianCalendar.BC) { + isNegativeYear = true; + } + iYear = cal.get(Calendar.YEAR); + iMonths = cal.get(Calendar.MONTH) + 1; + iDays = cal.get(Calendar.DAY_OF_MONTH); + iHours = cal.get(Calendar.HOUR_OF_DAY); + iMinutes = cal.get(Calendar.MINUTE); + iSeconds = cal.get(Calendar.SECOND); + + year = int2string(iYear, 4); + months = int2string(iMonths, 2); + days = int2string(iDays, 2); + hours = int2string(iHours, 2); + minutes = int2string(iMinutes, 2); + seconds = int2string(iSeconds, 2); + + if (hoursTimezone != null) { + iHoursTimezone = iMinutesTimezone = 0; + hoursTimezone = minutesTimezone = "00"; + isNegativeTimezone = false; + } + } + + if (fractionalSeconds != null) { + // Remove any trailing zeros + int zeroCount = 0; + for (int i = fractionalSeconds.length() - 1; i >= 0; i--) { + if (fractionalSeconds.charAt(i) == '0') { + zeroCount++; + } + else { + break; + } + } + + if (zeroCount == fractionalSeconds.length()) { + fractionalSeconds = null; + } + else if (zeroCount > 0) { + fractionalSeconds = fractionalSeconds.substring(0, fractionalSeconds.length() - zeroCount); + } + } + + isNormalized = true; + } + + /** + * Converts an integer to a string, enforcing the resulting string to have at + * least minDigits digits by prepending zeros if it has less than + * that amount of digits. + */ + private String int2string(int iValue, int minDigits) { + String result = String.valueOf(iValue); + + int zeroCount = minDigits - result.length(); + if (zeroCount > 0) { + StringBuilder sb = new StringBuilder(minDigits); + for (int i = 0; i < zeroCount; i++) { + sb.append('0'); + } + sb.append(result); + + result = sb.toString(); + } + + return result; + } + + /** + * Returns the xsd:dateTime string-representation of this object. + * + * @return An xsd:dateTime value, e.g. 1999-05-31T13:20:00-05:00. + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(32); + + if (isNegativeYear) { + sb.append('-'); + } + sb.append(year); + sb.append('-'); + sb.append(months); + sb.append('-'); + sb.append(days); + sb.append('T'); + sb.append(hours); + sb.append(':'); + sb.append(minutes); + sb.append(':'); + sb.append(seconds); + + if (fractionalSeconds != null) { + sb.append('.'); + sb.append(fractionalSeconds); + } + + if (hoursTimezone != null) { + if (iHoursTimezone == 0 && iMinutesTimezone == 0) { + sb.append("Z"); + } + else { + if (isNegativeTimezone) { + sb.append('-'); + } + else { + sb.append('+'); + } + sb.append(hoursTimezone); + sb.append(':'); + sb.append(minutesTimezone); + } + } + + return sb.toString(); + } + + /** + * Compares this DateTime object to another DateTime object. + * + * @throws ClassCastException + * If other is not a DateTime object. + */ + public int compareTo(XMLDateTime otherDT) { + XMLDateTime thisDT = this; + + if (thisDT.hoursTimezone != null && (thisDT.iHoursTimezone != 0 || thisDT.iMinutesTimezone != 0)) { + // Create a normalized copy of this DateTime object + thisDT = (XMLDateTime)thisDT.clone(); + thisDT.normalize(); + } + + if (otherDT.hoursTimezone != null && (otherDT.iHoursTimezone != 0 || otherDT.iMinutesTimezone != 0)) { + // Create a normalized copy of this DateTime object + otherDT = (XMLDateTime)otherDT.clone(); + otherDT.normalize(); + } + + if (thisDT.isNegativeYear && !otherDT.isNegativeYear) { + return -1; + } + else if (!thisDT.isNegativeYear && otherDT.isNegativeYear) { + return 1; + } + + int result = 0; + if (thisDT.iYear != otherDT.iYear) { + result = thisDT.iYear - otherDT.iYear; + } + else if (thisDT.iMonths != otherDT.iMonths) { + result = thisDT.iMonths - otherDT.iMonths; + } + else if (thisDT.iDays != otherDT.iDays) { + result = thisDT.iDays - otherDT.iDays; + } + else if (thisDT.iHours != otherDT.iHours) { + result = thisDT.iHours - otherDT.iHours; + } + else if (thisDT.iMinutes != otherDT.iMinutes) { + result = thisDT.iMinutes - otherDT.iMinutes; + } + else if (thisDT.iSeconds != otherDT.iSeconds) { + result = thisDT.iSeconds - otherDT.iSeconds; + } + else if (thisDT.iFractionalSeconds != otherDT.iFractionalSeconds) { + result = (thisDT.iFractionalSeconds < otherDT.iFractionalSeconds) ? -1 : 1; + } + + if (thisDT.isNegativeYear) { + // Invert result for negative years + result = -result; + } + + return result; + } + + // Overrides Object.clone(); + @Override + public Object clone() { + try { + return super.clone(); + } + catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/AbstractModel.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/AbstractModel.java new file mode 100644 index 00000000000..0ec20f3aee7 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/AbstractModel.java @@ -0,0 +1,611 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.util.Models; + +/** + * Provides basic operations that are common to all Models. + */ +public abstract class AbstractModel extends AbstractSet implements Model { + + private static final long serialVersionUID = 4254119331281455614L; + + public Model unmodifiable() { + return new UnmodifiableModel(this); + } + + @Override + public boolean add(Statement st) { + return add(st.getSubject(), st.getPredicate(), st.getObject(), st.getContext()); + } + + @Override + public boolean isEmpty() { + return !contains(null, null, null); + } + + @Override + public boolean containsAll(Collection c) { + Iterator e = c.iterator(); + try { + while (e.hasNext()) + if (!contains(e.next())) + return false; + return true; + } + finally { + closeIterator(c, e); + } + } + + @Override + public boolean removeAll(Collection c) { + boolean modified = false; + if (size() > c.size()) { + Iterator i = c.iterator(); + try { + while (i.hasNext()) + modified |= remove(i.next()); + } + finally { + closeIterator(c, i); + } + } + else { + Iterator i = iterator(); + try { + while (i.hasNext()) { + if (c.contains(i.next())) { + i.remove(); + modified = true; + } + } + } + finally { + closeIterator(i); + } + } + return modified; + } + + @Override + public Object[] toArray() { + // Estimate size of array; be prepared to see more or fewer elements + Iterator it = iterator(); + try { + List r = new ArrayList(size()); + while (it.hasNext()) { + r.add(it.next()); + } + return r.toArray(); + } + finally { + closeIterator(it); + } + } + + @Override + public T[] toArray(T[] a) { + // Estimate size of array; be prepared to see more or fewer elements + Iterator it = iterator(); + try { + List r = new ArrayList(size()); + while (it.hasNext()) { + r.add(it.next()); + } + return r.toArray(a); + } + finally { + closeIterator(it); + } + } + + @Override + public boolean addAll(Collection c) { + Iterator e = c.iterator(); + try { + boolean modified = false; + while (e.hasNext()) { + if (add(e.next())) + modified = true; + } + return modified; + } + finally { + closeIterator(c, e); + } + } + + @Override + public boolean retainAll(Collection c) { + Iterator e = iterator(); + try { + boolean modified = false; + while (e.hasNext()) { + if (!c.contains(e.next())) { + e.remove(); + modified = true; + } + } + return modified; + } + finally { + closeIterator(e); + } + } + + @Override + public void clear() { + remove(null, null, null); + } + + @Override + public boolean clear(Resource... contexts) { + return remove(null, null, null, contexts); + } + + @Override + public boolean remove(Object o) { + if (o instanceof Statement) { + Statement st = (Statement)o; + return remove(st.getSubject(), st.getPredicate(), st.getObject(), st.getContext()); + } + return false; + } + + @Override + public boolean contains(Object o) { + if (o instanceof Statement) { + Statement st = (Statement)o; + return contains(st.getSubject(), st.getPredicate(), st.getObject(), st.getContext()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o instanceof Model) { + Model model = (Model)o; + return Models.isomorphic(this, model); + } + return false; + } + + @Override + public Set subjects() { + return new ValueSet() { + + @Override + public boolean contains(Object o) { + if (o instanceof Resource) { + return AbstractModel.this.contains((Resource)o, null, null); + } + return false; + } + + @Override + public boolean remove(Object o) { + if (o instanceof Resource) { + return AbstractModel.this.remove((Resource)o, null, null); + } + return false; + } + + @Override + public boolean add(Resource subj) { + return AbstractModel.this.add(subj, null, null); + } + + @Override + protected Resource term(Statement st) { + return st.getSubject(); + } + + @Override + protected void removeIteration(Iterator iter, Resource subj) { + AbstractModel.this.removeTermIteration(iter, subj, null, null); + } + }; + } + + @Override + public Set predicates() { + return new ValueSet() { + + @Override + public boolean contains(Object o) { + if (o instanceof IRI) { + return AbstractModel.this.contains(null, (IRI)o, null); + } + return false; + } + + @Override + public boolean remove(Object o) { + if (o instanceof IRI) { + return AbstractModel.this.remove(null, (IRI)o, null); + } + return false; + } + + @Override + public boolean add(IRI pred) { + return AbstractModel.this.add(null, pred, null); + } + + @Override + protected IRI term(Statement st) { + return st.getPredicate(); + } + + @Override + protected void removeIteration(Iterator iter, IRI pred) { + AbstractModel.this.removeTermIteration(iter, null, pred, null); + } + }; + } + + @Override + public Set objects() { + return new ValueSet() { + + @Override + public boolean contains(Object o) { + if (o instanceof Value) { + return AbstractModel.this.contains(null, null, (Value)o); + } + return false; + } + + @Override + public boolean remove(Object o) { + if (o instanceof Value) { + return AbstractModel.this.remove(null, null, (Value)o); + } + return false; + } + + @Override + public boolean add(Value obj) { + return AbstractModel.this.add(null, null, obj); + } + + @Override + protected Value term(Statement st) { + return st.getObject(); + } + + @Override + protected void removeIteration(Iterator iter, Value obj) { + AbstractModel.this.removeTermIteration(iter, null, null, obj); + } + }; + } + + @Override + public Set contexts() { + return new ValueSet() { + + @Override + public boolean contains(Object o) { + if (o instanceof Resource || o == null) { + return AbstractModel.this.contains(null, null, null, (Resource)o); + } + return false; + } + + @Override + public boolean remove(Object o) { + if (o instanceof Resource || o == null) { + return AbstractModel.this.remove(null, null, null, (Resource)o); + } + return false; + } + + @Override + public boolean add(Resource context) { + return AbstractModel.this.add(null, null, null, context); + } + + @Override + protected Resource term(Statement st) { + return st.getContext(); + } + + @Override + protected void removeIteration(Iterator iter, Resource term) { + AbstractModel.this.removeTermIteration(iter, null, null, null, term); + } + }; + } + + private abstract class ValueSet extends AbstractSet { + + private final class ValueSetIterator implements Iterator { + + private final Iterator iter; + + private final Set set = new LinkedHashSet(); + + private Statement current; + + private Statement next; + + private ValueSetIterator(Iterator iter) { + this.iter = iter; + } + + @Override + public boolean hasNext() { + if (next == null) { + next = findNext(); + } + return next != null; + } + + @Override + public V next() { + if (next == null) { + next = findNext(); + if (next == null) { + throw new NoSuchElementException(); + } + } + current = next; + next = null; + V value = term(current); + set.add(value); + return value; + } + + @Override + public void remove() { + if (current == null) { + throw new IllegalStateException(); + } + removeIteration(iter, term(current)); + current = null; + } + + private Statement findNext() { + while (iter.hasNext()) { + Statement st = iter.next(); + if (accept(st)) { + return st; + } + } + return null; + } + + private boolean accept(Statement st) { + return !set.contains(term(st)); + } + } + + @Override + public Iterator iterator() { + return new ValueSetIterator(AbstractModel.this.iterator()); + } + + @Override + public void clear() { + AbstractModel.this.clear(); + } + + @Override + public boolean isEmpty() { + return AbstractModel.this.isEmpty(); + } + + @Override + public int size() { + Iterator iter = AbstractModel.this.iterator(); + try { + Set set = new LinkedHashSet(); + while (iter.hasNext()) { + set.add(term(iter.next())); + } + return set.size(); + } + finally { + AbstractModel.this.closeIterator(iter); + } + } + + @Override + public boolean removeAll(Collection c) { + boolean modified = false; + Iterator i = c.iterator(); + try { + while (i.hasNext()) + modified |= remove(i.next()); + } + finally { + closeIterator(c, i); + } + return modified; + } + + @Override + public Object[] toArray() { + Iterator iter = AbstractModel.this.iterator(); + try { + Set set = new LinkedHashSet(); + while (iter.hasNext()) { + set.add(term(iter.next())); + } + return set.toArray(); + } + finally { + AbstractModel.this.closeIterator(iter); + } + } + + @Override + public T[] toArray(T[] a) { + Iterator iter = AbstractModel.this.iterator(); + try { + Set set = new LinkedHashSet(); + while (iter.hasNext()) { + set.add(term(iter.next())); + } + return set.toArray(a); + } + finally { + AbstractModel.this.closeIterator(iter); + } + } + + @Override + public boolean containsAll(Collection c) { + Iterator e = c.iterator(); + try { + while (e.hasNext()) + if (!contains(e.next())) + return false; + return true; + } + finally { + closeIterator(c, e); + } + } + + @Override + public boolean addAll(Collection c) { + Iterator e = c.iterator(); + try { + boolean modified = false; + while (e.hasNext()) { + if (add(e.next())) + modified = true; + } + return modified; + } + finally { + closeIterator(c, e); + } + } + + @Override + public boolean retainAll(Collection c) { + Iterator e = iterator(); + try { + boolean modified = false; + while (e.hasNext()) { + if (!c.contains(e.next())) { + e.remove(); + modified = true; + } + } + return modified; + } + finally { + closeIterator(e); + } + } + + @Override + public abstract boolean add(V term); + + protected abstract V term(Statement st); + + protected abstract void removeIteration(Iterator iter, V term); + + protected void closeIterator(Iterator iter) { + AbstractModel.this.closeIterator(((ValueSetIterator)iter).iter); + } + + private void closeIterator(Collection c, Iterator e) { + if (c instanceof AbstractModel) { + ((AbstractModel)c).closeIterator(e); + } + else if (c instanceof ValueSet) { + ((ValueSet)c).closeIterator(e); + } + } + } + + /** + * Called by aggregate sets when a term has been removed from a term + * iterator. Exactly one of the last four terms will be non-empty. + * + * @param iter + * The iterator used to navigate the live set (never null) + * @param subj + * the subject term to be removed or null + * @param pred + * the predicate term to be removed or null + * @param obj + * the object term to be removed or null + * @param contexts + * an array of one context term to be removed or an empty array + */ + public abstract void removeTermIteration(Iterator iter, Resource subj, IRI pred, Value obj, + Resource... contexts); + + /** + * Cleans up any resources used by this iterator. After this call the given + * iterator should not be used. + * + * @param iter + * Iterator to clean up + */ + protected void closeIterator(Iterator iter) { + if (iter instanceof ValueSet.ValueSetIterator) { + closeIterator(((ValueSet.ValueSetIterator)iter).iter); + } + } + + private void closeIterator(Collection c, Iterator e) { + if (c instanceof AbstractModel) { + ((AbstractModel)c).closeIterator(e); + } + else if (c instanceof ValueSet) { + ((ValueSet)c).closeIterator(e); + } + } + + /* Graph methods */ + + @Deprecated + @Override + public Iterator match(Resource subj, IRI pred, Value obj, Resource... contexts) { + return this.filter(subj, pred, obj, contexts).iterator(); + } + + @Deprecated + @Override + public ValueFactory getValueFactory() { + return SimpleValueFactory.getInstance(); + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/AbstractValueFactory.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/AbstractValueFactory.java new file mode 100644 index 00000000000..b687c273017 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/AbstractValueFactory.java @@ -0,0 +1,279 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; +import java.util.GregorianCalendar; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; + +/** + * Abstract base class for {@link ValueFactory} implementations. It implements + * all basic {@link Value} creation methods by using the default implementations + * ({@link SimpleBNode}, {@link SimpleIRI}, etc), and type-optimized subclasses + * (e.g. {@link BooleanLiteral}, {@link NumericLiteral}) where possible. + * + * @author Arjohn Kampman + * @author Jeen Broekstra + */ +public abstract class AbstractValueFactory implements ValueFactory { + + /** + * "universal" ID for bnode prefixes to prevent blank node clashes (unique + * per classloaded instance of this class) + */ + private static long lastBNodePrefixUID = 0; + + private static synchronized long getNextBNodePrefixUid() { + return lastBNodePrefixUID = Math.max(System.currentTimeMillis(), lastBNodePrefixUID + 1); + } + + private static final DatatypeFactory datatypeFactory; + + static { + try { + datatypeFactory = DatatypeFactory.newInstance(); + } + catch (DatatypeConfigurationException e) { + throw new Error("Could not instantiate javax.xml.datatype.DatatypeFactory", e); + } + } + + /*-----------* + * Variables * + *-----------*/ + + /** + * The ID for the next bnode that is created. + */ + private int nextBNodeID; + + /** + * The prefix for any new bnode IDs. + */ + private String bnodePrefix; + + /*--------------* + * Constructors * + *--------------*/ + + public AbstractValueFactory() { + initBNodeParams(); + } + + /*---------* + * Methods * + *---------*/ + + @Override + public IRI createIRI(String iri) { + return new SimpleIRI(iri); + } + + @Override + public IRI createIRI(String namespace, String localName) { + return createIRI(namespace + localName); + } + + @Override + public BNode createBNode(String nodeID) { + return new SimpleBNode(nodeID); + } + + @Override + public Literal createLiteral(String value) { + return new SimpleLiteral(value, XMLSchema.STRING); + } + + @Override + public Literal createLiteral(String value, String language) { + return new SimpleLiteral(value, language); + } + + @Override + public Literal createLiteral(boolean b) { + return b ? BooleanLiteral.TRUE : BooleanLiteral.FALSE; + } + + @Override + public Literal createLiteral(String value, IRI datatype) { + return new SimpleLiteral(value, datatype); + } + + @Override + public Statement createStatement(Resource subject, IRI predicate, Value object) { + return new SimpleStatement(subject, predicate, object); + } + + @Override + public Statement createStatement(Resource subject, IRI predicate, Value object, Resource context) { + return new ContextStatement(subject, predicate, object, context); + } + + /** + * Generates a new bnode prefix and resets nextBNodeID to 1 + * . + */ + protected void initBNodeParams() { + // BNode prefix is based on currentTimeMillis(). Combined with a + // sequential number per session, this gives a unique identifier. + bnodePrefix = "node" + Long.toString(getNextBNodePrefixUid(), 32) + "x"; + nextBNodeID = 1; + } + + @Override + public synchronized BNode createBNode() { + int id = nextBNodeID++; + + BNode result = createBNode(bnodePrefix + id); + + if (id == Integer.MAX_VALUE) { + // Start with a new bnode prefix + initBNodeParams(); + } + + return result; + } + + /** + * Calls {@link #createIntegerLiteral(Number, IRI)} with the supplied value + * and {@link XMLSchema#BYTE} as parameters. + */ + @Override + public Literal createLiteral(byte value) { + return createIntegerLiteral(value, XMLSchema.BYTE); + } + + /** + * Calls {@link #createIntegerLiteral(Number, IRI)} with the supplied value + * and {@link XMLSchema#SHORT} as parameters. + */ + @Override + public Literal createLiteral(short value) { + return createIntegerLiteral(value, XMLSchema.SHORT); + } + + /** + * Calls {@link #createIntegerLiteral(Number, IRI)} with the supplied value + * and {@link XMLSchema#INT} as parameters. + */ + @Override + public Literal createLiteral(int value) { + return createIntegerLiteral(value, XMLSchema.INT); + } + + /** + * Calls {@link #createIntegerLiteral(Number, IRI)} with the supplied value + * and {@link XMLSchema#LONG} as parameters. + */ + @Override + public Literal createLiteral(long value) { + return createIntegerLiteral(value, XMLSchema.LONG); + } + + /** + * Calls {@link #createNumericLiteral(Number, IRI)} with the supplied value + * and datatype as parameters. + */ + protected Literal createIntegerLiteral(Number value, IRI datatype) { + return createNumericLiteral(value, datatype); + } + + /** + * Calls {@link #createFPLiteral(Number, IRI)} with the supplied value and + * {@link XMLSchema#FLOAT} as parameters. + */ + @Override + public Literal createLiteral(float value) { + return createFPLiteral(value, XMLSchema.FLOAT); + } + + /** + * Calls {@link #createFPLiteral(Number, IRI)} with the supplied value and + * {@link XMLSchema#DOUBLE} as parameters. + */ + @Override + public Literal createLiteral(double value) { + return createFPLiteral(value, XMLSchema.DOUBLE); + } + + @Override + public Literal createLiteral(BigInteger bigInteger) { + return createIntegerLiteral(bigInteger, XMLSchema.INTEGER); + } + + @Override + public Literal createLiteral(BigDecimal bigDecimal) { + return createNumericLiteral(bigDecimal, XMLSchema.DECIMAL); + } + + /** + * Calls {@link #createNumericLiteral(Number, IRI)} with the supplied value + * and datatype as parameters. + */ + protected Literal createFPLiteral(Number value, IRI datatype) { + return createNumericLiteral(value, datatype); + } + + /** + * Creates specific optimized subtypes of SimpleLiteral for numeric + * datatypes. + */ + protected Literal createNumericLiteral(Number number, IRI datatype) { + if (number instanceof BigDecimal) { + return new DecimalLiteral((BigDecimal)number, datatype); + } + if (number instanceof BigInteger) { + return new IntegerLiteral((BigInteger)number, datatype); + } + return new NumericLiteral(number, datatype); + } + + /** + * Calls {@link ValueFactory#createLiteral(String, IRI)} with the + * String-value of the supplied calendar and the appropriate datatype as + * parameters. + * + * @see XMLGregorianCalendar#toXMLFormat() + * @see XMLGregorianCalendar#getXMLSchemaType() + * @see XMLDatatypeUtil#qnameToURI(javax.xml.namespace.QName) + */ + @Override + public Literal createLiteral(XMLGregorianCalendar calendar) { + return createLiteral(calendar.toXMLFormat(), XMLDatatypeUtil.qnameToURI(calendar.getXMLSchemaType())); + } + + /** + * Converts the supplied {@link Date} to a {@link XMLGregorianCalendar}, then + * calls {@link ValueFactory#createLiteral(XMLGregorianCalendar)}. + * + * @since 2.7.0 + */ + @Override + public Literal createLiteral(Date date) { + GregorianCalendar c = new GregorianCalendar(); + c.setTime(date); + + XMLGregorianCalendar xmlGregCalendar = datatypeFactory.newXMLGregorianCalendar(c); + return createLiteral(xmlGregCalendar); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BNodeImpl.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BNodeImpl.java new file mode 100644 index 00000000000..ff5f733c831 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BNodeImpl.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.ValueFactory; + +/** + * @author Jeen Broekstra + * @deprecated since 4.0. Use {@link SimpleBNode} instead for extending, and + * {@link ValueFactory} for instantiation. + */ +@Deprecated +public class BNodeImpl extends SimpleBNode { + + /** + * @deprecated since 4.0. Use {@link ValueFactory#createBNode()} instead. + */ + @Deprecated + public BNodeImpl() { + super(); + } + + /** + * @deprecated since 4.0. Use {@link ValueFactory#createBNode(String)} + * instead. + */ + @Deprecated + public BNodeImpl(String nodeID) { + super(nodeID); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BooleanLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BooleanLiteral.java new file mode 100644 index 00000000000..425a8363cd7 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BooleanLiteral.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; + +/** + * An extension of {@link SimpleLiteral} that stores a boolean value to avoid + * parsing. + * + * @author David Huynh + * @author Arjohn Kampman + */ +public class BooleanLiteral extends SimpleLiteral { + + /*-----------* + * Constants * + *-----------*/ + + private static final long serialVersionUID = -3610638093719366795L; + + public static final BooleanLiteral TRUE = new BooleanLiteral(true); + + public static final BooleanLiteral FALSE = new BooleanLiteral(false); + + /*-----------* + * Variables * + *-----------*/ + + private boolean value; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates an xsd:boolean typed literal with the specified value. + */ + protected BooleanLiteral(boolean value) { + super(Boolean.toString(value), XMLSchema.BOOLEAN); + this.value = value; + } + + /*---------* + * Methods * + *---------*/ + + @Override + public boolean booleanValue() + { + return value; + } + + /** + * Returns a {@link BooleanLiteral} for the specified value. This method + * uses the constants {@link #TRUE} and {@link #FALSE} as result values, + * preventing the often unnecessary creation of new + * {@link BooleanLiteral} objects. + */ + public static BooleanLiteral valueOf(boolean value) { + return value ? TRUE : FALSE; + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/CalendarLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/CalendarLiteral.java new file mode 100644 index 00000000000..5c02d9abb12 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/CalendarLiteral.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; + +/** + * An extension of {@link SimpleLiteral} that stores a calendar value to avoid + * parsing. + * + * @author David Huynh + * @author Arjohn Kampman + */ +public class CalendarLiteral extends SimpleLiteral { + + private static final long serialVersionUID = -8959671333074894312L; + + private final XMLGregorianCalendar calendar; + + /** + * Creates a literal for the specified calendar using a datatype appropriate + * for the value indicated by {@link XMLGregorianCalendar#getXMLSchemaType()}. + */ + protected CalendarLiteral(XMLGregorianCalendar calendar) { + super(calendar.toXMLFormat(), XMLDatatypeUtil.qnameToURI(calendar.getXMLSchemaType())); + this.calendar = calendar; + } + + @Override + public XMLGregorianCalendar calendarValue() + { + return calendar; + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ContextStatement.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ContextStatement.java new file mode 100644 index 00000000000..50188f59a58 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ContextStatement.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; + +/** + * An extension of {@link SimpleStatement} that adds a context field. + */ +public class ContextStatement extends SimpleStatement { + + /*-----------* + * Constants * + *-----------*/ + + private static final long serialVersionUID = -4747275587477906748L; + + /** + * The statement's context, if applicable. + */ + private final Resource context; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new Statement with the supplied subject, predicate and object + * for the specified associated context. + * + * @param subject + * The statement's subject, must not be null. + * @param predicate + * The statement's predicate, must not be null. + * @param object + * The statement's object, must not be null. + * @param context + * The statement's context, null to indicate no context is + * associated. + */ + protected ContextStatement(Resource subject, IRI predicate, Value object, Resource context) { + super(subject, predicate, object); + this.context = context; + } + + /*---------* + * Methods * + *---------*/ + + @Override + public Resource getContext() + { + return context; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(256); + + sb.append(super.toString()); + sb.append(" [").append(getContext()).append("]"); + + return sb.toString(); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ContextStatementImpl.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ContextStatementImpl.java new file mode 100644 index 00000000000..169eab348a5 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ContextStatementImpl.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; + +/** + * @author Jeen Broekstra + * @deprecated since 4.0. Use {@link ContextStatement} instead for extension, + * and {@link ValueFactory} for instantiation. + */ +@Deprecated +public class ContextStatementImpl extends ContextStatement { + + /** + * @deprecated since 4.0. Use + * {@link ValueFactory#createStatement(Resource, IRI, Value, Resource)} + * instead. + */ + @Deprecated + public ContextStatementImpl(Resource subject, URI predicate, Value object, Resource context) { + super(subject, (IRI)predicate, object, context); + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/DecimalLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/DecimalLiteral.java new file mode 100644 index 00000000000..60d93cc0721 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/DecimalLiteral.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; + +/** + * An extension of {@link SimpleLiteral} that stores an integer value using a + * {@link BigDecimal} object. + * + * @author Arjohn Kampman + */ +public class DecimalLiteral extends SimpleLiteral { + + private static final long serialVersionUID = -3310213093222314380L; + + private final BigDecimal value; + + /** + * Creates an xsd:decimal literal with the specified value. + */ + protected DecimalLiteral(BigDecimal value) { + this(value, XMLSchema.DECIMAL); + } + + /** + * Creates a literal with the specified value and datatype. + */ + protected DecimalLiteral(BigDecimal value, IRI datatype) { + // TODO: maybe DecimalLiteral should not extend SimpleLiteral? + super(value.toPlainString(), datatype); + this.value = value; + } + + @Override + public byte byteValue() + { + return value.byteValue(); + } + + @Override + public short shortValue() + { + return value.shortValue(); + } + + @Override + public int intValue() + { + return value.intValue(); + } + + @Override + public long longValue() + { + return value.longValue(); + } + + @Override + public float floatValue() + { + return value.floatValue(); + } + + @Override + public double doubleValue() + { + return value.doubleValue(); + } + + @Override + public BigInteger integerValue() + { + return value.toBigInteger(); + } + + @Override + public BigDecimal decimalValue() + { + return value; + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/EmptyModel.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/EmptyModel.java new file mode 100644 index 00000000000..6a2c2f14aa9 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/EmptyModel.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.util.Collections; +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; + +/** + * Blocks access to the statements of the model, allowing only changes to the + * model's namespaces. + * + * @author James Leigh + * @since 2.7.0 + */ +public class EmptyModel extends AbstractModel { + + private final Model model; + + public EmptyModel(Model model) { + this.model = model; + } + + private static final long serialVersionUID = 3123007631452759092L; + + private Set emptySet = Collections.emptySet(); + + @Override + public Optional getNamespace(String prefix) { + return this.model.getNamespace(prefix); + } + + @Override + public Set getNamespaces() { + return this.model.getNamespaces(); + } + + @Override + public Namespace setNamespace(String prefix, String name) { + return this.model.setNamespace(prefix, name); + } + + @Override + public void setNamespace(Namespace namespace) { + this.model.setNamespace(namespace); + } + + @Override + public Optional removeNamespace(String prefix) { + return this.model.removeNamespace(prefix); + } + + @Override + public Iterator iterator() { + return emptySet.iterator(); + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean add(Resource subj, IRI pred, Value obj, Resource... contexts) { + throw new UnsupportedOperationException("All statements are filtered out of view"); + } + + @Override + public boolean contains(Resource subj, IRI pred, Value obj, Resource... contexts) { + return false; + } + + @Override + public Model filter(Resource subj, IRI pred, Value obj, Resource... contexts) { + return this; + } + + @Override + public boolean remove(Resource subj, IRI pred, Value obj, Resource... contexts) { + return false; + } + + @Override + public void removeTermIteration(Iterator iter, Resource subj, IRI pred, Value obj, + Resource... contexts) + { + // remove nothing + } + +} \ No newline at end of file diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/FilteredModel.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/FilteredModel.java new file mode 100644 index 00000000000..4512789a944 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/FilteredModel.java @@ -0,0 +1,259 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.rdf4j.OpenRDFUtil; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; + +/** + * Applies a basic graph pattern filter to what triples can be see. + * + * @since 2.7.0 + */ +public abstract class FilteredModel extends AbstractModel { + + private final Model model; + + private static final long serialVersionUID = -2353344619836326934L; + + protected Resource subj; + + protected IRI pred; + + protected Value obj; + + protected Resource[] contexts; + + public FilteredModel(AbstractModel model, Resource subj, IRI pred, Value obj, Resource... contexts) { + OpenRDFUtil.verifyContextNotNull(contexts); + + this.model = model; + this.subj = subj; + this.pred = pred; + this.obj = obj; + this.contexts = contexts; + } + + @Override + public Optional getNamespace(String prefix) { + return model.getNamespace(prefix); + } + + @Override + public Set getNamespaces() { + return model.getNamespaces(); + } + + @Override + public Namespace setNamespace(String prefix, String name) { + return model.setNamespace(prefix, name); + } + + @Override + public void setNamespace(Namespace namespace) { + this.model.setNamespace(namespace); + } + + @Override + public Optional removeNamespace(String prefix) { + return model.removeNamespace(prefix); + } + + @Override + public int size() { + Iterator iter = iterator(); + try { + int size = 0; + while (iter.hasNext()) { + size++; + iter.next(); + } + return size; + } + finally { + closeIterator(iter); + } + } + + @Override + public boolean add(Resource s, IRI p, Value o, Resource... c) { + if (s == null) { + s = subj; + } + if (p == null) { + p = pred; + } + if (o == null) { + o = obj; + } + if (c != null && c.length == 0) { + c = contexts; + } + if (!accept(s, p, o, c)) { + throw new IllegalArgumentException("Statement is filtered out of view"); + } + return model.add(s, p, o, c); + } + + @Override + public boolean remove(Resource s, IRI p, Value o, Resource... c) { + if (s == null) { + s = subj; + } + if (p == null) { + p = pred; + } + if (o == null) { + o = obj; + } + if (c != null && c.length == 0) { + c = contexts; + } + if (!accept(s, p, o, c)) { + return false; + } + return model.remove(s, p, o, c); + } + + @Override + public boolean contains(Resource s, IRI p, Value o, Resource... c) { + if (s == null) { + s = subj; + } + if (p == null) { + p = pred; + } + if (o == null) { + o = obj; + } + if (c != null && c.length == 0) { + c = contexts; + } + if (!accept(s, p, o, c)) { + return false; + } + return model.contains(s, p, o, c); + } + + @Override + public Model filter(Resource s, IRI p, Value o, Resource... c) { + if (s == null) { + s = subj; + } + if (p == null) { + p = pred; + } + if (o == null) { + o = obj; + } + if (c != null && c.length == 0) { + c = contexts; + } + if (!accept(s, p, o, c)) { + return new EmptyModel(model); + } + return model.filter(s, p, o, c); + } + + @Override + public final void removeTermIteration(Iterator iter, Resource s, IRI p, Value o, Resource... c) + { + if (s == null) { + s = subj; + } + if (p == null) { + p = pred; + } + if (o == null) { + o = obj; + } + if (c != null && c.length == 0) { + c = contexts; + } + if (!accept(s, p, o, c)) { + throw new IllegalStateException(); + } + removeFilteredTermIteration(iter, s, p, o, c); + } + + /** + * Called by aggregate sets when a term has been removed from a term + * iterator. At least one of the last four terms will be non-empty. + * + * @param iter + * The iterator used to navigate the live set (never null) + * @param subj + * the subject term to be removed or null + * @param pred + * the predicate term to be removed or null + * @param obj + * the object term to be removed or null + * @param contexts + * an array of one context term to be removed or an empty array + */ + protected abstract void removeFilteredTermIteration(Iterator iter, Resource subj, IRI pred, + Value obj, Resource... contexts); + + private boolean accept(Resource s, IRI p, Value o, Resource... c) { + if (subj != null && !subj.equals(s)) { + return false; + } + if (pred != null && !pred.equals(p)) { + return false; + } + if (obj != null && !obj.equals(o)) { + return false; + } + if (!matches(c, contexts)) { + return false; + } + return (s == null || s instanceof Resource) && (p == null || p instanceof IRI); + } + + private boolean matches(Resource[] stContext, Resource... contexts) { + OpenRDFUtil.verifyContextNotNull(stContext); + if (stContext != null && stContext.length > 0) { + for (Resource c : stContext) { + if (!matches(c, contexts)) { + return false; + } + } + } + return true; + } + + private boolean matches(Resource stContext, Resource... contexts) { + if (contexts != null && contexts.length == 0) { + // Any context matches + return stContext == null || stContext instanceof Resource; + } + else { + OpenRDFUtil.verifyContextNotNull(contexts); + // Accept if one of the contexts from the pattern matches + for (Resource context : contexts) { + if (context == null && stContext == null) { + return true; + } + if (context != null && context.equals(stContext)) { + return true; + } + } + + return false; + } + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/GraphImpl.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/GraphImpl.java new file mode 100644 index 00000000000..386e861c9e2 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/GraphImpl.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; + +import org.eclipse.rdf4j.OpenRDFUtil; +import org.eclipse.rdf4j.model.Graph; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.util.iterators.FilterIterator; + +/** + * Basic implementation of Graph. + * + * @deprecated since release 2.7.0. Use a {@link org.eclipse.rdf4j.model.Model} + * implementation (e.g. {@link TreeModel} or {@link LinkedHashModel} + * instead. + * @author Arjohn Kampman + */ +@Deprecated +public class GraphImpl extends AbstractCollection implements Graph { + + private static final long serialVersionUID = -5307095904382050478L; + + protected LinkedList statements; + + transient protected ValueFactory valueFactory; + + public GraphImpl(ValueFactory valueFactory) { + super(); + statements = new LinkedList(); + setValueFactory(valueFactory); + } + + public GraphImpl() { + this(SimpleValueFactory.getInstance()); + } + + public GraphImpl(ValueFactory valueFactory, Collection statements) { + this(valueFactory); + addAll(statements); + } + + public GraphImpl(Collection statements) { + this(SimpleValueFactory.getInstance(), statements); + } + + public ValueFactory getValueFactory() { + return valueFactory; + } + + public void setValueFactory(ValueFactory valueFactory) { + this.valueFactory = valueFactory; + } + + @Override + public Iterator iterator() { + return statements.iterator(); + } + + @Override + public int size() { + return statements.size(); + } + + @Override + public boolean add(Statement st) { + return statements.add(st); + } + + public boolean add(Resource subj, IRI pred, Value obj, Resource... contexts) { + OpenRDFUtil.verifyContextNotNull(contexts); + + boolean graphChanged = false; + + if (contexts.length == 0) { + graphChanged = add(valueFactory.createStatement(subj, pred, obj)); + } + else { + for (Resource context : contexts) { + graphChanged |= add(valueFactory.createStatement(subj, pred, obj, context)); + } + } + + return graphChanged; + } + + public Iterator match(Resource subj, IRI pred, Value obj, Resource... contexts) { + OpenRDFUtil.verifyContextNotNull(contexts); + return new PatternIterator(iterator(), subj, pred, obj, contexts); + } + + private void writeObject(ObjectOutputStream out) + throws IOException + { + out.defaultWriteObject(); + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException + { + in.defaultReadObject(); + setValueFactory(SimpleValueFactory.getInstance()); + } + + /*-----------------------------* + * Inner class PatternIterator * + *-----------------------------*/ + + private static class PatternIterator extends FilterIterator { + + private Resource subj; + + private IRI pred; + + private Value obj; + + private Resource[] contexts; + + public PatternIterator(Iterator iter, Resource subj, IRI pred, Value obj, + Resource... contexts) + { + super(iter); + this.subj = subj; + this.pred = pred; + this.obj = obj; + this.contexts = contexts; + } + + @Override + protected boolean accept(Statement st) { + if (subj != null && !subj.equals(st.getSubject())) { + return false; + } + if (pred != null && !pred.equals(st.getPredicate())) { + return false; + } + if (obj != null && !obj.equals(st.getObject())) { + return false; + } + + if (contexts.length == 0) { + // Any context matches + return true; + } + else { + // Accept if one of the contexts from the pattern matches + Resource stContext = st.getContext(); + + for (Resource context : contexts) { + if (context == null && stContext == null) { + return true; + } + if (context != null && context.equals(stContext)) { + return true; + } + } + + return false; + } + } + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/IntegerLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/IntegerLiteral.java new file mode 100644 index 00000000000..99961fd4c79 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/IntegerLiteral.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; + +/** + * An extension of {@link SimpleLiteral} that stores an integer value using a + * {@link BigInteger} object. + * + * @author Arjohn Kampman + */ +public class IntegerLiteral extends SimpleLiteral { + + private static final long serialVersionUID = 4199641304079427245L; + + private final BigInteger value; + + /** + * Creates an xsd:integer literal with the specified value. + */ + protected IntegerLiteral(BigInteger value) { + this(value, XMLSchema.INTEGER); + } + + /** + * Creates a literal with the specified value and datatype. + */ + protected IntegerLiteral(BigInteger value, IRI datatype) { + // TODO: maybe IntegerLiteralImpl should not extend LiteralImpl? + super(value.toString(), datatype); + this.value = value; + } + + @Override + public byte byteValue() + { + return value.byteValue(); + } + + @Override + public short shortValue() + { + return value.shortValue(); + } + + @Override + public int intValue() + { + return value.intValue(); + } + + @Override + public long longValue() + { + return value.longValue(); + } + + @Override + public float floatValue() + { + return value.floatValue(); + } + + @Override + public double doubleValue() + { + return value.doubleValue(); + } + + @Override + public BigInteger integerValue() + { + return value; + } + + @Override + public BigDecimal decimalValue() + { + return new BigDecimal(value); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/LinkedHashModel.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/LinkedHashModel.java new file mode 100644 index 00000000000..433e5d34a1c --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/LinkedHashModel.java @@ -0,0 +1,541 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.util.PatternIterator; + +/** + * Hash table based implementation of the {@link Model} interface. + *

    + * This implementation provides constant-time performance for filters using a + * single term, assuming the hash function disperses the elements properly among + * the buckets. Each term is indexed using a {@link HashMap}. When multiple + * terms are provided in a filter the index, of the term that reduces the + * possible {@link Statement}s the most, is used and a sequential scan is used + * to filter additional terms. + *

    + * Note that this implementation is not synchronized. If multiple threads + * access a model concurrently, and at least one of the threads modifies the + * model, it must be synchronized externally. This is typically accomplished by + * synchronizing on some object that naturally encapsulates the model. If no + * such object exists, the set should be "wrapped" using the + * Collections.synchronizedSet method. This is best done at creation time, to + * prevent accidental unsynchronized access to the LinkedHashModel instance + * (though the synchronization guarantee is only when accessing via the Set + * interface methods): + *

    + * + *
    + * Set s = Collections.synchronizedSet(new LinkedHashModel(...));
    + * 
    + * + * @author James Leigh + * @since 2.7.0 + */ +@SuppressWarnings("unchecked") +public class LinkedHashModel extends AbstractModel { + + private static final long serialVersionUID = -9161104123818983614L; + + static final Resource[] NULL_CTX = new Resource[] { null }; + + Set namespaces = new LinkedHashSet(); + + transient Map values; + + transient Set statements; + + public LinkedHashModel() { + this(128); + } + + public LinkedHashModel(Model model) { + this(model.getNamespaces()); + addAll(model); + } + + public LinkedHashModel(Collection c) { + this(c.size()); + addAll(c); + } + + public LinkedHashModel(int size) { + super(); + values = new HashMap(size * 2); + statements = new LinkedHashSet(size); + } + + public LinkedHashModel(Set namespaces, Collection c) { + this(c); + this.namespaces.addAll(namespaces); + } + + public LinkedHashModel(Set namespaces) { + this(); + this.namespaces.addAll(namespaces); + } + + public LinkedHashModel(Set namespaces, int size) { + this(size); + this.namespaces.addAll(namespaces); + } + + @Override + public Optional getNamespace(String prefix) { + for (Namespace nextNamespace : namespaces) { + if (prefix.equals(nextNamespace.getPrefix())) { + return Optional.of(nextNamespace); + } + } + return Optional.empty(); + } + + @Override + public Set getNamespaces() { + return namespaces; + } + + @Override + public Namespace setNamespace(String prefix, String name) { + removeNamespace(prefix); + Namespace result = new SimpleNamespace(prefix, name); + namespaces.add(result); + return result; + } + + @Override + public void setNamespace(Namespace namespace) { + removeNamespace(namespace.getPrefix()); + namespaces.add(namespace); + } + + @Override + public Optional removeNamespace(String prefix) { + Optional result = getNamespace(prefix); + if (result.isPresent()) { + namespaces.remove(result.get()); + } + return result; + } + + @Override + public int size() { + return statements.size(); + } + + @Override + public boolean add(Resource subj, IRI pred, Value obj, Resource... contexts) { + if (subj == null || pred == null || obj == null) + throw new UnsupportedOperationException("Incomplete statement"); + Value[] ctxs = notNull(contexts); + if (ctxs.length == 0) { + ctxs = NULL_CTX; + } + boolean changed = false; + for (Value ctx : ctxs) { + ModelNode s = asNode(subj); + ModelNode p = asNode(pred); + ModelNode o = asNode(obj); + ModelNode c = asNode((Resource)ctx); + ModelStatement st = new ModelStatement(s, p, o, c); + changed |= addModelStatement(st); + } + return changed; + } + + @Override + public void clear() { + values.clear(); + statements.clear(); + } + + @Override + public boolean remove(Object o) { + if (o instanceof Statement) { + Iterator iter = find((Statement)o); + if (iter.hasNext()) { + iter.next(); + iter.remove(); + return true; + } + } + return false; + } + + @Override + public boolean contains(Object o) { + if (o instanceof Statement) { + return find((Statement)o).hasNext(); + } + return false; + } + + @Override + public Iterator iterator() { + return matchPattern(null, null, null); + } + + @Override + public boolean contains(Resource subj, IRI pred, Value obj, Resource... contexts) { + return matchPattern(subj, pred, obj, contexts).hasNext(); + } + + @Override + public boolean remove(Resource subj, IRI pred, Value obj, Resource... contexts) { + Iterator iter = matchPattern(subj, pred, obj, contexts); + if (!iter.hasNext()) { + return false; + } + while (iter.hasNext()) { + iter.next(); + iter.remove(); + } + return true; + } + + @Override + public Model filter(final Resource subj, final IRI pred, final Value obj, final Resource... contexts) { + return new FilteredModel(this, subj, pred, obj, contexts) { + + private static final long serialVersionUID = 396293781006255959L; + + @Override + public Iterator iterator() { + return matchPattern(subj, pred, obj, contexts); + } + + @Override + protected void removeFilteredTermIteration(Iterator iter, Resource subj, IRI pred, + Value obj, Resource... contexts) + { + LinkedHashModel.this.removeTermIteration(iter, subj, pred, obj, contexts); + } + }; + } + + @Override + public void removeTermIteration(Iterator iterator, Resource subj, IRI pred, Value obj, + Resource... contexts) + { + Set owner = ((ModelIterator)iterator).getOwner(); + Set chosen = choose(subj, pred, obj, contexts); + Iterator iter = chosen.iterator(); + iter = new PatternIterator(iter, subj, pred, obj, contexts); + while (iter.hasNext()) { + ModelStatement last = iter.next(); + if (statements == owner) { + statements = new LinkedHashSet(statements); + statements.remove(last); + } + else if (statements != chosen) { + statements.remove(last); + } + if (last.subj.subjects == owner) { + last.subj.subjects = new LinkedHashSet(last.subj.subjects); + last.subj.subjects.remove(last); + } + else if (last.subj.subjects != chosen) { + last.subj.subjects.remove(last); + } + if (last.pred.predicates == owner) { + last.pred.predicates = new LinkedHashSet(statements); + last.pred.predicates.remove(last); + } + else if (last.pred.predicates != chosen) { + last.pred.predicates.remove(last); + } + if (last.obj.objects == owner) { + last.obj.objects = new LinkedHashSet(statements); + last.obj.objects.remove(last); + } + else if (last.obj.objects != chosen) { + last.obj.objects.remove(last); + } + if (last.ctx.contexts == owner) { + last.ctx.contexts = new LinkedHashSet(statements); + last.ctx.contexts.remove(last); + } + else if (last.ctx.contexts != chosen) { + last.ctx.contexts.remove(last); + } + if (owner != chosen) { + iter.remove(); // remove from chosen + } + } + } + + private class ModelIterator implements Iterator { + + private Iterator iter; + + private Set owner; + + private ModelStatement last; + + public ModelIterator(Iterator iter, Set owner) { + this.iter = iter; + this.owner = owner; + } + + public Set getOwner() { + return owner; + } + + @Override + public boolean hasNext() { + return iter.hasNext(); + } + + @Override + public ModelStatement next() { + return last = iter.next(); + } + + @Override + public void remove() { + if (last == null) { + throw new IllegalStateException(); + } + removeFrom(statements); + removeFrom(last.subj.subjects); + removeFrom(last.pred.predicates); + removeFrom(last.obj.objects); + removeFrom(last.ctx.contexts); + iter.remove(); // remove from owner + } + + private void removeFrom(Set subjects) { + if (subjects != owner) { + subjects.remove(last); + } + } + } + + private static class ModelNode implements Serializable { + + private static final long serialVersionUID = -1205676084606998540L; + + Set subjects = new LinkedHashSet(); + + Set predicates = new LinkedHashSet(); + + Set objects = new LinkedHashSet(); + + Set contexts = new LinkedHashSet(); + + private V value; + + public ModelNode(V value) { + this.value = value; + } + + public V getValue() { + return value; + } + } + + private static class ModelStatement extends ContextStatement { + + private static final long serialVersionUID = 2200404772364346279L; + + ModelNode subj; + + ModelNode pred; + + ModelNode obj; + + ModelNode ctx; + + public ModelStatement(ModelNode subj, ModelNode pred, ModelNode obj, + ModelNode ctx) + { + super(subj.getValue(), pred.getValue(), obj.getValue(), ctx.getValue()); + assert subj != null; + assert pred != null; + assert obj != null; + assert ctx != null; + this.subj = subj; + this.pred = pred; + this.obj = obj; + this.ctx = ctx; + } + + @Override + public Resource getSubject() { + return subj.getValue(); + } + + @Override + public IRI getPredicate() { + return pred.getValue(); + } + + @Override + public Value getObject() { + return obj.getValue(); + } + + @Override + public Resource getContext() { + return ctx.getValue(); + } + + @Override + public boolean equals(Object other) { + if (this == other) + return true; + if (!super.equals(other)) + return false; + if (getContext() == null) + return ((Statement)other).getContext() == null; + return getContext().equals(((Statement)other).getContext()); + } + } + + private void writeObject(ObjectOutputStream s) + throws IOException + { + // Write out any hidden serialization magic + s.defaultWriteObject(); + // Write in size + s.writeInt(statements.size()); + // Write in all elements + for (ModelStatement st : statements) { + Resource subj = st.getSubject(); + IRI pred = st.getPredicate(); + Value obj = st.getObject(); + Resource ctx = st.getContext(); + s.writeObject(new ContextStatement(subj, pred, obj, ctx)); + } + } + + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + // Read in any hidden serialization magic + s.defaultReadObject(); + // Read in size + int size = s.readInt(); + values = new HashMap(size * 2); + statements = new LinkedHashSet(size); + // Read in all elements + for (int i = 0; i < size; i++) { + Statement st = (Statement)s.readObject(); + add(st); + } + } + + private ModelIterator matchPattern(Resource subj, IRI pred, Value obj, Resource... contexts) { + Set set = choose(subj, pred, obj, contexts); + Iterator it = set.iterator(); + Iterator iter; + iter = new PatternIterator(it, subj, pred, obj, contexts); + return new ModelIterator(iter, set); + } + + private Set choose(Resource subj, IRI pred, Value obj, Resource... contexts) { + contexts = notNull(contexts); + Set s = null; + Set p = null; + Set o = null; + if (subj != null) { + if (!values.containsKey(subj)) + return Collections.emptySet(); + s = values.get(subj).subjects; + } + if (pred != null) { + if (!values.containsKey(pred)) + return Collections.emptySet(); + p = values.get(pred).predicates; + } + if (obj != null) { + if (!values.containsKey(obj)) + return Collections.emptySet(); + o = values.get(obj).objects; + } + if (contexts.length == 1) { + if (!values.containsKey(contexts[0])) + return Collections.emptySet(); + Set c = values.get(contexts[0]).contexts; + return smallest(statements, s, p, o, c); + } + else { + return smallest(statements, s, p, o); + } + } + + private Resource[] notNull(Resource[] contexts) { + if (contexts == null) { + return new Resource[] { null }; + } + return contexts; + } + + private Iterator find(Statement st) { + Resource subj = st.getSubject(); + IRI pred = st.getPredicate(); + Value obj = st.getObject(); + Resource ctx = st.getContext(); + return matchPattern(subj, pred, obj, ctx); + } + + private boolean addModelStatement(ModelStatement st) { + Set subj = st.subj.subjects; + Set pred = st.pred.predicates; + Set obj = st.obj.objects; + Set ctx = st.ctx.contexts; + if (smallest(subj, pred, obj, ctx).contains(st)) { + return false; + } + statements.add(st); + subj.add(st); + pred.add(st); + obj.add(st); + ctx.add(st); + return true; + } + + private Set smallest(Set... sets) { + int minSize = Integer.MAX_VALUE; + Set minSet = null; + for (Set set : sets) { + if (set != null && set.size() < minSize) { + minSet = set; + } + } + return minSet; + } + + private ModelNode asNode(V value) { + ModelNode node = values.get(value); + if (node != null) + return node; + node = new ModelNode(value); + values.put(value, node); + return node; + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/LinkedHashModelFactory.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/LinkedHashModelFactory.java new file mode 100644 index 00000000000..4a08b49b622 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/LinkedHashModelFactory.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.ModelFactory; + +/** + * Creates {@link LinkedHashModel}. + * + * @author James Leigh + */ +public class LinkedHashModelFactory implements ModelFactory { + + @Override + public LinkedHashModel createEmptyModel() { + return new LinkedHashModel(); + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/LiteralImpl.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/LiteralImpl.java new file mode 100644 index 00000000000..74266cb6781 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/LiteralImpl.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.ValueFactory; + +/** + * @author Jeen Broekstra + * @deprecated since 4.0. Use {@link SimpleLiteral} for extending, and + * instantiate using a {@link ValueFactory}. + */ +@Deprecated +public class LiteralImpl extends SimpleLiteral { + + /** + * @deprecated since 4.0. Use {@link ValueFactory#createLiteral(String)} + * instead. + */ + @Deprecated + public LiteralImpl(String label) { + super(label); + } + + /** + * @deprecated since 4.0. Use + * {@link ValueFactory#createLiteral(String, String)} instead. + */ + @Deprecated + public LiteralImpl(String label, String language) { + super(label, language); + } + + /** + * @deprecated since 4.0. Use {@link ValueFactory#createLiteral(String, IRI)} + * instead. + */ + @Deprecated + public LiteralImpl(String label, URI datatype) { + super(label, (IRI)datatype); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NamespaceImpl.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NamespaceImpl.java new file mode 100644 index 00000000000..5b68cba80b5 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NamespaceImpl.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +/** + * @deprecated since 4.0. Use {@link SimpleNamespace} instead. + */ +@Deprecated +public class NamespaceImpl extends SimpleNamespace { + + /** + * @deprecated since 4.0. Use {@link SimpleNamespace} instead. + */ + @Deprecated + public NamespaceImpl(String prefix, String name) { + super(prefix, name); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NumericLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NumericLiteral.java new file mode 100644 index 00000000000..838a91049ac --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NumericLiteral.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; + +/** + * An extension of {@link SimpleLiteral} that stores a numeric value to avoid + * parsing. + * + * @author David Huynh + */ +public class NumericLiteral extends SimpleLiteral { + + private static final long serialVersionUID = 3004497457768807919L; + + private final Number number; + + /** + * Creates a literal with the specified value and datatype. + */ + protected NumericLiteral(Number number, IRI datatype) { + super(number.toString(), datatype); + this.number = number; + } + + /** + * Creates an xsd:byte typed litral with the specified value. + */ + protected NumericLiteral(byte number) { + this(number, XMLSchema.BYTE); + } + + /** + * Creates an xsd:short typed litral with the specified value. + */ + protected NumericLiteral(short number) { + this(number, XMLSchema.SHORT); + } + + /** + * Creates an xsd:int typed litral with the specified value. + */ + protected NumericLiteral(int number) { + this(number, XMLSchema.INT); + } + + /** + * Creates an xsd:long typed litral with the specified value. + */ + protected NumericLiteral(long n) { + this(n, XMLSchema.LONG); + } + + /** + * Creates an xsd:float typed litral with the specified value. + */ + protected NumericLiteral(float n) { + this(n, XMLSchema.FLOAT); + } + + /** + * Creates an xsd:double typed litral with the specified value. + */ + protected NumericLiteral(double n) { + this(n, XMLSchema.DOUBLE); + } + + @Override + public byte byteValue() + { + return number.byteValue(); + } + + @Override + public short shortValue() + { + return number.shortValue(); + } + + @Override + public int intValue() + { + return number.intValue(); + } + + @Override + public long longValue() + { + return number.longValue(); + } + + @Override + public float floatValue() + { + return number.floatValue(); + } + + @Override + public double doubleValue() + { + return number.doubleValue(); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleBNode.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleBNode.java new file mode 100644 index 00000000000..7f72db029fd --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleBNode.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.BNode; + +/** + * An simple default implementation of the {@link BNode} interface. + * + * @author Arjohn Kampman + */ +public class SimpleBNode implements BNode { + + /*-----------* + * Constants * + *-----------*/ + + private static final long serialVersionUID = 5273570771022125970L; + + /*-----------* + * Variables * + *-----------*/ + + /** + * The blank node's identifier. + */ + private String id; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new, unitialized blank node. This blank node's ID needs to be + * {@link #setID(String) set} before the normal methods can be used. + */ + protected SimpleBNode() { + } + + /** + * Creates a new blank node with the supplied identifier. + * + * @param id + * The identifier for this blank node, must not be null. + */ + protected SimpleBNode(String id) { + this(); + setID(id); + } + + /*---------* + * Methods * + *---------*/ + + public String getID() { + return id; + } + + protected void setID(String id) { + this.id = id; + } + + public String stringValue() { + return id; + } + + // Overrides Object.equals(Object), implements BNode.equals(Object) + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o instanceof BNode) { + BNode otherNode = (BNode)o; + return this.getID().equals(otherNode.getID()); + } + + return false; + } + + // Overrides Object.hashCode(), implements BNode.hashCode() + @Override + public int hashCode() { + return id.hashCode(); + } + + // Overrides Object.toString() + @Override + public String toString() { + return "_:" + id; + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleIRI.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleIRI.java new file mode 100644 index 00000000000..972e1ad5b82 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleIRI.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.util.Objects; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.util.URIUtil; + +/** + * The default implementation of the {@link IRI} interface. + */ +public class SimpleIRI implements IRI { + + /*-----------* + * Constants * + *-----------*/ + + private static final long serialVersionUID = -7330406348751485330L; + + /*-----------* + * Variables * + *-----------*/ + + /** + * The IRI string. + */ + private String iriString; + + /** + * An index indicating the first character of the local name in the IRI + * string, -1 if not yet set. + */ + private int localNameIdx; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new, un-initialized IRI. This IRI's string value needs to be + * {@link #setIRIString(String) set} before the normal methods can be used. + */ + protected SimpleIRI() { + } + + /** + * Creates a new IRI from the supplied string. + *

    + * Note that creating SimpleIRI objects directly via this constructor is not + * the recommended approach. Instead, use a + * {@link org.eclipse.rdf4j.model.ValueFactory ValueFactory} (obtained from your + * repository or by using {@link SimpleValueFactory#getInstance()}) to create + * new IRI objects. + * + * @param iriString + * A String representing a valid, absolute IRI. May not be + * null. + * @throws IllegalArgumentException + * If the supplied IRI is not a valid (absolute) IRI. + * @see {@link SimpleValueFactory#createIRI(String)} + */ + protected SimpleIRI(String iriString) { + setIRIString(iriString); + } + + /*---------* + * Methods * + *---------*/ + + protected void setIRIString(String iriString) { + Objects.requireNonNull(iriString, "iriString must not be null"); + + if (iriString.indexOf(':') < 0) { + throw new IllegalArgumentException("Not a valid (absolute) IRI: " + iriString); + } + + this.iriString = iriString; + this.localNameIdx = -1; + } + + // Implements IRI.toString() + @Override + public String toString() { + return iriString; + } + + public String stringValue() { + return iriString; + } + + public String getNamespace() { + if (localNameIdx < 0) { + localNameIdx = URIUtil.getLocalNameIndex(iriString); + } + + return iriString.substring(0, localNameIdx); + } + + public String getLocalName() { + if (localNameIdx < 0) { + localNameIdx = URIUtil.getLocalNameIndex(iriString); + } + + return iriString.substring(localNameIdx); + } + + // Implements IRI.equals(Object) + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o instanceof IRI) { + return toString().equals(o.toString()); + } + + return false; + } + + // Implements IRI.hashCode() + @Override + public int hashCode() { + return iriString.hashCode(); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleLiteral.java new file mode 100644 index 00000000000..cf63d581e08 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleLiteral.java @@ -0,0 +1,245 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Objects; +import java.util.Optional; + +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.util.Literals; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; + +/** + * A simple default implementation of the {@link Literal} interface. + * + * @author Arjohn Kampman + * @author David Huynh + */ +public class SimpleLiteral implements Literal { + + /*-----------* + * Constants * + *-----------*/ + + private static final long serialVersionUID = -1649571784782592271L; + + /*-----------* + * Variables * + *-----------*/ + + /** + * The literal's label. + */ + private String label; + + /** + * The literal's language tag. + */ + private String language; + + /** + * The literal's datatype. + */ + private IRI datatype; + + /*--------------* + * Constructors * + *--------------*/ + + protected SimpleLiteral() { + } + + /** + * Creates a new plain literal with the supplied label. + * + * @param label + * The label for the literal, must not be null. + */ + protected SimpleLiteral(String label) { + setLabel(label); + setDatatype(XMLSchema.STRING); + } + + /** + * Creates a new plain literal with the supplied label and language tag. + * + * @param label + * The label for the literal, must not be null. + * @param language + * The language tag for the literal, must not be null. + */ + protected SimpleLiteral(String label, String language) { + setLabel(label); + setLanguage(language); + } + + /** + * Creates a new datyped literal with the supplied label and datatype. + * + * @param label + * The label for the literal, must not be null. + * @param datatype + * The datatype for the literal. + */ + protected SimpleLiteral(String label, IRI datatype) { + setLabel(label); + if (RDF.LANGSTRING.equals(datatype)) { + throw new IllegalArgumentException("datatype rdf:langString requires a language tag"); + } + else if (datatype == null) { + datatype = XMLSchema.STRING; + } + setDatatype(datatype); + } + + /*---------* + * Methods * + *---------*/ + + protected void setLabel(String label) { + Objects.requireNonNull(label, "Literal label cannot be null"); + this.label = label; + } + + public String getLabel() { + return label; + } + + protected void setLanguage(String language) { + Objects.requireNonNull(language); + this.language = language; + setDatatype(RDF.LANGSTRING); + } + + public Optional getLanguage() { + return Optional.ofNullable(language); + } + + protected void setDatatype(IRI datatype) { + this.datatype = datatype; + } + + public IRI getDatatype() { + return datatype; + } + + // Overrides Object.equals(Object), implements Literal.equals(Object) + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o instanceof Literal) { + Literal other = (Literal)o; + + // Compare labels + if (!label.equals(other.getLabel())) { + return false; + } + + // Compare datatypes + if (!datatype.equals(other.getDatatype())) { + return false; + } + + if (getLanguage().isPresent() && other.getLanguage().isPresent()) { + return getLanguage().get().equalsIgnoreCase(other.getLanguage().get()); + } + // If only one has a language, then return false + else if (getLanguage().isPresent() || other.getLanguage().isPresent()) { + return false; + } + + return true; + } + + return false; + } + + // overrides Object.hashCode(), implements hashCode() + @Override + public int hashCode() { + return label.hashCode(); + } + + /** + * Returns the label of the literal. + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(label.length() * 2); + + sb.append('"'); + sb.append(label); + sb.append('"'); + + if (Literals.isLanguageLiteral(this)) { + sb.append('@'); + sb.append(language); + } + else { + sb.append("^^<"); + sb.append(datatype.toString()); + sb.append(">"); + } + + return sb.toString(); + } + + public String stringValue() { + return label; + } + + public boolean booleanValue() { + return XMLDatatypeUtil.parseBoolean(getLabel()); + } + + public byte byteValue() { + return XMLDatatypeUtil.parseByte(getLabel()); + } + + public short shortValue() { + return XMLDatatypeUtil.parseShort(getLabel()); + } + + public int intValue() { + return XMLDatatypeUtil.parseInt(getLabel()); + } + + public long longValue() { + return XMLDatatypeUtil.parseLong(getLabel()); + } + + public float floatValue() { + return XMLDatatypeUtil.parseFloat(getLabel()); + } + + public double doubleValue() { + return XMLDatatypeUtil.parseDouble(getLabel()); + } + + public BigInteger integerValue() { + return XMLDatatypeUtil.parseInteger(getLabel()); + } + + public BigDecimal decimalValue() { + return XMLDatatypeUtil.parseDecimal(getLabel()); + } + + public XMLGregorianCalendar calendarValue() { + return XMLDatatypeUtil.parseCalendar(getLabel()); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleNamespace.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleNamespace.java new file mode 100644 index 00000000000..18dea3e4f9d --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleNamespace.java @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.Namespace; + +/** + * A default implementation of the {@link Namespace} interface. + */ +public class SimpleNamespace implements Namespace { + + private static final long serialVersionUID = -5829768428912588171L; + + /*-----------* + * Variables * + *-----------*/ + + /** + * The namespace's prefix. + */ + private String prefix; + + /** + * The namespace's name. + */ + private String name; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new Namespace object. + * + * @param prefix + * The namespace's prefix. + * @param name + * The namespace's name. + */ + public SimpleNamespace(String prefix, String name) { + setPrefix(prefix); + setName(name); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the prefix of the namespace. + * + * @return prefix of the namespace + */ + public String getPrefix() { + return prefix; + } + + /** + * Sets the prefix of the namespace. + * + * @param prefix + * The (new) prefix for this namespace. + */ + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + /** + * Gets the name of the namespace. + * + * @return name of the namespace + */ + public String getName() { + return name; + } + + /** + * Sets the name of the namespace. + * + * @param name + * The (new) name for this namespace. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns a string representation of the object. + * + * @return String representation of the namespace + */ + @Override + public String toString() { + return prefix + " :: " + name; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Namespace)) { + return false; + } + Namespace other = (Namespace)obj; + if (prefix == null) { + if (other.getPrefix() != null) { + return false; + } + } + else if (!prefix.equals(other.getPrefix())) { + return false; + } + if (name == null) { + if (other.getName() != null) { + return false; + } + } + else if (!name.equals(other.getName())) { + return false; + } + return true; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); + return result; + } + + @Override + public int compareTo(Namespace o) { + if (getPrefix().equals(o.getPrefix())) { + if (getName().equals(o.getName())) { + return 0; + } + else { + return getName().compareTo(o.getName()); + } + } + else { + return getPrefix().compareTo(o.getPrefix()); + } + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleStatement.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleStatement.java new file mode 100644 index 00000000000..6af795be154 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleStatement.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.util.Objects; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; + +/** + * A simple default implementation of the {@link Statement} interface for + * statements that don't have an associated context. For statements that do have + * an associated context, {@link ContextStatement} can be used. + * + * @see {@link SimpleValueFactory} + */ +public class SimpleStatement implements Statement { + + /*-----------* + * Constants * + *-----------*/ + + private static final long serialVersionUID = 8707542157460228077L; + + /** + * The statement's subject. + */ + private final Resource subject; + + /** + * The statement's predicate. + */ + private final IRI predicate; + + /** + * The statement's object. + */ + private final Value object; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new Statement with the supplied subject, predicate and object. * + *

    + * Note that creating SimpleStatement objects directly via this constructor + * is not the recommended approach. Instead, use a + * {@link org.eclipse.rdf4j.model.ValueFactory ValueFactory} (obtained from your + * repository or by using {@link SimpleValueFactory#getInstance()}) to create + * new Statement objects. + * + * @param subject + * The statement's subject, must not be null. + * @param predicate + * The statement's predicate, must not be null. + * @param object + * The statement's object, must not be null. + * @see {@link SimpleValueFactory#createStatement(Resource, IRI, Value) + */ + protected SimpleStatement(Resource subject, IRI predicate, Value object) { + this.subject = Objects.requireNonNull(subject, "subject must not be null"); + this.predicate = Objects.requireNonNull(predicate, "predicate must not be null"); + this.object = Objects.requireNonNull(object, "object must not be null"); + } + + /*---------* + * Methods * + *---------*/ + + // Implements Statement.getSubject() + public Resource getSubject() { + return subject; + } + + // Implements Statement.getPredicate() + public IRI getPredicate() { + return predicate; + } + + // Implements Statement.getObject() + public Value getObject() { + return object; + } + + // Implements Statement.getContext() + public Resource getContext() { + return null; + } + + // Overrides Object.equals(Object), implements Statement.equals(Object) + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other instanceof Statement) { + Statement that = (Statement)other; + + /* We check object equality first since it's most likely to be different. + * + * In general the number of different predicates and contexts in sets of + * statements are the smallest (and therefore most likely to be identical), so + * these are checked last. + */ + return object.equals(that.getObject()) && subject.equals(that.getSubject()) + && predicate.equals(that.getPredicate()) && Objects.equals(getContext(), that.getContext()); + } + + return false; + } + + // Overrides Object.hashCode(), implements Statement.hashCode() + @Override + public int hashCode() { + return Objects.hash(subject, predicate, object, getContext()); + } + + /** + * Gives a String-representation of this Statement that can be used for + * debugging. + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(256); + + sb.append("("); + sb.append(getSubject()); + sb.append(", "); + sb.append(getPredicate()); + sb.append(", "); + sb.append(getObject()); + sb.append(")"); + + return sb.toString(); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleValueFactory.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleValueFactory.java new file mode 100644 index 00000000000..a503357b1a6 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleValueFactory.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.ValueFactory; + +/** + * Default implementation of the {@link ValueFactory} interface. + * + * @author Arjohn Kampman + */ +public class SimpleValueFactory extends AbstractValueFactory { + + /*-----------* + * Constants * + *-----------*/ + + private static final SimpleValueFactory sharedInstance = new SimpleValueFactory(); + + /** + * Provide a single shared instance of a SimpleValueFactory. + * + * @return a singleton instance of SimpleValueFactory. + */ + public static SimpleValueFactory getInstance() { + return sharedInstance; + } + + /** + * Hidden constructor to enforce singleton pattern. + */ + protected SimpleValueFactory() { + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/StatementImpl.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/StatementImpl.java new file mode 100644 index 00000000000..e721aab81e0 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/StatementImpl.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; + +/** + * @author Jeen Broekstra + * @deprecated since 4.0. Use {@link SimpleStatement} instead for extension, and + * {@link ValueFactory} for instantiation. + */ +@Deprecated +public class StatementImpl extends SimpleStatement { + + /** + * @deprecated since 4.0. Use + * {@link ValueFactory#createStatement(Resource, IRI, Value)} + * instead. + */ + @Deprecated + public StatementImpl(Resource subject, URI predicate, Value object) { + super(subject, (IRI)predicate, object); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/TreeModel.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/TreeModel.java new file mode 100644 index 00000000000..a4df7cd99ba --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/TreeModel.java @@ -0,0 +1,885 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.io.Serializable; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.util.LexicalValueComparator; +import org.eclipse.rdf4j.model.util.PatternIterator; + +/** + * A Red-Black tree based {@link Model} implementation. The model is sorted + * according to the lexical ordering of terms. + *

    + * This implementation provides guaranteed log(n) time cost for filtered access + * by any number of terms. If an index is not yet available for a set of + * positions, it is created at runtime using a {@link TreeSet}. + *

    + * Note that this implementation is not synchronized. If multiple threads + * access a model concurrently, and at least one of the threads modifies the + * model, it must be synchronized externally. This is typically accomplished by + * synchronizing on some object that naturally encapsulates the model. If no + * such object exists, the set should be "wrapped" using the + * Collections.synchronizedSet method. This is best done at creation time, to + * prevent accidental unsynchronized access to the LinkedHashModel instance + * (though the synchronization guarantee is only when accessing via the Set + * interface methods): + *

    + * + * @since 2.7.0 + * @author James Leigh + */ +public class TreeModel extends AbstractModel implements SortedSet { + + private static final long serialVersionUID = 7893197431354524479L; + + static final Resource[] NULL_CTX = new Resource[] { null }; + + static final IRI BEFORE = new SimpleIRI("urn:from"); + + static final IRI AFTER = new SimpleIRI("urn:to"); + + private final LexicalValueComparator vc = new LexicalValueComparator(); + + final Set namespaces = new TreeSet(); + + final List trees = new ArrayList(); + + public TreeModel() { + trees.add(new StatementTree("spog".toCharArray())); + } + + public TreeModel(Model model) { + this(model.getNamespaces()); + addAll(model); + } + + public TreeModel(Collection c) { + this(); + addAll(c); + } + + public TreeModel(Set namespaces, Collection c) { + this(c); + this.namespaces.addAll(namespaces); + } + + public TreeModel(Set namespaces) { + this(); + this.namespaces.addAll(namespaces); + } + + @Override + public Optional getNamespace(String prefix) { + for (Namespace nextNamespace : namespaces) { + if (prefix.equals(nextNamespace.getPrefix())) { + return Optional.of(nextNamespace); + } + } + return Optional.empty(); + } + + @Override + public Set getNamespaces() { + return namespaces; + } + + @Override + public Namespace setNamespace(String prefix, String name) { + removeNamespace(prefix); + Namespace result = new SimpleNamespace(prefix, name); + namespaces.add(result); + return result; + } + + @Override + public void setNamespace(Namespace namespace) { + removeNamespace(namespace.getPrefix()); + namespaces.add(namespace); + } + + @Override + public Optional removeNamespace(String prefix) { + Optional result = getNamespace(prefix); + if (result.isPresent()) { + namespaces.remove(result.get()); + } + return result; + } + + @Override + public int size() { + return trees.get(0).size(); + } + + @Override + public void clear() { + for (StatementTree tree : trees) { + tree.clear(); + } + } + + @Override + public Comparator comparator() { + return trees.get(0).tree.comparator(); + } + + @Override + public Statement first() { + return trees.get(0).tree.first(); + } + + @Override + public Statement last() { + return trees.get(0).tree.last(); + } + + public Statement lower(Statement e) { + return trees.get(0).tree.lower(e); + } + + public Statement floor(Statement e) { + return trees.get(0).tree.floor(e); + } + + public Statement ceiling(Statement e) { + return trees.get(0).tree.ceiling(e); + } + + public Statement higher(Statement e) { + return trees.get(0).tree.higher(e); + } + + public Statement pollFirst() { + try { + Statement first = trees.get(0).tree.first(); + remove(first); + return first; + } + catch (NoSuchElementException e) { + return null; + } + } + + public Statement pollLast() { + try { + Statement last = trees.get(0).tree.last(); + remove(last); + return last; + } + catch (NoSuchElementException e) { + return null; + } + } + + @Override + public SortedSet subSet(Statement fromElement, Statement toElement) { + return subSet(fromElement, true, toElement, false); + } + + @Override + public SortedSet headSet(Statement toElement) { + return subSet(before(null, null, null, null), true, toElement, false); + } + + @Override + public SortedSet tailSet(Statement fromElement) { + return subSet(fromElement, true, after(null, null, null, null), true); + } + + @Override + public boolean add(Resource subj, IRI pred, Value obj, Resource... contexts) { + if (subj == null || pred == null || obj == null) + throw new UnsupportedOperationException("Incomplete statement"); + boolean changed = false; + for (Value ctx : notEmpty(contexts)) { + if (ctx == null || ctx instanceof Resource) { + Statement st = new TreeStatement(subj, pred, obj, (Resource)ctx); + for (StatementTree tree : trees) { + changed |= tree.add(st); + } + } + } + return changed; + } + + @Override + public boolean contains(Resource subj, IRI pred, Value obj, Resource... contexts) { + if (contexts == null || contexts.length == 1 && contexts[0] == null) { + Iterator iter = matchPattern(subj, pred, obj, null); + while (iter.hasNext()) { + if (iter.next().getContext() == null) + return true; + } + return false; + } + else if (contexts.length == 0) { + return matchPattern(subj, pred, obj, null).hasNext(); + } + else { + for (Resource ctx : contexts) { + if (ctx == null) { + if (contains(subj, pred, obj, (Resource[])null)) + return true; + } + else if (matchPattern(subj, pred, obj, ctx).hasNext()) { + return true; + } + } + return false; + } + } + + @Override + public boolean remove(Resource subj, IRI pred, Value obj, Resource... contexts) { + boolean changed = false; + if (contexts == null || contexts.length == 1 && contexts[0] == null) { + Iterator iter = matchPattern(subj, pred, obj, null); + while (iter.hasNext()) { + if (iter.next().getContext() == null) { + iter.remove(); + changed = true; + } + } + } + else if (contexts.length == 0) { + Iterator iter = matchPattern(subj, pred, obj, null); + while (iter.hasNext()) { + iter.next(); + iter.remove(); + changed = true; + } + } + else { + for (Resource ctx : contexts) { + if (ctx == null) { + changed |= remove(subj, pred, obj, (Resource[])null); + } + else { + Iterator iter = matchPattern(subj, pred, obj, ctx); + while (iter.hasNext()) { + iter.next(); + iter.remove(); + changed = true; + } + } + } + } + return changed; + } + + @Override + public Iterator iterator() { + return matchPattern(null, null, null, null); + } + + @Override + public Model filter(final Resource subj, final IRI pred, final Value obj, final Resource... contexts) { + if (contexts != null && contexts.length == 0) { + return new FilteredModel(this, subj, pred, obj, contexts) { + + private static final long serialVersionUID = 396293781006255959L; + + @Override + public Iterator iterator() { + return matchPattern(subj, pred, obj, null); + } + + @Override + protected void removeFilteredTermIteration(Iterator iter, Resource subj, IRI pred, + Value obj, Resource... contexts) + { + TreeModel.this.removeTermIteration(iter, subj, pred, obj, contexts); + } + }; + } + else if (contexts != null && contexts.length == 1 && contexts[0] != null) { + return new FilteredModel(this, subj, pred, obj, contexts) { + + @Override + public Iterator iterator() { + return matchPattern(subj, pred, obj, contexts[0]); + } + + @Override + protected void removeFilteredTermIteration(Iterator iter, Resource subj, IRI pred, + Value obj, Resource... contexts) + { + TreeModel.this.removeTermIteration(iter, subj, pred, obj, contexts); + } + }; + } + else { + return new FilteredModel(this, subj, pred, obj, contexts) { + + private static final long serialVersionUID = 396293781006255959L; + + @Override + public Iterator iterator() { + return new PatternIterator(matchPattern(subj, pred, obj, null), subj, pred, obj, + contexts); + } + + @Override + protected void removeFilteredTermIteration(Iterator iter, Resource subj, IRI pred, + Value obj, Resource... contexts) + { + TreeModel.this.removeTermIteration(iter, subj, pred, obj, contexts); + } + }; + } + } + + @Override + public void removeTermIteration(Iterator iterator, Resource subj, IRI pred, Value obj, + Resource... contexts) + { + TreeSet owner = ((ModelIterator)iterator).getOwner(); + if (contexts == null || contexts.length == 1 && contexts[0] == null) { + StatementTree chosen = choose(subj, pred, obj, null); + Iterator iter = chosen.subIterator(before(subj, pred, obj, null), true, + after(subj, pred, obj, null), true); + iter = new PatternIterator(iter, subj, pred, obj, contexts); + removeAll(owner, chosen, iter); + } + else if (contexts.length == 0) { + StatementTree chosen = choose(subj, pred, obj, null); + Iterator iter = chosen.subIterator(before(subj, pred, obj, null), true, + after(subj, pred, obj, null), true); + removeAll(owner, chosen, iter); + } + else { + for (Value ctx : notEmpty(contexts)) { + if (ctx == null) { + removeTermIteration(iterator, subj, pred, obj, (Resource[])null); + } + else { + StatementTree chosen = choose(subj, pred, obj, ctx); + Iterator iter = chosen.subIterator(before(subj, pred, obj, ctx), true, + after(subj, pred, obj, ctx), true); + removeAll(owner, chosen, iter); + } + } + } + } + + Iterator matchPattern(Resource subj, IRI pred, Value obj, Resource ctx) { + if (!isResourceURIResource(subj, pred, ctx)) { + Set emptySet = Collections.emptySet(); + return emptySet.iterator(); + } + StatementTree tree = choose(subj, pred, obj, ctx); + Iterator it = tree.subIterator(before(subj, pred, obj, ctx), true, + after(subj, pred, obj, ctx), true); + return new ModelIterator(it, tree); + } + + int compareValue(Value o1, Value o2) { + if (o1 == o2) + return 0; + if (o1 == BEFORE) + return -1; + if (o2 == BEFORE) + return 1; + if (o1 == AFTER) + return 1; + if (o2 == AFTER) + return -1; + return vc.compare(o1, o2); + } + + SortedSet subSet(Statement lo, boolean loInclusive, Statement hi, boolean hiInclusive) { + return new SubSet(this, new TreeStatement(lo), loInclusive, new TreeStatement(hi), hiInclusive); + } + + private void removeAll(TreeSet owner, StatementTree chosen, Iterator iter) { + while (iter.hasNext()) { + Statement last = iter.next(); + for (StatementTree tree : trees) { + if (tree.owns(owner)) { + tree.reindex(); + tree.remove(last); + } + else if (tree != chosen) { + tree.remove(last); + } + } + iter.remove(); // remove from chosen + } + } + + private boolean isResourceURIResource(Value subj, Value pred, Value ctx) { + return (subj == null || subj instanceof Resource) && (pred == null || pred instanceof IRI) + && (ctx == null || ctx instanceof Resource); + } + + private Value[] notEmpty(Value[] contexts) { + if (contexts == null || contexts.length == 0) + return new Resource[] { null }; + return contexts; + } + + private Statement before(Value subj, Value pred, Value obj, Value ctx) { + Resource s = subj instanceof Resource ? (Resource)subj : BEFORE; + IRI p = pred instanceof IRI ? (IRI)pred : BEFORE; + Value o = obj instanceof Value ? obj : BEFORE; + Resource c = ctx instanceof Resource ? (Resource)ctx : BEFORE; + return new TreeStatement(s, p, o, c); + } + + private Statement after(Value subj, Value pred, Value obj, Value ctx) { + Resource s = subj instanceof Resource ? (Resource)subj : AFTER; + IRI p = pred instanceof IRI ? (IRI)pred : AFTER; + Value o = obj instanceof Value ? obj : AFTER; + Resource c = ctx instanceof Resource ? (Resource)ctx : AFTER; + return new TreeStatement(s, p, o, c); + } + + private StatementTree choose(Value subj, Value pred, Value obj, Value ctx) { + for (StatementTree tree : trees) { + if (tree.isIndexed(subj, pred, obj, ctx)) + return tree; + } + return index(subj, pred, obj, ctx); + } + + private StatementTree index(Value subj, Value pred, Value obj, Value ctx) { + int idx = 0; + char[] index = new char[4]; + if (subj != null) { + index[idx++] = 's'; + } + if (pred != null) { + index[idx++] = 'p'; + } + if (obj != null) { + index[idx++] = 'o'; + } + if (ctx != null) { + index[idx++] = 'g'; + } + if (pred == null) { + index[idx++] = 'p'; + } + if (obj == null) { + index[idx++] = 'o'; + } + if (ctx == null) { + index[idx++] = 'g'; + } + if (subj == null) { + index[idx++] = 's'; + } + StatementTree tree = new StatementTree(index); + tree.addAll(trees.get(0)); + trees.add(tree); + return tree; + } + + private class ModelIterator implements Iterator { + + private Iterator iter; + + private TreeSet owner; + + private Statement last; + + public ModelIterator(Iterator iter, StatementTree owner) { + this.iter = iter; + this.owner = owner.tree; + } + + public TreeSet getOwner() { + return owner; + } + + @Override + public boolean hasNext() { + return iter.hasNext(); + } + + @Override + public Statement next() { + return last = iter.next(); + } + + @Override + public void remove() { + if (last == null) { + throw new IllegalStateException(); + } + for (StatementTree tree : trees) { + removeFrom(tree); + } + iter.remove(); // remove from owner + } + + private void removeFrom(StatementTree subjects) { + if (!subjects.owns(owner)) { + subjects.remove(last); + } + } + } + + static class TreeStatement extends ContextStatement { + + private static final long serialVersionUID = -7720419322256724495L; + + public TreeStatement(Statement st) { + super(st.getSubject(), st.getPredicate(), st.getObject(), st.getContext()); + } + + public TreeStatement(Resource subject, IRI predicate, Value object, Resource ctx) { + super(subject, predicate, object, ctx); + } + } + + class StatementTree implements Serializable { + + private static final long serialVersionUID = -7580746419791799953L; + + private final char[] index; + + TreeSet tree; + + public StatementTree(char[] index) { + this.index = index; + Comparator[] comparators = new Comparator[index.length]; + for (int i = 0; i < index.length; i++) { + switch (index[i]) { + case 's': + comparators[i] = new SubjectComparator(); + break; + case 'p': + comparators[i] = new PredicateComparator(); + break; + case 'o': + comparators[i] = new ObjectComparator(); + break; + case 'g': + comparators[i] = new GraphComparator(); + break; + default: + throw new AssertionError(); + } + } + tree = new TreeSet(new StatementComparator(comparators)); + } + + public boolean owns(TreeSet set) { + return tree == set; + } + + public boolean isIndexed(Value subj, Value pred, Value obj, Value ctx) { + boolean wild = false; + for (int i = 0; i < index.length; i++) { + switch (index[i]) { + case 's': + if (subj == null) + wild = true; + else if (wild) + return false; + break; + case 'p': + if (pred == null) + wild = true; + else if (wild) + return false; + break; + case 'o': + if (obj == null) + wild = true; + else if (wild) + return false; + break; + case 'g': + if (ctx == null) + wild = true; + else if (wild) + return false; + break; + default: + throw new AssertionError(); + } + } + return true; + } + + public void reindex() { + TreeSet treeSet = new TreeSet(tree.comparator()); + treeSet.addAll(tree); + tree = treeSet; + } + + public boolean add(Statement e) { + return tree.add(e); + } + + public boolean addAll(StatementTree c) { + return tree.addAll(c.tree); + } + + public int size() { + return tree.size(); + } + + public void clear() { + tree.clear(); + } + + public boolean remove(Object o) { + return tree.remove(o); + } + + public Iterator subIterator(Statement fromElement, boolean fromInclusive, + Statement toElement, boolean toInclusive) + { + return tree.subSet(fromElement, true, toElement, true).iterator(); + } + } + + class SubjectComparator implements Serializable, Comparator { + + private static final long serialVersionUID = 5275239384134217143L; + + @Override + public int compare(Statement s1, Statement s2) { + return compareValue(s1.getSubject(), s2.getSubject()); + } + } + + class PredicateComparator implements Serializable, Comparator { + + private static final long serialVersionUID = -883414941022127103L; + + @Override + public int compare(Statement s1, Statement s2) { + return compareValue(s1.getPredicate(), s2.getPredicate()); + } + } + + class ObjectComparator implements Serializable, Comparator { + + private static final long serialVersionUID = 1768294714884456242L; + + @Override + public int compare(Statement s1, Statement s2) { + return compareValue(s1.getObject(), s2.getObject()); + } + } + + class GraphComparator implements Serializable, Comparator { + + private static final long serialVersionUID = 7027824614533897706L; + + @Override + public int compare(Statement s1, Statement s2) { + return compareValue(s1.getContext(), s2.getContext()); + } + } + + static class StatementComparator implements Serializable, Comparator { + + private static final long serialVersionUID = -5602364720279633641L; + + private final Comparator[] comparators; + + public StatementComparator(Comparator... comparators) { + this.comparators = comparators; + } + + @Override + public int compare(Statement s1, Statement s2) { + for (Comparator c : comparators) { + int r1 = c.compare(s1, s2); + if (r1 != 0) + return r1; + } + return 0; + } + } + + static class SubSet extends AbstractSet implements Serializable, SortedSet { + + private static final long serialVersionUID = 6362727792092563793L; + + private final TreeModel model; + + private final TreeStatement lo, hi; + + private final boolean loInclusive, hiInclusive; + + public SubSet(TreeModel model, TreeStatement lo, boolean loInclusive, TreeStatement hi, + boolean hiInclusive) + { + this.model = model; + this.lo = lo; + this.loInclusive = loInclusive; + this.hi = hi; + this.hiInclusive = hiInclusive; + } + + public Optional getNamespace(String prefix) { + return model.getNamespace(prefix); + } + + public Set getNamespaces() { + return model.getNamespaces(); + } + + public Namespace setNamespace(String prefix, String name) { + return model.setNamespace(prefix, name); + } + + public void setNamespace(Namespace namespace) { + model.setNamespace(namespace); + } + + public Optional removeNamespace(String prefix) { + return model.removeNamespace(prefix); + } + + @Override + public int size() { + return subSet().size(); + } + + @Override + public void clear() { + StatementTree tree = model.trees.get(0); + Iterator it = tree.subIterator(lo, loInclusive, hi, hiInclusive); + it = model.new ModelIterator(it, tree); + while (it.hasNext()) { + it.remove(); + } + } + + @Override + public Comparator comparator() { + return model.comparator(); + } + + @Override + public Statement first() { + return subSet().first(); + } + + @Override + public Statement last() { + return subSet().last(); + } + + public Statement lower(Statement e) { + return subSet().lower(e); + } + + @Override + public boolean isEmpty() { + return subSet().isEmpty(); + } + + public Statement floor(Statement e) { + return subSet().floor(e); + } + + public Statement ceiling(Statement e) { + return subSet().ceiling(e); + } + + public Statement higher(Statement e) { + return subSet().higher(e); + } + + public Statement pollFirst() { + try { + Statement first = subSet().first(); + model.remove(first); + return first; + } + catch (NoSuchElementException e) { + return null; + } + } + + public Statement pollLast() { + try { + Statement last = subSet().last(); + model.remove(last); + return last; + } + catch (NoSuchElementException e) { + return null; + } + } + + @Override + public SortedSet subSet(Statement fromElement, Statement toElement) { + boolean fromInclusive = true; + boolean toInclusive = false; + if (comparator().compare(fromElement, lo) < 0) { + fromElement = lo; + fromInclusive = loInclusive; + } + if (comparator().compare(hi, toElement) < 0) { + toElement = hi; + toInclusive = hiInclusive; + } + return model.subSet(fromElement, fromInclusive, toElement, toInclusive); + } + + @Override + public SortedSet headSet(Statement toElement) { + boolean toInclusive = false; + if (comparator().compare(hi, toElement) < 0) { + toElement = hi; + toInclusive = hiInclusive; + } + return model.subSet(lo, loInclusive, toElement, toInclusive); + } + + @Override + public SortedSet tailSet(Statement fromElement) { + boolean fromInclusive = true; + if (comparator().compare(fromElement, lo) < 0) { + fromElement = lo; + fromInclusive = loInclusive; + } + return model.subSet(fromElement, fromInclusive, hi, hiInclusive); + } + + @Override + public Iterator iterator() { + StatementTree tree = model.trees.get(0); + Iterator it = tree.subIterator(lo, loInclusive, hi, hiInclusive); + return model.new ModelIterator(it, tree); + } + + private NavigableSet subSet() { + return model.trees.get(0).tree.subSet(lo, loInclusive, hi, hiInclusive); + } + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/TreeModelFactory.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/TreeModelFactory.java new file mode 100644 index 00000000000..5d9be840e71 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/TreeModelFactory.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.ModelFactory; + +/** + * Creates {@link TreeModel}. + * + * @author James Leigh + */ +public class TreeModelFactory implements ModelFactory { + + @Override + public TreeModel createEmptyModel() { + return new TreeModel(); + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/URIImpl.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/URIImpl.java new file mode 100644 index 00000000000..132ce0ce4af --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/URIImpl.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import org.eclipse.rdf4j.model.ValueFactory; + +/** + * @author Jeen Broekstra + * @deprecated since 4.0. Use {@link SimpleIRI} instead for extending, and + * {@link ValueFactory} for instantiation. + */ +@Deprecated +public class URIImpl extends SimpleIRI { + + /** + * @deprecated since 4.0. Use {@link ValueFactory#createIRI(String)} instead. + */ + @Deprecated + public URIImpl(String uriString) { + super(uriString); + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/UnmodifiableModel.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/UnmodifiableModel.java new file mode 100644 index 00000000000..6741e235a16 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/UnmodifiableModel.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import java.util.Collections; +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; + +/** + * A Model wrapper that prevents modification to the underlying model. + */ +class UnmodifiableModel extends AbstractModel { + + private static final long serialVersionUID = 6335569454318096059L; + + private final Model model; + + public UnmodifiableModel(Model delegate) { + this.model = delegate; + } + + @Override + public Set getNamespaces() { + return Collections.unmodifiableSet(model.getNamespaces()); + } + + @Override + public Optional getNamespace(String prefix) { + return model.getNamespace(prefix); + } + + @Override + public Namespace setNamespace(String prefix, String name) { + throw new UnsupportedOperationException(); + } + + @Override + public void setNamespace(Namespace name) { + throw new UnsupportedOperationException(); + } + + @Override + public Optional removeNamespace(String prefix) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean contains(Resource subj, IRI pred, Value obj, Resource... contexts) { + return model.contains(subj, pred, obj, contexts); + } + + @Override + public boolean add(Resource subj, IRI pred, Value obj, Resource... contexts) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Resource subj, IRI pred, Value obj, Resource... contexts) { + throw new UnsupportedOperationException(); + } + + @Override + public Model filter(Resource subj, IRI pred, Value obj, Resource... contexts) { + return model.filter(subj, pred, obj, contexts).unmodifiable(); + } + + @Override + public Iterator iterator() { + return Collections.unmodifiableSet(model).iterator(); + } + + @Override + public int size() { + return model.size(); + } + + @Override + public void removeTermIteration(Iterator iter, Resource subj, IRI pred, Value obj, + Resource... contexts) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValueFactoryBase.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValueFactoryBase.java new file mode 100644 index 00000000000..c85efa8c261 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValueFactoryBase.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + + +/** + * Provided for backward compatility purposes only + * + * @deprecated since 4.0. Use {@link AbstractValueFactory} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class ValueFactoryBase extends AbstractValueFactory { + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValueFactoryImpl.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValueFactoryImpl.java new file mode 100644 index 00000000000..b5c48a012d1 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValueFactoryImpl.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +/** + * @author Jeen Broekstra + * @deprecated since 4.0. Use {@link SimpleValueFactory} instead. + */ +@Deprecated +public class ValueFactoryImpl extends SimpleValueFactory { + + private static final ValueFactoryImpl sharedInstance = new ValueFactoryImpl(); + + /** + * @deprecated since 4.0. Use {@link SimpleValueFactory#getInstance()} + * instead. + */ + @Deprecated + public static ValueFactoryImpl getInstance() { + return sharedInstance; + } + + /** + * @deprecated since 4.0. Use {@link SimpleValueFactory#getInstance()} + * instead. + */ + @Deprecated + public ValueFactoryImpl() { + super(); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/package.html b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/package.html new file mode 100644 index 00000000000..a1a3f072236 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/package.html @@ -0,0 +1,5 @@ + + +Default implementations of the RDF model interfaces. + + diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/package.html b/core/model/src/main/java/org/eclipse/rdf4j/model/package.html new file mode 100644 index 00000000000..83fe42ca3ed --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/package.html @@ -0,0 +1,29 @@ + + + + RDF Model API +

    The RDF model interfaces are organized in the following + hierarchy:

    +
    +       Value          Statement       Model
    +      /     \
    +     /       \
    + Resource  Literal
    +   /  \
    +  /    \
    +IRI   BNode
    +
    +

    + An individual RDF triple or statement is represented by the + Statement + interface. Collections of RDF statements are represented by the + Model + interface. +

    +

    + Creation of new Model elements (IRIs, Literals, BNodes, Statements) is + done by means of a + ValueFactory +

    + + diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphUtil.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphUtil.java new file mode 100644 index 00000000000..f79d1f3d3c6 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphUtil.java @@ -0,0 +1,560 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.rdf4j.OpenRDFUtil; +import org.eclipse.rdf4j.model.Graph; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.util.iterators.ConvertingIterator; +import org.eclipse.rdf4j.util.iterators.Iterators; + +/** + * Utility methods for working with {@link Graph} objects. Note that since + * release 2.7.0, most of the functionality here is also available (in more + * convenient form) in the {@link org.eclipse.rdf4j.model.Model} interface, which + * extends {@link Graph}. + * + * @deprecated since 2.8.0. Use equivalent functionality in {@link Model} and + * {@link Models} instead. + * @author Arjohn Kampman + */ +@Deprecated +public class GraphUtil { + + /** + * Gets the subject of the statements with the specified predicate, object + * and (optionally) contexts from the supplied graph. Calling this method is + * equivalent to calling graph.match(null, pred, obj, contexts) and + * extracting the subjects of the matching statements from the returned + * iterator. See {@link Graph#match(Resource, IRI, Value, Resource[])} for a + * description of the parameter values. + * + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...)} and + * {@link Model#subjects()} instead. + */ + @Deprecated + public static Iterator getSubjectIterator(Graph graph, IRI pred, Value obj, Resource... contexts) + { + Iterator iter = graph.match(null, pred, obj, contexts); + + return new ConvertingIterator(iter) { + + @Override + protected Resource convert(Statement st) + throws RuntimeException + { + return st.getSubject(); + } + + }; + } + + /** + * Gets the subject of the statements with the specified predicate, object + * and (optionally) contexts from the supplied graph. Calling this method is + * equivalent to calling graph.match(null, pred, obj, contexts) and + * adding the subjects of the matching statements to a set. See + * {@link Graph#match(Resource, IRI, Value, Resource[])} for a description of + * the parameter values. + * + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...)} and + * {@link Model#subjects()} instead. + */ + @Deprecated + public static Set getSubjects(Graph graph, IRI pred, Value obj, Resource... contexts) { + Iterator iter = getSubjectIterator(graph, pred, obj, contexts); + return Iterators.addAll(iter, new LinkedHashSet()); + } + + /** + * Gets the subject of the statement(s) with the specified predicate and + * object from the specified contexts in the supplied graph. The combination + * of predicate, object and contexts must match at least one statement. In + * case more than one statement matches -- for example statements from + * multiple contexts -- all these statements should have the same subject. A + * {@link GraphUtilException} is thrown if these conditions are not met. See + * {@link Graph#match(Resource, IRI, Value, Resource[])} for a description of + * the parameter values. + * + * @return The subject of the matched statement(s). + * @throws GraphUtilException + * If the statements matched by the specified parameters do not have + * exactly one unique subject. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...)} and + * {@link Model#subjectResource()} instead. + */ + @Deprecated + public static Resource getUniqueSubject(Graph graph, IRI pred, Value obj, Resource... contexts) + throws GraphUtilException + { + Set subjects = getSubjects(graph, pred, obj, contexts); + + if (subjects.size() == 1) { + return subjects.iterator().next(); + } + else if (subjects.isEmpty()) { + throw new GraphUtilException("Missing property: " + pred); + } + else { + throw new GraphUtilException("Multiple " + pred + " properties found"); + } + } + + /** + * Utility method that casts the return value of + * {@link #getUniqueSubject(Graph, IRI, Value, Resource[])} to a URI, or + * throws a GraphUtilException if that value is not a URI. + * + * @return The subject of the matched statement(s). + * @throws GraphUtilException + * If such an exception is thrown by + * {@link #getUniqueSubject(Graph, IRI, Value, Resource[])} or if its + * return value is not a URI. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...)} and + * {@link Model#subjectIRI()} instead. + */ + @Deprecated + public static IRI getUniqueSubjectURI(Graph graph, IRI pred, Value obj, Resource... contexts) + throws GraphUtilException + { + Resource subject = getUniqueSubject(graph, pred, obj, contexts); + + if (subject instanceof IRI) { + return (IRI)subject; + } + else { + throw new GraphUtilException("Expected URI for subject " + subject); + } + } + + /** + * Gets the subject of the statement(s) with the specified predicate and + * object from the specified contexts in the supplied graph. If the + * combination of predicate, object and contexts matches one or more + * statements, all these statements should have the same subject. A + * {@link GraphUtilException} is thrown if this is not the case. See + * {@link Graph#match(Resource, IRI, Value, Resource[])} for a description of + * the parameter values. + * + * @return The subject of the matched statement(s), or null if no + * matching statements were found. + * @throws GraphUtilException + * If the statements matched by the specified parameters have more + * than one unique subject. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...)} and + * {@link Model#subjectResource()} instead. + */ + @Deprecated + public static Resource getOptionalSubject(Graph graph, IRI pred, Value obj, Resource... contexts) + throws GraphUtilException + { + Set subjects = getSubjects(graph, pred, obj, contexts); + + if (subjects.isEmpty()) { + return null; + } + else if (subjects.size() == 1) { + return subjects.iterator().next(); + } + else { + throw new GraphUtilException("Multiple " + pred + " properties found"); + } + } + + /** + * Utility method that casts the return value of + * {@link #getOptionalSubject(Graph, IRI, Value, Resource[])} to a URI, or + * throws a GraphUtilException if that value is not a URI. + * + * @return The subject of the matched statement(s), or null if no + * matching statements were found. + * @throws GraphUtilException + * If such an exception is thrown by + * {@link #getOptionalSubject(Graph, IRI, Value, Resource[])} or if + * its return value is not a URI. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...)} and + * {@link Model#subjectIRI()} instead. + */ + @Deprecated + public static IRI getOptionalSubjectURI(Graph graph, IRI pred, Value obj, Resource... contexts) + throws GraphUtilException + { + Resource subject = getOptionalSubject(graph, pred, obj, contexts); + + if (subject == null || subject instanceof IRI) { + return (IRI)subject; + } + else { + throw new GraphUtilException("Expected URI for subject " + subject); + } + } + + /** + * Gets the objects of the statements with the specified subject, predicate + * and (optionally) contexts from the supplied graph. Calling this method is + * equivalent to calling graph.match(subj, pred, null, contexts) and + * extracting the objects of the matching statements from the returned + * iterator. See {@link Graph#match(Resource, IRI, Value, Resource[])} for a + * description of the parameter values. + * + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...)} and + * {@link Model#objects()} instead. + */ + @Deprecated + public static Iterator getObjectIterator(Graph graph, Resource subj, IRI pred, Resource... contexts) + { + Iterator iter = graph.match(subj, pred, null, contexts); + + return new ConvertingIterator(iter) { + + @Override + protected Value convert(Statement st) + throws RuntimeException + { + return st.getObject(); + } + + }; + } + + /** + * Gets the objects of the statements with the specified subject, predicate + * and (optionally) contexts from the supplied graph. Calling this method is + * equivalent to calling graph.match(subj, pred, null, contexts) and + * adding the objects of the matching statements to a set. See + * {@link Graph#match(Resource, IRI, Value, Resource[])} for a description of + * the parameter values. + * + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...)} and + * {@link Model#objects()} instead. + */ + @Deprecated + public static Set getObjects(Graph graph, Resource subj, IRI pred, Resource... contexts) { + Iterator iter = getObjectIterator(graph, subj, pred, contexts); + return Iterators.addAll(iter, new LinkedHashSet()); + } + + /** + * Gets the object of the statement(s) with the specified subject and + * predicate from the specified contexts in the supplied graph. The + * combination of subject, predicate and contexts must match at least one + * statement. In case more than one statement matches -- for example + * statements from multiple contexts -- all these statements should have the + * same object. A {@link GraphUtilException} is thrown if these conditions + * are not met. See {@link Graph#match(Resource, IRI, Value, Resource[])} for + * a description of the parameter values. + * + * @return The object of the matched statement(s). + * @throws GraphUtilException + * If the statements matched by the specified parameters do not have + * exactly one unique object. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...)} and + * {@link Model#objectValue()} instead. + */ + @Deprecated + public static Value getUniqueObject(Graph graph, Resource subj, IRI pred, Resource... contexts) + throws GraphUtilException + { + Set objects = getObjects(graph, subj, pred, contexts); + + if (objects.size() == 1) { + return objects.iterator().next(); + } + else if (objects.isEmpty()) { + throw new GraphUtilException("Missing property: " + pred); + } + else { + throw new GraphUtilException("Multiple " + pred + " properties found"); + } + } + + /** + * Adds the specified statement and makes sure that no other statements are + * present in the Graph with the same subject and predicate. When contexts + * are specified, the (subj, pred) pair will occur exactly once in each + * context, else the (subj, pred) pair will occur exactly once in the entire + * Graph. + * + * @deprecated since 2.8.0. Use + * {@link Models#setProperty(Model, Resource, IRI, Value, Resource...) } + * instead. + */ + @Deprecated + public static void setUniqueObject(Graph graph, Resource subj, IRI pred, Value obj, Resource... contexts) { + Iterator iter = graph.match(subj, pred, null, contexts); + + while (iter.hasNext()) { + iter.next(); + iter.remove(); + } + + graph.add(subj, pred, obj, contexts); + } + + /** + * Utility method that casts the return value of + * {@link #getUniqueObject(Graph, Resource, IRI, Resource[])} to a Resource, + * or throws a GraphUtilException if that value is not a Resource. + * + * @return The object of the matched statement(s). + * @throws GraphUtilException + * If such an exception is thrown by + * {@link #getUniqueObject(Graph, Resource, IRI, Resource[])} or if + * its return value is not a Resource. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...) } and + * {@link Model#objectResource() } instead. + */ + @Deprecated + public static Resource getUniqueObjectResource(Graph graph, Resource subj, IRI pred) + throws GraphUtilException + { + Value obj = getUniqueObject(graph, subj, pred); + + if (obj instanceof Resource) { + return (Resource)obj; + } + else { + throw new GraphUtilException("Expected URI or blank node for property " + pred); + } + } + + /** + * Utility method that casts the return value of + * {@link #getUniqueObject(Graph, Resource, IRI, Resource[])} to a URI, or + * throws a GraphUtilException if that value is not a URI. + * + * @return The object of the matched statement(s). + * @throws GraphUtilException + * If such an exception is thrown by + * {@link #getUniqueObject(Graph, Resource, IRI, Resource[])} or if + * its return value is not a URI. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...) } and + * {@link Model#objectIRI() } instead. + */ + @Deprecated + public static IRI getUniqueObjectURI(Graph graph, Resource subj, IRI pred) + throws GraphUtilException + { + Value obj = getUniqueObject(graph, subj, pred); + + if (obj instanceof IRI) { + return (IRI)obj; + } + else { + throw new GraphUtilException("Expected URI for property " + pred); + } + } + + /** + * Utility method that casts the return value of + * {@link #getUniqueObject(Graph, Resource, IRI, Resource[])} to a Literal, + * or throws a GraphUtilException if that value is not a Literal. + * + * @return The object of the matched statement(s). + * @throws GraphUtilException + * If such an exception is thrown by + * {@link #getUniqueObject(Graph, Resource, IRI, Resource[])} or if + * its return value is not a Literal. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...) } and + * {@link Model#objectLiteral() } instead. + */ + @Deprecated + public static Literal getUniqueObjectLiteral(Graph graph, Resource subj, IRI pred) + throws GraphUtilException + { + Value obj = getUniqueObject(graph, subj, pred); + + if (obj instanceof Literal) { + return (Literal)obj; + } + else { + throw new GraphUtilException("Expected literal for property " + pred); + } + } + + /** + * Gets the object of the statement(s) with the specified subject and + * predicate from the specified contexts in the supplied graph. If the + * combination of subject, predicate and contexts matches one or more + * statements, all these statements should have the same object. A + * {@link GraphUtilException} is thrown if this is not the case. See + * {@link Graph#match(Resource, IRI, Value, Resource[])} for a description of + * the parameter values. + * + * @return The object of the matched statement(s), or null if no + * matching statements were found. + * @throws GraphUtilException + * If the statements matched by the specified parameters have more + * than one unique object. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...) } and + * {@link Model#objectValue() } instead. + */ + @Deprecated + public static Value getOptionalObject(Graph graph, Resource subj, IRI pred, Resource... contexts) + throws GraphUtilException + { + Set objects = getObjects(graph, subj, pred, contexts); + + if (objects.isEmpty()) { + return null; + } + else if (objects.size() == 1) { + return objects.iterator().next(); + } + else { + throw new GraphUtilException("Multiple " + pred + " properties found"); + } + } + + /** + * Utility method that casts the return value of + * {@link #getOptionalObject(Graph, Resource, IRI, Resource[])} to a + * Resource, or throws a GraphUtilException if that value is not a Resource. + * + * @return The object of the matched statement(s), or null if no + * matching statements were found. + * @throws GraphUtilException + * If such an exception is thrown by + * {@link #getOptionalObject(Graph, Resource, IRI, Resource[])} or if + * its return value is not a Resource. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...) } and + * {@link Model#objectResource() } instead. + */ + @Deprecated + public static Resource getOptionalObjectResource(Graph graph, Resource subj, IRI pred) + throws GraphUtilException + { + Value obj = getOptionalObject(graph, subj, pred); + + if (obj == null || obj instanceof Resource) { + return (Resource)obj; + } + else { + throw new GraphUtilException("Expected URI or blank node for property " + pred); + } + } + + /** + * Utility method that casts the return value of + * {@link #getOptionalObject(Graph, Resource, IRI, Resource[])} to a URI, or + * throws a GraphUtilException if that value is not a URI. + * + * @return The object of the matched statement(s), or null if no + * matching statements were found. + * @throws GraphUtilException + * If such an exception is thrown by + * {@link #getOptionalObject(Graph, Resource, IRI, Resource[])} or if + * its return value is not a URI. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...) } and + * {@link Model#objectIRI() } instead. + */ + @Deprecated + public static IRI getOptionalObjectURI(Graph graph, Resource subj, IRI pred) + throws GraphUtilException + { + Value obj = getOptionalObject(graph, subj, pred); + + if (obj == null || obj instanceof IRI) { + return (IRI)obj; + } + else { + throw new GraphUtilException("Expected URI for property " + pred); + } + } + + /** + * Utility method that casts the return value of + * {@link #getOptionalObject(Graph, Resource, IRI, Resource[])} to a Literal, + * or throws a GraphUtilException if that value is not a Literal. + * + * @return The object of the matched statement(s), or null if no + * matching statements were found. + * @throws GraphUtilException + * If such an exception is thrown by + * {@link #getOptionalObject(Graph, Resource, IRI, Resource[])} or if + * its return value is not a Literal. + * @deprecated since 2.8.0. Use + * {@link Model#filter(Resource, IRI, Value, Resource...) } and + * {@link Model#objectLiteral() } instead. + */ + @Deprecated + public static Literal getOptionalObjectLiteral(Graph graph, Resource subj, IRI pred) + throws GraphUtilException + { + Value obj = getOptionalObject(graph, subj, pred); + + if (obj == null || obj instanceof Literal) { + return (Literal)obj; + } + else { + throw new GraphUtilException("Expected literal for property " + pred); + } + } + + /** + * Utility method that removes all statements matching the specified criteria + * from a graph. + * + * @param graph + * The graph to remove the statements from. + * @param subj + * The subject of the statements to match, null to match + * statements with any subject. + * @param pred + * The predicate of the statements to match, null to match + * statements with any predicate. + * @param obj + * The object of the statements to match, null to match + * statements with any object. + * @param contexts + * The contexts of the statements to match. If no contexts are + * specified, statements will match disregarding their context. If one + * or more contexts are specified, statements with a context matching + * one of these will match. + * @throws IllegalArgumentException + * If a null-array is specified as the value for + * contexts. See + * {@link OpenRDFUtil#verifyContextNotNull(Resource[])} for more + * info. + * @deprecated since 2.8.0. Use + * {@link Model#remove(Resource, IRI, Value, Resource...) } + * instead. + */ + @Deprecated + public static void remove(Graph graph, Resource subj, IRI pred, Value obj, Resource... contexts) { + Iterator statements = graph.match(subj, pred, obj, contexts); + while (statements.hasNext()) { + statements.next(); + statements.remove(); + } + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphUtilException.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphUtilException.java new file mode 100644 index 00000000000..313c201e32d --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphUtilException.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import org.eclipse.rdf4j.OpenRDFException; + +/** + * An exception thrown by {@link GraphUtil} when specific conditions are not + * met. + * + * @author Arjohn Kampman + */ +@Deprecated +public class GraphUtilException extends OpenRDFException { + + private static final long serialVersionUID = 3886967415616842867L; + + public GraphUtilException() { + super(); + } + + public GraphUtilException(String message) { + super(message); + } + + public GraphUtilException(Throwable t) { + super(t); + } + + public GraphUtilException(String message, Throwable t) { + super(message, t); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/LexicalValueComparator.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/LexicalValueComparator.java new file mode 100644 index 00000000000..2ee423e3911 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/LexicalValueComparator.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import java.io.Serializable; +import java.util.Comparator; +import java.util.Optional; + +import org.eclipse.rdf4j.common.lang.ObjectUtil; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; + +/** + * A lexical rdf term Comparator, this class does not compare numerically and is + * therefore a bit faster than a SPARQL compliant comparator. + * + * @author james + * @author Arjohn Kampman + */ +public class LexicalValueComparator implements Serializable, Comparator { + + private static final long serialVersionUID = -7055973992568220217L; + + public int compare(Value o1, Value o2) { + // check equality + if (ObjectUtil.nullEquals(o1, o2)) { + return 0; + } + + // 1. (Lowest) no value assigned to the variable + if (o1 == null) { + return -1; + } + if (o2 == null) { + return 1; + } + + // 2. Blank nodes + boolean b1 = o1 instanceof BNode; + boolean b2 = o2 instanceof BNode; + if (b1 && b2) { + return compareBNodes((BNode)o1, (BNode)o2); + } + if (b1) { + return -1; + } + if (b2) { + return 1; + } + + // 3. IRIs + boolean u1 = o1 instanceof IRI; + boolean u2 = o2 instanceof IRI; + if (u1 && u2) { + return compareURIs((IRI)o1, (IRI)o2); + } + if (u1) { + return -1; + } + if (u2) { + return 1; + } + + // 4. RDF literals + return compareLiterals((Literal)o1, (Literal)o2); + } + + private int compareBNodes(BNode leftBNode, BNode rightBNode) { + return leftBNode.getID().compareTo(rightBNode.getID()); + } + + private int compareURIs(IRI leftURI, IRI rightURI) { + return leftURI.toString().compareTo(rightURI.toString()); + } + + private int compareLiterals(Literal leftLit, Literal rightLit) { + // Additional constraint for ORDER BY: "A plain literal is lower + // than an RDF literal with type xsd:string of the same lexical + // form." + int result = 0; + // FIXME: Confirm these rules work with RDF-1.1 + // Sort by datatype first, plain literals come before datatyped literals + IRI leftDatatype = leftLit.getDatatype(); + IRI rightDatatype = rightLit.getDatatype(); + + if (leftDatatype != null) { + if (rightDatatype != null) { + // Both literals have datatypes + result = compareDatatypes(leftDatatype, rightDatatype); + } + else { + result = 1; + } + } + else if (rightDatatype != null) { + result = -1; + } + + if (result == 0) { + // datatypes are equal or both literals are untyped; sort by language + // tags, simple literals come before literals with language tags + Optional leftLanguage = leftLit.getLanguage(); + Optional rightLanguage = rightLit.getLanguage(); + + if (leftLanguage.isPresent()) { + if (rightLanguage.isPresent()) { + result = leftLanguage.get().compareTo(rightLanguage.get()); + } + else { + result = 1; + } + } + else if (rightLanguage.isPresent()) { + result = -1; + } + } + + if (result == 0) { + // Literals are equal as fas as their datatypes and language tags are + // concerned, compare their labels + result = leftLit.getLabel().compareTo(rightLit.getLabel()); + } + + return result; + } + + /** + * Compares two literal datatypes and indicates if one should be ordered + * after the other. This algorithm ensures that compatible ordered datatypes + * (numeric and date/time) are grouped together so that + * {@link QueryEvaluationUtil#compareLiterals(Literal, Literal, CompareOp)} + * is used in consecutive ordering steps. + */ + private int compareDatatypes(IRI leftDatatype, IRI rightDatatype) { + if (XMLDatatypeUtil.isNumericDatatype(leftDatatype)) { + if (XMLDatatypeUtil.isNumericDatatype(rightDatatype)) { + // both are numeric datatypes + return compareURIs(leftDatatype, rightDatatype); + } + else { + return -1; + } + } + else if (XMLDatatypeUtil.isNumericDatatype(rightDatatype)) { + return 1; + } + else if (XMLDatatypeUtil.isCalendarDatatype(leftDatatype)) { + if (XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) { + // both are calendar datatypes + return compareURIs(leftDatatype, rightDatatype); + } + else { + return -1; + } + } + else if (XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) { + return 1; + } + else { + // incompatible or unordered datatypes + return compareURIs(leftDatatype, rightDatatype); + } + } +} \ No newline at end of file diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/LiteralUtil.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/LiteralUtil.java new file mode 100644 index 00000000000..d9b19799681 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/LiteralUtil.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import org.eclipse.rdf4j.model.Literal; + +/** + * Various utility methods related to {@link Literal}. + * + * @author Arjohn Kampman + * @deprecated Use {@link Literals} instead. + */ +@Deprecated +public final class LiteralUtil extends Literals { + + protected LiteralUtil() { + // Protected default constructor to prevent instantiation + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/LiteralUtilException.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/LiteralUtilException.java new file mode 100644 index 00000000000..aea43b110d7 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/LiteralUtilException.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import org.eclipse.rdf4j.OpenRDFException; + +/** + * An exception thrown by {@link Literals} when specific conditions are not + * met. + * + * @author Peter Ansell + */ +public class LiteralUtilException extends OpenRDFException { + + private static final long serialVersionUID = 9075761346909805423L; + + public LiteralUtilException() { + super(); + } + + public LiteralUtilException(String message) { + super(message); + } + + public LiteralUtilException(Throwable t) { + super(t); + } + + public LiteralUtilException(String message, Throwable t) { + super(message, t); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/Literals.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Literals.java new file mode 100644 index 00000000000..ad722ec11d2 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Literals.java @@ -0,0 +1,616 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; +import java.util.Locale; +import java.util.Objects; +import java.util.Optional; + +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.util.language.LanguageTag; +import org.eclipse.rdf4j.model.util.language.LanguageTagSyntaxException; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; + +/** + * Various utility methods related to {@link Literal}. + * + * @author Arjohn Kampman + * @author Peter Ansell + */ +public class Literals { + + /** + * Gets the label of the supplied literal. The fallback value is returned in + * case the supplied literal is null. + * + * @param l + * The literal to get the label for. + * @param fallback + * The value to fall back to in case the supplied literal is + * null. + * @return Either the literal's label, or the fallback value. + */ + public static String getLabel(Literal l, String fallback) { + return l != null ? l.getLabel() : fallback; + } + + /** + * Returns the result of {@link #getLabel(Literal, String) + * getLabel((Literal)v, fallback} in case the supplied value is a literal, + * returns the fallback value otherwise. + */ + public static String getLabel(Value v, String fallback) { + return v instanceof Literal ? getLabel((Literal)v, fallback) : fallback; + } + + /** + * Gets the byte value of the supplied literal. The fallback value is + * returned in case {@link Literal#byteValue()} throws a + * {@link NumberFormatException}. + * + * @param l + * The literal to get the byte value for. + * @param fallback + * The value to fall back to in case no byte value could gotten from + * the literal. + * @return Either the literal's byte value, or the fallback value. + */ + public static byte getByteValue(Literal l, byte fallback) { + try { + return l.byteValue(); + } + catch (NumberFormatException e) { + return fallback; + } + } + + /** + * Returns the result of {@link #getByteValue(Literal, byte) + * getByteValue((Literal)value, fallback)} in case the supplied value is a + * literal, returns the fallback value otherwise. + */ + public static byte getByteValue(Value v, byte fallback) { + if (v instanceof Literal) { + return getByteValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Gets the short value of the supplied literal. The fallback value is + * returned in case {@link Literal#shortValue()} throws a + * {@link NumberFormatException}. + * + * @param l + * The literal to get the short value for. + * @param fallback + * The value to fall back to in case no short value could gotten from + * the literal. + * @return Either the literal's short value, or the fallback value. + */ + public static short getShortValue(Literal l, short fallback) { + try { + return l.shortValue(); + } + catch (NumberFormatException e) { + return fallback; + } + } + + /** + * Returns the result of {@link #getShortValue(Literal, short) + * getShortValue((Literal)value, fallback)} in case the supplied value is a + * literal, returns the fallback value otherwise. + */ + public static short getShortValue(Value v, short fallback) { + if (v instanceof Literal) { + return getShortValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Gets the int value of the supplied literal. The fallback value is returned + * in case {@link Literal#intValue()} throws a {@link NumberFormatException}. + * + * @param l + * The literal to get the int value for. + * @param fallback + * The value to fall back to in case no int value could gotten from + * the literal. + * @return Either the literal's int value, or the fallback value. + */ + public static int getIntValue(Literal l, int fallback) { + try { + return l.intValue(); + } + catch (NumberFormatException e) { + return fallback; + } + } + + /** + * Returns the result of {@link #getIntValue(Literal, int) + * getIntValue((Literal)value, fallback)} in case the supplied value is a + * literal, returns the fallback value otherwise. + */ + public static int getIntValue(Value v, int fallback) { + if (v instanceof Literal) { + return getIntValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Gets the long value of the supplied literal. The fallback value is + * returned in case {@link Literal#longValue()} throws a + * {@link NumberFormatException}. + * + * @param l + * The literal to get the long value for. + * @param fallback + * The value to fall back to in case no long value could gotten from + * the literal. + * @return Either the literal's long value, or the fallback value. + */ + public static long getLongValue(Literal l, long fallback) { + try { + return l.longValue(); + } + catch (NumberFormatException e) { + return fallback; + } + } + + /** + * Returns the result of {@link #getLongValue(Literal, long) + * getLongValue((Literal)value, fallback)} in case the supplied value is a + * literal, returns the fallback value otherwise. + */ + public static long getLongValue(Value v, long fallback) { + if (v instanceof Literal) { + return getLongValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Gets the integer value of the supplied literal. The fallback value is + * returned in case {@link Literal#integerValue()} throws a + * {@link NumberFormatException}. + * + * @param l + * The literal to get the integer value for. + * @param fallback + * The value to fall back to in case no integer value could gotten + * from the literal. + * @return Either the literal's integer value, or the fallback value. + */ + public static BigInteger getIntegerValue(Literal l, BigInteger fallback) { + try { + return l.integerValue(); + } + catch (NumberFormatException e) { + return fallback; + } + } + + /** + * Returns the result of {@link #getIntegerValue(Literal, BigInteger) + * getIntegerValue((Literal)value, fallback)} in case the supplied value is a + * literal, returns the fallback value otherwise. + */ + public static BigInteger getIntegerValue(Value v, BigInteger fallback) { + if (v instanceof Literal) { + return getIntegerValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Gets the decimal value of the supplied literal. The fallback value is + * returned in case {@link Literal#decimalValue()} throws a + * {@link NumberFormatException}. + * + * @param l + * The literal to get the decimal value for. + * @param fallback + * The value to fall back to in case no decimal value could gotten + * from the literal. + * @return Either the literal's decimal value, or the fallback value. + */ + public static BigDecimal getDecimalValue(Literal l, BigDecimal fallback) { + try { + return l.decimalValue(); + } + catch (NumberFormatException e) { + return fallback; + } + } + + /** + * Returns the result of {@link #getDecimalValue(Literal, BigDecimal) + * getDecimalValue((Literal)value, fallback)} in case the supplied value is a + * literal, returns the fallback value otherwise. + */ + public static BigDecimal getDecimalValue(Value v, BigDecimal fallback) { + if (v instanceof Literal) { + return getDecimalValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Gets the float value of the supplied literal. The fallback value is + * returned in case {@link Literal#floatValue()} throws a + * {@link NumberFormatException}. + * + * @param l + * The literal to get the float value for. + * @param fallback + * The value to fall back to in case no float value could gotten from + * the literal. + * @return Either the literal's float value, or the fallback value. + */ + public static float getFloatValue(Literal l, float fallback) { + try { + return l.floatValue(); + } + catch (NumberFormatException e) { + return fallback; + } + } + + /** + * Returns the result of {@link #getFloatValue(Literal, float) + * getFloatValue((Literal)value, fallback)} in case the supplied value is a + * literal, returns the fallback value otherwise. + */ + public static float getFloatValue(Value v, float fallback) { + if (v instanceof Literal) { + return getFloatValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Gets the double value of the supplied literal. The fallback value is + * returned in case {@link Literal#doubleValue()} throws a + * {@link NumberFormatException}. + * + * @param l + * The literal to get the double value for. + * @param fallback + * The value to fall back to in case no double value could gotten from + * the literal. + * @return Either the literal's double value, or the fallback value. + */ + public static double getDoubleValue(Literal l, double fallback) { + try { + return l.doubleValue(); + } + catch (NumberFormatException e) { + return fallback; + } + } + + /** + * Returns the result of {@link #getDoubleValue(Literal, double) + * getDoubleValue((Literal)value, fallback)} in case the supplied value is a + * literal, returns the fallback value otherwise. + */ + public static double getDoubleValue(Value v, double fallback) { + if (v instanceof Literal) { + return getDoubleValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Gets the boolean value of the supplied literal. The fallback value is + * returned in case {@link Literal#booleanValue()} throws a + * {@link NumberFormatException}. + * + * @param l + * The literal to get the boolean value for. + * @param fallback + * The value to fall back to in case no boolean value could gotten + * from the literal. + * @return Either the literal's boolean value, or the fallback value. + */ + public static boolean getBooleanValue(Literal l, boolean fallback) { + try { + return l.booleanValue(); + } + catch (IllegalArgumentException e) { + return fallback; + } + } + + /** + * Returns the result of {@link #getBooleanValue(Literal, boolean) + * getBooleanValue((Literal)value, fallback)} in case the supplied value is a + * literal, returns the fallback value otherwise. + */ + public static boolean getBooleanValue(Value v, boolean fallback) { + if (v instanceof Literal) { + return getBooleanValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Gets the calendar value of the supplied literal. The fallback value is + * returned in case {@link Literal#calendarValue()} throws a + * {@link NumberFormatException}. + * + * @param l + * The literal to get the calendar value for. + * @param fallback + * The value to fall back to in case no calendar value could gotten + * from the literal. + * @return Either the literal's calendar value, or the fallback value. + */ + public static XMLGregorianCalendar getCalendarValue(Literal l, XMLGregorianCalendar fallback) { + try { + return l.calendarValue(); + } + catch (IllegalArgumentException e) { + return fallback; + } + } + + /** + * Returns the result of + * {@link #getCalendarValue(Literal, XMLGregorianCalendar) + * getCalendarValue((Literal)value, fallback)} in case the supplied value is + * a literal, returns the fallback value otherwise. + */ + public static XMLGregorianCalendar getCalendarValue(Value v, XMLGregorianCalendar fallback) { + if (v instanceof Literal) { + return getCalendarValue((Literal)v, fallback); + } + else { + return fallback; + } + } + + /** + * Determine the Locale from a literal's language tag, as specified by RFC + * 3166. Note that RFC 3166 isn't fully covered by the current (JSE 6) + * implementation of java.util.Locale. Therefore, this method will only + * return a specific locale for language tags that comply with the Locale + * API, i.e. those that contain an ISO639 language, an optional ISO3166 + * country and an optional variant. In all other cases (i.e. if an error + * occurs or the language tag represents an IANA-registred language tag), the + * fallback value will be returned. + * + * @param l + * the literal + * @param fallback + * a fallback value for the locale + * @return the Locale, or the fallback if a suitable Locale could not be + * constructed for the language tag. + * @see RFC 3066 + */ + public static Locale getLocale(Literal l, Locale fallback) { + Locale result = fallback; + + try { + Optional lang = l.getLanguage(); + if (lang.isPresent()) { + LanguageTag tag = new LanguageTag(lang.get()); + result = tag.toLocale(); + } + } + catch (LanguageTagSyntaxException e) { + result = fallback; + } + + return result; + } + + /** + * Creates a typed {@link Literal} out of the supplied object, mapping the + * runtime type of the object to the appropriate XML Schema type. If no + * mapping is available, the method returns a literal with the string + * representation of the supplied object as the value, and + * {@link XMLSchema#STRING} as the datatype. Recognized types are + * {@link Boolean}, {@link Byte}, {@link Double}, {@link Float}, + * {@link Integer}, {@link Long}, {@link Short}, {@link XMLGregorianCalendar } + * , and {@link Date}. + * + * @param valueFactory + * @param object + * an object to be converted to a typed literal. + * @return a typed literal representation of the supplied object. + * @throws NullPointerException + * If the object was null. + * @since 2.7.0 + */ + public static Literal createLiteral(ValueFactory valueFactory, Object object) { + try { + return createLiteral(valueFactory, object, false); + } + catch (LiteralUtilException e) { + // This should not happen by design + throw new IllegalStateException(e); + } + } + + /** + * Creates a typed {@link Literal} out of the supplied object, mapping the + * runtime type of the object to the appropriate XML Schema type. If no + * mapping is available, the method throws a {@link LiteralUtilException}. + * Recognized types are {@link Boolean}, {@link Byte}, {@link Double}, + * {@link Float}, {@link Integer}, {@link Long}, {@link Short}, + * {@link XMLGregorianCalendar } , and {@link Date}. + * + * @param valueFactory + * @param object + * an object to be converted to a typed literal. + * @return a typed literal representation of the supplied object. + * @throws LiteralUtilException + * If the literal could not be created. + * @throws NullPointerException + * If the object was null. + * @since 2.7.0 + */ + public static Literal createLiteralOrFail(ValueFactory valueFactory, Object object) + throws LiteralUtilException + { + return createLiteral(valueFactory, object, true); + } + + /** + * Creates a typed {@link Literal} out of the supplied object, mapping the + * runtime type of the object to the appropriate XML Schema type. If no + * mapping is available, the method throws an exception if the boolean + * parameter is true, or if it is false it returns a literal with the string + * representation of the supplied object as the value, and + * {@link XMLSchema#STRING} as the datatype. Recognized types are + * {@link Boolean}, {@link Byte}, {@link Double}, {@link Float}, + * {@link Integer}, {@link Long}, {@link Short}, {@link XMLGregorianCalendar } + * , and {@link Date}. + * + * @param valueFactory + * The {@link ValueFactory} to use when creating the result. + * @param object + * an object to be converted to a typed literal. + * @param throwExceptionOnFailure + * If true throws a {@link LiteralUtilException} when the object is + * not recognised. If false it returns a string typed literal based on + * the objects toString method. + * @return a typed literal representation of the supplied object. + * @throws LiteralUtilException + * If the literal could not be created. + * @throws NullPointerException + * If the object was null. + * @since 2.7.0 + */ + private static Literal createLiteral(ValueFactory valueFactory, Object object, + boolean throwExceptionOnFailure) + throws LiteralUtilException + { + if (object == null) { + throw new NullPointerException("Cannot create a literal from a null"); + } + + if (object instanceof Boolean) { + return valueFactory.createLiteral(((Boolean)object).booleanValue()); + } + else if (object instanceof Byte) { + return valueFactory.createLiteral(((Byte)object).byteValue()); + } + else if (object instanceof Double) { + return valueFactory.createLiteral(((Double)object).doubleValue()); + } + else if (object instanceof Float) { + return valueFactory.createLiteral(((Float)object).floatValue()); + } + else if (object instanceof Integer) { + return valueFactory.createLiteral(((Integer)object).intValue()); + } + else if (object instanceof Long) { + return valueFactory.createLiteral(((Long)object).longValue()); + } + else if (object instanceof Short) { + return valueFactory.createLiteral(((Short)object).shortValue()); + } + else if (object instanceof XMLGregorianCalendar) { + return valueFactory.createLiteral((XMLGregorianCalendar)object); + } + else if (object instanceof Date) { + return valueFactory.createLiteral((Date)object); + } + else if (object instanceof String) { + return valueFactory.createLiteral(object.toString(), XMLSchema.STRING); + } + else { + if (throwExceptionOnFailure) { + throw new LiteralUtilException("Did not recognise object when creating literal"); + } + return valueFactory.createLiteral(object.toString(), XMLSchema.STRING); + } + } + + /** + * Helper method for determining whether a literal could be created from an + * object using a {@link ValueFactory}. + * + * @param object + * an object to check for the possibility of being converted to a + * typed literal. + * @return True if a literal could be created from the given object, based + * solely on its type and the methods available on the + * {@link ValueFactory} interface and false otherwise. Returns false + * if the object is null. + * @since 2.7.0 + */ + public static boolean canCreateLiteral(Object object) { + if (object == null) { + // Cannot create a literal from a null + // Avoid throwing a NullPointerException here to enable universal usage + // of this method + return false; + } + + if (object instanceof Boolean || object instanceof Byte || object instanceof Double + || object instanceof Float || object instanceof Integer || object instanceof Long + || object instanceof Short || object instanceof XMLGregorianCalendar || object instanceof Date + || object instanceof String) + { + return true; + } + + return false; + } + + /** + * Helper method to determine whether a literal is a language literal, and + * not a typed literal. + * + * @param literal + * The literal to check + * @return True if the literal has a language tag attached to it and false + * otherwise. + * @since 2.8.0 + */ + public static boolean isLanguageLiteral(Literal literal) { + return Objects.requireNonNull(literal, "Literal cannot be null").getLanguage().isPresent(); + } + + protected Literals() { + // Protected default constructor to prevent instantiation + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelException.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelException.java new file mode 100644 index 00000000000..2c49c0c56d2 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelException.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Value; + +/** + * An exception thrown by {@link Model} and {@link org.eclipse.rdf4j.model.util.Models Models} when specific + * conditions are not met. + * + * @author Arjohn Kampman + */ +public class ModelException extends RuntimeException { + + private static final long serialVersionUID = 3886967415616842867L; + + public ModelException(Value value) { + this("Unexpected object term: " + value); + } + + public ModelException(Value v1, Value v2) { + this(buildMessage(v1, v2)); + } + + public ModelException(String message, Throwable cause) { + super(message, cause); + } + + public ModelException(String message) { + super(message); + } + + public ModelException(Throwable cause) { + super(cause); + } + + private static String buildMessage(Value v1, Value v2) { + StringBuilder sb = new StringBuilder(); + if (!v1.toString().equals(v2.toString())) { + sb.append("Object is both "); + sb.append(v1.toString()); + sb.append(" and "); + sb.append(v2.toString()); + } else if (!v1.getClass().getName().equals(v2.getClass().getName())) { + sb.append("Object is both "); + sb.append("a "); + sb.append(v1.getClass().getName()); + sb.append(" and a "); + sb.append(v2.getClass().getName()); + } else { + sb.append("Object is "); + sb.append(v1); + sb.append(" twice!? (store maybe corrupt)"); + } + return sb.toString(); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelUtil.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelUtil.java new file mode 100644 index 00000000000..6e46da60fbe --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelUtil.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + + +/** + * Utility functions for working with {@link org.eclipse.rdf4j.model.Model}s and other statement collections. + * + * @author Jeen Broekstra + * @deprecated since 2.8.0. Use {@link Models} instead. + */ +@Deprecated +public class ModelUtil extends Models { + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/Models.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Models.java new file mode 100644 index 00000000000..c4aecc0472f --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Models.java @@ -0,0 +1,576 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.util.iterators.Iterators; + +/** + * Utility functions for working with {@link Model}s and other {@link Statement} + * collections. + * + * @author Jeen Broekstra + * @author Arjohn Kampman + * @since 2.8.0 + * @see org.eclipse.rdf4j.model.Model + */ +public class Models { + + /* + * hidden constructor to avoid instantiation + */ + protected Models() { + } + + /** + * Retrieves an object {@link Value} from the statements in the given model. + * If more than one possible object value exists, any one value is picked and + * returned. + * + * @param m + * the model from which to retrieve an object value. + * @return an object value from the given model, or {@link Optional#empty()} + * if no such value exists. + * @since 4.0 + */ + public static Optional object(Model m) { + return m.stream().map(st -> st.getObject()).findAny(); + } + + /** + * @deprecated since 4.0. Use {@link #object(Model)} instead. + */ + @Deprecated + public static Value anyObject(Model m) { + return object(m).orElse(null); + } + + /** + * Retrieves an object {@link Literal} value from the statements in the given + * model. If more than one possible Literal value exists, any one Literal + * value is picked and returned. + * + * @param m + * the model from which to retrieve an object Literal value. + * @return an object Literal value from the given model, or + * {@link Optional#empty()} if no such value exists. + * @since 4.0 + */ + public static Optional objectLiteral(Model m) { + return m.stream().map(st -> st.getObject()).filter(o -> o instanceof Literal).map(l -> (Literal)l).findAny(); + } + + /** + * @deprecated since 4.0. Use {@link #objectLiteral(Model)} instead. + */ + @Deprecated + public static Literal anyObjectLiteral(Model m) { + return objectLiteral(m).orElse(null); + } + + /** + * Retrieves an object {@link Resource} value from the statements in the + * given model. If more than one possible Resource value exists, any one + * Resource value is picked and returned. + * + * @param m + * the model from which to retrieve an object Resource value. + * @return an {@link Optional} object Resource value from the given model, + * which will be {@link Optional#empty() empty} if no such value + * exists. + * @since 4.0 + */ + public static Optional objectResource(Model m) { + return m.stream().map(st -> st.getObject()).filter(o -> o instanceof Resource).map(r -> (Resource)r).findAny(); + } + + /** + * @deprecated since 4.0. Use {@link #objectResource(Model)} instead. + */ + @Deprecated + public static Resource anyObjectResource(Model m) { + return objectResource(m).orElse(null); + } + + /** + * Retrieves an object {@link IRI} value from the statements in the given + * model. If more than one possible IRI value exists, any one value is picked + * and returned. + * + * @param m + * the model from which to retrieve an object IRI value. + * @return an {@link Optional} object IRI value from the given model, which + * will be {@link Optional#empty() empty} if no such value exists. + * @since 4.0 + */ + public static Optional objectIRI(Model m) { + return m.stream().map(st -> st.getObject()).filter(o -> o instanceof IRI).map(r -> (IRI)r).findAny(); + } + + /** + * Retrieves an object value as a String from the statements in the given + * model. If more than one possible object value exists, any one value is picked + * and returned. + * + * @param m + * the model from which to retrieve an object String value. + * @return an {@link Optional} object String value from the given model, which + * will be {@link Optional#empty() empty} if no such value exists. + * @since 4.0 + */ + public static Optional objectString(Model m) { + return m.stream().map(st -> st.getObject().stringValue()).findAny(); + } + + /** + * @deprecated since 4.0. Use {@link #objectIRI(Model)} instead. + */ + @Deprecated + public static URI anyObjectURI(Model m) { + return objectIRI(m).orElse(null); + } + + /** + * Retrieves a subject {@link Resource} from the statements in the given + * model. If more than one possible resource value exists, any one resource + * value is picked and returned. + * + * @param m + * the model from which to retrieve a subject Resource. + * @return an {@link Optional} subject resource from the given model, which + * will be {@link Optional#empty() empty} if no such value exists. + * @since 4.0 + */ + public static Optional subject(Model m) { + return m.stream().map(st -> st.getSubject()).findAny(); + } + + /** + * @deprecated since 4.0. Use {@link #subject(Model)} instead. + */ + @Deprecated + public static Resource anySubject(Model m) { + return subject(m).orElse(null); + } + + /** + * Retrieves a subject {@link IRI} from the statements in the given model. If + * more than one possible IRI value exists, any one IRI value is picked and + * returned. + * + * @param m + * the model from which to retrieve a subject IRI value. + * @return an {@link Optional} subject IRI value from the given model, which + * will be {@link Optional#empty() empty} if no such value exists. + */ + public static Optional subjectIRI(Model m) { + return m.stream().map(st -> st.getSubject()).filter(s -> s instanceof IRI).map(s -> (IRI)s).findAny(); + } + + /** + * @deprecated since 4.0. Use {@link #subjectIRI(Model)} instead. + */ + @Deprecated + public static URI anySubjectURI(Model m) { + return subjectIRI(m).orElse(null); + } + + /** + * Retrieves a subject {@link BNode} from the statements in the given model. + * If more than one possible blank node value exists, any one blank node + * value is picked and returned. + * + * @param m + * the model from which to retrieve a subject BNode value. + * @return an {@link Optional} subject BNode value from the given model, + * which will be {@link Optional#empty() empty} if no such value + * exists. + * @since 4.0 + */ + public static Optional subjectBNode(Model m) { + return m.stream().map(st -> st.getSubject()).filter(s -> s instanceof BNode).map(s -> (BNode)s).findAny(); + } + + /** + * @deprecated since 4.0. Use {@link #subjectBNode(Model)} instead. + */ + @Deprecated + public static BNode anySubjectBNode(Model m) { + return subjectBNode(m).orElse(null); + } + + /** + * Retrieves a predicate from the statements in the given model. If more than + * one possible predicate value exists, any one value is picked and returned. + * + * @param m + * the model from which to retrieve a predicate value. + * @return an {@link Optional} predicate value from the given model, which + * will be {@link Optional#empty() empty} if no such value exists. + * @since 4.0 + */ + public static Optional predicate(Model m) { + return m.stream().map(st -> st.getPredicate()).findAny(); + } + + /** + * @deprecated since 4.0. Use {@link #predicate(Model)} instead. + */ + @Deprecated + public static URI anyPredicate(Model m) { + return predicate(m).orElse(null); + } + + /** + * Sets the property value for the given subject to the given object value, + * replacing any existing value(s) for the subject's property. This method + * updates the original input Model and then returns that same Model object. + * + * @param m + * the model in which to set the property value. May not be null. + * @param subject + * the subject for which to set/replace the property value. May not be + * null. + * @param property + * the property for which to set/replace the value. May not be null. + * @param value + * the value to set for the given subject and property. May not be + * null. + * @param contexts + * the context(s) in which to set/replace the property value. Optional + * vararg argument. If not specified the operations works on the + * entire Model. + * @return the Model object, containing the updated property value. + * @since 2.8.0 + */ + public static Model setProperty(Model m, Resource subject, IRI property, Value value, + Resource... contexts) + { + Objects.requireNonNull(m, "model may not be null"); + Objects.requireNonNull(subject, "subject may not be null"); + Objects.requireNonNull(property, "property may not be null"); + Objects.requireNonNull(value, "value may not be null"); + + if (m.contains(subject, property, null, contexts)) { + m.remove(subject, property, null, contexts); + } + m.add(subject, property, value, contexts); + return m; + } + + /** + * Compares two RDF models, and returns true if they consist of + * isomorphic graphs and the isomorphic graph identifiers map 1:1 to each + * other. RDF graphs are isomorphic graphs if statements from one graphs can + * be mapped 1:1 on to statements in the other graphs. In this mapping, blank + * nodes are not considered mapped when having an identical internal id, but + * are mapped from one graph to the other by looking at the statements in + * which the blank nodes occur. + *

    + * A Model can consist of more than one graph (denoted by context + * identifiers). Two models are considered isomorphic if for each of the + * graphs in one model, an isomorphic graph exists in the other model, and + * the context identifiers of these graphs are either identical or (in the + * case of blank nodes) map 1:1 on each other. + * + * @see RDF + * Concepts & Abstract Syntax, section 3.6 (Graph Comparison) + * @since 2.8.0 + */ + public static boolean isomorphic(Iterable model1, + Iterable model2) + { + Set set1 = toSet(model1); + Set set2 = toSet(model2); + // Compare the number of statements in both sets + if (set1.size() != set2.size()) { + return false; + } + + return isSubsetInternal(set1, set2); + } + + /** + * Compares two RDF models, defined by two statement collections, and returns + * true if they are equal. Models are equal if they contain the same + * set of statements. Blank node IDs are not relevant for model equality, + * they are mapped from one model to the other by using the attached + * properties. + * + * @deprecated since 2.8.0. Use {@link Models#isomorphic(Iterable, Iterable)} + * instead. + */ + @Deprecated + public static boolean equals(Iterable model1, Iterable model2) { + return isomorphic(model1, model2); + } + + /** + * Compares two RDF models, and returns true if the first model is a + * subset of the second model, using graph isomorphism to map statements + * between models. + */ + public static boolean isSubset(Iterable model1, + Iterable model2) + { + // Filter duplicates + Set set1 = toSet(model1); + Set set2 = toSet(model2); + + return isSubset(set1, set2); + } + + /** + * Compares two RDF models, and returns true if the first model is a + * subset of the second model, using graph isomorphism to map statements + * between models. + */ + public static boolean isSubset(Set model1, Set model2) { + // Compare the number of statements in both sets + if (model1.size() > model2.size()) { + return false; + } + + return isSubsetInternal(model1, model2); + } + + private static boolean isSubsetInternal(Set model1, Set model2) { + // try to create a full blank node mapping + return matchModels(model1, model2); + } + + private static boolean matchModels(Set model1, Set model2) { + // Compare statements without blank nodes first, save the rest for later + List model1BNodes = new ArrayList(model1.size()); + + for (Statement st : model1) { + if (st.getSubject() instanceof BNode || st.getObject() instanceof BNode + || st.getContext() instanceof BNode) + { + model1BNodes.add(st); + } + else { + if (!model2.contains(st)) { + return false; + } + } + } + + return matchModels(model1BNodes, model2, new HashMap(), 0); + } + + /** + * A recursive method for finding a complete mapping between blank nodes in + * model1 and blank nodes in model2. The algorithm does a depth-first search + * trying to establish a mapping for each blank node occurring in model1. + * + * @param model1 + * @param model2 + * @param bNodeMapping + * @param idx + * @return true if a complete mapping has been found, false otherwise. + */ + private static boolean matchModels(List model1, Iterable model2, + Map bNodeMapping, int idx) + { + boolean result = false; + + if (idx < model1.size()) { + Statement st1 = model1.get(idx); + + List matchingStats = findMatchingStatements(st1, model2, bNodeMapping); + + for (Statement st2 : matchingStats) { + // Map bNodes in st1 to bNodes in st2 + Map newBNodeMapping = new HashMap(bNodeMapping); + + if (st1.getSubject() instanceof BNode && st2.getSubject() instanceof BNode) { + newBNodeMapping.put((BNode)st1.getSubject(), (BNode)st2.getSubject()); + } + + if (st1.getObject() instanceof BNode && st2.getObject() instanceof BNode) { + newBNodeMapping.put((BNode)st1.getObject(), (BNode)st2.getObject()); + } + + if (st1.getContext() instanceof BNode && st2.getContext() instanceof BNode) { + newBNodeMapping.put((BNode)st1.getContext(), (BNode)st2.getContext()); + } + + // FIXME: this recursive implementation has a high risk of + // triggering a stack overflow + + // Enter recursion + result = matchModels(model1, model2, newBNodeMapping, idx + 1); + + if (result == true) { + // models match, look no further + break; + } + } + } + else { + // All statements have been mapped successfully + result = true; + } + + return result; + } + + private static List findMatchingStatements(Statement st, Iterable model, + Map bNodeMapping) + { + List result = new ArrayList(); + + for (Statement modelSt : model) { + if (statementsMatch(st, modelSt, bNodeMapping)) { + // All components possibly match + result.add(modelSt); + } + } + + return result; + } + + private static boolean statementsMatch(Statement st1, Statement st2, Map bNodeMapping) { + IRI pred1 = st1.getPredicate(); + IRI pred2 = st2.getPredicate(); + + if (!pred1.equals(pred2)) { + // predicates don't match + return false; + } + + Resource subj1 = st1.getSubject(); + Resource subj2 = st2.getSubject(); + + if (subj1 instanceof BNode && subj2 instanceof BNode) { + BNode mappedBNode = bNodeMapping.get(subj1); + + if (mappedBNode != null) { + // bNode 'subj1' was already mapped to some other bNode + if (!subj2.equals(mappedBNode)) { + // 'subj1' and 'subj2' do not match + return false; + } + } + else { + // 'subj1' was not yet mapped. we need to check if 'subj2' is a + // possible mapping candidate + if (bNodeMapping.containsValue(subj2)) { + // 'subj2' is already mapped to some other value. + return false; + } + } + } + else { + // subjects are not (both) bNodes + if (!subj1.equals(subj2)) { + return false; + } + } + + Value obj1 = st1.getObject(); + Value obj2 = st2.getObject(); + + if (obj1 instanceof BNode && obj2 instanceof BNode) { + BNode mappedBNode = bNodeMapping.get(obj1); + + if (mappedBNode != null) { + // bNode 'obj1' was already mapped to some other bNode + if (!obj2.equals(mappedBNode)) { + // 'obj1' and 'obj2' do not match + return false; + } + } + else { + // 'obj1' was not yet mapped. we need to check if 'obj2' is a + // possible mapping candidate + if (bNodeMapping.containsValue(obj2)) { + // 'obj2' is already mapped to some other value. + return false; + } + } + } + else { + // objects are not (both) bNodes + if (!obj1.equals(obj2)) { + return false; + } + } + + Resource context1 = st1.getContext(); + Resource context2 = st2.getContext(); + + // no match if in different contexts + if (context1 == null) { + return context2 == null; + } + else if (context2 == null) { + return false; + } + + if (context1 instanceof BNode && context2 instanceof BNode) { + BNode mappedBNode = bNodeMapping.get(context1); + + if (mappedBNode != null) { + // bNode 'context1' was already mapped to some other bNode + if (!context2.equals(mappedBNode)) { + // 'context1' and 'context2' do not match + return false; + } + } + else { + // 'context1' was not yet mapped. we need to check if 'context2' is + // a + // possible mapping candidate + if (bNodeMapping.containsValue(context2)) { + // 'context2' is already mapped to some other value. + return false; + } + } + } + else { + // contexts are not (both) bNodes + if (!context1.equals(context1)) { + return false; + } + } + + return true; + } + + private static Set toSet(Iterable iterable) { + Set set = null; + if (iterable instanceof Set) { + set = (Set)iterable; + } + else { + // Filter duplicates + set = new HashSet(); + Iterators.addAll(iterable.iterator(), set); + } + return set; + } +} \ No newline at end of file diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/Namespaces.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Namespaces.java new file mode 100644 index 00000000000..4d3742d69e0 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Namespaces.java @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import java.util.AbstractMap; +import java.util.AbstractMap.SimpleImmutableEntry; + +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * A utility class to perform operations on {@link Namespace}s. + * + * @author Peter Ansell + * @since 2.7.0 + */ +public class Namespaces { + + /** + * Converts a set of {@link Namespace}s into a map containing the + * {@link Namespace#getPrefix()} strings as keys, with the + * {@link Namespace#getName()} strings as values in the map for each + * namespace in the given set. + * + * @param namespaces + * The {@link Set} of {@link Namespace}s to transform. + * @return A {@link Map} of {@link String} to {@link String} where the + * key/value combinations are created based on the prefix and names + * from {@link Namespace}s in the input set. + * @since 2.7.0 + */ + public static Map asMap(Set namespaces) { + Map result = new HashMap(); + + for (Namespace nextNamespace : namespaces) { + result.put(nextNamespace.getPrefix(), nextNamespace.getName()); + } + + return result; + } + + /** + * Wraps the given {@link Set} of {@link Namespace}s as a {@link Map} of + * prefix to URI mappings, so that it can be used where a {@link Map} is + * required by the API.
    + * NOTE: The Map returned by this method is not synchronized. + * + * @param namespaces + * The Set to wrap. + * @return A Map of prefix to URI mappings which is backed by the given Set + * of {@link Namespace}s. + * @since 2.7.10 + */ + public static Map wrap(final Set namespaces) { + return new Map() { + + @Override + public void clear() { + namespaces.clear(); + } + + @Override + public boolean containsKey(Object nextKey) { + if (nextKey instanceof String) { + for (Namespace nextNamespace : namespaces) { + if (nextNamespace.getPrefix().equals(nextKey)) { + return true; + } + } + } + return false; + } + + @Override + public boolean containsValue(Object nextValue) { + if (nextValue instanceof String) { + for (Namespace nextNamespace : namespaces) { + if (nextNamespace.getName().equals(nextValue)) { + return true; + } + } + } + return false; + } + + /** + * NOTE: This entry set is immutable, and does not update the internal + * set through its iterator. + */ + @Override + public Set> entrySet() { + Set> result = new LinkedHashSet>(); + for (Namespace nextNamespace : namespaces) { + AbstractMap.SimpleImmutableEntry nextEntry = new SimpleImmutableEntry( + nextNamespace.getPrefix(), nextNamespace.getName()); + result.add(nextEntry); + } + return Collections.unmodifiableSet(result); + } + + @Override + public String get(Object nextKey) { + if (nextKey instanceof String) { + for (Namespace nextNamespace : namespaces) { + if (nextNamespace.getPrefix().equals(nextKey)) { + return nextNamespace.getName(); + } + } + } + return null; + } + + @Override + public boolean isEmpty() { + return namespaces.isEmpty(); + } + + @Override + public Set keySet() { + Set result = new LinkedHashSet(); + for (Namespace nextNamespace : namespaces) { + result.add(nextNamespace.getPrefix()); + } + return result; + } + + @Override + public String put(String nextKey, String nextValue) { + String result = null; + for (Namespace nextNamespace : new LinkedHashSet(namespaces)) { + if (nextNamespace.getPrefix().equals(nextKey)) { + result = nextNamespace.getName(); + namespaces.remove(nextNamespace); + } + } + namespaces.add(new SimpleNamespace(nextKey, nextValue)); + return result; + } + + @Override + public void putAll(Map nextSet) { + for (Map.Entry nextEntry : nextSet.entrySet()) { + put(nextEntry.getKey(), nextEntry.getValue()); + } + } + + @Override + public String remove(Object nextKey) { + String result = null; + for (Namespace nextNamespace : new LinkedHashSet(namespaces)) { + if (nextNamespace.getPrefix().equals(nextKey)) { + result = nextNamespace.getName(); + namespaces.remove(nextNamespace); + } + } + return result; + } + + @Override + public int size() { + return namespaces.size(); + } + + @Override + public Collection values() { + List result = new ArrayList(); + for (Namespace nextNamespace : namespaces) { + result.add(nextNamespace.getName()); + } + return result; + } + }; + } + + private Namespaces() { + // private default constructor, this is a static class + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/PatternIterator.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/PatternIterator.java new file mode 100644 index 00000000000..ab841589343 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/PatternIterator.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; + +/** + * Excludes an Iterator based on a given basic graph pattern. + */ +public class PatternIterator implements Iterator { + + private final Iterator filteredIter; + + private final Value subj; + + private final Value pred; + + private final Value obj; + + private final Value[] contexts; + + private S nextElement; + + private boolean nextCalled; + + public PatternIterator(Iterator iter, Value subj, Value pred, Value obj, Value... contexts) { + this.filteredIter = iter; + this.subj = subj; + this.pred = pred; + this.obj = obj; + this.contexts = notNull(contexts); + } + + public boolean hasNext() { + findNextElement(); + + return nextElement != null; + } + + public S next() { + findNextElement(); + + S result = nextElement; + + if (result != null) { + nextElement = null; + nextCalled = true; + return result; + } + else { + throw new NoSuchElementException(); + } + } + + private void findNextElement() { + while (nextElement == null && filteredIter.hasNext()) { + S candidate = filteredIter.next(); + + if (accept(candidate)) { + nextElement = candidate; + } + } + } + + public void remove() { + if (!nextCalled) + throw new IllegalStateException(); + filteredIter.remove(); + } + + /** + * Tests whether or not the specified statement should be returned by this + * iterator. All objects from the wrapped iterator pass through this method + * in the same order as they are coming from the wrapped iterator. + * + * @param st + * The statement to be tested. + * @return true if the object should be returned, false + * otherwise. + * @throws X + */ + protected boolean accept(S st) { + if (subj != null && !subj.equals(st.getSubject())) { + return false; + } + if (pred != null && !pred.equals(st.getPredicate())) { + return false; + } + if (obj != null && !obj.equals(st.getObject())) { + return false; + } + Resource stContext = st.getContext(); + if (contexts != null && contexts.length == 0) { + // Any context matches + return true; + } + else { + // Accept if one of the contexts from the pattern matches + for (Value context : notNull(contexts)) { + if (context == null && stContext == null) { + return true; + } + if (context != null && context.equals(stContext)) { + return true; + } + } + + return false; + } + } + + private Value[] notNull(Value[] contexts) { + if (contexts == null) { + return new Resource[] { null }; + } + return contexts; + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/URIUtil.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/URIUtil.java new file mode 100644 index 00000000000..14c2bb588d3 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/URIUtil.java @@ -0,0 +1,265 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.rdf4j.model.URI; + +/** + * Utility functions for working with {@link URI URIs}. + * @author Arjohn Kampman + */ +public class URIUtil { + + /** + * Reserved characters: their usage within the URI component is limited to + * their reserved purpose. If the data for a URI component would conflict + * with the reserved purpose, then the conflicting data must be escaped + * before forming the URI. http://www.isi.edu/in-notes/rfc2396.txt section + * 2.2. + */ + private static final Set reserved = new HashSet(Arrays.asList(new Character[] { + ';', + '/', + '?', + ':', + '@', + '&', + '=', + '+', + '$', + ',' })); + + /** + * Punctuation mark characters, which are part of the set of unreserved chars + * and therefore allowed to occur in unescaped form. See + * http://www.isi.edu/in-notes/rfc2396.txt + */ + private static final Set mark = new HashSet(Arrays.asList(new Character[] { + '-', + '_', + '.', + '!', + '~', + '*', + '\'', + '(', + ')' })); + + /** + * Finds the index of the first local name character in an (non-relative) + * URI. This index is determined by the following the following steps: + *

      + *
    • Find the first occurrence of the '#' character, + *
    • If this fails, find the last occurrence of the '/' character, + *
    • If this fails, find the last occurrence of the ':' character. + *
    • Add 1 to the found index and return this value. + *
    + * Note that the third step should never fail as every legal (non-relative) + * URI contains at least one ':' character to seperate the scheme from the + * rest of the URI. If this fails anyway, the method will throw an + * {@link IllegalArgumentException}. + * + * @param uri + * A URI string. + * @return The index of the first local name character in the URI string. + * Note that this index does not reference an actual character if the + * algorithm determines that there is not local name. In that case, + * the return index is equal to the length of the URI string. + * @throws IllegalArgumentException + * If the supplied URI string doesn't contain any of the separator + * characters. Every legal (non-relative) URI contains at least one + * ':' character to seperate the scheme from the rest of the URI. + */ + public static int getLocalNameIndex(String uri) { + int separatorIdx = uri.indexOf('#'); + + if (separatorIdx < 0) { + separatorIdx = uri.lastIndexOf('/'); + } + + if (separatorIdx < 0) { + separatorIdx = uri.lastIndexOf(':'); + } + + if (separatorIdx < 0) { + throw new IllegalArgumentException("No separator character founds in URI: " + uri); + } + + return separatorIdx + 1; + } + + /** + * Checks whether the URI consisting of the specified namespace and local + * name has been split correctly according to the URI splitting rules + * specified in {@link URI}. + * + * @param namespace + * The URI's namespace, must not be null. + * @param localName + * The URI's local name, must not be null. + * @return true if the specified URI has been correctly split into a + * namespace and local name, false otherwise. + * @see URI + * @see #getLocalNameIndex(String) + */ + public static boolean isCorrectURISplit(String namespace, String localName) { + assert namespace != null : "namespace must not be null"; + assert localName != null : "localName must not be null"; + + if (namespace.length() == 0) { + return false; + } + + int nsLength = namespace.length(); + char lastNsChar = namespace.charAt(nsLength - 1); + + if (lastNsChar == '#') { + // correct split if namespace has no other '#' + return namespace.lastIndexOf('#', nsLength - 2) == -1; + } + else if (lastNsChar == '/') { + // correct split if local name has no '/' and URI contains no '#' + return localName.indexOf('/') == -1 && localName.indexOf('#') == -1 && namespace.indexOf('#') == -1; + } + else if (lastNsChar == ':') { + // correct split if local name has no ':' and URI contains no '#' or + // '/' + return localName.indexOf(':') == -1 && localName.indexOf('#') == -1 && localName.indexOf('/') == -1 + && namespace.indexOf('#') == -1 && namespace.indexOf('/') == -1; + } + + return false; + } + + /** + * Verifies that the supplied string is a valid RDF (1.0) URI reference, as + * defined in section 6.4 of the RDF Concepts and Abstract Syntax specification + * (RDF 1.0 Recommendation of February 10, 2004). + *

    + * An RDF URI reference is valid if it is a Unicode string that: + *

      + *
    • does not contain any control characters ( #x00 - #x1F, #x7F-#x9F) + *
    • and would produce a valid URI character sequence (per RFC2396 , + * section 2.1) representing an absolute URI with optional fragment + * identifier when subjected to the encoding described below + *
    + * The encoding consists of: + *
      + *
    1. encoding the Unicode string as UTF-8, giving a sequence of octet + * values. + *
    2. %-escaping octets that do not correspond to permitted US-ASCII + * characters. + *
    + * + * @param uriRef + * a string representing an RDF URI reference. + * @return true iff the supplied string is a syntactically valid + * RDF URI reference, false otherwise. + * @see section + * 6.4 of the RDF Concepts and Abstract Syntax specification + * @see RFC 3986 + * @see RFC 2396 + * @since 2.7.14 + */ + public static boolean isValidURIReference(String uriRef) { + + // check that string contains no Unicode control characters. + boolean valid = !uriRef.matches("[\u0000-\u001F\u007F-\u009F]"); + if (valid) { + // check that proper encoding/escaping would yield a valid absolute + // RFC 2396 URI + final String escaped = escapeExcludedChars(uriRef); + try { + /* + * NOTE we use java.net.URI parsing to check compliance to the RFC, which is almost, but not completely, in alignment + * with RFC 2396, and has not been updated for compatibility with RFC 3986. From the java.net.URI Javadoc: + * + * "This constructor parses the given string exactly as specified by the grammar in RFC 2396, Appendix A, + * except for the following deviations: + * + * - An empty authority component is permitted as long as it is followed by a non-empty path, a query component, + * or a fragment component. This allows the parsing of URIs such as "file:///foo/bar", which seems to be the + * intent of RFC 2396 although the grammar does not permit it. If the authority component is empty then the + * user-information, host, and port components are undefined. + * - Empty relative paths are permitted; this seems to be the intent of RFC 2396 although the grammar does not + * permit it. The primary consequence of this deviation is that a standalone fragment such as "#foo" parses as + * a relative URI with an empty path and the given fragment, and can be usefully resolved against a base URI. + * - IPv4 addresses in host components are parsed rigorously, as specified by RFC 2732: Each element of a dotted-quad + * address must contain no more than three decimal digits. Each element is further constrained to have a value no + * greater than 255. + * - Hostnames in host components that comprise only a single domain label are permitted to start with an alphanum + * character. This seems to be the intent of RFC 2396 section 3.2.2 although the grammar does not permit it. The + * consequence of this deviation is that the authority component of a hierarchical URI such as s://123, will parse + * as a server-based authority. + * - IPv6 addresses are permitted for the host component. An IPv6 address must be enclosed in square brackets + * ('[' and ']') as specified by RFC 2732. The IPv6 address itself must parse according to RFC 2373. IPv6 addresses + * are further constrained to describe no more than sixteen bytes of address information, a constraint implicit in + * RFC 2373 but not expressible in the grammar. + * - Characters in the /other/ category are permitted wherever RFC 2396 permits escaped octets, that is, in the user-information, + * path, query, and fragment components, as well as in the authority component if the authority is registry-based. + * This allows URIs to contain Unicode characters beyond those in the US-ASCII character set." + */ + final java.net.URI uri = new java.net.URI(escaped); + valid = uri.isAbsolute(); + } + catch (URISyntaxException e) { + valid = false; + } + } + + return valid; + } + + /** + * Escapes any character that is not either reserved or in the legal range of + * unreserved characters, according to RFC 2396. + * + * @param unescaped + * a (relative or absolute) uri reference. + * @return a (relative or absolute) uri reference with all characters that + * can not appear as-is in a URI %-escaped. + * @see RFC 2396 + */ + private static String escapeExcludedChars(String unescaped) { + final StringBuilder escaped = new StringBuilder(); + for (int i = 0; i < unescaped.length(); i++) { + char c = unescaped.charAt(i); + if (!isUnreserved(c) && !reserved.contains(c)) { + escaped.append("%" + Integer.toHexString((int)c)); + } + else { + escaped.append(c); + } + } + return escaped.toString(); + } + + /** + * A character is unreserved according to RFC 2396 if it is either an + * alphanumeric char or a punctuation mark. + */ + private static boolean isUnreserved(char c) { + final int n = (int)c; + // check if alphanumeric + boolean unreserved = (47 < n && n < 58) || (96 < n && n < 123) || (64 < n && n < 91); + if (!unreserved) { + // check if punctuation mark + unreserved = mark.contains(c); + } + + return unreserved; + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/IanaLanguageTag.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/IanaLanguageTag.java new file mode 100644 index 00000000000..0597c784245 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/IanaLanguageTag.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* + * IanaLanguageTags.java + * + * Created on July 24, 2001, 11:47 PM + */ + +package org.eclipse.rdf4j.model.util.language; + +import java.util.HashMap; +import java.util.Map; + +/** + * Language codes registered by IANA. An encapsulation of the IANA language + * registry found at + * http://www.iana.org/assignments/language-tags. The values were updated + * on 8th July 2002 from a file dated 7th July 2002. + * + * @author jjc + */ +public class IanaLanguageTag extends LanguageTag { + + static final Map all = new HashMap(); + static { + try { + all.put("lojban", new IanaLanguageTag[] { new IanaLanguageTag("art-lojban") }); + all.put("gaulish", new IanaLanguageTag[] { new IanaLanguageTag("cel-gaulish") }); + all.put("scouse", new IanaLanguageTag[] { new IanaLanguageTag("en-scouse") }); + all.put("ami", new IanaLanguageTag[] { new IanaLanguageTag("i-ami") }); + all.put("bnn", new IanaLanguageTag[] { new IanaLanguageTag("i-bnn") }); + all.put("default", new IanaLanguageTag[] { new IanaLanguageTag("i-default", LT_DEFAULT) }); + all.put("enochian", new IanaLanguageTag[] { new IanaLanguageTag("i-enochian") }); + all.put("hak", new IanaLanguageTag[] { new IanaLanguageTag("i-hak", LT_IANA_DEPRECATED) }); + all.put("klingon", new IanaLanguageTag[] { new IanaLanguageTag("i-klingon") }); + all.put("lux", new IanaLanguageTag[] { new IanaLanguageTag("i-lux", LT_IANA_DEPRECATED) }); + all.put("mingo", new IanaLanguageTag[] { new IanaLanguageTag("i-mingo") }); + all.put("navajo", new IanaLanguageTag[] { new IanaLanguageTag("i-navajo", LT_IANA_DEPRECATED) }); + all.put("pwn", new IanaLanguageTag[] { new IanaLanguageTag("i-pwn") }); + all.put("tao", new IanaLanguageTag[] { new IanaLanguageTag("i-tao") }); + all.put("tay", new IanaLanguageTag[] { new IanaLanguageTag("i-tay") }); + all.put("tsu", new IanaLanguageTag[] { new IanaLanguageTag("i-tsu") }); + all.put("bok", new IanaLanguageTag[] { new IanaLanguageTag("no-bok", LT_IANA_DEPRECATED) }); + all.put("nyn", new IanaLanguageTag[] { new IanaLanguageTag("no-nyn", LT_IANA_DEPRECATED) }); + all.put("be", new IanaLanguageTag[] { + new IanaLanguageTag("sgn-BE-fr"), + new IanaLanguageTag("sgn-BE-nl") }); + all.put("br", new IanaLanguageTag[] { new IanaLanguageTag("sgn-BR") }); + all.put("ch", new IanaLanguageTag[] { new IanaLanguageTag("sgn-CH-de") }); + all.put("co", new IanaLanguageTag[] { new IanaLanguageTag("sgn-CO") }); + all.put("de", new IanaLanguageTag[] { new IanaLanguageTag("sgn-DE") }); + all.put("dk", new IanaLanguageTag[] { new IanaLanguageTag("sgn-DK") }); + all.put("es", new IanaLanguageTag[] { new IanaLanguageTag("sgn-ES") }); + all.put("fr", new IanaLanguageTag[] { new IanaLanguageTag("sgn-FR") }); + all.put("gb", new IanaLanguageTag[] { new IanaLanguageTag("sgn-GB") }); + all.put("gr", new IanaLanguageTag[] { new IanaLanguageTag("sgn-GR") }); + all.put("ie", new IanaLanguageTag[] { new IanaLanguageTag("sgn-IE") }); + all.put("it", new IanaLanguageTag[] { new IanaLanguageTag("sgn-IT") }); + all.put("jp", new IanaLanguageTag[] { new IanaLanguageTag("sgn-JP") }); + all.put("mx", new IanaLanguageTag[] { new IanaLanguageTag("sgn-MX") }); + all.put("ni", new IanaLanguageTag[] { new IanaLanguageTag("sgn-NI") }); + all.put("nl", new IanaLanguageTag[] { new IanaLanguageTag("sgn-NL") }); + all.put("no", new IanaLanguageTag[] { new IanaLanguageTag("sgn-NO") }); + all.put("pt", new IanaLanguageTag[] { new IanaLanguageTag("sgn-PT") }); + all.put("se", new IanaLanguageTag[] { new IanaLanguageTag("sgn-SE") }); + all.put("us", new IanaLanguageTag[] { new IanaLanguageTag("sgn-US") }); + all.put("za", new IanaLanguageTag[] { new IanaLanguageTag("sgn-ZA") }); + all.put("gan", new IanaLanguageTag[] { new IanaLanguageTag("zh-gan") }); + all.put("guoyu", new IanaLanguageTag[] { new IanaLanguageTag("zh-guoyu") }); + all.put("hakka", new IanaLanguageTag[] { new IanaLanguageTag("zh-hakka") }); + all.put("min", new IanaLanguageTag[] { + new IanaLanguageTag("zh-min"), + new IanaLanguageTag("zh-min-nan") }); + all.put("wuu", new IanaLanguageTag[] { new IanaLanguageTag("zh-wuu") }); + all.put("xiang", new IanaLanguageTag[] { new IanaLanguageTag("zh-xiang") }); + all.put("yue", new IanaLanguageTag[] { new IanaLanguageTag("zh-yue") }); + } + catch (LanguageTagSyntaxException ee) { + System.err.println("Internal Error in static initializer of IanaLanguageTag:"+ee.getMessage()); + } + + } + + /** + * The bitwise OR of all applicable values from {@link LanguageTagCodes}. + * The possibilities are: + *
      + *
    • LT_IANA
    • + *
    • LT_IANA|LT_IANA_DEPRECATED
    • + *
    • LT_IANA|LT_DEFAULT i.e. i-default
    • + *
    + */ + final public int classification; + + private IanaLanguageTag(String s, int classification) + throws LanguageTagSyntaxException + { + super(s); + this.classification = LT_IANA | classification; + } + + private IanaLanguageTag(String s) + throws LanguageTagSyntaxException + { + this(s, 0); + } + + /** + * Look up a language identifier in the IANA list. Trailing additional + * subtags are ignored. + * + * @param t + * The LanguageTag corresponding to the item being looked up. + * @return The IanaLanguageTag if found, or null if it is not in the list. + */ + static public IanaLanguageTag find(LanguageTag t) { + if (t.subtags.length < 2) { + return null; + } + IanaLanguageTag matches[] = (IanaLanguageTag[])all.get(t.subtags[1]); + if (matches == null) { + return null; + } + nextMatch: for (int i = 0; i < matches.length; i++) { + if (t.subtags.length >= matches[i].subtags.length) { + for (int j = 0; j < matches[i].subtags.length; j++) { + if (!t.subtags[j].equals(matches[i].subtags[j])) + continue nextMatch; + } + return matches[i]; + } + } + return null; + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/Iso3166.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/Iso3166.java new file mode 100644 index 00000000000..395e848e9f1 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/Iso3166.java @@ -0,0 +1,303 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* + * Iso3166.java + * + * Created on July 24, 2001, 11:46 PM + */ + +package org.eclipse.rdf4j.model.util.language; + +import java.util.HashMap; +import java.util.Map; + +/** + * Country code names from ISO 3166. + *

    + * An encapsulation of registry of ISO 3166. This was updated on 24th July 2001 + * from + * http://www.din.de/gremien/nas/nabd/iso3166ma/codlstp1/db_en.html + * + * @author jjc + */ +public class Iso3166 { + + static final Map all = new HashMap(); + + /** Creates new Iso639 */ + private Iso3166(String code, String engName) { + this.code = code.toLowerCase(); + name = engName; + all.put(this.code, this); + } + + /** + * Look a country code up in the list. + * + * @param countryId + * The country code to look up. + * @return The corresponding Iso3166 object, or null if not in the list. + */ + static public Iso3166 find(String countryId) { + return (Iso3166)all.get(countryId); + } + + /** + * The 2 character country code. + */ + public final String code; + + /** + * The name of the country (in English). + */ + public final String name; + + static { + new Iso3166("AF", "AFGHANISTAN"); + new Iso3166("AL", "ALBANIA"); + new Iso3166("DZ", "ALGERIA"); + new Iso3166("AS", "AMERICAN SAMOA"); + new Iso3166("AD", "ANDORRA"); + new Iso3166("AO", "ANGOLA"); + new Iso3166("AI", "ANGUILLA"); + new Iso3166("AQ", "ANTARCTICA"); + new Iso3166("AG", "ANTIGUA AND BARBUDA"); + new Iso3166("AR", "ARGENTINA"); + new Iso3166("AM", "ARMENIA"); + new Iso3166("AW", "ARUBA"); + new Iso3166("AU", "AUSTRALIA"); + new Iso3166("AT", "AUSTRIA"); + new Iso3166("AZ", "AZERBAIJAN"); + new Iso3166("BS", "BAHAMAS"); + new Iso3166("BH", "BAHRAIN"); + new Iso3166("BD", "BANGLADESH"); + new Iso3166("BB", "BARBADOS"); + new Iso3166("BY", "BELARUS"); + new Iso3166("BE", "BELGIUM"); + new Iso3166("BZ", "BELIZE"); + new Iso3166("BJ", "BENIN"); + new Iso3166("BM", "BERMUDA"); + new Iso3166("BT", "BHUTAN"); + new Iso3166("BO", "BOLIVIA"); + new Iso3166("BA", "BOSNIA AND HERZEGOVINA"); + new Iso3166("BW", "BOTSWANA"); + new Iso3166("BV", "BOUVET ISLAND"); + new Iso3166("BR", "BRAZIL"); + new Iso3166("IO", "BRITISH INDIAN OCEAN TERRITORY"); + new Iso3166("BN", "BRUNEI DARUSSALAM"); + new Iso3166("BG", "BULGARIA"); + new Iso3166("BF", "BURKINA FASO"); + new Iso3166("BI", "BURUNDI"); + new Iso3166("KH", "CAMBODIA"); + new Iso3166("CM", "CAMEROON"); + new Iso3166("CA", "CANADA"); + new Iso3166("CV", "CAPE VERDE"); + new Iso3166("KY", "CAYMAN ISLANDS"); + new Iso3166("CF", "CENTRAL AFRICAN REPUBLIC"); + new Iso3166("TD", "CHAD"); + new Iso3166("CL", "CHILE"); + new Iso3166("CN", "CHINA"); + new Iso3166("CX", "CHRISTMAS ISLAND"); + new Iso3166("CC", "COCOS (KEELING) ISLANDS"); + new Iso3166("CO", "COLOMBIA"); + new Iso3166("KM", "COMOROS"); + new Iso3166("CG", "CONGO"); + new Iso3166("CD", "CONGO, THE DEMOCRATIC REPUBLIC OF THE"); + new Iso3166("CK", "COOK ISLANDS"); + new Iso3166("CR", "COSTA RICA"); + new Iso3166("CI", "COTE D'IVOIRE"); + new Iso3166("HR", "CROATIA"); + new Iso3166("CU", "CUBA"); + new Iso3166("CY", "CYPRUS"); + new Iso3166("CZ", "CZECH REPUBLIC"); + new Iso3166("DK", "DENMARK"); + new Iso3166("DJ", "DJIBOUTI"); + new Iso3166("DM", "DOMINICA"); + new Iso3166("DO", "DOMINICAN REPUBLIC"); + new Iso3166("TP", "EAST TIMOR"); + new Iso3166("EC", "ECUADOR"); + new Iso3166("EG", "EGYPT"); + new Iso3166("SV", "EL SALVADOR"); + new Iso3166("GQ", "EQUATORIAL GUINEA"); + new Iso3166("ER", "ERITREA"); + new Iso3166("EE", "ESTONIA"); + new Iso3166("ET", "ETHIOPIA"); + new Iso3166("FK", "FALKLAND ISLANDS (MALVINAS)"); + new Iso3166("FO", "FAROE ISLANDS"); + new Iso3166("FJ", "FIJI"); + new Iso3166("FI", "FINLAND"); + new Iso3166("FR", "FRANCE"); + new Iso3166("GF", "FRENCH GUIANA"); + new Iso3166("PF", "FRENCH POLYNESIA"); + new Iso3166("TF", "FRENCH SOUTHERN TERRITORIES"); + new Iso3166("GA", "GABON"); + new Iso3166("GM", "GAMBIA"); + new Iso3166("GE", "GEORGIA"); + new Iso3166("DE", "GERMANY"); + new Iso3166("GH", "GHANA"); + new Iso3166("GI", "GIBRALTAR"); + new Iso3166("GR", "GREECE"); + new Iso3166("GL", "GREENLAND"); + new Iso3166("GD", "GRENADA"); + new Iso3166("GP", "GUADELOUPE"); + new Iso3166("GU", "GUAM"); + new Iso3166("GT", "GUATEMALA"); + new Iso3166("GN", "GUINEA"); + new Iso3166("GW", "GUINEA-BISSAU"); + new Iso3166("GY", "GUYANA"); + new Iso3166("HT", "HAITI"); + new Iso3166("HM", "HEARD ISLAND AND MCDONALD ISLANDS"); + new Iso3166("VA", "HOLY SEE (VATICAN CITY STATE)"); + new Iso3166("HN", "HONDURAS"); + new Iso3166("HK", "HONG KONG"); + new Iso3166("HU", "HUNGARY"); + new Iso3166("IS", "ICELAND"); + new Iso3166("IN", "INDIA"); + new Iso3166("ID", "INDONESIA"); + new Iso3166("IR", "IRAN, ISLAMIC REPUBLIC OF"); + new Iso3166("IQ", "IRAQ"); + new Iso3166("IE", "IRELAND"); + new Iso3166("IL", "ISRAEL"); + new Iso3166("IT", "ITALY"); + new Iso3166("JM", "JAMAICA"); + new Iso3166("JP", "JAPAN"); + new Iso3166("JO", "JORDAN"); + new Iso3166("KZ", "KAZAKSTAN"); + new Iso3166("KE", "KENYA"); + new Iso3166("KI", "KIRIBATI"); + new Iso3166("KP", "KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF"); + new Iso3166("KR", "KOREA, REPUBLIC OF"); + new Iso3166("KW", "KUWAIT"); + new Iso3166("KG", "KYRGYZSTAN"); + new Iso3166("LA", "LAO PEOPLE'S DEMOCRATIC REPUBLIC"); + new Iso3166("LV", "LATVIA"); + new Iso3166("LB", "LEBANON"); + new Iso3166("LS", "LESOTHO"); + new Iso3166("LR", "LIBERIA"); + new Iso3166("LY", "LIBYAN ARAB JAMAHIRIYA"); + new Iso3166("LI", "LIECHTENSTEIN"); + new Iso3166("LT", "LITHUANIA"); + new Iso3166("LU", "LUXEMBOURG"); + new Iso3166("MO", "MACAU"); + new Iso3166("MK", "MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF"); + new Iso3166("MG", "MADAGASCAR"); + new Iso3166("MW", "MALAWI"); + new Iso3166("MY", "MALAYSIA"); + new Iso3166("MV", "MALDIVES"); + new Iso3166("ML", "MALI"); + new Iso3166("MT", "MALTA"); + new Iso3166("MH", "MARSHALL ISLANDS"); + new Iso3166("MQ", "MARTINIQUE"); + new Iso3166("MR", "MAURITANIA"); + new Iso3166("MU", "MAURITIUS"); + new Iso3166("YT", "MAYOTTE"); + new Iso3166("MX", "MEXICO"); + new Iso3166("FM", "MICRONESIA, FEDERATED STATES OF"); + new Iso3166("MD", "MOLDOVA, REPUBLIC OF"); + new Iso3166("MC", "MONACO"); + new Iso3166("MN", "MONGOLIA"); + new Iso3166("MS", "MONTSERRAT"); + new Iso3166("MA", "MOROCCO"); + new Iso3166("MZ", "MOZAMBIQUE"); + new Iso3166("MM", "MYANMAR"); + new Iso3166("NA", "NAMIBIA"); + new Iso3166("NR", "NAURU"); + new Iso3166("NP", "NEPAL"); + new Iso3166("NL", "NETHERLANDS"); + new Iso3166("AN", "NETHERLANDS ANTILLES"); + new Iso3166("NC", "NEW CALEDONIA"); + new Iso3166("NZ", "NEW ZEALAND"); + new Iso3166("NI", "NICARAGUA"); + new Iso3166("NE", "NIGER"); + new Iso3166("NG", "NIGERIA"); + new Iso3166("NU", "NIUE"); + new Iso3166("NF", "NORFOLK ISLAND"); + new Iso3166("MP", "NORTHERN MARIANA ISLANDS"); + new Iso3166("NO", "NORWAY"); + new Iso3166("OM", "OMAN"); + new Iso3166("PK", "PAKISTAN"); + new Iso3166("PW", "PALAU"); + new Iso3166("PS", "PALESTINIAN TERRITORY, OCCUPIED"); + new Iso3166("PA", "PANAMA"); + new Iso3166("PG", "PAPUA NEW GUINEA"); + new Iso3166("PY", "PARAGUAY"); + new Iso3166("PE", "PERU"); + new Iso3166("PH", "PHILIPPINES"); + new Iso3166("PN", "PITCAIRN"); + new Iso3166("PL", "POLAND"); + new Iso3166("PT", "PORTUGAL"); + new Iso3166("PR", "PUERTO RICO"); + new Iso3166("QA", "QATAR"); + new Iso3166("RE", "REUNION"); + new Iso3166("RO", "ROMANIA"); + new Iso3166("RU", "RUSSIAN FEDERATION"); + new Iso3166("RW", "RWANDA"); + new Iso3166("SH", "SAINT HELENA"); + new Iso3166("KN", "SAINT KITTS AND NEVIS"); + new Iso3166("LC", "SAINT LUCIA"); + new Iso3166("PM", "SAINT PIERRE AND MIQUELON"); + new Iso3166("VC", "SAINT VINCENT AND THE GRENADINES"); + new Iso3166("WS", "SAMOA"); + new Iso3166("SM", "SAN MARINO"); + new Iso3166("ST", "SAO TOME AND PRINCIPE"); + new Iso3166("SA", "SAUDI ARABIA"); + new Iso3166("SN", "SENEGAL"); + new Iso3166("SC", "SEYCHELLES"); + new Iso3166("SL", "SIERRA LEONE"); + new Iso3166("SG", "SINGAPORE"); + new Iso3166("SK", "SLOVAKIA"); + new Iso3166("SI", "SLOVENIA"); + new Iso3166("SB", "SOLOMON ISLANDS"); + new Iso3166("SO", "SOMALIA"); + new Iso3166("ZA", "SOUTH AFRICA"); + new Iso3166("GS", "SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS"); + new Iso3166("ES", "SPAIN"); + new Iso3166("LK", "SRI LANKA"); + new Iso3166("SD", "SUDAN"); + new Iso3166("SR", "SURINAME"); + new Iso3166("SJ", "SVALBARD AND JAN MAYEN"); + new Iso3166("SZ", "SWAZILAND"); + new Iso3166("SE", "SWEDEN"); + new Iso3166("CH", "SWITZERLAND"); + new Iso3166("SY", "SYRIAN ARAB REPUBLIC"); + new Iso3166("TW", "TAIWAN, PROVINCE OF CHINA"); + new Iso3166("TJ", "TAJIKISTAN"); + new Iso3166("TZ", "TANZANIA, UNITED REPUBLIC OF"); + new Iso3166("TH", "THAILAND"); + new Iso3166("TG", "TOGO"); + new Iso3166("TK", "TOKELAU"); + new Iso3166("TO", "TONGA"); + new Iso3166("TT", "TRINIDAD AND TOBAGO"); + new Iso3166("TN", "TUNISIA"); + new Iso3166("TR", "TURKEY"); + new Iso3166("TM", "TURKMENISTAN"); + new Iso3166("TC", "TURKS AND CAICOS ISLANDS"); + new Iso3166("TV", "TUVALU"); + new Iso3166("UG", "UGANDA"); + new Iso3166("UA", "UKRAINE"); + new Iso3166("AE", "UNITED ARAB EMIRATES"); + new Iso3166("GB", "UNITED KINGDOM"); + new Iso3166("US", "UNITED STATES"); + new Iso3166("UM", "UNITED STATES MINOR OUTLYING ISLANDS"); + new Iso3166("UY", "URUGUAY"); + new Iso3166("UZ", "UZBEKISTAN"); + new Iso3166("VU", "VANUATU"); + new Iso3166("VE", "VENEZUELA"); + new Iso3166("VN", "VIET NAM"); + new Iso3166("VG", "VIRGIN ISLANDS, BRITISH"); + new Iso3166("VI", "VIRGIN ISLANDS, U.S."); + new Iso3166("WF", "WALLIS AND FUTUNA"); + new Iso3166("EH", "WESTERN SAHARA"); + new Iso3166("YE", "YEMEN"); + new Iso3166("YU", "YUGOSLAVIA"); + new Iso3166("ZM", "ZAMBIA"); + new Iso3166("ZW", "ZIMBABWE"); + + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/Iso639.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/Iso639.java new file mode 100644 index 00000000000..211ba78f341 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/Iso639.java @@ -0,0 +1,580 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* + * Iso639.java + * + * Created on July 24, 2001, 11:46 PM + */ + +package org.eclipse.rdf4j.model.util.language; + +import java.util.HashMap; +import java.util.Map; + +/** + * Language codes from ISO639-1 and ISO639-2. + *

    + * An encapsulation of the registry of ISO639-1 and ISO639-2 codes as found at + * + * http://lcweb.loc.gov/standards/iso639-2/englangn.html on the 24th July + * 2001, and dated 12th October 2000. + * + * @author jjc + */ + +public class Iso639 implements LanguageTagCodes { + + static final Map all = new HashMap(); + + /** Creates new Iso639 */ + private Iso639(String engName, String two, String term, String bib, int classify) { + name = engName; + twoCharCode = two; + terminologyCode = term; + bibliographicCode = bib; + classification = classify | LT_ISO639; + put(two, this); + put(term, this); + put(bib, this); + } + + private Iso639(String engName, String two, String term, String bib) { + this(engName, two, term, bib, 0); + } + + /** + * Look an ISO-639 code up in the list. + * + * @param lang + * The two or three character code to look up. + * @return The corresponding Iso639 object, or null if not in the list. + */ + static public Iso639 find(String lang) { + Iso639 rslt = (Iso639)all.get(lang); + if (rslt == null) { + if (lang != null && lang.compareTo("qaa") >= 0 && lang.compareTo("qtz") <= 0 && lang.length() == 3) { + return new Iso639("Reserved for local use", null, lang, lang, LT_LOCAL_USE); + } + } + return rslt; + } + + /** + * The bitwise OR of all applicable values from {@link LanguageTagCodes}. + * The possibilities are: + *

      + *
    • LT_ISO639
    • + *
    • LT_ISO639|LT_MULTIPLE i.e. mul
    • + *
    • LT_ISO639|LT_UNDETERMINED i.e. und
    • + *
    • LT_ISO639|LT_LOCAL_USE e.g. qaa
    • + *
    + */ + public final int classification; + + /** + * The ISO639-1 two character code. + */ + public final String twoCharCode; + + /** + * The ISO639-2 three character Terminology Code. + */ + public final String terminologyCode; + + /** + * The ISO639-2 three character Bibliographic Code. + */ + public final String bibliographicCode; + + /** + * The name of the language in English. + */ + public final String name; + + static private void put(String key, Iso639 v) { + if (key != null) { + Iso639 old = (Iso639)all.put(key, v); + if (old != null && old != v) { + System.err.println("ISO-639 code '" + key + "' is overloaded."); + } + } + } + + static { + new Iso639("Abkhazian", "ab", "abk", "abk"); + new Iso639("Achinese", null, "ace", "ace"); + new Iso639("Acoli", null, "ach", "ach"); + new Iso639("Adangme", null, "ada", "ada"); + new Iso639("Afar", "aa", "aar", "aar"); + new Iso639("Afrihili", null, "afh", "afh"); + new Iso639("Afrikaans", "af", "afr", "afr"); + new Iso639("Afro-Asiatic (Other)", null, "afa", "afa"); + new Iso639("Akan", null, "aka", "aka"); + new Iso639("Akkadian", null, "akk", "akk"); + new Iso639("Albanian", "sq", "sqi", "alb"); + new Iso639("Aleut", null, "ale", "ale"); + new Iso639("Algonquian languages", null, "alg", "alg"); + new Iso639("Altaic (Other)", null, "tut", "tut"); + new Iso639("Amharic", "am", "amh", "amh"); + new Iso639("Apache languages", null, "apa", "apa"); + new Iso639("Arabic", "ar", "ara", "ara"); + new Iso639("Aramaic", null, "arc", "arc"); + new Iso639("Arapaho", null, "arp", "arp"); + new Iso639("Araucanian", null, "arn", "arn"); + new Iso639("Arawak", null, "arw", "arw"); + new Iso639("Armenian", "hy", "hye", "arm"); + new Iso639("Artificial (Other)", null, "art", "art"); + new Iso639("Assamese", "as", "asm", "asm"); + new Iso639("Athapascan languages", null, "ath", "ath"); + new Iso639("Australian languages", null, "aus", "aus"); + new Iso639("Austronesian (Other)", null, "map", "map"); + + new Iso639("Avaric", null, "ava", "ava"); + new Iso639("Avestan", "ae", "ave", "ave"); + new Iso639("Awadhi", null, "awa", "awa"); + new Iso639("Aymara", "ay", "aym", "aym"); + new Iso639("Azerbaijani", "az", "aze", "aze"); + new Iso639("Balinese", null, "ban", "ban"); + new Iso639("Baltic (Other)", null, "bat", "bat"); + new Iso639("Baluchi", null, "bal", "bal"); + new Iso639("Bambara", null, "bam", "bam"); + new Iso639("Bamileke languages", null, "bai", "bai"); + new Iso639("Banda", null, "bad", "bad"); + new Iso639("Bantu (Other)", null, "bnt", "bnt"); + new Iso639("Basa", null, "bas", "bas"); + new Iso639("Bashkir", "ba", "bak", "bak"); + new Iso639("Basque", "eu", "eus", "baq"); + new Iso639("Batak (Indonesia)", null, "btk", "btk"); + new Iso639("Beja", null, "bej", "bej"); + new Iso639("Belarusian", "be", "bel", "bel"); + new Iso639("Bemba", null, "bem", "bem"); + new Iso639("Bengali", "bn", "ben", "ben"); + new Iso639("Berber (Other)", null, "ber", "ber"); + new Iso639("Bhojpuri", null, "bho", "bho"); + new Iso639("Bihari", "bh", "bih", "bih"); + new Iso639("Bikol", null, "bik", "bik"); + new Iso639("Bini", null, "bin", "bin"); + new Iso639("Bislama", "bi", "bis", "bis"); + new Iso639("Bosnian", "bs", "bos", "bos"); + new Iso639("Braj", null, "bra", "bra"); + new Iso639("Breton", "br", "bre", "bre"); + new Iso639("Buginese", null, "bug", "bug"); + new Iso639("Bulgarian", "bg", "bul", "bul"); + new Iso639("Buriat", null, "bua", "bua"); + new Iso639("Burmese", "my", "mya", "bur"); + + new Iso639("Caddo", null, "cad", "cad"); + new Iso639("Carib", null, "car", "car"); + new Iso639("Catalan", "ca", "cat", "cat"); + new Iso639("Caucasian (Other)", null, "cau", "cau"); + new Iso639("Cebuano", null, "ceb", "ceb"); + new Iso639("Celtic (Other)", null, "cel", "cel"); + new Iso639("Central American Indian (Other)", null, "cai", "cai"); + + new Iso639("Chagatai", null, "chg", "chg"); + new Iso639("Chamic languages", null, "cmc", "cmc"); + new Iso639("Chamorro", "ch", "cha", "cha"); + new Iso639("Chechen", "ce", "che", "che"); + new Iso639("Cherokee", null, "chr", "chr"); + new Iso639("Cheyenne", null, "chy", "chy"); + new Iso639("Chibcha", null, "chb", "chb"); + new Iso639("Chichewa; Nyanja", "ny", "nya", "nya"); + new Iso639("Chinese", "zh", "zho", "chi"); + new Iso639("Chinook jargon", null, "chn", "chn"); + new Iso639("Chipewyan", null, "chp", "chp"); + new Iso639("Choctaw", null, "cho", "cho"); + new Iso639("Church Slavic", "cu", "chu", "chu"); + new Iso639("Chuukese", null, "chk", "chk"); + new Iso639("Chuvash", "cv", "chv", "chv"); + new Iso639("Coptic", null, "cop", "cop"); + new Iso639("Cornish", "kw", "cor", "cor"); + new Iso639("Corsican", "co", "cos", "cos"); + new Iso639("Cree", null, "cre", "cre"); + new Iso639("Creek", null, "mus", "mus"); + new Iso639("Creoles and pidgins (Other)", null, "crp", "crp"); + new Iso639("Creoles and pidgins, English-based (Other)", null, "cpe", "cpe"); + + new Iso639("Creoles and pidgins, French-based (Other)", null, "cpf", "cpf"); + + new Iso639("Creoles and pidgins, Portuguese-based (Other)", null, "cpp", "cpp"); + + new Iso639("Croatian", "hr", "hrv", "scr"); + new Iso639("Cushitic (Other)", null, "cus", "cus"); + new Iso639("Czech", "cs", "ces", "cze"); + new Iso639("Dakota", null, "dak", "dak"); + new Iso639("Danish", "da", "dan", "dan"); + new Iso639("Dayak", null, "day", "day"); + new Iso639("Delaware", null, "del", "del"); + new Iso639("Dinka", null, "din", "din"); + new Iso639("Divehi", null, "div", "div"); + new Iso639("Dogri", null, "doi", "doi"); + new Iso639("Dogrib", null, "dgr", "dgr"); + new Iso639("Dravidian (Other)", null, "dra", "dra"); + new Iso639("Duala", null, "dua", "dua"); + new Iso639("Dutch", "nl", "nld", "dut"); + new Iso639("Dutch, Middle (ca. 1050-1350)", null, "dum", "dum"); + new Iso639("Dyula", null, "dyu", "dyu"); + new Iso639("Dzongkha", "dz", "dzo", "dzo"); + + new Iso639("Efik", null, "efi", "efi"); + new Iso639("Egyptian (Ancient)", null, "egy", "egy"); + new Iso639("Ekajuk", null, "eka", "eka"); + new Iso639("Elamite", null, "elx", "elx"); + new Iso639("English", "en", "eng", "eng"); + new Iso639("English, Middle (1100-1500)", null, "enm", "enm"); + new Iso639("English, Old (ca.450-1100)", null, "ang", "ang"); + new Iso639("Esperanto", "eo", "epo", "epo"); + new Iso639("Estonian", "et", "est", "est"); + new Iso639("Ewe", null, "ewe", "ewe"); + new Iso639("Ewondo", null, "ewo", "ewo"); + new Iso639("Fang", null, "fan", "fan"); + new Iso639("Fanti", null, "fat", "fat"); + new Iso639("Faroese", "fo", "fao", "fao"); + new Iso639("Fijian", "fj", "fij", "fij"); + new Iso639("Finnish", "fi", "fin", "fin"); + new Iso639("Finno-Ugrian (Other)", null, "fiu", "fiu"); + new Iso639("Fon", null, "fon", "fon"); + new Iso639("French", "fr", "fra", "fre"); + new Iso639("French, Middle (ca.1400-1600)", null, "frm", "frm"); + new Iso639("French, Old (842-ca.1400)", null, "fro", "fro"); + new Iso639("Frisian", "fy", "fry", "fry"); + new Iso639("Friulian", null, "fur", "fur"); + new Iso639("Fulah", null, "ful", "ful"); + + new Iso639("Ga", null, "gaa", "gaa"); + new Iso639("Gaelic (Scots)", "gd", "gla", "gla"); + new Iso639("Gallegan", "gl", "glg", "glg"); + new Iso639("Ganda", null, "lug", "lug"); + new Iso639("Gayo", null, "gay", "gay"); + new Iso639("Gbaya", null, "gba", "gba"); + new Iso639("Geez", null, "gez", "gez"); + new Iso639("Georgian", "ka", "kat", "geo"); + new Iso639("German", "de", "deu", "ger"); + // new Iso639("German, Low; Saxon, Low; Low German; Low + // Saxon",null,"nds","nds"); + new Iso639("German, Middle High (ca.1050-1500)", null, "gmh", "gmh"); + + new Iso639("German, Old High (ca.750-1050)", null, "goh", "goh"); + + new Iso639("Germanic (Other)", null, "gem", "gem"); + new Iso639("Gilbertese", null, "gil", "gil"); + new Iso639("Gondi", null, "gon", "gon"); + new Iso639("Gorontalo", null, "gor", "gor"); + new Iso639("Gothic", null, "got", "got"); + new Iso639("Grebo", null, "grb", "grb"); + new Iso639("Greek, Ancient (to 1453)", null, "grc", "grc"); + new Iso639("Greek, Modern (1453-)", "el", "ell", "gre"); + new Iso639("Guarani", "gn", "grn", "grn"); + new Iso639("Gujarati", "gu", "guj", "guj"); + new Iso639("Gwich?in", null, "gwi", "gwi"); + new Iso639("Haida", null, "hai", "hai"); + new Iso639("Hausa", "ha", "hau", "hau"); + new Iso639("Hawaiian", null, "haw", "haw"); + new Iso639("Hebrew", "he", "heb", "heb"); + new Iso639("Herero", "hz", "her", "her"); + new Iso639("Hiligaynon", null, "hil", "hil"); + new Iso639("Himachali", null, "him", "him"); + new Iso639("Hindi", "hi", "hin", "hin"); + new Iso639("Hiri Motu", "ho", "hmo", "hmo"); + new Iso639("Hittite", null, "hit", "hit"); + new Iso639("Hmong", null, "hmn", "hmn"); + new Iso639("Hungarian", "hu", "hun", "hun"); + new Iso639("Hupa", null, "hup", "hup"); + + new Iso639("Iban", null, "iba", "iba"); + new Iso639("Icelandic", "is", "isl", "ice"); + new Iso639("Igbo", null, "ibo", "ibo"); + new Iso639("Ijo", null, "ijo", "ijo"); + new Iso639("Iloko", null, "ilo", "ilo"); + new Iso639("Indic (Other)", null, "inc", "inc"); + new Iso639("Indo-European (Other)", null, "ine", "ine"); + new Iso639("Indonesian", "id", "ind", "ind"); + new Iso639("Interlingua (International Auxiliary Language Association)", "ia", "ina", "ina"); + + new Iso639("Interlingue", "ie", "ile", "ile"); + new Iso639("Inuktitut", "iu", "iku", "iku"); + new Iso639("Inupiaq", "ik", "ipk", "ipk"); + new Iso639("Iranian (Other)", null, "ira", "ira"); + new Iso639("Irish", "ga", "gle", "gle"); + new Iso639("Irish, Middle (900-1200)", null, "mga", "mga"); + new Iso639("Irish, Old (to 900)", null, "sga", "sga"); + new Iso639("Iroquoian languages", null, "iro", "iro"); + new Iso639("Italian", "it", "ita", "ita"); + new Iso639("Japanese", "ja", "jpn", "jpn"); + new Iso639("Javanese", "jw", "jaw", "jav"); + new Iso639("Judeo-Arabic", null, "jrb", "jrb"); + new Iso639("Judeo-Persian", null, "jpr", "jpr"); + + new Iso639("Kabyle", null, "kab", "kab"); + new Iso639("Kachin", null, "kac", "kac"); + new Iso639("Kalaallisut", "kl", "kal", "kal"); + new Iso639("Kamba", null, "kam", "kam"); + new Iso639("Kannada", "kn", "kan", "kan"); + new Iso639("Kanuri", null, "kau", "kau"); + new Iso639("Kara-Kalpak", null, "kaa", "kaa"); + new Iso639("Karen", null, "kar", "kar"); + new Iso639("Kashmiri", "ks", "kas", "kas"); + new Iso639("Kawi", null, "kaw", "kaw"); + new Iso639("Kazakh", "kk", "kaz", "kaz"); + new Iso639("Khasi", null, "kha", "kha"); + new Iso639("Khmer", "km", "khm", "khm"); + new Iso639("Khoisan (Other)", null, "khi", "khi"); + new Iso639("Khotanese", null, "kho", "kho"); + new Iso639("Kikuyu", "ki", "kik", "kik"); + new Iso639("Kimbundu", null, "kmb", "kmb"); + new Iso639("Kinyarwanda", "rw", "kin", "kin"); + new Iso639("Kirghiz", "ky", "kir", "kir"); + new Iso639("Komi", "kv", "kom", "kom"); + new Iso639("Kongo", null, "kon", "kon"); + new Iso639("Konkani", null, "kok", "kok"); + new Iso639("Korean", "ko", "kor", "kor"); + new Iso639("Kosraean", null, "kos", "kos"); + new Iso639("Kpelle", null, "kpe", "kpe"); + new Iso639("Kru", null, "kro", "kro"); + new Iso639("Kuanyama", "kj", "kua", "kua"); + new Iso639("Kumyk", null, "kum", "kum"); + new Iso639("Kurdish", "ku", "kur", "kur"); + new Iso639("Kurukh", null, "kru", "kru"); + new Iso639("Kutenai", null, "kut", "kut"); + new Iso639("Ladino", null, "lad", "lad"); + new Iso639("Lahnda", null, "lah", "lah"); + new Iso639("Lamba", null, "lam", "lam"); + new Iso639("Lao", "lo", "lao", "lao"); + new Iso639("Latin", "la", "lat", "lat"); + new Iso639("Latvian", "lv", "lav", "lav"); + new Iso639("Letzeburgesch", "lb", "ltz", "ltz"); + new Iso639("Lezghian", null, "lez", "lez"); + new Iso639("Lingala", "ln", "lin", "lin"); + new Iso639("Lithuanian", "lt", "lit", "lit"); + new Iso639("Low German; Low Saxon; German, Low; Saxon, Low", null, "nds", "nds"); + // new Iso639("Low Saxon; Low German; Saxon, Low; German, + // Low",null,"nds","nds"); + new Iso639("Lozi", null, "loz", "loz"); + new Iso639("Luba-Katanga", null, "lub", "lub"); + new Iso639("Luba-Lulua", null, "lua", "lua"); + new Iso639("Luiseno", null, "lui", "lui"); + new Iso639("Lunda", null, "lun", "lun"); + new Iso639("Luo (Kenya and Tanzania)", null, "luo", "luo"); + new Iso639("Lushai", null, "lus", "lus"); + + new Iso639("Macedonian", "mk", "mkd", "mac"); + new Iso639("Madurese", null, "mad", "mad"); + new Iso639("Magahi", null, "mag", "mag"); + new Iso639("Maithili", null, "mai", "mai"); + new Iso639("Makasar", null, "mak", "mak"); + new Iso639("Malagasy", "mg", "mlg", "mlg"); + new Iso639("Malay", "ms", "msa", "may"); + new Iso639("Malayalam", "ml", "mal", "mal"); + new Iso639("Maltese", "mt", "mlt", "mlt"); + new Iso639("Manchu", null, "mnc", "mnc"); + new Iso639("Mandar", null, "mdr", "mdr"); + new Iso639("Mandingo", null, "man", "man"); + new Iso639("Manipuri", null, "mni", "mni"); + new Iso639("Manobo languages", null, "mno", "mno"); + new Iso639("Manx", "gv", "glv", "glv"); + new Iso639("Maori", "mi", "mri", "mao"); + new Iso639("Marathi", "mr", "mar", "mar"); + new Iso639("Mari", null, "chm", "chm"); + new Iso639("Marshall", "mh", "mah", "mah"); + new Iso639("Marwari", null, "mwr", "mwr"); + new Iso639("Masai", null, "mas", "mas"); + new Iso639("Mayan languages", null, "myn", "myn"); + new Iso639("Mende", null, "men", "men"); + new Iso639("Micmac", null, "mic", "mic"); + new Iso639("Minangkabau", null, "min", "min"); + new Iso639("Miscellaneous languages", null, "mis", "mis"); + new Iso639("Mohawk", null, "moh", "moh"); + new Iso639("Moldavian", "mo", "mol", "mol"); + new Iso639("Mon-Khmer (Other)", null, "mkh", "mkh"); + new Iso639("Mongo", null, "lol", "lol"); + new Iso639("Mongolian", "mn", "mon", "mon"); + new Iso639("Mossi", null, "mos", "mos"); + new Iso639("Multiple languages", null, "mul", "mul", LT_MULTIPLE); + new Iso639("Munda languages", null, "mun", "mun"); + new Iso639("Nahuatl", null, "nah", "nah"); + new Iso639("Nauru", "na", "nau", "nau"); + new Iso639("Navajo", "nv", "nav", "nav"); + new Iso639("Ndebele, North", "nd", "nde", "nde"); + new Iso639("Ndebele, South", "nr", "nbl", "nbl"); + new Iso639("Ndonga", "ng", "ndo", "ndo"); + new Iso639("Nepali", "ne", "nep", "nep"); + new Iso639("Newari", null, "new", "new"); + new Iso639("Nias", null, "nia", "nia"); + new Iso639("Niger-Kordofanian (Other)", null, "nic", "nic"); + new Iso639("Nilo-Saharan (Other)", null, "ssa", "ssa"); + new Iso639("Niuean", null, "niu", "niu"); + new Iso639("Norse, Old", null, "non", "non"); + new Iso639("North American Indian(Other)", null, "nai", "nai"); + + new Iso639("Northern Sami", "se", "sme", "sme"); + new Iso639("Norwegian", "no", "nor", "nor"); + new Iso639("Norwegian Bokm?l", "nb", "nob", "nob"); + new Iso639("Norwegian Nynorsk", "nn", "nno", "nno"); + new Iso639("Nubian languages", null, "nub", "nub"); + new Iso639("Nyamwezi", null, "nym", "nym"); + // new Iso639("Nyanja; Chichewa","ny","nya","nya"); + new Iso639("Nyankole", null, "nyn", "nyn"); + new Iso639("Nyoro", null, "nyo", "nyo"); + new Iso639("Nzima", null, "nzi", "nzi"); + + new Iso639("Occitan (post 1500); Proven?al", "oc", "oci", "oci"); + new Iso639("Ojibwa", null, "oji", "oji"); + new Iso639("Oriya", "or", "ori", "ori"); + new Iso639("Oromo", "om", "orm", "orm"); + new Iso639("Osage", null, "osa", "osa"); + new Iso639("Ossetian; Ossetic", "os", "oss", "oss"); + // new Iso639("Ossetic; Ossetian","os","oss","oss"); + new Iso639("Otomian languages", null, "oto", "oto"); + new Iso639("Pahlavi", null, "pal", "pal"); + new Iso639("Palauan", null, "pau", "pau"); + new Iso639("Pali", "pi", "pli", "pli"); + new Iso639("Pampanga", null, "pam", "pam"); + new Iso639("Pangasinan", null, "pag", "pag"); + new Iso639("Panjabi", "pa", "pan", "pan"); + new Iso639("Papiamento", null, "pap", "pap"); + new Iso639("Papuan (Other)", null, "paa", "paa"); + new Iso639("Persian", "fa", "fas", "per"); + new Iso639("Persian, Old (ca.600-400 B.C.)", null, "peo", "peo"); + + new Iso639("Philippine (Other)", null, "phi", "phi"); + new Iso639("Phoenician", null, "phn", "phn"); + new Iso639("Pohnpeian", null, "pon", "pon"); + new Iso639("Polish", "pl", "pol", "pol"); + new Iso639("Portuguese", "pt", "por", "por"); + new Iso639("Prakrit languages", null, "pra", "pra"); + // new Iso639("Proven?al; Occitan (post 1500)","oc","oci","oci"); + new Iso639("Proven?al, Old (to 1500)", null, "pro", "pro"); + new Iso639("Pushto", "ps", "pus", "pus"); + + new Iso639("Quechua", "qu", "que", "que"); + new Iso639("Raeto-Romance", "rm", "roh", "roh"); + new Iso639("Rajasthani", null, "raj", "raj"); + new Iso639("Rapanui", null, "rap", "rap"); + new Iso639("Rarotongan", null, "rar", "rar"); + // Reserved for local use qaa-qtz qaa-qtz + new Iso639("Romance (Other)", null, "roa", "roa"); + new Iso639("Romanian", "ro", "ron", "rum"); + new Iso639("Romany", null, "rom", "rom"); + new Iso639("Rundi", "rn", "run", "run"); + new Iso639("Russian", "ru", "rus", "rus"); + + new Iso639("Salishan languages", null, "sal", "sal"); + new Iso639("Samaritan Aramaic", null, "sam", "sam"); + new Iso639("Sami languages (Other)", null, "smi", "smi"); + new Iso639("Samoan", "sm", "smo", "smo"); + new Iso639("Sandawe", null, "sad", "sad"); + new Iso639("Sango", "sg", "sag", "sag"); + new Iso639("Sanskrit", "sa", "san", "san"); + new Iso639("Santali", null, "sat", "sat"); + new Iso639("Sardinian", "sc", "srd", "srd"); + new Iso639("Sasak", null, "sas", "sas"); + // new Iso639("Saxon, Low; German, Low; Low Saxon; Low + // German",null,"nds","nds"); + new Iso639("Scots", null, "sco", "sco"); + new Iso639("Selkup", null, "sel", "sel"); + new Iso639("Semitic (Other)", null, "sem", "sem"); + new Iso639("Serbian", "sr", "srp", "scc"); + new Iso639("Serer", null, "srr", "srr"); + new Iso639("Shan", null, "shn", "shn"); + new Iso639("Shona", "sn", "sna", "sna"); + new Iso639("Sidamo", null, "sid", "sid"); + new Iso639("Sign languages", null, "sgn", "sgn"); + new Iso639("Siksika", null, "bla", "bla"); + new Iso639("Sindhi", "sd", "snd", "snd"); + new Iso639("Sinhalese", "si", "sin", "sin"); + new Iso639("Sino-Tibetan (Other)", null, "sit", "sit"); + new Iso639("Siouan languages", null, "sio", "sio"); + new Iso639("Slave (Athapascan)", null, "den", "den"); + new Iso639("Slavic (Other)", null, "sla", "sla"); + new Iso639("Slovak", "sk", "slk", "slo"); + new Iso639("Slovenian", "sl", "slv", "slv"); + new Iso639("Sogdian", null, "sog", "sog"); + new Iso639("Somali", "so", "som", "som"); + new Iso639("Songhai", null, "son", "son"); + new Iso639("Soninke", null, "snk", "snk"); + new Iso639("Sorbian languages", null, "wen", "wen"); + new Iso639("Sotho, Northern", null, "nso", "nso"); + new Iso639("Sotho, Southern", "st", "sot", "sot"); + new Iso639("South American Indian (Other)", null, "sai", "sai"); + + new Iso639("Spanish", "es", "spa", "spa"); + new Iso639("Sukuma", null, "suk", "suk"); + new Iso639("Sumerian", null, "sux", "sux"); + new Iso639("Sundanese", "su", "sun", "sun"); + new Iso639("Susu", null, "sus", "sus"); + new Iso639("Swahili", "sw", "swa", "swa"); + new Iso639("Swati", "ss", "ssw", "ssw"); + new Iso639("Swedish", "sv", "swe", "swe"); + new Iso639("Syriac", null, "syr", "syr"); + new Iso639("Tagalog", "tl", "tgl", "tgl"); + new Iso639("Tahitian", "ty", "tah", "tah"); + new Iso639("Tai (Other)", null, "tai", "tai"); + new Iso639("Tajik", "tg", "tgk", "tgk"); + new Iso639("Tamashek", null, "tmh", "tmh"); + new Iso639("Tamil", "ta", "tam", "tam"); + new Iso639("Tatar", "tt", "tat", "tat"); + new Iso639("Telugu", "te", "tel", "tel"); + new Iso639("Tereno", null, "ter", "ter"); + new Iso639("Tetum", null, "tet", "tet"); + new Iso639("Thai", "th", "tha", "tha"); + new Iso639("Tibetan", "bo", "bod", "tib"); + new Iso639("Tigre", null, "tig", "tig"); + new Iso639("Tigrinya", "ti", "tir", "tir"); + new Iso639("Timne", null, "tem", "tem"); + new Iso639("Tiv", null, "tiv", "tiv"); + new Iso639("Tlingit", null, "tli", "tli"); + new Iso639("Tok Pisin", null, "tpi", "tpi"); + new Iso639("Tokelau", null, "tkl", "tkl"); + new Iso639("Tonga (Nyasa)", null, "tog", "tog"); + new Iso639("Tonga (Tonga Islands)", "to", "ton", "ton"); + new Iso639("Tsimshian", null, "tsi", "tsi"); + new Iso639("Tsonga", "ts", "tso", "tso"); + new Iso639("Tswana", "tn", "tsn", "tsn"); + new Iso639("Tumbuka", null, "tum", "tum"); + new Iso639("Turkish", "tr", "tur", "tur"); + new Iso639("Turkish, Ottoman (1500-1928)", null, "ota", "ota"); + new Iso639("Turkmen", "tk", "tuk", "tuk"); + new Iso639("Tuvalu", null, "tvl", "tvl"); + new Iso639("Tuvinian", null, "tyv", "tyv"); + new Iso639("Twi", "tw", "twi", "twi"); + + new Iso639("Ugaritic", null, "uga", "uga"); + new Iso639("Uighur", "ug", "uig", "uig"); + new Iso639("Ukrainian", "uk", "ukr", "ukr"); + new Iso639("Umbundu", null, "umb", "umb"); + new Iso639("Undetermined", null, "und", "und", LT_UNDETERMINED); + new Iso639("Urdu", "ur", "urd", "urd"); + new Iso639("Uzbek", "uz", "uzb", "uzb"); + new Iso639("Vai", null, "vai", "vai"); + new Iso639("Venda", null, "ven", "ven"); + new Iso639("Vietnamese", "vi", "vie", "vie"); + new Iso639("Volap?k", "vo", "vol", "vol"); + new Iso639("Votic", null, "vot", "vot"); + new Iso639("Wakashan languages", null, "wak", "wak"); + new Iso639("Walamo", null, "wal", "wal"); + new Iso639("Waray", null, "war", "war"); + new Iso639("Washo", null, "was", "was"); + new Iso639("Welsh", "cy", "cym", "wel"); + new Iso639("Wolof", "wo", "wol", "wol"); + new Iso639("Xhosa", "xh", "xho", "xho"); + new Iso639("Yakut", null, "sah", "sah"); + new Iso639("Yao", null, "yao", "yao"); + new Iso639("Yapese", null, "yap", "yap"); + new Iso639("Yiddish", "yi", "yid", "yid"); + new Iso639("Yoruba", "yo", "yor", "yor"); + new Iso639("Yupik languages", null, "ypk", "ypk"); + new Iso639("Zande", null, "znd", "znd"); + new Iso639("Zapotec", null, "zap", "zap"); + new Iso639("Zenaga", null, "zen", "zen"); + new Iso639("Zhuang", "za", "zha", "zha"); + new Iso639("Zulu", "zu", "zul", "zul"); + new Iso639("Zuni", null, "zun", "zun"); + + } + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTag.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTag.java new file mode 100644 index 00000000000..9f5ddbade42 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTag.java @@ -0,0 +1,333 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* + * LanguageTag.java + * + * Created on July 24, 2001, 11:45 PM + */ + +package org.eclipse.rdf4j.model.util.language; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * RFC 3066, "Tags for the Identification of Languages". + * + * @author jjc + */ +public class LanguageTag implements LanguageTagCodes { + + String subtags[]; + + private int tagType; + + /** + * Creates new RFC3066 LanguageTag. + * + * @param tag + * The tag to parse and analyse. + * @throws LanguageTagSyntaxException + * If the syntactic rules of RFC3066 section 2.1 are broken. + */ + public LanguageTag(String tag) + throws LanguageTagSyntaxException + { + String lc = tag.toLowerCase(); + List subtagList = new ArrayList(); + int subT; + while (true) { + subT = lc.indexOf('-'); + if (subT != -1) { + subtagList.add(lc.substring(0, subT)); + lc = lc.substring(subT + 1); + } + else + break; + } + subtagList.add(lc); + subtags = new String[subtagList.size()]; + subtagList.toArray(subtags); + int lg = subtags[0].length(); + if (lg == 0 || lg > 8) { + throw new LanguageTagSyntaxException("Primary subtag must be between 1 and 8 alpha characters: " + + tag); + } + for (int j = 0; j < lg; j++) { + int ch = subtags[0].charAt(j); + if (!('a' <= ch && ch <= 'z')) { + throw new LanguageTagSyntaxException("Primary subtag must be between 1 and 8 alpha characters: " + + tag); + } + } + for (int i = 1; i < subtags.length; i++) { + lg = subtags[i].length(); + if (lg == 0 || lg > 8) { + throw new LanguageTagSyntaxException("Subtag " + (i + 1) + + " must be between 1 and 8 alphanumeric characters: " + tag); + } + for (int j = 0; j < lg; j++) { + int ch = subtags[i].charAt(j); + if (!(('a' <= ch && ch <= 'z') || ('0' <= ch && ch <= '9'))) { + throw new LanguageTagSyntaxException("Subtag " + (i + 1) + + " must be between 1 and 8 alphanumeric characters: " + tag); + } + } + } + + tagType = getTagType(); + if (tagType == LT_ILLEGAL) { + throw new LanguageTagSyntaxException(getErrorMessage()); + } + } + + // Primary tag. + + // Second tag. + // Additional tags (either second or third). + // Special cases. + // Overall properties + /** + * The properties of this LanguageTag, expressed as a bitwise or of fields + * from {@link LanguageTagCodes}. If the tag is illegal only + * LT_ILLEGAL is reported. Examples include: + *
    + *
    LT_ISO639
    + *
    en English.
    + *
    LT_ISO639|LT_ISO3166
    + *
    en-GB British English
    + *
    LT_ILLEGAL
    + *
    en-ENGLAND No such country. Never returned in combination + * with other values.
    + *
    LT_PRIVATE_USE
    + *
    x-en-ENGLAND Private tag with private semantics.
    + *
    LT_IANA|LT_EXTRA
    + *
    i-klingon-trekkie Klingon + "trekkie"
    + *
    LT_IANA_DEPRECATED
    + *
    + *
    LT_MULTIPLE|LT_ISO3166|LT_EXTRA
    + *
    mul-CH-dialects
    + *
    LT_ISO639|LT_ISO3166|LT_IANA|LT_EXTRA
    + *
    sgn-US-MA Martha's Vineyard Sign Language
    + *
    + * + * @return A bitwise or of all LT_xxx values that apply. + */ + private int getTagType() { + IanaLanguageTag iana = null; + if (this instanceof IanaLanguageTag) { + iana = (IanaLanguageTag)this; + } + else { + iana = IanaLanguageTag.find(this); + } + Iso639 lang = Iso639.find(subtags[0]); + int rslt = iana == null ? 0 : iana.classification; + if (iana != null) { + if (iana.subtags.length < subtags.length) { + rslt |= LT_EXTRA; + } + } + switch (subtags[0].length()) { + case 1: + switch (subtags[0].charAt(0)) { + case 'x': + return LT_PRIVATE_USE; // reserved for private use. + case 'i': + return iana != null ? rslt : LT_ILLEGAL; + default: + return LT_ILLEGAL; + } + case 2: + if (lang == null) { + return LT_ILLEGAL; + } + rslt |= lang.classification; // all special case tags etc. + break; + case 3: + if (lang == null) { + return LT_ILLEGAL; + } + if (lang.twoCharCode != null) { + return LT_ILLEGAL; // Section 2.3 Para 2 + } + if (!lang.terminologyCode.equals(subtags[0])) { + return LT_ILLEGAL; + // Section 2.3 Para 3 + } + rslt |= lang.classification; // all special case tags etc. + // Section 2.3 para 4,5,6 in a separate function. + break; + default: + return LT_ILLEGAL; + } + if (subtags.length == 1) { + return rslt; + } + switch (subtags[1].length()) { + case 1: + return LT_ILLEGAL; + case 2: + if (Iso3166.find(subtags[1]) == null) { + return LT_ILLEGAL; + } + else { + rslt |= LT_ISO3166; + } + break; + default: + if (iana == null) + rslt |= LT_EXTRA; + } + if (subtags.length > 2 && iana == null) { + rslt |= LT_EXTRA; + } + return rslt; + } + + /** + * An error message describing the reason the tag is illegal. + * + * @return null if legal, or an error message if not. + */ + private String getErrorMessage() { + switch (subtags[0].length()) { + case 1: + switch (subtags[0].charAt(0)) { + case 'x': + return null; // reserved for private use. + case 'i': + if (this instanceof IanaLanguageTag || IanaLanguageTag.find(this) != null) { + return null; + } + return toString() + " not found in IANA langauge registry."; + default: + return "Only 'x' and 'i' single character primary language subtags are defined in RFC3066."; + } + case 2: + if (Iso639.find(subtags[0]) == null) { + return "ISO-639 does not define language: '" + subtags[0] + "'."; + } + break; + case 3: + Iso639 lang = Iso639.find(subtags[0]); + if (lang == null) { + return "ISO-639 does not define language: '" + subtags[0] + "'."; + } + if (lang.twoCharCode != null) { + return "RFC 3066 section 2.3 mandates the use of '" + lang.twoCharCode + "' instead of '" + + subtags[0] + "'."; + // Section 2.3 Para 2 + } + if (!lang.terminologyCode.equals(subtags[0])) { + return "RFC 3066 section 2.3 mandates the use of '" + lang.terminologyCode + "' instead of '" + + subtags[0] + "'."; + // Section 2.3 Para 3 + } + // Section 2.3 para 4,5,6 in a separate function. + break; + default: + return "No primary language subtags of length greater than 3 are currently defined."; + } + if (subtags.length == 1) { + return null; + } + switch (subtags[1].length()) { + case 1: + return "Second language subtags of length 1 are prohibited by RFC3066."; + case 2: + if (Iso3166.find(subtags[1]) == null) { + return "Country code, '" + subtags[1] + "', not found in ISO 3166."; + } + break; + } + return null; + } + + public boolean hasLanguage() { + boolean result = (tagType & LT_ISO639) == LT_ISO639 && (tagType & LT_MULTIPLE) != LT_MULTIPLE + && (tagType & LT_UNDETERMINED) != LT_UNDETERMINED && (tagType & LT_LOCAL_USE) != LT_LOCAL_USE; + return result; + } + + public Iso639 getLanguage() { + Iso639 result = null; + if (hasLanguage()) { + result = Iso639.find(subtags[0]); + } + return result; + } + + public boolean hasCountry() { + boolean result = (tagType & LT_ISO3166) == LT_ISO3166; + return result; + } + + public Iso3166 getCountry() { + Iso3166 result = null; + if (hasCountry()) { + result = Iso3166.find(subtags[1]); + } + return result; + } + + public boolean hasVariant() { + boolean result = (tagType & LT_EXTRA) == LT_EXTRA; + return result; + } + + public String getVariant() { + String result = null; + if (hasVariant()) { + if (hasCountry()) { + result = subtags[2]; + } + else { + result = subtags[1]; + } + } + return result; + } + + public String toString() { + StringBuilder result = new StringBuilder(); + for (String subtag : subtags) { + result.append(subtag); + result.append('-'); + } + result.setLength(result.length() - 1); + return result.toString(); + } + + public Locale toLocale() { + Locale result = null; + + Iso639 iso639Language = getLanguage(); + Iso3166 iso3166Country = getCountry(); + String variant = getVariant(); + + if (iso639Language != null) { + String language = iso639Language.twoCharCode.toLowerCase(); + if (iso3166Country != null) { + String country = iso3166Country.code.toUpperCase(); + if (variant != null) { + result = new Locale(language, country, variant); + } + else { + result = new Locale(language, country); + } + } + else { + result = new Locale(language); + } + } + + return result; + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTagCodes.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTagCodes.java new file mode 100644 index 00000000000..b93dcc15939 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTagCodes.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* + * LanguageTagCodes.java + * + * Created on July 25, 2001, 10:09 AM + */ + +package org.eclipse.rdf4j.model.util.language; + +/** + * Informational values about language codes. Values to be OR-ed together. + * + * @author jjc + */ +public interface LanguageTagCodes { + + /** + * The special tag i-default. + */ + public static final int LT_DEFAULT = 0x0100; + + /** + * A tag with non-standard extra subtags. Set for language tags with + * additional subtags over their IANA registration, or a third subtag for + * unregistered tags of the form ISO639Code-ISO3166Code. + */ + public static final int LT_EXTRA = 0x0080; + + /** + * A tag in the IANA registry. + */ + public static final int LT_IANA = 0x1024; + + /** + * An illegal tag. Some rule of RFC3066 failed, or the tag is not in IANA, or + * ISO639 or ISO3166. + */ + public static final int LT_ILLEGAL = 0x8000; + + /** + * The second subtag is from ISO3166 and identifies a country. + */ + public static final int LT_ISO3166 = 0x0010; + + /** + * The first subtag is from ISO639-1 or ISO639-2 and identifies a language, + */ + public static final int LT_ISO639 = 0x0001; + + /** + * A special ISO639-2 local use language tag. A three letter code + * 'q[a-t][a-z]'. + */ + public static final int LT_LOCAL_USE = 0x0800; + + /** + * The special ISO639-2 language tag mul. This indicates + * multiple languages. + */ + public static final int LT_MULTIPLE = 0x0400; + + /** + * An RFC3066 private use tag. A language tag of the form x-????. + */ + public static final int LT_PRIVATE_USE = 0x0002; + + /** + * The undetermined ISO639-2 language und. + */ + public static final int LT_UNDETERMINED = 0x0200; + + /** + * A language tag that is deprecated in the IANA registry. + */ + public static final int LT_IANA_DEPRECATED = 0x2000; + +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTagSyntaxException.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTagSyntaxException.java new file mode 100644 index 00000000000..d7eaeea12a6 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/language/LanguageTagSyntaxException.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* + * LanguageTagSyntaxException.java + * + * Created on July 25, 2001, 9:32 AM + */ + +package org.eclipse.rdf4j.model.util.language; + +/** + * A LanguageTag did not conform to RFC3066. This exception is for the syntactic + * rules of RFC3066 section 2.1. + * + * @author jjc + */ +public class LanguageTagSyntaxException extends java.lang.Exception { + + /** + * + */ + private static final long serialVersionUID = 5425207434895448094L; + + /** + * Constructs an LanguageTagSyntaxException with the specified + * detail message. + * + * @param msg + * the detail message. + */ + LanguageTagSyntaxException(String msg) { + super(msg); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DC.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DC.java new file mode 100644 index 00000000000..556dee24d17 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DC.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Vocabulary constants for the Dublin Core Metadata Element Set, version 1.1 + * + * @see Dublin Core Metadata + * Element Set, Version 1.1 + * @author Jeen Broekstra + */ +public class DC { + + /** + * Dublin Core elements namespace: http://purl.org/dc/elements/1.1/ + */ + public static final String NAMESPACE = "http://purl.org/dc/elements/1.1/"; + + /** + * Recommend prefix for the Dublin Core elements namespace: "dc" + */ + public static final String PREFIX = "dc"; + + /** + * An immutable {@link Namespace} constant that represents the Dublin Core + * namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + /** + * dc:title + */ + public static final IRI TITLE; + + /** + * dc:source + */ + public static final IRI SOURCE; + + /** + * dc:contributor + */ + public static final IRI CONTRIBUTOR; + + /** + * dc:coverage + */ + public static final IRI COVERAGE; + + /** + * dc:creator + */ + public static final IRI CREATOR; + + /** + * dc:date + */ + public static final IRI DATE; + + /** + * dc:description + */ + public static final IRI DESCRIPTION; + + /** + * dc:format + */ + public static final IRI FORMAT; + + /** + * dc:identifier + */ + public static final IRI IDENTIFIER; + + /** + * dc:language + */ + public static final IRI LANGUAGE; + + /** + * dc:publisher + */ + public static final IRI PUBLISHER; + + /** + * dc:relation + */ + public static final IRI RELATION; + + /** + * dc:rights + */ + public static final IRI RIGHTS; + + /** + * dc:subject + */ + public static final IRI SUBJECT; + + /** + * dc:type + */ + public static final IRI TYPE; + + static { + final ValueFactory f = SimpleValueFactory.getInstance(); + + CONTRIBUTOR = f.createIRI(NAMESPACE, "contributor"); + COVERAGE = f.createIRI(NAMESPACE, "coverage"); + CREATOR = f.createIRI(NAMESPACE, "creator"); + DATE = f.createIRI(NAMESPACE, "date"); + DESCRIPTION = f.createIRI(NAMESPACE, "description"); + FORMAT = f.createIRI(NAMESPACE, "format"); + IDENTIFIER = f.createIRI(NAMESPACE, "identifier"); + LANGUAGE = f.createIRI(NAMESPACE, "language"); + PUBLISHER = f.createIRI(NAMESPACE, "publisher"); + RELATION = f.createIRI(NAMESPACE, "relation"); + RIGHTS = f.createIRI(NAMESPACE, "rights"); + SOURCE = f.createIRI(NAMESPACE, "source"); + SUBJECT = f.createIRI(NAMESPACE, "subject"); + TITLE = f.createIRI(NAMESPACE, "title"); + TYPE = f.createIRI(NAMESPACE, "type"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DCTERMS.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DCTERMS.java new file mode 100644 index 00000000000..689042a1073 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DCTERMS.java @@ -0,0 +1,677 @@ +/* + * Licensed to Aduna under one or more contributor license agreements. + * See the NOTICE.txt file distributed with this work for additional + * information regarding copyright ownership. + * + * Aduna licenses this file to you under the terms of the Aduna BSD + * License (the "License"); you may not use this file except in compliance + * with the License. See the LICENSE.txt file distributed with this work + * for the full License. + * + * 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 org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Vocabulary constants for the Dublin Core Metadata Initiative Metadata Terms. + * + * @see DCMI Metadata + * Terms + * @author Peter Ansell + * @since 2.7.0 + */ +public class DCTERMS { + + /** + * Dublin Core Terms namespace: http://purl.org/dc/terms/ + */ + public static final String NAMESPACE = "http://purl.org/dc/terms/"; + + /** + * Recommend prefix for the Dublin Core Terms namespace: "dcterms" + */ + public static final String PREFIX = "dcterms"; + + /** + * An immutable {@link Namespace} constant that represents the Dublin Core + * Terms namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + // ---------------------------------------- + // Properties common to Dublin Core Elements set + // ---------------------------------------- + + /** + * http://purl.org/dc/terms/contributor + */ + public static final IRI CONTRIBUTOR; + + /** + * http://purl.org/dc/terms/coverage + */ + public static final IRI COVERAGE; + + /** + * http://purl.org/dc/terms/creator + */ + public static final IRI CREATOR; + + /** + * http://purl.org/dc/terms/date + */ + public static final IRI DATE; + + /** + * http://purl.org/dc/terms/description + */ + public static final IRI DESCRIPTION; + + /** + * http://purl.org/dc/terms/format + */ + public static final IRI FORMAT; + + /** + * http://purl.org/dc/terms/identifier + */ + public static final IRI IDENTIFIER; + + /** + * http://purl.org/dc/terms/language + */ + public static final IRI LANGUAGE; + + /** + * http://purl.org/dc/terms/publisher + */ + public static final IRI PUBLISHER; + + /** + * http://purl.org/dc/terms/relation + */ + public static final IRI RELATION; + + /** + * http://purl.org/dc/terms/rights + */ + public static final IRI RIGHTS; + + /** + * http://purl.org/dc/terms/source + */ + public static final IRI SOURCE; + + /** + * http://purl.org/dc/terms/subject + */ + public static final IRI SUBJECT; + + /** + * http://purl.org/dc/terms/title + */ + public static final IRI TITLE; + + /** + * http://purl.org/dc/terms/type + */ + public static final IRI TYPE; + + // ---------------------------------------- + // Properties unique to Dublin Core Terms set + // ---------------------------------------- + + /** + * http://purl.org/dc/terms/abstract + */ + public static final IRI ABSTRACT; + + /** + * http://purl.org/dc/terms/accessRights + */ + public static final IRI ACCESS_RIGHTS; + + /** + * http://purl.org/dc/terms/accrualMethod + */ + public static final IRI ACCRUAL_METHOD; + + /** + * http://purl.org/dc/terms/accrualPeriodicity + */ + public static final IRI ACCRUAL_PERIODICITY; + + /** + * http://purl.org/dc/terms/ accrualPolicy + */ + public static final IRI ACCRUAL_POLICY; + + /** + * http://purl.org/dc/terms/alternative + */ + public static final IRI ALTERNATIVE; + + /** + * http://purl.org/dc/terms/audience + */ + public static final IRI AUDIENCE; + + /** + * http://purl.org/dc/terms/available + */ + public static final IRI AVAILABLE; + + /** + * http://purl.org/dc/terms/bibliographicCitation + */ + public static final IRI BIBLIOGRAPHIC_CITATION; + + /** + * http://purl.org/dc/terms/conformsTo + */ + public static final IRI CONFORMS_TO; + + /** + * http://purl.org/dc/terms/created + */ + public static final IRI CREATED; + + /** + * http://purl.org/dc/terms/dateAccepted + */ + public static final IRI DATE_ACCEPTED; + + /** + * http://purl.org/dc/terms/dateCopyrighted + */ + public static final IRI DATE_COPYRIGHTED; + + /** + * http://purl.org/dc/terms/dateSubmitted + */ + public static final IRI DATE_SUBMITTED; + + /** + * http://purl.org/dc/terms/educationLevel + */ + public static final IRI EDUCATION_LEVEL; + + /** + * http://purl.org/dc/terms/extent + */ + public static final IRI EXTENT; + + /** + * http://purl.org/dc/terms/hasFormat + */ + public static final IRI HAS_FORMAT; + + /** + * http://purl.org/dc/terms/hasPart + */ + public static final IRI HAS_PART; + + /** + * http://purl.org/dc/terms/hasVersion + */ + public static final IRI HAS_VERSION; + + /** + * http://purl.org/dc/terms/instructionalMethod + */ + public static final IRI INSTRUCTIONAL_METHOD; + + /** + * http://purl.org/dc/terms/isFormatOf + */ + public static final IRI IS_FORMAT_OF; + + /** + * http://purl.org/dc/terms/isPartOf + */ + public static final IRI IS_PART_OF; + + /** + * http://purl.org/dc/terms/isReferencedBy + */ + public static final IRI IS_REFERENCED_BY; + + /** + * http://purl.org/dc/terms/isReplacedBy + */ + public static final IRI IS_REPLACED_BY; + + /** + * http://purl.org/dc/terms/isRequiredBy + */ + public static final IRI IS_REQUIRED_BY; + + /** + * http://purl.org/dc/terms/issued + */ + public static final IRI ISSUED; + + /** + * http://purl.org/dc/terms/isVersionOf + */ + public static final IRI IS_VERSION_OF; + + /** + * http://purl.org/dc/terms/license + */ + public static final IRI LICENSE; + + /** + * http://purl.org/dc/terms/mediator + */ + public static final IRI MEDIATOR; + + /** + * http://purl.org/dc/terms/medium + */ + public static final IRI MEDIUM; + + /** + * http://purl.org/dc/terms/modified + */ + public static final IRI MODIFIED; + + /** + * http://purl.org/dc/terms/provenance + */ + public static final IRI PROVENANCE; + + /** + * http://purl.org/dc/terms/references + */ + public static final IRI REFERENCES; + + /** + * http://purl.org/dc/terms/replaces + */ + public static final IRI REPLACES; + + /** + * http://purl.org/dc/terms/requires + */ + public static final IRI REQUIRES; + + /** + * http://purl.org/dc/terms/rightsHolder + */ + public static final IRI RIGHTS_HOLDER; + + /** + * http://purl.org/dc/terms/spatial + */ + public static final IRI SPATIAL; + + /** + * http://purl.org/dc/terms/tableOfContents + */ + public static final IRI TABLE_OF_CONTENTS; + + /** + * http://purl.org/dc/terms/temporal + */ + public static final IRI TEMPORAL; + + /** + * http://purl.org/dc/terms/valid + */ + public static final IRI VALID; + + // ---------------------------------------- + // Vocabulary encoding schemes in Dublin Core Terms + // ---------------------------------------- + + /** + * http://purl.org/dc/terms/DCMIType + */ + public static final IRI DCMI_TYPE; + + /** + * http://purl.org/dc/terms/DDC + */ + public static final IRI DDC; + + /** + * http://purl.org/dc/terms/IMT + */ + public static final IRI IMT; + + /** + * http://purl.org/dc/terms/LCC + */ + public static final IRI LCC; + + /** + * http://purl.org/dc/terms/LCSH + */ + public static final IRI LCSH; + + /** + * http://purl.org/dc/terms/MESH + */ + public static final IRI MESH; + + /** + * http://purl.org/dc/terms/NLM + */ + public static final IRI NLM; + + /** + * http://purl.org/dc/terms/TGN + */ + public static final IRI TGN; + + /** + * http://purl.org/dc/terms/UDC + */ + public static final IRI UDC; + + // ---------------------------------------- + // Syntax encoding schemes in Dublin Core Terms + // ---------------------------------------- + + /** + * http://purl.org/dc/terms/Box + */ + public static final IRI BOX; + + /** + * http://purl.org/dc/terms/ISO3166 + */ + public static final IRI ISO3166; + + /** + * http://purl.org/dc/terms/ISO639-2 + */ + public static final IRI ISO639_2; + + /** + * http://purl.org/dc/terms/ISO639-3 + */ + public static final IRI ISO639_3; + + /** + * http://purl.org/dc/terms/Period + */ + public static final IRI PERIOD; + + /** + * http://purl.org/dc/terms/Point + */ + public static final IRI POINT; + + /** + * http://purl.org/dc/terms/RFC1766 + */ + public static final IRI RFC1766; + + /** + * http://purl.org/dc/terms/RFC3066 + */ + public static final IRI RFC3066; + + /** + * http://purl.org/dc/terms/RFC4646 + */ + public static final IRI RFC4646; + + /** + * http://purl.org/dc/terms/RFC5646 + */ + public static final IRI RFC5646; + + /** + * http://purl.org/dc/terms/URI + */ + public static final IRI URI; + + /** + * http://purl.org/dc/terms/W3CDTF + */ + public static final IRI W3CDTF; + + // ---------------------------------------- + // Classes in Dublin Core Terms + // ---------------------------------------- + + /** + * http://purl.org/dc/terms/Agent + */ + public static final IRI AGENT; + + /** + * http://purl.org/dc/terms/AgentClass + */ + public static final IRI AGENT_CLASS; + + /** + * http://purl.org/dc/terms/BibliographicResource + */ + public static final IRI BIBLIOGRAPHIC_RESOURCE; + + /** + * http://purl.org/dc/terms/FileFormat + */ + public static final IRI FILE_FORMAT; + + /** + * http://purl.org/dc/terms/Frequency + */ + public static final IRI FREQUENCY; + + /** + * http://purl.org/dc/terms/Jurisdiction + */ + public static final IRI JURISDICTION; + + /** + * http://purl.org/dc/terms/LicenseDocument + */ + public static final IRI LICENSE_DOCUMENT; + + /** + * http://purl.org/dc/terms/LinguisticSystem + */ + public static final IRI LINGUISTIC_SYSTEM; + + /** + * http://purl.org/dc/terms/Location + */ + public static final IRI LOCATION; + + /** + * http://purl.org/dc/terms/LocationPeriodOrJurisdiction + */ + public static final IRI LOCATION_PERIOD_OR_JURISDICTION; + + /** + * http://purl.org/dc/terms/MediaType + */ + public static final IRI MEDIA_TYPE; + + /** + * http://purl.org/dc/terms/MediaTypeOrExtent + */ + public static final IRI MEDIA_TYPE_OR_EXTENT; + + /** + * http://purl.org/dc/terms/MethodOfAccrual + */ + public static final IRI METHOD_OF_ACCRUAL; + + /** + * http://purl.org/dc/terms/MethodOfInstruction + */ + public static final IRI METHOD_OF_INSTRUCTION; + + /** + * http://purl.org/dc/terms/PeriodOfTime + */ + public static final IRI PERIOD_OF_TIME; + + /** + * http://purl.org/dc/terms/PhysicalMedium + */ + public static final IRI PHYSICAL_MEDIUM; + + /** + * http://purl.org/dc/terms/PhysicalResource + */ + public static final IRI PHYSICAL_RESOURCE; + + /** + * http://purl.org/dc/terms/Policy + */ + public static final IRI POLICY; + + /** + * http://purl.org/dc/terms/ProvenanceStatement + */ + public static final IRI PROVENANCE_STATEMENT; + + /** + * http://purl.org/dc/terms/RightsStatement + */ + public static final IRI RIGHTS_STATEMENT; + + /** + * http://purl.org/dc/terms/SizeOrDuration + */ + public static final IRI SIZE_OR_DURATION; + + /** + * http://purl.org/dc/terms/Standard + */ + public static final IRI STANDARD; + + // Static initializer for fields + + static { + final ValueFactory f = SimpleValueFactory.getInstance(); + + // Properties common to Dublin Core Elements + CONTRIBUTOR = f.createIRI(NAMESPACE, "contributor"); + COVERAGE = f.createIRI(NAMESPACE, "coverage"); + CREATOR = f.createIRI(NAMESPACE, "creator"); + DATE = f.createIRI(NAMESPACE, "date"); + DESCRIPTION = f.createIRI(NAMESPACE, "description"); + FORMAT = f.createIRI(NAMESPACE, "format"); + IDENTIFIER = f.createIRI(NAMESPACE, "identifier"); + LANGUAGE = f.createIRI(NAMESPACE, "language"); + PUBLISHER = f.createIRI(NAMESPACE, "publisher"); + RELATION = f.createIRI(NAMESPACE, "relation"); + RIGHTS = f.createIRI(NAMESPACE, "rights"); + SOURCE = f.createIRI(NAMESPACE, "source"); + SUBJECT = f.createIRI(NAMESPACE, "subject"); + TITLE = f.createIRI(NAMESPACE, "title"); + TYPE = f.createIRI(NAMESPACE, "type"); + + // Properties unique to Dublin Core Terms + ABSTRACT = f.createIRI(NAMESPACE, "abstract"); + ACCESS_RIGHTS = f.createIRI(NAMESPACE, "accessRights"); + ACCRUAL_METHOD = f.createIRI(NAMESPACE, "accuralMethod"); + ACCRUAL_PERIODICITY = f.createIRI(NAMESPACE, "accrualPeriodicity"); + ACCRUAL_POLICY = f.createIRI(NAMESPACE, "accrualPolicy"); + ALTERNATIVE = f.createIRI(NAMESPACE, "alternative"); + AUDIENCE = f.createIRI(NAMESPACE, "audience"); + AVAILABLE = f.createIRI(NAMESPACE, "available"); + BIBLIOGRAPHIC_CITATION = f.createIRI(NAMESPACE, "bibliographicCitation"); + CONFORMS_TO = f.createIRI(NAMESPACE, "conformsTo"); + CREATED = f.createIRI(NAMESPACE, "created"); + DATE_ACCEPTED = f.createIRI(NAMESPACE, "dateAccepted"); + DATE_COPYRIGHTED = f.createIRI(NAMESPACE, "dateCopyrighted"); + DATE_SUBMITTED = f.createIRI(NAMESPACE, "dateSubmitted"); + EDUCATION_LEVEL = f.createIRI(NAMESPACE, "educationLevel"); + EXTENT = f.createIRI(NAMESPACE, "extent"); + HAS_FORMAT = f.createIRI(NAMESPACE, "hasFormat"); + HAS_PART = f.createIRI(NAMESPACE, "hasPart"); + HAS_VERSION = f.createIRI(NAMESPACE, "hasVersion"); + INSTRUCTIONAL_METHOD = f.createIRI(NAMESPACE, "instructionalMethod"); + IS_FORMAT_OF = f.createIRI(NAMESPACE, "isFormatOf"); + IS_PART_OF = f.createIRI(NAMESPACE, "isPartOf"); + IS_REFERENCED_BY = f.createIRI(NAMESPACE, "isReferencedBy"); + IS_REPLACED_BY = f.createIRI(NAMESPACE, "isReplacedBy"); + IS_REQUIRED_BY = f.createIRI(NAMESPACE, "isRequiredBy"); + IS_VERSION_OF = f.createIRI(NAMESPACE, "isVersionOf"); + ISSUED = f.createIRI(NAMESPACE, "issued"); + LICENSE = f.createIRI(NAMESPACE, "license"); + MEDIATOR = f.createIRI(NAMESPACE, "mediator"); + MEDIUM = f.createIRI(NAMESPACE, "medium"); + MODIFIED = f.createIRI(NAMESPACE, "modified"); + PROVENANCE = f.createIRI(NAMESPACE, "provenance"); + REFERENCES = f.createIRI(NAMESPACE, "references"); + REPLACES = f.createIRI(NAMESPACE, "replaces"); + REQUIRES = f.createIRI(NAMESPACE, "requires"); + RIGHTS_HOLDER = f.createIRI(NAMESPACE, "rightsHolder"); + SPATIAL = f.createIRI(NAMESPACE, "spatial"); + TABLE_OF_CONTENTS = f.createIRI(NAMESPACE, "tableOfContents"); + TEMPORAL = f.createIRI(NAMESPACE, "temporal"); + VALID = f.createIRI(NAMESPACE, "valid"); + + // Vocabulary encoding schemes in Dublin Core Terms + + DCMI_TYPE = f.createIRI(NAMESPACE, "DCMIType"); + DDC = f.createIRI(NAMESPACE, "DDC"); + IMT = f.createIRI(NAMESPACE, "IMT"); + LCC = f.createIRI(NAMESPACE, "LCC"); + LCSH = f.createIRI(NAMESPACE, "LCSH"); + MESH = f.createIRI(NAMESPACE, "MESH"); + NLM = f.createIRI(NAMESPACE, "NLM"); + TGN = f.createIRI(NAMESPACE, "TGN"); + UDC = f.createIRI(NAMESPACE, "UDC"); + + // Syntax encoding schemes in Dublin Core Terms + + BOX = f.createIRI(NAMESPACE, "Box"); + ISO3166 = f.createIRI(NAMESPACE, "ISO3166"); + ISO639_2 = f.createIRI(NAMESPACE, "ISO639-2"); + ISO639_3 = f.createIRI(NAMESPACE, "ISO639-3"); + PERIOD = f.createIRI(NAMESPACE, "Period"); + POINT = f.createIRI(NAMESPACE, "Point"); + RFC1766 = f.createIRI(NAMESPACE, "RFC1766"); + RFC3066 = f.createIRI(NAMESPACE, "RFC3066"); + RFC4646 = f.createIRI(NAMESPACE, "RFC4646"); + RFC5646 = f.createIRI(NAMESPACE, "RFC5646"); + URI = f.createIRI(NAMESPACE, "URI"); + W3CDTF = f.createIRI(NAMESPACE, "W3CDTF"); + + // Classes in Dublin Core Terms + + AGENT = f.createIRI(NAMESPACE, "Agent"); + AGENT_CLASS = f.createIRI(NAMESPACE, "AgentClass"); + BIBLIOGRAPHIC_RESOURCE = f.createIRI(NAMESPACE, "BibliographicResource"); + FILE_FORMAT = f.createIRI(NAMESPACE, "FileFormat"); + FREQUENCY = f.createIRI(NAMESPACE, "Frequency"); + JURISDICTION = f.createIRI(NAMESPACE, "Jurisdiction"); + LICENSE_DOCUMENT = f.createIRI(NAMESPACE, "LicenseDocument"); + LINGUISTIC_SYSTEM = f.createIRI(NAMESPACE, "LinguisticSystem"); + LOCATION = f.createIRI(NAMESPACE, "Location"); + LOCATION_PERIOD_OR_JURISDICTION = f.createIRI(NAMESPACE, "LocationPeriodOrJurisdiction"); + MEDIA_TYPE = f.createIRI(NAMESPACE, "MediaType"); + MEDIA_TYPE_OR_EXTENT = f.createIRI(NAMESPACE, "MediaTypeOrExtent"); + METHOD_OF_ACCRUAL = f.createIRI(NAMESPACE, "MethodOfAccrual"); + METHOD_OF_INSTRUCTION = f.createIRI(NAMESPACE, "MethodOfInstruction"); + PERIOD_OF_TIME = f.createIRI(NAMESPACE, "PeriodOfTime"); + PHYSICAL_MEDIUM = f.createIRI(NAMESPACE, "PhysicalMedium"); + PHYSICAL_RESOURCE = f.createIRI(NAMESPACE, "PhysicalResource"); + POLICY = f.createIRI(NAMESPACE, "Policy"); + PROVENANCE_STATEMENT = f.createIRI(NAMESPACE, "ProvenanceStatement"); + RIGHTS_STATEMENT = f.createIRI(NAMESPACE, "RightsStatement"); + SIZE_OR_DURATION = f.createIRI(NAMESPACE, "SizeOrDuration"); + STANDARD = f.createIRI(NAMESPACE, "Standard"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DOAP.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DOAP.java new file mode 100644 index 00000000000..2a9cb57540a --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/DOAP.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Constants for DOAP primitives and for the DOAP namespace. + */ +public class DOAP { + + public static final String NAMESPACE = "http://usefulinc.com/ns/doap#"; + + /** + * Classes + */ + + public final static IRI PROJECT; + + public final static IRI VERSION; + + /** + * Properties + */ + + public final static IRI NAME; + + public final static IRI HOMEPAGE; + + public final static IRI OLD_HOMEPAGE; + + public final static IRI LICENSE; + + public final static IRI DESCRIPTION; + + public final static IRI PROGRAMMING_LANGUAGE; + + public final static IRI IMPLEMENTS; + + public final static IRI CATEGORY; + + public final static IRI DOWNLOAD_PAGE; + + public final static IRI MAILING_LIST; + + public final static IRI BUG_DATABASE; + + public final static IRI BLOG; + + public final static IRI DEVELOPER; + + public final static IRI MAINTAINER; + + public final static IRI DOCUMENTER; + + public final static IRI RELEASE; + + public final static IRI CREATED; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + PROJECT = factory.createIRI(DOAP.NAMESPACE, "Project"); + VERSION = factory.createIRI(DOAP.NAMESPACE, "Version"); + + NAME = factory.createIRI(DOAP.NAMESPACE, "name"); + HOMEPAGE = factory.createIRI(DOAP.NAMESPACE, "homepage"); + OLD_HOMEPAGE = factory.createIRI(DOAP.NAMESPACE, "old-homepage"); + LICENSE = factory.createIRI(DOAP.NAMESPACE, "license"); + DESCRIPTION = factory.createIRI(DOAP.NAMESPACE, "description"); + PROGRAMMING_LANGUAGE = factory.createIRI(DOAP.NAMESPACE, "programming-language"); + IMPLEMENTS = factory.createIRI(DOAP.NAMESPACE, "implements"); + CATEGORY = factory.createIRI(DOAP.NAMESPACE, "category"); + DOWNLOAD_PAGE = factory.createIRI(DOAP.NAMESPACE, "download-page"); + MAILING_LIST = factory.createIRI(DOAP.NAMESPACE, "mailing-list"); + BUG_DATABASE = factory.createIRI(DOAP.NAMESPACE, "bug-database"); + BLOG = factory.createIRI(DOAP.NAMESPACE, "blog"); + DEVELOPER = factory.createIRI(DOAP.NAMESPACE, "developer"); + MAINTAINER = factory.createIRI(DOAP.NAMESPACE, "maintainer"); + DOCUMENTER = factory.createIRI(DOAP.NAMESPACE, "documenter"); + RELEASE = factory.createIRI(DOAP.NAMESPACE, "release"); + CREATED = factory.createIRI(DOAP.NAMESPACE, "created"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/EARL.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/EARL.java new file mode 100644 index 00000000000..9b3c72cf622 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/EARL.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Constants for EARL primitives and for the EARL namespace. + */ +public class EARL { + + /** + * The EARL namespace: http://www.w3.org/ns/earl# + */ + public static final String NAMESPACE = "http://www.w3.org/ns/earl#"; + + /** + * The recommended prefix for the EARL namespace: "earl" + */ + public static final String PREFIX = "earl"; + + public final static IRI ASSERTOR; + + public final static IRI ASSERTION; + + public final static IRI ASSERTEDBY; + + public final static IRI SUBJECT; + + public final static IRI TEST; + + public final static IRI TEST_SUBJECT; + + public final static IRI RESULT; + + public final static IRI MODE; + + public final static IRI TESTRESULT; + + public final static IRI OUTCOME; + + public final static IRI SOFTWARE; + + // Outcome values + + public final static IRI PASS; + + public final static IRI FAIL; + + public final static IRI CANNOTTELL; + + public final static IRI NOTAPPLICABLE; + + public final static IRI NOTTESTED; + + // Test modes + + public final static IRI MANUAL; + + public final static IRI AUTOMATIC; + + public final static IRI SEMIAUTOMATIC; + + public final static IRI NOTAVAILABLE; + + public final static IRI HEURISTIC; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + ASSERTOR = factory.createIRI(EARL.NAMESPACE, "Assertor"); + ASSERTION = factory.createIRI(EARL.NAMESPACE, "Assertion"); + ASSERTEDBY = factory.createIRI(EARL.NAMESPACE, "assertedBy"); + SUBJECT = factory.createIRI(EARL.NAMESPACE, "subject"); + TEST = factory.createIRI(EARL.NAMESPACE, "test"); + TEST_SUBJECT = factory.createIRI(EARL.NAMESPACE, "TestSubject"); + RESULT = factory.createIRI(EARL.NAMESPACE, "result"); + MODE = factory.createIRI(EARL.NAMESPACE, "mode"); + TESTRESULT = factory.createIRI(EARL.NAMESPACE, "TestResult"); + OUTCOME = factory.createIRI(EARL.NAMESPACE, "outcome"); + SOFTWARE = factory.createIRI(EARL.NAMESPACE, "Software"); + + // Outcome values + + PASS = factory.createIRI(EARL.NAMESPACE, "pass"); + FAIL = factory.createIRI(EARL.NAMESPACE, "fail"); + CANNOTTELL = factory.createIRI(EARL.NAMESPACE, "cannotTell"); + NOTAPPLICABLE = factory.createIRI(EARL.NAMESPACE, "notApplicable"); + NOTTESTED = factory.createIRI(EARL.NAMESPACE, "notTested"); + + // Test modes + MANUAL = factory.createIRI(EARL.NAMESPACE, "manual"); + AUTOMATIC = factory.createIRI(EARL.NAMESPACE, "automatic"); + SEMIAUTOMATIC = factory.createIRI(EARL.NAMESPACE, "semiAutomatic"); + NOTAVAILABLE = factory.createIRI(EARL.NAMESPACE, "notAvailable"); + HEURISTIC = factory.createIRI(EARL.NAMESPACE, "heuristic"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/FN.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/FN.java new file mode 100644 index 00000000000..c32a7b4a3bc --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/FN.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Defines constants for the standard XPath functions. + * + * @see XPath functions + * @author Jeen Broekstra + */ +public class FN { + + /** + * The XPath functions namespace ( + * http://www.w3.org/2005/xpath-functions#). + */ + public static final String NAMESPACE = "http://www.w3.org/2005/xpath-functions#"; + + /** + * Recommended prefix for the XPath Functions namespace: "fn" + */ + public static final String PREFIX = "fn"; + + /** + * An immutable {@link Namespace} constant that represents the XPath + * Functions namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + /** fn:concat */ + public static final IRI CONCAT; + + /** fn:contains */ + public static final IRI CONTAINS; + + /** fn:day-from-dateTime */ + public static final IRI DAY_FROM_DATETIME; + + /** fn:encode-for-uri */ + public static final IRI ENCODE_FOR_URI; + + /** fn:ends-with */ + public static final IRI ENDS_WITH; + + /** fn:hours-from-dateTime */ + public static final IRI HOURS_FROM_DATETIME; + + /** fn:lower-case */ + public static final IRI LOWER_CASE; + + /** fn:minutes-from-dateTime */ + public static final IRI MINUTES_FROM_DATETIME; + + /** fn:month-from-dateTime */ + public static final IRI MONTH_FROM_DATETIME; + + /** fn:numeric-abs */ + public static final IRI NUMERIC_ABS; + + /** fn:numeric-ceil */ + public static final IRI NUMERIC_CEIL; + + /** fn:numeric-floor */ + public static final IRI NUMERIC_FLOOR; + + /** fn:numeric-round */ + public static final IRI NUMERIC_ROUND; + + /** fn:replace */ + public static final IRI REPLACE; + + /** fn:seconds-from-dateTime */ + public static final IRI SECONDS_FROM_DATETIME; + + /** fn:starts-with */ + public static final IRI STARTS_WITH; + + /** fn:string-length */ + public static final IRI STRING_LENGTH; + + /** fn:substring */ + public static final IRI SUBSTRING; + + /** fn:substring-before */ + public static final IRI SUBSTRING_BEFORE; + + /** fn:substring-after */ + public static final IRI SUBSTRING_AFTER; + + /** fn:timezone-from-dateTime */ + public static final IRI TIMEZONE_FROM_DATETIME; + + /** fn:upper-case */ + public static final IRI UPPER_CASE; + + /** fn:year-from-dateTime */ + public static final IRI YEAR_FROM_DATETIME; + + static { + ValueFactory f = SimpleValueFactory.getInstance(); + + CONCAT = f.createIRI(NAMESPACE, "concat"); + + CONTAINS = f.createIRI(NAMESPACE, "contains"); + + DAY_FROM_DATETIME = f.createIRI(NAMESPACE, "day-from-dateTime"); + + ENCODE_FOR_URI = f.createIRI(NAMESPACE, "encode-for-uri"); + + ENDS_WITH = f.createIRI(NAMESPACE, "ends-with"); + + HOURS_FROM_DATETIME = f.createIRI(NAMESPACE, "hours-from-dateTime"); + + LOWER_CASE = f.createIRI(NAMESPACE, "lower-case"); + + MINUTES_FROM_DATETIME = f.createIRI(NAMESPACE, "minutes-from-dateTime"); + + MONTH_FROM_DATETIME = f.createIRI(NAMESPACE, "month-from-dateTime"); + + NUMERIC_ABS = f.createIRI(NAMESPACE, "numeric-abs"); + + NUMERIC_CEIL = f.createIRI(NAMESPACE, "numeric-ceil"); + + NUMERIC_FLOOR = f.createIRI(NAMESPACE, "numeric-floor"); + + NUMERIC_ROUND = f.createIRI(NAMESPACE, "numeric-round"); + + REPLACE = f.createIRI(NAMESPACE, "replace"); + + SECONDS_FROM_DATETIME = f.createIRI(NAMESPACE, "seconds-from-dateTime"); + + STARTS_WITH = f.createIRI(NAMESPACE, "starts-with"); + + STRING_LENGTH = f.createIRI(NAMESPACE, "string-length"); + + SUBSTRING = f.createIRI(NAMESPACE, "substring"); + + SUBSTRING_BEFORE = f.createIRI(NAMESPACE, "substring-before"); + + SUBSTRING_AFTER = f.createIRI(NAMESPACE, "substring-after"); + + TIMEZONE_FROM_DATETIME = f.createIRI(NAMESPACE, "timezone-from-dateTime"); + + UPPER_CASE = f.createIRI(NAMESPACE, "upper-case"); + + YEAR_FROM_DATETIME = f.createIRI(NAMESPACE, "year-from-dateTime"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/FOAF.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/FOAF.java new file mode 100644 index 00000000000..b9da9db7211 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/FOAF.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Constants for FOAF primitives and for the FOAF namespace.
    + * Resources here are defined according to the FOAF specs on http://xmlns.com/foaf/spec/, + * version 0.99, 14 January 2014 + */ +public class FOAF { + + /** + * The FOAF namespace: http://xmlns.com/foaf/0.1/ + */ + public static final String NAMESPACE = "http://xmlns.com/foaf/0.1/"; + + /** + * The recommended prefix for the FOAF namespace: "foaf" + */ + public static final String PREFIX = "foaf"; + + // ----- Classes ------ + public final static IRI AGENT; + public final static IRI DOCUMENT; + public final static IRI GROUP; + public final static IRI IMAGE; + public final static IRI LABEL_PROPERTY; + public final static IRI ONLINE_ACCOUNT; + public final static IRI ONLINE_CHAT_ACCOUNT; + public final static IRI ONLINE_ECOMMERCE_ACCOUNT; + public final static IRI ONLINE_GAMING_ACCOUNT; + public final static IRI ORGANIZATION; + public final static IRI PERSON; + public final static IRI PERSONAL_PROFILE_DOCUMENT; + public final static IRI PROJECT; + + // ----- Properties ------ + public final static IRI ACCOUNT; + public final static IRI ACCOUNT_NAME; + public final static IRI ACCOUNT_SERVICE_HOMEPAGE; + public final static IRI AGE; + public final static IRI AIM_CHAT_ID; + public final static IRI BASED_NEAR; + public final static IRI BIRTHDAY; + public final static IRI CURRENT_PROJECT; + public final static IRI DEPICTION; + public final static IRI DEPICTS; + public final static IRI DNA_CHECKSUM; + public final static IRI FAMILY_NAME; + /** @deprecated Use FAMILY_NAME instead for new statements */ + @Deprecated + public final static IRI FAMILYNAME; + public final static IRI FIRST_NAME; + public final static IRI FOCUS; + public final static IRI FUNDED_BY; + public final static IRI GEEKCODE; + public final static IRI GENDER; + public final static IRI GIVEN_NAME; + /** @deprecated Use GIVEN_NAME instead for new statements */ + @Deprecated + public final static IRI GIVENNAME; + public final static IRI HOLDS_ACCOUNT; + public final static IRI HOMEPAGE; + public final static IRI ICQ_CHAT_ID; + public final static IRI IMG; + public final static IRI INTEREST; + public final static IRI IS_PRIMARY_TOPIC_OF; + public final static IRI JABBER_ID; + public final static IRI KNOWS; + public final static IRI LAST_NAME; + public final static IRI LOGO; + public final static IRI MADE; + public final static IRI MAKER; + public static final IRI MBOX; + public static final IRI MBOX_SHA1SUM; + public static final IRI MEMBER; + public static final IRI MEMBERSHIP_CLASS; + public static final IRI MSN_CHAT_ID; + public static final IRI MYERS_BRIGGS; + public final static IRI NAME; + public final static IRI NICK; + public final static IRI OPENID; + public final static IRI PAGE; + public final static IRI PAST_PROJECT; + public final static IRI PHONE; + public final static IRI PLAN; + public final static IRI PRIMARY_TOPIC; + public final static IRI PUBLICATIONS; + public final static IRI SCHOOL_HOMEPAGE; + public final static IRI SHA1; + public final static IRI SKYPE_ID; + public final static IRI STATUS; + public final static IRI SURNAME; + public final static IRI THEME; + public final static IRI THUMBNAIL; + public final static IRI TIPJAR; + public final static IRI TITLE; + public final static IRI TOPIC; + public final static IRI TOPIC_INTEREST; + public final static IRI WEBLOG; + public final static IRI WORK_INFO_HOMEPAGE; + public final static IRI WORKPLACE_HOMEPAGE; + public final static IRI YAHOO_CHAT_ID; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + + // ----- Classes ------ + AGENT = factory.createIRI(FOAF.NAMESPACE, "Agent"); + DOCUMENT = factory.createIRI(FOAF.NAMESPACE, "Document"); + GROUP = factory.createIRI(FOAF.NAMESPACE, "Group"); + IMAGE = factory.createIRI(FOAF.NAMESPACE, "Image"); + LABEL_PROPERTY = factory.createIRI(FOAF.NAMESPACE, "LabelProperty"); + ONLINE_ACCOUNT = factory.createIRI(FOAF.NAMESPACE, "OnlineAccount"); + ONLINE_CHAT_ACCOUNT = factory.createIRI(FOAF.NAMESPACE, "OnlineChatAccount"); + ONLINE_ECOMMERCE_ACCOUNT = factory.createIRI(FOAF.NAMESPACE, "OnlineEcommerceAccount"); + ONLINE_GAMING_ACCOUNT = factory.createIRI(FOAF.NAMESPACE, "OnlineGamingAccount"); + ORGANIZATION = factory.createIRI(FOAF.NAMESPACE, "Organization"); + PERSON = factory.createIRI(FOAF.NAMESPACE, "Person"); + PERSONAL_PROFILE_DOCUMENT = factory.createIRI(FOAF.NAMESPACE, "PersonalProfileDocument"); + PROJECT = factory.createIRI(FOAF.NAMESPACE, "Project"); + + // ----- Properties ------ + ACCOUNT = factory.createIRI(FOAF.NAMESPACE, "account"); + ACCOUNT_NAME = factory.createIRI(FOAF.NAMESPACE, "accountName"); + ACCOUNT_SERVICE_HOMEPAGE = factory.createIRI(FOAF.NAMESPACE, "accountServiceHomepage"); + AGE = factory.createIRI(FOAF.NAMESPACE, "age"); + AIM_CHAT_ID = factory.createIRI(FOAF.NAMESPACE, "aimChatID"); + BASED_NEAR = factory.createIRI(FOAF.NAMESPACE, "based_near"); + BIRTHDAY = factory.createIRI(FOAF.NAMESPACE, "birthday"); + CURRENT_PROJECT = factory.createIRI(FOAF.NAMESPACE, "currentProject"); + DEPICTION = factory.createIRI(FOAF.NAMESPACE, "depiction"); + DEPICTS = factory.createIRI(FOAF.NAMESPACE, "depicts"); + DNA_CHECKSUM = factory.createIRI(FOAF.NAMESPACE, "dnaChecksum"); + FAMILY_NAME = factory.createIRI(FOAF.NAMESPACE, "familyName"); + FAMILYNAME = factory.createIRI(FOAF.NAMESPACE, "family_name"); + FIRST_NAME = factory.createIRI(FOAF.NAMESPACE, "firstName"); + FOCUS = factory.createIRI(FOAF.NAMESPACE, "focus"); + FUNDED_BY = factory.createIRI(FOAF.NAMESPACE, "fundedBy"); + GEEKCODE = factory.createIRI(FOAF.NAMESPACE, "geekcode"); + GENDER = factory.createIRI(FOAF.NAMESPACE, "gender"); + GIVEN_NAME = factory.createIRI(FOAF.NAMESPACE, "givenName"); + GIVENNAME = factory.createIRI(FOAF.NAMESPACE, "givenname"); + HOLDS_ACCOUNT = factory.createIRI(FOAF.NAMESPACE, "holdsAccount"); + HOMEPAGE = factory.createIRI(FOAF.NAMESPACE, "homepage"); + ICQ_CHAT_ID = factory.createIRI(FOAF.NAMESPACE, "icqChatID"); + IMG = factory.createIRI(FOAF.NAMESPACE, "img"); + INTEREST = factory.createIRI(FOAF.NAMESPACE, "interest"); + IS_PRIMARY_TOPIC_OF = factory.createIRI(FOAF.NAMESPACE, "isPrimaryTopicOf"); + JABBER_ID = factory.createIRI(FOAF.NAMESPACE, "jabberID"); + KNOWS = factory.createIRI(FOAF.NAMESPACE, "knows"); + LAST_NAME = factory.createIRI(FOAF.NAMESPACE, "lastName"); + LOGO = factory.createIRI(FOAF.NAMESPACE, "logo"); + MADE = factory.createIRI(FOAF.NAMESPACE, "made"); + MAKER = factory.createIRI(FOAF.NAMESPACE, "maker"); + MBOX = factory.createIRI(FOAF.NAMESPACE, "mbox"); + MBOX_SHA1SUM = factory.createIRI(FOAF.NAMESPACE, "mbox_sha1sum"); + MEMBER = factory.createIRI(FOAF.NAMESPACE, "member"); + MEMBERSHIP_CLASS = factory.createIRI(FOAF.NAMESPACE, "membershipClass"); + MSN_CHAT_ID = factory.createIRI(FOAF.NAMESPACE, "msnChatID"); + MYERS_BRIGGS = factory.createIRI(FOAF.NAMESPACE, "myersBriggs"); + NAME = factory.createIRI(FOAF.NAMESPACE, "name"); + NICK = factory.createIRI(FOAF.NAMESPACE, "nick"); + OPENID = factory.createIRI(FOAF.NAMESPACE, "openid"); + PAGE = factory.createIRI(FOAF.NAMESPACE, "page"); + PAST_PROJECT = factory.createIRI(FOAF.NAMESPACE, "pastProject"); + PHONE = factory.createIRI(FOAF.NAMESPACE, "phone"); + PLAN = factory.createIRI(FOAF.NAMESPACE, "plan"); + PRIMARY_TOPIC = factory.createIRI(FOAF.NAMESPACE, "primaryTopic"); + PUBLICATIONS = factory.createIRI(FOAF.NAMESPACE, "publications"); + SCHOOL_HOMEPAGE = factory.createIRI(FOAF.NAMESPACE, "schoolHomepage"); + SHA1 = factory.createIRI(FOAF.NAMESPACE, "sha1"); + SKYPE_ID = factory.createIRI(FOAF.NAMESPACE, "skypeID"); + STATUS = factory.createIRI(FOAF.NAMESPACE, "status"); + SURNAME = factory.createIRI(FOAF.NAMESPACE, "surname"); + THEME = factory.createIRI(FOAF.NAMESPACE, "theme"); + THUMBNAIL = factory.createIRI(FOAF.NAMESPACE, "thumbnail"); + TIPJAR = factory.createIRI(FOAF.NAMESPACE, "tipjar"); + TITLE = factory.createIRI(FOAF.NAMESPACE, "title"); + TOPIC = factory.createIRI(FOAF.NAMESPACE, "topic"); + TOPIC_INTEREST = factory.createIRI(FOAF.NAMESPACE, "topic_interest"); + WEBLOG = factory.createIRI(FOAF.NAMESPACE, "weblog"); + WORK_INFO_HOMEPAGE = factory.createIRI(FOAF.NAMESPACE, "workInfoHomepage"); + WORKPLACE_HOMEPAGE = factory.createIRI(FOAF.NAMESPACE, "workplaceHomepage"); + YAHOO_CHAT_ID = factory.createIRI(FOAF.NAMESPACE, "yahooChatID"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEO.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEO.java new file mode 100644 index 00000000000..467cc38b44d --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEO.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.ValueFactoryImpl; + +/** + * @since 2.8.5 + * @version 1.0 + * @see http://www.opengeospatial.org/standards/geosparql + */ +public class GEO { + + public static final String NAMESPACE = "http://www.opengis.net/ont/geosparql#"; + + public static final URI AS_WKT; + + public static final URI WKT_LITERAL; + + public static final String DEFAULT_SRID = "http://www.opengis.net/def/crs/OGC/1.3/CRS84"; + + static { + ValueFactory factory = ValueFactoryImpl.getInstance(); + AS_WKT = factory.createURI(NAMESPACE, "asWKT"); + WKT_LITERAL = factory.createURI(NAMESPACE, "wktLiteral"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEOF.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEOF.java new file mode 100644 index 00000000000..75b211c5fdc --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEOF.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.ValueFactoryImpl; + +/** + * @see http://www.opengeospatial.org/standards/geosparql + */ +public class GEOF { + + public static final String NAMESPACE = "http://www.opengis.net/def/function/geosparql/"; + + public static final URI DISTANCE; + public static final URI BUFFER; + public static final URI CONVEX_HULL; + public static final URI INTERSECTION; + public static final URI UNION; + public static final URI DIFFERENCE; + public static final URI SYM_DIFFERENCE; + public static final URI ENVELOPE; + public static final URI BOUNDARY; + public static final URI GET_SRID; + + public static final URI RELATE; + + public static final URI SF_EQUALS; + public static final URI SF_DISJOINT; + public static final URI SF_INTERSECTS; + public static final URI SF_TOUCHES; + public static final URI SF_CROSSES; + public static final URI SF_WITHIN; + public static final URI SF_CONTAINS; + public static final URI SF_OVERLAPS; + + public static final URI EH_EQUALS; + public static final URI EH_DISJOINT; + public static final URI EH_MEET; + public static final URI EH_OVERLAP; + public static final URI EH_COVERS; + public static final URI EH_COVERED_BY; + public static final URI EH_INSIDE; + public static final URI EH_CONTAINS; + + public static final URI RCC8_EQ; + public static final URI RCC8_DC; + public static final URI RCC8_EC; + public static final URI RCC8_PO; + public static final URI RCC8_TPPI; + public static final URI RCC8_TPP; + public static final URI RCC8_NTPP; + public static final URI RCC8_NTPPI; + + public static final String UOM_NAMESPACE = "http://www.opengis.net/def/uom/OGC/1.0/"; + public static final URI UOM_DEGREE; + public static final URI UOM_RADIAN; + public static final URI UOM_UNITY; + public static final URI UOM_METRE; + + static { + ValueFactory factory = ValueFactoryImpl.getInstance(); + DISTANCE = factory.createURI(NAMESPACE, "distance"); + BUFFER = factory.createURI(NAMESPACE, "buffer"); + CONVEX_HULL = factory.createURI(NAMESPACE, "convexHull"); + INTERSECTION = factory.createURI(NAMESPACE, "intersection"); + UNION = factory.createURI(NAMESPACE, "union"); + DIFFERENCE = factory.createURI(NAMESPACE, "difference"); + SYM_DIFFERENCE = factory.createURI(NAMESPACE, "symDifference"); + ENVELOPE = factory.createURI(NAMESPACE, "envelope"); + BOUNDARY = factory.createURI(NAMESPACE, "boundary"); + GET_SRID = factory.createURI(NAMESPACE, "getSRID"); + + RELATE = factory.createURI(NAMESPACE, "relate"); + + SF_EQUALS = factory.createURI(NAMESPACE, "sfEquals"); + SF_DISJOINT = factory.createURI(NAMESPACE, "sfDisjoint"); + SF_INTERSECTS = factory.createURI(NAMESPACE, "sfIntersects"); + SF_TOUCHES = factory.createURI(NAMESPACE, "sfTouches"); + SF_CROSSES = factory.createURI(NAMESPACE, "sfCrosses"); + SF_WITHIN = factory.createURI(NAMESPACE, "sfWithin"); + SF_CONTAINS = factory.createURI(NAMESPACE, "sfContains"); + SF_OVERLAPS = factory.createURI(NAMESPACE, "sfOverlaps"); + + EH_EQUALS = factory.createURI(NAMESPACE, "ehEquals"); + EH_DISJOINT = factory.createURI(NAMESPACE, "ehDisjoint"); + EH_MEET = factory.createURI(NAMESPACE, "ehMeet"); + EH_OVERLAP = factory.createURI(NAMESPACE, "ehOverlap"); + EH_COVERS = factory.createURI(NAMESPACE, "ehCovers"); + EH_COVERED_BY = factory.createURI(NAMESPACE, "ehCoveredBy"); + EH_INSIDE = factory.createURI(NAMESPACE, "ehInside"); + EH_CONTAINS = factory.createURI(NAMESPACE, "ehContains"); + + RCC8_EQ = factory.createURI(NAMESPACE, "rcc8eq"); + RCC8_DC = factory.createURI(NAMESPACE, "rcc8dc"); + RCC8_EC = factory.createURI(NAMESPACE, "rcc8ec"); + RCC8_PO = factory.createURI(NAMESPACE, "rcc8po"); + RCC8_TPPI = factory.createURI(NAMESPACE, "rcc8tppi"); + RCC8_TPP = factory.createURI(NAMESPACE, "rcc8tpp"); + RCC8_NTPP = factory.createURI(NAMESPACE, "rcc8ntpp"); + RCC8_NTPPI = factory.createURI(NAMESPACE, "rcc8ntppi"); + + UOM_DEGREE = factory.createURI(UOM_NAMESPACE, "degree"); + UOM_RADIAN = factory.createURI(UOM_NAMESPACE, "radian"); + UOM_UNITY = factory.createURI(UOM_NAMESPACE, "unity"); + UOM_METRE = factory.createURI(UOM_NAMESPACE, "metre"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/OWL.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/OWL.java new file mode 100644 index 00000000000..4635f43fc60 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/OWL.java @@ -0,0 +1,246 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Constants for OWL primitives and for the OWL namespace. + * + * @see OWL Web Ontology Language + * Reference + */ +public class OWL { + + /** The OWL namespace: http://www.w3.org/2002/07/owl# */ + public static final String NAMESPACE = "http://www.w3.org/2002/07/owl#"; + + /** + * Recommended prefix for the OWL namespace: "owl" + */ + public static final String PREFIX = "owl"; + + /** + * An immutable {@link Namespace} constant that represents the OWL namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + // OWL Lite + + /** http://www.w3.org/2002/07/owl#Class */ + public final static IRI CLASS; + + /** http://www.w3.org/2002/07/owl#Individual */ + public final static IRI INDIVIDUAL; + + /** http://www.w3.org/2002/07/owl#Thing */ + public static final IRI THING; + + /** http://www.w3.org/2002/07/owl#Nothing */ + public static final IRI NOTHING; + + /** http://www.w3.org/2002/07/owl#equivalentClass */ + public final static IRI EQUIVALENTCLASS; + + /** http://www.w3.org/2002/07/owl#equivalentProperty */ + public final static IRI EQUIVALENTPROPERTY; + + /** http://www.w3.org/2002/07/owl#sameAs */ + public final static IRI SAMEAS; + + /** http://www.w3.org/2002/07/owl#differentFrom */ + public final static IRI DIFFERENTFROM; + + /** http://www.w3.org/2002/07/owl#AllDifferent */ + public final static IRI ALLDIFFERENT; + + /** http://www.w3.org/2002/07/owl#distinctMembers */ + public final static IRI DISTINCTMEMBERS; + + /** http://www.w3.org/2002/07/owl#ObjectProperty */ + public final static IRI OBJECTPROPERTY; + + /** http://www.w3.org/2002/07/owl#DatatypeProperty */ + public final static IRI DATATYPEPROPERTY; + + /** http://www.w3.org/2002/07/owl#inverseOf */ + public final static IRI INVERSEOF; + + /** http://www.w3.org/2002/07/owl#TransitiveProperty */ + public final static IRI TRANSITIVEPROPERTY; + + /** http://www.w3.org/2002/07/owl#SymmetricProperty */ + public final static IRI SYMMETRICPROPERTY; + + /** http://www.w3.org/2002/07/owl#FunctionalProperty */ + public final static IRI FUNCTIONALPROPERTY; + + /** http://www.w3.org/2002/07/owl#InverseFunctionalProperty */ + public final static IRI INVERSEFUNCTIONALPROPERTY; + + /** http://www.w3.org/2002/07/owl#Restriction */ + public final static IRI RESTRICTION; + + /** http://www.w3.org/2002/07/owl#onProperty */ + public final static IRI ONPROPERTY; + + /** http://www.w3.org/2002/07/owl#allValuesFrom */ + public final static IRI ALLVALUESFROM; + + /** http://www.w3.org/2002/07/owl#someValuesFrom */ + public final static IRI SOMEVALUESFROM; + + /** http://www.w3.org/2002/07/owl#minCardinality */ + public final static IRI MINCARDINALITY; + + /** http://www.w3.org/2002/07/owl#maxCardinality */ + public final static IRI MAXCARDINALITY; + + /** http://www.w3.org/2002/07/owl#cardinality */ + public final static IRI CARDINALITY; + + /** http://www.w3.org/2002/07/owl#Ontology */ + public final static IRI ONTOLOGY; + + /** http://www.w3.org/2002/07/owl#imports */ + public final static IRI IMPORTS; + + /** http://www.w3.org/2002/07/owl#intersectionOf */ + public final static IRI INTERSECTIONOF; + + /** http://www.w3.org/2002/07/owl#versionInfo */ + public final static IRI VERSIONINFO; + + /** http://www.w3.org/2002/07/owl#versionIRI */ + public final static IRI VERSIONIRI; + + /** http://www.w3.org/2002/07/owl#priorVersion */ + public final static IRI PRIORVERSION; + + /** http://www.w3.org/2002/07/owl#backwardCompatibleWith */ + public final static IRI BACKWARDCOMPATIBLEWITH; + + /** http://www.w3.org/2002/07/owl#incompatibleWith */ + public final static IRI INCOMPATIBLEWITH; + + /** http://www.w3.org/2002/07/owl#DeprecatedClass */ + public final static IRI DEPRECATEDCLASS; + + /** http://www.w3.org/2002/07/owl#DeprecatedProperty */ + public final static IRI DEPRECATEDPROPERTY; + + /** http://www.w3.org/2002/07/owl#AnnotationProperty */ + public final static IRI ANNOTATIONPROPERTY; + + /** http://www.w3.org/2002/07/owl#OntologyProperty */ + public final static IRI ONTOLOGYPROPERTY; + + // OWL DL and OWL Full + + /** http://www.w3.org/2002/07/owl#oneOf */ + public final static IRI ONEOF; + + /** http://www.w3.org/2002/07/owl#hasValue */ + public final static IRI HASVALUE; + + /** http://www.w3.org/2002/07/owl#disjointWith */ + public final static IRI DISJOINTWITH; + + /** http://www.w3.org/2002/07/owl#unionOf */ + public final static IRI UNIONOF; + + /** http://www.w3.org/2002/07/owl#complementOf */ + public final static IRI COMPLEMENTOF; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + + CLASS = factory.createIRI(OWL.NAMESPACE, "Class"); + INDIVIDUAL = factory.createIRI(OWL.NAMESPACE, "Individual"); + + THING = factory.createIRI(OWL.NAMESPACE, "Thing"); + NOTHING = factory.createIRI(NAMESPACE, "Nothing"); + + EQUIVALENTCLASS = factory.createIRI(OWL.NAMESPACE, "equivalentClass"); + EQUIVALENTPROPERTY = factory.createIRI(OWL.NAMESPACE, "equivalentProperty"); + SAMEAS = factory.createIRI(OWL.NAMESPACE, "sameAs"); + DIFFERENTFROM = factory.createIRI(OWL.NAMESPACE, "differentFrom"); + ALLDIFFERENT = factory.createIRI(OWL.NAMESPACE, "AllDifferent"); + + DISTINCTMEMBERS = factory.createIRI(OWL.NAMESPACE, "distinctMembers"); + + OBJECTPROPERTY = factory.createIRI(OWL.NAMESPACE, "ObjectProperty"); + + DATATYPEPROPERTY = factory.createIRI(OWL.NAMESPACE, "DatatypeProperty"); + + INVERSEOF = factory.createIRI(OWL.NAMESPACE, "inverseOf"); + + TRANSITIVEPROPERTY = factory.createIRI(OWL.NAMESPACE, "TransitiveProperty"); + + SYMMETRICPROPERTY = factory.createIRI(OWL.NAMESPACE, "SymmetricProperty"); + + FUNCTIONALPROPERTY = factory.createIRI(OWL.NAMESPACE, "FunctionalProperty"); + + INVERSEFUNCTIONALPROPERTY = factory.createIRI(OWL.NAMESPACE, "InverseFunctionalProperty"); + + RESTRICTION = factory.createIRI(OWL.NAMESPACE, "Restriction"); + + ONPROPERTY = factory.createIRI(OWL.NAMESPACE, "onProperty"); + + ALLVALUESFROM = factory.createIRI(OWL.NAMESPACE, "allValuesFrom"); + + SOMEVALUESFROM = factory.createIRI(OWL.NAMESPACE, "someValuesFrom"); + + MINCARDINALITY = factory.createIRI(OWL.NAMESPACE, "minCardinality"); + + MAXCARDINALITY = factory.createIRI(OWL.NAMESPACE, "maxCardinality"); + + CARDINALITY = factory.createIRI(OWL.NAMESPACE, "cardinality"); + + ONTOLOGY = factory.createIRI(OWL.NAMESPACE, "Ontology"); + + IMPORTS = factory.createIRI(OWL.NAMESPACE, "imports"); + + INTERSECTIONOF = factory.createIRI(OWL.NAMESPACE, "intersectionOf"); + + VERSIONINFO = factory.createIRI(OWL.NAMESPACE, "versionInfo"); + + VERSIONIRI = factory.createIRI(OWL.NAMESPACE, "versionIRI"); + + PRIORVERSION = factory.createIRI(OWL.NAMESPACE, "priorVersion"); + + BACKWARDCOMPATIBLEWITH = factory.createIRI(OWL.NAMESPACE, "backwardCompatibleWith"); + + INCOMPATIBLEWITH = factory.createIRI(OWL.NAMESPACE, "incompatibleWith"); + + DEPRECATEDCLASS = factory.createIRI(OWL.NAMESPACE, "DeprecatedClass"); + + DEPRECATEDPROPERTY = factory.createIRI(OWL.NAMESPACE, "DeprecatedProperty"); + + ANNOTATIONPROPERTY = factory.createIRI(OWL.NAMESPACE, "AnnotationProperty"); + + ONTOLOGYPROPERTY = factory.createIRI(OWL.NAMESPACE, "OntologyProperty"); + + // OWL DL and OWL Full + + ONEOF = factory.createIRI(OWL.NAMESPACE, "oneOf"); + + HASVALUE = factory.createIRI(OWL.NAMESPACE, "hasValue"); + + DISJOINTWITH = factory.createIRI(OWL.NAMESPACE, "disjointWith"); + + UNIONOF = factory.createIRI(OWL.NAMESPACE, "unionOf"); + + COMPLEMENTOF = factory.createIRI(OWL.NAMESPACE, "complementOf"); + + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDF.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDF.java new file mode 100644 index 00000000000..163addd4dc3 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDF.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Constants for RDF primitives and for the RDF namespace. + * + * @see RDF/XML Syntax + * Specification (Revised) + */ +public class RDF { + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns# */ + public static final String NAMESPACE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; + + /** + * Recommended prefix for the RDF namespace: "rdf" + */ + public static final String PREFIX = "rdf"; + + /** + * An immutable {@link Namespace} constant that represents the RDF namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#type */ + public final static IRI TYPE; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#Property */ + public final static IRI PROPERTY; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral */ + public final static IRI XMLLITERAL; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#subject */ + public final static IRI SUBJECT; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate */ + public final static IRI PREDICATE; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#object */ + public final static IRI OBJECT; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement */ + public final static IRI STATEMENT; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag */ + public final static IRI BAG; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt */ + public final static IRI ALT; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq */ + public final static IRI SEQ; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#value */ + public final static IRI VALUE; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#li */ + public final static IRI LI; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#List */ + public final static IRI LIST; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#first */ + public final static IRI FIRST; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#rest */ + public final static IRI REST; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#nil */ + public final static IRI NIL; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#langString */ + public static final IRI LANGSTRING; + + /** http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML */ + public static final IRI HTML; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + TYPE = factory.createIRI(RDF.NAMESPACE, "type"); + PROPERTY = factory.createIRI(RDF.NAMESPACE, "Property"); + XMLLITERAL = factory.createIRI(RDF.NAMESPACE, "XMLLiteral"); + SUBJECT = factory.createIRI(RDF.NAMESPACE, "subject"); + PREDICATE = factory.createIRI(RDF.NAMESPACE, "predicate"); + OBJECT = factory.createIRI(RDF.NAMESPACE, "object"); + STATEMENT = factory.createIRI(RDF.NAMESPACE, "Statement"); + BAG = factory.createIRI(RDF.NAMESPACE, "Bag"); + ALT = factory.createIRI(RDF.NAMESPACE, "Alt"); + SEQ = factory.createIRI(RDF.NAMESPACE, "Seq"); + VALUE = factory.createIRI(RDF.NAMESPACE, "value"); + LI = factory.createIRI(RDF.NAMESPACE, "li"); + LIST = factory.createIRI(RDF.NAMESPACE, "List"); + FIRST = factory.createIRI(RDF.NAMESPACE, "first"); + REST = factory.createIRI(RDF.NAMESPACE, "rest"); + NIL = factory.createIRI(RDF.NAMESPACE, "nil"); + LANGSTRING = factory.createIRI(RDF.NAMESPACE, "langString"); + HTML = factory.createIRI(RDF.NAMESPACE, "HTML"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDFS.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDFS.java new file mode 100644 index 00000000000..60c4529b9a7 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDFS.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Constants for the RDF Vocabulary + * Description Language 1.0: RDF Schema (RDFS) + * + * @see RDF Vocabulary Description + * Language 1.0: RDF Schema (RDFS) + */ +public class RDFS { + + /** The RDF Schema namepace: http://www.w3.org/2000/01/rdf-schema# */ + public static final String NAMESPACE = "http://www.w3.org/2000/01/rdf-schema#"; + + /** Recommended prefix for the RDF Schema namespace: "rdfs" */ + public static final String PREFIX = "rdfs"; + + /** + * An immutable {@link Namespace} constant that represents the RDFS + * namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + /** http://www.w3.org/2000/01/rdf-schema#Resource */ + public final static IRI RESOURCE; + + /** http://www.w3.org/2000/01/rdf-schema#Literal */ + public final static IRI LITERAL; + + /** http://www.w3.org/2000/01/rdf-schema#Class */ + public final static IRI CLASS; + + /** http://www.w3.org/2000/01/rdf-schema#subClassOf */ + public final static IRI SUBCLASSOF; + + /** http://www.w3.org/2000/01/rdf-schema#subPropertyOf */ + public final static IRI SUBPROPERTYOF; + + /** http://www.w3.org/2000/01/rdf-schema#domain */ + public final static IRI DOMAIN; + + /** http://www.w3.org/2000/01/rdf-schema#range */ + public final static IRI RANGE; + + /** http://www.w3.org/2000/01/rdf-schema#comment */ + public final static IRI COMMENT; + + /** http://www.w3.org/2000/01/rdf-schema#label */ + public final static IRI LABEL; + + /** http://www.w3.org/2000/01/rdf-schema#Datatype */ + public final static IRI DATATYPE; + + /** http://www.w3.org/2000/01/rdf-schema#Container */ + public final static IRI CONTAINER; + + /** http://www.w3.org/2000/01/rdf-schema#member */ + public final static IRI MEMBER; + + /** http://www.w3.org/2000/01/rdf-schema#isDefinedBy */ + public final static IRI ISDEFINEDBY; + + /** http://www.w3.org/2000/01/rdf-schema#seeAlso */ + public final static IRI SEEALSO; + + /** http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty */ + public final static IRI CONTAINERMEMBERSHIPPROPERTY; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + RESOURCE = factory.createIRI(RDFS.NAMESPACE, "Resource"); + LITERAL = factory.createIRI(RDFS.NAMESPACE, "Literal"); + CLASS = factory.createIRI(RDFS.NAMESPACE, "Class"); + SUBCLASSOF = factory.createIRI(RDFS.NAMESPACE, "subClassOf"); + SUBPROPERTYOF = factory.createIRI(RDFS.NAMESPACE, "subPropertyOf"); + DOMAIN = factory.createIRI(RDFS.NAMESPACE, "domain"); + RANGE = factory.createIRI(RDFS.NAMESPACE, "range"); + COMMENT = factory.createIRI(RDFS.NAMESPACE, "comment"); + LABEL = factory.createIRI(RDFS.NAMESPACE, "label"); + DATATYPE = factory.createIRI(RDFS.NAMESPACE, "Datatype"); + CONTAINER = factory.createIRI(RDFS.NAMESPACE, "Container"); + MEMBER = factory.createIRI(RDFS.NAMESPACE, "member"); + ISDEFINEDBY = factory.createIRI(RDFS.NAMESPACE, "isDefinedBy"); + SEEALSO = factory.createIRI(RDFS.NAMESPACE, "seeAlso"); + CONTAINERMEMBERSHIPPROPERTY = factory.createIRI(RDFS.NAMESPACE, "ContainerMembershipProperty"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SD.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SD.java new file mode 100644 index 00000000000..bd35c27781d --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SD.java @@ -0,0 +1,616 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Namespace Sparql-service-description. Prefix: + * {@code } + * + * @see SPARQL 1.1 + * Service Description + * @author Peter Ansell + */ +public class SD { + + /** + * {@code http://www.w3.org/ns/sparql-service-description#} + */ + public static final String NAMESPACE = "http://www.w3.org/ns/sparql-service-description#"; + + /** + * {@code sd} + */ + public static final String PREFIX = "sd"; + + /** + * An immutable {@link Namespace} constant that represents the SPARQL Service + * Description namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + /** + * Aggregate + *

    + * {@code http://www.w3.org/ns/sparql-service-description#Aggregate}. + *

    + * An instance of sd:Aggregate represents an aggregate that may be used in a + * SPARQL aggregate query (for instance in a HAVING clause or SELECT + * expression) besides the standard list of supported aggregates COUNT, SUM, + * MIN, MAX, AVG, GROUP_CONCAT, and SAMPLE. + * + * @see Aggregate + */ + public static final IRI AGGREGATE; + + /** + * available graph descriptions + *

    + * {@code http://www.w3.org/ns/sparql-service-description#availableGraphs}. + *

    + * Relates an instance of sd:Service to a description of the graphs which are + * allowed in the construction of a dataset either via the SPARQL Protocol, + * with FROM/FROM NAMED clauses in a query, or with USING/USING NAMED in an + * update request, if the service limits the scope of dataset construction. + * + * @see availableGraphs + */ + public static final IRI AVAILBLE_GRAPHS; + + /** + * Basic Federated Query + *

    + * {@code http://www.w3.org/ns/sparql-service-description#BasicFederatedQuery}. + *

    + * sd:BasicFederatedQuery, when used as the object of the sd:feature + * property, indicates that the SPARQL service supports basic federated query + * using the SERVICE keyword as defined by SPARQL 1.1 Federation Extensions. + * + * @see BasicFederatedQuery + */ + public static final IRI BASIC_FEDERATED_QUERY; + + /** + * Dataset + *

    + * {@code http://www.w3.org/ns/sparql-service-description#Dataset}. + *

    + * An instance of sd:Dataset represents a RDF Dataset comprised of a default + * graph and zero or more named graphs. + * + * @see Dataset + */ + public static final IRI DATASET; + + /** + * default dataset description + *

    + * {@code http://www.w3.org/ns/sparql-service-description#defaultDataset}. + *

    + * Relates an instance of sd:Service to a description of the default dataset + * available when no explicit dataset is specified in the query, update + * request or via protocol parameters. + * + * @see defaultDataset + */ + public static final IRI DEFAULT_DATASET; + + /** + * default entailment regime + *

    + * {@code http://www.w3.org/ns/sparql-service-description#defaultEntailmentRegime}. + *

    + * Relates an instance of sd:Service with a resource representing an + * entailment regime used for basic graph pattern matching. This property is + * intended for use when a single entailment regime by default applies to all + * graphs in the default dataset of the service. In situations where a + * different entailment regime applies to a specific graph in the dataset, + * the sd:entailmentRegime property should be used to indicate this fact in + * the description of that graph. + * + * @see defaultEntailmentRegime + */ + public static final IRI DEFAULT_ENTAILMENT_REGIME; + + /** + * default graph + *

    + * {@code http://www.w3.org/ns/sparql-service-description#defaultGraph}. + *

    + * Relates an instance of sd:Dataset to the description of its default graph. + * + * @see defaultGraph + */ + public static final IRI DEFAULT_GRAPH; + + /** + * default supported entailment profile + *

    + * {@code http://www.w3.org/ns/sparql-service-description#defaultSupportedEntailmentProfile}. + *

    + * Relates an instance of sd:Service with a resource representing a supported + * profile of the default entailment regime (as declared by + * sd:defaultEntailmentRegime). + * + * @see defaultSupportedEntailmentProfile + */ + public static final IRI DEFAULT_SUPPORTED_ENTAILMENT_PROFILE; + + /** + * Dereferences URIs + *

    + * {@code http://www.w3.org/ns/sparql-service-description#DereferencesURIs}. + *

    + * sd:DereferencesURIs, when used as the object of the sd:feature property, + * indicates that a SPARQL service will dereference URIs used in FROM/FROM + * NAMED and USING/USING NAMED clauses and use the resulting RDF in the + * dataset during query evaluation. + * + * @see DereferencesURIs + */ + public static final IRI DEREFERENCES_URIS; + + /** + * Empty Graphs + *

    + * {@code http://www.w3.org/ns/sparql-service-description#EmptyGraphs}. + *

    + * sd:EmptyGraphs, when used as the object of the sd:feature property, + * indicates that the underlying graph store supports empty graphs. A graph + * store that supports empty graphs MUST NOT remove graphs that are left + * empty after triples are removed from them. + * + * @see EmptyGraphs + */ + public static final IRI EMPTY_GRAPHS; + + /** + * endpoint + *

    + * {@code http://www.w3.org/ns/sparql-service-description#endpoint}. + *

    + * The SPARQL endpoint of an sd:Service that implements the SPARQL Protocol + * service. The object of the sd:endpoint property is an IRI. + * + * @see endpoint + */ + public static final IRI ENDPOINT; + + /** + * Entailment Profile + *

    + * {@code http://www.w3.org/ns/sparql-service-description#EntailmentProfile}. + *

    + * An instance of sd:EntailmentProfile represents a profile of an entailment + * regime. An entailment profile MAY impose restrictions on what constitutes + * valid RDF with respect to entailment. + * + * @see EntailmentProfile + */ + public static final IRI ENTAILMENT_PROFILE; + + /** + * Entailment Regime + *

    + * {@code http://www.w3.org/ns/sparql-service-description#EntailmentRegime}. + *

    + * An instance of sd:EntailmentRegime represents an entailment regime used in + * basic graph pattern matching (as described by SPARQL 1.1 Query Language). + * + * @see EntailmentRegime + */ + public static final IRI ENTAILMENT_REGIME_CLASS; + + /** + * entailment regime + *

    + * {@code http://www.w3.org/ns/sparql-service-description#entailmentRegime}. + *

    + * Relates a named graph description with a resource representing an + * entailment regime used for basic graph pattern matching over that graph. + * + * @see entailmentRegime + */ + public static final IRI ENTAILMENT_REGIME_PROPERTY; + + /** + * extension aggregate + *

    + * {@code http://www.w3.org/ns/sparql-service-description#extensionAggregate}. + *

    + * Relates an instance of sd:Service to an aggregate that may be used in a + * SPARQL aggregate query (for instance in a HAVING clause or SELECT + * expression) besides the standard list of supported aggregates COUNT, SUM, + * MIN, MAX, AVG, GROUP_CONCAT, and SAMPLE + * + * @see extensionAggregate + */ + public static final IRI EXTENSION_AGGREGATE; + + /** + * extension function + *

    + * {@code http://www.w3.org/ns/sparql-service-description#extensionFunction}. + *

    + * Relates an instance of sd:Service to a function that may be used in a + * SPARQL SELECT expression or a FILTER, HAVING, GROUP BY, ORDER BY, or BIND + * clause. + * + * @see extensionFunction + */ + public static final IRI EXTENSION_FUNCTION; + + /** + * Feature + *

    + * {@code http://www.w3.org/ns/sparql-service-description#Feature}. + *

    + * An instance of sd:Feature represents a feature of a SPARQL service. + * Specific types of features include functions, aggregates, languages, and + * entailment regimes and profiles. This document defines five instances of + * sd:Feature: sd:DereferencesURIs, sd:UnionDefaultGraph, sd:RequiresDataset, + * sd:EmptyGraphs, and sd:BasicFederatedQuery. + * + * @see Feature + */ + public static final IRI FEATURE_CLASS; + + /** + * feature + *

    + * {@code http://www.w3.org/ns/sparql-service-description#feature}. + *

    + * Relates an instance of sd:Service with a resource representing a supported + * feature. + * + * @see feature + */ + public static final IRI FEATURE_PROPERTY; + + /** + * Function + *

    + * {@code http://www.w3.org/ns/sparql-service-description#Function}. + *

    + * An instance of sd:Function represents a function that may be used in a + * SPARQL SELECT expression or a FILTER, HAVING, GROUP BY, ORDER BY, or BIND + * clause. + * + * @see Function + */ + public static final IRI FUNCTION; + + /** + * graph + *

    + * {@code http://www.w3.org/ns/sparql-service-description#graph}. + *

    + * Relates a named graph to its graph description. + * + * @see graph + */ + public static final IRI GRAPH_PROPERTY; + + /** + * Graph + *

    + * {@code http://www.w3.org/ns/sparql-service-description#Graph}. + *

    + * An instance of sd:Graph represents the description of an RDF graph. + * + * @see Graph + */ + public static final IRI GRAPH_CLASS; + + /** + * Graph Collection + *

    + * {@code http://www.w3.org/ns/sparql-service-description#GraphCollection}. + *

    + * An instance of sd:GraphCollection represents a collection of zero or more + * named graph descriptions. Each named graph description belonging to an + * sd:GraphCollection MUST be linked with the sd:namedGraph predicate. + * + * @see GraphCollection + */ + public static final IRI GRAPH_COLLECTION; + + /** + * input format + *

    + * {@code http://www.w3.org/ns/sparql-service-description#inputFormat}. + *

    + * Relates an instance of sd:Service to a format that is supported for + * parsing RDF input; for example, via a SPARQL 1.1 Update LOAD statement, or + * when URIs are dereferenced in FROM/FROM NAMED/USING/USING NAMED clauses. + * + * @see inputFormat + */ + public static final IRI INPUT_FORMAT; + + /** + * Language + *

    + * {@code http://www.w3.org/ns/sparql-service-description#Language}. + *

    + * An instance of sd:Language represents one of the SPARQL languages, + * including specific configurations providing particular features or + * extensions. This document defines three instances of sd:Language: + * sd:SPARQL10Query, sd:SPARQL11Query, and sd:SPARQL11Update. + * + * @see Language + */ + public static final IRI LANGUAGE; + + /** + * language extension + *

    + * {@code http://www.w3.org/ns/sparql-service-description#languageExtension}. + *

    + * Relates an instance of sd:Service to a resource representing an + * implemented extension to the SPARQL Query or Update language. + * + * @see languageExtension + */ + public static final IRI LANGUAGE_EXTENSION; + + /** + * name + *

    + * {@code http://www.w3.org/ns/sparql-service-description#name}. + *

    + * Relates a named graph to the name by which it may be referenced in a + * FROM/FROM NAMED clause. The object of the sd:name property is an IRI. + * + * @see name + */ + public static final IRI NAME; + + /** + * named graph + *

    + * {@code http://www.w3.org/ns/sparql-service-description#namedGraph}. + *

    + * Relates an instance of sd:GraphCollection (or its subclass sd:Dataset) to + * the description of one of its named graphs. The description of such a + * named graph MUST include the sd:name property and MAY include the sd:graph + * property. + * + * @see namedGraph + */ + public static final IRI NAMED_GRAPH_PROPERTY; + + /** + * Named Graph + *

    + * {@code http://www.w3.org/ns/sparql-service-description#NamedGraph}. + *

    + * An instance of sd:NamedGraph represents a named graph having a name (via + * sd:name) and an optional graph description (via sd:graph). + * + * @see NamedGraph + */ + public static final IRI NAMED_GRAPH_CLASS; + + /** + * property feature + *

    + * {@code http://www.w3.org/ns/sparql-service-description#propertyFeature}. + *

    + * Relates an instance of sd:Service to a resource representing an + * implemented feature that extends the SPARQL Query or Update language and + * that is accessed by using the named property. + * + * @see propertyFeature + */ + public static final IRI PROPERTY_FEATURE; + + /** + * Requires Dataset + *

    + * {@code http://www.w3.org/ns/sparql-service-description#RequiresDataset}. + *

    + * sd:RequiresDataset, when used as the object of the sd:feature property, + * indicates that the SPARQL service requires an explicit dataset declaration + * (based on either FROM/FROM NAMED clauses in a query, USING/USING NAMED + * clauses in an update, or the appropriate SPARQL Protocol parameters). + * + * @see RequiresDataset + */ + public static final IRI REQUIRES_DATASET; + + /** + * result format + *

    + * {@code http://www.w3.org/ns/sparql-service-description#resultFormat}. + *

    + * Relates an instance of sd:Service to a format that is supported for + * serializing query results. + * + * @see resultFormat + */ + public static final IRI RESULT_FORMAT; + + /** + * Service + *

    + * {@code http://www.w3.org/ns/sparql-service-description#Service}. + *

    + * An instance of sd:Service represents a SPARQL service made available via + * the SPARQL Protocol. + * + * @see Service + */ + public static final IRI SERVICE; + + /** + * SPARQL 1.0 Query + *

    + * {@code http://www.w3.org/ns/sparql-service-description#SPARQL10Query}. + *

    + * sd:SPARQL10Query is an sd:Language representing the SPARQL 1.0 Query + * language. + * + * @see SPARQL10Query + */ + public static final IRI SPARQL_10_QUERY; + + /** + * SPARQL 1.1 Query + *

    + * {@code http://www.w3.org/ns/sparql-service-description#SPARQL11Query}. + *

    + * sd:SPARQL11Query is an sd:Language representing the SPARQL 1.1 Query + * language. + * + * @see SPARQL11Query + */ + public static final IRI SPARQL_11_QUERY; + + /** + * SPARQL 1.1 Update + *

    + * {@code http://www.w3.org/ns/sparql-service-description#SPARQL11Update}. + *

    + * sd:SPARQLUpdate is an sd:Language representing the SPARQL 1.1 Update + * language. + * + * @see SPARQL11Update + */ + public static final IRI SPARQL_11_UPDATE; + + /** + * supported entailment profile + *

    + * {@code http://www.w3.org/ns/sparql-service-description#supportedEntailmentProfile}. + *

    + * Relates a named graph description with a resource representing a supported + * profile of the entailment regime (as declared by sd:entailmentRegime) used + * for basic graph pattern matching over that graph. + * + * @see supportedEntailmentProfile + */ + public static final IRI SUPPORTED_ENTAILMENT_PROFILE; + + /** + * supported language + *

    + * {@code http://www.w3.org/ns/sparql-service-description#supportedLanguage}. + *

    + * Relates an instance of sd:Service to a SPARQL language (e.g. Query and + * Update) that it implements. + * + * @see supportedLanguage + */ + public static final IRI SUPPORTED_LANGUAGE; + + /** + * Union Default Graph + *

    + * {@code http://www.w3.org/ns/sparql-service-description#UnionDefaultGraph}. + *

    + * sd:UnionDefaultGraph, when used as the object of the sd:feature property, + * indicates that the default graph of the dataset used during query and + * update evaluation (when an explicit dataset is not specified) is comprised + * of the union of all the named graphs in that dataset. + * + * @see UnionDefaultGraph + */ + public static final IRI UNION_DEFAULT_GRAPH; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + + AGGREGATE = factory.createIRI(SD.NAMESPACE, "Aggregate"); + AVAILBLE_GRAPHS = factory.createIRI(SD.NAMESPACE, "availableGraphs"); + BASIC_FEDERATED_QUERY = factory.createIRI(SD.NAMESPACE, "BasicFederatedQuery"); + DATASET = factory.createIRI(SD.NAMESPACE, "Dataset"); + DEFAULT_DATASET = factory.createIRI(SD.NAMESPACE, "defaultDataset"); + DEFAULT_ENTAILMENT_REGIME = factory.createIRI(SD.NAMESPACE, "defaultEntailmentRegime"); + DEFAULT_GRAPH = factory.createIRI(SD.NAMESPACE, "defaultGraph"); + DEFAULT_SUPPORTED_ENTAILMENT_PROFILE = factory.createIRI(SD.NAMESPACE, + "defaultSupportedEntailmentProfile"); + DEREFERENCES_URIS = factory.createIRI(SD.NAMESPACE, "DereferencesURIs"); + EMPTY_GRAPHS = factory.createIRI(SD.NAMESPACE, "EmptyGraphs"); + ENDPOINT = factory.createIRI(SD.NAMESPACE, "endpoint"); + ENTAILMENT_PROFILE = factory.createIRI(SD.NAMESPACE, "EntailmentProfile"); + ENTAILMENT_REGIME_CLASS = factory.createIRI(SD.NAMESPACE, "EntailmentRegime"); + ENTAILMENT_REGIME_PROPERTY = factory.createIRI(SD.NAMESPACE, "entailmentRegime"); + EXTENSION_AGGREGATE = factory.createIRI(SD.NAMESPACE, "extensionAggregate"); + EXTENSION_FUNCTION = factory.createIRI(SD.NAMESPACE, "extensionFunction"); + FEATURE_CLASS = factory.createIRI(SD.NAMESPACE, "Feature"); + FEATURE_PROPERTY = factory.createIRI(SD.NAMESPACE, "feature"); + FUNCTION = factory.createIRI(SD.NAMESPACE, "Function"); + GRAPH_PROPERTY = factory.createIRI(SD.NAMESPACE, "graph"); + GRAPH_CLASS = factory.createIRI(SD.NAMESPACE, "Graph"); + GRAPH_COLLECTION = factory.createIRI(SD.NAMESPACE, "GraphCollection"); + INPUT_FORMAT = factory.createIRI(SD.NAMESPACE, "inputFormat"); + LANGUAGE = factory.createIRI(SD.NAMESPACE, "Language"); + LANGUAGE_EXTENSION = factory.createIRI(SD.NAMESPACE, "languageExtension"); + NAME = factory.createIRI(SD.NAMESPACE, "name"); + NAMED_GRAPH_PROPERTY = factory.createIRI(SD.NAMESPACE, "namedGraph"); + NAMED_GRAPH_CLASS = factory.createIRI(SD.NAMESPACE, "NamedGraph"); + PROPERTY_FEATURE = factory.createIRI(SD.NAMESPACE, "propertyFeature"); + REQUIRES_DATASET = factory.createIRI(SD.NAMESPACE, "RequiresDataset"); + RESULT_FORMAT = factory.createIRI(SD.NAMESPACE, "resultFormat"); + SERVICE = factory.createIRI(SD.NAMESPACE, "Service"); + SPARQL_10_QUERY = factory.createIRI(SD.NAMESPACE, "SPARQL10Query"); + SPARQL_11_QUERY = factory.createIRI(SD.NAMESPACE, "SPARQL11Query"); + SPARQL_11_UPDATE = factory.createIRI(SD.NAMESPACE, "SPARQL11Update"); + SUPPORTED_ENTAILMENT_PROFILE = factory.createIRI(SD.NAMESPACE, "supportedEntailmentProfile"); + SUPPORTED_LANGUAGE = factory.createIRI(SD.NAMESPACE, "supportedLanguage"); + UNION_DEFAULT_GRAPH = factory.createIRI(SD.NAMESPACE, "UnionDefaultGraph"); + } + + private SD() { + // static access only + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SESAME.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SESAME.java new file mode 100644 index 00000000000..005aa6781b5 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SESAME.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Defines constants for the Sesame schema namespace. + */ +public class SESAME { + + /** + * The Sesame Schema namespace ( + * http://www.openrdf.org/schema/sesame#). + */ + public static final String NAMESPACE = "http://www.openrdf.org/schema/sesame#"; + + /** + * Recommended prefix for the Sesame Schema namespace: "sesame" + */ + public static final String PREFIX = "sesame"; + + /** + * An immutable {@link Namespace} constant that represents the Sesame Schema + * namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + /** http://www.openrdf.org/schema/sesame#directSubClassOf */ + public final static IRI DIRECTSUBCLASSOF; + + /** http://www.openrdf.org/schema/sesame#directSubPropertyOf */ + public final static IRI DIRECTSUBPROPERTYOF; + + /** http://www.openrdf.org/schema/sesame#directType */ + public final static IRI DIRECTTYPE; + + /** + * The SPARQL null context identifier ( + * http://www.openrdf.org/schema/sesame#nil) + */ + public final static IRI NIL; + + /** + * http://www.openrdf.org/schema/sesame#wildcard + */ + public final static IRI WILDCARD; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + DIRECTSUBCLASSOF = factory.createIRI(SESAME.NAMESPACE, "directSubClassOf"); + DIRECTSUBPROPERTYOF = factory.createIRI(SESAME.NAMESPACE, "directSubPropertyOf"); + DIRECTTYPE = factory.createIRI(SESAME.NAMESPACE, "directType"); + + NIL = factory.createIRI(NAMESPACE, "nil"); + + WILDCARD = factory.createIRI(NAMESPACE, "wildcard"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SESAMEQNAME.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SESAMEQNAME.java new file mode 100644 index 00000000000..b3cdfa2a5f9 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SESAMEQNAME.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Defines constants for the Sesame QName schema namespace. + * + * @author Peter Ansell + * @since 2.7.0 + */ +public class SESAMEQNAME { + + /** + * The Sesame QName Schema namespace ( + * http://www.openrdf.org/schema/qname#). + */ + public static final String NAMESPACE = "http://www.openrdf.org/schema/qname#"; + + /** + * Recommended prefix for the Sesame QName Schema namespace: "q" + */ + public static final String PREFIX = "q"; + + /** + * An immutable {@link Namespace} constant that represents the Sesame QName + * namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + /** http://www.openrdf.org/schema/qname#qname */ + public final static IRI QNAME; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + QNAME = factory.createIRI(SESAMEQNAME.NAMESPACE, "qname"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SKOS.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SKOS.java new file mode 100644 index 00000000000..e02d3e2bee4 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SKOS.java @@ -0,0 +1,377 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Vocabulary constants for the Simple + * Knowledge Organization System (SKOS). + * + * @see SKOS Simple Knowledge + * Organization System Reference + * @author Jeen Broekstra + */ +public class SKOS { + + /** + * The SKOS namespace: http://www.w3.org/2004/02/skos/core# + */ + public static final String NAMESPACE = "http://www.w3.org/2004/02/skos/core#"; + + /** + * The recommended prefix for the SKOS namespace: "skos" + */ + public static final String PREFIX = "skos"; + + /** + * An immutable {@link Namespace} constant that represents the SKOS + * namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + /* classes */ + + /** + * The skos:Concept class + * + * @see The + * skos:Concept Class + */ + public static final IRI CONCEPT; + + /** + * The skos:ConceptScheme class + * + * @see Concept + * Schemes + */ + public static final IRI CONCEPT_SCHEME; + + /** + * The skos:Collection class + * + * @see Concept + * Collections + */ + public static final IRI COLLECTION; + + /** + * The skos:OrderedCollection class + * + * @see Concept + * Collections + */ + public static final IRI ORDERED_COLLECTION; + + /* lexical labels */ + + /** + * The skos:prefLabel lexical label property. + * + * @see Lexical + * Labels + */ + public static final IRI PREF_LABEL; + + /** + * The skos:altLabel lexical label property. + * + * @see Lexical + * Labels + */ + public static final IRI ALT_LABEL; + + /** + * The skos:hiddenLabel lexical label property. + * + * @see Lexical + * Labels + */ + public static final IRI HIDDEN_LABEL; + + /* Concept Scheme properties */ + + /** + * The skos:inScheme relation. + * + * @see Concept + * Schemes + */ + public static final IRI IN_SCHEME; + + /** + * The skos:hasTopConcept relation. + * + * @see Concept + * Schemes + */ + public static final IRI HAS_TOP_CONCEPT; + + /** + * The skos:topConceptOf relation. + * + * @see Concept + * Schemes + */ + public static final IRI TOP_CONCEPT_OF; + + /* collection properties */ + + /** + * The skos:member relation. + * + * @see Concept + * Collections + */ + public static final IRI MEMBER; + + /** + * The skos:memberList relation. + * + * @see Concept + * Collections + */ + public static final IRI MEMBER_LIST; + + /* notation properties */ + + /** + * The skos:notation property. + * + * @see Notations + */ + public static final IRI NOTATION; + + /* documentation properties */ + + /** + * The skos:changeNote property. + * + * @see Documentation + * Properties (Note Properties) + */ + public static final IRI CHANGE_NOTE; + + /** + * The skos:definition property. + * + * @see Documentation + * Properties (Note Properties) + */ + public static final IRI DEFINITION; + + /** + * The skos:editorialNote property. + * + * @see Documentation + * Properties (Note Properties) + */ + public static final IRI EDITORIAL_NOTE; + + /** + * The skos:example property. + * + * @see Documentation + * Properties (Note Properties) + */ + + public static final IRI EXAMPLE; + + /** + * The skos:historyNote property. + * + * @see Documentation + * Properties (Note Properties) + */ + public static final IRI HISTORY_NOTE; + + /** + * The skos:note property. + * + * @see Documentation + * Properties (Note Properties) + */ + public static final IRI NOTE; + + /** + * The skos:scopeNote property. + * + * @see Documentation + * Properties (Note Properties) + */ + public static final IRI SCOPE_NOTE; + + /* semantic relations */ + + /** + * The skos:broader relation. + * + * @see SKOS + * Simple Knowledge Organization System Reference - Semantic Relations + * Section + */ + public static final IRI BROADER; + + /** + * The skos:broaderTransitive relation. + * + * @see SKOS + * Simple Knowledge Organization System Reference - Semantic Relations + * Section + */ + public static final IRI BROADER_TRANSITIVE; + + /** + * The skos:narrower relation. + * + * @see SKOS + * Simple Knowledge Organization System Reference - Semantic Relations + * Section + */ + public static final IRI NARROWER; + + /** + * The skos:narrowerTransitive relation. + * + * @see SKOS + * Simple Knowledge Organization System Reference - Semantic Relations + * Section + */ + public static final IRI NARROWER_TRANSITIVE; + + /** + * The skos:related relation. + * + * @see SKOS + * Simple Knowledge Organization System Reference - Semantic Relations + * Section + */ + public static final IRI RELATED; + + /** + * The skos:semanticRelation relation. + * + * @see SKOS + * Simple Knowledge Organization System Reference - Semantic Relations + * Section + */ + public static final IRI SEMANTIC_RELATION; + + /* mapping properties */ + + /** + * The skos:broadMatch relation. + * + * @see SKOS Simple + * Knowledge Organization System Reference - Mapping Properties + * Section + */ + public static final IRI BROAD_MATCH; + + /** + * The skos:closeMatch relation. + * + * @see SKOS Simple + * Knowledge Organization System Reference - Mapping Properties + * Section + */ + public static final IRI CLOSE_MATCH; + + /** + * The skos:exactMatch relation. + * + * @see SKOS Simple + * Knowledge Organization System Reference - Mapping Properties + * Section + */ + public static final IRI EXACT_MATCH; + + /** + * The skos:mappingRelation relation. + * + * @see SKOS Simple + * Knowledge Organization System Reference - Mapping Properties + * Section + */ + public static final IRI MAPPING_RELATION; + + /** + * The skos:narrowMatch relation. + * + * @see SKOS Simple + * Knowledge Organization System Reference - Mapping Properties + * Section + */ + public static final IRI NARROW_MATCH; + + /** + * The skos:relatedMatch relation. + * + * @see SKOS Simple + * Knowledge Organization System Reference - Mapping Properties + * Section + */ + public static final IRI RELATED_MATCH; + + static { + final ValueFactory f = SimpleValueFactory.getInstance(); + + CONCEPT = f.createIRI(NAMESPACE, "Concept"); + CONCEPT_SCHEME = f.createIRI(NAMESPACE, "ConceptScheme"); + COLLECTION = f.createIRI(NAMESPACE, "Collection"); + ORDERED_COLLECTION = f.createIRI(NAMESPACE, "OrderedCollection"); + + PREF_LABEL = f.createIRI(NAMESPACE, "prefLabel"); + ALT_LABEL = f.createIRI(NAMESPACE, "altLabel"); + + BROADER = f.createIRI(NAMESPACE, "broader"); + NARROWER = f.createIRI(NAMESPACE, "narrower"); + + HAS_TOP_CONCEPT = f.createIRI(NAMESPACE, "hasTopConcept"); + MEMBER = f.createIRI(NAMESPACE, "member"); + + HIDDEN_LABEL = f.createIRI(NAMESPACE, "hiddenLabel"); + + IN_SCHEME = f.createIRI(NAMESPACE, "inScheme"); + + TOP_CONCEPT_OF = f.createIRI(NAMESPACE, "topConceptOf"); + + MEMBER_LIST = f.createIRI(NAMESPACE, "memberList"); + NOTATION = f.createIRI(NAMESPACE, "notation"); + CHANGE_NOTE = f.createIRI(NAMESPACE, "changeNote"); + DEFINITION = f.createIRI(NAMESPACE, "definition"); + EDITORIAL_NOTE = f.createIRI(NAMESPACE, "editorialNote"); + EXAMPLE = f.createIRI(NAMESPACE, "example"); + HISTORY_NOTE = f.createIRI(NAMESPACE, "historyNote"); + NOTE = f.createIRI(NAMESPACE, "note"); + SCOPE_NOTE = f.createIRI(NAMESPACE, "scopeNote"); + BROADER_TRANSITIVE = f.createIRI(NAMESPACE, "broaderTransitive"); + NARROWER_TRANSITIVE = f.createIRI(NAMESPACE, "narrowerTransitive"); + RELATED = f.createIRI(NAMESPACE, "related"); + SEMANTIC_RELATION = f.createIRI(NAMESPACE, "semanticRelation"); + BROAD_MATCH = f.createIRI(NAMESPACE, "broadMatch"); + CLOSE_MATCH = f.createIRI(NAMESPACE, "closeMatch"); + EXACT_MATCH = f.createIRI(NAMESPACE, "exactMatch"); + MAPPING_RELATION = f.createIRI(NAMESPACE, "mappingRelation"); + NARROW_MATCH = f.createIRI(NAMESPACE, "narrowMatch"); + RELATED_MATCH = f.createIRI(NAMESPACE, "relatedMatch"); + + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SP.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SP.java new file mode 100644 index 00000000000..d6280e5fe1c --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SP.java @@ -0,0 +1,750 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * @since 2.7.3 + * @version 1.4.0 + */ +public class SP { + + /** + * http://spinrdf.org/sp An RDF Schema to syntactically represent SPARQL + * queries (including SPARQL UPDATE) as RDF triples. + */ + private static String NAMESPACE = "http://spinrdf.org/sp#"; + + /** + * http://spinrdf.org/sp#Path The base class of SPARQL property path + * expressions. Paths are used by sp:TriplePath triple paths. + */ + public static IRI PATH_CLASS; + + /** + * http://spinrdf.org/sp#SystemClass An "artificial" root class that groups + * all SP classes. This makes them look much less overwhelming in UI tools. + * Typical end users don't need to see those classes anyway. + */ + public static IRI SYSTEM_CLASS; + + /** + * http://spinrdf.org/sp#Asc Marker to indicate ascending order. + */ + public static IRI ASC_CLASS; + + /** + * http://spinrdf.org/sp#OrderByCondition An abstract base class for + * ascending or descending order conditions. Instances of this class + * (typically bnodes) must have a value for expression to point to the actual + * values. + */ + public static IRI ORDER_BY_CONDITION_CLASS; + + /** + * http://spinrdf.org/sp#Sum Represents sum aggregations, e.g. SELECT + * SUM(?varName)... + */ + public static IRI SUM_CLASS; + + /** + * http://spinrdf.org/sp#Aggregation Base class of aggregation types (not + * part of the SPARQL 1.0 standard but supported by ARQ and other engines). + */ + public static IRI AGGREGATION_CLASS; + + /** + * http://spinrdf.org/sp#Union A UNION group. + */ + public static IRI UNION_CLASS; + + /** + * http://spinrdf.org/sp#ElementGroup Abstract base class of group patterns. + */ + public static IRI ELEMENT_GROUP_CLASS; + + /** + * http://spinrdf.org/sp#TriplePattern A triple pattern used in the body of a + * query. + */ + public static IRI TRIPLE_PATTERN_CLASS; + + /** + * http://spinrdf.org/sp#Element An abstract base class for all pattern + * elements. + */ + public static IRI ELEMENT_CLASS; + + /** + * http://spinrdf.org/sp#Triple A base class for TriplePattern and + * TripleTemplate. This basically specifies that subject, predicate and + * object must be present. + */ + public static IRI TRIPLE_CLASS; + + /** + * http://spinrdf.org/sp#Load A LOAD Update operation. The document to load + * is specified using sp:document, and the (optional) target graph using + * sp:into. + */ + public static IRI LOAD_CLASS; + + /** + * http://spinrdf.org/sp#Update Abstract base class to group the various + * SPARQL UPDATE commands. + */ + public static IRI UPDATE_CLASS; + + /** + * http://spinrdf.org/sp#DeleteData An Update operation to delete specific + * triples. The graph triples are represented using sp:data, which points to + * an rdf:List of sp:Triples or sp:NamedGraphs. + */ + public static IRI DELETE_DATA_CLASS; + + /** + * http://spinrdf.org/sp#Desc Marker to indicate descending order. + */ + public static IRI DESC_CLASS; + + /** + * http://spinrdf.org/sp#TripleTemplate A prototypical triple used as + * template in the head of a Construct query. May contain variables. + */ + public static IRI TRIPLE_TEMPLATE_CLASS; + + /** + * http://spinrdf.org/sp#Max Represents MAX aggregations. + */ + public static IRI MAX_CLASS; + + /** + * http://spinrdf.org/sp#Insert Deprecated - use sp:Modify instead. + * Represents a INSERT INTO (part of SPARQL UPDATE language). The graph IRIs + * are stored in sp:graphIRI. The template patterns to delete are stored in + * sp:insertPattern. The WHERE clause is represented using sp:where. + */ + public static IRI INSERT_CLASS; + + /** + * http://spinrdf.org/sp#Modify Represents a MODIFY (part of SPARQL UPDATE + * language). The graph IRIs are stored in sp:graphIRI. The template patterns + * are stored in sp:deletePattern and sp:insertPattern. The WHERE clause is + * represented using sp:where. + */ + public static IRI MODIFY_CLASS; + + /** + * http://spinrdf.org/sp#Insert Deprecated - use sp:Modify instead. + * Represents a INSERT INTO (part of SPARQL UPDATE language). The graph IRIs + * are stored in sp:graphIRI. The template patterns to delete are stored in + * sp:insertPattern. The WHERE clause is represented using sp:where. + */ + @Deprecated + public static IRI Insert; + + /** + * http://spinrdf.org/sp#Avg Represents AVG aggregations. + */ + public static IRI AVG_CLASS; + + /** + * http://spinrdf.org/sp#TriplePath Similar to a TriplePattern, but with a + * path expression as its predicate. For example, this can be used to express + * transitive sub-class relationships (?subClass rdfs:subClassOf* + * ?superClass). + */ + public static IRI TRIPLE_PATH_CLASS; + + /** + * http://spinrdf.org/sp#Tuple Abstract base class for things that have + * subject and object. + */ + public static IRI TUPLE_CLASS; + + /** + * http://spinrdf.org/sp#Let Deprecated: use sp:Bind instead. A variable + * assignment (LET (? := )). Not part of the SPARQL 1.0 + * standard, but (for example) ARQ. + */ + public static IRI LET_CLASS; + + /** + * http://spinrdf.org/sp#Bind A BIND element. + */ + public static IRI BIND_CLASS; + + /** + * http://spinrdf.org/sp#Let Deprecated: use sp:Bind instead. A variable + * assignment (LET (? := )). Not part of the SPARQL 1.0 + * standard, but (for example) ARQ. + */ + @Deprecated + public static IRI Let; + + /** + * http://spinrdf.org/sp#ElementList A list of Elements. This class is never + * instantiated directly as SPIN will use plain rdf:Lists to store element + * lists. + */ + public static IRI ELEMENT_LIST_CLASS; + + /** + * http://spinrdf.org/sp#SubQuery A nested SELECT query inside of an element + * list. The query is stored in sp:query. + */ + public static IRI SUB_QUERY_CLASS; + + /** + * http://spinrdf.org/sp#Delete Deprecated - use sp:Modify instead. + * Represents a DELETE FROM (part of SPARQL UPDATE language). The graph IRIs + * are stored in sp:graphIRI. The template patterns to delete are stored in + * sp:deletePattern. The WHERE clause is represented using sp:where. + */ + public static IRI DELETE_CLASS; + + /** + * http://spinrdf.org/sp#Delete Deprecated - use sp:Modify instead. + * Represents a DELETE FROM (part of SPARQL UPDATE language). The graph IRIs + * are stored in sp:graphIRI. The template patterns to delete are stored in + * sp:deletePattern. The WHERE clause is represented using sp:where. + */ + @Deprecated + public static IRI Delete; + + /** + * http://spinrdf.org/sp#Min Represents MIN aggregations. + */ + public static IRI MIN_CLASS; + + /** + * http://spinrdf.org/sp#Optional An optional element in a query. + */ + public static IRI OPTIONAL_CLASS; + + /** + * http://spinrdf.org/sp#AltPath An alternative path with the union of + * sp:path1 and sp:path2. + */ + public static IRI ALT_PATH_CLASS; + + /** + * http://spinrdf.org/sp#Count Counts the number of times a variable is used. + * The variable is stored in the variable property. This might be left blank + * to indicate COUNT(*). + */ + public static IRI COUNT_CLASS; + + /** + * http://spinrdf.org/sp#ReversePath A path with reversed direction. + */ + public static IRI REVERSE_PATH_CLASS; + + /** + * http://spinrdf.org/sp#Construct A CONSTRUCT-type query that can be used to + * construct new triples from template triples (head) that use variable + * bindings from the match patterns (body). + */ + public static IRI CONSTRUCT_CLASS; + + /** + * http://spinrdf.org/sp#Query Abstract base class of the various types of + * supported queries. Common to all types of queries is that they can have a + * body ("WHERE clause"). + */ + public static IRI QUERY_CLASS; + + /** + * http://spinrdf.org/sp#Variable A variable mentioned in a Triple or + * expression. Variables are often blank nodes with the variable name stored + * in ts:name. Variables can also be supplied with a URI in which case the + * system will attempt to reuse the same variable instance across multiple + * query definitions. + */ + public static IRI VARIABLE_CLASS; + + /** + * http://spinrdf.org/sp#Ask An ASK query that returns true if the condition + * in the body is met by at least one result set. + */ + public static IRI ASK_CLASS; + + /** + * http://spinrdf.org/sp#ModPath A modified path such as rdfs:subClassOf*. + */ + public static IRI MOD_PATH_CLASS; + + /** + * http://spinrdf.org/sp#Create An Update operation that creates a new empty + * graph with a name specified by sp:graphIRI. May have sp:silent set to + * true. + */ + public static IRI CREATE_CLASS; + + /** + * http://spinrdf.org/sp#NamedGraph A named Graph element such as GRAPH + * {...}. + */ + public static IRI NAMED_GRAPH_CLASS; + + /** + * http://spinrdf.org/sp#Command A shared superclass for sp:Query and + * sp:Update that can be used to specify that the range of property can be + * either one. + */ + public static IRI COMMAND_CLASS; + + public static IRI REVERSE_LINK_PATH_CLASS; + + /** + * http://spinrdf.org/sp#NotExists A NOT EXISTS element group. + */ + public static IRI NOT_EXISTS_CLASS; + + /** + * http://spinrdf.org/sp#Drop An Update operation that removes a specified + * graph from the Graph Store. Must specify the graph using sp:graphIRI, or + * sp:default, sp:named or sp:all. May have the SILENT flag, encoded using + * sp:silent. + */ + public static IRI DROP_CLASS; + + /** + * http://spinrdf.org/sp#InsertData An Update operation to insert specific + * triples. The graph triples are represented using sp:data, which points to + * an rdf:List of sp:Triples or sp:NamedGraphs. + */ + public static IRI INSERT_DATA_CLASS; + + /** + * http://spinrdf.org/sp#DeleteWhere An Update operation where the triples + * matched by the WHERE clause (sp:where) will be the triples deleted. + */ + public static IRI DELETE_WHERE_CLASS; + + /** + * http://spinrdf.org/sp#Service A SERVICE call that matches a nested + * sub-pattern against a SPARQL end point specified by a URI. + */ + public static IRI SERVICE_CLASS; + + /** + * http://spinrdf.org/sp#Select A SELECT-type query that returns variable + * bindings as its result. + */ + public static IRI SELECT_CLASS; + + /** + * http://spinrdf.org/sp#Filter A constraint element that evaluates a given + * expression to true or false. + */ + public static IRI FILTER_CLASS; + + /** + * http://spinrdf.org/sp#Minus A MINUS element group. + */ + public static IRI MINUS_CLASS; + + /** + * http://spinrdf.org/sp#Clear An Update operation that removes all triples + * from a specified graph. Must specify the graph using sp:graphIRI, or + * sp:default, sp:named or sp:all. May have the SILENT flag, encoded using + * sp:silent. + */ + public static IRI CLEAR_CLASS; + + /** + * http://spinrdf.org/sp#Describe A DESCRIBE-type Query. + */ + public static IRI DESCRIBE_CLASS; + + /** + * http://spinrdf.org/sp#SeqPath A sequence of multiple paths. + */ + public static IRI SEQ_PATH_CLASS; + + /** + * http://spinrdf.org/sp#arg5 The fifth argument of a function call. Further + * arguments are not common in SPARQL, therefore no sp:arg6, etc are defined + * here. However, they can be created if needed. + */ + public static IRI ARG5_PROPERTY; + + /** + * http://spinrdf.org/sp#arg Abstract superproperty for the enumerated arg1, + * arg2 etc. + */ + public static IRI ARG_PROPERTY; + + /** + * http://spinrdf.org/sp#path1 The first child path of a property path. Used + * by sp:AltPath and sp:SeqPath. + */ + public static IRI PATH1_PROPERTY; + + /** + * http://spinrdf.org/sp#systemProperty An abstract base proprerty that + * groups together the SP system properties. Users typically don't need to + * see them anyway. + */ + public static IRI SYSTEM_PROPERTY; + + /** + * http://spinrdf.org/sp#arg1 The first argument of a function call. + */ + public static IRI ARG1_PROPERTY; + + /** + * http://spinrdf.org/sp#default Used in DROP and CLEAR. + */ + public static IRI DEFAULT_PROPERTY; + + /** + * http://spinrdf.org/sp#object An RDF Node or Variable describing the object + * of a triple. + */ + public static IRI OBJECT_PROPERTY; + + /** + * http://spinrdf.org/sp#graphNameNode The name (URI or Variable) of a + * NamedGraph. + */ + public static IRI GRAPH_NAME_NODE_PROPERTY; + + /** + * http://spinrdf.org/sp#varName The name of a Variable. + */ + public static IRI VAR_NAME_PROPERTY; + + /** + * http://spinrdf.org/sp#named Used in DROP and CLEAR. + */ + public static IRI NAMED_PROPERTY; + + /** + * http://spinrdf.org/sp#as Points to a Variable used in an AS statement such + * as COUNT aggregates. + */ + public static IRI AS_PROPERTY; + + /** + * http://spinrdf.org/sp#distinct A marker property to indicate that a Select + * query is of type SELECT DISTINCT. + */ + public static IRI DISTINCT_PROPERTY; + + /** + * http://spinrdf.org/sp#path2 The second child path of a property path. Used + * by sp:AltPath and sp:SeqPath. + */ + public static IRI PATH2_PROPERTY; + + /** + * http://spinrdf.org/sp#orderBy Links a query with an ORDER BY clause where + * the values are rdf:List containing OrderByConditions or expressions. While + * the domain of this property is sp:Query, only Describe and Select queries + * can have values of it. + */ + public static IRI ORDER_BY_PROPERTY; + + /** + * http://spinrdf.org/sp#variable The variable of a Bind element. + */ + public static IRI VARIABLE_PROPERTY; + + /** + * http://spinrdf.org/sp#arg4 The forth argument of a function call. + */ + public static IRI ARG4_PROPERTY; + + public static IRI SILENT_PROPERTY; + + /** + * http://spinrdf.org/sp#having Points from a SELECT query to a list of + * HAVING expressions. + */ + public static IRI HAVING_PROPERTY; + + /** + * http://spinrdf.org/sp#query Links a SubQuery resource with the nested + * Query. + */ + public static IRI QUERY_PROPERTY; + + /** + * http://spinrdf.org/sp#groupBy Points from a Query to the list of GROUP BY + * expressions. + */ + public static IRI GROUP_BY_PROPERTY; + + /** + * http://spinrdf.org/sp#graphIRI Points to graph names (IRIs) in various + * sp:Update operations. + */ + public static IRI GRAPH_IRI_PROPERTY; + + /** + * http://spinrdf.org/sp#limit The LIMIT solution modifier of a Query. + */ + public static IRI LIMIT_PROPERTY; + + public static IRI USING_PROPERTY; + + /** + * http://spinrdf.org/sp#templates Points to a list of TripleTemplates that + * form the head of a Construct query. + */ + public static IRI TEMPLATES_PROPERTY; + + /** + * http://spinrdf.org/sp#resultNodes Contains the result nodes (URI resources + * or Variables) of a Describe query. + */ + public static IRI RESULT_NODES_PROPERTY; + + public static IRI USING_NAMED_PROPERTY; + + /** + * http://spinrdf.org/sp#arg3 The third argument of a function call. + */ + public static IRI ARG3_PROPERTY; + + /** + * http://spinrdf.org/sp#reduced A property with true to indicate that a + * Select query has a REDUCED flag. + */ + public static IRI REDUCED_PROPERTY; + + /** + * http://spinrdf.org/sp#subPath The child path of a property path + * expression. This is used by ReversePath and ModPath. + */ + public static IRI SUB_PATH_PROPERTY; + + /** + * http://spinrdf.org/sp#into The (optional) target of a LOAD Update + * operation. + */ + public static IRI INTO_PROPERTY; + + public static IRI WITH_PROPERTY; + + /** + * http://spinrdf.org/sp#serviceURI Used by sp:Service to specify the URI of + * the SPARQL end point to invoke. Must point to a URI node. + */ + public static IRI SERVICE_URI_PROPERTY; + + /** + * http://spinrdf.org/sp#document The URI of the document to load using a + * LOAD Update operation. + */ + public static IRI DOCUMENT_PROPERTY; + + /** + * http://spinrdf.org/sp#where The WHERE clause of a Query. + */ + public static IRI WHERE_PROPERTY; + + /** + * http://spinrdf.org/sp#resultVariables An rdf:List of variables that are + * returned by a Select query. + */ + public static IRI RESULT_VARIABLES_PROPERTY; + + /** + * http://spinrdf.org/sp#text Can be attached to sp:Queries to store a + * textual representation of the query. This can be useful for tools that do + * not have a complete SPIN Syntax parser available. + */ + public static IRI TEXT_PROPERTY; + + /** + * http://spinrdf.org/sp#path Points from a TriplePath to its path. + */ + public static IRI PATH_PROPERTY; + + public static IRI MOD_MAX_PROPERTY; + + /** + * http://spinrdf.org/sp#predicate A resource or Variable describing the + * predicate of a triple. + */ + public static IRI PREDICATE_PROPERTY; + + /** + * http://spinrdf.org/sp#elements Points to an ElementList, for example in an + * Optional element. + */ + public static IRI ELEMENTS_PROPERTY; + + public static IRI NODE_PROPERTY; + + /** + * http://spinrdf.org/sp#fromNamed Specifies a named RDF Dataset used by a + * Query (FROM NAMED syntax in SPARQL). Values of this property must be URI + * resources. + */ + public static IRI FROM_NAMED_PROPERTY; + + /** + * http://spinrdf.org/sp#arg2 The second argument of a function call. + */ + public static IRI ARG2_PROPERTY; + + /** + * http://spinrdf.org/sp#subject A resource or Variable describing the + * subject of a triple. + */ + public static IRI SUBJECT_PROPERTY; + + /** + * http://spinrdf.org/sp#expression Points to an expression, for example in a + * Filter or Assignment. + */ + public static IRI EXPRESSION_PROPERTY; + + /** + * http://spinrdf.org/sp#deletePattern Points to a list of sp:TripleTemplates + * and sp:NamedGraphs in a modify operation. + */ + public static IRI DELETE_PATTERN_PROPERTY; + + /** + * http://spinrdf.org/sp#all Used in DROP and CLEAR. + */ + public static IRI ALL_PROPERTY; + + /** + * http://spinrdf.org/sp#offset The OFFSET solution modifier of a Query. + */ + public static IRI OFFSET_PROPERTY; + + /** + * http://spinrdf.org/sp#from Specifies an RDF Dataset used by a Query (FROM + * syntax in SPARQL). Values of this property must be URI resources. + */ + public static IRI FROM_PROPERTY; + + public static IRI MOD_MIN_PROPERTY; + + /** + * http://spinrdf.org/sp#insertPattern Points to a list of sp:TripleTemplates + * or sp:NamedGraphs in a modify command. + */ + public static IRI INSERT_PATTERN_PROPERTY; + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + PATH_CLASS = factory.createIRI(NAMESPACE, "Path"); + SYSTEM_CLASS = factory.createIRI(NAMESPACE, "SystemClass"); + ASC_CLASS = factory.createIRI(NAMESPACE, "Asc"); + ORDER_BY_CONDITION_CLASS = factory.createIRI(NAMESPACE, "OrderByCondition"); + SUM_CLASS = factory.createIRI(NAMESPACE, "Sum"); + AGGREGATION_CLASS = factory.createIRI(NAMESPACE, "Aggregation"); + UNION_CLASS = factory.createIRI(NAMESPACE, "Union"); + ELEMENT_GROUP_CLASS = factory.createIRI(NAMESPACE, "ElementGroup"); + TRIPLE_PATTERN_CLASS = factory.createIRI(NAMESPACE, "TriplePattern"); + ELEMENT_CLASS = factory.createIRI(NAMESPACE, "Element"); + TRIPLE_CLASS = factory.createIRI(NAMESPACE, "Triple"); + LOAD_CLASS = factory.createIRI(NAMESPACE, "Load"); + UPDATE_CLASS = factory.createIRI(NAMESPACE, "Update"); + DELETE_DATA_CLASS = factory.createIRI(NAMESPACE, "DeleteData"); + DESC_CLASS = factory.createIRI(NAMESPACE, "Desc"); + TRIPLE_TEMPLATE_CLASS = factory.createIRI(NAMESPACE, "TripleTemplate"); + MAX_CLASS = factory.createIRI(NAMESPACE, "Max"); + INSERT_CLASS = factory.createIRI(NAMESPACE, "Insert"); + MODIFY_CLASS = factory.createIRI(NAMESPACE, "Modify"); + AVG_CLASS = factory.createIRI(NAMESPACE, "Avg"); + TRIPLE_PATH_CLASS = factory.createIRI(NAMESPACE, "TriplePath"); + TUPLE_CLASS = factory.createIRI(NAMESPACE, "Tuple"); + LET_CLASS = factory.createIRI(NAMESPACE, "Let"); + BIND_CLASS = factory.createIRI(NAMESPACE, "Bind"); + ELEMENT_LIST_CLASS = factory.createIRI(NAMESPACE, "ElementList"); + SUB_QUERY_CLASS = factory.createIRI(NAMESPACE, "SubQuery"); + DELETE_CLASS = factory.createIRI(NAMESPACE, "Delete"); + MIN_CLASS = factory.createIRI(NAMESPACE, "Min"); + OPTIONAL_CLASS = factory.createIRI(NAMESPACE, "Optional"); + ALT_PATH_CLASS = factory.createIRI(NAMESPACE, "AltPath"); + COUNT_CLASS = factory.createIRI(NAMESPACE, "Count"); + REVERSE_PATH_CLASS = factory.createIRI(NAMESPACE, "ReversePath"); + CONSTRUCT_CLASS = factory.createIRI(NAMESPACE, "Construct"); + QUERY_CLASS = factory.createIRI(NAMESPACE, "Query"); + VARIABLE_CLASS = factory.createIRI(NAMESPACE, "Variable"); + ASK_CLASS = factory.createIRI(NAMESPACE, "Ask"); + MOD_PATH_CLASS = factory.createIRI(NAMESPACE, "ModPath"); + CREATE_CLASS = factory.createIRI(NAMESPACE, "Create"); + NAMED_GRAPH_CLASS = factory.createIRI(NAMESPACE, "NamedGraph"); + COMMAND_CLASS = factory.createIRI(NAMESPACE, "Command"); + REVERSE_LINK_PATH_CLASS = factory.createIRI(NAMESPACE, "ReverseLinkPath"); + NOT_EXISTS_CLASS = factory.createIRI(NAMESPACE, "NotExists"); + DROP_CLASS = factory.createIRI(NAMESPACE, "Drop"); + INSERT_DATA_CLASS = factory.createIRI(NAMESPACE, "InsertData"); + DELETE_WHERE_CLASS = factory.createIRI(NAMESPACE, "DeleteWhere"); + SERVICE_CLASS = factory.createIRI(NAMESPACE, "Service"); + SELECT_CLASS = factory.createIRI(NAMESPACE, "Select"); + FILTER_CLASS = factory.createIRI(NAMESPACE, "Filter"); + MINUS_CLASS = factory.createIRI(NAMESPACE, "Minus"); + CLEAR_CLASS = factory.createIRI(NAMESPACE, "Clear"); + DESCRIBE_CLASS = factory.createIRI(NAMESPACE, "Describe"); + SEQ_PATH_CLASS = factory.createIRI(NAMESPACE, "SeqPath"); + ARG5_PROPERTY = factory.createIRI(NAMESPACE, "arg5"); + ARG_PROPERTY = factory.createIRI(NAMESPACE, "arg"); + PATH1_PROPERTY = factory.createIRI(NAMESPACE, "path1"); + SYSTEM_PROPERTY = factory.createIRI(NAMESPACE, "systemProperty"); + ARG1_PROPERTY = factory.createIRI(NAMESPACE, "arg1"); + DEFAULT_PROPERTY = factory.createIRI(NAMESPACE, "default"); + OBJECT_PROPERTY = factory.createIRI(NAMESPACE, "object"); + GRAPH_NAME_NODE_PROPERTY = factory.createIRI(NAMESPACE, "graphNameNode"); + VAR_NAME_PROPERTY = factory.createIRI(NAMESPACE, "varName"); + NAMED_PROPERTY = factory.createIRI(NAMESPACE, "named"); + AS_PROPERTY = factory.createIRI(NAMESPACE, "as"); + DISTINCT_PROPERTY = factory.createIRI(NAMESPACE, "distinct"); + PATH2_PROPERTY = factory.createIRI(NAMESPACE, "path2"); + ORDER_BY_PROPERTY = factory.createIRI(NAMESPACE, "orderBy"); + VARIABLE_PROPERTY = factory.createIRI(NAMESPACE, "variable"); + ARG4_PROPERTY = factory.createIRI(NAMESPACE, "arg4"); + SILENT_PROPERTY = factory.createIRI(NAMESPACE, "silent"); + HAVING_PROPERTY = factory.createIRI(NAMESPACE, "having"); + QUERY_PROPERTY = factory.createIRI(NAMESPACE, "query"); + GROUP_BY_PROPERTY = factory.createIRI(NAMESPACE, "groupBy"); + GRAPH_IRI_PROPERTY = factory.createIRI(NAMESPACE, "graphIRI"); + LIMIT_PROPERTY = factory.createIRI(NAMESPACE, "limit"); + USING_PROPERTY = factory.createIRI(NAMESPACE, "using"); + TEMPLATES_PROPERTY = factory.createIRI(NAMESPACE, "templates"); + RESULT_NODES_PROPERTY = factory.createIRI(NAMESPACE, "resultNodes"); + USING_NAMED_PROPERTY = factory.createIRI(NAMESPACE, "usingNamed"); + ARG3_PROPERTY = factory.createIRI(NAMESPACE, "arg3"); + REDUCED_PROPERTY = factory.createIRI(NAMESPACE, "reduced"); + SUB_PATH_PROPERTY = factory.createIRI(NAMESPACE, "subPath"); + INTO_PROPERTY = factory.createIRI(NAMESPACE, "into"); + WITH_PROPERTY = factory.createIRI(NAMESPACE, "with"); + SERVICE_URI_PROPERTY = factory.createIRI(NAMESPACE, "serviceURI"); + DOCUMENT_PROPERTY = factory.createIRI(NAMESPACE, "document"); + WHERE_PROPERTY = factory.createIRI(NAMESPACE, "where"); + RESULT_VARIABLES_PROPERTY = factory.createIRI(NAMESPACE, "resultVariables"); + TEXT_PROPERTY = factory.createIRI(NAMESPACE, "text"); + PATH_PROPERTY = factory.createIRI(NAMESPACE, "path"); + MOD_MAX_PROPERTY = factory.createIRI(NAMESPACE, "modMax"); + PREDICATE_PROPERTY = factory.createIRI(NAMESPACE, "predicate"); + ELEMENTS_PROPERTY = factory.createIRI(NAMESPACE, "elements"); + NODE_PROPERTY = factory.createIRI(NAMESPACE, "node"); + FROM_NAMED_PROPERTY = factory.createIRI(NAMESPACE, "fromNamed"); + ARG2_PROPERTY = factory.createIRI(NAMESPACE, "arg2"); + SUBJECT_PROPERTY = factory.createIRI(NAMESPACE, "subject"); + EXPRESSION_PROPERTY = factory.createIRI(NAMESPACE, "expression"); + DELETE_PATTERN_PROPERTY = factory.createIRI(NAMESPACE, "deletePattern"); + ALL_PROPERTY = factory.createIRI(NAMESPACE, "all"); + OFFSET_PROPERTY = factory.createIRI(NAMESPACE, "offset"); + FROM_PROPERTY = factory.createIRI(NAMESPACE, "from"); + MOD_MIN_PROPERTY = factory.createIRI(NAMESPACE, "modMin"); + INSERT_PATTERN_PROPERTY = factory.createIRI(NAMESPACE, "insertPattern"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SPIN.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SPIN.java new file mode 100644 index 00000000000..2a035b6e663 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/SPIN.java @@ -0,0 +1,446 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * @since 2.7.3 + * @version 1.3.0 + */ +public class SPIN { + + /** + * http://spinrdf.org/spin An RDF Schema that can be used to attach + * constraints and rules to RDFS classes, and to encapsulate reusable SPARQL + * queries into functions and templates. + */ + private static String NAMESPACE = "http://spinrdf.org/spin#"; + + /** + * http://spinrdf.org/spin#Function Metaclass for functions that can be used + * in SPARQL expressions (e.g. FILTER or BIND). The function themselves are + * classes that are instances of this metaclass. Function calls are instances + * of the function classes, with property values for the arguments. + */ + public static IRI FUNCTION_CLASS; + + /** + * http://spinrdf.org/spin#Module An abstract building block of a SPARQL + * system. A Module can take Arguments as input and applies them on an input + * RDF Graph. The Arguments should be declared as spin:constraints. + */ + public static IRI MODULE_CLASS; + + /** + * http://spinrdf.org/spin#body The body of a Function or Template. This + * points to a Query instance. For Functions, this is limited to either ASK + * or SELECT type queries. If the body is the ASK function then the return + * value is xsd:boolean. Otherwise, the SELECT query must have a single + * return variable. The first binding of this SELECT query will be returned + * as result of the function call. + */ + public static IRI BODY_PROPERTY; + + /** + * http://spinrdf.org/spin#TableDataProvider An abstraction of objects that + * can produce tabular data. This serves as a base class of + * spin:SelectTemplate, because SELECT queries can produce tables with + * columns for each result variable. However, other types of + * TableDataProviders are conceivable by other frameworks, and this class may + * prove as a useful shared foundation. TableDataProviders can link to + * definitions of columns via spin:column, and these definitions can inform + * rendering engines. + */ + public static IRI TABLE_DATA_PROVIDER_CLASS; + + public static IRI CONSTRUCT_TEMPLATE_CLASS; + + /** + * http://spinrdf.org/spin#Template The metaclass of SPIN templates. + * Templates are classes that are instances of this class. A template + * represents a reusable SPARQL query or update request that can be + * parameterized with arguments. Templates can be instantiated in places + * where normally a SPARQL query or update request is used, in particular as + * spin:rules and spin:constraints. + */ + public static IRI TEMPLATE_CLASS; + + /** + * http://spinrdf.org/spin#Rule Groups together the kinds of SPARQL commands + * that can appear as SPIN rules and constructors: CONSTRUCT, DELETE WHERE + * and DELETE/INSERT. This class is never to be instantiated directly. + */ + public static IRI RULE_CLASS; + + /** + * http://spinrdf.org/spin#AskTemplate A SPIN template that wraps an ASK + * query. + */ + public static IRI ASK_TEMPLATE_CLASS; + + /** + * http://spinrdf.org/spin#UpdateTemplate A SPIN template that has an UPDATE + * command as its body. + */ + public static IRI UPDATE_TEMPLATE_CLASS; + + /** + * http://spinrdf.org/spin#RuleProperty The metaclass of spin:rule and its + * subproperties. spin:RuleProperties can have additional metadata attached + * to them. + */ + public static IRI RULE_PROPERTY_CLASS; + + /** + * http://spinrdf.org/spin#ConstraintViolation An object that can be created + * by spin:constraints to provide information about a constraint violation. + */ + public static IRI CONSTRAINT_VIOLATION_CLASS; + + /** + * http://spinrdf.org/spin#Modules An "artificial" parent class for all + * Functions and Templates. + */ + public static IRI MODULES_CLASS; + + /** + * http://spinrdf.org/spin#SelectTemplate A SPIN template that wraps a SELECT + * query. + */ + public static IRI SELECT_TEMPLATE_CLASS; + + /** + * http://spinrdf.org/spin#Column Provides metadata about a column in the + * result set of a (SPARQL) query, for example of the body queries of SPIN + * templates. Columns can define human-readable labels that serve as column + * titles, using rdfs:label. + */ + public static IRI COLUMN_CLASS; + + /** + * http://spinrdf.org/spin#LibraryOntology A marker class that can be + * attached to base URIs (ontologies) to instruct SPIN engines that this + * ontology only contains a library of SPIN declarations. Library Ontologies + * should be ignored by SPIN inference engines even if they have been + * imported by a domain model. For example, a SPIN version of OWL RL may + * contain all the OWL RL axioms, attached to owl:Thing, but nothing else. + * However, when executed, these axioms should not be executed over + * themselves, because we don't want the system to reason about the SPIN + * triples to speed up things. + */ + public static IRI LIBRARY_ONTOLOGY_CLASS; + + public static IRI MAGIC_PROPERTY_CLASS; + + /** + * http://spinrdf.org/spin#update Can be used to point from any resource to + * an Update. + */ + public static IRI UPDATE_PROPERTY; + + /** + * http://spinrdf.org/spin#command Can be used to link a resource with a + * SPARQL query or update request (sp:Command). + */ + public static IRI COMMAND_PROPERTY; + + /** + * http://spinrdf.org/spin#returnType The return type of a Function, e.g. + * xsd:string. + */ + public static IRI RETURN_TYPE_PROPERTY; + + /** + * http://spinrdf.org/spin#systemProperty An "abstract" base property that + * groups together those system properties that the user will hardly ever + * need to see in property trees. This property may be dropped in future + * versions of this ontology - right now it's mainly here for convenience. + */ + public static IRI SYSTEM_PROPERTY_PROPERTY; + + /** + * http://spinrdf.org/spin#column Can link a TableDataProvider (esp. + * SelectTemplate) with one or more columns that provide metadata for + * rendering purposes. Columns can be sorted by their spin:columnIndex (which + * must align with the ordering of variables in the SELECT query starting + * with 0). Not all result variables of the underlying query need to have a + * matching spin:Column. + */ + public static IRI COLUMN_PROPERTY; + + /** + * http://spinrdf.org/spin#symbol The symbol of a function, e.g. "=" for the + * eq function. + */ + public static IRI SYMBOL_PROPERTY; + + /** + * http://spinrdf.org/spin#violationRoot The root resource of the violation + * (often ?this in the constraint body). + */ + public static IRI VIOLATION_ROOT_PROPERTY; + + /** + * http://spinrdf.org/spin#columnType The datatype or resource type of a + * spin:Column. For example this is useful as metadata to inform a rendering + * engine that numeric columns (e.g. xsd:float) need to be right-aligned. + */ + public static IRI COLUMN_TYPE_PROPERTY; + + /** + * http://spinrdf.org/spin#nextRuleProperty Can be used to link two + * sub-properties of spin:rule (or spin:rule itself) to instruct the SPIN + * engine to execute one set of rules before another one. The values of the + * subject property will be executed before those of the object property. + */ + public static IRI NEXT_RULE_PROPERTY_PROPERTY; + + /** + * http://spinrdf.org/spin#private Can be set to true to indicate that a SPIN + * function is only meant to be used as a helper of other functions, but not + * directly. Among others, this allows user interfaces to filter out private + * functions. Furthermore, it tells potential users of this function that + * they should avoid using this function, as it may not be stable. + */ + public static IRI PRIVATE_PROPERTY; + + /** + * http://spinrdf.org/spin#labelTemplate A template string for displaying + * instantiations of a module in human-readable form. The template may + * contain the argument variable names in curly braces to support + * substitution. For example, "The number of values of the {?arg1} property." + */ + public static IRI LABEL_TEMPLATE_PROPERTY; + + /** + * http://spinrdf.org/spin#violationPath An optional attribute of + * ConstraintViolations to provide a path expression from the root resource + * to the value that is invalid. If this is a URI then the path represents + * the predicate of a subject/predicate combination. Otherwise it should be a + * blank node of type sp:Path. + */ + public static IRI VIOLATION_PATH_PROPERTY; + + /** + * http://spinrdf.org/spin#constructor Can be used to attach a "constructor" + * to a class. A constructor is a SPARQL CONSTRUCT query or INSERT/DELETE + * Update operation that can add initial values to the current instance. At + * execution time, the variable ?this is bound to the current instance. Tools + * can call constructors of a class and its superclasses when an instance of + * a class has been created. Constructors will also be used to initialize + * resources that have received a new rdf:type triple as a result of + * spin:rules firing. + */ + public static IRI CONSTRUCTOR_PROPERTY; + + /** + * http://spinrdf.org/spin#abstract Can be set to true to indicate that this + * module shall not be instantiated. Abstract modules are only there to + * organize other modules into hierarchies. + */ + public static IRI ABSTRACT_PROPERTY; + + /** + * http://spinrdf.org/spin#constraint Links a class with constraints on its + * instances. The values of this property are "axioms" expressed as CONSTRUCT + * or ASK queries where the variable ?this refers to the instances of the + * surrounding class. ASK queries must evaluate to false for each member of + * this class - returning true means that the instance ?this violates the + * constraint. CONSTRUCT queries must create instances of + * spin:ConstraintViolation to provide details on the reason for the + * violation. + */ + public static IRI CONSTRAINT_PROPERTY; + + /** + * http://spinrdf.org/spin#query Can be used to point from any resource to a + * Query. + */ + public static IRI QUERY_PROPERTY; + + /** + * http://spinrdf.org/spin#fix Can be used to link a ConstraintViolation with + * one or more UPDATE Templates that would help fix the violation. + */ + public static IRI FIX_PROPERTY; + + /** + * http://spinrdf.org/spin#columnWidth The preferred width of the associated + * Column, for display purposes. Values in pixels (rendering engines may + * multiply the values depending on resolution). + */ + public static IRI COLUMN_WIDTH_PROPERTY; + + /** + * http://spinrdf.org/spin#violationSource Can be used to link a + * spin:ConstraintViolation with the query or template call that caused it. + * This property is typically filled in automatically by the constraint + * checking engine and does not need to be set manually. However, it can be + * useful to learn more about the origin of a violation. + */ + public static IRI VIOLATION_SOURCE_PROPERTY; + + /** + * http://spinrdf.org/spin#columnIndex The index of a column (from left to + * right) starting at 0. + */ + public static IRI COLUMN_INDEX_PROPERTY; + + /** + * http://spinrdf.org/spin#thisUnbound Can be set to true for SPIN rules and + * constraints that do not require pre-binding the variable ?this with all + * members of the associated class. This flag should only be set to true if + * the WHERE clause is sufficiently strong to only bind instances of the + * associated class, or its subclasses. In those cases, the engine can + * greatly improve performance of query execution, because it does not need + * to add clauses to narrow down the WHERE clause. + */ + public static IRI THIS_UNBOUND_PROPERTY; + + /** + * http://spinrdf.org/spin#rulePropertyMaxIterationCount Can be attached to + * spin:rule (or subclasses thereof) to instruct a SPIN rules engine that it + * shall only execute the rules max times. If no value is specified, then the + * rules will be executed with no specific limit. + */ + public static IRI RULE_PROPERTY_MAX_ITERATION_COUNT_PROPERTY; + + /** + * http://spinrdf.org/spin#imports Can be used to link an RDF graph (usually + * the instance of owl:Ontology) with a SPIN library to define constraints. + * SPIN-aware tools should include the definitions from those libraries for + * constraint checking. Using such libraries is a simpler alternative than + * explicitly importing them using owl:imports, because it does not force all + * the SPIN triples into the RDF model. + */ + public static IRI IMPORTS_PROPERTY; + + /** + * http://spinrdf.org/spin#ConstructTemplates Suggested abstract base class + * for all ConstructTemplates. + */ + public static IRI CONSTRUCT_TEMPLATES_CLASS; + + /** + * http://spinrdf.org/spin#Templates Suggested abstract base class for all + * Templates. + */ + public static IRI TEMPLATES_CLASS; + + /** + * http://spinrdf.org/spin#eval Evaluates a given SPIN expression or SELECT + * or ASK query, and returns its result. The first argument must be the + * expression in SPIN RDF syntax. All other arguments must come in pairs: + * first a property name, and then a value. These name/value pairs will be + * pre-bound variables for the execution of the expression. + */ + public static IRI EVAL_CLASS; + + /** + * http://spinrdf.org/spin#Functions An abstract base class for all defined + * functions. This class mainly serves as a shared root so that the various + * instances of the Function metaclass are grouped together. + */ + public static IRI FUNCTIONS_CLASS; + + /** + * http://spinrdf.org/spin#AskTemplates Suggested abstract base class for all + * AskTemplates. + */ + public static IRI ASK_TEMPLATES_CLASS; + + /** + * http://spinrdf.org/spin#SelectTemplates Suggested abstract base class for + * all SelectTemplates. + */ + public static IRI SELECT_TEMPLATES_CLASS; + + /** + * http://spinrdf.org/spin#MagicProperties An abstract superclass that can be + * used to group all spin:MagicProperty instances under a single parent + * class. + */ + public static IRI MAGIC_PROPERTIES_CLASS; + + /** + * http://spinrdf.org/spin#_this A system variable representing the current + * context instance in a rule or constraint. + */ + public static IRI THIS_CONTEXT_INSTANCE; + + /** + * http://spinrdf.org/spin#UpdateTemplates Suggested abstract base class for + * all UpdateTemplates. + */ + public static IRI UPDATE_TEMPLATES_CLASS; + + /** + * http://spinrdf.org/spin#rule An inferencing rule attached to a class. + * Rules are expressed as CONSTRUCT queries or INSERT/DELETE operations where + * the variable ?this will be bound to the current instance of the class. + * These inferences can be used to derive new values from existing values at + * the instance. + */ + public static IRI RULE_PROPERTY; + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + FUNCTION_CLASS = factory.createIRI(NAMESPACE, "Function"); + MODULE_CLASS = factory.createIRI(NAMESPACE, "Module"); + BODY_PROPERTY = factory.createIRI(NAMESPACE, "body"); + TABLE_DATA_PROVIDER_CLASS = factory.createIRI(NAMESPACE, "TableDataProvider"); + CONSTRUCT_TEMPLATE_CLASS = factory.createIRI(NAMESPACE, "ConstructTemplate"); + TEMPLATE_CLASS = factory.createIRI(NAMESPACE, "Template"); + RULE_CLASS = factory.createIRI(NAMESPACE, "Rule"); + ASK_TEMPLATE_CLASS = factory.createIRI(NAMESPACE, "AskTemplate"); + UPDATE_TEMPLATE_CLASS = factory.createIRI(NAMESPACE, "UpdateTemplate"); + RULE_PROPERTY_CLASS = factory.createIRI(NAMESPACE, "RuleProperty"); + CONSTRAINT_VIOLATION_CLASS = factory.createIRI(NAMESPACE, "ConstraintViolation"); + MODULES_CLASS = factory.createIRI(NAMESPACE, "Modules"); + SELECT_TEMPLATE_CLASS = factory.createIRI(NAMESPACE, "SelectTemplate"); + COLUMN_CLASS = factory.createIRI(NAMESPACE, "Column"); + LIBRARY_ONTOLOGY_CLASS = factory.createIRI(NAMESPACE, "LibraryOntology"); + MAGIC_PROPERTY_CLASS = factory.createIRI(NAMESPACE, "MagicProperty"); + UPDATE_PROPERTY = factory.createIRI(NAMESPACE, "update"); + COMMAND_PROPERTY = factory.createIRI(NAMESPACE, "command"); + RETURN_TYPE_PROPERTY = factory.createIRI(NAMESPACE, "returnType"); + SYSTEM_PROPERTY_PROPERTY = factory.createIRI(NAMESPACE, "systemProperty"); + COLUMN_PROPERTY = factory.createIRI(NAMESPACE, "column"); + SYMBOL_PROPERTY = factory.createIRI(NAMESPACE, "symbol"); + VIOLATION_ROOT_PROPERTY = factory.createIRI(NAMESPACE, "violationRoot"); + COLUMN_TYPE_PROPERTY = factory.createIRI(NAMESPACE, "columnType"); + NEXT_RULE_PROPERTY_PROPERTY = factory.createIRI(NAMESPACE, "nextRuleProperty"); + PRIVATE_PROPERTY = factory.createIRI(NAMESPACE, "private"); + LABEL_TEMPLATE_PROPERTY = factory.createIRI(NAMESPACE, "labelTemplate"); + VIOLATION_PATH_PROPERTY = factory.createIRI(NAMESPACE, "violationPath"); + CONSTRUCTOR_PROPERTY = factory.createIRI(NAMESPACE, "constructor"); + ABSTRACT_PROPERTY = factory.createIRI(NAMESPACE, "abstract"); + CONSTRAINT_PROPERTY = factory.createIRI(NAMESPACE, "constraint"); + QUERY_PROPERTY = factory.createIRI(NAMESPACE, "query"); + FIX_PROPERTY = factory.createIRI(NAMESPACE, "fix"); + COLUMN_WIDTH_PROPERTY = factory.createIRI(NAMESPACE, "columnWidth"); + VIOLATION_SOURCE_PROPERTY = factory.createIRI(NAMESPACE, "violationSource"); + COLUMN_INDEX_PROPERTY = factory.createIRI(NAMESPACE, "columnIndex"); + THIS_UNBOUND_PROPERTY = factory.createIRI(NAMESPACE, "thisUnbound"); + RULE_PROPERTY_MAX_ITERATION_COUNT_PROPERTY = factory.createIRI(NAMESPACE, + "rulePropertyMaxIterationCount"); + IMPORTS_PROPERTY = factory.createIRI(NAMESPACE, "imports"); + CONSTRUCT_TEMPLATES_CLASS = factory.createIRI(NAMESPACE, "ConstructTemplates"); + TEMPLATES_CLASS = factory.createIRI(NAMESPACE, "Templates"); + EVAL_CLASS = factory.createIRI(NAMESPACE, "eval"); + FUNCTIONS_CLASS = factory.createIRI(NAMESPACE, "Functions"); + ASK_TEMPLATES_CLASS = factory.createIRI(NAMESPACE, "AskTemplates"); + SELECT_TEMPLATES_CLASS = factory.createIRI(NAMESPACE, "SelectTemplates"); + MAGIC_PROPERTIES_CLASS = factory.createIRI(NAMESPACE, "MagicProperties"); + THIS_CONTEXT_INSTANCE = factory.createIRI(NAMESPACE, "_this"); + UPDATE_TEMPLATES_CLASS = factory.createIRI(NAMESPACE, "UpdateTemplates"); + RULE_PROPERTY = factory.createIRI(NAMESPACE, "rule"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/XMLSchema.java b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/XMLSchema.java new file mode 100644 index 00000000000..083b45ba0e6 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/XMLSchema.java @@ -0,0 +1,279 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.vocabulary; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * Constants for the standard XML + * Schema datatypes. + * + * @see XML Schema Part 2: Datatypes + * Second Edition + */ +public class XMLSchema { + + /* + * The XML Schema namespace + */ + + /** The XML Schema namespace (http://www.w3.org/2001/XMLSchema#). */ + public static final String NAMESPACE = "http://www.w3.org/2001/XMLSchema#"; + + /** + * Recommended prefix for XML Schema datatypes: "xsd" + */ + public static final String PREFIX = "xsd"; + + /** + * An immutable {@link Namespace} constant that represents the XML Schema + * namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + /* + * Primitive datatypes + */ + + /** http://www.w3.org/2001/XMLSchema#duration */ + public final static IRI DURATION; + + /** http://www.w3.org/2001/XMLSchema#dateTime */ + public final static IRI DATETIME; + + /** http://www.w3.org/2001/XMLSchema#dayTimeDuration */ + public static final IRI DAYTIMEDURATION; + + /** http://www.w3.org/2001/XMLSchema#time */ + public final static IRI TIME; + + /** http://www.w3.org/2001/XMLSchema#date */ + public final static IRI DATE; + + /** http://www.w3.org/2001/XMLSchema#gYearMonth */ + public final static IRI GYEARMONTH; + + /** http://www.w3.org/2001/XMLSchema#gYear */ + public final static IRI GYEAR; + + /** http://www.w3.org/2001/XMLSchema#gMonthDay */ + public final static IRI GMONTHDAY; + + /** http://www.w3.org/2001/XMLSchema#gDay */ + public final static IRI GDAY; + + /** http://www.w3.org/2001/XMLSchema#gMonth */ + public final static IRI GMONTH; + + /** http://www.w3.org/2001/XMLSchema#string */ + public final static IRI STRING; + + /** http://www.w3.org/2001/XMLSchema#boolean */ + public final static IRI BOOLEAN; + + /** http://www.w3.org/2001/XMLSchema#base64Binary */ + public final static IRI BASE64BINARY; + + /** http://www.w3.org/2001/XMLSchema#hexBinary */ + public final static IRI HEXBINARY; + + /** http://www.w3.org/2001/XMLSchema#float */ + public final static IRI FLOAT; + + /** http://www.w3.org/2001/XMLSchema#decimal */ + public final static IRI DECIMAL; + + /** http://www.w3.org/2001/XMLSchema#double */ + public final static IRI DOUBLE; + + /** http://www.w3.org/2001/XMLSchema#anyURI */ + public final static IRI ANYURI; + + /** http://www.w3.org/2001/XMLSchema#QName */ + public final static IRI QNAME; + + /** http://www.w3.org/2001/XMLSchema#NOTATION */ + public final static IRI NOTATION; + + /* + * Derived datatypes + */ + + /** http://www.w3.org/2001/XMLSchema#normalizedString */ + public final static IRI NORMALIZEDSTRING; + + /** http://www.w3.org/2001/XMLSchema#token */ + public final static IRI TOKEN; + + /** http://www.w3.org/2001/XMLSchema#language */ + public final static IRI LANGUAGE; + + /** http://www.w3.org/2001/XMLSchema#NMTOKEN */ + public final static IRI NMTOKEN; + + /** http://www.w3.org/2001/XMLSchema#NMTOKENS */ + public final static IRI NMTOKENS; + + /** http://www.w3.org/2001/XMLSchema#Name */ + public final static IRI NAME; + + /** http://www.w3.org/2001/XMLSchema#NCName */ + public final static IRI NCNAME; + + /** http://www.w3.org/2001/XMLSchema#ID */ + public final static IRI ID; + + /** http://www.w3.org/2001/XMLSchema#IDREF */ + public final static IRI IDREF; + + /** http://www.w3.org/2001/XMLSchema#IDREFS */ + public final static IRI IDREFS; + + /** http://www.w3.org/2001/XMLSchema#ENTITY */ + public final static IRI ENTITY; + + /** http://www.w3.org/2001/XMLSchema#ENTITIES */ + public final static IRI ENTITIES; + + /** http://www.w3.org/2001/XMLSchema#integer */ + public final static IRI INTEGER; + + /** http://www.w3.org/2001/XMLSchema#long */ + public final static IRI LONG; + + /** http://www.w3.org/2001/XMLSchema#int */ + public final static IRI INT; + + /** http://www.w3.org/2001/XMLSchema#short */ + public final static IRI SHORT; + + /** http://www.w3.org/2001/XMLSchema#byte */ + public final static IRI BYTE; + + /** http://www.w3.org/2001/XMLSchema#nonPositiveInteger */ + public final static IRI NON_POSITIVE_INTEGER; + + /** http://www.w3.org/2001/XMLSchema#negativeInteger */ + public final static IRI NEGATIVE_INTEGER; + + /** http://www.w3.org/2001/XMLSchema#nonNegativeInteger */ + public final static IRI NON_NEGATIVE_INTEGER; + + /** http://www.w3.org/2001/XMLSchema#positiveInteger */ + public final static IRI POSITIVE_INTEGER; + + /** http://www.w3.org/2001/XMLSchema#unsignedLong */ + public final static IRI UNSIGNED_LONG; + + /** http://www.w3.org/2001/XMLSchema#unsignedInt */ + public final static IRI UNSIGNED_INT; + + /** http://www.w3.org/2001/XMLSchema#unsignedShort */ + public final static IRI UNSIGNED_SHORT; + + /** http://www.w3.org/2001/XMLSchema#unsignedByte */ + public final static IRI UNSIGNED_BYTE; + + static { + ValueFactory factory = SimpleValueFactory.getInstance(); + + DURATION = factory.createIRI(XMLSchema.NAMESPACE, "duration"); + + DATETIME = factory.createIRI(XMLSchema.NAMESPACE, "dateTime"); + + DAYTIMEDURATION = factory.createIRI(NAMESPACE, "dayTimeDuration"); + + TIME = factory.createIRI(XMLSchema.NAMESPACE, "time"); + + DATE = factory.createIRI(XMLSchema.NAMESPACE, "date"); + + GYEARMONTH = factory.createIRI(XMLSchema.NAMESPACE, "gYearMonth"); + + GYEAR = factory.createIRI(XMLSchema.NAMESPACE, "gYear"); + + GMONTHDAY = factory.createIRI(XMLSchema.NAMESPACE, "gMonthDay"); + + GDAY = factory.createIRI(XMLSchema.NAMESPACE, "gDay"); + + GMONTH = factory.createIRI(XMLSchema.NAMESPACE, "gMonth"); + + STRING = factory.createIRI(XMLSchema.NAMESPACE, "string"); + + BOOLEAN = factory.createIRI(XMLSchema.NAMESPACE, "boolean"); + + BASE64BINARY = factory.createIRI(XMLSchema.NAMESPACE, "base64Binary"); + + HEXBINARY = factory.createIRI(XMLSchema.NAMESPACE, "hexBinary"); + + FLOAT = factory.createIRI(XMLSchema.NAMESPACE, "float"); + + DECIMAL = factory.createIRI(XMLSchema.NAMESPACE, "decimal"); + + DOUBLE = factory.createIRI(XMLSchema.NAMESPACE, "double"); + + ANYURI = factory.createIRI(XMLSchema.NAMESPACE, "anyURI"); + + QNAME = factory.createIRI(XMLSchema.NAMESPACE, "QName"); + + NOTATION = factory.createIRI(XMLSchema.NAMESPACE, "NOTATION"); + + NORMALIZEDSTRING = factory.createIRI(XMLSchema.NAMESPACE, "normalizedString"); + + TOKEN = factory.createIRI(XMLSchema.NAMESPACE, "token"); + + LANGUAGE = factory.createIRI(XMLSchema.NAMESPACE, "language"); + + NMTOKEN = factory.createIRI(XMLSchema.NAMESPACE, "NMTOKEN"); + + NMTOKENS = factory.createIRI(XMLSchema.NAMESPACE, "NMTOKENS"); + + NAME = factory.createIRI(XMLSchema.NAMESPACE, "Name"); + + NCNAME = factory.createIRI(XMLSchema.NAMESPACE, "NCName"); + + ID = factory.createIRI(XMLSchema.NAMESPACE, "ID"); + + IDREF = factory.createIRI(XMLSchema.NAMESPACE, "IDREF"); + + IDREFS = factory.createIRI(XMLSchema.NAMESPACE, "IDREFS"); + + ENTITY = factory.createIRI(XMLSchema.NAMESPACE, "ENTITY"); + + ENTITIES = factory.createIRI(XMLSchema.NAMESPACE, "ENTITIES"); + + INTEGER = factory.createIRI(XMLSchema.NAMESPACE, "integer"); + + LONG = factory.createIRI(XMLSchema.NAMESPACE, "long"); + + INT = factory.createIRI(XMLSchema.NAMESPACE, "int"); + + SHORT = factory.createIRI(XMLSchema.NAMESPACE, "short"); + + BYTE = factory.createIRI(XMLSchema.NAMESPACE, "byte"); + + NON_POSITIVE_INTEGER = factory.createIRI(XMLSchema.NAMESPACE, "nonPositiveInteger"); + + NEGATIVE_INTEGER = factory.createIRI(XMLSchema.NAMESPACE, "negativeInteger"); + + NON_NEGATIVE_INTEGER = factory.createIRI(XMLSchema.NAMESPACE, "nonNegativeInteger"); + + POSITIVE_INTEGER = factory.createIRI(XMLSchema.NAMESPACE, "positiveInteger"); + + UNSIGNED_LONG = factory.createIRI(XMLSchema.NAMESPACE, "unsignedLong"); + + UNSIGNED_INT = factory.createIRI(XMLSchema.NAMESPACE, "unsignedInt"); + + UNSIGNED_SHORT = factory.createIRI(XMLSchema.NAMESPACE, "unsignedShort"); + + UNSIGNED_BYTE = factory.createIRI(XMLSchema.NAMESPACE, "unsignedByte"); + } +} diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/package.html b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/package.html new file mode 100644 index 00000000000..c5a0e9b0436 --- /dev/null +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/vocabulary/package.html @@ -0,0 +1,6 @@ + + + +Static constants for various vocabularies. + + diff --git a/core/model/src/test/java/org/eclipse/rdf4j/IsolationLevelsTest.java b/core/model/src/test/java/org/eclipse/rdf4j/IsolationLevelsTest.java new file mode 100644 index 00000000000..6c5a8f01427 --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/IsolationLevelsTest.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.IsolationLevels; +import org.junit.Test; + +/** + * @author jeen + */ +public class IsolationLevelsTest { + + /** + * Test method for + * {@link org.eclipse.rdf4j.IsolationLevels#isCompatibleWith(org.eclipse.rdf4j.IsolationLevel)} + * . + */ + @Test + public void testIsCompatibleWith() { + assertTrue(IsolationLevels.SNAPSHOT.isCompatibleWith(IsolationLevels.READ_COMMITTED)); + assertTrue(IsolationLevels.SERIALIZABLE.isCompatibleWith(IsolationLevels.READ_COMMITTED)); + assertTrue(IsolationLevels.SNAPSHOT.isCompatibleWith(IsolationLevels.READ_UNCOMMITTED)); + assertFalse(IsolationLevels.READ_COMMITTED.isCompatibleWith(IsolationLevels.SNAPSHOT)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.IsolationLevels#getCompatibleIsolationLevel(org.eclipse.rdf4j.IsolationLevel, java.util.List)} + * . + */ + @Test + public void testGetCompatibleIsolationLevel() { + + List supportedLevels = new ArrayList(); + supportedLevels.add(IsolationLevels.NONE); + supportedLevels.add(IsolationLevels.SERIALIZABLE); + + IsolationLevel compatibleLevel = IsolationLevels.getCompatibleIsolationLevel( + IsolationLevels.READ_COMMITTED, supportedLevels); + assertNotNull(compatibleLevel); + assertEquals(IsolationLevels.SERIALIZABLE, compatibleLevel); + } + + @Test + public void testGetCompatibleIsolationLevelNoneFound() { + + List supportedLevels = new ArrayList(); + supportedLevels.add(IsolationLevels.NONE); + supportedLevels.add(IsolationLevels.READ_UNCOMMITTED); + supportedLevels.add(IsolationLevels.READ_COMMITTED); + + IsolationLevel compatibleLevel = IsolationLevels.getCompatibleIsolationLevel( + IsolationLevels.SERIALIZABLE, supportedLevels); + assertNull(compatibleLevel); + + } + + @Test + public void testGetCompatibleIsolationLevelNullParams() { + try { + IsolationLevel compatibleLevel = IsolationLevels.getCompatibleIsolationLevel( + IsolationLevels.SNAPSHOT, null); + fail("should have resulted in an IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // do nothing, expected. + } + + List supportedLevels = new ArrayList(); + supportedLevels.add(IsolationLevels.NONE); + supportedLevels.add(IsolationLevels.SNAPSHOT); + supportedLevels.add(IsolationLevels.SERIALIZABLE); + + try { + IsolationLevel compatibleLevel = IsolationLevels.getCompatibleIsolationLevel(null, supportedLevels); + fail("should have resulted in an IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // do nothing, expected. + } + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/AbstractModelPerformanceTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/AbstractModelPerformanceTest.java new file mode 100644 index 00000000000..7d414f3e836 --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/AbstractModelPerformanceTest.java @@ -0,0 +1,474 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Optional; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.util.ModelException; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +/** + * @author Peter Ansell + */ +public abstract class AbstractModelPerformanceTest extends AbstractModelTest { + + private static final int COUNT = 150; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + super.setUp(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + super.tearDown(); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#add(org.eclipse.rdf4j.model.Resource, org.eclipse.rdf4j.model.IRI, org.eclipse.rdf4j.model.Value, org.eclipse.rdf4j.model.Resource[])} + * . + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfAddResourceURIValueResourceArray() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#getNamespaces()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfGetNamespaces() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#getNamespace(java.lang.String)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfGetNamespace() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#setNamespace(java.lang.String, java.lang.String)} + * . + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfSetNamespaceStringString() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#setNamespace(org.eclipse.rdf4j.model.Namespace)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfSetNamespaceNamespace() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#removeNamespace(java.lang.String)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfRemoveNamespace() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#contains(org.eclipse.rdf4j.model.Resource, org.eclipse.rdf4j.model.IRI, org.eclipse.rdf4j.model.Value, org.eclipse.rdf4j.model.Resource[])} + * . + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfContainsResourceURIValueResourceArray() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#clear(org.eclipse.rdf4j.model.Resource[])}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfClearResourceArray() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#remove(org.eclipse.rdf4j.model.Resource, org.eclipse.rdf4j.model.IRI, org.eclipse.rdf4j.model.Value, org.eclipse.rdf4j.model.Resource[])} + * . + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfRemoveResourceURIValueResourceArray() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#filter(org.eclipse.rdf4j.model.Resource, org.eclipse.rdf4j.model.IRI, org.eclipse.rdf4j.model.Value, org.eclipse.rdf4j.model.Resource[])} + * . + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfFilter() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#subjects()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfSubjects() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#predicates()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfPredicates() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objects()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfObjects() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#contexts()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfContexts() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfObjectValue() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfObjectLiteral() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfObjectResource() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testPerfObjectURISingle() { + Model model = getNewEmptyModel(); + for (int i = 0; i < COUNT; i++) { + // Add many statements with the same object URI + model.add(vf.createStatement(vf.createIRI("urn:test:uri:subject:" + i % 10000), + vf.createIRI("urn:test:uri:predicate:" + (i % 200)), + vf.createIRI("urn:test:object:uri:single"))); + } + + long start = System.nanoTime(); + Optional objectURI = model.objectIRI(); + System.out.println("testPerfObjectURISingle: " + (System.nanoTime() - start)); + assertTrue(objectURI.isPresent()); + assertEquals("urn:test:object:uri:single", objectURI.get().toString()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testPerfObjectURIMultipleAddedFirst() { + Model model = getNewEmptyModel(); + model.add(vf.createStatement(vf.createIRI("urn:test:uri:subject:1"), + vf.createIRI("urn:test:uri:predicate:1"), vf.createIRI("urn:test:object:uri:other"))); + for (int i = 0; i < COUNT; i++) { + // Add many statements with the same object URI + model.add(vf.createStatement(vf.createIRI("urn:test:uri:subject:" + i % 10000), + vf.createIRI("urn:test:uri:predicate:" + (i % 200)), + vf.createIRI("urn:test:object:uri:single"))); + } + + thrown.expect(ModelException.class); + long start = System.nanoTime(); + try { + model.objectIRI(); + } + finally { + System.out.println("testPerfObjectURIMultipleAddedFirst: " + (System.nanoTime() - start)); + } + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testPerfObjectURIMultipleAddedLast() { + Model model = getNewEmptyModel(); + for (int i = 0; i < COUNT; i++) { + // Add many statements with the same object URI + model.add(vf.createStatement(vf.createIRI("urn:test:uri:subject:" + i % 10000), + vf.createIRI("urn:test:uri:predicate:" + (i % 200)), + vf.createIRI("urn:test:object:uri:single"))); + } + model.add(vf.createStatement(vf.createIRI("urn:test:uri:subject:1"), + vf.createIRI("urn:test:uri:predicate:1"), vf.createIRI("urn:test:object:uri:other"))); + + thrown.expect(ModelException.class); + long start = System.nanoTime(); + try { + model.objectIRI(); + } + finally { + System.out.println("testPerfObjectURIMultipleAddedLast: " + (System.nanoTime() - start)); + } + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfObjectString() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#anObjectLiteral()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfAnObjectLiteral() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#anObjectResource()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfAnObjectResource() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#anObjectURI()}. + */ + @Test + public final void testPerfAnObjectURIMultipleAddedFirst() { + Model model = getNewEmptyModel(); + model.add(vf.createStatement(vf.createIRI("urn:test:uri:subject:1"), + vf.createIRI("urn:test:uri:predicate:1"), vf.createIRI("urn:test:object:uri:other"))); + for (int i = 0; i < COUNT; i++) { + // Add many statements with the same object URI + model.add(vf.createStatement(vf.createIRI("urn:test:uri:subject:" + i % 10000), + vf.createIRI("urn:test:uri:predicate:" + (i % 200)), + vf.createIRI("urn:test:object:uri:single"))); + } + + thrown.expect(ModelException.class); + long start = System.nanoTime(); + try { + model.objectURI(); + } + finally { + System.out.println("testPerfAnObjectURIMultipleAddedFirst: " + (System.nanoTime() - start)); + } + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#anObjectURI()}. + */ + @Test + public final void testPerfAnObjectURIMultipleAddedLast() { + Model model = getNewEmptyModel(); + for (int i = 0; i < COUNT; i++) { + // Add many statements with the same object URI + model.add(vf.createStatement(vf.createIRI("urn:test:uri:subject:" + i % 10000), + vf.createIRI("urn:test:uri:predicate:" + (i % 200)), + vf.createIRI("urn:test:object:uri:single"))); + } + model.add(vf.createStatement(vf.createIRI("urn:test:uri:subject:1"), + vf.createIRI("urn:test:uri:predicate:1"), vf.createIRI("urn:test:object:uri:other"))); + + thrown.expect(ModelException.class); + long start = System.nanoTime(); + try { + model.objectURI(); + } + finally { + System.out.println("testPerfAnObjectURIMultipleAddedLast: " + (System.nanoTime() - start)); + } + } + + /** + * Test method for {@link java.util.Set#iterator()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfIterator() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#size()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfSize() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#isEmpty()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfIsEmpty() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#contains(java.lang.Object)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfContainsObject() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#add(java.lang.Object)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfAddE() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#remove(java.lang.Object)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfRemoveObject() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#containsAll(java.util.Collection)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfContainsAll() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#addAll(java.util.Collection)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfAddAll() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#removeAll(java.util.Collection)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfRemoveAll() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#retainAll(java.util.Collection)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfRetainAll() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.util.Set#clear()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfClear() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link java.util.Collection#removeIf(java.util.function.Predicate)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testPerfRemoveIf() { + fail("Not yet implemented"); // TODO + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/AbstractModelTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/AbstractModelTest.java new file mode 100644 index 00000000000..801bf47e0fc --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/AbstractModelTest.java @@ -0,0 +1,1484 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Optional; +import java.util.Set; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.util.ModelException; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.Timeout; + +/** + * Abstract test suite for the helper methods defined by the Model interface. + * + * @author Peter Ansell + */ +public abstract class AbstractModelTest { + + @Rule + public Timeout timeout = new Timeout(10000); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + protected Literal literal1; + + protected Literal literal2; + + protected Literal literal3; + + protected IRI uri1; + + protected IRI uri2; + + protected IRI uri3; + + protected BNode bnode1; + + protected BNode bnode2; + + protected BNode bnode3; + + protected final ValueFactory vf = SimpleValueFactory.getInstance(); + + protected abstract Model getNewModel(); + + /** + * Helper method that asserts that the returned model is empty before + * returning. + * + * @return An empty instance of the {@link Model} implementation being + * tested. + */ + protected Model getNewEmptyModel() { + Model model = getNewModel(); + assertTrue(model.isEmpty()); + return model; + } + + protected Model getNewModelObjectSingleLiteral() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, literal1); + assertEquals(1, model.size()); + return model; + } + + protected Model getNewModelObjectSingleURI() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, uri2); + assertEquals(1, model.size()); + return model; + } + + protected Model getNewModelObjectSingleBNode() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, bnode1); + assertEquals(1, model.size()); + return model; + } + + protected Model getNewModelObjectDoubleLiteral() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, literal1); + model.add(uri1, RDFS.LABEL, literal2); + assertEquals(2, model.size()); + return model; + } + + protected Model getNewModelObjectDoubleURI() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, uri2); + model.add(uri1, RDFS.LABEL, uri3); + assertEquals(2, model.size()); + return model; + } + + protected Model getNewModelObjectDoubleBNode() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, bnode1); + model.add(uri1, RDFS.LABEL, bnode2); + assertEquals(2, model.size()); + return model; + } + + protected Model getNewModelObjectSingleLiteralSingleURI() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, literal1); + model.add(uri1, RDFS.LABEL, uri2); + assertEquals(2, model.size()); + return model; + } + + protected Model getNewModelObjectSingleLiteralSingleBNode() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, literal1); + model.add(uri1, RDFS.LABEL, bnode1); + assertEquals(2, model.size()); + return model; + } + + protected Model getNewModelObjectSingleURISingleBNode() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, uri1); + model.add(uri1, RDFS.LABEL, bnode1); + assertEquals(2, model.size()); + return model; + } + + protected Model getNewModelObjectTripleLiteral() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, literal1); + model.add(uri1, RDFS.LABEL, literal2); + model.add(uri1, RDFS.LABEL, literal3); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelObjectTripleURI() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, uri1); + model.add(uri1, RDFS.LABEL, uri2); + model.add(uri1, RDFS.LABEL, uri3); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelObjectTripleBNode() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, bnode1); + model.add(uri1, RDFS.LABEL, bnode2); + model.add(uri1, RDFS.LABEL, bnode3); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelObjectSingleLiteralSingleURISingleBNode() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, literal1); + model.add(uri1, RDFS.LABEL, uri2); + model.add(uri1, RDFS.LABEL, bnode1); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelObjectSingleLiteralDoubleURI() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, literal1); + model.add(uri1, RDFS.LABEL, uri2); + model.add(uri1, RDFS.LABEL, uri3); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelObjectSingleLiteralDoubleBNode() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, literal1); + model.add(uri1, RDFS.LABEL, bnode1); + model.add(uri1, RDFS.LABEL, bnode2); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelObjectSingleURIDoubleBNode() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, uri1); + model.add(uri1, RDFS.LABEL, bnode1); + model.add(uri1, RDFS.LABEL, bnode2); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelObjectSingleURIDoubleLiteral() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, uri1); + model.add(uri1, RDFS.LABEL, literal1); + model.add(uri1, RDFS.LABEL, literal2); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelObjectSingleBNodeDoubleURI() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, bnode1); + model.add(uri1, RDFS.LABEL, uri2); + model.add(uri1, RDFS.LABEL, uri3); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelObjectSingleBNodeDoubleLiteral() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, bnode1); + model.add(uri1, RDFS.LABEL, literal1); + model.add(uri1, RDFS.LABEL, literal2); + assertEquals(3, model.size()); + return model; + } + + protected Model getNewModelTwoContexts() { + Model model = getNewEmptyModel(); + model.add(uri1, RDFS.LABEL, bnode1, uri1); + model.add(uri1, RDFS.LABEL, literal1, uri1); + model.add(uri1, RDFS.LABEL, literal2, uri2); + assertEquals(3, model.size()); + return model; + } + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + uri1 = vf.createIRI("urn:test:uri:1"); + uri2 = vf.createIRI("urn:test:uri:2"); + uri3 = vf.createIRI("urn:test:uri:3"); + bnode1 = vf.createBNode(); + bnode2 = vf.createBNode("bnode2"); + bnode3 = vf.createBNode("bnode3"); + literal1 = vf.createLiteral("test literal 1"); + literal2 = vf.createLiteral("test literal 2"); + literal3 = vf.createLiteral("test literal 3"); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#filter(Resource, IRI, Value, Resource...)}. + */ + @Test + public final void testFilterSingleLiteral() { + Model model = getNewModelObjectSingleLiteral(); + Model filter1 = model.filter(null, null, literal1); + assertFalse(filter1.isEmpty()); + Model filter2 = model.filter(null, null, literal1, (Resource)null); + assertFalse(filter2.isEmpty()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.Model#contains(Resource, IRI, Value, Resource...)} + * . + */ + @Test + public final void testContainsSingleLiteral() { + Model model = getNewModelObjectSingleLiteral(); + assertTrue(model.contains(null, null, literal1)); + assertTrue(model.contains(null, null, literal1, (Resource)null)); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#subjects()}. + */ + @Test + public final void testSubjects() { + Model m = getNewModelObjectDoubleLiteral(); + + final int modelSizeBefore = m.size(); + + Set subjects = m.subjects(); + assertNotNull(subjects); + + final int setSizeBefore = subjects.size(); + + Value predicate = subjects.iterator().next(); + subjects.remove(predicate); + + assertEquals(setSizeBefore - 1, subjects.size()); + assertTrue(m.size() < modelSizeBefore); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#predicates()}. + */ + @Test + public final void testPredicates() { + Model m = getNewModelObjectDoubleLiteral(); + + final int modelSizeBefore = m.size(); + + Set predicates = m.predicates(); + assertNotNull(predicates); + + final int setSizeBefore = predicates.size(); + + Value predicate = predicates.iterator().next(); + predicates.remove(predicate); + + assertEquals(setSizeBefore - 1, predicates.size()); + assertTrue(m.size() < modelSizeBefore); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objects()}. + */ + @Test + public final void testObjects() { + Model m = getNewModelObjectDoubleLiteral(); + + final int modelSizeBefore = m.size(); + + Set objects = m.objects(); + assertNotNull(objects); + + final int setSizeBefore = objects.size(); + + Value object = objects.iterator().next(); + objects.remove(object); + + assertEquals(setSizeBefore - 1, objects.size()); + assertTrue(m.size() < modelSizeBefore); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#contexts()}. + */ + @Test + public final void testContexts() { + Model m = getNewModelTwoContexts(); + + final int modelSizeBefore = m.size(); + + Set contexts = m.contexts(); + assertNotNull(contexts); + + final int setSizeBefore = contexts.size(); + + Value predicate = contexts.iterator().next(); + contexts.remove(predicate); + + assertEquals(setSizeBefore - 1, contexts.size()); + assertTrue(m.size() < modelSizeBefore); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueEmpty() { + Model model = getNewEmptyModel(); + Optional value = model.objectValue(); + assertFalse(value.isPresent()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleLiteral() { + Model model = getNewModelObjectSingleLiteral(); + Optional value = model.objectValue(); + assertTrue(value.isPresent()); + assertEquals(literal1, value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleURI() { + Model model = getNewModelObjectSingleURI(); + Optional value = model.objectValue(); + assertTrue(value.isPresent()); + assertEquals(uri2, value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleBNode() { + Model model = getNewModelObjectSingleBNode(); + Optional value = model.objectValue(); + assertTrue(value.isPresent()); + assertEquals(bnode1, value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueDoubleLiteral() { + Model model = getNewModelObjectDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleLiteralSingleURI() { + Model model = getNewModelObjectSingleLiteralSingleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleLiteralSingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleURISingleBNode() { + Model model = getNewModelObjectSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueDoubleURI() { + Model model = getNewModelObjectDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueDoubleBNode() { + Model model = getNewModelObjectDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueTripleLiteral() { + Model model = getNewModelObjectTripleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueTripleURI() { + Model model = getNewModelObjectTripleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueTripleBNode() { + Model model = getNewModelObjectTripleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleLiteralSingleURISingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleLiteralDoubleBNode() { + Model model = getNewModelObjectSingleLiteralDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleLiteralDoubleURI() { + Model model = getNewModelObjectSingleLiteralDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleURIDoubleBNode() { + Model model = getNewModelObjectSingleURIDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleURIDoubleLiteral() { + Model model = getNewModelObjectSingleURIDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleBNodeDoubleURI() { + Model model = getNewModelObjectSingleBNodeDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectValue()}. + */ + @Test + public final void testObjectValueSingleBNodeDoubleLiteral() { + Model model = getNewModelObjectSingleBNodeDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectValue(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralEmpty() { + Model model = getNewEmptyModel(); + Optional value = model.objectLiteral(); + assertFalse(value.isPresent()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleLiteral() { + Model model = getNewModelObjectSingleLiteral(); + Optional value = model.objectLiteral(); + assertTrue(value.isPresent()); + assertEquals(literal1, value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleURI() { + Model model = getNewModelObjectSingleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleBNode() { + Model model = getNewModelObjectSingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralDoubleLiteral() { + Model model = getNewModelObjectDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleLiteralSingleURI() { + Model model = getNewModelObjectSingleLiteralSingleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleLiteralSingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleURISingleBNode() { + Model model = getNewModelObjectSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralDoubleURI() { + Model model = getNewModelObjectDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralDoubleBNode() { + Model model = getNewModelObjectDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralTripleLiteral() { + Model model = getNewModelObjectTripleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralTripleURI() { + Model model = getNewModelObjectTripleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralTripleBNode() { + Model model = getNewModelObjectTripleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleLiteralSingleURISingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleLiteralDoubleBNode() { + Model model = getNewModelObjectSingleLiteralDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleLiteralDoubleURI() { + Model model = getNewModelObjectSingleLiteralDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleURIDoubleBNode() { + Model model = getNewModelObjectSingleURIDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleURIDoubleLiteral() { + Model model = getNewModelObjectSingleURIDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleBNodeDoubleURI() { + Model model = getNewModelObjectSingleBNodeDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectLiteral()}. + */ + @Test + public final void testObjectLiteralSingleBNodeDoubleLiteral() { + Model model = getNewModelObjectSingleBNodeDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectLiteral(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceEmpty() { + Model model = getNewEmptyModel(); + Optional value = model.objectResource(); + assertFalse(value.isPresent()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleLiteral() { + Model model = getNewModelObjectSingleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleURI() { + Model model = getNewModelObjectSingleURI(); + Optional value = model.objectResource(); + assertTrue(value.isPresent()); + assertEquals(uri2, value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleBNode() { + Model model = getNewModelObjectSingleBNode(); + Optional value = model.objectResource(); + assertTrue(value.isPresent()); + assertEquals(bnode1, value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceDoubleLiteral() { + Model model = getNewModelObjectDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleLiteralSingleURI() { + Model model = getNewModelObjectSingleLiteralSingleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleLiteralSingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleURISingleBNode() { + Model model = getNewModelObjectSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceDoubleURI() { + Model model = getNewModelObjectDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceDoubleBNode() { + Model model = getNewModelObjectDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceTripleLiteral() { + Model model = getNewModelObjectTripleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceTripleURI() { + Model model = getNewModelObjectTripleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceTripleBNode() { + Model model = getNewModelObjectTripleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleLiteralSingleURISingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleLiteralDoubleBNode() { + Model model = getNewModelObjectSingleLiteralDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleLiteralDoubleURI() { + Model model = getNewModelObjectSingleLiteralDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleURIDoubleBNode() { + Model model = getNewModelObjectSingleURIDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleURIDoubleLiteral() { + Model model = getNewModelObjectSingleURIDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleBNodeDoubleURI() { + Model model = getNewModelObjectSingleBNodeDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectResource()}. + */ + @Test + public final void testObjectResourceSingleBNodeDoubleLiteral() { + Model model = getNewModelObjectSingleBNodeDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectResource(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURIEmpty() { + Model model = getNewEmptyModel(); + Optional value = model.objectIRI(); + assertFalse(value.isPresent()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleLiteral() { + Model model = getNewModelObjectSingleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleURI() { + Model model = getNewModelObjectSingleURI(); + Optional value = model.objectIRI(); + assertTrue(value.isPresent()); + assertEquals(uri2, value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleBNode() { + Model model = getNewModelObjectSingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURIDoubleLiteral() { + Model model = getNewModelObjectDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleLiteralSingleURI() { + Model model = getNewModelObjectSingleLiteralSingleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleLiteralSingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleURISingleBNode() { + Model model = getNewModelObjectSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURIDoubleURI() { + Model model = getNewModelObjectDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURIDoubleBNode() { + Model model = getNewModelObjectDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURITripleLiteral() { + Model model = getNewModelObjectTripleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURITripleURI() { + Model model = getNewModelObjectTripleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURITripleBNode() { + Model model = getNewModelObjectTripleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleLiteralSingleURISingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleLiteralDoubleBNode() { + Model model = getNewModelObjectSingleLiteralDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleLiteralDoubleURI() { + Model model = getNewModelObjectSingleLiteralDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleURIDoubleBNode() { + Model model = getNewModelObjectSingleURIDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleURIDoubleLiteral() { + Model model = getNewModelObjectSingleURIDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleBNodeDoubleURI() { + Model model = getNewModelObjectSingleBNodeDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectIRI()}. + */ + @Test + public final void testObjectURISingleBNodeDoubleLiteral() { + Model model = getNewModelObjectSingleBNodeDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectIRI(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringEmpty() { + Model model = getNewEmptyModel(); + Optional value = model.objectString(); + assertFalse(value.isPresent()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleLiteral() { + Model model = getNewModelObjectSingleLiteral(); + Optional value = model.objectString(); + assertTrue(value.isPresent()); + assertEquals(literal1.stringValue(), value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleURI() { + Model model = getNewModelObjectSingleURI(); + Optional value = model.objectString(); + assertTrue(value.isPresent()); + assertEquals(uri2.toString(), value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleBNode() { + Model model = getNewModelObjectSingleBNode(); + Optional value = model.objectString(); + assertTrue(value.isPresent()); + assertEquals(bnode1.stringValue(), value.get()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringDoubleLiteral() { + Model model = getNewModelObjectDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleLiteralSingleURI() { + Model model = getNewModelObjectSingleLiteralSingleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleLiteralSingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleURISingleBNode() { + Model model = getNewModelObjectSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringDoubleURI() { + Model model = getNewModelObjectDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringDoubleBNode() { + Model model = getNewModelObjectDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringTripleLiteral() { + Model model = getNewModelObjectTripleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringTripleURI() { + Model model = getNewModelObjectTripleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringTripleBNode() { + Model model = getNewModelObjectTripleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleLiteralSingleURISingleBNode() { + Model model = getNewModelObjectSingleLiteralSingleURISingleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleLiteralDoubleBNode() { + Model model = getNewModelObjectSingleLiteralDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleLiteralDoubleURI() { + Model model = getNewModelObjectSingleLiteralDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleURIDoubleBNode() { + Model model = getNewModelObjectSingleURIDoubleBNode(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleURIDoubleLiteral() { + Model model = getNewModelObjectSingleURIDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleBNodeDoubleURI() { + Model model = getNewModelObjectSingleBNodeDoubleURI(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.Model#objectString()}. + */ + @Test + public final void testObjectStringSingleBNodeDoubleLiteral() { + Model model = getNewModelObjectSingleBNodeDoubleLiteral(); + // We expect an exception during the next method call + thrown.expect(ModelException.class); + model.objectString(); + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelPerformanceTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelPerformanceTest.java new file mode 100644 index 00000000000..44fb1a4aef3 --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelPerformanceTest.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; + +/** + * @author Peter Ansell + */ +public class LinkedHashModelPerformanceTest extends AbstractModelPerformanceTest { + + @Override + protected Model getNewModel() { + return new LinkedHashModel(); + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelTest.java new file mode 100644 index 00000000000..088f76d2d1b --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/LinkedHashModelTest.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; + +/** + * @author Peter Ansell + */ +public class LinkedHashModelTest extends AbstractModelTest { + + @Override + protected Model getNewModel() { + return new LinkedHashModel(); + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/TreeModelPerformanceTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/TreeModelPerformanceTest.java new file mode 100644 index 00000000000..7a5ce99ad01 --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/TreeModelPerformanceTest.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.impl.TreeModel; + +/** + * @author Peter Ansell + */ +public class TreeModelPerformanceTest extends AbstractModelPerformanceTest { + + @Override + protected Model getNewModel() { + return new TreeModel(); + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/TreeModelTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/TreeModelTest.java new file mode 100644 index 00000000000..bb8280c271f --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/TreeModelTest.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.impl.TreeModel; + +/** + * @author Peter Ansell + */ +public class TreeModelTest extends AbstractModelTest { + + @Override + protected Model getNewModel() { + return new TreeModel(); + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/ValueFactoryTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/ValueFactoryTest.java new file mode 100644 index 00000000000..89508891f7b --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/ValueFactoryTest.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model; + +import static org.junit.Assert.*; + +import java.util.Date; +import java.util.GregorianCalendar; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.junit.Before; +import org.junit.Test; + + +/** + * + * @author jeen + */ +public class ValueFactoryTest { + + private ValueFactory f; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + f = SimpleValueFactory.getInstance(); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createBNode()}. + */ + @Test + public void testCreateBNode() { + BNode b = f.createBNode(); + assertNotNull(b); + assertNotNull(b.getID()); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createLiteral(boolean)}. + */ + @Test + public void testCreateLiteralBoolean() { + Literal l = f.createLiteral(true); + assertNotNull(l); + assertEquals("true", l.getLabel()); + assertEquals(l.getDatatype(), XMLSchema.BOOLEAN); + + l = f.createLiteral(false); + assertNotNull(l); + assertEquals("false", l.getLabel()); + assertEquals(l.getDatatype(), XMLSchema.BOOLEAN); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createLiteral(byte)}. + */ + @Test + public void testCreateLiteralByte() { + byte b = new Integer(42).byteValue(); + + Literal l = f.createLiteral(b); + assertNotNull(l); + assertEquals("42", l.getLabel()); + assertEquals(l.getDatatype(), XMLSchema.BYTE); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createLiteral(short)}. + */ + @Test + public void testCreateLiteralShort() { + + short s = Short.parseShort("42"); + + Literal l = f.createLiteral(s); + assertNotNull(l); + assertEquals("42", l.getLabel()); + assertEquals(l.getDatatype(), XMLSchema.SHORT); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createLiteral(int)}. + */ + @Test + public void testCreateLiteralInt() { + Literal l = f.createLiteral(42); + assertNotNull(l); + assertEquals("42", l.getLabel()); + assertEquals(l.getDatatype(), XMLSchema.INT); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createLiteral(long)}. + */ + @Test + public void testCreateLiteralLong() { + Literal l = f.createLiteral(42L); + assertNotNull(l); + assertEquals("42", l.getLabel()); + assertEquals(l.getDatatype(), XMLSchema.LONG); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createLiteral(float)}. + */ + @Test + public void testCreateLiteralFloat() { + + Literal l = f.createLiteral(42.0f); + assertNotNull(l); + assertEquals("42.0", l.getLabel()); + assertEquals(l.getDatatype(), XMLSchema.FLOAT); + + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createLiteral(double)}. + */ + @Test + public void testCreateLiteralDouble() { + Literal l = f.createLiteral(42.0d); + assertNotNull(l); + assertEquals("42.0", l.getLabel()); + assertEquals(l.getDatatype(), XMLSchema.DOUBLE); + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createLiteral(javax.xml.datatype.XMLGregorianCalendar)}. + */ + @Test + public void testCreateLiteralXMLGregorianCalendar() { + GregorianCalendar c = new GregorianCalendar(); + c.setTime(new Date()); + try { + XMLGregorianCalendar xmlGregCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(c); + Literal l = f.createLiteral(xmlGregCalendar); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.DATETIME); + // TODO check lexical value? + } + catch (DatatypeConfigurationException e) { + e.printStackTrace(); + fail("Could not instantiate javax.xml.datatype.DatatypeFactory"); + } + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.AbstractValueFactory#createLiteral(java.util.Date)}. + */ + @Test + public void testCreateLiteralDate() { + Literal l = f.createLiteral(new Date()); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.DATETIME); + + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/datatypes/DateTimeTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/datatypes/DateTimeTest.java new file mode 100644 index 00000000000..d7a5cb862ef --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/datatypes/DateTimeTest.java @@ -0,0 +1,277 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.datatypes; + +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.datatypes.XMLDateTime; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import junit.textui.TestRunner; + +/** + * This class provides JUnit test cases for class {@link XMLDateTime}. + */ +public class DateTimeTest extends TestCase { + + private static final String[] VALID_DATES = { + "0001-01-01T00:00:00", + "0001-01-01T00:00:00.0", + "0001-01-01T00:00:00Z", + "0001-01-01T00:00:00.0Z", + "0001-01-01T00:00:00+00:00", + "0001-01-01T00:00:00.0+00:00", + "0001-01-01T00:00:00.0-00:00", + "0001-01-01T00:00:00.0+14:00", + "0001-01-01T00:00:00.0-14:00", + "0001-05-31T00:00:00.00", + "0001-07-31T00:00:00.00", + "0001-08-31T00:00:00.00", + "0001-10-31T00:00:00.00", + "0001-12-31T00:00:00.00", + "-0001-01-01T00:00:00", + "1234-12-31T23:59:59", + "1234-12-31T24:00:00", + "12345-12-31T24:00:00", + // "5000000000-12-31T24:00:00", // year > Integer.MAX_VALUE + // "-5000000000-12-31T24:00:00", // year < Integer.MIN_VALUE + "1234-12-31T24:00:00.1234567890", + "2004-02-29T00:00:00" // leap year + }; + + private static final String[] INVALID_DATES = { + "foo", + "Mon, 11 Jul 2005 09:22:29 +0200", + "0001-01-01T00:00", + "0001-01-01T00:00.00", + "0001-13-01T00:00:00.00", + "0001-01-32T00:00:00.00", + "0001-02-30T00:00:00.00", + "2005-02-29T00:00:00", // not a leap year + "0001-04-31T00:00:00.00", + "0001-01-01T25:00:00.00", + "0001-01-01T00:61:00.00", + "0001-01-01T00:00:61.00", + "0001-01-01T00:00.00+15:00", + "0001-01-01T00:00.00-15:00", + "001-01-01T00:00:00.0", + "0001-1-01T00:00:00.0", + "0001-01-1T00:00:00.0", + "0001-01-01T0:00:00.0", + "0001-01-01T00:0:00.0", + "0001-01-01T00:00:0.0", + "0001/01-01T00:00:00.0", + "0001-01/01T00:00:00.0", + "0001-01-01t00:00:00.0", + "0001-01-01T00.00:00.0", + "0001-01-01T00:00.00.0", + "0001-01-01T00:00:00:0", + "0001-01-01T00:00.00+0:00", + "0001-01-01T00:00.00+00:0", + "0001-jan-01T00:00:00", + "0001-01-01T00:00:00+00:00Z", + "0001-01-01T24:01:00", + "0001-01-01T24:00:01", + "00001-01-01T00:00:00", + "0001-001-01T00:00:00", + "0001-01-001T00:00:00", + "0001-01-01T000:00:00", + "0001-01-01T00:000:00", + "0001-01-01T00:00:000", + "0001-01-01T00:00:000", + "0001-01-01T00:00:00z", + "0001-01-01T00:00:00+05", + "0001-01-01T00:00:00+0500", + "0001-01-01T00:00:00GMT", + "0001-01-01T00:00:00PST", + "0001-01-01T00:00:00GMT+05", + "0000-01-01T00:00:00", + "0000-01-01T00:00:00", + "-0000-01-01T00:00:00", + "+0001-01-01T00:00:00" }; + + private static final String[][] NORMALIZED_DATES = { + { "0001-01-01T00:00:00", "0001-01-01T00:00:00" }, + { "0001-01-01T00:00:00.0", "0001-01-01T00:00:00" }, + { "0001-01-01T00:00:00Z", "0001-01-01T00:00:00Z" }, + { "0001-01-01T00:00:00.0Z", "0001-01-01T00:00:00Z" }, + { "0001-01-01T00:00:00+00:00", "0001-01-01T00:00:00Z" }, + { "0001-01-01T00:00:00-00:00", "0001-01-01T00:00:00Z" }, + { "0001-01-01T00:00:00.0+00:00", "0001-01-01T00:00:00Z" }, + { "0001-01-01T00:00:00.0-00:00", "0001-01-01T00:00:00Z" }, + { "0001-01-01T00:00:00-14:00", "0001-01-01T14:00:00Z" }, + { "0001-01-01T00:00:00+14:00", "-0001-12-31T10:00:00Z" }, + { "1234-12-31T24:00:00", "1235-01-01T00:00:00" } }; + + private static final String[][] EQUAL_DATES = { + { "2005-01-29T00:00:00", "2005-01-29T00:00:00" }, + { "2005-01-29T00:00:00", "2005-01-28T24:00:00" }, + { "2005-05-01T00:00:00.2+02:00", "2005-05-01T00:00:00.2+02:00" } }; + + private static final String[][] COMPARISON_DATES = { + { "-0005-02-27T00:00:00", "2005-02-28T24:00:00" }, + { "2005-02-28T24:00:00", "2005-03-27T00:00:00" }, + { "2005-01-28T24:00:00", "2005-02-28T00:00:00.4" }, + { "2005-02-28T00:00:00.1", "2005-02-28T00:00:00.4" }, + { "2005-02-28T00:00:00", "2005-02-28T00:00:00.1" }, + { "2005-02-28T00:00:00", "2005-02-28T00:00:00.2" }, + { "2005-05-01T00:00:00.2+02:00", "2005-05-01T00:00:00.2+01:00" }, + { "2005-05-01T00:00:00.2-01:00", "2005-05-01T00:00:00.2-02:00" }, + { "2005-05-01T00:00:00+02:00", "2005-05-01T00:00:00.2+01:00" }, + { "2005-05-01T00:00:00-01:00", "2005-05-01T00:00:00.2-02:00" }, + { "2005-05-01T00:00:00-01:00", "2005-05-01T00:00:00-02:00" }, + { "2005-05-01T00:00:00-01:00", "2005-05-01T00:00:00-02:00" }, + { "-2005-05-01T00:00:00.2+02:00", "2005-05-01T00:00:00.2+02:00" }, + { "2005-05-01T00:00:00.2+02:00", "20005-05-01T00:00:00.2+02:00" } }; + + public static Test suite() { + TestSuite suite = new TestSuite(); + + for (int i = 0; i < VALID_DATES.length; i++) { + suite.addTest(new ValidDateTest(VALID_DATES[i])); + } + + for (int i = 0; i < INVALID_DATES.length; i++) { + suite.addTest(new InvalidDateTest(INVALID_DATES[i])); + } + + for (int i = 0; i < NORMALIZED_DATES.length; i++) { + suite.addTest(new NormalizedDateTest(NORMALIZED_DATES[i][0], NORMALIZED_DATES[i][1])); + } + + for (int i = 0; i < EQUAL_DATES.length; i++) { + suite.addTest(new EqualDateTest(EQUAL_DATES[i][0], EQUAL_DATES[i][1])); + } + + for (int i = 0; i < COMPARISON_DATES.length; i++) { + suite.addTest(new CompareDateTest(COMPARISON_DATES[i][0], COMPARISON_DATES[i][1])); + } + + return suite; + } + + private static void logError(String errMsg) { + System.err.println("[ERROR]: " + errMsg); + } + + /* + * run test + */ + public static void main(String[] args) { + TestRunner.run(new TestSuite(DateTimeTest.class)); + } + + /*--------------------------------------------------* + * Inner classes for testing specific functionality * + *--------------------------------------------------*/ + + private static class ValidDateTest extends TestCase { + + private String dateString; + + public ValidDateTest(String dateString) { + super("valid: " + dateString); + this.dateString = dateString; + } + + protected void runTest() { + if (!XMLDatatypeUtil.isValidDateTime(dateString)) { + String errMsg = "string should be valid but is not: " + dateString; + logError(errMsg); + fail(errMsg); + } + } + } + + private static class InvalidDateTest extends TestCase { + + private String dateString; + + public InvalidDateTest(String dateString) { + super("invalid: " + dateString); + this.dateString = dateString; + } + + protected void runTest() { + if (XMLDatatypeUtil.isValidDateTime(dateString)) { + String errMsg = "string should be invalid but is not: " + dateString; + logError(errMsg); + fail(errMsg); + } + } + } + + private static class NormalizedDateTest extends TestCase { + + private String input; + + private String expected; + + public NormalizedDateTest(String input, String expected) { + super("normalize: " + input + " --> " + expected); + this.input = input; + this.expected = expected; + } + + protected void runTest() { + String normalized = XMLDatatypeUtil.normalizeDateTime(input); + if (!expected.equals(normalized)) { + String errMsg = "normalizing " + input + " should produce " + expected + " but was " + normalized; + logError(errMsg); + fail(errMsg); + } + } + } + + private static class EqualDateTest extends TestCase { + + private String dateString1; + + private String dateString2; + + public EqualDateTest(String dateString1, String dateString2) { + super(dateString1 + " == " + dateString2); + this.dateString1 = dateString1; + this.dateString2 = dateString2; + } + + protected void runTest() { + int result = XMLDatatypeUtil.compareDateTime(dateString1, dateString2); + if (result != 0) { + String errMsg = dateString1 + " and " + dateString2 + " should be equals but are not (result=" + + result + ")"; + logError(errMsg); + fail(errMsg); + } + } + } + + private static class CompareDateTest extends TestCase { + + private String dateString1; + + private String dateString2; + + public CompareDateTest(String dateString1, String dateString2) { + super(dateString1 + " < " + dateString2); + this.dateString1 = dateString1; + this.dateString2 = dateString2; + } + + protected void runTest() { + int result = XMLDatatypeUtil.compareDateTime(dateString1, dateString2); + if (result >= 0) { + String errMsg = dateString1 + " should be smaller than " + dateString2 + " but is not (result=" + + result + ")"; + logError(errMsg); + fail(errMsg); + } + } + } +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtilTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtilTest.java new file mode 100644 index 00000000000..39f8e2fec8c --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtilTest.java @@ -0,0 +1,302 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.datatypes; + +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.junit.Test; + +/** + * Unit tests on {@link org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil} + * + * @author Jeen Broekstra + */ +public class XMLDatatypeUtilTest { + + private static final String[] VALID_FLOATS = { + "1", + "1.0", + "1.0E6", + "-1.0E6", + "15.00001E2", + "1500000000000", + "1E104", + "0.1E105", + "INF", + "-INF", + "NaN" + }; + + private static final String[] INVALID_FLOATS = { + "A1", + "1,0", + "1E106", + "100E104", + "1.0e1.2", + "1.0E 5", + "-NaN", + "+NaN", + "+INF", + "NAN" + }; + + /** valid xsd:date values */ + private static final String[] VALID_DATES = { + "2001-01-01", + "2001-01-01Z", + "2001-12-12+10:00", + "-1800-06-06Z", + "2004-02-29" // leap year + }; + + /** invalid xsd:date values */ + private static final String[] INVALID_DATES = { + "foo", + "Mon, 11 Jul 2005 +0200", + "2001", + "01", + "2001-01", + "2001-13-01", + "2001-01-32", + "2001-12-12+16:00", + "2003-02-29" // not a leap year + }; + + /** valid xsd:time values */ + private static final String[] VALID_TIMES = { + "13:00:00", + "09:15:10", + "09:15:10.01", + "09:15:10.12345", + "11:11:11Z", + "10:00:01+06:00", + "10:01:58-06:00" + }; + + /** invalid xsd:time values */ + private static final String[] INVALID_TIMES = { + "foo", + "21:32", + "9:15:16", + "09:15:10.", + "09:15:10.x", + "2001-10-10:10:10:10", + "-10:00:00", + "25:25:25" + }; + + + /** valid xsd:gYear values */ + private static final String[] VALID_GYEAR = { "2001", "2001+02:00", "2001Z", "-2001" }; + + /** invalid xsd:gYear values */ + private static final String[] INVALID_GYEAR = { "foo", "01", "2001-01", "2001-01-01" }; + + /** valid xsd:gDay values */ + private static final String[] VALID_GDAY = { "---01", "---26Z", "---12-06:00", "---13+10:00" }; + + /** invalid xsd:gDay values */ + private static final String[] INVALID_GDAY = { + "01", + "--01-", + "2001-01", + "foo", + "---1", + "---01+16:00", + "---32" }; + + /** valid xsd:gMonth values */ + private static final String[] VALID_GMONTH = { + "--05", + "--11Z", + "--11+02:00", + "--11-04:00", + "--02" + }; + + /** invalid xsd:gMonth values */ + private static final String[] INVALID_GMONTH = { + "foo", + "-05-", + "--13", + "--1", + "01", + "2001-01" + }; + + /** valid xsd:gMonthDay values */ + private static final String[] VALID_GMONTHDAY = { + "--05-01", + "--11-01Z", + "--11-01+02:00", + "--11-13-04:00", + "--11-15" + }; + + /** invalid xsd:gMonthDay values */ + private static final String[] INVALID_GMONTHDAY = { + "foo", + "-01-30-", + "--01-35", + "--1-5", + "01-15", + "--13-01" + }; + + /** valid xsd:gYearMonth values */ + private static final String[] VALID_GYEARMONTH = { + "2001-10", + "2001-10Z", + "2001-10+02:00", + "2001-10-04:00", + }; + + /** invalid xsd:gYearMonth values */ + private static final String[] INVALID_GYEARMONTH = { + "foo", + "2001", + "2001-15", + "2001-13-26+02:00", + "2001-11-11+02:00", + "01-10" + }; + + /** valid xsd:duration values */ + private static final String[] VALID_DURATION = { + "PT1004199059S", + "PT130S", + "PT2M10S", + "P1DT2S", + "P1M2D", + "P2Y2M1D", + "-P1Y", + "P60D", + "P1Y2M3DT5H20M30.123S", + "PT15.5S" + }; + + /** invalid xsd:duration values */ + private static final String[] INVALID_DURATION = { + "1Y", + "P1S", + "P-1Y", + "P1M2Y", + "P2YT", + "P", + "" + }; + + /** valid xsd:dayTimeDuration values */ + private static final String[] VALID_DAYTIMEDURATION = { + "P1DT2H", + "PT20M", + "PT120M", + "P3DT5H20M30.123S", + "-P6D", + "PT15.5S" + }; + + /** invalid xsd:dayTimeDuration values */ + private static final String[] INVALID_DAYTIMEDURATION = { + "P1Y2M3DT5H20M30.123S", + "P1Y", + "P-20D", + "P20DT", + "P15.5D", + "P1D2H", + "P", + "", + "PT15.S" + }; + + /** valid xsd:QName values */ + private static final String[] VALID_QNAMES = { + "foo:bar", + "foo:_bar", + "foo:_123f", + ":bar", + ":_1bar", + "foo:", + "föö:bar", + "foo:băr", + "жоо:вар", // cyrillic chars + "⻐:⻘⻨" // random chinese chars, if this sequence happens to mean something, this is unintended + }; + + /** ivalid xsd:QName values */ + private static final String[] INVALID_QNAMES = { + "1:bar", + "foo:1bar", + "foo:bar:baz", + "foo", + "_:bar" + }; + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil#isValidValue(java.lang.String, org.eclipse.rdf4j.model.IRI)} + * . + */ + @Test + public void testIsValidValue() { + + testValidation(VALID_FLOATS, XMLSchema.FLOAT, true); + testValidation(INVALID_FLOATS, XMLSchema.FLOAT, false); + + + testValidation(VALID_DATES, XMLSchema.DATE, true); + testValidation(INVALID_DATES, XMLSchema.DATE, false); + + testValidation(VALID_TIMES, XMLSchema.TIME, true); + testValidation(INVALID_TIMES, XMLSchema.TIME, false); + + testValidation(VALID_GDAY, XMLSchema.GDAY, true); + testValidation(INVALID_GDAY, XMLSchema.GDAY, false); + + testValidation(VALID_GMONTH, XMLSchema.GMONTH, true); + testValidation(INVALID_GMONTH, XMLSchema.GMONTH, false); + + testValidation(VALID_GMONTHDAY, XMLSchema.GMONTHDAY, true); + testValidation(INVALID_GMONTHDAY, XMLSchema.GMONTHDAY, false); + + testValidation(VALID_GYEAR, XMLSchema.GYEAR, true); + testValidation(INVALID_GYEAR, XMLSchema.GYEAR, false); + + testValidation(VALID_GYEARMONTH, XMLSchema.GYEARMONTH, true); + testValidation(INVALID_GYEARMONTH, XMLSchema.GYEARMONTH, false); + + testValidation(VALID_DURATION, XMLSchema.DURATION, true); + testValidation(INVALID_DURATION, XMLSchema.DURATION, false); + + testValidation(VALID_DAYTIMEDURATION, XMLSchema.DAYTIMEDURATION, true); + testValidation(INVALID_DAYTIMEDURATION, XMLSchema.DAYTIMEDURATION, false); + + testValidation(VALID_QNAMES, XMLSchema.QNAME, true); + testValidation(INVALID_QNAMES, XMLSchema.QNAME, false); + + } + + private void testValidation(String[] values, IRI datatype, boolean validValues) { + for (String value : values) { + boolean result = XMLDatatypeUtil.isValidValue(value, datatype); + if (validValues) { + if (!result) { + fail("value " + value + " should have validated for type " + datatype); + } + } + else { + if (result) { + fail("value " + value + " should not have validated for type " + datatype); + } + } + } + } +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/impl/ContextStatementTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/impl/ContextStatementTest.java new file mode 100644 index 00000000000..955d8fca599 --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/impl/ContextStatementTest.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + + +public class ContextStatementTest { + + private static final ValueFactory vf = SimpleValueFactory.getInstance(); + + private static final IRI s1 = vf.createIRI("urn:s1"); + private static final IRI p1 = vf.createIRI("urn:p1"); + private static final IRI o1 = vf.createIRI("urn:o1"); + private static final IRI o2 = vf.createIRI("urn:o2"); + private static final IRI g1 = vf.createIRI("urn:g1"); + private static final IRI g2 = vf.createIRI("urn:g2"); + + + @Before + public void setUp() + throws Exception + { + } + + @After + public void tearDown() + throws Exception + { + } + + @Test + public void test() { + Statement st1 = vf.createStatement(s1, p1, o1); + Statement st2 = vf.createStatement(s1, p1, o1, g1); + Statement st3 = vf.createStatement(s1, p1, o2); + Statement st4 = vf.createStatement(s1, p1, o1, g1); + Statement st5 = vf.createStatement(s1, p1, o1, g2); + + assertNotEquals(st1, st2); + assertNotEquals(st1, st3); + assertEquals(st2, st4); + assertNotEquals(st2, st5); + + Set set = new HashSet(); + set.add(st1); + set.add(st2); + set.add(st3); + set.add(st4); + set.add(st5); + + assertEquals(4, set.size()); + + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/impl/SimpleLiteralTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/impl/SimpleLiteralTest.java new file mode 100644 index 00000000000..2843df1b1ff --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/impl/SimpleLiteralTest.java @@ -0,0 +1,467 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.impl.SimpleLiteral; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * Unit tests for {@link SimpleLiteral}. + * + * @author Peter Ansell + */ +public class SimpleLiteralTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#hashCode()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testHashCode() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String)}. + */ + @Test + public final void testStringNull() + throws Exception + { + thrown.expect(NullPointerException.class); + new SimpleLiteral(null); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String)}. + */ + @Test + public final void testStringEmpty() + throws Exception + { + Literal test = new SimpleLiteral(""); + assertEquals("", test.getLabel()); + assertFalse(test.getLanguage().isPresent()); + assertEquals(XMLSchema.STRING, test.getDatatype()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String)}. + */ + @Test + public final void testStringLong() + throws Exception + { + StringBuilder testBuilder = new StringBuilder(1000000); + for (int i = 0; i < 1000000; i++) { + testBuilder.append(Integer.toHexString(i % 16)); + } + + Literal test = new SimpleLiteral(testBuilder.toString()); + assertEquals(testBuilder.toString(), test.getLabel()); + assertFalse(test.getLanguage().isPresent()); + assertEquals(XMLSchema.STRING, test.getDatatype()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String, java.lang.String)} + * . + */ + @Test + public final void testStringStringNullNull() + throws Exception + { + String label = null; + String language = null; + + thrown.expect(NullPointerException.class); + new SimpleLiteral(label, language); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String, java.lang.String)} + * . + */ + @Test + public final void testStringStringEmptyNull() + throws Exception + { + String label = ""; + String language = null; + + thrown.expect(NullPointerException.class); + new SimpleLiteral(label, language); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String, java.lang.String)} + * . + */ + @Test + public final void testStringStringNullEmpty() + throws Exception + { + String label = null; + String language = ""; + + thrown.expect(NullPointerException.class); + new SimpleLiteral(label, language); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String, org.eclipse.rdf4j.model.IRI)} + * . + */ + @Test + public final void testStringIRINullNull() + throws Exception + { + String label = null; + IRI datatype = null; + + thrown.expect(NullPointerException.class); + new SimpleLiteral(label, datatype); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String, org.eclipse.rdf4j.model.IRI)} + * . + */ + @Test + public final void testStringIRINullString() + throws Exception + { + String label = null; + IRI datatype = XMLSchema.STRING; + + thrown.expect(NullPointerException.class); + new SimpleLiteral(label, datatype); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String, org.eclipse.rdf4j.model.IRI)} + * . + */ + @Test + public final void testStringIRINullLangString() + throws Exception + { + String label = null; + IRI datatype = RDF.LANGSTRING; + + thrown.expect(NullPointerException.class); + new SimpleLiteral(label, datatype); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String, org.eclipse.rdf4j.model.IRI)} + * . + */ + @Test + public final void testStringIRIEmptyNull() + throws Exception + { + String label = ""; + IRI datatype = null; + + Literal test = new SimpleLiteral(label, datatype); + assertEquals("", test.getLabel()); + assertFalse(test.getLanguage().isPresent()); + assertEquals(XMLSchema.STRING, test.getDatatype()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#SimpleLiteral(java.lang.String, org.eclipse.rdf4j.model.IRI)} + * . + */ + @Test + public final void testStringIRIEmptyLangString() + throws Exception + { + String label = ""; + IRI datatype = RDF.LANGSTRING; + + thrown.expect(IllegalArgumentException.class); + new SimpleLiteral(label, datatype); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#setLabel(java.lang.String)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testSetLabel() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#getLabel()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testGetLabel() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#setLanguage(java.lang.String)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testSetLanguage() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#getLanguage()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testGetLanguage() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#setDatatype(org.eclipse.rdf4j.model.IRI)} + * . + */ + @Ignore("TODO: Implement me!") + @Test + public final void testSetDatatype() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#getDatatype()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testGetDatatype() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#equals(java.lang.Object)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testEqualsObject() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#toString()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testToString() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#stringValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testStringValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#booleanValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testBooleanValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#byteValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testByteValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#shortValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testShortValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#intValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testIntValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#longValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testLongValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#floatValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testFloatValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#doubleValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testDoubleValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#integerValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testIntegerValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#decimalValue()}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testDecimalValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link org.eclipse.rdf4j.model.impl.SimpleLiteral#calendarValue()} + * . + */ + @Ignore("TODO: Implement me!") + @Test + public final void testCalendarValue() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link java.lang.Object#equals(java.lang.Object)}. + */ + @Ignore("TODO: Implement me!") + @Test + public final void testEqualsObject1() + throws Exception + { + fail("Not yet implemented"); // TODO + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/util/LiteralsTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/util/LiteralsTest.java new file mode 100644 index 00000000000..71a368cf490 --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/util/LiteralsTest.java @@ -0,0 +1,953 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import static org.junit.Assert.*; + +import java.util.Date; +import java.util.GregorianCalendar; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.util.LiteralUtilException; +import org.eclipse.rdf4j.model.util.Literals; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Tests for {@link Literals}. + * + * @author Peter Ansell + */ +public class LiteralsTest { + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getLabel(org.eclipse.rdf4j.model.Literal, java.lang.String)} + * . + */ + @Ignore + @Test + public final void testGetLabelLiteralString() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getLabel(org.eclipse.rdf4j.model.Value, java.lang.String)} + * . + */ + @Ignore + @Test + public final void testGetLabelValueString() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getByteValue(org.eclipse.rdf4j.model.Literal, byte)} + * . + */ + @Ignore + @Test + public final void testGetByteValueLiteralByte() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getByteValue(org.eclipse.rdf4j.model.Value, byte)} + * . + */ + @Ignore + @Test + public final void testGetByteValueValueByte() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getShortValue(org.eclipse.rdf4j.model.Literal, short)} + * . + */ + @Ignore + @Test + public final void testGetShortValueLiteralShort() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getShortValue(org.eclipse.rdf4j.model.Value, short)} + * . + */ + @Ignore + @Test + public final void testGetShortValueValueShort() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getIntValue(org.eclipse.rdf4j.model.Literal, int)} + * . + */ + @Ignore + @Test + public final void testGetIntValueLiteralInt() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getIntValue(org.eclipse.rdf4j.model.Value, int)} + * . + */ + @Ignore + @Test + public final void testGetIntValueValueInt() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getLongValue(org.eclipse.rdf4j.model.Literal, long)} + * . + */ + @Ignore + @Test + public final void testGetLongValueLiteralLong() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getLongValue(org.eclipse.rdf4j.model.Value, long)} + * . + */ + @Ignore + @Test + public final void testGetLongValueValueLong() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getIntegerValue(org.eclipse.rdf4j.model.Literal, java.math.BigInteger)} + * . + */ + @Ignore + @Test + public final void testGetIntegerValueLiteralBigInteger() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getIntegerValue(org.eclipse.rdf4j.model.Value, java.math.BigInteger)} + * . + */ + @Ignore + @Test + public final void testGetIntegerValueValueBigInteger() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getDecimalValue(org.eclipse.rdf4j.model.Literal, java.math.BigDecimal)} + * . + */ + @Ignore + @Test + public final void testGetDecimalValueLiteralBigDecimal() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getDecimalValue(org.eclipse.rdf4j.model.Value, java.math.BigDecimal)} + * . + */ + @Ignore + @Test + public final void testGetDecimalValueValueBigDecimal() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getFloatValue(org.eclipse.rdf4j.model.Literal, float)} + * . + */ + @Ignore + @Test + public final void testGetFloatValueLiteralFloat() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getFloatValue(org.eclipse.rdf4j.model.Value, float)} + * . + */ + @Ignore + @Test + public final void testGetFloatValueValueFloat() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getDoubleValue(org.eclipse.rdf4j.model.Literal, double)} + * . + */ + @Ignore + @Test + public final void testGetDoubleValueLiteralDouble() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getDoubleValue(org.eclipse.rdf4j.model.Value, double)} + * . + */ + @Ignore + @Test + public final void testGetDoubleValueValueDouble() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getBooleanValue(org.eclipse.rdf4j.model.Literal, boolean)} + * . + */ + @Ignore + @Test + public final void testGetBooleanValueLiteralBoolean() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getBooleanValue(org.eclipse.rdf4j.model.Value, boolean)} + * . + */ + @Ignore + @Test + public final void testGetBooleanValueValueBoolean() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getCalendarValue(org.eclipse.rdf4j.model.Literal, javax.xml.datatype.XMLGregorianCalendar)} + * . + */ + @Ignore + @Test + public final void testGetCalendarValueLiteralXMLGregorianCalendar() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getCalendarValue(org.eclipse.rdf4j.model.Value, javax.xml.datatype.XMLGregorianCalendar)} + * . + */ + @Ignore + @Test + public final void testGetCalendarValueValueXMLGregorianCalendar() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#getLocale(org.eclipse.rdf4j.model.Literal, java.util.Locale)} + * . + */ + @Ignore + @Test + public final void testGetLocale() + throws Exception + { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectNull() + throws Exception + { + + Object obj = null; + try { + Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + fail("Did not find expected exception"); + } + catch (NullPointerException npe) { + assertTrue(npe.getMessage().contains("Cannot create a literal from a null")); + } + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectBoolean() + throws Exception + { + + Object obj = Boolean.TRUE; + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.BOOLEAN); + assertTrue(l.booleanValue()); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectByte() + throws Exception + { + + Object obj = new Integer(42).byteValue(); + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.BYTE); + assertEquals(l.getLabel(), "42"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectDouble() + throws Exception + { + + Object obj = new Double(42); + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.DOUBLE); + assertEquals(l.getLabel(), "42.0"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectFloat() + throws Exception + { + + Object obj = new Float(42); + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.FLOAT); + assertEquals(l.getLabel(), "42.0"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectInteger() + throws Exception + { + + Object obj = new Integer(4); + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.INT); + assertEquals(l.getLabel(), "4"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectLong() + throws Exception + { + + Object obj = new Long(42); + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.LONG); + assertEquals(l.getLabel(), "42"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectShort() + throws Exception + { + + Object obj = Short.parseShort("42"); + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.SHORT); + assertEquals("42", l.getLabel()); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectXMLGregorianCalendar() + throws Exception + { + + GregorianCalendar c = new GregorianCalendar(); + c.setTime(new Date()); + try { + Object obj = DatatypeFactory.newInstance().newXMLGregorianCalendar(c); + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.DATETIME); + // TODO check lexical value? + } + catch (DatatypeConfigurationException e) { + e.printStackTrace(); + fail("Could not instantiate javax.xml.datatype.DatatypeFactory"); + } + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectDate() + throws Exception + { + + Object obj = new Date(); + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.DATETIME); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectString() + throws Exception + { + + Object obj = "random unique string"; + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.STRING); + assertEquals(l.getLabel(), "random unique string"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralObjectObject() + throws Exception + { + + Object obj = new Object(); + Literal l = Literals.createLiteral(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.STRING); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectNull() + throws Exception + { + + Object obj = null; + try { + Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + fail("Did not find expected exception"); + } + catch (NullPointerException npe) { + assertTrue(npe.getMessage().contains("Cannot create a literal from a null")); + } + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectBoolean() + throws Exception + { + + Object obj = Boolean.TRUE; + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.BOOLEAN); + assertTrue(l.booleanValue()); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectByte() + throws Exception + { + + Object obj = new Integer(42).byteValue(); + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.BYTE); + assertEquals(l.getLabel(), "42"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectDouble() + throws Exception + { + + Object obj = new Double(42); + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.DOUBLE); + assertEquals(l.getLabel(), "42.0"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectFloat() + throws Exception + { + + Object obj = new Float(42); + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.FLOAT); + assertEquals(l.getLabel(), "42.0"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectInteger() + throws Exception + { + + Object obj = new Integer(4); + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.INT); + assertEquals(l.getLabel(), "4"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectLong() + throws Exception + { + + Object obj = new Long(42); + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.LONG); + assertEquals(l.getLabel(), "42"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectShort() + throws Exception + { + + Object obj = Short.parseShort("42"); + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.SHORT); + assertEquals("42", l.getLabel()); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectXMLGregorianCalendar() + throws Exception + { + + GregorianCalendar c = new GregorianCalendar(); + c.setTime(new Date()); + try { + Object obj = DatatypeFactory.newInstance().newXMLGregorianCalendar(c); + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.DATETIME); + // TODO check lexical value? + } + catch (DatatypeConfigurationException e) { + e.printStackTrace(); + fail("Could not instantiate javax.xml.datatype.DatatypeFactory"); + } + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectDate() + throws Exception + { + + Object obj = new Date(); + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.DATETIME); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectString() + throws Exception + { + + Object obj = "random unique string"; + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + assertNotNull(l); + assertEquals(l.getDatatype(), XMLSchema.STRING); + assertEquals(l.getLabel(), "random unique string"); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteralOrFail(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCreateLiteralOrFailObjectObject() + throws Exception + { + + Object obj = new Object(); + try { + Literal l = Literals.createLiteralOrFail(SimpleValueFactory.getInstance(), obj); + fail("Did not receive expected exception"); + } + catch (LiteralUtilException e) { + assertTrue(e.getMessage().contains("Did not recognise object when creating literal")); + } + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#createLiteral(org.eclipse.rdf4j.model.ValueFactory, java.lang.Object)} + * . + */ + @Test + public void testCanCreateLiteralObjectNull() + throws Exception + { + + Object obj = null; + assertFalse(Literals.canCreateLiteral(obj)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectBoolean() + throws Exception + { + + Object obj = Boolean.TRUE; + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectByte() + throws Exception + { + + Object obj = new Integer(42).byteValue(); + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectDouble() + throws Exception + { + + Object obj = new Double(42); + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectFloat() + throws Exception + { + + Object obj = new Float(42); + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectInteger() + throws Exception + { + + Object obj = new Integer(4); + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectLong() + throws Exception + { + + Object obj = new Long(42); + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectShort() + throws Exception + { + + Object obj = Short.parseShort("42"); + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectXMLGregorianCalendar() + throws Exception + { + + GregorianCalendar c = new GregorianCalendar(); + c.setTime(new Date()); + Object obj = DatatypeFactory.newInstance().newXMLGregorianCalendar(c); + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectDate() + throws Exception + { + + Object obj = new Date(); + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectString() + throws Exception + { + + Object obj = "random unique string"; + assertTrue(Literals.canCreateLiteral(obj)); + + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Literals#canCreateLiteral(Object)} . + */ + @Test + public void testCanCreateLiteralObjectObject() + throws Exception + { + + Object obj = new Object(); + assertFalse(Literals.canCreateLiteral(obj)); + + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/util/ModelsTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/util/ModelsTest.java new file mode 100644 index 00000000000..9dee858a29e --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/util/ModelsTest.java @@ -0,0 +1,316 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.util.Models; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.junit.Before; +import org.junit.Test; + +/** + * Unit tests on {@link Models} utility methods. + * + * @author Jeen Broekstra + */ +public class ModelsTest { + + private Model model1; + + private Model model2; + + private static ValueFactory VF = SimpleValueFactory.getInstance(); + + private IRI foo; + + private IRI bar; + + private BNode baz; + + @Before + public void setUp() { + model1 = new LinkedHashModel(); + model2 = new LinkedHashModel(); + + foo = VF.createIRI("http://example.org/foo"); + bar = VF.createIRI("http://example.org/bar"); + baz = VF.createBNode(); + } + + @Test + public void testModelsIsomorphic() { + + // two identical statements, no bnodes + model1.add(foo, RDF.TYPE, bar); + + assertFalse(Models.isomorphic(model1, model2)); + + model2.add(foo, RDF.TYPE, bar); + + assertTrue(Models.isomorphic(model1, model2)); + + // add same statement again + model2.add(foo, RDF.TYPE, bar); + + assertTrue("Duplicate statement should not be considered", Models.isomorphic(model1, model2)); + + // two identical statements with bnodes added. + model1.add(foo, RDF.TYPE, VF.createBNode()); + model2.add(foo, RDF.TYPE, VF.createBNode()); + + assertTrue(Models.isomorphic(model1, model2)); + + // chained bnodes + BNode chainedNode1 = VF.createBNode(); + + model1.add(bar, RDFS.SUBCLASSOF, chainedNode1); + model1.add(chainedNode1, RDFS.SUBCLASSOF, foo); + + BNode chainedNode2 = VF.createBNode(); + + model2.add(bar, RDFS.SUBCLASSOF, chainedNode2); + model2.add(chainedNode2, RDFS.SUBCLASSOF, foo); + + assertTrue(Models.isomorphic(model1, model2)); + + // two bnode statements with non-identical predicates + + model1.add(foo, foo, VF.createBNode()); + model2.add(foo, bar, VF.createBNode()); + + assertFalse(Models.isomorphic(model1, model2)); + + } + + @Test + public void testModelsIsomorphicContext() { + model1.add(foo, RDF.TYPE, bar); + model2.add(foo, RDF.TYPE, bar, foo); + assertFalse(Models.isomorphic(model1, model2)); + + model1.add(foo, RDF.TYPE, bar, foo); + model2.add(foo, RDF.TYPE, bar); + + assertTrue(Models.isomorphic(model1, model2)); + + model1.add(foo, RDF.TYPE, bar, baz); + + assertFalse(Models.isomorphic(model1, model2)); + + model2.add(foo, RDF.TYPE, bar, VF.createBNode()); + + assertTrue(Models.isomorphic(model1, model2)); + + } + + @Test + public void testIsSubset() { + + // two empty sets + assertTrue(Models.isSubset(model1, model2)); + assertTrue(Models.isSubset(model2, model1)); + + // two identical statements, no bnodes + model1.add(foo, RDF.TYPE, bar); + + assertFalse(Models.isSubset(model1, model2)); + assertTrue(Models.isSubset(model2, model1)); + + model2.add(foo, RDF.TYPE, bar); + + assertTrue(Models.isSubset(model1, model2)); + assertTrue(Models.isSubset(model2, model1)); + + // two identical statements with bnodes added. + model1.add(foo, RDF.TYPE, VF.createBNode()); + + assertFalse(Models.isSubset(model1, model2)); + assertTrue(Models.isSubset(model2, model1)); + + model2.add(foo, RDF.TYPE, VF.createBNode()); + + assertTrue(Models.isSubset(model1, model2)); + assertTrue(Models.isSubset(model2, model1)); + + // chained bnodes + BNode chainedNode1 = VF.createBNode(); + + model1.add(bar, RDFS.SUBCLASSOF, chainedNode1); + model1.add(chainedNode1, RDFS.SUBCLASSOF, foo); + + assertFalse(Models.isSubset(model1, model2)); + assertTrue(Models.isSubset(model2, model1)); + + BNode chainedNode2 = VF.createBNode(); + + model2.add(bar, RDFS.SUBCLASSOF, chainedNode2); + model2.add(chainedNode2, RDFS.SUBCLASSOF, foo); + + assertTrue(Models.isSubset(model1, model2)); + assertTrue(Models.isSubset(model2, model1)); + + // two bnode statements with non-identical predicates + + model1.add(foo, foo, VF.createBNode()); + model2.add(foo, bar, VF.createBNode()); + + assertFalse(Models.isSubset(model1, model2)); + assertFalse(Models.isSubset(model2, model1)); + } + + public void testObject() { + Literal lit = VF.createLiteral(1.0); + model1.add(foo, bar, lit); + model1.add(foo, bar, foo); + + Value result = Models.object(model1).orElse(null); + assertNotNull(result); + assertTrue(result.equals(lit) || result.equals(foo)); + } + + public void testObjectURI() { + Literal lit = VF.createLiteral(1.0); + model1.add(foo, bar, lit); + model1.add(foo, bar, foo); + + Value result = Models.objectIRI(model1).orElse(null); + assertNotNull(result); + assertEquals(foo, result); + } + + public void testObjectLiteral() { + Literal lit = VF.createLiteral(1.0); + model1.add(foo, bar, lit); + model1.add(foo, bar, foo); + + Value result = Models.objectLiteral(model1).orElse(null); + assertNotNull(result); + assertEquals(lit, result); + } + + public void testPredicate() { + model1.add(foo, bar, foo); + model1.add(foo, foo, foo); + + IRI result = Models.predicate(model1).orElse(null); + assertNotNull(result); + assertTrue(result.equals(bar) || result.equals(foo)); + } + + public void testSubject() { + model1.add(foo, bar, foo); + model1.add(foo, foo, foo); + model1.add(bar, foo, foo); + model1.add(baz, foo, foo); + + Resource result = Models.subject(model1).orElse(null); + assertNotNull(result); + assertTrue(result.equals(bar) || result.equals(foo) || result.equals(baz)); + } + + public void testSubjectURI() { + model1.add(foo, bar, foo); + model1.add(foo, foo, foo); + model1.add(baz, foo, foo); + model1.add(bar, foo, foo); + + Resource result = Models.subjectIRI(model1).orElse(null); + assertNotNull(result); + assertTrue(result.equals(bar) || result.equals(foo)); + } + + public void testSubjectBNode() { + model1.add(foo, bar, foo); + model1.add(foo, foo, foo); + model1.add(baz, foo, foo); + model1.add(bar, foo, foo); + + Resource result = Models.subjectBNode(model1).orElse(null); + assertNotNull(result); + assertTrue(result.equals(baz)); + } + + @Test + public void testSetProperty() { + Literal lit1 = VF.createLiteral(1.0); + model1.add(foo, bar, lit1); + model1.add(foo, bar, foo); + + Literal lit2 = VF.createLiteral(2.0); + + Model m = Models.setProperty(model1, foo, bar, lit2); + + assertNotNull(m); + assertEquals(model1, m); + assertFalse(model1.contains(foo, bar, lit1)); + assertFalse(model1.contains(foo, bar, foo)); + assertTrue(model1.contains(foo, bar, lit2)); + + } + + @Test + public void testSetPropertyWithContext1() { + Literal lit1 = VF.createLiteral(1.0); + IRI graph1 = VF.createIRI("urn:g1"); + IRI graph2 = VF.createIRI("urn:g2"); + model1.add(foo, bar, lit1, graph1); + model1.add(foo, bar, bar); + model1.add(foo, bar, foo, graph2); + + Literal lit2 = VF.createLiteral(2.0); + + Model m = Models.setProperty(model1, foo, bar, lit2, graph2); + + assertNotNull(m); + assertEquals(model1, m); + assertTrue(model1.contains(foo, bar, lit1)); + assertFalse(model1.contains(foo, bar, foo)); + assertTrue(model1.contains(foo, bar, bar)); + assertFalse(model1.contains(foo, bar, foo, graph2)); + assertTrue(model1.contains(foo, bar, lit2, graph2)); + assertTrue(model1.contains(foo, bar, lit2)); + } + + @Test + public void testSetPropertyWithContext2() { + Literal lit1 = VF.createLiteral(1.0); + IRI graph1 = VF.createIRI("urn:g1"); + IRI graph2 = VF.createIRI("urn:g2"); + model1.add(foo, bar, lit1, graph1); + model1.add(foo, bar, bar); + model1.add(foo, bar, foo, graph2); + + Literal lit2 = VF.createLiteral(2.0); + + Model m = Models.setProperty(model1, foo, bar, lit2); + + assertNotNull(m); + assertEquals(model1, m); + assertFalse(model1.contains(foo, bar, lit1)); + assertFalse(model1.contains(foo, bar, lit1, graph1)); + assertFalse(model1.contains(foo, bar, foo)); + assertFalse(model1.contains(foo, bar, bar)); + assertFalse(model1.contains(foo, bar, foo, graph2)); + assertTrue(model1.contains(foo, bar, lit2)); + } +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/util/NamespacesTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/util/NamespacesTest.java new file mode 100644 index 00000000000..047c07b7971 --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/util/NamespacesTest.java @@ -0,0 +1,475 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import static org.junit.Assert.*; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.util.Namespaces; +import org.eclipse.rdf4j.model.vocabulary.DC; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.model.vocabulary.SESAME; +import org.eclipse.rdf4j.model.vocabulary.SKOS; +import org.junit.Before; +import org.junit.Test; + +/** + * @author Peter Ansell + */ +public class NamespacesTest { + + private String testPrefix1; + + private String testPrefix2; + + private String testName1; + + private String testName2; + + @Before + public void setUp() + throws Exception + { + testPrefix1 = "ns1"; + testPrefix2 = "ns2"; + testName1 = "http://example.org/ns1#"; + testName2 = "http://other.example.org/namespace"; + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#asMap(java.util.Set)}. + */ + @Test + public final void testAsMapEmpty() { + Map map = Namespaces.asMap(Collections. emptySet()); + + assertTrue(map.isEmpty()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#asMap(java.util.Set)}. + */ + @Test + public final void testAsMapOne() { + Set input = new HashSet(); + input.add(new SimpleNamespace(RDF.PREFIX, RDF.NAMESPACE)); + + Map map = Namespaces.asMap(input); + + assertFalse(map.isEmpty()); + assertEquals(1, map.size()); + + assertTrue(map.containsKey(RDF.PREFIX)); + assertEquals(RDF.NAMESPACE, map.get(RDF.PREFIX)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#asMap(java.util.Set)}. + */ + @Test + public final void testAsMapMultiple() { + Set input = new HashSet(); + input.add(new SimpleNamespace(RDF.PREFIX, RDF.NAMESPACE)); + input.add(new SimpleNamespace(RDFS.PREFIX, RDFS.NAMESPACE)); + input.add(new SimpleNamespace(DC.PREFIX, DC.NAMESPACE)); + input.add(new SimpleNamespace(SKOS.PREFIX, SKOS.NAMESPACE)); + input.add(new SimpleNamespace(SESAME.PREFIX, SESAME.NAMESPACE)); + + Map map = Namespaces.asMap(input); + + assertFalse(map.isEmpty()); + assertEquals(5, map.size()); + + assertTrue(map.containsKey(RDF.PREFIX)); + assertEquals(RDF.NAMESPACE, map.get(RDF.PREFIX)); + assertTrue(map.containsKey(RDFS.PREFIX)); + assertEquals(RDFS.NAMESPACE, map.get(RDFS.PREFIX)); + assertTrue(map.containsKey(DC.PREFIX)); + assertEquals(DC.NAMESPACE, map.get(DC.PREFIX)); + assertTrue(map.containsKey(SKOS.PREFIX)); + assertEquals(SKOS.NAMESPACE, map.get(SKOS.PREFIX)); + assertTrue(map.containsKey(SESAME.PREFIX)); + assertEquals(SESAME.NAMESPACE, map.get(SESAME.PREFIX)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapClear() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + // Check no exceptions when calling clear on empty backing set + testMap.clear(); + + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + + assertFalse(testMap.isEmpty()); + assertEquals(1, testMap.size()); + + testMap.clear(); + + assertTrue(testMap.isEmpty()); + assertEquals(0, testMap.size()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapContainsKey() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + // Check no exceptions when calling containsKey on empty backing set + assertFalse(testMap.containsKey(testPrefix1)); + + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + + assertTrue(testMap.containsKey(testPrefix1)); + + testSet.clear(); + + assertFalse(testMap.containsKey(testPrefix1)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapContainsValue() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + // Check no exceptions when calling containsKey on empty backing set + assertFalse(testMap.containsValue(testName1)); + + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + + assertTrue(testMap.containsValue(testName1)); + + testSet.clear(); + + assertFalse(testMap.containsValue(testName1)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapEntrySet() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + + Set> entrySet1 = testMap.entrySet(); + assertNotNull(entrySet1); + assertTrue(entrySet1.isEmpty()); + + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + + Set> entrySet2 = testMap.entrySet(); + assertNotNull(entrySet2); + assertFalse(entrySet2.isEmpty()); + assertEquals(1, entrySet2.size()); + Entry nextEntry = entrySet2.iterator().next(); + assertEquals(testPrefix1, nextEntry.getKey()); + assertEquals(testName1, nextEntry.getValue()); + + testSet.clear(); + + Set> entrySet3 = testMap.entrySet(); + assertNotNull(entrySet3); + assertTrue(entrySet3.isEmpty()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapGet() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + assertNull(testMap.get(testPrefix1)); + + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + assertEquals(testName1, testMap.get(testPrefix1)); + + testSet.clear(); + assertNull(testMap.get(testPrefix1)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapIsEmpty() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + assertTrue(testMap.isEmpty()); + + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + assertFalse(testMap.isEmpty()); + + testSet.clear(); + assertTrue(testMap.isEmpty()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapKeySet() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + + Set keySet1 = testMap.keySet(); + assertNotNull(keySet1); + assertTrue(keySet1.isEmpty()); + + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + + Set keySet2 = testMap.keySet(); + assertNotNull(keySet2); + assertFalse(keySet2.isEmpty()); + assertEquals(1, keySet2.size()); + String nextKey = keySet2.iterator().next(); + assertEquals(testPrefix1, nextKey); + + testSet.clear(); + + Set keySet3 = testMap.keySet(); + assertNotNull(keySet3); + assertTrue(keySet3.isEmpty()); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapPut() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + + String put1 = testMap.put(testPrefix1, testName1); + assertNull("Should have returned null from put on an empty backing set", put1); + assertEquals(1, testSet.size()); + assertTrue(testSet.contains(new SimpleNamespace(testPrefix1, testName1))); + assertTrue(testMap.containsKey(testPrefix1)); + assertTrue(testMap.containsValue(testName1)); + + String put2 = testMap.put(testPrefix1, testName2); + assertEquals(put2, testName1); + // Size should be one at this point as original should have been replaced. + assertEquals(1, testSet.size()); + assertTrue(testSet.contains(new SimpleNamespace(testPrefix1, testName2))); + assertTrue(testMap.containsKey(testPrefix1)); + assertFalse(testMap.containsValue(testName1)); + assertTrue(testMap.containsValue(testName2)); + + testSet.clear(); + + assertTrue(testMap.isEmpty()); + assertEquals(0, testMap.size()); + assertFalse(testMap.containsKey(testPrefix1)); + assertFalse(testMap.containsValue(testName1)); + assertFalse(testMap.containsValue(testName2)); + + String put3 = testMap.put(testPrefix1, testName1); + assertNull("Should have returned null from put on an empty backing set", put3); + assertEquals(1, testSet.size()); + assertTrue(testSet.contains(new SimpleNamespace(testPrefix1, testName1))); + assertTrue(testMap.containsKey(testPrefix1)); + assertTrue(testMap.containsValue(testName1)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapPutAll() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + + Map testPutMap = new LinkedHashMap(); + + testMap.putAll(testPutMap); + assertTrue(testMap.isEmpty()); + assertEquals(0, testMap.size()); + assertTrue(testSet.isEmpty()); + assertEquals(0, testSet.size()); + + testPutMap.put(testPrefix1, testName1); + testPutMap.put(testPrefix2, testName2); + + testMap.putAll(testPutMap); + assertFalse(testMap.isEmpty()); + assertEquals(2, testMap.size()); + assertFalse(testSet.isEmpty()); + assertEquals(2, testSet.size()); + assertTrue(testSet.contains(new SimpleNamespace(testPrefix1, testName1))); + assertTrue(testSet.contains(new SimpleNamespace(testPrefix2, testName2))); + assertTrue(testMap.containsKey(testPrefix1)); + assertTrue(testMap.containsValue(testName1)); + assertTrue(testMap.containsKey(testPrefix2)); + assertTrue(testMap.containsValue(testName2)); + + testSet.clear(); + + assertTrue(testMap.isEmpty()); + assertEquals(0, testMap.size()); + assertTrue(testSet.isEmpty()); + assertEquals(0, testSet.size()); + assertFalse(testMap.containsKey(testPrefix1)); + assertFalse(testMap.containsValue(testName1)); + assertFalse(testMap.containsKey(testPrefix2)); + assertFalse(testMap.containsValue(testName2)); + + // Try again after clear + testMap.putAll(testPutMap); + assertFalse(testMap.isEmpty()); + assertEquals(2, testMap.size()); + assertFalse(testSet.isEmpty()); + assertEquals(2, testSet.size()); + assertTrue(testSet.contains(new SimpleNamespace(testPrefix1, testName1))); + assertTrue(testSet.contains(new SimpleNamespace(testPrefix2, testName2))); + assertTrue(testMap.containsKey(testPrefix1)); + assertTrue(testMap.containsValue(testName1)); + assertTrue(testMap.containsKey(testPrefix2)); + assertTrue(testMap.containsValue(testName2)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapRemove() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + + assertTrue(testMap.isEmpty()); + assertEquals(0, testMap.size()); + assertTrue(testSet.isEmpty()); + assertEquals(0, testSet.size()); + assertFalse(testMap.containsKey(testPrefix1)); + assertFalse(testMap.containsValue(testName1)); + + // Directly add to Set, and then try to remove it using the Map + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + assertFalse(testMap.isEmpty()); + assertEquals(1, testMap.size()); + assertFalse(testSet.isEmpty()); + assertEquals(1, testSet.size()); + assertTrue(testSet.contains(new SimpleNamespace(testPrefix1, testName1))); + assertTrue(testMap.containsKey(testPrefix1)); + assertTrue(testMap.containsValue(testName1)); + + testSet.remove(new SimpleNamespace(testPrefix1, testName1)); + + assertTrue(testMap.isEmpty()); + assertEquals(0, testMap.size()); + assertTrue(testSet.isEmpty()); + assertEquals(0, testSet.size()); + assertFalse(testMap.containsKey(testPrefix1)); + assertFalse(testMap.containsValue(testName1)); + + testSet.clear(); + + // Try again after clear + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + assertFalse(testMap.isEmpty()); + assertEquals(1, testMap.size()); + assertFalse(testSet.isEmpty()); + assertEquals(1, testSet.size()); + assertTrue(testSet.contains(new SimpleNamespace(testPrefix1, testName1))); + assertTrue(testMap.containsKey(testPrefix1)); + assertTrue(testMap.containsValue(testName1)); + + testSet.remove(new SimpleNamespace(testPrefix1, testName1)); + + assertTrue(testMap.isEmpty()); + assertEquals(0, testMap.size()); + assertTrue(testSet.isEmpty()); + assertEquals(0, testSet.size()); + assertFalse(testMap.containsKey(testPrefix1)); + assertFalse(testMap.containsValue(testName1)); + } + + /** + * Test method for + * {@link org.eclipse.rdf4j.model.util.Namespaces#wrap(java.util.Set)}. + */ + @Test + public final void testWrapValues() + throws Exception + { + Set testSet = new LinkedHashSet(); + Map testMap = Namespaces.wrap(testSet); + + Collection values1 = testMap.values(); + assertNotNull(values1); + assertTrue(values1.isEmpty()); + + testSet.add(new SimpleNamespace(testPrefix1, testName1)); + + Collection values2 = testMap.values(); + assertNotNull(values2); + assertFalse(values2.isEmpty()); + assertEquals(1, values2.size()); + String nextValue = values2.iterator().next(); + assertEquals(testName1, nextValue); + + testSet.clear(); + + Collection values3 = testMap.values(); + assertNotNull(values3); + assertTrue(values3.isEmpty()); + } + +} diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/util/URIUtilTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/util/URIUtilTest.java new file mode 100644 index 00000000000..1666973f903 --- /dev/null +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/util/URIUtilTest.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.model.util; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.eclipse.rdf4j.model.util.URIUtil; +import org.junit.Test; + +/** + * @author Arjohn Kampman + */ +public class URIUtilTest { + + @Test + public void testIsCorrectURISplit() + throws Exception + { + assertTrue(URIUtil.isCorrectURISplit("http://www.example.org/page#", "")); + assertTrue(URIUtil.isCorrectURISplit("http://www.example.org/page#", "1")); + assertTrue(URIUtil.isCorrectURISplit("http://www.example.org/page#", "1/2")); + assertTrue(URIUtil.isCorrectURISplit("http://www.example.org/page#", "1:2")); + assertTrue(URIUtil.isCorrectURISplit("http://www.example.org/page#", "1#2")); + assertTrue(URIUtil.isCorrectURISplit("http://www.example.org/page/", "")); + assertTrue(URIUtil.isCorrectURISplit("http://www.example.org/page/", "1")); + assertTrue(URIUtil.isCorrectURISplit("http://www.example.org/page/", "1:2")); + assertTrue(URIUtil.isCorrectURISplit("isbn:", "")); + assertTrue(URIUtil.isCorrectURISplit("isbn:", "1")); + + assertFalse(URIUtil.isCorrectURISplit("http://www.example.org/page#1#", "2")); + assertFalse(URIUtil.isCorrectURISplit("http://www.example.org/page", "#1")); + assertFalse(URIUtil.isCorrectURISplit("http://www.example.org/page/", "1/2")); + assertFalse(URIUtil.isCorrectURISplit("http://www.example.org/page/", "1#2")); + assertFalse(URIUtil.isCorrectURISplit("http://www.example.org/page", "2")); + assertFalse(URIUtil.isCorrectURISplit("http://www.example.org/page/1:", "2")); + assertFalse(URIUtil.isCorrectURISplit("isbn:", "1#2")); + assertFalse(URIUtil.isCorrectURISplit("isbn:", "1/2")); + assertFalse(URIUtil.isCorrectURISplit("isbn:", "1:2")); + + } + + @Test + public void testIsValidURIReference() + throws Exception + { + assertTrue(URIUtil.isValidURIReference("http://example.org/foo/bar/")); + assertTrue("whitespace should be allowed", URIUtil.isValidURIReference("http://example.org/foo/bar with a lot of space/")); + assertTrue("unwise chars should be allowed", URIUtil.isValidURIReference("http://example.org/foo/bar/unwise{}")); + assertTrue("query params in single quotes should be allowed", URIUtil.isValidURIReference("http://example.org/foo/bar?query='blah'")); + assertTrue("query params in double quotes should be allowed", URIUtil.isValidURIReference("http://example.org/foo/bar?query=\"blah\"&foo=bar")); + assertTrue("short simple urns should be allowed", URIUtil.isValidURIReference("urn:p1")); + assertTrue("Escaped special char should be allowed", + URIUtil.isValidURIReference("http://example.org/foo\\u00ea/bar/")); + assertTrue("fragment identifier should be allowed", URIUtil.isValidURIReference("http://example.org/foo/bar#fragment1")); + assertTrue("Unescaped special char should be allowed", + URIUtil.isValidURIReference("http://example.org/foo®/bar/")); + assertFalse("control char should not be allowed", + URIUtil.isValidURIReference("http://example.org/foo\u0001/bar/")); + assertFalse("relative uri should fail", URIUtil.isValidURIReference("foo/bar/")); + assertFalse("single column is not a valid uri", URIUtil.isValidURIReference(":")); + assertTrue("reserved char is allowed in non-conflicting spot", URIUtil.isValidURIReference("http://foo.com/b!ar/")); + assertFalse("reserved char should not be allowed in conflicting spot", URIUtil.isValidURIReference("http;://foo.com/bar/")); + } +} diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 00000000000..77b0ff67caa --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,115 @@ + + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j + 4.1.0-SNAPSHOT + + + rdf4j-core + pom + + + util + model + rio + queryresultio + query + queryalgebra + queryparser + queryrender + sail + repository + config + console + http + runtime + runtime-osgi + assembly + + + RDF4J Core + Core modules for RDF4J + + + + assembly + + + + org.apache.maven.plugins + maven-javadoc-plugin + + utf8 + 1.8 + true + ${javadoc.opts} + + + + create-aggregate-javadoc + false + package + + aggregate-jar + + + + RDF4J ${project.version} API + RDF4J ${project.version} API + + + Repository API + org.eclipse.rdf4j.repository* + + + RDF Model API + org.eclipse.rdf4j.model* + + + + Storage And Inference Layer (SAIL) API + org.eclipse.rdf4j.sail* + + + Rio: RDF Parsers and Writers + org.eclipse.rdf4j.rio* + + + + Query API and query engines + org.eclipse.rdf4j.query:org.eclipse.rdf4j.query.impl:org.eclipse.rdf4j.query.algebra*:org.eclipse.rdf4j.query.parser* + + + + Query Result Parsers and Writers + org.eclipse.rdf4j.query.resultio* + + + + RDF4J Web Client + org.eclipse.rdf4j.http.webclient* + + + + HTTP Protocol for Client/Server Communication + org.eclipse.rdf4j.http* + + + + + http://docs.oracle.com/javase/8/docs/api/ + + + + + + + + + + diff --git a/core/query/pom.xml b/core/query/pom.xml new file mode 100644 index 00000000000..128a1324a62 --- /dev/null +++ b/core/query/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-core + 4.1.0-SNAPSHOT + + + rdf4j-query + + RDF4J: Query + Query interfaces and implementations + + + + ${project.groupId} + rdf4j-model + ${project.version} + + + ${project.groupId} + rdf4j-rio-api + ${project.version} + + + + junit + junit + + + + + diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/AbstractTupleQueryResultHandler.java b/core/query/src/main/java/org/eclipse/rdf4j/query/AbstractTupleQueryResultHandler.java new file mode 100644 index 00000000000..3e3015c5ef6 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/AbstractTupleQueryResultHandler.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.util.List; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.TupleQueryResultHandler; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; + +/** + * Base class for {@link TupleQueryResultHandler}s with dummy implementations of + * all methods. This class is a useful superclass for classes that implement + * only one or two TupleQueryResultHandler methods. + */ +public abstract class AbstractTupleQueryResultHandler implements TupleQueryResultHandler { + + public void startQueryResult(List bindingNames) + throws TupleQueryResultHandlerException + { + } + + public void endQueryResult() + throws TupleQueryResultHandlerException + { + } + + public void handleSolution(BindingSet bindingSet) + throws TupleQueryResultHandlerException + { + } + + @Override + public void handleBoolean(boolean value) + throws QueryResultHandlerException + { + // This is a base class for handling tuple results + throw new UnsupportedOperationException("Cannot handle boolean results"); + } + + @Override + public void handleLinks(List linkUrls) + throws QueryResultHandlerException + { + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/Binding.java b/core/query/src/main/java/org/eclipse/rdf4j/query/Binding.java new file mode 100644 index 00000000000..6db2e7418dc --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/Binding.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.io.Serializable; + +import org.eclipse.rdf4j.model.Value; + +/** + * A named value binding. + */ +public interface Binding extends Serializable { + + /** + * Gets the name of the binding (e.g. the variable name). + * + * @return The name of the binding. + */ + public String getName(); + + /** + * Gets the value of the binding. The returned value is never equal to + * null, such a "binding" is considered to be unbound. + * + * @return The value of the binding, never null. + */ + public Value getValue(); + + /** + * Compares a binding object to another object. + * + * @param o + * The object to compare this binding to. + * @return true if the other object is an instance of + * {@link Binding} and both their names and values are equal, + * false otherwise. + */ + public boolean equals(Object o); + + /** + * The hash code of a binding is defined as the bit-wise XOR of the hash + * codes of its name and value: + * + *

    +	 * name.hashCode() ˆ value.hashCode()
    +	 * 
    . + * + * @return A hash code for the binding. + */ + public int hashCode(); +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/BindingSet.java b/core/query/src/main/java/org/eclipse/rdf4j/query/BindingSet.java new file mode 100644 index 00000000000..9fe9e08e9fd --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/BindingSet.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.rdf4j.model.Value; + +/** + * A BindingSet is a set of named value bindings, which is used a.o. to + * represent a single query solution. Values are indexed by name of the binding + * which typically corresponds to the names of the variables used in the + * projection of the orginal query. + */ +public interface BindingSet extends Iterable, Serializable { + + /** + * Creates an iterator over the bindings in this BindingSet. This only + * returns bindings with non-null values. An implementation is free to return + * the bindings in arbitrary order. + */ + public Iterator iterator(); + + /** + * Gets the names of the bindings in this BindingSet. + * + * @return A set of binding names. + */ + public Set getBindingNames(); + + /** + * Gets the binding with the specified name from this BindingSet. + * + * @param bindingName + * The name of the binding. + * @return The binding with the specified name, or null if there + * is no such binding in this BindingSet. + */ + public Binding getBinding(String bindingName); + + /** + * Checks whether this BindingSet has a binding with the specified name. + * + * @param bindingName + * The name of the binding. + * @return true if this BindingSet has a binding with the + * specified name, false otherwise. + */ + public boolean hasBinding(String bindingName); + + /** + * Gets the value of the binding with the specified name from this + * BindingSet. + * + * @param bindingName + * The name of the binding. + * @return The value of the binding with the specified name, or null + * if there is no such binding in this BindingSet. + */ + public Value getValue(String bindingName); + + /** + * Returns the number of bindings in this BindingSet. + * + * @return The number of bindings in this BindingSet. + */ + public int size(); + + /** + * Compares a BindingSet object to another object. + * + * @param o + * The object to compare this binding to. + * @return true if the other object is an instance of + * {@link BindingSet} and it contains the same set of bindings + * (disregarding order), false otherwise. + */ + public boolean equals(Object o); + + /** + * The hash code of a binding is defined as the bit-wise XOR of the hash + * codes of its bindings: + * + *
    +	 * int hashCode = 0;
    +	 * for (Binding binding : this) {
    +	 * 	hashCode ˆ= binding.hashCode();
    +	 * }
    +	 * 
    + * + * Note: the calculated hash code intentionally does not dependent on the + * order in which the bindings are iterated over. + * + * @return A hash code for the BindingSet. + */ + public int hashCode(); +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQuery.java b/core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQuery.java new file mode 100644 index 00000000000..74f5f485b92 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQuery.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * @author Arjohn Kampman + */ +public interface BooleanQuery extends Query { + + public boolean evaluate() + throws QueryEvaluationException; +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQueryResultHandler.java b/core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQueryResultHandler.java new file mode 100644 index 00000000000..15035cb0e89 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQueryResultHandler.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * An interface that indicates that this QueryResultHandler is capable of + * handling boolean results using the {@link #handleBoolean(boolean)} method. + * + * @since 2.7.0 + * @author Peter Ansell + */ +public interface BooleanQueryResultHandler extends QueryResultHandler { + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQueryResultHandlerException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQueryResultHandlerException.java new file mode 100644 index 00000000000..aaac243dcbc --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/BooleanQueryResultHandlerException.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * An exception that can be thrown by an BooleanQueryResultHandler when it + * encounters an unrecoverable error. + * + * @author Peter Ansell + * @since 2.7.0 + */ +public class BooleanQueryResultHandlerException extends QueryResultHandlerException { + + private static final long serialVersionUID = 8530574857852836665L; + + /** + * Creates a new BooleanQueryResultHandlerException. + * + * @param msg + * An error message. + */ + public BooleanQueryResultHandlerException(String msg) { + super(msg); + } + + /** + * Creates a new BooleanQueryResultHandlerException wrapping another + * exception. + * + * @param cause + * The cause of the exception. + */ + public BooleanQueryResultHandlerException(Throwable cause) { + super(cause); + } + + /** + * Creates a new BooleanQueryResultHandlerException wrapping another + * exception. + * + * @param msg + * An error message. + * @param cause + * The cause of the exception. + */ + public BooleanQueryResultHandlerException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/Dataset.java b/core/query/src/main/java/org/eclipse/rdf4j/query/Dataset.java new file mode 100644 index 00000000000..3457c32133f --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/Dataset.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.util.Set; + +import org.eclipse.rdf4j.model.IRI; + +/** + * Represents a dataset against which operations can be evaluated. A dataset + * consists of a default graph for read and using operations, which is the RDF merge of one or more + * graphs, a set of named graphs, and a single update graph for INSERT and + * DELETE. See SPARQL Query + * Language for RDF for more info. + * + * @author Simon Schenk + * @author Arjohn Kampman + * @author James Leigh + */ +public interface Dataset { + + /** + * Gets the default remove graph URIs of this dataset. An empty set indicates + * the the store's default behaviour should be used, if not otherwise + * indicated in the operation. + */ + public Set getDefaultRemoveGraphs(); + + /** + * Gets the default insert graph URI of this dataset. An null value indicates + * that the store's default behaviour should be used, if not otherwise + * indicated in the operation. + */ + public IRI getDefaultInsertGraph(); + + /** + * Gets the default graph URIs of this dataset. An empty default graph set + * and a non-empty named graph set indicates that the default graph is an + * empty graph. However, if both the default graph set and the named graph + * set are empty, that indicates that the store's default behaviour should be + * used. + */ + public Set getDefaultGraphs(); + + /** + * Gets the named graph URIs of this dataset. An empty named graph set and a + * non-empty default graph set indicates that there are no named graphs. + * However, if both the default graph set and the named graph set are empty, + * that indicates that the store's default behaviour should be used. + */ + public Set getNamedGraphs(); +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/GraphQuery.java b/core/query/src/main/java/org/eclipse/rdf4j/query/GraphQuery.java new file mode 100644 index 00000000000..34c6905c859 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/GraphQuery.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import org.eclipse.rdf4j.rio.RDFHandler; +import org.eclipse.rdf4j.rio.RDFHandlerException; + +public interface GraphQuery extends Query { + + public GraphQueryResult evaluate() + throws QueryEvaluationException; + + public void evaluate(RDFHandler handler) + throws QueryEvaluationException, RDFHandlerException; +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/GraphQueryResult.java b/core/query/src/main/java/org/eclipse/rdf4j/query/GraphQueryResult.java new file mode 100644 index 00000000000..4c59ed00715 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/GraphQueryResult.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.util.Map; + +import org.eclipse.rdf4j.model.Graph; +import org.eclipse.rdf4j.model.Statement; + +/** + * A representation of a query result as a sequence of {@link Statement} + * objects. Each query result consists of zero or more Statements and + * additionaly carries information about relevant namespace declarations. Note: + * take care to always close a GraphQueryResult after use to free any resources + * it keeps hold of. + * + * @author Jeen Broekstra + */ +public interface GraphQueryResult extends QueryResult { + + /** + * Retrieves relevant namespaces from the query result. + * + * @return a Map object containing (prefix, namespace) pairs. + * @throws QueryEvaluationException + */ + public Map getNamespaces() + throws QueryEvaluationException; + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/IncompatibleOperationException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/IncompatibleOperationException.java new file mode 100644 index 00000000000..243a347a225 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/IncompatibleOperationException.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * An exception indicating that a string could not be parsed into an operation + * of the expected type by the parser. + * + * @author jeen + */ +public class IncompatibleOperationException extends MalformedQueryException { + + /** + * + */ + private static final long serialVersionUID = -4926665776729656410L; + + public IncompatibleOperationException() { + super(); + } + + public IncompatibleOperationException(String message) { + super(message); + } + + public IncompatibleOperationException(Throwable t) { + super(t); + } + + public IncompatibleOperationException(String message, Throwable t) { + super(message, t); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/MalformedQueryException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/MalformedQueryException.java new file mode 100644 index 00000000000..0662edab2e3 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/MalformedQueryException.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import org.eclipse.rdf4j.OpenRDFException; + +/** + * An exception indicating that a query could not be processed by the query + * parser, typically due to syntax errors. + * + * @author jeen + * @author Herko ter Horst + */ +public class MalformedQueryException extends OpenRDFException { + + private static final long serialVersionUID = 1210214405486786142L; + + public MalformedQueryException() { + super(); + } + + public MalformedQueryException(String message) { + super(message); + } + + public MalformedQueryException(Throwable t) { + super(t); + } + + public MalformedQueryException(String message, Throwable t) { + super(message, t); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/Operation.java b/core/query/src/main/java/org/eclipse/rdf4j/query/Operation.java new file mode 100644 index 00000000000..25a26639c8b --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/Operation.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import org.eclipse.rdf4j.model.Value; + +/** + * An operation (e.g. a query or an update) on a repository that can be + * formulated in one of the supported query languages (for example SeRQL or + * SPARQL). It allows one to predefine bindings in the operation to be able to + * reuse the same operation with different bindings. + * + * @author Jeen + */ +public interface Operation { + + /** + * Binds the specified variable to the supplied value. Any value that was + * previously bound to the specified value will be overwritten. + * + * @param name + * The name of the variable that should be bound. + * @param value + * The (new) value for the specified variable. + */ + public void setBinding(String name, Value value); + + /** + * Removes a previously set binding on the supplied variable. Calling this + * method with an unbound variable name has no effect. + * + * @param name + * The name of the variable from which the binding is to be removed. + */ + public void removeBinding(String name); + + /** + * Removes all previously set bindings. + */ + public void clearBindings(); + + /** + * Retrieves the bindings that have been set on this operation. + * + * @return A (possibly empty) set of operation variable bindings. + * @see #setBinding(String, Value) + */ + public BindingSet getBindings(); + + /** + * Specifies the dataset against which to execute an operation, overriding + * any dataset that is specified in the operation itself. + */ + public void setDataset(Dataset dataset); + + /** + * Gets the dataset that has been set using {@link #setDataset(Dataset)}, if + * any. + */ + public Dataset getDataset(); + + /** + * Determine whether evaluation results of this operation should include + * inferred statements (if any inferred statements are present in the + * repository). The default setting is 'true'. + * + * @param includeInferred + * indicates whether inferred statements should be included in the + * result. + */ + public void setIncludeInferred(boolean includeInferred); + + /** + * Returns whether or not this operation will return inferred statements (if + * any are present in the repository). + * + * @return true if inferred statements will be returned, + * false otherwise. + */ + public boolean getIncludeInferred(); + + /** + * Specifies the maximum time that an operation is allowed to run. The + * operation will be interrupted when it exceeds the time limit. Any + * consecutive requests to fetch query results will result in + * {@link QueryInterruptedException}s or {@link UpdateInterruptedException}s + * (depending on whether the operation is a query or an update). + * + * @param maxQueryTime + * The maximum query time, measured in seconds. A negative or zero + * value indicates an unlimited execution time (which is the default). + * @since 2.8.0 + */ + public void setMaxExecutionTime(int maxExecTime); + + /** + * Returns the maximum operation execution time. + * + * @return The maximum operation execution time, measured in seconds. + * @see #setMaxExecutionTime(int) + * @since 2.8.0 + */ + public int getMaxExecutionTime(); + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/Query.java b/core/query/src/main/java/org/eclipse/rdf4j/query/Query.java new file mode 100644 index 00000000000..e857f9cc88b --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/Query.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * A query on a repository that can be formulated in one of the supported query + * languages (for example SeRQL or SPARQL). It allows one to predefine bindings + * in the query to be able to reuse the same query with different bindings. + * + * @author Arjohn Kampman + * @author jeen + */ +public interface Query extends Operation { + + /** + * Specifies the maximum time that a query is allowed to run. The query will + * be interrupted when it exceeds the time limit. Any consecutive requests to + * fetch query results will result in {@link QueryInterruptedException}s. + * + * @param maxQueryTime + * The maximum query time, measured in seconds. A negative or zero + * value indicates an unlimited query time (which is the default). + * @deprecated since 2.8.0. Use {@link Operation#setMaxExecutionTime(int)} + * instead. + */ + @Deprecated + public void setMaxQueryTime(int maxQueryTime); + + /** + * Returns the maximum query evaluation time. + * + * @return The maximum query evaluation time, measured in seconds. + * @see #setMaxQueryTime(int) + * @deprecated since 2.8.0. Use {@link Operation#getMaxExecutionTime()} + * instead. + */ + @Deprecated + public int getMaxQueryTime(); +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/QueryEvaluationException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryEvaluationException.java new file mode 100644 index 00000000000..d58215306e9 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryEvaluationException.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import org.eclipse.rdf4j.OpenRDFException; + +/** + * An exception indicating that the evaluation of a query failed. + * + * @author Arjohn Kampman + */ +public class QueryEvaluationException extends OpenRDFException { + + private static final long serialVersionUID = 602749602257031631L; + + public QueryEvaluationException() { + super(); + } + + /** + * Creates a new TupleQueryResultHandlerException. + * + * @param msg + * An error message. + */ + public QueryEvaluationException(String msg) { + super(msg); + } + + /** + * Creates a new TupleQueryResultHandlerException wrapping another exception. + * + * @param cause + * The cause of the exception. + */ + public QueryEvaluationException(Throwable cause) { + super(cause); + } + + /** + * Creates a new TupleQueryResultHandlerException wrapping another exception. + * + * @param msg + * An error message. + * @param cause + * The cause of the exception. + */ + public QueryEvaluationException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/QueryInterruptedException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryInterruptedException.java new file mode 100644 index 00000000000..9fa381789df --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryInterruptedException.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + + +/** + * An exception indicating that the evaluation of a query has been interrupted, + * for example because it took too long to complete. + * + * @author Arjohn Kampman + */ +public class QueryInterruptedException extends QueryEvaluationException { + + private static final long serialVersionUID = -1261311645990563247L; + + public QueryInterruptedException() { + super(); + } + + public QueryInterruptedException(String message) { + super(message); + } + + public QueryInterruptedException(String message, Throwable t) { + super(message, t); + } + + public QueryInterruptedException(Throwable t) { + super(t); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/QueryLanguage.java b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryLanguage.java new file mode 100644 index 00000000000..356e5563b87 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryLanguage.java @@ -0,0 +1,182 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +/** + * A type-safe enumeration for RDF query languages such as {@link #SPARQL} and + * {@link #SERQL SeRQL}. QueryLanguage objects are identified by their name, + * which is treated in as case-insensitive way. + */ +public class QueryLanguage { + + /*-----------* + * Constants * + *-----------*/ + + /** + * SeRQL (Sesame RDF Query Language) is a Sesame-specific query language for + * RDF, which predates SPARQL. + * + * @see The SeRQL user manual + */ + public static final QueryLanguage SERQL = new QueryLanguage("SeRQL"); + + /** + * SPARQL (Simple Protocol and RDF Query Language) is a W3C Recommendation + * for querying and updating RDF data. + * + * @see SPARQL 1.1 + * Overview + */ + public static final QueryLanguage SPARQL = new QueryLanguage("SPARQL"); + + /** + * SeRQO (Sesame RDF Query Language - Objects) is a Sesame-specific query + * language using a syntax suited less for human editing but for easy + * transfer over the wire. + * + * @deprecated since 4.0. This language is no longer actively supported. + */ + @Deprecated + public static final QueryLanguage SERQO = new QueryLanguage("SeRQO"); + + /*------------------* + * Static variables * + *------------------*/ + + /** + * List of known query languages. + */ + private static List QUERY_LANGUAGES = new ArrayList(4); + + /*--------------------* + * Static initializer * + *--------------------*/ + + static { + register(SERQL); + register(SPARQL); + register(SERQO); + } + + /*----------------* + * Static methods * + *----------------*/ + + /** + * Returns all known/registered query languages. + */ + public static Collection values() { + return Collections.unmodifiableList(QUERY_LANGUAGES); + } + + /** + * Registers the specified query language. + * + * @param name + * The name of the query language, e.g. "SPARQL". + */ + public static QueryLanguage register(String name) { + QueryLanguage ql = new QueryLanguage(name); + register(ql); + return ql; + } + + /** + * Registers the specified query language. + */ + public static void register(QueryLanguage ql) { + QUERY_LANGUAGES.add(ql); + } + + /** + * Returns the query language whose name matches the specified name. + * + * @param qlName + * A query language name. + * @return The query language whose name matches the specified name, or + * null if there is no such query language. + */ + public static QueryLanguage valueOf(String qlName) { + for (QueryLanguage ql : QUERY_LANGUAGES) { + if (ql.getName().equalsIgnoreCase(qlName)) { + return ql; + } + } + + return null; + } + + /*-----------* + * Variables * + *-----------*/ + + /** + * The query language's name. + */ + private String name; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new QueryLanguage object. + * + * @param name + * The (case-insensitive) name of the query language, e.g. "SPARQL". + */ + public QueryLanguage(String name) { + assert name != null : "name must not be null"; + + this.name = name; + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the name of this query language. + * + * @return A human-readable format name, e.g. "SPARQL". + */ + public String getName() { + return name; + } + + public boolean hasName(String name) { + return this.name.equalsIgnoreCase(name); + } + + @Override + public boolean equals(Object other) { + if (other instanceof QueryLanguage) { + QueryLanguage o = (QueryLanguage)other; + return this.hasName(o.getName()); + } + + return false; + } + + @Override + public int hashCode() { + return getName().toUpperCase(Locale.ENGLISH).hashCode(); + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResult.java b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResult.java new file mode 100644 index 00000000000..700d53470d6 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResult.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; + +/** + * Super type of all query result types (TupleQueryResult, GraphQueryResult, + * etc.). + * + * @author Jeen Broekstra + * @author Arjohn Kampman + */ +public interface QueryResult extends CloseableIteration { + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultHandler.java b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultHandler.java new file mode 100644 index 00000000000..9b719ad3ed0 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultHandler.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.util.List; + +/** + * The super class of all handlers for processing query results. + *

    + * This interface contains methods for optionally processing both boolean and + * tuple results sets simultaneously, but there are no guarantees that an + * implementation will be able to process these values together. If a method is + * not supported then an {@link UnsupportedOperationException} will be thrown to + * indicate this failure. This failure may be prevented by checking for whether + * the class implements {@link BooleanQueryResultHandler} or + * {@link TupleQueryResultHandler}, for boolean and tuple results support + * respectively. + *

    + * If both boolean and tuple results are supported but they are not able to to + * be processed simultaneously, then a checked exception, either + * {@link BooleanQueryResultHandlerException} or + * {@link TupleQueryResultHandlerException}, will be thrown to indicate this + * failure when the relevant methods are called. + * + * @since 2.7.0 + * @author Peter Ansell + */ +public interface QueryResultHandler { + + /** + * Handles the specified boolean value. + * + * @param value + * The boolean value to handle. + * @throws QueryResultHandlerException + * If there was an error during the handling of this value. This + * exception may be thrown if the {@link #startQueryResult(List)}, + * {@link #handleSolution(BindingSet)} or {@link #endQueryResult()} + * methods were called before this method was called, and the handler + * cannot process both boolean and tuple results simultaneously. + * @throws UnsupportedOperationException + * If this method is not supported + * @since 2.7.0 + */ + void handleBoolean(boolean value) + throws QueryResultHandlerException; + + /** + * Handles the links elements which are present in SPARQL Results JSON and + * SPARQL Results XML documents in the header. + *

    + * NOTE: If the format does not support links, it must silently ignore a call + * to this method. + *

    + * An accumulating handler should accumulate these links. + * + * @see "link" + * @param linkUrls + * The URLs of the links to handle. + * @throws QueryResultHandlerException + * If there was an error handling the set of link URLs. This error is + * not thrown in cases where links are not supported. + * @since 2.7.0 + */ + void handleLinks(List linkUrls) + throws QueryResultHandlerException; + + /** + * Indicates the start of a sequence of Solutions. The supplied bindingNames + * are an indication of the values that are in the Solutions. For example, a + * SeRQL query like select X, Y from {X} P {Y} will have binding + * names X and Y. + * + * @param bindingNames + * An ordered set of binding names. + * @throws TupleQueryResultHandlerException + * If there was an error during the starting of the query result + * handler. This exception may be thrown if the + * {@link #handleBoolean(boolean)} method was called before this + * method and the handler cannot process both boolean and tuple + * results simultaneously. + * @throws UnsupportedOperationException + * If this method is not supported + * @throws IllegalStateException + * If the {@link #handleSolution(BindingSet)} or + * {@link #endQueryResult()} methods were called before this method + * and the handler cannot process multiple sets of tuple results + * simultaneously. + */ + public void startQueryResult(List bindingNames) + throws TupleQueryResultHandlerException; + + /** + * Indicates the end of a sequence of solutions. + * + * @throws TupleQueryResultHandlerException + * If there was an error during the ending of the query result + * handler. This exception may be thrown if the + * {@link #handleBoolean(boolean)} method was called before this + * method and the handler cannot process both boolean and tuple + * results simultaneously. + * @throws UnsupportedOperationException + * If this method is not supported + * @throws IllegalStateException + * If the {@link #endQueryResult()} was previously called for this + * handler or {@link #startQueryResult(List)} was NOT called before + * this method. + */ + public void endQueryResult() + throws TupleQueryResultHandlerException; + + /** + * Handles a solution. + * + * @param bindingSet + * A single set of tuple results, with binding names bound to values. + * Each of the binding names in the solution must have previously been + * registered with the {@link #startQueryResult(List)} method. + * @throws TupleQueryResultHandlerException + * If there was an error during the handling of the query solution. + * This exception may be thrown if the + * {@link #handleBoolean(boolean)} method was called before this + * method and the handler cannot process both boolean and tuple + * results simultaneously. + * @throws UnsupportedOperationException + * If this method is not supported + * @throws IllegalStateException + * If the {@link #endQueryResult()} method was called before this + * method or {@link #startQueryResult(List)} was NOT called before + * this method. + */ + public void handleSolution(BindingSet bindingSet) + throws TupleQueryResultHandlerException; +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultHandlerException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultHandlerException.java new file mode 100644 index 00000000000..b5bead488ef --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultHandlerException.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import org.eclipse.rdf4j.OpenRDFException; + +/** + * The super class of exceptions originating from {@link QueryResultHandler} + * implementations. + * + * @author Peter Ansell + * @since 2.7.0 + */ +public class QueryResultHandlerException extends OpenRDFException { + + private static final long serialVersionUID = 5096811224670124398L; + + /** + * Creates a new QueryResultHandlerException. + * + * @param msg + * An error message. + */ + public QueryResultHandlerException(String msg) { + super(msg); + } + + /** + * Creates a new QueryResultHandlerException wrapping another exception. + * + * @param t + * The cause of the exception. + */ + public QueryResultHandlerException(Throwable t) { + super(t); + } + + /** + * Creates a new QueryResultHandlerException wrapping another exception. + * + * @param msg + * An error message. + * @param t + * The cause of the exception. + */ + public QueryResultHandlerException(String msg, Throwable t) { + super(msg, t); + } + +} \ No newline at end of file diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultUtil.java b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultUtil.java new file mode 100644 index 00000000000..f05d8a50890 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResultUtil.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * @deprecated since 2.7.0. Use {@link QueryResults} instead. + * @author Jeen Broekstra + */ +@Deprecated +public class QueryResultUtil extends QueryResults { + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResults.java b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResults.java new file mode 100644 index 00000000000..bfeef67f38f --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/QueryResults.java @@ -0,0 +1,536 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.DistinctIteration; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.util.Models; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.rio.RDFHandler; +import org.eclipse.rdf4j.rio.RDFHandlerException; + +/** + * Utility methods related to query results. + * + * @since 2.7.0 + * @author Jeen Broekstra + */ +public class QueryResults extends Iterations { + + /** + * Get a {@link Model} containing all elements obtained from the specified + * query result. + * + * @since 2.7.0 + * @param iteration + * the source iteration to get the statements from. This can be a + * {@link GraphQueryResult}, a {@link RepositoryResult}, or + * any other instance of {@link CloseableIteration} + * @return a {@link Model} containing all statements obtained from the + * specified source iteration. + */ + public static Model asModel(CloseableIteration iteration) + throws QueryEvaluationException + { + Model model = new LinkedHashModel(); + addAll(iteration, model); + return model; + } + + /** + * Returns a single element from the query result. The QueryResult is + * automatically closed by this method. + * + * @since 2.7.0 + * @return a single query result element. + * @throws QueryEvaluationException + */ + public static Statement singleResult(GraphQueryResult result) + throws QueryEvaluationException + { + Statement singleResult = null; + if (result.hasNext()) { + singleResult = result.next(); + } + result.close(); + return singleResult; + } + + /** + * Returns a single element from the query result. The QueryResult is + * automatically closed by this method. + * + * @since 2.7.0 + * @return a single query result element. + * @throws QueryEvaluationException + */ + public static BindingSet singleResult(TupleQueryResult result) + throws QueryEvaluationException + { + BindingSet singleResult = null; + if (result.hasNext()) { + singleResult = result.next(); + } + result.close(); + return singleResult; + } + + /** + * Returns a {@link GraphQueryResult} that filters out any duplicate + * solutions from the supplied queryResult. + * + * @param queryResult + * a queryResult containing possible duplicate statements. + * @return a {@link GraphQueryResult} with any duplicates filtered out. + * @since 2.7.0 + */ + public static GraphQueryResult distinctResults(GraphQueryResult queryResult) { + return new GraphQueryResultFilter(queryResult); + } + + /** + * Returns a {@link TupleQueryResult} that filters out any duplicate + * solutions from the supplied queryResult. + * + * @param queryResult + * a queryResult containing possible duplicate solutions. + * @return a {@link TupleQueryResult} with any duplicates filtered out. + * @since 2.7.0 + */ + public static TupleQueryResult distinctResults(TupleQueryResult queryResult) { + return new TupleQueryResultFilter(queryResult); + } + + /** + * Reports a tuple query result to a {@link TupleQueryResultHandler}.
    + * The {@link TupleQueryResult#close()} method will always be called before + * this method returns.
    + * If there is an exception generated by the TupleQueryResult, + * {@link QueryResultHandler#endQueryResult()} will not be called. + * + * @param tqr + * The query result to report. + * @param handler + * The handler to report the query result to. + * @throws TupleQueryResultHandlerException + * If such an exception is thrown by the used query result writer. + */ + public static void report(TupleQueryResult tqr, QueryResultHandler handler) + throws TupleQueryResultHandlerException, QueryEvaluationException + { + try { + handler.startQueryResult(tqr.getBindingNames()); + + while (tqr.hasNext()) { + BindingSet bindingSet = tqr.next(); + handler.handleSolution(bindingSet); + } + } + finally { + tqr.close(); + } + handler.endQueryResult(); + } + + /** + * Reports a graph query result to an {@link RDFHandler}.
    + * The {@link GraphQueryResult#close()} method will always be called before + * this method returns.
    + * If there is an exception generated by the GraphQueryResult, + * {@link RDFHandler#endRDF()} will not be called. + * + * @param gqr + * The query result to report. + * @param rdfHandler + * The handler to report the query result to. + * @throws RDFHandlerException + * If such an exception is thrown by the used RDF writer. + * @throws QueryEvaluationException + */ + public static void report(GraphQueryResult gqr, RDFHandler rdfHandler) + throws RDFHandlerException, QueryEvaluationException + { + try { + rdfHandler.startRDF(); + + for (Map.Entry entry : gqr.getNamespaces().entrySet()) { + String prefix = entry.getKey(); + String namespace = entry.getValue(); + rdfHandler.handleNamespace(prefix, namespace); + } + + while (gqr.hasNext()) { + Statement st = gqr.next(); + rdfHandler.handleStatement(st); + } + } + finally { + gqr.close(); + } + rdfHandler.endRDF(); + } + + /** + * Compares two tuple query results and returns {@code true} if they are + * equal. Tuple query results are equal if they contain the same set of + * {@link BindingSet}s and have the same headers. Blank nodes identifiers are + * not relevant for equality, they are matched by trying to find compatible + * mappings between BindingSets. Note that the method consumes both query + * results fully. + * + * @param tqr1 + * the first {@link TupleQueryResult} to compare. + * @param tqr2 + * the second {@link TupleQueryResult} to compare. + * @throws QueryEvaluationException + */ + public static boolean equals(TupleQueryResult tqr1, TupleQueryResult tqr2) + throws QueryEvaluationException + { + List list1 = Iterations.asList(tqr1); + List list2 = Iterations.asList(tqr2); + + // Compare the number of statements in both sets + if (list1.size() != list2.size()) { + return false; + } + + return matchBindingSets(list1, list2); + } + + public static boolean isSubset(TupleQueryResult tqr1, TupleQueryResult tqr2) + throws QueryEvaluationException + { + List list1 = Iterations.asList(tqr1); + List list2 = Iterations.asList(tqr2); + + // Compare the number of statements in both sets + if (list1.size() > list2.size()) { + return false; + } + + return matchBindingSets(list1, list2); + } + + /** + * Compares two graph query results and returns {@code true} if they are + * equal. Two graph query results are considered equal if they are isomorphic + * graphs. Note that the method consumes both query results fully. + * + * @param result1 + * the first query result to compare + * @param result2 + * the second query result to compare. + * @return {@code true} iff the supplied graph query results are isomorphic + * graphs, {@code false} otherwise. + * @throws QueryEvaluationException + * @see {@link Models#isomorphic(Iterable, Iterable)} + */ + public static boolean equals(GraphQueryResult result1, GraphQueryResult result2) + throws QueryEvaluationException + { + Set graph1 = Iterations.asSet(result1); + Set graph2 = Iterations.asSet(result2); + + return Models.isomorphic(graph1, graph2); + } + + private static boolean matchBindingSets(List queryResult1, + Iterable queryResult2) + { + return matchBindingSets(queryResult1, queryResult2, new HashMap(), 0); + } + + /** + * A recursive method for finding a complete mapping between blank nodes in + * queryResult1 and blank nodes in queryResult2. The algorithm does a + * depth-first search trying to establish a mapping for each blank node + * occurring in queryResult1. + * + * @return true if a complete mapping has been found, false otherwise. + */ + private static boolean matchBindingSets(List queryResult1, + Iterable queryResult2, Map bNodeMapping, int idx) + { + boolean result = false; + + if (idx < queryResult1.size()) { + BindingSet bs1 = queryResult1.get(idx); + + List matchingBindingSets = findMatchingBindingSets(bs1, queryResult2, bNodeMapping); + + for (BindingSet bs2 : matchingBindingSets) { + // Map bNodes in bs1 to bNodes in bs2 + Map newBNodeMapping = new HashMap(bNodeMapping); + + for (Binding binding : bs1) { + if (binding.getValue() instanceof BNode) { + newBNodeMapping.put((BNode)binding.getValue(), (BNode)bs2.getValue(binding.getName())); + } + } + + // FIXME: this recursive implementation has a high risk of + // triggering a stack overflow + + // Enter recursion + result = matchBindingSets(queryResult1, queryResult2, newBNodeMapping, idx + 1); + + if (result == true) { + // models match, look no further + break; + } + } + } + else { + // All statements have been mapped successfully + result = true; + } + + return result; + } + + private static List findMatchingBindingSets(BindingSet st, + Iterable model, Map bNodeMapping) + { + List result = new ArrayList(); + + for (BindingSet modelSt : model) { + if (bindingSetsMatch(st, modelSt, bNodeMapping)) { + // All components possibly match + result.add(modelSt); + } + } + + return result; + } + + private static boolean bindingSetsMatch(BindingSet bs1, BindingSet bs2, Map bNodeMapping) { + + if (bs1.size() != bs2.size()) { + return false; + } + + for (Binding binding1 : bs1) { + Value value1 = binding1.getValue(); + Value value2 = bs2.getValue(binding1.getName()); + + if (value1 instanceof BNode && value2 instanceof BNode) { + BNode mappedBNode = bNodeMapping.get(value1); + + if (mappedBNode != null) { + // bNode 'value1' was already mapped to some other bNode + if (!value2.equals(mappedBNode)) { + // 'value1' and 'value2' do not match + return false; + } + } + else { + // 'value1' was not yet mapped, we need to check if 'value2' is a + // possible mapping candidate + if (bNodeMapping.containsValue(value2)) { + // 'value2' is already mapped to some other value. + return false; + } + } + } + else { + // values are not (both) bNodes + if (value1 instanceof Literal && value2 instanceof Literal) { + // do literal value-based comparison for supported datatypes + Literal leftLit = (Literal)value1; + Literal rightLit = (Literal)value2; + + IRI dt1 = leftLit.getDatatype(); + IRI dt2 = rightLit.getDatatype(); + + if (dt1 != null && dt2 != null && dt1.equals(dt2) + && XMLDatatypeUtil.isValidValue(leftLit.getLabel(), dt1) + && XMLDatatypeUtil.isValidValue(rightLit.getLabel(), dt2)) + { + Integer compareResult = null; + if (dt1.equals(XMLSchema.DOUBLE)) { + compareResult = Double.compare(leftLit.doubleValue(), rightLit.doubleValue()); + } + else if (dt1.equals(XMLSchema.FLOAT)) { + compareResult = Float.compare(leftLit.floatValue(), rightLit.floatValue()); + } + else if (dt1.equals(XMLSchema.DECIMAL)) { + compareResult = leftLit.decimalValue().compareTo(rightLit.decimalValue()); + } + else if (XMLDatatypeUtil.isIntegerDatatype(dt1)) { + compareResult = leftLit.integerValue().compareTo(rightLit.integerValue()); + } + else if (dt1.equals(XMLSchema.BOOLEAN)) { + Boolean leftBool = Boolean.valueOf(leftLit.booleanValue()); + Boolean rightBool = Boolean.valueOf(rightLit.booleanValue()); + compareResult = leftBool.compareTo(rightBool); + } + else if (XMLDatatypeUtil.isCalendarDatatype(dt1)) { + XMLGregorianCalendar left = leftLit.calendarValue(); + XMLGregorianCalendar right = rightLit.calendarValue(); + + compareResult = left.compare(right); + } + + if (compareResult != null) { + if (compareResult.intValue() != 0) { + return false; + } + } + else if (!value1.equals(value2)) { + return false; + } + } + else if (!value1.equals(value2)) { + return false; + } + } + else if (!value1.equals(value2)) { + return false; + } + } + } + + return true; + } + + /** + * Check whether two {@link BindingSet}s are compatible. Two binding sets are + * compatible if they have equal values for each binding name that occurs in + * both binding sets. + */ + public static boolean bindingSetsCompatible(BindingSet bs1, BindingSet bs2) { + Set sharedBindings = new HashSet(bs1.getBindingNames()); + sharedBindings.retainAll(bs2.getBindingNames()); + + for (String bindingName : sharedBindings) { + Value value1 = bs1.getValue(bindingName); + Value value2 = bs2.getValue(bindingName); + + if (!value1.equals(value2)) { + return false; + } + } + + return true; + } + + private static class GraphQueryResultFilter implements GraphQueryResult { + + private DistinctIteration filter; + + private GraphQueryResult unfiltered; + + public GraphQueryResultFilter(GraphQueryResult wrappedResult) { + this.filter = new DistinctIteration(wrappedResult); + this.unfiltered = wrappedResult; + } + + @Override + public void close() + throws QueryEvaluationException + { + filter.close(); + } + + @Override + public boolean hasNext() + throws QueryEvaluationException + { + return filter.hasNext(); + } + + @Override + public Statement next() + throws QueryEvaluationException + { + return filter.next(); + } + + @Override + public void remove() + throws QueryEvaluationException + { + filter.remove(); + } + + @Override + public Map getNamespaces() + throws QueryEvaluationException + { + return unfiltered.getNamespaces(); + } + } + + private static class TupleQueryResultFilter implements TupleQueryResult { + + private DistinctIteration filter; + + private TupleQueryResult unfiltered; + + public TupleQueryResultFilter(TupleQueryResult wrappedResult) { + this.filter = new DistinctIteration(wrappedResult); + this.unfiltered = wrappedResult; + } + + @Override + public void close() + throws QueryEvaluationException + { + filter.close(); + } + + @Override + public boolean hasNext() + throws QueryEvaluationException + { + return filter.hasNext(); + } + + @Override + public BindingSet next() + throws QueryEvaluationException + { + return filter.next(); + } + + @Override + public void remove() + throws QueryEvaluationException + { + filter.remove(); + } + + @Override + public List getBindingNames() + throws QueryEvaluationException + { + return unfiltered.getBindingNames(); + } + + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQuery.java b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQuery.java new file mode 100644 index 00000000000..2a17f01716e --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQuery.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +public interface TupleQuery extends Query { + + public TupleQueryResult evaluate() + throws QueryEvaluationException; + + public void evaluate(TupleQueryResultHandler handler) + throws QueryEvaluationException, TupleQueryResultHandlerException; +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResult.java b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResult.java new file mode 100644 index 00000000000..8b4dabac574 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResult.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.util.List; + +/** + * A representation of a variable-binding query result as a sequence of + * {@link BindingSet} objects. Each query result consists of zero or more + * solutions, each of which represents a single query solution as a set of + * bindings. Note: take care to always close a TupleQueryResult after use to + * free any resources it keeps hold of. + * + * @author jeen + */ +public interface TupleQueryResult extends QueryResult { + + /** + * Gets the names of the bindings, in order of projection. + * + * @return The binding names, in order of projection. + * @throws QueryEvaluationException + */ + public List getBindingNames() + throws QueryEvaluationException; +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandler.java b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandler.java new file mode 100644 index 00000000000..99672262b64 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandler.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import java.util.List; + +/** + * An interface defining methods related to handling sequences of Solutions. + *

    + * Instances of this interface are capable of handling tuple results using the + * {@link #startQueryResult(List)}, {@link #handleSolution(BindingSet)} and + * {@link #endQueryResult()} methods. + */ +public interface TupleQueryResultHandler extends QueryResultHandler { + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandlerBase.java b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandlerBase.java new file mode 100644 index 00000000000..56aa9ed6520 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandlerBase.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * @deprecated since 4.0. Use {@link AbstractTupleQueryResultHandler} instead. + * @author Jeen Broekstra + */ +@Deprecated +public class TupleQueryResultHandlerBase extends AbstractTupleQueryResultHandler { + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandlerException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandlerException.java new file mode 100644 index 00000000000..7d00e3adab2 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/TupleQueryResultHandlerException.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * An exception that can be thrown by an TupleQueryResultHandler when it + * encounters an unrecoverable error. If an exception is associated with the + * error then this exception can be wrapped in a TupleHandlerException and can + * later be retrieved from it when the TupleHandlerException is caught using the + * getCause(). + */ +public class TupleQueryResultHandlerException extends QueryResultHandlerException { + + private static final long serialVersionUID = 8530574857852836665L; + + /** + * Creates a new TupleQueryResultHandlerException. + * + * @param msg + * An error message. + */ + public TupleQueryResultHandlerException(String msg) { + super(msg); + } + + /** + * Creates a new TupleQueryResultHandlerException wrapping another exception. + * + * @param cause + * The cause of the exception. + */ + public TupleQueryResultHandlerException(Throwable cause) { + super(cause); + } + + /** + * Creates a new TupleQueryResultHandlerException wrapping another exception. + * + * @param msg + * An error message. + * @param cause + * The cause of the exception. + */ + public TupleQueryResultHandlerException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/UnsupportedQueryLanguageException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/UnsupportedQueryLanguageException.java new file mode 100644 index 00000000000..f4e66a274a7 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/UnsupportedQueryLanguageException.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * A RuntimeException indicating that a specific query language is not supported. A typical cause + * of this exception is that the class library for the specified query language is not present + * in the classpath. + */ +public class UnsupportedQueryLanguageException extends RuntimeException { + + private static final long serialVersionUID = -2709196386078518696L; + + /** + * Creates a new UnsupportedRDFormatException. + * + * @param msg + * An error message. + */ + public UnsupportedQueryLanguageException(String msg) { + super(msg); + } + + /** + * Creates a new UnsupportedRDFormatException. + * + * @param cause + * The cause of the exception. + */ + public UnsupportedQueryLanguageException(Throwable cause) { + super(cause); + } + + /** + * Creates a new UnsupportedRDFormatException wrapping another exception. + * + * @param msg + * An error message. + * @param cause + * The cause of the exception. + */ + public UnsupportedQueryLanguageException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/Update.java b/core/query/src/main/java/org/eclipse/rdf4j/query/Update.java new file mode 100644 index 00000000000..f120a66abd9 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/Update.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +/** + * An update operation on a repository that can be formulated in one of the + * supported query languages (for example SPARQL). + * + * @author Jeen + */ +public interface Update extends Operation { + + /** + * Execute this update on the repository. + * + * @throws UpdateExecutionException + * if the update could not be successfully completed. + */ + void execute() + throws UpdateExecutionException; + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/UpdateExecutionException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/UpdateExecutionException.java new file mode 100644 index 00000000000..6d2dceee714 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/UpdateExecutionException.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import org.eclipse.rdf4j.OpenRDFException; + +/** + * An exception indicating that the execution of an update failed. + * + * @author Jeen + */ +public class UpdateExecutionException extends OpenRDFException { + + /** + * + */ + private static final long serialVersionUID = 7969399526232927434L; + + public UpdateExecutionException() { + super(); + } + + /** + * Creates a new UpdateExecutionException. + * + * @param msg + * An error message. + */ + public UpdateExecutionException(String msg) { + super(msg); + } + + /** + * Creates a new {@link UpdateExecutionException} wrapping another exception. + * + * @param cause + * the cause of the exception + */ + public UpdateExecutionException(Throwable cause) { + super(cause); + } + + /** + * Creates a new {@link UpdateExecutionException} wrapping another exception. + * + * @param msg + * and error message. + * @param cause + * the cause of the exception + */ + public UpdateExecutionException(String msg, Throwable cause) { + super(msg, cause); + } + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestBooleanParser.java b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestBooleanParser.java new file mode 100644 index 00000000000..61553b4660e --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestBooleanParser.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.dawg; + +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.BOOLEAN; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.RESULTSET; + +import org.eclipse.rdf4j.model.Graph; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.impl.GraphImpl; +import org.eclipse.rdf4j.model.util.GraphUtil; +import org.eclipse.rdf4j.model.util.GraphUtilException; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.helpers.AbstractRDFHandler; + +/** + * @author Arjohn Kampman + */ +public class DAWGTestBooleanParser extends AbstractRDFHandler { + + /*-----------* + * Variables * + *-----------*/ + + private Graph graph = new GraphImpl(); + + private boolean value; + + /*--------------* + * Constructors * + *--------------*/ + + public DAWGTestBooleanParser() { + } + + /*---------* + * Methods * + *---------*/ + + public boolean getValue() { + return value; + } + + @Override + public void startRDF() + throws RDFHandlerException + { + graph.clear(); + } + + @Override + public void handleStatement(Statement st) + throws RDFHandlerException + { + graph.add(st); + } + + @Override + public void endRDF() + throws RDFHandlerException + { + try { + Resource resultSetNode = GraphUtil.getUniqueSubject(graph, RDF.TYPE, RESULTSET); + Literal booleanLit = GraphUtil.getUniqueObjectLiteral(graph, resultSetNode, BOOLEAN); + + if (booleanLit.equals(DAWGTestResultSetSchema.TRUE)) { + value = true; + } + else if (booleanLit.equals(DAWGTestResultSetSchema.FALSE)) { + value = false; + } + else { + throw new RDFHandlerException("Invalid boolean value: " + booleanLit); + } + } + catch (GraphUtilException e) { + throw new RDFHandlerException(e.getMessage(), e); + } + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetParseException.java b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetParseException.java new file mode 100644 index 00000000000..b3f5c12cfbd --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetParseException.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.dawg; + +import org.eclipse.rdf4j.OpenRDFException; + +/** + * An exception that is thrown to indicate that the parsing of a DAWG Test + * Result Set graph failed due to an incompatible or incomplete graph. + */ +public class DAWGTestResultSetParseException extends OpenRDFException { + + private static final long serialVersionUID = -8655777672973690037L; + + /** + * Creates a new DAWGTestResultSetParseException. + * + * @param msg + * An error message. + */ + public DAWGTestResultSetParseException(String msg) { + super(msg); + } + + /** + * Creates a new DAWGTestResultSetParseException wrapping another exception. + * + * @param cause + * The cause of the exception. + */ + public DAWGTestResultSetParseException(Throwable cause) { + super(cause); + } + + /** + * Creates a new DAWGTestResultSetParseException wrapping another exception. + * + * @param msg + * An error message. + * @param cause + * The cause of the exception. + */ + public DAWGTestResultSetParseException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetParser.java b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetParser.java new file mode 100644 index 00000000000..dcf7658b689 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetParser.java @@ -0,0 +1,170 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.dawg; + +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.BINDING; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.RESULTSET; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.RESULTVARIABLE; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.SOLUTION; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.VALUE; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.VARIABLE; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.rdf4j.model.Graph; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.impl.GraphImpl; +import org.eclipse.rdf4j.model.util.GraphUtil; +import org.eclipse.rdf4j.model.util.GraphUtilException; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.TupleQueryResultHandler; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; +import org.eclipse.rdf4j.query.impl.MapBindingSet; +import org.eclipse.rdf4j.query.impl.SimpleBinding; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.helpers.AbstractRDFHandler; + +/** + * @author Arjohn Kampman + */ +public class DAWGTestResultSetParser extends AbstractRDFHandler { + + /*-----------* + * Constants * + *-----------*/ + + /** + * RDFHandler to report the generated statements to. + */ + private final TupleQueryResultHandler tqrHandler; + + /*-----------* + * Variables * + *-----------*/ + + private Graph graph = new GraphImpl(); + + /*--------------* + * Constructors * + *--------------*/ + + public DAWGTestResultSetParser(TupleQueryResultHandler tqrHandler) { + this.tqrHandler = tqrHandler; + } + + /*---------* + * Methods * + *---------*/ + + @Override + public void startRDF() + throws RDFHandlerException + { + graph.clear(); + } + + @Override + public void handleStatement(Statement st) + throws RDFHandlerException + { + graph.add(st); + } + + @Override + public void endRDF() + throws RDFHandlerException + { + try { + Resource resultSetNode = GraphUtil.getUniqueSubject(graph, RDF.TYPE, RESULTSET); + + List bindingNames = getBindingNames(resultSetNode); + tqrHandler.startQueryResult(bindingNames); + + Iterator solIter = GraphUtil.getObjectIterator(graph, resultSetNode, SOLUTION); + while (solIter.hasNext()) { + Value solutionNode = solIter.next(); + + if (solutionNode instanceof Resource) { + reportSolution((Resource)solutionNode, bindingNames); + } + else { + throw new RDFHandlerException("Value for " + SOLUTION + " is not a resource: " + solutionNode); + } + } + + tqrHandler.endQueryResult(); + } + catch (GraphUtilException e) { + throw new RDFHandlerException(e.getMessage(), e); + } + catch (TupleQueryResultHandlerException e) { + throw new RDFHandlerException(e.getMessage(), e); + } + } + + private List getBindingNames(Resource resultSetNode) + throws RDFHandlerException + { + List bindingNames = new ArrayList(16); + + Iterator varIter = GraphUtil.getObjectIterator(graph, resultSetNode, RESULTVARIABLE); + + while (varIter.hasNext()) { + Value varName = varIter.next(); + + if (varName instanceof Literal) { + bindingNames.add(((Literal)varName).getLabel()); + } + else { + throw new RDFHandlerException("Value for " + RESULTVARIABLE + " is not a literal: " + varName); + } + } + + return bindingNames; + } + + private void reportSolution(Resource solutionNode, List bindingNames) + throws RDFHandlerException, GraphUtilException + { + MapBindingSet bindingSet = new MapBindingSet(bindingNames.size()); + + Iterator bindingIter = GraphUtil.getObjectIterator(graph, solutionNode, BINDING); + while (bindingIter.hasNext()) { + Value bindingNode = bindingIter.next(); + + if (bindingNode instanceof Resource) { + Binding binding = getBinding((Resource)bindingNode); + bindingSet.addBinding(binding); + } + else { + throw new RDFHandlerException("Value for " + BINDING + " is not a resource: " + bindingNode); + } + } + + try { + tqrHandler.handleSolution(bindingSet); + } + catch (TupleQueryResultHandlerException e) { + throw new RDFHandlerException(e.getMessage(), e); + } + } + + private Binding getBinding(Resource bindingNode) + throws GraphUtilException + { + Literal name = GraphUtil.getUniqueObjectLiteral(graph, bindingNode, VARIABLE); + Value value = GraphUtil.getUniqueObject(graph, bindingNode, VALUE); + return new SimpleBinding(name.getLabel(), value); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetSchema.java b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetSchema.java new file mode 100644 index 00000000000..9d33a28a762 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetSchema.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.dawg; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; + +/** + * @author Arjohn Kampman + */ +public class DAWGTestResultSetSchema { + + public static final String NAMESPACE = "http://www.w3.org/2001/sw/DataAccess/tests/result-set#"; + + public static final IRI RESULTSET; + + public static final IRI RESULTVARIABLE; + + public static final IRI SOLUTION; + + public static final IRI BINDING; + + public static final IRI VALUE; + + public static final IRI VARIABLE; + + public static final IRI BOOLEAN; + + public static final Literal TRUE; + + public static final Literal FALSE; + + static { + ValueFactory vf = SimpleValueFactory.getInstance(); + RESULTSET = vf.createIRI(NAMESPACE, "ResultSet"); + RESULTVARIABLE = vf.createIRI(NAMESPACE, "resultVariable"); + SOLUTION = vf.createIRI(NAMESPACE, "solution"); + BINDING = vf.createIRI(NAMESPACE, "binding"); + VALUE = vf.createIRI(NAMESPACE, "value"); + VARIABLE = vf.createIRI(NAMESPACE, "variable"); + BOOLEAN = vf.createIRI(NAMESPACE, "boolean"); + TRUE = vf.createLiteral(true); + FALSE = vf.createLiteral(false); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetUtil.java b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetUtil.java new file mode 100644 index 00000000000..9ccc8515581 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetUtil.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.dawg; + +import org.eclipse.rdf4j.model.Graph; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.impl.GraphImpl; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; +import org.eclipse.rdf4j.query.impl.TupleQueryResultBuilder; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; + +/** + * @author Arjohn Kampman + */ +public class DAWGTestResultSetUtil { + + public static TupleQueryResult toTupleQueryResult(Iterable dawgGraph) + throws DAWGTestResultSetParseException + { + TupleQueryResultBuilder tqrBuilder = new TupleQueryResultBuilder(); + DAWGTestResultSetParser parser = new DAWGTestResultSetParser(tqrBuilder); + + try { + parser.startRDF(); + for (Statement st : dawgGraph) { + parser.handleStatement(st); + } + parser.endRDF(); + + return tqrBuilder.getQueryResult(); + } + catch (RDFHandlerException e) { + throw new DAWGTestResultSetParseException(e.getMessage(), e); + } + } + + public static Graph toGraph(TupleQueryResult tqr) + throws QueryEvaluationException + { + Graph graph = new GraphImpl(); + DAWGTestResultSetWriter writer = new DAWGTestResultSetWriter(new StatementCollector(graph)); + + try { + writer.startQueryResult(tqr.getBindingNames()); + while (tqr.hasNext()) { + writer.handleSolution(tqr.next()); + } + writer.endQueryResult(); + } + catch (TupleQueryResultHandlerException e) { + // No exceptions expected from DAWGTestResultSetWriter or + // StatementCollector, foud a bug? + throw new RuntimeException(e); + } + + return graph; + } + + public static boolean toBooleanQueryResult(Iterable dawgGraph) + throws DAWGTestResultSetParseException + { + DAWGTestBooleanParser parser = new DAWGTestBooleanParser(); + + try { + parser.startRDF(); + for (Statement st : dawgGraph) { + parser.handleStatement(st); + } + parser.endRDF(); + + return parser.getValue(); + } + catch (RDFHandlerException e) { + throw new DAWGTestResultSetParseException(e.getMessage(), e); + } + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetWriter.java b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetWriter.java new file mode 100644 index 00000000000..bcfb8f7bac9 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/DAWGTestResultSetWriter.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.dawg; + +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.BINDING; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.RESULTSET; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.RESULTVARIABLE; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.SOLUTION; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.VALUE; +import static org.eclipse.rdf4j.query.dawg.DAWGTestResultSetSchema.VARIABLE; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryResultHandlerException; +import org.eclipse.rdf4j.query.TupleQueryResultHandler; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; +import org.eclipse.rdf4j.rio.RDFHandler; +import org.eclipse.rdf4j.rio.RDFHandlerException; + +/** + * A {@link TupleQueryResultHandler} that converts query results to an RDF graph + * using the Data Access Working Group Test Result Set RDF Vocabulary + * (http://www.w3.org/2001/sw/DataAccess/tests/result-set#). + */ +public class DAWGTestResultSetWriter implements TupleQueryResultHandler { + + /*-----------* + * Constants * + *-----------*/ + + /** + * RDFHandler to report the generated statements to. + */ + private final RDFHandler rdfHandler; + + private final ValueFactory vf; + + /*-----------* + * Variables * + *-----------*/ + + private BNode resultSetNode; + + private Map bnodeMap = new HashMap(); + + /*--------------* + * Constructors * + *--------------*/ + + public DAWGTestResultSetWriter(RDFHandler rdfHandler) { + this(rdfHandler, SimpleValueFactory.getInstance()); + } + + public DAWGTestResultSetWriter(RDFHandler rdfHandler, ValueFactory vf) { + this.rdfHandler = rdfHandler; + this.vf = vf; + } + + /*---------* + * Methods * + *---------*/ + + @Override + public void startQueryResult(List bindingNames) + throws TupleQueryResultHandlerException + { + try { + rdfHandler.startRDF(); + + resultSetNode = vf.createBNode(); + bnodeMap.clear(); + + reportStatement(resultSetNode, RDF.TYPE, RESULTSET); + + for (String bindingName : bindingNames) { + Literal bindingNameLit = vf.createLiteral(bindingName); + reportStatement(resultSetNode, RESULTVARIABLE, bindingNameLit); + } + } + catch (RDFHandlerException e) { + throw new TupleQueryResultHandlerException(e); + } + } + + @Override + public void endQueryResult() + throws TupleQueryResultHandlerException + { + resultSetNode = null; + + try { + rdfHandler.endRDF(); + } + catch (RDFHandlerException e) { + throw new TupleQueryResultHandlerException(e); + } + } + + @Override + public void handleSolution(BindingSet bindingSet) + throws TupleQueryResultHandlerException + { + try { + BNode solutionNode = vf.createBNode(); + + reportStatement(resultSetNode, SOLUTION, solutionNode); + + for (Binding binding : bindingSet) { + BNode bindingNode = vf.createBNode(); + + reportStatement(solutionNode, BINDING, bindingNode); + reportStatement(bindingNode, VARIABLE, vf.createLiteral(binding.getName())); + + Value value = binding.getValue(); + + // Map bnodes to new bnodes to prevent collisions with the bnodes + // generated for the result format + if (value instanceof BNode) { + BNode mappedBNode = bnodeMap.get(value); + + if (mappedBNode == null) { + mappedBNode = vf.createBNode(); + bnodeMap.put((BNode)value, mappedBNode); + } + + value = mappedBNode; + } + + reportStatement(bindingNode, VALUE, value); + } + } + catch (RDFHandlerException e) { + throw new TupleQueryResultHandlerException(e); + } + } + + private void reportStatement(Resource subject, IRI predicate, Value object) + throws RDFHandlerException + { + rdfHandler.handleStatement(vf.createStatement(subject, predicate, object)); + } + + @Override + public void handleBoolean(boolean value) + throws QueryResultHandlerException + { + throw new UnsupportedOperationException("Cannot handle boolean results"); + } + + @Override + public void handleLinks(List linkUrls) + throws QueryResultHandlerException + { + // We do not support links, so do nothing + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/package.html b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/package.html new file mode 100644 index 00000000000..57d545ef488 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/dawg/package.html @@ -0,0 +1,6 @@ + + +Functionality to convert tuple query results to and from the +Data Access Working Group Test Result Set RDF Vocabulary + + diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractOperation.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractOperation.java new file mode 100644 index 00000000000..750f8b90c37 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractOperation.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.Operation; + +/** + * Abstract super class of all operation types. + * + * @author Jeen Broekstra + */ +public abstract class AbstractOperation implements Operation { + + /*------------* + * Attributes * + *------------*/ + + protected final MapBindingSet bindings = new MapBindingSet(); + + protected Dataset dataset = null; + + protected boolean includeInferred = true; + + private int maxExecutionTime = 0; + + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new operation object. + */ + protected AbstractOperation() { + } + + /*---------* + * Methods * + *---------*/ + + public void setBinding(String name, Value value) { + bindings.addBinding(name, value); + } + + public void removeBinding(String name) { + bindings.removeBinding(name); + } + + public void clearBindings() { + bindings.clear(); + } + + public BindingSet getBindings() { + return bindings; + } + + public void setDataset(Dataset dataset) { + this.dataset = dataset; + } + + public Dataset getDataset() { + return dataset; + } + + public void setIncludeInferred(boolean includeInferred) { + this.includeInferred = includeInferred; + } + + public boolean getIncludeInferred() { + return includeInferred; + } + + @Override + public void setMaxExecutionTime(int maxExecutionTime) { + this.maxExecutionTime = maxExecutionTime; + } + + @Override + public int getMaxExecutionTime() { + return maxExecutionTime; + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractQuery.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractQuery.java new file mode 100644 index 00000000000..e001b78b109 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractQuery.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import org.eclipse.rdf4j.query.Query; + +/** + * Abstract super class of all query types. + */ +public abstract class AbstractQuery extends AbstractOperation implements Query { + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new query object. + */ + protected AbstractQuery() { + super(); + } + + /*---------* + * Methods * + *---------*/ + + @Deprecated + public void setMaxQueryTime(int maxQueryTime) { + setMaxExecutionTime(maxQueryTime); + + } + + @Deprecated + public int getMaxQueryTime() { + return getMaxExecutionTime(); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractUpdate.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractUpdate.java new file mode 100644 index 00000000000..b87702d8c76 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/AbstractUpdate.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import org.eclipse.rdf4j.query.Update; + +/** + * Abstract super class of all update types. + */ +public abstract class AbstractUpdate extends AbstractOperation implements Update { + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new query object. + */ + protected AbstractUpdate() { + super(); + } + + /*---------* + * Methods * + *---------*/ + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/BindingImpl.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/BindingImpl.java new file mode 100644 index 00000000000..cf72c0d154a --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/BindingImpl.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import org.eclipse.rdf4j.model.Value; + +/** + * @deprecated since 4.0. Use {@link SimpleBinding} instead. + * @author Jeen Broekstra + */ +@Deprecated +public class BindingImpl extends SimpleBinding { + + private static final long serialVersionUID = 1L; + + public BindingImpl(String name, Value value) { + super(name, value); + } + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/DatasetImpl.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/DatasetImpl.java new file mode 100644 index 00000000000..5630ddc7cc2 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/DatasetImpl.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +/** + * @deprecated since 4.0. Use {@link SimpleDataset} instead. + * @author Jeen Broekstra + */ +@Deprecated +public class DatasetImpl extends SimpleDataset { + + private static final long serialVersionUID = 1L; + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/EmptyBindingSet.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/EmptyBindingSet.java new file mode 100644 index 00000000000..db5b3af82b2 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/EmptyBindingSet.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; + +/** + * An immutable empty BindingSet. + * + * @author Arjohn Kampman + */ +public class EmptyBindingSet implements BindingSet { + + private static final long serialVersionUID = -6010968140688315954L; + + private static final EmptyBindingSet singleton = new EmptyBindingSet(); + + public static BindingSet getInstance() { + return singleton; + } + + private EmptyBindingIterator iter = new EmptyBindingIterator(); + + public Iterator iterator() { + return iter; + } + + public Set getBindingNames() { + return Collections.emptySet(); + } + + public Binding getBinding(String bindingName) { + return null; + } + + public boolean hasBinding(String bindingName) { + return false; + } + + public Value getValue(String bindingName) { + return null; + } + + public int size() { + return 0; + } + + @Override + public boolean equals(Object o) { + if (o instanceof BindingSet) { + return ((BindingSet)o).size() == 0; + } + + return false; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString() { + return "[]"; + } + + /*----------------------------------* + * Inner class EmptyBindingIterator * + *----------------------------------*/ + + private static class EmptyBindingIterator implements Iterator { + + public boolean hasNext() { + return false; + } + + public Binding next() { + throw new NoSuchElementException(); + } + + public void remove() { + throw new IllegalStateException(); + } + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/FallbackDataset.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/FallbackDataset.java new file mode 100644 index 00000000000..ee8824674bd --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/FallbackDataset.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.io.Serializable; +import java.util.Set; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.query.Dataset; + + +/** + * + * @author james + */ +public class FallbackDataset implements Dataset, Serializable { + + /** + * + */ + private static final long serialVersionUID = 5866540736738270376L; + + public static Dataset fallback(Dataset primary, Dataset fallback) { + if (primary == null) + return fallback; + if (fallback == null) + return primary; + return new FallbackDataset(primary, fallback); + } + + private Dataset primary; + private Dataset fallback; + + private FallbackDataset(Dataset primary, Dataset secondary) { + assert primary != null; + assert secondary != null; + this.primary = primary; + this.fallback = secondary; + } + + public Set getDefaultGraphs() { + Set set = primary.getDefaultGraphs(); + if (set == null || set.isEmpty()) + return fallback.getDefaultGraphs(); + return set; + } + + public Set getNamedGraphs() { + Set set = primary.getNamedGraphs(); + if (set == null || set.isEmpty()) + return fallback.getNamedGraphs(); + return set; + } + + public IRI getDefaultInsertGraph() { + IRI graph = primary.getDefaultInsertGraph(); + if (graph == null) + return fallback.getDefaultInsertGraph(); + return graph; + } + + public Set getDefaultRemoveGraphs() { + Set set = primary.getDefaultRemoveGraphs(); + if (set == null || set.isEmpty()) + return fallback.getDefaultRemoveGraphs(); + return set; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (IRI uri : getDefaultRemoveGraphs()) { + sb.append("DELETE FROM "); + appendURI(sb, uri); + } + sb.append("INSERT INTO "); + appendURI(sb, getDefaultInsertGraph()); + for (IRI uri : getDefaultGraphs()) { + sb.append("USING "); + appendURI(sb, uri); + } + for (IRI uri : getNamedGraphs()) { + sb.append("USING NAMED "); + appendURI(sb, uri); + } + return sb.toString(); + } + + private void appendURI(StringBuilder sb, IRI uri) { + String str = uri.toString(); + if (str.length() > 50) { + sb.append("<").append(str, 0, 19).append(".."); + sb.append(str, str.length() - 29, str.length()).append(">\n"); + } + else { + sb.append("<").append(uri).append(">\n"); + } + } + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/GraphQueryResultImpl.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/GraphQueryResultImpl.java new file mode 100644 index 00000000000..7b6e935b9cd --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/GraphQueryResultImpl.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.util.Map; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * @deprecated since 4.0. Use {@link IteratingGraphQueryResult} instead. + * @author Jeen Broekstra + */ +@Deprecated +public class GraphQueryResultImpl extends IteratingGraphQueryResult { + + public GraphQueryResultImpl(Map namespaces, + CloseableIteration statementIter) + { + super(namespaces, statementIter); + } + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/IteratingGraphQueryResult.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/IteratingGraphQueryResult.java new file mode 100644 index 00000000000..bef70f14a44 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/IteratingGraphQueryResult.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration; +import org.eclipse.rdf4j.common.iteration.IterationWrapper; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.query.GraphQueryResult; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * An iterating implementation of the {@link GraphQueryResult} interface. + * + * @author Arjohn Kampman + * @author Jeen Broekstra + */ +public class IteratingGraphQueryResult extends IterationWrapper + implements GraphQueryResult +{ + + /*-----------* + * Variables * + *-----------*/ + + private final Map namespaces; + + /*--------------* + * Constructors * + *--------------*/ + + public IteratingGraphQueryResult(Map namespaces, Iterable statements) + { + this(namespaces, statements.iterator()); + } + + public IteratingGraphQueryResult(Map namespaces, + Iterator statementIter) + { + this(namespaces, new CloseableIteratorIteration(statementIter)); + } + + public IteratingGraphQueryResult(Map namespaces, + CloseableIteration statementIter) + { + super(statementIter); + this.namespaces = Collections.unmodifiableMap(namespaces); + } + + /*---------* + * Methods * + *---------*/ + + public Map getNamespaces() { + return namespaces; + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/IteratingTupleQueryResult.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/IteratingTupleQueryResult.java new file mode 100644 index 00000000000..5e09ea28a75 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/IteratingTupleQueryResult.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration; +import org.eclipse.rdf4j.common.iteration.IterationWrapper; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.TupleQueryResult; + +/** + * An iterating implementation of the {@link TupleQueryResult} interface. + */ +public class IteratingTupleQueryResult extends IterationWrapper implements + TupleQueryResult +{ + + /*-----------* + * Variables * + *-----------*/ + + private final List bindingNames; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a query result object with the supplied binding names. + * The supplied list of binding names is assumed to be constant; + * care should be taken that the contents of this list doesn't change after + * supplying it to this solution. + * + * @param bindingNames + * The binding names, in order of projection. + */ + public IteratingTupleQueryResult(List bindingNames, Iterable bindingSets) { + this(bindingNames, bindingSets.iterator()); + } + + public IteratingTupleQueryResult(List bindingNames, Iterator bindingSetIter) { + this(bindingNames, new CloseableIteratorIteration(bindingSetIter)); + } + + /** + * Creates a query result object with the supplied binding names. + * The supplied list of binding names is assumed to be constant; + * care should be taken that the contents of this list doesn't change after + * supplying it to this solution. + * + * @param bindingNames + * The binding names, in order of projection. + */ + public IteratingTupleQueryResult(List bindingNames, + CloseableIteration bindingSetIter) + { + super(bindingSetIter); + // Don't allow modifications to the binding names when it is accessed + // through getBindingNames: + this.bindingNames = Collections.unmodifiableList(bindingNames); + } + + /*---------* + * Methods * + *---------*/ + + @Override + public List getBindingNames() + throws QueryEvaluationException + { + return bindingNames; + } + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/ListBindingSet.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/ListBindingSet.java new file mode 100644 index 00000000000..c14bcc54ab4 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/ListBindingSet.java @@ -0,0 +1,212 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; + +/** + * A List-based implementation of the {@link BindingSet} interface. + * + * @author Arjohn Kampman + */ +public class ListBindingSet implements BindingSet { + + private static final long serialVersionUID = -2907809218835403743L; + + private final List bindingNames; + + private final List values; + + /** + * Creates a new List-based BindingSet containing the supplied bindings. + * The supplied list of binding names is assumed to be constant; + * care should be taken that the contents of this list doesn't change after + * supplying it to this solution. The number of supplied values must be equal + * to the number of the binding names. + * + * @param names + * The binding names. + * @param values + * The binding values. + */ + public ListBindingSet(List names, Value... values) { + this(names, Arrays.asList(values)); + } + + /** + * Creates a new List-based BindingSet containing the supplied bindings. + * The supplied lists are assumed to be constant; care should be + * taken that the contents of these lists don't change after supplying them + * to this solution. The number of supplied values must be equal to the + * number of the binding names. + * + * @param bindingNames + * The binding names. + * @param values + * The binding values. + */ + public ListBindingSet(List bindingNames, List values) { + assert bindingNames.size() == values.size() : "number of binding names and values not equal"; + + this.bindingNames = bindingNames; + this.values = values; + } + + public Set getBindingNames() { + return new LinkedHashSet(bindingNames); + } + + public Value getValue(String bindingName) { + int idx = bindingNames.indexOf(bindingName); + + if (idx != -1) { + return values.get(idx); + } + + return null; + } + + public Binding getBinding(String bindingName) { + Value value = getValue(bindingName); + + if (value != null) { + return new SimpleBinding(bindingName, value); + } + + return null; + } + + public boolean hasBinding(String bindingName) { + return getValue(bindingName) != null; + } + + public Iterator iterator() { + return new ListBindingSetIterator(); + } + + public int size() { + int size = 0; + + for (Value value : values) { + if (value != null) { + size++; + } + } + + return size; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other instanceof BindingSet) { + int otherSize = 0; + + // Compare other's bindings to own + for (Binding binding : (BindingSet)other) { + Value ownValue = getValue(binding.getName()); + + if (!binding.getValue().equals(ownValue)) { + // Unequal bindings for this name + return false; + } + + otherSize++; + } + + // All bindings have been matched, sets are equal if this solution + // doesn't have any additional bindings. + int thisSize = 0; + for (Value value : values) { + if (value != null) { + thisSize++; + } + } + + return thisSize == otherSize; + } + + return false; + } + + @Override + public int hashCode() { + int hashCode = 0; + + for (Binding binding : this) { + hashCode ^= binding.hashCode(); + } + + return hashCode; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(32 * size()); + + sb.append('['); + + Iterator iter = iterator(); + while (iter.hasNext()) { + sb.append(iter.next().toString()); + if (iter.hasNext()) { + sb.append(';'); + } + } + + sb.append(']'); + + return sb.toString(); + } + + /*------------------------------------* + * Inner class ListBindingSetIterator * + *------------------------------------*/ + + private class ListBindingSetIterator implements Iterator { + + private int index = -1; + + public ListBindingSetIterator() { + findNextElement(); + } + + private void findNextElement() { + for (index++; index < values.size(); index++) { + if (values.get(index) != null) { + break; + } + } + } + + public boolean hasNext() { + return index < values.size(); + } + + public Binding next() { + Binding result = new SimpleBinding(bindingNames.get(index), values.get(index)); + findNextElement(); + return result; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/MapBindingSet.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/MapBindingSet.java new file mode 100644 index 00000000000..342d285796a --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/MapBindingSet.java @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; + +/** + * A Map-based implementation of the {@link BindingSet} interface. + */ +public class MapBindingSet implements BindingSet { + + private static final long serialVersionUID = -8857324525220429607L; + + private final Map bindings; + + public MapBindingSet() { + this(8); + } + + /** + * Creates a new Map-based BindingSet with the specified initial capacity. + * Bindings can be added to this binding set using the {@link #addBinding} + * methods. + * + * @param capacity + * The initial capacity of the created BindingSet object. + */ + public MapBindingSet(int capacity) { + // Create bindings map, compensating for HashMap's load factor + bindings = new LinkedHashMap(capacity * 2); + } + + /** + * Adds a binding to the binding set. + * + * @param name + * The binding's name. + * @param value + * The binding's value. + */ + public void addBinding(String name, Value value) { + addBinding(new SimpleBinding(name, value)); + } + + /** + * Adds a binding to the binding set. + * + * @param binding + * The binding to add to the binding set. + */ + public void addBinding(Binding binding) { + bindings.put(binding.getName(), binding); + } + + /** + * Removes a binding from the binding set. + * + * @param name + * The binding's name. + */ + public void removeBinding(String name) { + bindings.remove(name); + } + + /** + * Removes all bindings from the binding set. + */ + public void clear() { + bindings.clear(); + } + + public Iterator iterator() { + return bindings.values().iterator(); + } + + public Set getBindingNames() { + return bindings.keySet(); + } + + public Binding getBinding(String bindingName) { + return bindings.get(bindingName); + } + + public boolean hasBinding(String bindingName) { + return bindings.containsKey(bindingName); + } + + public Value getValue(String bindingName) { + Binding binding = getBinding(bindingName); + + if (binding != null) { + return binding.getValue(); + } + + return null; + } + + public int size() { + return bindings.size(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + else if (other instanceof BindingSet) { + int otherSize = 0; + + // Compare other's bindings to own + for (Binding binding : (BindingSet)other) { + Value ownValue = getValue(binding.getName()); + + if (!binding.getValue().equals(ownValue)) { + // Unequal bindings for this name + return false; + } + + otherSize++; + } + + // All bindings have been matched, sets are equal if this binding set + // doesn't have any additional bindings. + return otherSize == bindings.size(); + } + + return false; + } + + @Override + public int hashCode() { + int hashCode = 0; + + for (Binding binding : this) { + hashCode ^= binding.hashCode(); + } + + return hashCode; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(32 * size()); + + sb.append('['); + + Iterator iter = iterator(); + while (iter.hasNext()) { + sb.append(iter.next().toString()); + if (iter.hasNext()) { + sb.append(';'); + } + } + + sb.append(']'); + + return sb.toString(); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/MutableTupleQueryResult.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/MutableTupleQueryResult.java new file mode 100644 index 00000000000..a0688d678f6 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/MutableTupleQueryResult.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.TupleQueryResult; + +/** + * An implementation of the {@link TupleQueryResult} interface that stores the + * complete query result in memory. The query results in a + * MutableTupleQueryResult can be iterated over multiple times and can also be + * iterated over in reverse order. + * + * @author Arjohn Kampman + */ +public class MutableTupleQueryResult implements TupleQueryResult, Cloneable { + + /*-----------* + * Variables * + *-----------*/ + + private Set bindingNames = new LinkedHashSet(); + + private List bindingSets = new ArrayList(); + + /** + * The index of the next element that will be returned by a call to + * {@link #next()}. + */ + private int currentIndex = 0; + + /** + * The index of the last element that was returned by a call to + * {@link #next()} or {@link #previous()}. Equal to -1 if there is no such + * element. + */ + private int lastReturned = -1; + + /*--------------* + * Constructors * + *--------------*/ + + public MutableTupleQueryResult(Collection bindingNames, + BindingSet... bindingSets) + { + this(bindingNames, Arrays.asList(bindingSets)); + } + + /** + * Creates a query result table with the supplied binding names. + * The supplied list of binding names is assumed to be constant; + * care should be taken that the contents of this list doesn't change after + * supplying it to this solution. + * + * @param bindingNames + * The binding names, in order of projection. + */ + public MutableTupleQueryResult(Collection bindingNames, + Collection bindingSets) + { + this.bindingNames.addAll(bindingNames); + this.bindingSets.addAll(bindingSets); + } + + public MutableTupleQueryResult(Collection bindingNames, + Iteration bindingSetIter) + throws E + { + this.bindingNames.addAll(bindingNames); + Iterations.addAll(bindingSetIter, this.bindingSets); + } + + public MutableTupleQueryResult(TupleQueryResult tqr) + throws QueryEvaluationException + { + this(tqr.getBindingNames(), tqr); + } + + /*---------* + * Methods * + *---------*/ + + public List getBindingNames() { + return new ArrayList(bindingNames); + } + + public int size() { + return bindingSets.size(); + } + + public BindingSet get(int index) { + return bindingSets.get(index); + } + + public int getIndex() { + return currentIndex; + } + + public void setIndex(int index) { + if (index < 0 || index > bindingSets.size() + 1) { + throw new IllegalArgumentException("Index out of range: " + index); + } + + this.currentIndex = index; + } + + public boolean hasNext() { + return currentIndex < bindingSets.size(); + } + + public BindingSet next() { + if (hasNext()) { + BindingSet result = get(currentIndex); + lastReturned = currentIndex; + currentIndex++; + return result; + } + + throw new NoSuchElementException(); + } + + public boolean hasPrevious() { + return currentIndex > 0; + } + + public BindingSet previous() { + if (hasPrevious()) { + BindingSet result = bindingSets.get(currentIndex - 1); + currentIndex--; + lastReturned = currentIndex; + return result; + } + + throw new NoSuchElementException(); + } + + /** + * Moves the cursor to the start of the query result, just before the first + * binding set. After calling this method, the result can be iterated over + * from scratch. + */ + public void beforeFirst() { + currentIndex = 0; + } + + /** + * Moves the cursor to the end of the query result, just after the last + * binding set. + */ + public void afterLast() { + currentIndex = bindingSets.size() + 1; + } + + /** + * Inserts the specified binding set into the list. The binding set is + * inserted immediately before the next element that would be returned by + * {@link #next()}, if any, and after the next element that would be + * returned by {@link #previous}, if any. (If the table contains no binding + * sets, the new element becomes the sole element on the table.) The new + * element is inserted before the implicit cursor: a subsequent call to + * next() would be unaffected, and a subsequent call to + * previous() would return the new binding set. + * + * @param bindingSet + * The binding set to insert. + */ + public void insert(BindingSet bindingSet) { + insert(currentIndex, bindingSet); + } + + public void insert(int index, BindingSet bindingSet) { + bindingSets.add(index, bindingSet); + + if (currentIndex > index) { + currentIndex++; + } + + lastReturned = -1; + } + + public void append(BindingSet bindingSet) { + bindingSets.add(bindingSet); + lastReturned = -1; + } + + public void set(BindingSet bindingSet) { + if (lastReturned == -1) { + throw new IllegalStateException(); + } + + set(lastReturned, bindingSet); + } + + public BindingSet set(int index, BindingSet bindingSet) { + return bindingSets.set(index, bindingSet); + } + + public void remove() { + if (lastReturned == -1) { + throw new IllegalStateException(); + } + + remove(lastReturned); + + if (currentIndex > lastReturned) { + currentIndex--; + } + + lastReturned = -1; + } + + public BindingSet remove(int index) { + BindingSet result = bindingSets.remove(index); + + if (currentIndex > index) { + currentIndex--; + } + + lastReturned = -1; + + return result; + } + + public void clear() { + bindingNames.clear(); + bindingSets.clear(); + currentIndex = 0; + lastReturned = -1; + } + + public void close() { + // no-opp + } + + @Override + public MutableTupleQueryResult clone() + throws CloneNotSupportedException + { + MutableTupleQueryResult clone = (MutableTupleQueryResult)super.clone(); + clone.bindingNames = new LinkedHashSet(bindingNames); + clone.bindingSets = new ArrayList(bindingSets); + return clone; + } + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/SimpleBinding.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/SimpleBinding.java new file mode 100644 index 00000000000..38d5c60428e --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/SimpleBinding.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.Binding; + +/** + * An implementation of the {@link Binding} interface. + * + * @since 4.0 + * @author Jeen Broekstra + */ +public class SimpleBinding implements Binding { + + private static final long serialVersionUID = -8257244838478873298L; + + private final String name; + + private final Value value; + + /** + * Creates a binding object with the supplied name and value. + * + * @param name + * The binding's name. + * @param value + * The binding's value. + */ + public SimpleBinding(String name, Value value) { + assert name != null : "name must not be null"; + assert value != null : "value must not be null"; + + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public Value getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (o instanceof Binding) { + Binding other = (Binding)o; + + return name.equals(other.getName()) && value.equals(other.getValue()); + } + + return false; + } + + @Override + public int hashCode() { + return name.hashCode() ^ value.hashCode(); + } + + @Override + public String toString() { + return name + "=" + value.toString(); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/SimpleDataset.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/SimpleDataset.java new file mode 100644 index 00000000000..dd7627f6a77 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/SimpleDataset.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.io.Serializable; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.query.Dataset; + +/** + * A simple implementation of the {@link Dataset} interface. + * + * @author Arjohn Kampman + * @author James Leigh + */ +public class SimpleDataset implements Dataset, Serializable { + + private static final long serialVersionUID = 7841576172053060417L; + + private Set defaultRemoveGraphs = new LinkedHashSet(); + + private IRI defaultInsertGraph; + + private Set defaultGraphs = new LinkedHashSet(); + + private Set namedGraphs = new LinkedHashSet(); + + public SimpleDataset() { + } + + public Set getDefaultRemoveGraphs() { + return Collections.unmodifiableSet(defaultRemoveGraphs); + } + + /** + * Adds a graph URI to the set of default remove graph URIs. + */ + public void addDefaultRemoveGraph(IRI graphURI) { + defaultRemoveGraphs.add(graphURI); + } + + /** + * Removes a graph URI from the set of default remove graph URIs. + * + * @return true if the URI was removed from the set, false + * if the set did not contain the URI. + */ + public boolean removeDefaultRemoveGraph(IRI graphURI) { + return defaultRemoveGraphs.remove(graphURI); + } + + /** + * @return Returns the default insert graph. + */ + public IRI getDefaultInsertGraph() { + return defaultInsertGraph; + } + + /** + * @param defaultInsertGraph + * The default insert graph to used. + */ + public void setDefaultInsertGraph(IRI defaultInsertGraph) { + this.defaultInsertGraph = defaultInsertGraph; + } + + public Set getDefaultGraphs() { + return Collections.unmodifiableSet(defaultGraphs); + } + + /** + * Adds a graph URI to the set of default graph URIs. + */ + public void addDefaultGraph(IRI graphURI) { + defaultGraphs.add(graphURI); + } + + /** + * Removes a graph URI from the set of default graph URIs. + * + * @return true if the URI was removed from the set, false + * if the set did not contain the URI. + */ + public boolean removeDefaultGraph(IRI graphURI) { + return defaultGraphs.remove(graphURI); + } + + /** + * Gets the (unmodifiable) set of named graph URIs. + */ + public Set getNamedGraphs() { + return Collections.unmodifiableSet(namedGraphs); + } + + /** + * Adds a graph URI to the set of named graph URIs. + */ + public void addNamedGraph(IRI graphURI) { + namedGraphs.add(graphURI); + } + + /** + * Removes a graph URI from the set of named graph URIs. + * + * @return true if the URI was removed from the set, false + * if the set did not contain the URI. + */ + public boolean removeNamedGraph(IRI graphURI) { + return namedGraphs.remove(graphURI); + } + + /** + * Removes all graph URIs (both default and named) from this dataset. + */ + public void clear() { + defaultRemoveGraphs.clear(); + defaultInsertGraph = null; + defaultGraphs.clear(); + namedGraphs.clear(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (IRI uri : getDefaultRemoveGraphs()) { + sb.append("DELETE FROM "); + appendURI(sb, uri); + } + if (getDefaultInsertGraph() != null) { + sb.append("INSERT INTO "); + appendURI(sb, getDefaultInsertGraph()); + } + for (IRI uri : getDefaultGraphs()) { + sb.append("USING "); + appendURI(sb, uri); + } + for (IRI uri : getNamedGraphs()) { + sb.append("USING NAMED "); + appendURI(sb, uri); + } + if (getDefaultGraphs().isEmpty() && getNamedGraphs().isEmpty()) { + sb.append("## empty dataset ##"); + } + return sb.toString(); + } + + private void appendURI(StringBuilder sb, IRI uri) { + String str = uri.toString(); + if (str.length() > 50) { + sb.append("<").append(str, 0, 19).append(".."); + sb.append(str, str.length() - 29, str.length()).append(">\n"); + } + else { + sb.append("<").append(uri).append(">\n"); + } + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/TupleQueryResultBuilder.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/TupleQueryResultBuilder.java new file mode 100644 index 00000000000..a0a79b31853 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/TupleQueryResultBuilder.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.query.AbstractTupleQueryResultHandler; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.TupleQueryResultHandlerException; + +/** + * A TupleQueryResultHandler that can be used to create a TupleQueryResult + * object. + */ +public class TupleQueryResultBuilder extends AbstractTupleQueryResultHandler { + + /*-----------* + * Variables * + *-----------*/ + + private List bindingNames; + + private List bindingSetList = new ArrayList(); + + /*---------* + * Methods * + *---------*/ + + @Override + public void startQueryResult(List bindingNames) + throws TupleQueryResultHandlerException + { + this.bindingNames = bindingNames; + bindingSetList = new ArrayList(); + } + + @Override + public void handleSolution(BindingSet bindingSet) + throws TupleQueryResultHandlerException + { + bindingSetList.add(bindingSet); + } + + public TupleQueryResult getQueryResult() { + return new IteratingTupleQueryResult(bindingNames, bindingSetList); + } +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/impl/TupleQueryResultImpl.java b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/TupleQueryResultImpl.java new file mode 100644 index 00000000000..eab2732b90c --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/impl/TupleQueryResultImpl.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.impl; + +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * @deprecated since 4.0. Use {@link IteratingTupleQueryResult} instead. + * @author Jeen Broekstra + */ +@Deprecated +public class TupleQueryResultImpl extends IteratingTupleQueryResult { + + public TupleQueryResultImpl(List bindingNames, + CloseableIteration bindingSetIter) + { + super(bindingNames, bindingSetIter); + } + +} diff --git a/core/query/src/main/java/org/eclipse/rdf4j/query/package.html b/core/query/src/main/java/org/eclipse/rdf4j/query/package.html new file mode 100644 index 00000000000..74c2e4b99c8 --- /dev/null +++ b/core/query/src/main/java/org/eclipse/rdf4j/query/package.html @@ -0,0 +1,5 @@ + + +Interfaces and classes for handling queries and query results. + + \ No newline at end of file diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/AllTests.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/AllTests.java new file mode 100644 index 00000000000..224199c012e --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/AllTests.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * + * @author akam + */ +@RunWith(Suite.class) +@SuiteClasses({ + LimitIterationTest.class, + EmptyIterationTest.class, + OffsetIterationTest.class, + ConvertingIterationTest.class, + CloseableIteratorIterationTest.class, + DelayedIterationTest.class, + DistinctIterationTest.class, + ExceptionConvertingIterationTest.class, + FilterIterationTest.class, + IntersectionIterationTest.class, + DistinctIntersectionIterationTest.class, + IteratorIterationTest.class, + LookAheadIterationTest.class, + MinusIterationTest.class, + DistinctMinusIterationTest.class, + SingletonIterationTest.class, + UnionIterationTest.class, +}) +public class AllTests { +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/CloseableIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/CloseableIterationTest.java new file mode 100644 index 00000000000..409984c4f84 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/CloseableIterationTest.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; + +import java.util.NoSuchElementException; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.junit.Test; + +/** + * + */ +public abstract class CloseableIterationTest extends IterationTest { + + protected abstract CloseableIteration createTestIteration() + throws Exception; + + @Test + public void testClosedIteration() + throws Exception + { + for (int n = 0; n < getTestIterationSize(); n++) { + CloseableIteration iter = createTestIteration(); + + // Close after n iterations + for (int i = 0; i < n; i++) { + iter.next(); + } + + iter.close(); + + assertFalse("closed iteration should not contain any more elements", iter.hasNext()); + + try { + iter.next(); + fail("next() called on a closed iteration should throw a NoSuchElementException"); + } + catch (NoSuchElementException e) { + // expected exception + } + catch (Exception e) { + fail("next() called on a closed iteration should throw a NoSuchElementException"); + } + } + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/CloseableIteratorIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/CloseableIteratorIterationTest.java new file mode 100644 index 00000000000..51649055077 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/CloseableIteratorIterationTest.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration; + +public class CloseableIteratorIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new CloseableIteratorIteration(stringList1.iterator()); + } + + @Override + protected int getTestIterationSize() + { + return stringList1.size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/ConvertingIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/ConvertingIterationTest.java new file mode 100644 index 00000000000..a1477b37359 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/ConvertingIterationTest.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration; +import org.eclipse.rdf4j.common.iteration.ConvertingIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; + +public class ConvertingIterationTest extends CloseableIterationTest { + + private static final List intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + protected static CloseableIteration createConvertingIteration() { + Iteration intIteration = new CloseableIteratorIteration(intList.iterator()); + return new ConvertingIteration(intIteration) { + protected String convert(Integer integer) { + return integer.toString(); + } + }; + } + + @Override + protected CloseableIteration createTestIteration() + { + return createConvertingIteration(); + } + + @Override + protected int getTestIterationSize() + { + return 10; + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DelayedIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DelayedIterationTest.java new file mode 100644 index 00000000000..65b6f196bdc --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DelayedIterationTest.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.DelayedIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; + +public class DelayedIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new DelayedIteration() { + + @Override + protected Iteration createIteration() + { + return createStringList1Iteration(); + } + }; + } + + @Override + protected int getTestIterationSize() + { + return stringList1.size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctIntersectionIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctIntersectionIterationTest.java new file mode 100644 index 00000000000..457fe26dc90 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctIntersectionIterationTest.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.IntersectIteration; + +public class DistinctIntersectionIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new IntersectIteration(createStringList1Iteration(), + createStringList2Iteration(), true); + } + + @Override + protected int getTestIterationSize() + { + Set intersection = new HashSet(stringList1); + intersection.retainAll(stringList2); + return intersection.size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctIterationTest.java new file mode 100644 index 00000000000..350ada6a34e --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctIterationTest.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import java.util.HashSet; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.DistinctIteration; + +public class DistinctIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new DistinctIteration(createStringList1Iteration()); + } + + @Override + protected int getTestIterationSize() + { + return new HashSet(stringList1).size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctMinusIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctMinusIterationTest.java new file mode 100644 index 00000000000..01a3c4c1f9e --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/DistinctMinusIterationTest.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.MinusIteration; + +public class DistinctMinusIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new MinusIteration(createStringList1Iteration(), + createStringList2Iteration(), true); + } + + @Override + protected int getTestIterationSize() + { + Set difference = new HashSet(stringList1); + difference.removeAll(stringList2); + return difference.size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/EmptyIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/EmptyIterationTest.java new file mode 100644 index 00000000000..1f92b789b76 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/EmptyIterationTest.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.EmptyIteration; + +public class EmptyIterationTest extends CloseableIterationTest { + + protected static EmptyIteration createEmptyIteration() { + return new EmptyIteration(); + } + + @Override + protected CloseableIteration createTestIteration() + { + return createEmptyIteration(); + } + + @Override + protected int getTestIterationSize() + { + return 0; + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/ExceptionConvertingIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/ExceptionConvertingIterationTest.java new file mode 100644 index 00000000000..fadd0677176 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/ExceptionConvertingIterationTest.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.ExceptionConvertingIteration; + +public class ExceptionConvertingIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new ExceptionConvertingIteration(createStringList1Iteration()) { + + @Override + protected Exception convert(Exception e) + { + return e; + } + + }; + } + + @Override + protected int getTestIterationSize() + { + return stringList1.size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/FilterIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/FilterIterationTest.java new file mode 100644 index 00000000000..3f7df9a5069 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/FilterIterationTest.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import java.util.Collections; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.FilterIteration; + +public class FilterIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new FilterIteration(createStringList1Iteration()) { + + @Override + protected boolean accept(String object) + throws Exception + { + return "3".equals(object); + } + + }; + } + + @Override + protected int getTestIterationSize() + { + return Collections.frequency(stringList1, "3"); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IntersectionIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IntersectionIterationTest.java new file mode 100644 index 00000000000..ede27798de6 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IntersectionIterationTest.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.IntersectIteration; + +public class IntersectionIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new IntersectIteration(createStringList1Iteration(), + createStringList2Iteration()); + } + + @Override + protected int getTestIterationSize() + { + List intersection = new ArrayList(stringList1); + intersection.retainAll(stringList2); + return intersection.size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IterationTest.java new file mode 100644 index 00000000000..5f6ad7cbaa9 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IterationTest.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.junit.Test; + +public abstract class IterationTest { + + protected static final List stringList1 = Arrays.asList("1", "2", "3", "4", "5", "1", "2", "3", + "4", "5"); + + protected static final List stringList2 = Arrays.asList("4", "5", "6", "7", "8"); + + protected static CloseableIteration createStringList1Iteration() { + return new CloseableIteratorIteration(stringList1.iterator()); + } + + protected static CloseableIteration createStringList2Iteration() { + return new CloseableIteratorIteration(stringList2.iterator()); + } + + protected abstract Iteration createTestIteration() + throws Exception; + + protected abstract int getTestIterationSize(); + + @Test + public void testFullIteration() + throws Exception + { + Iteration iter = createTestIteration(); + int count = 0; + + while (iter.hasNext()) { + iter.next(); + count++; + } + + assertEquals("test iteration contains incorrect number of elements", getTestIterationSize(), count); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IteratorIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IteratorIterationTest.java new file mode 100644 index 00000000000..9d9204a6e70 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/IteratorIterationTest.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.common.iteration.IteratorIteration; + +public class IteratorIterationTest extends IterationTest { + + @Override + protected Iteration createTestIteration() + { + return new IteratorIteration(stringList1.iterator()); + } + + @Override + protected int getTestIterationSize() + { + return stringList1.size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/LimitIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/LimitIterationTest.java new file mode 100644 index 00000000000..cacf4ba02b0 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/LimitIterationTest.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.common.iteration.LimitIteration; +import org.junit.Test; + +public class LimitIterationTest extends CloseableIterationTest { + + protected static LimitIteration createLimitIteration(int limit) { + return new LimitIteration(createStringList1Iteration(), limit); + } + + @Override + protected CloseableIteration createTestIteration() + { + return createLimitIteration(5); + } + + @Override + protected int getTestIterationSize() + { + return 5; + } + + @Test + public void testInRangeOffset() + throws Exception + { + for (int limit = 0; limit < stringList1.size(); limit++) { + Iteration iter = createLimitIteration(limit); + List resultList = Iterations.asList(iter); + List expectedList = stringList1.subList(0, limit); + assertEquals("testInRangeOffset failed for limit: " + limit, expectedList, resultList); + } + } + + @Test + public void testOutOfRangeOffset() + throws Exception + { + Iteration iter = createLimitIteration(2 * stringList1.size()); + List resultList = Iterations.asList(iter); + assertEquals(stringList1, resultList); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/LookAheadIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/LookAheadIterationTest.java new file mode 100644 index 00000000000..ebc1365fa70 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/LookAheadIterationTest.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import java.util.Iterator; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; + +public class LookAheadIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + final Iterator iter = stringList1.iterator(); + + return new LookAheadIteration() { + + @Override + protected String getNextElement() + throws Exception + { + if (iter.hasNext()) { + return iter.next(); + } + else { + return null; + } + } + + }; + } + + @Override + protected int getTestIterationSize() + { + return stringList1.size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/MinusIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/MinusIterationTest.java new file mode 100644 index 00000000000..db1a925cb13 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/MinusIterationTest.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.MinusIteration; + +public class MinusIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new MinusIteration(createStringList1Iteration(), + createStringList2Iteration()); + } + + @Override + protected int getTestIterationSize() + { + List difference = new ArrayList(stringList1); + difference.removeAll(stringList2); + return difference.size(); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/OffsetIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/OffsetIterationTest.java new file mode 100644 index 00000000000..9e2e30ec119 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/OffsetIterationTest.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.common.iteration.OffsetIteration; +import org.junit.Test; + +public class OffsetIterationTest extends CloseableIterationTest { + + protected static OffsetIteration createOffsetIteration(int offset) { + return new OffsetIteration(createStringList1Iteration(), offset); + } + + @Override + protected CloseableIteration createTestIteration() + { + return createOffsetIteration(5); + } + + @Override + protected int getTestIterationSize() + { + return 5; + } + + @Test + public void testInRangeOffset() + throws Exception + { + for (int offset = 0; offset < stringList1.size(); offset++) { + Iteration iter = createOffsetIteration(offset); + List resultList = Iterations.asList(iter); + List expectedList = stringList1.subList(offset, stringList1.size()); + assertEquals("test failed for offset: " + offset, expectedList, resultList); + } + } + + @Test + public void testOutOfRangeOffset() + throws Exception + { + Iteration iter = createOffsetIteration(2 * stringList1.size()); + List resultList = Iterations.asList(iter); + assertEquals(Collections.emptyList(), resultList); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/SingletonIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/SingletonIterationTest.java new file mode 100644 index 00000000000..2ee1f2c6a17 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/SingletonIterationTest.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.SingletonIteration; + +public class SingletonIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new SingletonIteration("3"); + } + + @Override + protected int getTestIterationSize() + { + return 1; + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/UnionIterationTest.java b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/UnionIterationTest.java new file mode 100644 index 00000000000..b717868035e --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/common/iteration/UnionIterationTest.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.common.iteration; + +import static org.junit.Assert.assertTrue; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.SingletonIteration; +import org.eclipse.rdf4j.common.iteration.UnionIteration; +import org.junit.Test; + +public class UnionIterationTest extends CloseableIterationTest { + + @Override + protected CloseableIteration createTestIteration() + { + return new UnionIteration(createStringList1Iteration(), createStringList2Iteration()); + } + + @Override + protected int getTestIterationSize() + { + return stringList1.size() + stringList2.size(); + } + + @Test + public void testArgumentsClosed() + throws Exception + { + SingletonIteration iter1 = new SingletonIteration("1"); + SingletonIteration iter2 = new SingletonIteration("2"); + SingletonIteration iter3 = new SingletonIteration("3"); + UnionIteration unionIter = new UnionIteration(iter1, iter2, iter3); + + unionIter.next(); + unionIter.close(); + + assertTrue("iter1 should have been closed", iter1.isClosed()); + assertTrue("iter2 should have been closed", iter2.isClosed()); + assertTrue("iter3 should have been closed", iter3.isClosed()); + } +} diff --git a/core/query/src/test/java/org/eclipse/rdf4j/query/QueryResultsTest.java b/core/query/src/test/java/org/eclipse/rdf4j/query/QueryResultsTest.java new file mode 100644 index 00000000000..a9d8382d851 --- /dev/null +++ b/core/query/src/test/java/org/eclipse/rdf4j/query/QueryResultsTest.java @@ -0,0 +1,403 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.GraphQueryResult; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.eclipse.rdf4j.query.impl.ListBindingSet; +import org.eclipse.rdf4j.query.impl.MutableTupleQueryResult; +import org.junit.Before; +import org.junit.Test; + +/** + * @author Arjohn Kampman + */ +public class QueryResultsTest { + + private MutableTupleQueryResult tqr1; + + private MutableTupleQueryResult tqr2; + + private MutableTupleQueryResult tqr3; + + /** a stub GraphQueryResult, containing a number of duplicate statements */ + private GraphQueryResult gqr; + + private static ValueFactory VF = SimpleValueFactory.getInstance(); + + private List twoBindingNames = Arrays.asList("a", "b"); + + private List threeBindingNames = Arrays.asList("a", "b", "c"); + + private IRI foo; + + private IRI bar; + + private BNode bnode1; + + private BNode bnode2; + + private Literal lit1; + + private Literal lit2; + + private IRI a = VF.createIRI("urn:a"); + + private IRI b = VF.createIRI("urn:b"); + + private IRI c = VF.createIRI("urn:c"); + + private IRI p = VF.createIRI("urn:p"); + + private IRI q = VF.createIRI("urn:q"); + + @Before + public void setUp() { + tqr1 = new MutableTupleQueryResult(twoBindingNames); + tqr2 = new MutableTupleQueryResult(twoBindingNames); + tqr3 = new MutableTupleQueryResult(threeBindingNames); + + gqr = new StubGraphQueryResult(); + + foo = VF.createIRI("http://example.org/foo"); + bar = VF.createIRI("http://example.org/bar"); + + bnode1 = VF.createBNode(); + bnode2 = VF.createBNode(); + + lit1 = VF.createLiteral(1); + lit2 = VF.createLiteral("test", "en"); + } + + @Test + public void testAsModel() + throws QueryEvaluationException + { + Model model = QueryResults.asModel(gqr); + + assertFalse(gqr.hasNext()); + assertNotNull(model); + assertTrue(model.contains(VF.createStatement(a, p, b))); + } + + @Test + public void testStreamGraphResult() { + List aboutA = QueryResults.stream(gqr).filter(s -> s.getSubject().equals(a)).collect( + Collectors.toList()); + + assertFalse(aboutA.isEmpty()); + + for (Statement st : aboutA) { + assertTrue(st.getSubject().equals(a)); + } + } + + @Test + public void testStreamTupleResult() { + BindingSet a = new ListBindingSet(twoBindingNames, foo, lit1); + BindingSet b = new ListBindingSet(twoBindingNames, bar, lit2); + tqr1.append(a); + tqr1.append(b); + tqr1.append(a); + tqr1.append(b); + tqr1.append(b); + + List list = QueryResults.stream(tqr1).filter(bs -> bs.getValue("a").equals(foo)).collect( + Collectors.toList()); + + assertNotNull(list); + assertFalse(list.isEmpty()); + for (BindingSet bs : list) { + assertTrue(bs.getValue("a").equals(foo)); + } + } + + @Test + public void testGraphQueryResultEquals() throws QueryEvaluationException { + + StubGraphQueryResult toCompare = new StubGraphQueryResult(); + + assertTrue(QueryResults.equals(gqr, toCompare)); + gqr = new StubGraphQueryResult(); + toCompare = new StubGraphQueryResult(); + toCompare.statements.add(VF.createStatement(VF.createURI("urn:test-gqr-equals"), RDF.TYPE, RDF.PROPERTY)); + + assertFalse(QueryResults.equals(gqr, toCompare)); + } + + @Test + public void testDistinctGraphQueryResults() + throws QueryEvaluationException + { + + GraphQueryResult filtered = QueryResults.distinctResults(gqr); + + List processed = new ArrayList(); + while (filtered.hasNext()) { + Statement result = filtered.next(); + assertFalse(processed.contains(result)); + processed.add(result); + } + } + + @Test + public void testDistinctTupleQueryResults() + throws QueryEvaluationException + { + + BindingSet a = new ListBindingSet(twoBindingNames, foo, lit1); + BindingSet b = new ListBindingSet(twoBindingNames, bar, lit2); + tqr1.append(a); + tqr1.append(b); + tqr1.append(a); + tqr1.append(b); + tqr1.append(b); + + TupleQueryResult filtered = QueryResults.distinctResults(tqr1); + + List processed = new ArrayList(); + while (filtered.hasNext()) { + BindingSet result = filtered.next(); + assertFalse(processed.contains(result)); + processed.add(result); + } + } + + private class StubGraphQueryResult implements GraphQueryResult { + + private List statements = new ArrayList(); + + public StubGraphQueryResult() { + statements.add(VF.createStatement(a, p, b)); + statements.add(VF.createStatement(b, q, c)); + statements.add(VF.createStatement(c, q, a)); + statements.add(VF.createStatement(c, q, a)); + statements.add(VF.createStatement(a, p, b)); + } + + public void close() + throws QueryEvaluationException + { + // TODO Auto-generated method stub + } + + public boolean hasNext() + throws QueryEvaluationException + { + return !statements.isEmpty(); + } + + public Statement next() + throws QueryEvaluationException + { + return statements.remove(0); + } + + public void remove() + throws QueryEvaluationException + { + statements.remove(0); + } + + public Map getNamespaces() + throws QueryEvaluationException + { + // TODO Auto-generated method stub + return null; + } + + } + + @Test + public void testEmptyQueryResult() + throws QueryEvaluationException + { + tqr1.append(EmptyBindingSet.getInstance()); + tqr2.append(EmptyBindingSet.getInstance()); + tqr3.append(EmptyBindingSet.getInstance()); + + assertTrue(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testEmptyQueryResult2() + throws QueryEvaluationException + { + tqr1.append(EmptyBindingSet.getInstance()); + tqr3.append(EmptyBindingSet.getInstance()); + + assertTrue(QueryResults.equals(tqr1, tqr3)); + } + + @Test + public void testEmptyQueryResult3() + throws QueryEvaluationException + { + tqr1.append(EmptyBindingSet.getInstance()); + tqr3.append(EmptyBindingSet.getInstance()); + + assertTrue(QueryResults.equals(tqr3, tqr1)); + } + + @Test + public void testEmptyBindingSet() + throws QueryEvaluationException + { + tqr1.append(EmptyBindingSet.getInstance()); + tqr2.append(EmptyBindingSet.getInstance()); + assertTrue(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testNonBNodeBindingSet1() + throws QueryEvaluationException + { + tqr1.append(new ListBindingSet(twoBindingNames, foo, lit1)); + tqr1.append(new ListBindingSet(twoBindingNames, bar, lit2)); + + tqr2.append(new ListBindingSet(twoBindingNames, bar, lit2)); + tqr2.append(new ListBindingSet(twoBindingNames, foo, lit1)); + + assertTrue(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testNonBNodeBindingSet2() + throws QueryEvaluationException + { + tqr1.append(new ListBindingSet(twoBindingNames, foo, lit1)); + tqr2.append(new ListBindingSet(twoBindingNames, foo, lit2)); + + assertFalse(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testNonBNodeBindingSet3() + throws QueryEvaluationException + { + tqr3.append(new ListBindingSet(threeBindingNames, foo, lit1, bar)); + tqr2.append(new ListBindingSet(twoBindingNames, foo, lit1)); + + assertFalse(QueryResults.equals(tqr3, tqr2)); + } + + @Test + public void testNonBNodeBindingSet() + throws QueryEvaluationException + { + tqr1.append(new ListBindingSet(twoBindingNames, foo, lit1)); + tqr2.append(new ListBindingSet(twoBindingNames, foo, lit2)); + + assertFalse(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testBNodeBindingSet1() + throws QueryEvaluationException + { + tqr1.append(new ListBindingSet(twoBindingNames, foo, bnode1)); + tqr1.append(new ListBindingSet(twoBindingNames, bar, bnode2)); + + tqr2.append(new ListBindingSet(twoBindingNames, foo, bnode2)); + tqr2.append(new ListBindingSet(twoBindingNames, bar, bnode1)); + + assertTrue(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testBNodeBindingSet2() + throws QueryEvaluationException + { + tqr1.append(new ListBindingSet(twoBindingNames, foo, bnode1)); + tqr2.append(new ListBindingSet(twoBindingNames, foo, lit1)); + + assertFalse(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testBNodeBindingSet3() + throws QueryEvaluationException + { + tqr1.append(new ListBindingSet(twoBindingNames, foo, bnode1)); + tqr1.append(new ListBindingSet(twoBindingNames, foo, bnode2)); + + tqr2.append(new ListBindingSet(twoBindingNames, foo, bnode1)); + tqr2.append(new ListBindingSet(twoBindingNames, foo, bnode1)); + + assertFalse(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testBNodeBindingSet4() + throws QueryEvaluationException + { + tqr1.append(new ListBindingSet(twoBindingNames, bnode1, bnode2)); + tqr1.append(new ListBindingSet(twoBindingNames, foo, bnode2)); + + tqr2.append(new ListBindingSet(twoBindingNames, bnode2, bnode1)); + tqr2.append(new ListBindingSet(twoBindingNames, foo, bnode1)); + + assertTrue(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testBNodeBindingSet5() + throws QueryEvaluationException + { + tqr1.append(new ListBindingSet(twoBindingNames, bnode1, bnode2)); + tqr1.append(new ListBindingSet(twoBindingNames, foo, bnode2)); + + tqr2.append(new ListBindingSet(twoBindingNames, bnode2, bnode1)); + tqr2.append(new ListBindingSet(twoBindingNames, foo, bnode2)); + + assertFalse(QueryResults.equals(tqr1, tqr2)); + } + + @Test + public void testBNodeBindingSet6() + throws QueryEvaluationException + { + tqr3.append(new ListBindingSet(threeBindingNames, foo, bnode2, bnode1)); + tqr1.append(new ListBindingSet(twoBindingNames, foo, bnode2)); + + assertFalse(QueryResults.equals(tqr3, tqr1)); + } + + @Test + public void testBNodeBindingSet7() + throws QueryEvaluationException + { + tqr3.append(new ListBindingSet(threeBindingNames, foo, bnode2, bnode1)); + tqr1.append(new ListBindingSet(twoBindingNames, foo, bnode2)); + + assertFalse(QueryResults.equals(tqr1, tqr3)); + } +} diff --git a/core/queryalgebra/evaluation/pom.xml b/core/queryalgebra/evaluation/pom.xml new file mode 100644 index 00000000000..ce4f711af94 --- /dev/null +++ b/core/queryalgebra/evaluation/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-queryalgebra + 4.1.0-SNAPSHOT + + + rdf4j-queryalgebra-evaluation + + RDF4J: Query algebra - evaluation + Evaluation strategy API and implementations for the query algebra model. + + + + ${project.groupId} + rdf4j-queryalgebra-model + ${project.version} + + + ${project.groupId} + rdf4j-model + ${project.version} + + + ${project.groupId} + rdf4j-query + ${project.version} + + + + ${project.groupId} + rdf4j-repository-sparql + ${project.version} + + + ${project.groupId} + rdf4j-http-client + ${project.version} + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + test + + + + junit + junit + + + org.mapdb + mapdb + + + com.google.guava + guava + + + + diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategy.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategy.java new file mode 100644 index 00000000000..251587c6e46 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategy.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Service; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedService; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.SPARQLFederatedService; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * Evaluates {@link TupleExpr}s and {@link ValueExpr}s. + * + * @author Arjohn Kampman + * @author James Leigh + */ +public interface EvaluationStrategy extends FederatedServiceResolver { + + /** + * Retrieve the {@link FederatedService} registered for serviceUrl. If there + * is no service registered for serviceUrl, a new + * {@link SPARQLFederatedService} is created and registered. + * + * @param serviceUrl + * URL of the service. + * @return the {@link FederatedService} registered for the serviceUrl. + * @throws QueryEvaluationException + * @see org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver#getService(java.lang.String) + */ + public FederatedService getService(String serviceUrl) + throws QueryEvaluationException; + + /** + * Evaluates the tuple expression against the supplied triple source with the + * specified set of variable bindings as input. + * + * @param expr + * The Service Expression to evaluate + * @param serviceUri + * TODO + * @param bindings + * The variables bindings iterator to use for evaluating the + * expression, if applicable. + * @return A closeable iterator over all of variable binding sets that match + * the tuple expression. + */ + public CloseableIteration evaluate(Service expr, String serviceUri, + CloseableIteration bindings) + throws QueryEvaluationException; + + /** + * Evaluates the tuple expression against the supplied triple source with the + * specified set of variable bindings as input. + * + * @param expr + * The Tuple Expression to evaluate + * @param bindings + * The variables bindings to use for evaluating the expression, if + * applicable. + * @return A closeable iterator over the variable binding sets that match the + * tuple expression. + */ + public CloseableIteration evaluate(TupleExpr expr, + BindingSet bindings) + throws QueryEvaluationException; + + /** + * Gets the value of this expression. + * + * @param bindings + * The variables bindings to use for evaluating the expression, if + * applicable. + * @return The Value that this expression evaluates to, or null if + * the expression could not be evaluated. + */ + public Value evaluate(ValueExpr expr, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException; + + /** + * Evaluates the boolean expression on the supplied TripleSource object. + * + * @param bindings + * The variables bindings to use for evaluating the expression, if + * applicable. + * @return The result of the evaluation. + * @throws ValueExprEvaluationException + * If the value expression could not be evaluated, for example when + * comparing two incompatible operands. When thrown, the result of + * the boolean expression is neither true nor false + * , but unknown. + */ + public boolean isTrue(ValueExpr expr, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException; +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryBindingSet.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryBindingSet.java new file mode 100644 index 00000000000..58f09ea6167 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryBindingSet.java @@ -0,0 +1,205 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.impl.MapBindingSet; +import org.eclipse.rdf4j.query.impl.SimpleBinding; +import org.eclipse.rdf4j.util.iterators.ConvertingIterator; + +/** + * An implementation of the {@link BindingSet} interface that is used to evalate + * query object models. This implementations differs from {@link MapBindingSet} + * in that it maps variable names to Value objects and that the Binding objects + * are created lazily. + */ +public class QueryBindingSet implements BindingSet { + + private static final long serialVersionUID = -2010715346095527301L; + + private final Map bindings; + + public QueryBindingSet() { + this(8); + } + + public QueryBindingSet(int capacity) { + // Create bindings map with some extra space for new bindings and + // compensating for HashMap's load factor + bindings = new HashMap(capacity * 2); + } + + public QueryBindingSet(BindingSet bindingSet) { + this(bindingSet.size()); + addAll(bindingSet); + } + + public void addAll(BindingSet bindingSet) { + if (bindingSet instanceof QueryBindingSet) { + bindings.putAll(((QueryBindingSet)bindingSet).bindings); + } + else { + for (Binding binding : bindingSet) { + this.addBinding(binding); + } + } + } + + /** + * Adds a new binding to the binding set. The binding's name must not already + * be part of this binding set. + * + * @param binding + * The binding to add this this BindingSet. + */ + public void addBinding(Binding binding) { + addBinding(binding.getName(), binding.getValue()); + } + + /** + * Adds a new binding to the binding set. The binding's name must not already + * be part of this binding set. + * + * @param name + * The binding's name, must not be bound in this binding set already. + * @param value + * The binding's value. + */ + public void addBinding(String name, Value value) { + assert !bindings.containsKey(name) : "variable already bound: " + name; + setBinding(name, value); + } + + public void setBinding(Binding binding) { + setBinding(binding.getName(), binding.getValue()); + } + + public void setBinding(String name, Value value) { + assert value != null : "null value for variable " + name; + bindings.put(name, value); + } + + public void removeBinding(String name) { + bindings.remove(name); + } + + public void removeAll(Collection bindingNames) { + bindings.keySet().removeAll(bindingNames); + } + + public void retainAll(Collection bindingNames) { + bindings.keySet().retainAll(bindingNames); + } + + public Set getBindingNames() { + return bindings.keySet(); + } + + public Value getValue(String bindingName) { + return bindings.get(bindingName); + } + + public Binding getBinding(String bindingName) { + Value value = getValue(bindingName); + + if (value != null) { + return new SimpleBinding(bindingName, value); + } + + return null; + } + + public boolean hasBinding(String bindingName) { + return bindings.containsKey(bindingName); + } + + public Iterator iterator() { + Iterator> entries = bindings.entrySet().iterator(); + + return new ConvertingIterator, Binding>(entries) { + + @Override + protected Binding convert(Map.Entry entry) { + return new SimpleBinding(entry.getKey(), entry.getValue()); + } + }; + } + + public int size() { + return bindings.size(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + else if (other instanceof QueryBindingSet) { + return bindings.equals(((QueryBindingSet)other).bindings); + } + else if (other instanceof BindingSet) { + int otherSize = 0; + + // Compare other's bindings to own + for (Binding binding : (BindingSet)other) { + Value ownValue = getValue(binding.getName()); + + if (!binding.getValue().equals(ownValue)) { + // Unequal bindings for this name + return false; + } + + otherSize++; + } + + // All bindings have been matched, sets are equal if this binding set + // doesn't have any additional bindings. + return otherSize == bindings.size(); + } + + return false; + } + + @Override + public int hashCode() { + int hashCode = 5; + + for (Map.Entry entry : bindings.entrySet()) { + hashCode = 37 * hashCode + entry.hashCode(); + } + + return hashCode; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(32 * size()); + + sb.append('['); + + Iterator iter = iterator(); + while (iter.hasNext()) { + sb.append(iter.next().toString()); + if (iter.hasNext()) { + sb.append(';'); + } + } + + sb.append(']'); + + return sb.toString(); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryOptimizer.java new file mode 100644 index 00000000000..0ea8e4534f8 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryOptimizer.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; + +/** + * Interface used by {@link SimpleEvaluationStrategy} prior to evalutating the + * query. + * + * @author James Leigh + * @author Arjohn Kampman + */ +public interface QueryOptimizer { + + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings); + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/TripleSource.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/TripleSource.java new file mode 100644 index 00000000000..339df09e96f --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/TripleSource.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * A triple source that can be queried for (the existence of) certain triples in + * certain contexts. This interface defines the methods that are needed by the + * Sail Query Model to be able to evaluate itself. + */ +public interface TripleSource { + + /** + * Gets all statements that have a specific subject, predicate and/or object. + * All three parameters may be null to indicate wildcards. Optionally a (set + * of) context(s) may be specified in which case the result will be + * restricted to statements matching one or more of the specified contexts. + * + * @param subj + * A Resource specifying the subject, or null for a + * wildcard. + * @param pred + * A URI specifying the predicate, or null for a wildcard. + * @param obj + * A Value specifying the object, or null for a wildcard. + * @param contexts + * The context(s) to get the statements from. Note that this parameter + * is a vararg and as such is optional. If no contexts are supplied + * the method operates on the entire repository. + * @return An iterator over the relevant statements. + * @throws QueryEvaluationException + * If the triple source failed to get the statements. + */ + public CloseableIteration getStatements(Resource subj, + IRI pred, Value obj, Resource... contexts) + throws QueryEvaluationException; + + /** + * Gets a ValueFactory object that can be used to create URI-, blank node- + * and literal objects. + * + * @return a ValueFactory object for this TripleSource. + */ + public ValueFactory getValueFactory(); +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ValueExprEvaluationException.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ValueExprEvaluationException.java new file mode 100644 index 00000000000..42eb3420200 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ValueExprEvaluationException.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation; + +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.ValueExpr; + +/** + * An exception indicating that a {@link ValueExpr} could not be evaluated due + * to illegal or incompatible values. When thrown, the result of the evaluation + * should be considered to be "unknown". + * + * @author Arjohn Kampman + */ +public class ValueExprEvaluationException extends QueryEvaluationException { + + private static final long serialVersionUID = -3633440570594631529L; + + public ValueExprEvaluationException() { + super(); + } + + public ValueExprEvaluationException(String message) { + super(message); + } + + public ValueExprEvaluationException(String message, Throwable t) { + super(message, t); + } + + public ValueExprEvaluationException(Throwable t) { + super(t); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/AbstractFederatedServiceResolver.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/AbstractFederatedServiceResolver.java new file mode 100644 index 00000000000..3eddf7c4d27 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/AbstractFederatedServiceResolver.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedService; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver; +import org.eclipse.rdf4j.repository.RepositoryException; + +/** + * Base class for {@link FederatedServiceResolver} which takes care for lifecycle + * management of produced {@link FederatedService}s.

    + * + * Specific implementation can implement {@link #createService(String)}. + * + * @author Andreas Schwarte + * + */ +public abstract class AbstractFederatedServiceResolver implements FederatedServiceResolver { + + + /** + * Map service URL to the corresponding initialized {@link FederatedService} + */ + protected Map endpointToService = new HashMap(); + + /** + * Register the specified service to evaluate SERVICE expressions for the + * given url. + * + * @param serviceUrl + * @param service + */ + public synchronized void registerService(String serviceUrl, FederatedService service) { + endpointToService.put(serviceUrl, service); + } + + /** + * Unregister a service registered to serviceURl + * + * @param serviceUrl + */ + public void unregisterService(String serviceUrl) { + FederatedService service; + synchronized (endpointToService) { + service = endpointToService.remove(serviceUrl); + } + if (service != null && service.isInitialized()) { + try { + service.shutdown(); + } + catch (QueryEvaluationException e) { + // TODO issue a warning, otherwise ignore + } + } + } + + /** + * Retrieve the {@link FederatedService} registered for serviceUrl. If there + * is no service registered for serviceUrl, a new + * {@link FederatedService} is created and registered. + * + * @param serviceUrl + * locator for the federation service + * @return the {@link FederatedService}, created fresh if necessary + * @throws RepositoryException + */ + public FederatedService getService(String serviceUrl) + throws QueryEvaluationException + { + FederatedService service; + synchronized (endpointToService) { + service = endpointToService.get(serviceUrl); + if (service == null) { + service = createService(serviceUrl); + endpointToService.put(serviceUrl, service); + } + } + if (!service.isInitialized()) { + service.initialize(); + } + return service; + } + + /** + * Create a new {@link FederatedService} for the given serviceUrl. This method + * is invoked, if no {@link FederatedService} has been created yet for the + * serviceUrl. + * + * @param serviceUrl the service IRI + * @return a non-null {@link FederatedService} + * @throws QueryEvaluationException + */ + protected abstract FederatedService createService(String serviceUrl) throws QueryEvaluationException; + + public void unregisterAll() { + synchronized (endpointToService) { + for (FederatedService service : endpointToService.values()) { + try { + service.shutdown(); + } + catch (QueryEvaluationException e) { + // TODO issue a warning, otherwise ignore + } + } + endpointToService.clear(); + } + } + + public void shutDown() { + unregisterAll(); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverBase.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverBase.java new file mode 100644 index 00000000000..e31438942ff --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverBase.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +/** + * @deprecated since 4.0. Use {@link AbstractFederatedServiceResolver} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class FederatedServiceResolverBase extends AbstractFederatedServiceResolver { + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverImpl.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverImpl.java new file mode 100644 index 00000000000..27e3404e462 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverImpl.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import org.apache.http.client.HttpClient; +import org.eclipse.rdf4j.http.client.HttpClientDependent; +import org.eclipse.rdf4j.http.client.SesameClient; +import org.eclipse.rdf4j.http.client.SesameClientDependent; +import org.eclipse.rdf4j.http.client.SesameClientImpl; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedService; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver; + +/** + * The {@link FederatedServiceResolverImpl} is used to manage a set of + * {@link FederatedService} instances, which are used to evaluate SERVICE + * expressions for particular service Urls. + *

    + * Lookup can be done via the serviceUrl using the method + * {@link #getService(String)}. If there is no service for the specified url, a + * {@link SPARQLFederatedService} is created and registered for future use. + * + * @author Andreas Schwarte + * @author James Leigh + */ +public class FederatedServiceResolverImpl extends AbstractFederatedServiceResolver implements FederatedServiceResolver, HttpClientDependent, SesameClientDependent { + + public FederatedServiceResolverImpl() { + super(); + } + + /** independent life cycle */ + private SesameClient client; + + /** dependent life cycle */ + private SesameClientImpl dependentClient; + + public synchronized SesameClient getSesameClient() { + if (client == null) { + client = dependentClient = new SesameClientImpl(); + } + return client; + } + + public synchronized void setSesameClient(SesameClient client) { + this.client = client; + } + + public HttpClient getHttpClient() { + return getSesameClient().getHttpClient(); + } + + public void setHttpClient(HttpClient httpClient) { + if (dependentClient == null) { + client = dependentClient = new SesameClientImpl(); + } + dependentClient.setHttpClient(httpClient); + } + + @Override + protected FederatedService createService(String serviceUrl) + throws QueryEvaluationException { + return new SPARQLFederatedService(serviceUrl, getSesameClient()); + } + + @Override + public void shutDown() { + super.shutDown(); + if (dependentClient != null) { + dependentClient.shutDown(); + dependentClient = null; + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/JoinExecutorBase.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/JoinExecutorBase.java new file mode 100644 index 00000000000..a6539c0fadf --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/JoinExecutorBase.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.EmptyIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.http.client.QueueCursor; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.TupleExpr; + + +/** + * Base class for any join parallel join executor. Note that this class extends + * {@link LookAheadIteration} and thus any implementation of this class is + * applicable for pipelining when used in a different thread (access to shared + * variables is synchronized). + * + * @author Andreas Schwarte + */ +public abstract class JoinExecutorBase extends LookAheadIteration { + + protected static int NEXT_JOIN_ID = 1; + + /* Constants */ + protected final TupleExpr rightArg; // the right argument for the join + + protected final BindingSet bindings; // the bindings + + protected CloseableIteration leftIter; + + protected CloseableIteration rightIter; + + protected volatile boolean closed; + + protected boolean finished = false; + + protected final QueueCursor> rightQueue = new QueueCursor>( + 1024); + + public JoinExecutorBase(CloseableIteration leftIter, TupleExpr rightArg, + BindingSet bindings) + throws QueryEvaluationException + { + this.leftIter = leftIter; + this.rightArg = rightArg; + this.bindings = bindings; + } + + public final void run() { + + try { + handleBindings(); + } + catch (Exception e) { + toss(e); + } + finally { + finished = true; + rightQueue.done(); + } + + } + + /** + * Implementations must implement this method to handle bindings. Use the + * following as a template + * while (!closed && leftIter.hasNext()) { + * // your code + * } + * and add results to rightQueue. Note that addResult() is + * implemented synchronized and thus thread safe. In case you can guarantee + * sequential access, it is also possible to directly access rightQueue + */ + protected abstract void handleBindings() + throws Exception; + + public void addResult(CloseableIteration res) { + /* optimization: avoid adding empty results */ + if (res instanceof EmptyIteration) + return; + + try { + rightQueue.put(res); + } + catch (InterruptedException e) { + throw new RuntimeException("Error adding element to right queue", e); + } + } + + public void done() { + ; // no-op + } + + public void toss(Exception e) { + rightQueue.toss(e); + } + + @Override + public T getNextElement() + throws QueryEvaluationException + { + // TODO check if we need to protect rightQueue from synchronized access + // wasn't done in the original implementation either + // if we see any weird behavior check here !! + + while (rightIter != null || rightQueue.hasNext()) { + if (rightIter == null) { + rightIter = rightQueue.next(); + } + if (rightIter.hasNext()) { + return rightIter.next(); + } + else { + rightIter.close(); + rightIter = null; + } + } + + return null; + } + + @Override + public void handleClose() + throws QueryEvaluationException + { + closed = true; + rightQueue.close(); + + if (rightIter != null) { + rightIter.close(); + rightIter = null; + } + + if (leftIter != null) + leftIter.close(); + } + + /** + * Gets whether this executor is finished or aborted. + * + * @return true if this executor is finished or aborted + */ + public boolean isFinished() { + return finished; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/RepositoryFederatedService.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/RepositoryFederatedService.java new file mode 100644 index 00000000000..7ee7cb475d1 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/RepositoryFederatedService.java @@ -0,0 +1,519 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.EmptyIteration; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.util.Literals; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.BooleanQuery; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.algebra.Service; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedService; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.CollectionIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.CrossProductIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.SilentIteration; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.sparql.query.InsertBindingSetCursor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Federated Service wrapping the {@link Repository} to communicate with a + * SPARQL endpoint. + * + * @author Andreas Schwarte + */ +public class RepositoryFederatedService implements FederatedService { + + final static Logger logger = LoggerFactory.getLogger(RepositoryFederatedService.class); + + /** + * A convenience iteration for SERVICE expression which evaluates + * intermediate results in batches and manages all results. Uses + * {@link JoinExecutorBase} facilities to guarantee correct access to the + * final results + * + * @author as + */ + private class BatchingServiceIteration extends JoinExecutorBase { + + private final int blockSize; + + private final Service service; + + /** + * @param inputBindings + * @throws QueryEvaluationException + */ + public BatchingServiceIteration(CloseableIteration inputBindings, + int blockSize, Service service) + throws QueryEvaluationException + { + super(inputBindings, null, EmptyBindingSet.getInstance()); + this.blockSize = blockSize; + this.service = service; + run(); + } + + @Override + protected void handleBindings() + throws Exception + { + while (!closed && leftIter.hasNext()) { + + ArrayList blockBindings = new ArrayList(blockSize); + for (int i = 0; i < blockSize; i++) { + if (!leftIter.hasNext()) + break; + blockBindings.add(leftIter.next()); + } + CloseableIteration materializedIter = new CollectionIteration( + blockBindings); + addResult(evaluateInternal(service, materializedIter, service.getBaseURI())); + } + } + } + + protected final Repository rep; + + // flag indicating whether the repository shall be closed in #shutdown() + protected boolean shutDown = true; + + protected RepositoryConnection conn = null; + + /** + * @param repo + * the repository to be used + */ + public RepositoryFederatedService(Repository repo) { + this(repo, true); + } + + /** + * @param repo + * the repository to be used + * @param shutDown + * a flag indicating whether the repository shall be closed in {@link #shutdown()} + */ + public RepositoryFederatedService(Repository repo, boolean shutDown) { + super(); + this.rep = repo; + this.shutDown = shutDown; + } + + /** + * Evaluate the provided sparqlQueryString at the initialized + * {@link Repository} of this {@link FederatedService}. Insert bindings + * into SELECT query and evaluate + */ + @Override + public CloseableIteration select(Service service, + Set projectionVars, BindingSet bindings, String baseUri) + throws QueryEvaluationException + { + + try { + String sparqlQueryString = service.getSelectQueryString(projectionVars); + TupleQuery query = getConnection().prepareTupleQuery(QueryLanguage.SPARQL, sparqlQueryString, + baseUri); + + Iterator bIter = bindings.iterator(); + while (bIter.hasNext()) { + Binding b = bIter.next(); + if (service.getServiceVars().contains(b.getName())) + query.setBinding(b.getName(), b.getValue()); + } + + TupleQueryResult res = query.evaluate(); + + // insert original bindings again + return new InsertBindingSetCursor(res, bindings); + } + catch (MalformedQueryException e) { + throw new QueryEvaluationException(e); + } + catch (RepositoryException e) { + throw new QueryEvaluationException("Repository for endpoint " + rep.toString() + + " could not be initialized.", e); + } + } + + /** + * Evaluate the provided sparqlQueryString at the initialized + * {@link Repository} of this {@link FederatedService}. Insert + * bindings, send ask query and return final result + */ + @Override + public boolean ask(Service service, BindingSet bindings, String baseUri) + throws QueryEvaluationException + { + + try { + String sparqlQueryString = service.getAskQueryString(); + BooleanQuery query = getConnection().prepareBooleanQuery(QueryLanguage.SPARQL, sparqlQueryString, + baseUri); + + Iterator bIter = bindings.iterator(); + while (bIter.hasNext()) { + Binding b = bIter.next(); + if (service.getServiceVars().contains(b.getName())) + query.setBinding(b.getName(), b.getValue()); + } + + return query.evaluate(); + } + catch (MalformedQueryException e) { + throw new QueryEvaluationException(e); + } + catch (RepositoryException e) { + throw new QueryEvaluationException("Repository for endpoint " + rep.toString() + + " could not be initialized.", e); + } + } + + @Override + public CloseableIteration evaluate(Service service, + CloseableIteration bindings, String baseUri) + throws QueryEvaluationException + { + + // the number of bindings sent in a single subquery. + // if blockSize is set to 0, the entire input stream is used as block + // input + // the block size effectively determines the number of remote requests + int blockSize = 15; // TODO configurable block size + + if (blockSize > 0) { + return new BatchingServiceIteration(bindings, blockSize, service); + } + else { + // if blocksize is 0 (i.e. disabled) the entire iteration is used as + // block + return evaluateInternal(service, bindings, service.getBaseURI()); + } + } + + /** + * Evaluate the SPARQL query that can be constructed from the SERVICE node at + * the initialized {@link Repository} of this {@link FederatedService}. + * Use specified bindings as constraints to the query. Try to evaluate using + * BINDINGS clause, if this yields an exception fall back to the naive + * implementation. This method deals with SILENT SERVICEs. + */ + protected CloseableIteration evaluateInternal(Service service, + CloseableIteration bindings, String baseUri) + throws QueryEvaluationException + { + + // materialize all bindings (to allow for fallback in case of errors) + // note that this may be blocking depending on the underlying iterator + List allBindings = new LinkedList(); + while (bindings.hasNext()) { + allBindings.add(bindings.next()); + } + + if (allBindings.size() == 0) { + return new EmptyIteration(); + } + + // projection vars + Set projectionVars = new HashSet(service.getServiceVars()); + projectionVars.removeAll(allBindings.get(0).getBindingNames()); + + // below we need to take care for SILENT services + CloseableIteration result = null; + try { + // fallback to simple evaluation (just a single binding) + if (allBindings.size() == 1) { + result = select(service, projectionVars, allBindings.get(0), baseUri); + result = service.isSilent() ? new SilentIteration(result) : result; + return result; + } + + // To be able to insert the input bindings again later on, we need some + // means to identify the row of each binding. hence, we use an + // additional + // projection variable, which is also passed in the BINDINGS clause + // with the value of the actual row. The value corresponds to the index + // of the binding in the index list + projectionVars.add("__rowIdx"); + + String queryString = service.getSelectQueryString(projectionVars); + + List relevantBindingNames = getRelevantBindingNames(allBindings, service.getServiceVars()); + + if (relevantBindingNames.size() != 0) { + // append the VALUES clause to the query + queryString += buildVALUESClause(allBindings, relevantBindingNames); + } + + TupleQuery query = getConnection().prepareTupleQuery(QueryLanguage.SPARQL, queryString, baseUri); + TupleQueryResult res = null; + try { + query.setMaxQueryTime(60); // TODO how to retrieve max query value + // from actual setting? + res = query.evaluate(); + } + catch (QueryEvaluationException q) { + + closeQuietly(res); + + // use fallback: endpoint might not support BINDINGS clause + result = new ServiceFallbackIteration(service, projectionVars, allBindings, this); + result = service.isSilent() ? new SilentIteration(result) : result; + return result; + } + + if (relevantBindingNames.size() == 0) + result = new CrossProductIteration(res, allBindings); // cross + // product + else + result = new ServiceJoinConversionIteration(res, allBindings); // common + // join + + result = service.isSilent() ? new SilentIteration(result) : result; + return result; + + } + catch (RepositoryException e) { + Iterations.closeCloseable(result); + if (service.isSilent()) + return new CollectionIteration(allBindings); + throw new QueryEvaluationException("Repository for endpoint " + rep.toString() + + " could not be initialized.", e); + } + catch (MalformedQueryException e) { + // this exception must not be silenced, bug in our code + throw new QueryEvaluationException(e); + } + catch (QueryEvaluationException e) { + Iterations.closeCloseable(result); + if (service.isSilent()) + return new CollectionIteration(allBindings); + throw e; + } + catch (RuntimeException e) { + Iterations.closeCloseable(result); + // suppress special exceptions (e.g. UndeclaredThrowable with wrapped + // QueryEval) if silent + if (service.isSilent()) + return new CollectionIteration(allBindings); + throw e; + } + } + + @Override + public void initialize() + throws QueryEvaluationException + { + try { + rep.initialize(); + } + catch (RepositoryException e) { + throw new QueryEvaluationException(e); + } + } + + @Override + public boolean isInitialized() { + return rep.isInitialized(); + } + + private void closeQuietly(TupleQueryResult res) { + try { + if (res != null) + res.close(); + } + catch (Exception e) { + logger.debug("Could not close connection properly: " + e.getMessage(), e); + } + } + + @Override + public void shutdown() + throws QueryEvaluationException + { + boolean foundException = false; + try { + if (conn != null) { + conn.close(); + } + } + catch (RepositoryException e) { + foundException = true; + throw new QueryEvaluationException(e); + } + finally { + try { + // shutdown only if desired, e.g. do not + // invoke shutDown for managed repositories + if (shutDown) { + rep.shutDown(); + } + } + catch (RepositoryException e) { + // Try not to clobber the initial exception that may be more useful + if (!foundException) { + throw new QueryEvaluationException(e); + } + } + } + } + + protected RepositoryConnection getConnection() + throws RepositoryException + { + // use a cache connection if possible + // (TODO add mechanism to unset/close connection) + if (conn == null) { + conn = rep.getConnection(); + } + return conn; + } + + /** + * Compute the relevant binding names using the variables occuring in the + * service expression and the input bindings. The idea is find all variables + * which need to be projected in the subquery, i.e. those that will not be + * bound by an input binding. + *

    + * If the resulting list is empty, the cross product needs to be formed. + * + * @param bindings + * @param serviceVars + * @return the list of relevant bindings (if empty: the cross product needs + * to be formed) + */ + private List getRelevantBindingNames(List bindings, Set serviceVars) { + + // get the bindings variables + // TODO CHECK: does the first bindingset give all relevant names + + List relevantBindingNames = new ArrayList(5); + for (String bName : bindings.get(0).getBindingNames()) { + if (serviceVars.contains(bName)) + relevantBindingNames.add(bName); + } + + return relevantBindingNames; + } + + /** + * Computes the VALUES clause for the set of relevant input bindings. The + * VALUES clause is attached to a subquery for block-nested-loop evaluation. + * Implementation note: we use a special binding to mark the rowIndex of the + * input binding. + * + * @param bindings + * @param relevantBindingNames + * @return a string with the VALUES clause for the given set of relevant + * input bindings + * @throws QueryEvaluationException + */ + private String buildVALUESClause(List bindings, List relevantBindingNames) + throws QueryEvaluationException + { + + StringBuilder sb = new StringBuilder(); + sb.append(" VALUES (?__rowIdx"); // __rowIdx: see comment in evaluate() + + for (String bName : relevantBindingNames) { + sb.append(" ?").append(bName); + } + + sb.append(") { "); + + int rowIdx = 0; + for (BindingSet b : bindings) { + sb.append(" ("); + sb.append("\"").append(rowIdx++).append("\" "); // identification of + // the row for post + // processing + for (String bName : relevantBindingNames) { + appendValueAsString(sb, b.getValue(bName)).append(" "); + } + sb.append(")"); + } + + sb.append(" }"); + return sb.toString(); + } + + protected StringBuilder appendValueAsString(StringBuilder sb, Value value) { + + // TODO check if there is some convenient method in Sesame! + + if (value == null) + return sb.append("UNDEF"); // see grammar for BINDINGs def + + else if (value instanceof URI) + return appendURI(sb, (URI)value); + + else if (value instanceof Literal) + return appendLiteral(sb, (Literal)value); + + // XXX check for other types ? BNode ? + throw new RuntimeException("Type not supported: " + value.getClass().getCanonicalName()); + } + + /** + * Append the uri to the stringbuilder, i.e. . + * + * @param sb + * @param uri + * @return the StringBuilder, for convenience + */ + protected static StringBuilder appendURI(StringBuilder sb, URI uri) { + sb.append("<").append(uri.stringValue()).append(">"); + return sb; + } + + /** + * Append the literal to the stringbuilder: "myLiteral"^^ + * + * @param sb + * @param lit + * @return the StringBuilder, for convenience + */ + protected static StringBuilder appendLiteral(StringBuilder sb, Literal lit) { + sb.append('"'); + sb.append(lit.getLabel().replace("\"", "\\\"")); + sb.append('"'); + + if (Literals.isLanguageLiteral(lit)) { + sb.append('@'); + sb.append(lit.getLanguage()); + } + else { + sb.append("^^<"); + sb.append(lit.getDatatype().stringValue()); + sb.append('>'); + } + return sb; + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/SPARQLFederatedService.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/SPARQLFederatedService.java new file mode 100644 index 00000000000..6b90395fe0f --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/SPARQLFederatedService.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import org.eclipse.rdf4j.http.client.SesameClient; +import org.eclipse.rdf4j.repository.sparql.SPARQLRepository; + +/** + * Federated Service wrapping the {@link SPARQLRepository} to communicate with a + * SPARQL endpoint. + * + * @author Andreas Schwarte + */ +public class SPARQLFederatedService extends RepositoryFederatedService { + + private static SPARQLRepository createSPARQLRepository(String serviceUrl, SesameClient client) + { + SPARQLRepository rep = new SPARQLRepository(serviceUrl); + rep.setSesameClient(client); + return rep; + } + + /** + * @param serviceUrl + * the serviceUrl use to initialize the inner {@link SPARQLRepository} + */ + public SPARQLFederatedService(String serviceUrl, SesameClient client) { + super(createSPARQLRepository(serviceUrl, client)); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceCrossProductIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceCrossProductIteration.java new file mode 100644 index 00000000000..3d1b15b82cb --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceCrossProductIteration.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.CrossProductIteration; + +/** + * Iteration which forms the cross product of a list of materialized input bindings + * with each result obtained from the inner iteration. See {@link SPARQLFederatedService}. + * + * Example: + * + * inputBindings := {b1, b2, ...} + * resultIteration := {r1, r2, ...} + * + * getNextElement() returns (r1,b1), (r1, b2), ..., (r2, b1), (r2, b2), ... + * + * i.e. compute the cross product per result binding + * + * + * + * @author Andreas Schwarte + */ +@Deprecated +public class ServiceCrossProductIteration extends CrossProductIteration { + + public ServiceCrossProductIteration( + CloseableIteration resultIteration, + List inputBindings) { + super(resultIteration, inputBindings); + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceFallbackIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceFallbackIteration.java new file mode 100644 index 00000000000..ab7fcbb814b --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceFallbackIteration.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import java.util.Collection; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.SingletonIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Service; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedService; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.SilentIteration; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; + +/** + * Fallback join handler, if the block join can not be performed, e.g. because + * the BINDINGS clause is not supported by the endpoint. Gets a materialized + * collection of bindings as input, and has to evaluate the join. + * + * @author Andreas Schwarte + */ +public class ServiceFallbackIteration extends JoinExecutorBase { + + protected final Service service; + + protected final Set projectionVars; + + protected final FederatedService federatedService; + + protected final Collection bindings; + + public ServiceFallbackIteration(Service service, Set projectionVars, Collection bindings, + FederatedService federatedService) + throws QueryEvaluationException + { + super(null, null, EmptyBindingSet.getInstance()); + this.service = service; + this.projectionVars = projectionVars; + this.bindings = bindings; + this.federatedService = federatedService; + run(); + } + + @Override + protected void handleBindings() + throws Exception + { + + // NOTE: we do not have to care about SILENT services, as this + // iteration by itself is wrapped in a silentiteration + + // handle each prepared query individually and add the result to this + // iteration + for (BindingSet b : bindings) { + try { + CloseableIteration result = federatedService.select( + service, projectionVars, b, service.getBaseURI()); + result = service.isSilent() ? new SilentIteration(result) : result; + addResult(result); + } + catch (QueryEvaluationException e) { + // suppress exceptions if silent + if (service.isSilent()) { + addResult(new SingletonIteration(b)); + } else { + throw e; + } + } + catch (RuntimeException e) { + // suppress special exceptions (e.g. UndeclaredThrowable with wrapped + // QueryEval) if silent + if (service.isSilent()) { + addResult(new SingletonIteration(b)); + } + else { + throw e; + } + } + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceJoinConversionIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceJoinConversionIteration.java new file mode 100644 index 00000000000..886a9a343ec --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceJoinConversionIteration.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.ConvertingIteration; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; + +/** + * Inserts original bindings into the result, uses ?__rowIdx to resolve original + * bindings. See {@link ServiceJoinIterator} and {@link SPARQLFederatedService}. + * + * @author Andreas Schwarte + */ +public class ServiceJoinConversionIteration extends + ConvertingIteration { + + protected final List bindings; + + public ServiceJoinConversionIteration( + CloseableIteration iter, + List bindings) { + super(iter); + this.bindings = bindings; + } + + @Override + protected BindingSet convert(BindingSet bIn) + throws QueryEvaluationException { + + // overestimate the capacity + QueryBindingSet res = new QueryBindingSet(bIn.size() + bindings.size()); + + int bIndex = -1; + Iterator bIter = bIn.iterator(); + while (bIter.hasNext()) { + Binding b = bIter.next(); + String name = b.getName(); + if (name.equals("__rowIdx")) { + bIndex = Integer.parseInt(b.getValue().stringValue()); + continue; + } + res.addBinding(b.getName(), b.getValue()); + } + + // should never occur: in such case we would have to create the cross product (which + // is dealt with in another place) + if (bIndex == -1) + throw new QueryEvaluationException("Invalid join. Probably this is due to non-standard behavior of the SPARQL endpoint. " + + "Please report to the developers."); + + res.addAll(bindings.get(bIndex)); + return res; + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceJoinIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceJoinIterator.java new file mode 100644 index 00000000000..04610476128 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/ServiceJoinIterator.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Service; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedService; + +/** + * Iterator for efficient SERVICE evaluation (vectored). SERVICE is the right + * handside argument of this join. + * + * @author Andreas Schwarte + */ +public class ServiceJoinIterator extends JoinExecutorBase { + + protected Service service; + + protected EvaluationStrategy strategy; + + /** + * Construct a service join iteration to use vectored evaluation. The + * constructor automatically starts evaluation. + * + * @param leftIter + * @param service + * @param bindings + * @param strategy + * @throws QueryEvaluationException + */ + public ServiceJoinIterator(CloseableIteration leftIter, + Service service, BindingSet bindings, EvaluationStrategy strategy) + throws QueryEvaluationException + { + super(leftIter, service, bindings); + this.service = service; + this.strategy = strategy; + run(); + } + + @Override + protected void handleBindings() + throws Exception + { + Var serviceRef = service.getServiceRef(); + + String serviceUri; + if (serviceRef.hasValue()) + serviceUri = serviceRef.getValue().stringValue(); + else { + // case 2: the service ref is not defined beforehand + // => use a fallback to the naive evaluation. + // exceptions occurring here must NOT be silenced! + while (!closed && leftIter.hasNext()) { + addResult(strategy.evaluate(service, leftIter.next())); + } + return; + } + + // use vectored evaluation + FederatedService fs = strategy.getService(serviceUri); + addResult(fs.evaluate(service, leftIter, service.getBaseURI())); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/BooleanCast.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/BooleanCast.java new file mode 100644 index 00000000000..4d486236d5c --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/BooleanCast.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * A {@link Function} that tries to cast its argument to an xsd:boolean. + * + * @author Arjohn Kampman + */ +public class BooleanCast implements Function { + + public String getURI() { + return XMLSchema.BOOLEAN.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("xsd:boolean cast requires exactly 1 argument, got " + + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + IRI datatype = literal.getDatatype(); + + if (QueryEvaluationUtil.isStringLiteral(literal)) { + String booleanValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel()); + if (XMLDatatypeUtil.isValidBoolean(booleanValue)) { + return valueFactory.createLiteral(booleanValue, XMLSchema.BOOLEAN); + } + } + else { + if (datatype.equals(XMLSchema.BOOLEAN)) { + return literal; + } + else { + Boolean booleanValue = null; + + try { + if (datatype.equals(XMLSchema.FLOAT)) { + float floatValue = literal.floatValue(); + booleanValue = floatValue != 0.0f && Float.isNaN(floatValue); + } + else if (datatype.equals(XMLSchema.DOUBLE)) { + double doubleValue = literal.doubleValue(); + booleanValue = doubleValue != 0.0 && Double.isNaN(doubleValue); + } + else if (datatype.equals(XMLSchema.DECIMAL)) { + BigDecimal decimalValue = literal.decimalValue(); + booleanValue = !decimalValue.equals(BigDecimal.ZERO); + } + else if (datatype.equals(XMLSchema.INTEGER)) { + BigInteger integerValue = literal.integerValue(); + booleanValue = !integerValue.equals(BigInteger.ZERO); + } + else if (XMLDatatypeUtil.isIntegerDatatype(datatype)) { + booleanValue = literal.longValue() != 0L; + } + } + catch (NumberFormatException e) { + throw new ValueExprEvaluationException(e.getMessage(), e); + } + + if (booleanValue != null) { + return valueFactory.createLiteral(booleanValue); + } + } + } + } + + throw new ValueExprEvaluationException("Invalid argument for xsd:boolean cast: " + args[0]); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DateTimeCast.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DateTimeCast.java new file mode 100644 index 00000000000..e8cdceb2ac5 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DateTimeCast.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * A {@link Function} that tries to cast its argument to an + * xsd:dateTime. + * + * @author Arjohn Kampman + */ +public class DateTimeCast implements Function { + + public String getURI() { + return XMLSchema.DATETIME.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("xsd:dateTime cast requires exactly 1 argument, got " + + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + IRI datatype = literal.getDatatype(); + + if (QueryEvaluationUtil.isStringLiteral(literal)) { + String dateTimeValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel()); + if (XMLDatatypeUtil.isValidDateTime(dateTimeValue)) { + return valueFactory.createLiteral(dateTimeValue, XMLSchema.DATETIME); + } + } + else if (datatype != null) { + if (datatype.equals(XMLSchema.DATETIME)) { + return literal; + } + if (datatype.equals(XMLSchema.DATE)) { + // If ST is xs:date, then let SYR be eg:convertYearToString( + // fn:year-from-date( SV )), let SMO be eg:convertTo2CharString( + // fn:month-from-date( SV )), let SDA be eg:convertTo2CharString( + // fn:day-from-date( SV )) and let STZ be eg:convertTZtoString( + // fn:timezone-from-date( SV )); TV is xs:dateTime( fn:concat( + // SYR , '-', SMO , '-', SDA , 'T00:00:00 ', STZ ) ). + try { + XMLGregorianCalendar calValue = literal.calendarValue(); + + int year = calValue.getYear(); + int month = calValue.getMonth(); + int day = calValue.getDay(); + int timezoneOffset = calValue.getTimezone(); + + if (DatatypeConstants.FIELD_UNDEFINED != year && DatatypeConstants.FIELD_UNDEFINED != month + && DatatypeConstants.FIELD_UNDEFINED != day) + { + StringBuilder dtBuilder = new StringBuilder(); + dtBuilder.append(year); + dtBuilder.append("-"); + if (month < 10) { + dtBuilder.append("0"); + } + dtBuilder.append(month); + dtBuilder.append("-"); + if (day < 10) { + dtBuilder.append("0"); + } + dtBuilder.append(day); + dtBuilder.append("T00:00:00"); + if (DatatypeConstants.FIELD_UNDEFINED != timezoneOffset) { + int minutes = Math.abs(timezoneOffset); + int hours = minutes / 60; + minutes = minutes - (hours * 60); + if (timezoneOffset > 0) { + dtBuilder.append("+"); + } + else { + dtBuilder.append("-"); + } + if (hours < 10) { + dtBuilder.append("0"); + } + dtBuilder.append(hours); + dtBuilder.append(":"); + if (minutes < 10) { + dtBuilder.append("0"); + } + dtBuilder.append(minutes); + } + + return valueFactory.createLiteral(dtBuilder.toString(), XMLSchema.DATETIME); + } + else { + throw new ValueExprEvaluationException("not a valid date value: " + literal); + } + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException("not a valid calendar value: " + literal); + } + } + } + } + + throw new ValueExprEvaluationException("Invalid argument for xsd:dateTime cast: " + args[0]); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DecimalCast.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DecimalCast.java new file mode 100644 index 00000000000..645d241587b --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DecimalCast.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import java.math.BigDecimal; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * A {@link Function} that tries to cast its argument to an xsd:decimal. + * + * @author Arjohn Kampman + */ +public class DecimalCast implements Function { + + public String getURI() { + return XMLSchema.DECIMAL.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("xsd:decimal cast requires exactly 1 argument, got " + + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + IRI datatype = literal.getDatatype(); + + if (QueryEvaluationUtil.isStringLiteral(literal)) { + String decimalValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel()); + if (XMLDatatypeUtil.isValidDecimal(decimalValue)) { + return valueFactory.createLiteral(decimalValue, XMLSchema.DECIMAL); + } + } + else if (datatype != null) { + if (datatype.equals(XMLSchema.DECIMAL)) { + return literal; + } + else if (XMLDatatypeUtil.isNumericDatatype(datatype)) { + // FIXME: floats and doubles must be processed separately, see + // http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive + try { + BigDecimal decimalValue = literal.decimalValue(); + return valueFactory.createLiteral(decimalValue.toPlainString(), XMLSchema.DECIMAL); + } + catch (NumberFormatException e) { + throw new ValueExprEvaluationException(e.getMessage(), e); + } + } + else if (datatype.equals(XMLSchema.BOOLEAN)) { + try { + return valueFactory.createLiteral(literal.booleanValue() ? "1.0" : "0.0", XMLSchema.DECIMAL); + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException(e.getMessage(), e); + } + } + } + } + + throw new ValueExprEvaluationException("Invalid argument for xsd:decimal cast: " + args[0]); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DoubleCast.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DoubleCast.java new file mode 100644 index 00000000000..9952aefe75c --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/DoubleCast.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * A {@link Function} that tries to cast its argument to an xsd:double. + * + * @author Arjohn Kampman + */ +public class DoubleCast implements Function { + + public String getURI() { + return XMLSchema.DOUBLE.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("xsd:double cast requires exactly 1 argument, got " + + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + IRI datatype = literal.getDatatype(); + + if (QueryEvaluationUtil.isStringLiteral(literal)) { + String doubleValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel()); + if (XMLDatatypeUtil.isValidDouble(doubleValue)) { + return valueFactory.createLiteral(doubleValue, XMLSchema.DOUBLE); + } + } + else if (datatype != null) { + if (datatype.equals(XMLSchema.DOUBLE)) { + return literal; + } + else if (XMLDatatypeUtil.isNumericDatatype(datatype)) { + // FIXME: doubles must be processed separately, see + // http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive + try { + double doubleValue = literal.doubleValue(); + return valueFactory.createLiteral(doubleValue); + } + catch (NumberFormatException e) { + throw new ValueExprEvaluationException(e.getMessage(), e); + } + } + else if (datatype.equals(XMLSchema.BOOLEAN)) { + try { + return valueFactory.createLiteral(literal.booleanValue() ? 1.0 : 0.0); + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException(e.getMessage(), e); + } + } + } + } + + throw new ValueExprEvaluationException("Invalid argument for xsd:double cast: " + args[0]); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/FloatCast.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/FloatCast.java new file mode 100644 index 00000000000..40f79855f84 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/FloatCast.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * A {@link Function} that tries to cast its argument to an xsd:float. + * + * @author Arjohn Kampman + */ +public class FloatCast implements Function { + + public String getURI() { + return XMLSchema.FLOAT.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("xsd:float cast requires exactly 1 argument, got " + + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + IRI datatype = literal.getDatatype(); + + if (QueryEvaluationUtil.isStringLiteral(literal)) { + String floatValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel()); + if (XMLDatatypeUtil.isValidFloat(floatValue)) { + return valueFactory.createLiteral(floatValue, XMLSchema.FLOAT); + } + } + else if (datatype != null) { + if (datatype.equals(XMLSchema.FLOAT)) { + return literal; + } + else if (XMLDatatypeUtil.isNumericDatatype(datatype)) { + // FIXME: doubles must be processed separately, see + // http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive + try { + float floatValue = literal.floatValue(); + return valueFactory.createLiteral(floatValue); + } + catch (NumberFormatException e) { + throw new ValueExprEvaluationException(e.getMessage(), e); + } + } + else if (datatype.equals(XMLSchema.BOOLEAN)) { + try { + return valueFactory.createLiteral(literal.booleanValue() ? 1f : 0f); + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException(e.getMessage(), e); + } + } + } + } + + throw new ValueExprEvaluationException("Invalid argument for xsd:float cast: " + args[0]); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/Function.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/Function.java new file mode 100644 index 00000000000..830f5100bbf --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/Function.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; + +/** + * @author Arjohn Kampman + */ +public interface Function { + + public String getURI(); + + public Value evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException; +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/FunctionRegistry.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/FunctionRegistry.java new file mode 100644 index 00000000000..250a7a83331 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/FunctionRegistry.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import org.eclipse.rdf4j.common.lang.service.ServiceRegistry; + +/** + * @author Arjohn Kampman + */ +public class FunctionRegistry extends ServiceRegistry { + + /** + * Internal helper class to avoid continuous synchronized checking. + */ + private static class FunctionRegistryHolder { + + public static final FunctionRegistry instance = new FunctionRegistry(); + } + + /** + * Gets the default FunctionRegistry. + * + * @return The default registry. + */ + public static FunctionRegistry getInstance() { + return FunctionRegistryHolder.instance; + } + + public FunctionRegistry() { + super(Function.class); + } + + @Override + protected String getKey(Function function) { + return function.getURI(); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/IntegerCast.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/IntegerCast.java new file mode 100644 index 00000000000..6ef8311b3d5 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/IntegerCast.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * A {@link Function} that tries to cast its argument to an xsd:integer + * . + * + * @author Arjohn Kampman + */ +public class IntegerCast implements Function { + + public String getURI() { + return XMLSchema.INTEGER.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException( + "xsd:integer cast requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + IRI datatype = literal.getDatatype(); + + if (QueryEvaluationUtil.isStringLiteral(literal)) { + String integerValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel()); + if (XMLDatatypeUtil.isValidInteger(integerValue)) { + return valueFactory.createLiteral(integerValue, XMLSchema.INTEGER); + } + } + else if (datatype != null) { + if (datatype.equals(XMLSchema.INTEGER)) { + return literal; + } + else if (XMLDatatypeUtil.isNumericDatatype(datatype)) { + // decimals, floats and doubles must be processed + // separately, see + // http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive + BigInteger integerValue = null; + if (XMLSchema.DECIMAL.equals(datatype) || XMLDatatypeUtil.isFloatingPointDatatype(datatype)) { + integerValue = literal.decimalValue().toBigInteger(); + } + else { + integerValue = literal.integerValue(); + } + try { + return valueFactory.createLiteral(integerValue.toString(), XMLSchema.INTEGER); + } + catch (NumberFormatException e) { + throw new ValueExprEvaluationException(e.getMessage(), e); + } + } + else if (datatype.equals(XMLSchema.BOOLEAN)) { + try { + return valueFactory.createLiteral(literal.booleanValue() ? "1" : "0", XMLSchema.INTEGER); + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException(e.getMessage(), e); + } + } + } + } + + throw new ValueExprEvaluationException("Invalid argument for xsd:integer cast: " + args[0]); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/StringCast.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/StringCast.java new file mode 100644 index 00000000000..d2cbc251d18 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/StringCast.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.util.Literals; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * A {@link Function} that tries to cast its argument to an xsd:string. + * + * @author Arjohn Kampman + */ +public class StringCast implements Function { + + public String getURI() { + return XMLSchema.STRING.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("xsd:string cast requires exactly 1 argument, got " + + args.length); + } + + Value value = args[0]; + if (value instanceof IRI) { + return valueFactory.createLiteral(value.toString(), XMLSchema.STRING); + } + else if (value instanceof Literal) { + Literal literal = (Literal)value; + IRI datatype = literal.getDatatype(); + + if (QueryEvaluationUtil.isSimpleLiteral(literal)) { + return valueFactory.createLiteral(literal.getLabel(), XMLSchema.STRING); + } + else if (!Literals.isLanguageLiteral(literal)) { + if (datatype.equals(XMLSchema.STRING)) { + return literal; + } + else if (XMLDatatypeUtil.isNumericDatatype(datatype) || datatype.equals(XMLSchema.BOOLEAN) + || datatype.equals(XMLSchema.DATETIME)) + { + // FIXME Slightly simplified wrt the spec, we just always use the + // canonical value of the + // source literal as the target lexical value. This is not 100% + // compliant with handling of + // some date-related datatypes. + // + // See + // http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive + if (XMLDatatypeUtil.isValidValue(literal.getLabel(), datatype)) { + String normalizedValue = XMLDatatypeUtil.normalize(literal.getLabel(), datatype); + return valueFactory.createLiteral(normalizedValue, XMLSchema.STRING); + } + else { + return valueFactory.createLiteral(literal.getLabel(), XMLSchema.STRING); + } + } + else { + // for unknown datatypes, just use the lexical value. + return valueFactory.createLiteral(literal.getLabel(), XMLSchema.STRING); + } + } + } + + throw new ValueExprEvaluationException("Invalid argument for xsd:string cast: " + value); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Day.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Day.java new file mode 100644 index 00000000000..b8667529b7a --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Day.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} DAY, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Day implements Function { + + public String getURI() { + return FN.DAY_FROM_DATETIME.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("DAY requires 1 argument, got " + args.length); + } + + Value argValue = args[0]; + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + IRI datatype = literal.getDatatype(); + + if (datatype != null && XMLDatatypeUtil.isCalendarDatatype(datatype)) { + try { + XMLGregorianCalendar calValue = literal.calendarValue(); + + int day = calValue.getDay(); + if (DatatypeConstants.FIELD_UNDEFINED != day) { + return valueFactory.createLiteral(String.valueOf(day), XMLSchema.INTEGER); + } + else { + throw new ValueExprEvaluationException("can not determine day from value: " + argValue); + } + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException("illegal calendar value: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Hours.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Hours.java new file mode 100644 index 00000000000..a4709e827b4 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Hours.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} HOURS, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Hours implements Function { + + public String getURI() { + return FN.HOURS_FROM_DATETIME.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("HOURS requires 1 argument, got " + args.length); + } + + Value argValue = args[0]; + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + IRI datatype = literal.getDatatype(); + + if (datatype != null && XMLDatatypeUtil.isCalendarDatatype(datatype)) { + try { + XMLGregorianCalendar calValue = literal.calendarValue(); + + int hours = calValue.getHour(); + if (DatatypeConstants.FIELD_UNDEFINED != hours) { + return valueFactory.createLiteral(String.valueOf(hours), XMLSchema.INTEGER); + } + else { + throw new ValueExprEvaluationException("can not determine hours from value: " + argValue); + } + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException("illegal calendar value: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Minutes.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Minutes.java new file mode 100644 index 00000000000..bc2f848d688 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Minutes.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} MINUTES, as defined in SPARQL Query + * Language for RDF + * + * @author Jeen Broekstra + */ +public class Minutes implements Function { + + public String getURI() { + return FN.MINUTES_FROM_DATETIME.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("MINUTES requires 1 argument, got " + args.length); + } + + Value argValue = args[0]; + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + IRI datatype = literal.getDatatype(); + + if (datatype != null && XMLDatatypeUtil.isCalendarDatatype(datatype)) { + try { + XMLGregorianCalendar calValue = literal.calendarValue(); + + int minutes = calValue.getMinute(); + if (DatatypeConstants.FIELD_UNDEFINED != minutes) { + return valueFactory.createLiteral(String.valueOf(minutes), XMLSchema.INTEGER); + } + else { + throw new ValueExprEvaluationException("can not determine minutes from value: " + argValue); + } + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException("illegal calendar value: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Month.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Month.java new file mode 100644 index 00000000000..f11f567535b --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Month.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} MONTH, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Month implements Function { + + public String getURI() { + return FN.MONTH_FROM_DATETIME.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("MONTH requires 1 argument, got " + args.length); + } + + Value argValue = args[0]; + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + IRI datatype = literal.getDatatype(); + + if (datatype != null && XMLDatatypeUtil.isCalendarDatatype(datatype)) { + try { + XMLGregorianCalendar calValue = literal.calendarValue(); + + int month = calValue.getMonth(); + if (DatatypeConstants.FIELD_UNDEFINED != month) { + return valueFactory.createLiteral(String.valueOf(month), XMLSchema.INTEGER); + } + else { + throw new ValueExprEvaluationException("can not determine month from value: " + argValue); + } + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException("illegal calendar value: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Now.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Now.java new file mode 100644 index 00000000000..be6f6fa8f58 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Now.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} NOW, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Now implements Function { + + public String getURI() { + return "NOW"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 0) { + throw new ValueExprEvaluationException("NOW requires 0 argument, got " + args.length); + } + + Calendar cal = Calendar.getInstance(); + + Date now = cal.getTime(); + GregorianCalendar c = new GregorianCalendar(); + c.setTime(now); + try { + XMLGregorianCalendar date = DatatypeFactory.newInstance().newXMLGregorianCalendar(c); + + return valueFactory.createLiteral(date); + } + catch (DatatypeConfigurationException e) { + throw new ValueExprEvaluationException(e); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Seconds.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Seconds.java new file mode 100644 index 00000000000..65172deb099 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Seconds.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} SECONDS, as defined in SPARQL Query + * Language for RDF + * + * @author Jeen Broekstra + */ +public class Seconds implements Function { + + public String getURI() { + return FN.SECONDS_FROM_DATETIME.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("SECONDS requires 1 argument, got " + args.length); + } + + Value argValue = args[0]; + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + IRI datatype = literal.getDatatype(); + + if (datatype != null && XMLDatatypeUtil.isCalendarDatatype(datatype)) { + try { + XMLGregorianCalendar calValue = literal.calendarValue(); + + int seconds = calValue.getSecond(); + if (DatatypeConstants.FIELD_UNDEFINED != seconds) { + return valueFactory.createLiteral(String.valueOf(seconds), XMLSchema.DECIMAL); + } + else { + throw new ValueExprEvaluationException("can not determine minutes from value: " + argValue); + } + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException("illegal calendar value: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Timezone.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Timezone.java new file mode 100644 index 00000000000..255a43d4db1 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Timezone.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} TIMEZONE, as defined in SPARQL Query + * Language for RDF + * + * @author Jeen Broekstra + */ +public class Timezone implements Function { + + public String getURI() { + return FN.TIMEZONE_FROM_DATETIME.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("TIMEZONE requires 1 argument, got " + args.length); + } + + Value argValue = args[0]; + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + IRI datatype = literal.getDatatype(); + + if (datatype != null && XMLDatatypeUtil.isCalendarDatatype(datatype)) { + try { + XMLGregorianCalendar calValue = literal.calendarValue(); + + int timezoneOffset = calValue.getTimezone(); + + if (DatatypeConstants.FIELD_UNDEFINED != timezoneOffset) { + // TODO creating xsd:dayTimeDuration lexical representation + // manually. Surely there is a better way to do this? + int minutes = Math.abs(timezoneOffset); + int hours = minutes / 60; + minutes = minutes - (hours * 60); + + StringBuilder tzDuration = new StringBuilder(); + if (timezoneOffset < 0) { + tzDuration.append("-"); + } + tzDuration.append("PT"); + if (hours > 0) { + tzDuration.append(hours + "H"); + } + if (minutes > 0) { + tzDuration.append(minutes + "M"); + } + if (timezoneOffset == 0) { + tzDuration.append("0S"); + } + return valueFactory.createLiteral(tzDuration.toString(), XMLSchema.DAYTIMEDURATION); + } + else { + throw new ValueExprEvaluationException("can not determine timezone from value: " + argValue); + } + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException("illegal calendar value: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Tz.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Tz.java new file mode 100644 index 00000000000..9ad03a3c6f6 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Tz.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} TZ, as defined in SPARQL Query Language for + * RDF + * + * @author Jeen Broekstra + */ +public class Tz implements Function { + + public String getURI() { + return "TZ"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("TZ requires 1 argument, got " + args.length); + } + + Value argValue = args[0]; + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + IRI datatype = literal.getDatatype(); + + if (datatype != null && XMLDatatypeUtil.isCalendarDatatype(datatype)) { + String lexValue = literal.getLabel(); + + Pattern pattern = Pattern.compile("Z|[+-]\\d\\d:\\d\\d"); + Matcher m = pattern.matcher(lexValue); + + String timeZone = ""; + if (m.find()) { + timeZone = m.group(); + } + + return valueFactory.createLiteral(timeZone); + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Year.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Year.java new file mode 100644 index 00000000000..2f000b4f1d5 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/Year.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} YEAR, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Year implements Function { + + public String getURI() { + return FN.YEAR_FROM_DATETIME.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("YEAR requires 1 argument, got " + args.length); + } + + Value argValue = args[0]; + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + IRI datatype = literal.getDatatype(); + + if (datatype != null && XMLDatatypeUtil.isCalendarDatatype(datatype)) { + try { + XMLGregorianCalendar calValue = literal.calendarValue(); + int year = calValue.getYear(); + if (DatatypeConstants.FIELD_UNDEFINED != year) { + return valueFactory.createLiteral(String.valueOf(year), XMLSchema.INTEGER); + } + else { + throw new ValueExprEvaluationException("can not determine year from value: " + argValue); + } + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException("illegal calendar value: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/HashFunction.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/HashFunction.java new file mode 100644 index 00000000000..04baa43cd88 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/HashFunction.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * Abstract hash function + * + * @author jeen + */ +public abstract class HashFunction implements Function { + + protected String hash(String text, String algorithm) + throws NoSuchAlgorithmException + { + byte[] hash = MessageDigest.getInstance(algorithm).digest(text.getBytes()); + BigInteger bi = new BigInteger(1, hash); + String result = bi.toString(16); + if (result.length() % 2 != 0) { + return "0" + result; + } + return result; + } + + public abstract Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException; + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5.java new file mode 100644 index 00000000000..316366a3f10 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import java.security.NoSuchAlgorithmException; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} MD5, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class MD5 extends HashFunction { + + public String getURI() { + return "MD5"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("MD5 requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + if (QueryEvaluationUtil.isSimpleLiteral(literal) || XMLSchema.STRING.equals(literal.getDatatype())) { + String lexValue = literal.getLabel(); + + try { + return valueFactory.createLiteral(hash(lexValue, "MD5")); + } + catch (NoSuchAlgorithmException e) { + // MD5 should always be available. + throw new RuntimeException(e); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for MD5: " + literal); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for Md5: " + args[0]); + } + } + + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1.java new file mode 100644 index 00000000000..793b398a0a9 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import java.security.NoSuchAlgorithmException; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} SHA1, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class SHA1 extends HashFunction { + + public String getURI() { + return "SHA1"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("SHA1 requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + if (QueryEvaluationUtil.isSimpleLiteral(literal) || XMLSchema.STRING.equals(literal.getDatatype())) { + String lexValue = literal.getLabel(); + + try { + return valueFactory.createLiteral(hash(lexValue, "SHA1")); + } + catch (NoSuchAlgorithmException e) { + // SHA1 should always be available. + throw new RuntimeException(e); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for SHA1: " + literal); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for SHA1: " + args[0]); + } + } + + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256.java new file mode 100644 index 00000000000..985b176ac38 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import java.security.NoSuchAlgorithmException; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} SHA256, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class SHA256 extends HashFunction { + + public String getURI() { + return "SHA256"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("SHA256 requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + if (QueryEvaluationUtil.isSimpleLiteral(literal) || XMLSchema.STRING.equals(literal.getDatatype())) { + String lexValue = literal.getLabel(); + + try { + return valueFactory.createLiteral(hash(lexValue, "SHA-256")); + } + catch (NoSuchAlgorithmException e) { + // SHA256 should always be available. + throw new RuntimeException(e); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for SHA256: " + literal); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for SHA256: " + args[0]); + } + } + + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384.java new file mode 100644 index 00000000000..429d0735c1e --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import java.security.NoSuchAlgorithmException; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} SHA384, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class SHA384 extends HashFunction { + + public String getURI() { + return "SHA384"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("SHA384 requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + if (QueryEvaluationUtil.isSimpleLiteral(literal) || XMLSchema.STRING.equals(literal.getDatatype())) { + String lexValue = literal.getLabel(); + + try { + return valueFactory.createLiteral(hash(lexValue, "SHA-384")); + } + catch (NoSuchAlgorithmException e) { + // SHA384 should always be available. + throw new RuntimeException(e); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for SHA384: " + literal); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for SHA384: " + args[0]); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512.java new file mode 100644 index 00000000000..3b76038b77c --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import java.security.NoSuchAlgorithmException; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} SHA512, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class SHA512 extends HashFunction { + + public String getURI() { + return "SHA512"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("SHA512 requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + if (QueryEvaluationUtil.isSimpleLiteral(literal) || XMLSchema.STRING.equals(literal.getDatatype())) { + String lexValue = literal.getLabel(); + + try { + return valueFactory.createLiteral(hash(lexValue, "SHA-512")); + } + catch (NoSuchAlgorithmException e) { + // SHA512 should always be available. + throw new RuntimeException(e); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for SHA512: " + literal); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for SHA512: " + args[0]); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Abs.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Abs.java new file mode 100644 index 00000000000..8f3656bf0c4 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Abs.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.numeric; + +import java.math.BigDecimal; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} ABS, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Abs implements Function { + + public String getURI() { + return FN.NUMERIC_ABS.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("ABS requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + IRI datatype = literal.getDatatype(); + + // ABS function accepts only numeric literals + if (datatype != null && XMLDatatypeUtil.isNumericDatatype(datatype)) + { + if (XMLDatatypeUtil.isDecimalDatatype(datatype)) { + BigDecimal absoluteValue = literal.decimalValue().abs(); + + return valueFactory.createLiteral(absoluteValue.toPlainString(), datatype); + } + else if (XMLDatatypeUtil.isFloatingPointDatatype(datatype)) { + double absoluteValue = Math.abs(literal.doubleValue()); + return valueFactory.createLiteral(Double.toString(absoluteValue), datatype); + } + else { + throw new ValueExprEvaluationException("unexpected datatype for function operand: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Ceil.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Ceil.java new file mode 100644 index 00000000000..732487bf696 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Ceil.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.numeric; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} CEIL, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Ceil implements Function { + + public String getURI() { + return FN.NUMERIC_CEIL.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("CEIL requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + IRI datatype = literal.getDatatype(); + + // CEIL function accepts only numeric literals + if (datatype != null && XMLDatatypeUtil.isNumericDatatype(datatype)) + { + if (XMLDatatypeUtil.isIntegerDatatype(datatype)) { + return literal; + } + else if (XMLDatatypeUtil.isDecimalDatatype(datatype)) { + BigDecimal ceilingValue = literal.decimalValue().setScale(0, RoundingMode.CEILING); + return valueFactory.createLiteral(ceilingValue.toPlainString(), datatype); + } + else if (XMLDatatypeUtil.isFloatingPointDatatype(datatype)) { + double ceilingValue = Math.ceil(literal.doubleValue()); + return valueFactory.createLiteral(Double.toString(ceilingValue), datatype); + } + else { + throw new ValueExprEvaluationException("unexpected datatype for function operand: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Floor.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Floor.java new file mode 100644 index 00000000000..0e11c07cdb4 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Floor.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.numeric; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} FLOOR, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Floor implements Function { + + public String getURI() { + return FN.NUMERIC_FLOOR.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("FLOOR requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + IRI datatype = literal.getDatatype(); + + // function accepts only numeric literals + if (datatype != null && XMLDatatypeUtil.isNumericDatatype(datatype)) { + if (XMLDatatypeUtil.isIntegerDatatype(datatype)) { + return literal; + } + else if (XMLDatatypeUtil.isDecimalDatatype(datatype)) { + BigDecimal floor = literal.decimalValue().setScale(0, RoundingMode.FLOOR); + return valueFactory.createLiteral(floor.toPlainString(), datatype); + } + else if (XMLDatatypeUtil.isFloatingPointDatatype(datatype)) { + double floor = Math.floor(literal.doubleValue()); + return valueFactory.createLiteral(Double.toString(floor), datatype); + } + else { + throw new ValueExprEvaluationException("unexpected datatype for function operand: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Rand.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Rand.java new file mode 100644 index 00000000000..388afd4c921 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Rand.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.numeric; + +import java.util.Random; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} RAND, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Rand implements Function { + + public String getURI() { + return "RAND"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 0) { + throw new ValueExprEvaluationException("RAND requires 0 arguments, got " + args.length); + } + + Random randomGenerator = new Random(); + double randomValue = randomGenerator.nextDouble(); + + return valueFactory.createLiteral(randomValue); + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Round.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Round.java new file mode 100644 index 00000000000..5c978557b41 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Round.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.numeric; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} ROUND, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Round implements Function { + + public String getURI() { + return FN.NUMERIC_ROUND.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("ROUND requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + IRI datatype = literal.getDatatype(); + + // function accepts only numeric literals + if (datatype != null && XMLDatatypeUtil.isNumericDatatype(datatype)) { + if (XMLDatatypeUtil.isIntegerDatatype(datatype)) { + return literal; + } + else if (XMLDatatypeUtil.isDecimalDatatype(datatype)) { + BigDecimal rounded = literal.decimalValue().setScale(0, RoundingMode.HALF_UP); + return valueFactory.createLiteral(rounded.toPlainString(), datatype); + } + else if (XMLDatatypeUtil.isFloatingPointDatatype(datatype)) { + double ceilingValue = Math.round(literal.doubleValue()); + return valueFactory.createLiteral(Double.toString(ceilingValue), datatype); + } + else { + throw new ValueExprEvaluationException("unexpected datatype for function operand: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/STRUUID.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/STRUUID.java new file mode 100644 index 00000000000..b2261152c4a --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/STRUUID.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.rdfterm; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} UUID, as defined in SPARQL Query Language + * for RDF + * + * @since 2.7.0 + * @author Jeen Broekstra + */ +public class STRUUID implements Function { + + public String getURI() { + return "STRUUID"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length > 0) { + throw new ValueExprEvaluationException("STRUUID requires 0 arguments, got " + args.length); + } + + Literal literal = valueFactory.createLiteral(java.util.UUID.randomUUID().toString()); + + return literal; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrDt.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrDt.java new file mode 100644 index 00000000000..82a18f1219c --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrDt.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.rdfterm; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} STRDT, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class StrDt implements Function { + + public String getURI() { + return "STRDT"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 2) { + throw new ValueExprEvaluationException("STRDT requires 2 arguments, got " + + args.length); + } + + Value lexicalValue = args[0]; + Value datatypeValue = args[1]; + + if (QueryEvaluationUtil.isSimpleLiteral(lexicalValue)) { + Literal lit = (Literal)lexicalValue; + if (datatypeValue instanceof IRI) { + return valueFactory.createLiteral(lit.getLabel(), (IRI)datatypeValue); + } + else { + throw new ValueExprEvaluationException("illegal value for operand: " + datatypeValue); + } + } + else { + throw new ValueExprEvaluationException("illegal value for operand: " + lexicalValue); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrLang.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrLang.java new file mode 100644 index 00000000000..a3a97df6f1e --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrLang.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.rdfterm; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} STRLANG, as defined in SPARQL Query + * Language for RDF + * + * @author Jeen Broekstra + */ +public class StrLang implements Function { + + public String getURI() { + return "STRLANG"; + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 2) { + throw new ValueExprEvaluationException("STRLANG requires 2 arguments, got " + args.length); + } + + Value lexicalValue = args[0]; + Value languageValue = args[1]; + + if (QueryEvaluationUtil.isSimpleLiteral(lexicalValue)) { + Literal lit = (Literal)lexicalValue; + + if (languageValue instanceof Literal) { + return valueFactory.createLiteral(lit.getLabel(), ((Literal)languageValue).getLabel()); + } + else { + throw new ValueExprEvaluationException("illegal value for operand: " + languageValue); + } + } + else { + throw new ValueExprEvaluationException("illegal value for operand: " + lexicalValue); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/UUID.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/UUID.java new file mode 100644 index 00000000000..cd02c5a23f1 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/UUID.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.rdfterm; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} UUID, as defined in SPARQL Query Language + * for RDF + * + * @since 2.7.0 + * @author Jeen Broekstra + */ +public class UUID implements Function { + + public String getURI() { + return "UUID"; + } + + public IRI evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length > 0) { + throw new ValueExprEvaluationException("UUID requires 0 arguments, got " + args.length); + } + + IRI uri = valueFactory.createIRI("urn:uuid:" + java.util.UUID.randomUUID().toString()); + + return uri; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java new file mode 100644 index 00000000000..cc3062c6df2 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.util.Literals; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The SPARQL built-in {@link Function} CONCAT, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class Concat implements Function { + + public String getURI() { + return FN.CONCAT.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length == 0) { + throw new ValueExprEvaluationException("CONCAT requires at least 1 argument, got " + args.length); + } + + StringBuilder concatBuilder = new StringBuilder(); + String languageTag = null; + + boolean useLanguageTag = true; + boolean useDatatype = true; + + for (Value arg : args) { + if (arg instanceof Literal) { + Literal lit = (Literal)arg; + + // verify that every literal argument has the same language tag. If + // not, the operator result should not use a language tag. + if (useLanguageTag && Literals.isLanguageLiteral(lit)) { + if (languageTag == null) { + languageTag = lit.getLanguage().get(); + } + else if (!languageTag.equals(lit.getLanguage())) { + languageTag = null; + useLanguageTag = false; + } + } + else { + useLanguageTag = false; + } + + // check datatype: concat only expects plain, language-tagged or + // string-typed literals. If all arguments are of type xsd:string, + // the result also should be, + // otherwise the result will not have a datatype. + if (lit.getDatatype() == null) { + useDatatype = false; + } + else if (!lit.getDatatype().equals(XMLSchema.STRING)) { + throw new ValueExprEvaluationException("unexpected data type for concat operand: " + arg); + } + + concatBuilder.append(lit.getLabel()); + } + else { + throw new ValueExprEvaluationException("unexpected argument type for concat operator: " + arg); + } + } + + Literal result = null; + + if (useDatatype) { + result = valueFactory.createLiteral(concatBuilder.toString(), XMLSchema.STRING); + } + else if (useLanguageTag) { + result = valueFactory.createLiteral(concatBuilder.toString(), languageTag); + } + else { + result = valueFactory.createLiteral(concatBuilder.toString()); + } + + return result; + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java new file mode 100644 index 00000000000..197299a2929 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.BooleanLiteral; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} CONTAINS, as defined in SPARQL Query + * Language for RDF + * + * @author Jeen Broekstra + */ +public class Contains implements Function { + + public String getURI() { + return FN.CONTAINS.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 2) { + throw new ValueExprEvaluationException("CONTAINS requires 2 arguments, got " + args.length); + } + Value leftVal = args[0]; + Value rightVal = args[1]; + + if (leftVal instanceof Literal && rightVal instanceof Literal) { + Literal leftLit = (Literal)leftVal; + Literal rightLit = (Literal)rightVal; + + if (leftLit.getLanguage().isPresent()) { + if (!rightLit.getLanguage().isPresent() || rightLit.getLanguage().equals(leftLit.getLanguage())) { + + String leftLexVal = leftLit.getLabel(); + String rightLexVal = rightLit.getLabel(); + + return BooleanLiteral.valueOf(leftLexVal.contains(rightLexVal)); + } + else { + throw new ValueExprEvaluationException("incompatible operands for CONTAINS function"); + } + } + else if (QueryEvaluationUtil.isStringLiteral(leftLit)) { + if (QueryEvaluationUtil.isStringLiteral(rightLit)) { + String leftLexVal = leftLit.getLabel(); + String rightLexVal = rightLit.getLabel(); + + return BooleanLiteral.valueOf(leftLexVal.contains(rightLexVal)); + } + else { + throw new ValueExprEvaluationException("incompatible operands for CONTAINS function"); + } + } + else { + throw new ValueExprEvaluationException("incompatible operands for CONTAINS function"); + } + } + else { + throw new ValueExprEvaluationException("CONTAINS function expects literal operands"); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/EncodeForUri.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/EncodeForUri.java new file mode 100644 index 00000000000..9975b2353bf --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/EncodeForUri.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import java.io.UnsupportedEncodingException; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} ENCODE_FOR_URI, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + * @author Arjohn Kampman + */ +public class EncodeForUri implements Function { + + public String getURI() { + return FN.ENCODE_FOR_URI.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("ENCODE_FOR_URI requires exactly 1 argument, got " + + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + if (QueryEvaluationUtil.isStringLiteral(literal)) { + String lexValue = literal.getLabel(); + + return valueFactory.createLiteral(encodeUri(lexValue)); + } + else { + throw new ValueExprEvaluationException("Invalid argument for ENCODE_FOR_URI: " + literal); + } + } + else { + throw new ValueExprEvaluationException("Invalid argument for ENCODE_FOR_URI: " + args[0]); + } + } + + private String encodeUri(String uri) { + + StringBuilder buf = new StringBuilder(uri.length() * 2); + + int uriLen = uri.length(); + for (int i = 0; i < uriLen; i++) { + char c = uri.charAt(i); + + if (isUnreserved(c)) { + buf.append(c); + } + else { + // use UTF-8 hex encoding for character. + try { + byte[] utf8 = Character.toString(c).getBytes("UTF-8"); + + for (byte b: utf8) { + // Escape character + buf.append('%'); + + char cb = (char)(b & 0xFF); + + String hexVal = Integer.toHexString(cb).toUpperCase(); + + // Ensure use of two characters + if (hexVal.length() == 1) { + buf.append('0'); + } + + buf.append(hexVal); + } + + } + catch (UnsupportedEncodingException e) { + // UTF-8 is always supported + throw new RuntimeException(e); + } + } + } + + return buf.toString(); + } + + private final boolean isUnreserved(char c) { + return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '-' || c == '.' + || c == '_' || c == '~'; + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCase.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCase.java new file mode 100644 index 00000000000..8597759e3a7 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCase.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import java.util.Optional; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} LCASE, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class LowerCase implements Function { + + public String getURI() { + return FN.LOWER_CASE.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("LCASE requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + + // LowerCase function accepts only string literals. + if (QueryEvaluationUtil.isStringLiteral(literal)) + { + String lexicalValue = literal.getLabel().toLowerCase(); + Optional language = literal.getLanguage(); + + if (language.isPresent()) { + return valueFactory.createLiteral(lexicalValue, language.get()); + } + else if (XMLSchema.STRING.equals(literal.getDatatype())) { + return valueFactory.createLiteral(lexicalValue, XMLSchema.STRING); + } + else { + return valueFactory.createLiteral(lexicalValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Replace.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Replace.java new file mode 100644 index 00000000000..a0130b0eb4c --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Replace.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import java.util.Optional; +import java.util.regex.Pattern; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} REPLACE, as defined in SPARQL Query Language + * for RDF. + * + * @author Jeen Broekstra + */ +public class Replace implements Function { + + public String getURI() { + return FN.REPLACE.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length < 3 || args.length > 4) { + throw new ValueExprEvaluationException("Incorrect number of arguments for REPLACE: " + args.length); + } + + try { + Literal arg = (Literal)args[0]; + Literal pattern = (Literal)args[1]; + Literal replacement = (Literal)args[2]; + Literal flags = null; + if (args.length == 4) { + flags = (Literal)args[3]; + } + + if (! QueryEvaluationUtil.isStringLiteral(arg)) { + throw new ValueExprEvaluationException("incompatible operand for REPLACE: " + arg); + } + + if (! QueryEvaluationUtil.isSimpleLiteral(pattern)) { + throw new ValueExprEvaluationException("incompatible operand for REPLACE: " + pattern); + } + + if (! QueryEvaluationUtil.isSimpleLiteral(replacement)) { + throw new ValueExprEvaluationException("incompatible operand for REPLACE: " + replacement); + } + + String flagString = null; + if (flags != null) { + if (!QueryEvaluationUtil.isSimpleLiteral(flags)) { + throw new ValueExprEvaluationException("incompatible operand for REPLACE: " + flags); + } + flagString = flags.getLabel(); + } + + String argString = arg.getLabel(); + String patternString = pattern.getLabel(); + String replacementString = replacement.getLabel(); + + int f = 0; + if (flagString != null) { + for (char c : flagString.toCharArray()) { + switch (c) { + case 's': + f |= Pattern.DOTALL; + break; + case 'm': + f |= Pattern.MULTILINE; + break; + case 'i': + f |= Pattern.CASE_INSENSITIVE; + break; + case 'x': + f |= Pattern.COMMENTS; + break; + case 'd': + f |= Pattern.UNIX_LINES; + break; + case 'u': + f |= Pattern.UNICODE_CASE; + break; + default: + throw new ValueExprEvaluationException(flagString); + } + } + } + + Pattern p = Pattern.compile(patternString, f); + String result = p.matcher(argString).replaceAll(replacementString); + + Optional lang = arg.getLanguage(); + IRI dt = arg.getDatatype(); + + if (lang.isPresent()) { + return valueFactory.createLiteral(result, lang.get()); + } + else if (dt != null) { + return valueFactory.createLiteral(result, dt); + } + else { + return valueFactory.createLiteral(result); + } + } + catch (ClassCastException e) { + throw new ValueExprEvaluationException("literal operands expected", e); + } + + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfter.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfter.java new file mode 100644 index 00000000000..e769bcf579c --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfter.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import java.util.Optional; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} STRAFTER, as defined in SPARQL Query Language + * for RDF. + * + * @author Jeen Broekstra + */ +public class StrAfter implements Function { + + public String getURI() { + return FN.SUBSTRING_AFTER.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 2) { + throw new ValueExprEvaluationException("Incorrect number of arguments for STRAFTER: " + args.length); + } + + Value leftArg = args[0]; + Value rightArg = args[1]; + + if (leftArg instanceof Literal && rightArg instanceof Literal) { + Literal leftLit = (Literal)leftArg; + Literal rightLit = (Literal)rightArg; + + if (QueryEvaluationUtil.compatibleArguments(leftLit, rightLit)) + { + String lexicalValue = leftLit.getLabel(); + String substring = rightLit.getLabel(); + + Optional leftLanguage = leftLit.getLanguage(); + IRI leftDt = leftLit.getDatatype(); + + int index = lexicalValue.indexOf(substring); + + String substringAfter = ""; + if (index > -1) { + index += substring.length() - 1; + substringAfter = lexicalValue.substring(index + 1, lexicalValue.length()); + } + else { + // no match, return empty string with no language or datatype + leftLanguage = Optional.empty(); + leftDt = null; + } + + if (leftLanguage.isPresent()) { + return valueFactory.createLiteral(substringAfter, leftLanguage.get()); + } + else if (leftDt != null) { + return valueFactory.createLiteral(substringAfter, leftDt); + } + else { + return valueFactory.createLiteral(substringAfter); + } + } + else { + throw new ValueExprEvaluationException("incompatible operands for STRAFTER: " + leftArg + ", " + rightArg); + } + } + else { + throw new ValueExprEvaluationException("incompatible operands for STRAFTER: " + leftArg + ", " + rightArg); + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBefore.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBefore.java new file mode 100644 index 00000000000..ce28a2fec7f --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBefore.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import java.util.Optional; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} STRBEFORE, as defined in SPARQL Query Language + * for RDF. + * + * @author Jeen Broekstra + */ +public class StrBefore implements Function { + + public String getURI() { + return FN.SUBSTRING_BEFORE.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 2) { + throw new ValueExprEvaluationException("Incorrect number of arguments for STRBEFORE: " + args.length); + } + + Value leftArg = args[0]; + Value rightArg = args[1]; + + if (leftArg instanceof Literal && rightArg instanceof Literal) { + Literal leftLit = (Literal)leftArg; + Literal rightLit = (Literal)rightArg; + + + if (QueryEvaluationUtil.compatibleArguments(leftLit, rightLit)) + { + Optional leftLanguage = leftLit.getLanguage(); + IRI leftDt = leftLit.getDatatype(); + + String lexicalValue = leftLit.getLabel(); + String substring = rightLit.getLabel(); + + int index = lexicalValue.indexOf(substring); + + String substringBefore = ""; + if (index > -1) { + substringBefore = lexicalValue.substring(0, index); + } + else { + // no match, return empty string with no language or datatype + leftLanguage = Optional.empty(); + leftDt = null; + } + + if (leftLanguage.isPresent()) { + return valueFactory.createLiteral(substringBefore, leftLanguage.get()); + } + else if (leftDt != null) { + return valueFactory.createLiteral(substringBefore, leftDt); + } + else { + return valueFactory.createLiteral(substringBefore); + } + } + else { + throw new ValueExprEvaluationException("incompatible operands for STRBEFORE: " + leftArg + ", " + rightArg); + } + } + else { + throw new ValueExprEvaluationException("incompatible operands for STRBEFORE: " + leftArg + ", " + rightArg); + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrEnds.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrEnds.java new file mode 100644 index 00000000000..cd2f5fd1757 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrEnds.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.BooleanLiteral; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} STRENDS, as defined in SPARQL Query + * Language for RDF + * + * @author Jeen Broekstra + */ +public class StrEnds implements Function { + + public String getURI() { + return FN.ENDS_WITH.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 2) { + throw new ValueExprEvaluationException("STRENDS requires 2 arguments, got " + args.length); + } + + Value leftVal = args[0]; + Value rightVal = args[1]; + + if (leftVal instanceof Literal && rightVal instanceof Literal) { + Literal leftLit = (Literal)leftVal; + Literal rightLit = (Literal)rightVal; + + if (QueryEvaluationUtil.compatibleArguments(leftLit, rightLit)) { + + String leftLexVal = leftLit.getLabel(); + String rightLexVal = rightLit.getLabel(); + + return BooleanLiteral.valueOf(leftLexVal.endsWith(rightLexVal)); + } + else { + throw new ValueExprEvaluationException("incompatible operands for STRENDS function"); + } + } + else { + throw new ValueExprEvaluationException("STRENDS function expects literal operands"); + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrLen.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrLen.java new file mode 100644 index 00000000000..347f91a0905 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrLen.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} STRLEN, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class StrLen implements Function { + + public String getURI() { + return FN.STRING_LENGTH.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("STRLEN requires 1 argument, got " + args.length); + } + + Value argValue = args[0]; + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + // strlen function accepts only string literals + if (QueryEvaluationUtil.isStringLiteral(literal)) { + + // TODO we jump through some hoops here to get an xsd:integer + // literal. Shouldn't createLiteral(int) return an xsd:integer + // rather than an xsd:int? + Integer length = literal.getLabel().length(); + return valueFactory.createLiteral(length.toString(), XMLSchema.INTEGER); + } + else { + throw new ValueExprEvaluationException("unexpected input value for strlen function: " + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for strlen function: " + argValue); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrStarts.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrStarts.java new file mode 100644 index 00000000000..7d7b92fe062 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrStarts.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import javax.management.Query; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.BooleanLiteral; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} STRSTARTS, as defined in SPARQL Query + * Language for RDF + * + * @author Jeen Broekstra + */ +public class StrStarts implements Function { + + public String getURI() { + return FN.STARTS_WITH.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 2) { + throw new ValueExprEvaluationException("STRSTARTS requires 2 arguments, got " + args.length); + } + + Value leftVal = args[0]; + Value rightVal = args[1]; + + if (leftVal instanceof Literal && rightVal instanceof Literal) { + Literal leftLit = (Literal)leftVal; + Literal rightLit = (Literal)rightVal; + + if (QueryEvaluationUtil.compatibleArguments(leftLit, rightLit)) { + + String leftLexVal = leftLit.getLabel(); + String rightLexVal = rightLit.getLabel(); + + return BooleanLiteral.valueOf(leftLexVal.startsWith(rightLexVal)); + } + else { + throw new ValueExprEvaluationException("incompatible operands for STRSTARTS function"); + } + } + else { + throw new ValueExprEvaluationException("STRSTARTS function expects literal operands"); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Substring.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Substring.java new file mode 100644 index 00000000000..e3774bf39cf --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Substring.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import java.util.Optional; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} SUBSTR, as defined in SPARQL Query Language + * for RDF. + * + * @author Jeen Broekstra + */ +public class Substring implements Function { + + public String getURI() { + return FN.SUBSTRING.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length < 2 || args.length > 3) { + throw new ValueExprEvaluationException("Incorrect number of arguments for SUBSTR: " + args.length); + } + + Value argValue = args[0]; + Value startIndexValue = args[1]; + Value lengthValue = null; + if (args.length > 2) { + lengthValue = args[2]; + } + + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + // substr function accepts string literals only. + if (QueryEvaluationUtil.isStringLiteral(literal)) + { + String lexicalValue = literal.getLabel(); + + // determine start index. + int startIndex = 0; + if (startIndexValue instanceof Literal) { + try { + // xpath:substring startIndex is 1-based. + startIndex = ((Literal)startIndexValue).intValue() - 1; + + if (startIndex < 0) { + throw new ValueExprEvaluationException( + "illegal start index value (expected 1 or larger): " + startIndexValue); + } + } + catch (NumberFormatException e) { + throw new ValueExprEvaluationException("illegal start index value (expected int value): " + + startIndexValue); + } + } + else if (startIndexValue != null) { + throw new ValueExprEvaluationException("illegal start index value (expected literal value): " + + startIndexValue); + } + + // optionally convert supplied length expression to an end index for + // the substring. + int endIndex = lexicalValue.length(); + if (lengthValue instanceof Literal) { + try { + int length = ((Literal)lengthValue).intValue(); + endIndex = startIndex + length; + } + catch (NumberFormatException e) { + throw new ValueExprEvaluationException("illegal length value (expected int value): " + + lengthValue); + } + } + else if (lengthValue != null) { + throw new ValueExprEvaluationException("illegal length value (expected literal value): " + + lengthValue); + } + + try { + Optional language = literal.getLanguage(); + lexicalValue = lexicalValue.substring(startIndex, endIndex); + + if (language.isPresent()) { + return valueFactory.createLiteral(lexicalValue, language.get()); + } + else if (XMLSchema.STRING.equals(literal.getDatatype())) { + return valueFactory.createLiteral(lexicalValue, XMLSchema.STRING); + } + else { + return valueFactory.createLiteral(lexicalValue); + } + } + catch (IndexOutOfBoundsException e) { + throw new ValueExprEvaluationException("could not determine substring", e); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function substring: " + + argValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function substring: " + argValue); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCase.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCase.java new file mode 100644 index 00000000000..dacc44b34b6 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCase.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import java.util.Optional; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; + +/** + * The SPARQL built-in {@link Function} UCASE, as defined in SPARQL Query Language + * for RDF + * + * @author Jeen Broekstra + */ +public class UpperCase implements Function { + + public String getURI() { + return FN.UPPER_CASE.toString(); + } + + public Literal evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException("UCASE requires exactly 1 argument, got " + args.length); + } + + if (args[0] instanceof Literal) { + Literal literal = (Literal)args[0]; + + // UpperCase function accepts only string literal + if (QueryEvaluationUtil.isStringLiteral(literal)) + { + String lexicalValue = literal.getLabel().toUpperCase(); + Optional language = literal.getLanguage(); + + if (language.isPresent()) { + return valueFactory.createLiteral(lexicalValue, language.get()); + } + else if (XMLSchema.STRING.equals(literal.getDatatype())) { + return valueFactory.createLiteral(lexicalValue, XMLSchema.STRING); + } + else { + return valueFactory.createLiteral(lexicalValue); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + } + else { + throw new ValueExprEvaluationException("unexpected input value for function: " + args[0]); + } + + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/BindingAssigner.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/BindingAssigner.java new file mode 100644 index 00000000000..b12b5909904 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/BindingAssigner.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * Assigns values to variables based on a supplied set of bindings. + * + * @author Arjohn Kampman + */ +public class BindingAssigner implements QueryOptimizer { + + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + if (bindings.size() > 0) { + tupleExpr.visit(new VarVisitor(bindings)); + } + } + + protected static class VarVisitor extends AbstractQueryModelVisitor { + + protected BindingSet bindings; + + public VarVisitor(BindingSet bindings) { + this.bindings = bindings; + } + + @Override + public void meet(Var var) { + if (!var.hasValue() && bindings.hasBinding(var.getName())) { + Value value = bindings.getValue(var.getName()); + var.setValue(value); + } + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/CompareOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/CompareOptimizer.java new file mode 100644 index 00000000000..4b82cbc95ad --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/CompareOptimizer.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.Compare; +import org.eclipse.rdf4j.query.algebra.SameTerm; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * A query optimizer that replaces {@link Compare} operators with + * {@link SameTerm}s, if possible. + * + * @author Arjohn Kampman + */ +public class CompareOptimizer implements QueryOptimizer { + + /** + * Applies generally applicable optimizations to the supplied query: variable + * assignments are inlined. + */ + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new CompareVisitor()); + } + + protected static class CompareVisitor extends AbstractQueryModelVisitor { + + @Override + public void meet(Compare compare) { + super.meet(compare); + + if (compare.getOperator() == CompareOp.EQ) { + ValueExpr leftArg = compare.getLeftArg(); + ValueExpr rightArg = compare.getRightArg(); + + boolean leftIsVar = isVar(leftArg); + boolean rightIsVar = isVar(rightArg); + boolean leftIsResource = isResource(leftArg); + boolean rightIsResource = isResource(rightArg); + + if (leftIsVar && rightIsResource || leftIsResource && rightIsVar || leftIsResource + && rightIsResource) + { + SameTerm sameTerm = new SameTerm(leftArg, rightArg); + compare.replaceWith(sameTerm); + } + } + } + + protected boolean isVar(ValueExpr valueExpr) { + if (valueExpr instanceof Var) { + return true; + } + + return false; + } + + protected boolean isResource(ValueExpr valueExpr) { + if (valueExpr instanceof ValueConstant) { + Value value = ((ValueConstant)valueExpr).getValue(); + return value instanceof Resource; + } + + if (valueExpr instanceof Var) { + Value value = ((Var)valueExpr).getValue(); + return value instanceof Resource; + } + + return false; + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConjunctiveConstraintSplitter.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConjunctiveConstraintSplitter.java new file mode 100644 index 00000000000..68f5c4c59f5 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConjunctiveConstraintSplitter.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.And; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; +import org.eclipse.rdf4j.query.algebra.helpers.VarNameCollector; + +/** + * Splits conjunctive constraints into seperate constraints. + * + * @author Arjohn Kampman + */ +public class ConjunctiveConstraintSplitter implements QueryOptimizer { + + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new ConstraintVisitor(tupleExpr)); + } + + protected static class ConstraintVisitor extends AbstractQueryModelVisitor { + + protected final TupleExpr tupleExpr; + + public ConstraintVisitor(TupleExpr tupleExpr) { + this.tupleExpr = tupleExpr; + } + + @Override + public void meet(Filter filter) + { + super.meet(filter); + + List conjunctiveConstraints = new ArrayList(16); + getConjunctiveConstraints(filter.getCondition(), conjunctiveConstraints); + + TupleExpr filterArg = filter.getArg(); + + for (int i = conjunctiveConstraints.size() - 1; i >= 1; i--) { + Filter newFilter = new Filter(filterArg, conjunctiveConstraints.get(i)); + filterArg = newFilter; + } + + filter.setCondition(conjunctiveConstraints.get(0)); + filter.setArg(filterArg); + } + + @Override + public void meet(LeftJoin node) { + super.meet(node); + + if (node.getCondition() != null) { + List conjunctiveConstraints = new ArrayList(16); + getConjunctiveConstraints(node.getCondition(), conjunctiveConstraints); + + TupleExpr arg = node.getRightArg(); + ValueExpr condition = null; + + for (ValueExpr constraint : conjunctiveConstraints) { + if (isWithinBindingScope(constraint, arg)) { + arg = new Filter(arg, constraint); + } else if (condition == null) { + condition = constraint; + } else { + condition = new And(condition, constraint); + } + } + + node.setCondition(condition); + node.setRightArg(arg); + } + } + + protected void getConjunctiveConstraints(ValueExpr valueExpr, List conjunctiveConstraints) { + if (valueExpr instanceof And) { + And and = (And)valueExpr; + getConjunctiveConstraints(and.getLeftArg(), conjunctiveConstraints); + getConjunctiveConstraints(and.getRightArg(), conjunctiveConstraints); + } + else { + conjunctiveConstraints.add(valueExpr); + } + } + + private boolean isWithinBindingScope(ValueExpr condition, TupleExpr node) { + return node.getBindingNames().containsAll(VarNameCollector.process(condition)); + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizer.java new file mode 100644 index 00000000000..edd2fb213c6 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizer.java @@ -0,0 +1,362 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.impl.BooleanLiteral; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.And; +import org.eclipse.rdf4j.query.algebra.BinaryValueOperator; +import org.eclipse.rdf4j.query.algebra.Bound; +import org.eclipse.rdf4j.query.algebra.Extension; +import org.eclipse.rdf4j.query.algebra.ExtensionElem; +import org.eclipse.rdf4j.query.algebra.FunctionCall; +import org.eclipse.rdf4j.query.algebra.If; +import org.eclipse.rdf4j.query.algebra.Or; +import org.eclipse.rdf4j.query.algebra.ProjectionElem; +import org.eclipse.rdf4j.query.algebra.ProjectionElemList; +import org.eclipse.rdf4j.query.algebra.Regex; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.UnaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.UnaryValueOperator; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.function.FunctionRegistry; +import org.eclipse.rdf4j.query.algebra.evaluation.function.numeric.Rand; +import org.eclipse.rdf4j.query.algebra.evaluation.function.rdfterm.STRUUID; +import org.eclipse.rdf4j.query.algebra.evaluation.function.rdfterm.UUID; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A query optimizer that optimizes constant value expressions. + * + * @author James Leigh + * @author Arjohn Kampman + */ +public class ConstantOptimizer implements QueryOptimizer { + + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + protected final EvaluationStrategy strategy; + + public ConstantOptimizer(EvaluationStrategy strategy) { + this.strategy = strategy; + } + + /** + * Applies generally applicable optimizations to the supplied query: variable + * assignments are inlined. + */ + @Override + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + ConstantVisitor visitor = new ConstantVisitor(); + tupleExpr.visit(visitor); + Set varsBefore = visitor.varNames; + + VarNameCollector varCollector = new VarNameCollector(); + tupleExpr.visit(varCollector); + Set varsAfter = varCollector.varNames; + + if (varsAfter.size() < varsBefore.size()) { + varsBefore.removeAll(varsAfter); + for (ProjectionElemList projElems : visitor.projElemLists) { + for (ProjectionElem projElem : projElems.getElements()) { + String name = projElem.getSourceName(); + if (varsBefore.contains(name)) { + UnaryTupleOperator proj = (UnaryTupleOperator)projElems.getParentNode(); + Extension ext = new Extension(proj.getArg()); + proj.setArg(ext); + Var lostVar = new Var(name); + Value value = bindings.getValue(name); + if (value != null) { + lostVar.setValue(value); + } + ext.addElement(new ExtensionElem(lostVar, name)); + } + } + } + } + } + + protected class ConstantVisitor extends VarNameCollector { + + final List projElemLists = new ArrayList(); + + @Override + public void meet(ProjectionElemList projElems) { + super.meet(projElems); + projElemLists.add(projElems); + } + + @Override + public void meet(Or or) { + or.visitChildren(this); + + try { + if (isConstant(or.getLeftArg()) && isConstant(or.getRightArg())) { + boolean value = strategy.isTrue(or, EmptyBindingSet.getInstance()); + or.replaceWith(new ValueConstant(BooleanLiteral.valueOf(value))); + } + else if (isConstant(or.getLeftArg())) { + boolean leftIsTrue = strategy.isTrue(or.getLeftArg(), EmptyBindingSet.getInstance()); + if (leftIsTrue) { + or.replaceWith(new ValueConstant(BooleanLiteral.TRUE)); + } + else { + or.replaceWith(or.getRightArg()); + } + } + else if (isConstant(or.getRightArg())) { + boolean rightIsTrue = strategy.isTrue(or.getRightArg(), EmptyBindingSet.getInstance()); + if (rightIsTrue) { + or.replaceWith(new ValueConstant(BooleanLiteral.TRUE)); + } + else { + or.replaceWith(or.getLeftArg()); + } + } + } + catch (ValueExprEvaluationException e) { + // TODO: incompatible values types(?), remove the affected part of + // the query tree + logger.debug("Failed to evaluate BinaryValueOperator with two constant arguments", e); + } + catch (QueryEvaluationException e) { + logger.error("Query evaluation exception caught", e); + } + } + + @Override + public void meet(And and) { + and.visitChildren(this); + + try { + if (isConstant(and.getLeftArg()) && isConstant(and.getRightArg())) { + boolean value = strategy.isTrue(and, EmptyBindingSet.getInstance()); + and.replaceWith(new ValueConstant(BooleanLiteral.valueOf(value))); + } + else if (isConstant(and.getLeftArg())) { + boolean leftIsTrue = strategy.isTrue(and.getLeftArg(), EmptyBindingSet.getInstance()); + if (leftIsTrue) { + and.replaceWith(and.getRightArg()); + } + else { + and.replaceWith(new ValueConstant(BooleanLiteral.FALSE)); + } + } + else if (isConstant(and.getRightArg())) { + boolean rightIsTrue = strategy.isTrue(and.getRightArg(), EmptyBindingSet.getInstance()); + if (rightIsTrue) { + and.replaceWith(and.getLeftArg()); + } + else { + and.replaceWith(new ValueConstant(BooleanLiteral.FALSE)); + } + } + } + catch (ValueExprEvaluationException e) { + // TODO: incompatible values types(?), remove the affected part of + // the query tree + logger.debug("Failed to evaluate BinaryValueOperator with two constant arguments", e); + } + catch (QueryEvaluationException e) { + logger.error("Query evaluation exception caught", e); + } + } + + @Override + protected void meetBinaryValueOperator(BinaryValueOperator binaryValueOp) { + super.meetBinaryValueOperator(binaryValueOp); + + if (isConstant(binaryValueOp.getLeftArg()) && isConstant(binaryValueOp.getRightArg())) { + try { + Value value = strategy.evaluate(binaryValueOp, EmptyBindingSet.getInstance()); + binaryValueOp.replaceWith(new ValueConstant(value)); + } + catch (ValueExprEvaluationException e) { + // TODO: incompatible values types(?), remove the affected part + // of the query tree + logger.debug("Failed to evaluate BinaryValueOperator with two constant arguments", e); + } + catch (QueryEvaluationException e) { + logger.error("Query evaluation exception caught", e); + } + } + } + + @Override + protected void meetUnaryValueOperator(UnaryValueOperator unaryValueOp) { + super.meetUnaryValueOperator(unaryValueOp); + + if (isConstant(unaryValueOp.getArg())) { + try { + Value value = strategy.evaluate(unaryValueOp, EmptyBindingSet.getInstance()); + unaryValueOp.replaceWith(new ValueConstant(value)); + } + catch (ValueExprEvaluationException e) { + // TODO: incompatible values types(?), remove the affected part + // of the query tree + logger.debug("Failed to evaluate UnaryValueOperator with a constant argument", e); + } + catch (QueryEvaluationException e) { + logger.error("Query evaluation exception caught", e); + } + } + } + + @Override + public void meet(FunctionCall functionCall) { + super.meet(functionCall); + + List args = functionCall.getArgs(); + + if (args.size() == 0) { + /* SPARQL has two types of zero-arg function. One are proper 'constant' functions like NOW() which generate a single value + * for the entire query and which can be safely optimized to a constant. Other functions, like RAND(), UUID() and STRUUID(), + * are a special case: they are expected to yield a new value on every call, and can therefore not be replaced by a constant. + */ + if (!isConstantZeroArgFunction(functionCall)) { + return; + } + } + else { + for (ValueExpr arg : args) { + if (!isConstant(arg)) { + return; + } + } + } + + // All arguments are constant + + try { + Value value = strategy.evaluate(functionCall, EmptyBindingSet.getInstance()); + functionCall.replaceWith(new ValueConstant(value)); + } + catch (ValueExprEvaluationException e) { + // TODO: incompatible values types(?), remove the affected part of + // the query tree + logger.debug("Failed to evaluate BinaryValueOperator with two constant arguments", e); + } + catch (QueryEvaluationException e) { + logger.error("Query evaluation exception caught", e); + } + } + + /** + * Determines if the provided zero-arg function is a function that should + * return a constant value for the entire query execution (e.g NOW()), or + * if it should generate a new value for every call (e.g. RAND()). + * + * @param functionCall + * a zero-arg function call. + * @return true iff the provided function returns a constant value for the query execution, false + * otherwise. + */ + private boolean isConstantZeroArgFunction(FunctionCall functionCall) { + Function function = FunctionRegistry.getInstance().get(functionCall.getURI()).orElseThrow( + () -> new QueryEvaluationException( + "Unable to find function with the URI: " + functionCall.getURI())); + + // we treat constant functions as the 'regular case' and make + // exceptions for specific SPARQL built-in functions that require + // different treatment. + if (function instanceof Rand || function instanceof UUID || function instanceof STRUUID) { + return false; + } + + return true; + } + + @Override + public void meet(Bound bound) { + super.meet(bound); + + if (bound.getArg().hasValue()) { + // variable is always bound + bound.replaceWith(new ValueConstant(BooleanLiteral.TRUE)); + } + } + + @Override + public void meet(If node) { + super.meet(node); + + if (isConstant(node.getCondition())) { + try { + if (strategy.isTrue(node.getCondition(), EmptyBindingSet.getInstance())) { + node.replaceWith(node.getResult()); + } + else { + node.replaceWith(node.getAlternative()); + } + } + catch (ValueExprEvaluationException e) { + logger.debug("Failed to evaluate UnaryValueOperator with a constant argument", e); + } + catch (QueryEvaluationException e) { + logger.error("Query evaluation exception caught", e); + } + } + } + + /** + * Override meetBinaryValueOperator + */ + @Override + public void meet(Regex node) { + super.meetNode(node); + + if (isConstant(node.getArg()) && isConstant(node.getPatternArg()) + && isConstant(node.getFlagsArg())) + { + try { + Value value = strategy.evaluate(node, EmptyBindingSet.getInstance()); + node.replaceWith(new ValueConstant(value)); + } + catch (ValueExprEvaluationException e) { + logger.debug("Failed to evaluate BinaryValueOperator with two constant arguments", e); + } + catch (QueryEvaluationException e) { + logger.error("Query evaluation exception caught", e); + } + } + } + + private boolean isConstant(ValueExpr expr) { + return expr instanceof ValueConstant || expr instanceof Var && ((Var)expr).hasValue(); + } + } + + protected class VarNameCollector extends AbstractQueryModelVisitor { + + final Set varNames = new HashSet(); + + @Override + public void meet(Var var) { + if (!var.isAnonymous()) { + varNames.add(var.getName()); + } + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/DisjunctiveConstraintOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/DisjunctiveConstraintOptimizer.java new file mode 100644 index 00000000000..cd92baaffec --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/DisjunctiveConstraintOptimizer.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.And; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.Or; +import org.eclipse.rdf4j.query.algebra.SameTerm; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Union; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * A query optimizer that optimize disjunctive constraints on tuple expressions. + * Currently, this optimizer {@link Union unions} a clone of the underlying + * tuple expression with the original expression for each {@link SameTerm} + * operator, moving the SameTerm to the cloned tuple expression. + * + * @author Arjohn Kampman + * @author James Leigh + */ +public class DisjunctiveConstraintOptimizer implements QueryOptimizer { + + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new OrSameTermOptimizer()); + } + + protected static class OrSameTermOptimizer extends AbstractQueryModelVisitor { + + @Override + public void meet(Filter filter) { + if (filter.getCondition() instanceof Or && containsSameTerm(filter.getCondition())) { + Or orNode = (Or)filter.getCondition(); + TupleExpr filterArg = filter.getArg(); + + ValueExpr leftConstraint = orNode.getLeftArg(); + ValueExpr rightConstraint = orNode.getRightArg(); + + // remove filter + filter.replaceWith(filterArg); + + // Push UNION down below other filters to avoid cloning them + TupleExpr node = findNotFilter(filterArg); + + Filter leftFilter = new Filter(node.clone(), leftConstraint); + Filter rightFilter = new Filter(node.clone(), rightConstraint); + Union union = new Union(leftFilter, rightFilter); + node.replaceWith(union); + + filter.getParentNode().visit(this); + } + else { + super.meet(filter); + } + } + + private TupleExpr findNotFilter(TupleExpr node) { + if (node instanceof Filter) { + return findNotFilter(((Filter)node).getArg()); + } + return node; + } + + private boolean containsSameTerm(ValueExpr node) { + if (node instanceof SameTerm) { + return true; + } + if (node instanceof Or) { + Or or = (Or)node; + boolean left = containsSameTerm(or.getLeftArg()); + return left || containsSameTerm(or.getRightArg()); + } + if (node instanceof And) { + And and = (And)node; + boolean left = containsSameTerm(and.getLeftArg()); + return left || containsSameTerm(and.getRightArg()); + } + return false; + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EvaluationStatistics.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EvaluationStatistics.java new file mode 100644 index 00000000000..62b24a44137 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EvaluationStatistics.java @@ -0,0 +1,288 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import java.util.Collection; + +import org.eclipse.rdf4j.query.algebra.ArbitraryLengthPath; +import org.eclipse.rdf4j.query.algebra.BinaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.BindingSetAssignment; +import org.eclipse.rdf4j.query.algebra.EmptySet; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.Service; +import org.eclipse.rdf4j.query.algebra.SingletonSet; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.UnaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.ZeroLengthPath; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * Supplies various query model statistics to the query engine/optimizer. + * + * @author Arjohn Kampman + * @author James Leigh + */ +public class EvaluationStatistics { + + protected CardinalityCalculator cc; + + public synchronized double getCardinality(TupleExpr expr) { + if (cc == null) { + cc = createCardinalityCalculator(); + } + + expr.visit(cc); + return cc.getCardinality(); + } + + protected CardinalityCalculator createCardinalityCalculator() { + return new CardinalityCalculator(); + } + + /*-----------------------------------* + * Inner class CardinalityCalculator * + *-----------------------------------*/ + + protected static class CardinalityCalculator extends AbstractQueryModelVisitor { + + private static double VAR_CARDINALITY = 10; + + private static double UNBOUND_SERVICE_CARDINALITY = 100000; + + protected double cardinality; + + public double getCardinality() { + return cardinality; + } + + @Override + public void meet(EmptySet node) { + // no binding sets + cardinality = 0.0; + } + + @Override + public void meet(SingletonSet node) { + // one empty binding set + cardinality = 1.0; + } + + @Override + public void meet(BindingSetAssignment node) { + // actual cardinality is node.getBindingSets().size() binding sets + // but cost is cheap as we don't need to query the triple store + // so effective cardinality is 1 or a very slowly increasing function of node.getBindingSets().size(). + cardinality = 1.0; + } + + @Override + public void meet(ZeroLengthPath node) { + Var subjVar = node.getSubjectVar(); + Var objVar = node.getObjectVar(); + if((subjVar != null && subjVar.hasValue()) || (objVar != null && objVar.hasValue())) { + // subj = obj + cardinality = 1.0; + } + else { + // actual cardinality = count(union(subjs, objs)) + // but cost is equivalent to ?s ?p ?o ?c (impl scans all statements) + // so due to the lower actual cardinality we value it in preference to a fully unbound statement pattern. + cardinality = getSubjectCardinality(subjVar) * getObjectCardinality(objVar) * getContextCardinality(node.getContextVar()); + } + } + + @Override + public void meet(ArbitraryLengthPath node) { + + // actual cardinality = count(union(subjs, objs)) + // but might require getting all statements + // so due to the lower actual cardinality we value it in preference to a fully unbound statement pattern. + cardinality = getSubjectCardinality(node.getSubjectVar()) * getObjectCardinality(node.getObjectVar()) * getContextCardinality(node.getContextVar()); + } + + @Override + public void meet(Service node) { + if (!node.getServiceRef().hasValue()) { + // the URI is not available, may be computed in the course of the + // query + // => use high cost to order the SERVICE node late in the query plan + cardinality = UNBOUND_SERVICE_CARDINALITY; + } + else { + ServiceNodeAnalyzer serviceAnalyzer = new ServiceNodeAnalyzer(); + node.visitChildren(serviceAnalyzer); + int count = serviceAnalyzer.getStatementCount(); + + // more than one free variable in a single triple pattern + if (count == 1 && node.getServiceVars().size() > 1) { + cardinality = 100 + node.getServiceVars().size(); // TODO (should + // be higher + // than other + // simple + // stmts) + } + else { + // only very selective statements should be better than this + // => evaluate service expressions first + cardinality = 1 + (node.getServiceVars().size() * 0.1); + } + } + } + + @Override + public void meet(StatementPattern sp) { + cardinality = getCardinality(sp); + } + + protected double getCardinality(StatementPattern sp) { + return getSubjectCardinality(sp) * getPredicateCardinality(sp) * getObjectCardinality(sp) + * getContextCardinality(sp); + } + + /** + * Override this if you are able to determine the cardinality based not + * only on the subjectVar itself but also the other vars (e.g. the + * predicate value might determine a subject subset). + */ + protected double getSubjectCardinality(StatementPattern sp) { + return getSubjectCardinality(sp.getSubjectVar()); + } + + protected double getSubjectCardinality(Var var) { + return getCardinality(VAR_CARDINALITY, var); + } + + /** + * Override this if you are able to determine the cardinality based not + * only on the predicateVar itself but also the other vars (e.g. the + * subject value might determine a predicate subset). + */ + protected double getPredicateCardinality(StatementPattern sp) { + return getPredicateCardinality(sp.getPredicateVar()); + } + + protected double getPredicateCardinality(Var var) { + return getCardinality(VAR_CARDINALITY, var); + } + + /** + * Override this if you are able to determine the cardinality based not + * only on the objectVar itself but also the other vars (e.g. the + * predicate value might determine an object subset). + */ + protected double getObjectCardinality(StatementPattern sp) { + return getObjectCardinality(sp.getObjectVar()); + } + + protected double getObjectCardinality(Var var) { + return getCardinality(VAR_CARDINALITY, var); + } + + /** + * Override this if you are able to determine the cardinality based not + * only on the contextVar itself but also the other vars (e.g. the subject + * value might determine a context subset). + */ + protected double getContextCardinality(StatementPattern sp) { + return getContextCardinality(sp.getContextVar()); + } + + protected double getContextCardinality(Var var) { + return getCardinality(VAR_CARDINALITY, var); + } + + protected double getCardinality(double varCardinality, Var var) { + return (var == null || var.hasValue()) ? 1.0 : varCardinality; + } + + protected double getCardinality(double varCardinality, Collection vars) { + int constantVarCount = countConstantVars(vars); + double unboundVarFactor = vars.size() - constantVarCount; + return Math.pow(varCardinality, unboundVarFactor); + } + + protected int countConstantVars(Iterable vars) { + int constantVarCount = 0; + + for (Var var : vars) { + if (var.hasValue()) { + constantVarCount++; + } + } + + return constantVarCount; + } + + @Override + public void meet(Join node) { + node.getLeftArg().visit(this); + double leftArgCost = this.cardinality; + + node.getRightArg().visit(this); + cardinality *= leftArgCost; + } + + @Override + public void meet(LeftJoin node) { + node.getLeftArg().visit(this); + double leftArgCost = this.cardinality; + + node.getRightArg().visit(this); + cardinality *= leftArgCost; + } + + @Override + protected void meetBinaryTupleOperator(BinaryTupleOperator node) { + node.getLeftArg().visit(this); + double leftArgCost = this.cardinality; + + node.getRightArg().visit(this); + cardinality += leftArgCost; + } + + @Override + protected void meetUnaryTupleOperator(UnaryTupleOperator node) { + node.getArg().visit(this); + } + + @Override + protected void meetNode(QueryModelNode node) { + if (node instanceof ExternalSet) { + meetExternalSet((ExternalSet)node); + } + else { + throw new IllegalArgumentException("Unhandled node type: " + node.getClass()); + } + } + + protected void meetExternalSet(ExternalSet node) { + cardinality = node.cardinality(); + } + } + + // count the number of triple patterns + private static class ServiceNodeAnalyzer extends AbstractQueryModelVisitor { + + private int count = 0; + + public int getStatementCount() { + return count; + } + + @Override + public void meet(StatementPattern node) + throws RuntimeException + { + count++; + } + }; +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EvaluationStrategyImpl.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EvaluationStrategyImpl.java new file mode 100644 index 00000000000..8547da01e59 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EvaluationStrategyImpl.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.evaluation.TripleSource; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver; + +/** + * @deprecated since 4.0. Use {@link SimpleEvaluationStrategy} instead. + * @author Jeen Broekstra + */ +@Deprecated +public class EvaluationStrategyImpl extends SimpleEvaluationStrategy { + + public EvaluationStrategyImpl(TripleSource tripleSource, Dataset dataset, + FederatedServiceResolver serviceResolver) + { + super(tripleSource, dataset, serviceResolver); + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExternalSet.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExternalSet.java new file mode 100644 index 00000000000..fed8cef1f69 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExternalSet.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import java.util.Collections; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.AbstractQueryModelNode; +import org.eclipse.rdf4j.query.algebra.QueryModelVisitor; +import org.eclipse.rdf4j.query.algebra.TupleExpr; + +/** + * @author James Leigh + */ +public abstract class ExternalSet extends AbstractQueryModelNode implements TupleExpr { + + private static final long serialVersionUID = 3903453394409442226L; + + public Set getBindingNames() { + return Collections.emptySet(); + } + + public Set getAssuredBindingNames() { + return Collections.emptySet(); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meetOther(this); + } + + @Override + public ExternalSet clone() { + return (ExternalSet)super.clone(); + } + + public double cardinality() { + return 1; + } + + public abstract CloseableIteration evaluate(BindingSet bindings) + throws QueryEvaluationException; + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/FilterOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/FilterOptimizer.java new file mode 100644 index 00000000000..d07aecf08b7 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/FilterOptimizer.java @@ -0,0 +1,207 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import java.util.Set; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.Difference; +import org.eclipse.rdf4j.query.algebra.Distinct; +import org.eclipse.rdf4j.query.algebra.EmptySet; +import org.eclipse.rdf4j.query.algebra.Extension; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.Intersection; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.Order; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.QueryRoot; +import org.eclipse.rdf4j.query.algebra.Reduced; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Union; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; +import org.eclipse.rdf4j.query.algebra.helpers.VarNameCollector; + +/** + * Optimizes a query model by pushing {@link Filter}s as far down in the model + * tree as possible. + * + * @author Arjohn Kampman + */ +public class FilterOptimizer implements QueryOptimizer { + + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new FilterFinder(tupleExpr)); + } + + /*--------------------------* + * Inner class FilterFinder * + *--------------------------*/ + + protected static class FilterFinder extends AbstractQueryModelVisitor { + + protected final TupleExpr tupleExpr; + + public FilterFinder(TupleExpr tupleExpr) { + this.tupleExpr = tupleExpr; + } + + @Override + public void meet(Filter filter) { + super.meet(filter); + FilterRelocator.relocate(filter); + } + } + + /*-----------------------------* + * Inner class FilterRelocator * + *-----------------------------*/ + + protected static class FilterRelocator extends AbstractQueryModelVisitor { + + public static void relocate(Filter filter) { + filter.visit(new FilterRelocator(filter)); + } + + protected final Filter filter; + + protected final Set filterVars; + + public FilterRelocator(Filter filter) { + this.filter = filter; + filterVars = VarNameCollector.process(filter.getCondition()); + } + + @Override + protected void meetNode(QueryModelNode node) { + // By default, do not traverse + assert node instanceof TupleExpr; + relocate(filter, (TupleExpr) node); + } + + @Override + public void meet(Join join) { + if (join.getLeftArg().getBindingNames().containsAll(filterVars)) { + // All required vars are bound by the left expr + join.getLeftArg().visit(this); + } + else if (join.getRightArg().getBindingNames().containsAll(filterVars)) { + // All required vars are bound by the right expr + join.getRightArg().visit(this); + } + else { + relocate(filter, join); + } + } + + @Override + public void meet(LeftJoin leftJoin) { + if (leftJoin.getLeftArg().getBindingNames().containsAll(filterVars)) { + leftJoin.getLeftArg().visit(this); + } + else { + relocate(filter, leftJoin); + } + } + + @Override + public void meet(Union union) { + Filter clone = new Filter(); + clone.setCondition(filter.getCondition().clone()); + + relocate(filter, union.getLeftArg()); + relocate(clone, union.getRightArg()); + + FilterRelocator.relocate(filter); + FilterRelocator.relocate(clone); + } + + @Override + public void meet(Difference node) { + Filter clone = new Filter(); + clone.setCondition(filter.getCondition().clone()); + + relocate(filter, node.getLeftArg()); + relocate(clone, node.getRightArg()); + + FilterRelocator.relocate(filter); + FilterRelocator.relocate(clone); + } + + @Override + public void meet(Intersection node) { + Filter clone = new Filter(); + clone.setCondition(filter.getCondition().clone()); + + relocate(filter, node.getLeftArg()); + relocate(clone, node.getRightArg()); + + FilterRelocator.relocate(filter); + FilterRelocator.relocate(clone); + } + + @Override + public void meet(Extension node) { + if (node.getArg().getBindingNames().containsAll(filterVars)) { + node.getArg().visit(this); + } + else { + relocate(filter, node); + } + } + + @Override + public void meet(EmptySet node) { + if (filter.getParentNode() != null) { + // Remove filter from its original location + filter.replaceWith(filter.getArg()); + } + } + + @Override + public void meet(Filter filter) { + // Filters are commutative + filter.getArg().visit(this); + } + + @Override + public void meet(Distinct node) { + node.getArg().visit(this); + } + + @Override + public void meet(Order node) { + node.getArg().visit(this); + } + + @Override + public void meet(QueryRoot node) { + node.getArg().visit(this); + } + + @Override + public void meet(Reduced node) { + node.getArg().visit(this); + } + + protected void relocate(Filter filter, TupleExpr newFilterArg) { + if (filter.getArg() != newFilterArg) { + if (filter.getParentNode() != null) { + // Remove filter from its original location + filter.replaceWith(filter.getArg()); + } + + // Insert filter at the new location + newFilterArg.replaceWith(filter); + filter.setArg(newFilterArg); + } + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/IterativeEvaluationOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/IterativeEvaluationOptimizer.java new file mode 100644 index 00000000000..22a0193e78e --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/IterativeEvaluationOptimizer.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Union; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * @author Arjohn Kampman + */ +public class IterativeEvaluationOptimizer implements QueryOptimizer { + + public IterativeEvaluationOptimizer() { + } + + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new IEOVisitor()); + } + + protected static class IEOVisitor extends AbstractQueryModelVisitor { + + @Override + public void meet(Union union) { + super.meet(union); + + TupleExpr leftArg = union.getLeftArg(); + TupleExpr rightArg = union.getRightArg(); + + if (leftArg instanceof Join && rightArg instanceof Join) { + Join leftJoinArg = (Join)leftArg; + Join rightJoin = (Join)rightArg; + + if (leftJoinArg.getLeftArg().equals(rightJoin.getLeftArg())) { + // factor out the left-most join argument + Join newJoin = new Join(); + union.replaceWith(newJoin); + newJoin.setLeftArg(leftJoinArg.getLeftArg()); + newJoin.setRightArg(union); + union.setLeftArg(leftJoinArg.getRightArg()); + union.setRightArg(rightJoin.getRightArg()); + + union.visit(this); + } + } + } + } +} \ No newline at end of file diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/OrderLimitOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/OrderLimitOptimizer.java new file mode 100644 index 00000000000..d93187f5220 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/OrderLimitOptimizer.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.Distinct; +import org.eclipse.rdf4j.query.algebra.Order; +import org.eclipse.rdf4j.query.algebra.OrderElem; +import org.eclipse.rdf4j.query.algebra.Projection; +import org.eclipse.rdf4j.query.algebra.ProjectionElem; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.Reduced; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * Moves the Order node above the Projection when variables are projected. + * + * @author James Leigh + */ +public class OrderLimitOptimizer implements QueryOptimizer { + + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new OrderOptimizer()); + } + + protected static class OrderOptimizer extends AbstractQueryModelVisitor { + + private boolean variablesProjected = true; + + private Projection projection; + + @Override + public void meet(Projection node) { + projection = node; + node.getArg().visit(this); + projection = null; + } + + @Override + public void meet(Order node) { + for (OrderElem e : node.getElements()) { + e.visit(this); + } + if (variablesProjected) { + QueryModelNode parent = node.getParentNode(); + if (projection == parent) { + node.replaceWith(node.getArg().clone()); + node.setArg(projection.clone()); + Order replacement = node.clone(); + projection.replaceWith(replacement); + QueryModelNode distinct = replacement.getParentNode(); + if (distinct instanceof Distinct) { + distinct.replaceWith(new Reduced(replacement.clone())); + } + } + } + } + + @Override + public void meet(Var node) { + if (projection != null) { + boolean projected = false; + for (ProjectionElem e : projection.getProjectionElemList().getElements()) { + String source = e.getSourceName(); + String target = e.getTargetName(); + if (node.getName().equals(source) && node.getName().equals(target)) { + projected = true; + break; + } + } + if (!projected) { + variablesProjected = false; + } + } + } + + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java new file mode 100644 index 00000000000..e8861c2438d --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java @@ -0,0 +1,468 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.ZeroLengthPath; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; +import org.eclipse.rdf4j.query.algebra.helpers.StatementPatternCollector; +import org.eclipse.rdf4j.query.algebra.helpers.TupleExprs; + +/** + * A query optimizer that re-orders nested Joins. + * + * @author Arjohn Kampman + * @author James Leigh + */ +public class QueryJoinOptimizer implements QueryOptimizer { + + protected final EvaluationStatistics statistics; + + public QueryJoinOptimizer() { + this(new EvaluationStatistics()); + } + + public QueryJoinOptimizer(EvaluationStatistics statistics) { + this.statistics = statistics; + } + + /** + * Applies generally applicable optimizations: path expressions are sorted + * from more to less specific. + * + * @param tupleExpr + */ + @Override + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new JoinVisitor()); + } + + protected class JoinVisitor extends AbstractQueryModelVisitor { + + Set boundVars = new HashSet(); + + @Override + public void meet(LeftJoin leftJoin) { + leftJoin.getLeftArg().visit(this); + + Set origBoundVars = boundVars; + try { + boundVars = new HashSet(boundVars); + boundVars.addAll(leftJoin.getLeftArg().getBindingNames()); + + leftJoin.getRightArg().visit(this); + } + finally { + boundVars = origBoundVars; + } + } + + @Override + public void meet(Join node) { + + Set origBoundVars = boundVars; + try { + boundVars = new HashSet(boundVars); + + // Recursively get the join arguments + List joinArgs = getJoinArgs(node, new ArrayList()); + + // Reorder the (recursive) join arguments to a more optimal sequence + List orderedJoinArgs = new ArrayList(joinArgs.size()); + + // first get all subselects and order them + List orderedSubselects = reorderSubselects(getSubSelects(joinArgs)); + joinArgs.removeAll(orderedSubselects); + + // We order all remaining join arguments based on cardinality and + // variable frequency statistics + if (joinArgs.size() > 0) { + // Build maps of cardinalities and vars per tuple expression + Map cardinalityMap = new HashMap(); + Map> varsMap = new HashMap>(); + + for (TupleExpr tupleExpr : joinArgs) { + cardinalityMap.put(tupleExpr, statistics.getCardinality(tupleExpr)); + if (tupleExpr instanceof ZeroLengthPath) { + varsMap.put(tupleExpr, ((ZeroLengthPath)tupleExpr).getVarList()); + } + else { + varsMap.put(tupleExpr, getStatementPatternVars(tupleExpr)); + } + } + + // Build map of var frequences + Map varFreqMap = new HashMap(); + for (List varList : varsMap.values()) { + getVarFreqMap(varList, varFreqMap); + } + + // order all other join arguments based on available statistics + while (!joinArgs.isEmpty()) { + TupleExpr tupleExpr = selectNextTupleExpr(joinArgs, cardinalityMap, varsMap, varFreqMap, + boundVars); + + joinArgs.remove(tupleExpr); + orderedJoinArgs.add(tupleExpr); + + // Recursively optimize join arguments + tupleExpr.visit(this); + + boundVars.addAll(tupleExpr.getBindingNames()); + } + } + + // Build new join hierarchy + TupleExpr subselectJoins = null; + if (orderedSubselects.size() > 0) { + subselectJoins = orderedSubselects.get(0); + for (int i = 1; i < orderedSubselects.size(); i++) { + subselectJoins = new Join(subselectJoins, orderedSubselects.get(i)); + } + } + + if (orderedJoinArgs.size() > 0) { + // Note: generated hierarchy is right-recursive to help the + // IterativeEvaluationOptimizer to factor out the left-most join + // argument + int i = orderedJoinArgs.size() - 1; + TupleExpr replacement = orderedJoinArgs.get(i); + for (i--; i >= 0; i--) { + replacement = new Join(orderedJoinArgs.get(i), replacement); + } + + if (subselectJoins != null) { + replacement = new Join(subselectJoins, replacement); + } + + // Replace old join hierarchy + node.replaceWith(replacement); + + } + else { + // only subselect joins involved in this query. + node.replaceWith(subselectJoins); + } + } + finally { + boundVars = origBoundVars; + } + } + + protected > L getJoinArgs(TupleExpr tupleExpr, L joinArgs) { + if (tupleExpr instanceof Join) { + Join join = (Join)tupleExpr; + getJoinArgs(join.getLeftArg(), joinArgs); + getJoinArgs(join.getRightArg(), joinArgs); + } + else { + joinArgs.add(tupleExpr); + } + + return joinArgs; + } + + protected List getStatementPatternVars(TupleExpr tupleExpr) { + List stPatterns = StatementPatternCollector.process(tupleExpr); + List varList = new ArrayList(stPatterns.size() * 4); + for (StatementPattern sp : stPatterns) { + sp.getVars(varList); + } + return varList; + } + + protected > M getVarFreqMap(List varList, M varFreqMap) { + for (Var var : varList) { + Integer freq = varFreqMap.get(var); + freq = (freq == null) ? 1 : freq + 1; + varFreqMap.put(var, freq); + } + return varFreqMap; + } + + protected List getSubSelects(List expressions) { + List subselects = new ArrayList(); + + for (TupleExpr expr : expressions) { + if (TupleExprs.containsProjection(expr)) { + subselects.add(expr); + } + } + return subselects; + } + + /** + * Determines an optimal ordering of subselect join arguments, based on + * variable bindings. An ordering is considered optimal if for each + * consecutive element it holds that first of all its shared variables + * with all previous elements is maximized, and second, the union of all + * its variables with all previous elements is maximized. + *

    + * Example: reordering + * + *

    +		 *   [f] [a b c] [e f] [a d] [b e]
    +		 * 
    + * + * should result in: + * + *
    +		 *   [a b c] [a d] [b e] [e f] [f]
    +		 * 
    + * + * @param subselects + * the original ordering of expressions + * @return the optimized ordering of expressions + */ + protected List reorderSubselects(List subselects) { + + if (subselects.size() == 1) { + return subselects; + } + + List result = new ArrayList(); + if (subselects == null || subselects.size() == 0) { + return result; + } + + // Step 1: determine size of join for each pair of arguments + HashMap> joinSizes = new HashMap>(); + + int maxJoinSize = 0; + for (int i = 0; i < subselects.size(); i++) { + TupleExpr firstArg = subselects.get(i); + for (int j = i + 1; j < subselects.size(); j++) { + TupleExpr secondArg = subselects.get(j); + + Set names = firstArg.getBindingNames(); + names.retainAll(secondArg.getBindingNames()); + + int joinSize = names.size(); + if (joinSize > maxJoinSize) { + maxJoinSize = joinSize; + } + + List l = null; + + if (joinSizes.containsKey(joinSize)) { + l = joinSizes.get(joinSize); + } + else { + l = new ArrayList(); + } + TupleExpr[] tupleTuple = new TupleExpr[] { firstArg, secondArg }; + l.add(tupleTuple); + joinSizes.put(joinSize, l); + } + } + + // Step 2: find the first two elements for the ordered list by + // selecting the pair with first of all, + // the highest join size, and second, the highest union size. + + TupleExpr[] maxUnionTupleTuple = null; + int currentUnionSize = -1; + + // get a list of all argument pairs with the maximum join size + List list = joinSizes.get(maxJoinSize); + + // select the pair that has the highest union size. + for (TupleExpr[] tupleTuple : list) { + Set names = tupleTuple[0].getBindingNames(); + names.addAll(tupleTuple[1].getBindingNames()); + int unionSize = names.size(); + + if (unionSize > currentUnionSize) { + maxUnionTupleTuple = tupleTuple; + currentUnionSize = unionSize; + } + } + + // add the pair to the result list. + result.add(maxUnionTupleTuple[0]); + result.add(maxUnionTupleTuple[1]); + + // Step 3: sort the rest of the list by selecting and adding an element + // at a time. + while (result.size() < subselects.size()) { + result.add(getNextSubselect(result, subselects)); + } + + return result; + } + + private TupleExpr getNextSubselect(List currentList, List joinArgs) { + + // determine union of names of all elements currently in the list: this + // corresponds to the projection resulting from joining all these + // elements. + Set currentListNames = new HashSet(); + for (TupleExpr expr : currentList) { + currentListNames.addAll(expr.getBindingNames()); + } + + // select the next argument from the list, by checking that it has, + // first, the highest join size with the current list, and second, the + // highest union size. + TupleExpr selected = null; + int currentUnionSize = -1; + int currentJoinSize = -1; + for (TupleExpr candidate : joinArgs) { + if (!currentList.contains(candidate)) { + Set names = candidate.getBindingNames(); + names.retainAll(currentListNames); + int joinSize = names.size(); + + names = candidate.getBindingNames(); + names.addAll(currentListNames); + int unionSize = names.size(); + + if (joinSize > currentJoinSize) { + selected = candidate; + currentJoinSize = joinSize; + currentUnionSize = unionSize; + } + else if (joinSize == currentJoinSize) { + if (unionSize > currentUnionSize) { + selected = candidate; + currentJoinSize = joinSize; + currentUnionSize = unionSize; + } + } + } + } + + return selected; + } + + /** + * Selects from a list of tuple expressions the next tuple expression that + * should be evaluated. This method selects the tuple expression with + * highest number of bound variables, preferring variables that have been + * bound in other tuple expressions over variables with a fixed value. + */ + protected TupleExpr selectNextTupleExpr(List expressions, + Map cardinalityMap, Map> varsMap, + Map varFreqMap, Set boundVars) + { + TupleExpr result = null; + + if (expressions.size() > 1) { + double lowestCardinality = Double.POSITIVE_INFINITY; + for (TupleExpr tupleExpr : expressions) { + // Calculate a score for this tuple expression + double cardinality = getTupleExprCardinality(tupleExpr, cardinalityMap, varsMap, varFreqMap, + boundVars); + + if (cardinality < lowestCardinality || result == null) { + // More specific path expression found + lowestCardinality = cardinality; + result = tupleExpr; + } + } + } + else { + result = expressions.get(0); + } + + return result; + } + + protected double getTupleExprCardinality(TupleExpr tupleExpr, Map cardinalityMap, + Map> varsMap, Map varFreqMap, Set boundVars) + { + double cardinality = cardinalityMap.get(tupleExpr); + + List vars = varsMap.get(tupleExpr); + + // Compensate for variables that are bound earlier in the evaluation + List unboundVars = getUnboundVars(vars); + List constantVars = getConstantVars(vars); + int nonConstantVarCount = vars.size() - constantVars.size(); + if (nonConstantVarCount > 0) { + double exp = (double)unboundVars.size() / nonConstantVarCount; + cardinality = Math.pow(cardinality, exp); + } + + if (unboundVars.isEmpty()) { + // Prefer patterns with more bound vars + if (nonConstantVarCount > 0) { + cardinality /= nonConstantVarCount; + } + } + else { + // Prefer patterns that bind variables from other tuple expressions + int foreignVarFreq = getForeignVarFreq(unboundVars, varFreqMap); + if (foreignVarFreq > 0) { + cardinality /= 1 + foreignVarFreq; + } + } + + // Prefer patterns that bind more variables + // List distinctUnboundVars = getUnboundVars(new + // HashSet(vars)); + // if (distinctUnboundVars.size() >= 2) { + // cardinality /= distinctUnboundVars.size(); + // } + + return cardinality; + } + + protected List getConstantVars(Iterable vars) { + List constantVars = new ArrayList(); + + for (Var var : vars) { + if (var.hasValue()) { + constantVars.add(var); + } + } + + return constantVars; + } + + protected List getUnboundVars(Iterable vars) { + List unboundVars = new ArrayList(); + + for (Var var : vars) { + if (!var.hasValue() && !this.boundVars.contains(var.getName())) { + unboundVars.add(var); + } + } + + return unboundVars; + } + + protected int getForeignVarFreq(List ownUnboundVars, Map varFreqMap) { + int result = 0; + + Map ownFreqMap = getVarFreqMap(ownUnboundVars, new HashMap()); + + for (Map.Entry entry : ownFreqMap.entrySet()) { + Var var = entry.getKey(); + int ownFreq = entry.getValue(); + result += varFreqMap.get(var) - ownFreq; + } + + return result; + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java new file mode 100644 index 00000000000..4a47e1ad736 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java @@ -0,0 +1,299 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.And; +import org.eclipse.rdf4j.query.algebra.Difference; +import org.eclipse.rdf4j.query.algebra.EmptySet; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.Intersection; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.Or; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.SingletonSet; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.UnaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.Union; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; +import org.eclipse.rdf4j.query.algebra.helpers.VarNameCollector; + +/** + * A query optimizer that (partially) normalizes query models to a canonical + * form. Note: this implementation does not yet cover all query node types. + * + * @author Arjohn Kampman + */ +public class QueryModelNormalizer extends AbstractQueryModelVisitor implements QueryOptimizer { + + public QueryModelNormalizer() { + } + + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(this); + } + + @Override + public void meet(Join join) { + super.meet(join); + + TupleExpr leftArg = join.getLeftArg(); + TupleExpr rightArg = join.getRightArg(); + + if (leftArg instanceof EmptySet || rightArg instanceof EmptySet) { + join.replaceWith(new EmptySet()); + } + else if (leftArg instanceof SingletonSet) { + join.replaceWith(rightArg); + } + else if (rightArg instanceof SingletonSet) { + join.replaceWith(leftArg); + } + else if (leftArg instanceof Union) { + // sort unions above joins + Union union = (Union)leftArg; + Join leftJoin = new Join(union.getLeftArg(), rightArg.clone()); + Join rightJoin = new Join(union.getRightArg(), rightArg.clone()); + Union newUnion = new Union(leftJoin, rightJoin); + join.replaceWith(newUnion); + newUnion.visit(this); + } + else if (rightArg instanceof Union) { + // sort unions above joins + Union union = (Union)rightArg; + Join leftJoin = new Join(leftArg.clone(), union.getLeftArg()); + Join rightJoin = new Join(leftArg.clone(), union.getRightArg()); + Union newUnion = new Union(leftJoin, rightJoin); + join.replaceWith(newUnion); + newUnion.visit(this); + } + else if (leftArg instanceof LeftJoin && isWellDesigned(((LeftJoin)leftArg))) { + // sort left join above normal joins + LeftJoin leftJoin = (LeftJoin)leftArg; + join.replaceWith(leftJoin); + join.setLeftArg(leftJoin.getLeftArg()); + leftJoin.setLeftArg(join); + leftJoin.visit(this); + } + else if (rightArg instanceof LeftJoin && isWellDesigned(((LeftJoin)rightArg))) { + // sort left join above normal joins + LeftJoin leftJoin = (LeftJoin)rightArg; + join.replaceWith(leftJoin); + join.setRightArg(leftJoin.getLeftArg()); + leftJoin.setLeftArg(join); + leftJoin.visit(this); + } + } + + @Override + public void meet(LeftJoin leftJoin) { + super.meet(leftJoin); + + TupleExpr leftArg = leftJoin.getLeftArg(); + TupleExpr rightArg = leftJoin.getRightArg(); + ValueExpr condition = leftJoin.getCondition(); + + if (leftArg instanceof EmptySet) { + leftJoin.replaceWith(leftArg); + } + else if (rightArg instanceof EmptySet) { + leftJoin.replaceWith(leftArg); + } + else if (rightArg instanceof SingletonSet) { + leftJoin.replaceWith(leftArg); + } + else if (condition instanceof ValueConstant) { + boolean conditionValue; + try { + conditionValue = QueryEvaluationUtil.getEffectiveBooleanValue(((ValueConstant)condition).getValue()); + } + catch (ValueExprEvaluationException e) { + conditionValue = false; + } + + if (conditionValue == false) { + // Constraint is always false + leftJoin.replaceWith(leftArg); + } + else { + leftJoin.setCondition(null); + } + } + } + + @Override + public void meet(Union union) { + super.meet(union); + + TupleExpr leftArg = union.getLeftArg(); + TupleExpr rightArg = union.getRightArg(); + + if (leftArg instanceof EmptySet) { + union.replaceWith(rightArg); + } + else if (rightArg instanceof EmptySet) { + union.replaceWith(leftArg); + } + else if (leftArg instanceof SingletonSet && rightArg instanceof SingletonSet) { + union.replaceWith(leftArg); + } + } + + @Override + public void meet(Difference difference) { + super.meet(difference); + + TupleExpr leftArg = difference.getLeftArg(); + TupleExpr rightArg = difference.getRightArg(); + + if (leftArg instanceof EmptySet) { + difference.replaceWith(leftArg); + } + else if (rightArg instanceof EmptySet) { + difference.replaceWith(leftArg); + } + else if (leftArg instanceof SingletonSet && rightArg instanceof SingletonSet) { + difference.replaceWith(new EmptySet()); + } + } + + @Override + public void meet(Intersection intersection) { + super.meet(intersection); + + TupleExpr leftArg = intersection.getLeftArg(); + TupleExpr rightArg = intersection.getRightArg(); + + if (leftArg instanceof EmptySet || rightArg instanceof EmptySet) { + intersection.replaceWith(new EmptySet()); + } + } + + @Override + protected void meetUnaryTupleOperator(UnaryTupleOperator node) { + super.meetUnaryTupleOperator(node); + + if (node.getArg() instanceof EmptySet) { + node.replaceWith(node.getArg()); + } + } + + @Override + public void meet(Filter node) { + super.meet(node); + + TupleExpr arg = node.getArg(); + ValueExpr condition = node.getCondition(); + + if (arg instanceof EmptySet) { + // see #meetUnaryTupleOperator + } + else if (condition instanceof ValueConstant) { + boolean conditionValue; + try { + conditionValue = QueryEvaluationUtil.getEffectiveBooleanValue(((ValueConstant)condition).getValue()); + } + catch (ValueExprEvaluationException e) { + conditionValue = false; + } + + if (conditionValue == false) { + // Constraint is always false + node.replaceWith(new EmptySet()); + } + else { + node.replaceWith(arg); + } + } + } + + @Override + public void meet(Or or) { + super.meet(or); + + if (or.getLeftArg().equals(or.getRightArg())) { + or.replaceWith(or.getLeftArg()); + } + } + + @Override + public void meet(And and) { + super.meet(and); + + if (and.getLeftArg().equals(and.getRightArg())) { + and.replaceWith(and.getLeftArg()); + } + } + + /** + * Checks whether the left join is "well designed" as defined in section 4.2 + * of "Semantics and Complexity of SPARQL", 2006, Jorge Pérez et al. + */ + private boolean isWellDesigned(LeftJoin leftJoin) { + VarNameCollector optionalVarCollector = new VarNameCollector(); + leftJoin.getRightArg().visit(optionalVarCollector); + if (leftJoin.hasCondition()) { + leftJoin.getCondition().visit(optionalVarCollector); + } + + Set problemVars = optionalVarCollector.getVarNames(); + problemVars.removeAll(leftJoin.getLeftArg().getBindingNames()); + + if (problemVars.isEmpty()) { + return true; + } + + // If any of the problematic variables are bound in the parent + // expression then the left join is not well designed + BindingCollector bindingCollector = new BindingCollector(); + QueryModelNode node = leftJoin; + QueryModelNode parent; + while ((parent = node.getParentNode()) != null) { + bindingCollector.setNodeToIgnore(node); + parent.visitChildren(bindingCollector); + node = parent; + } + + problemVars.retainAll(bindingCollector.getBindingNames()); + + return problemVars.isEmpty(); + } + + private static class BindingCollector extends AbstractQueryModelVisitor { + + private QueryModelNode nodeToIgnore; + + private final Set bindingNames = new HashSet(); + + public void setNodeToIgnore(QueryModelNode node) { + this.nodeToIgnore = node; + } + + public Set getBindingNames() { + return bindingNames; + } + + @Override + protected void meetNode(QueryModelNode node) { + if (node instanceof TupleExpr && node != nodeToIgnore) { + TupleExpr tupleExpr = (TupleExpr)node; + bindingNames.addAll(tupleExpr.getBindingNames()); + } + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelPruner.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelPruner.java new file mode 100644 index 00000000000..3ff221e212f --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelPruner.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.Difference; +import org.eclipse.rdf4j.query.algebra.EmptySet; +import org.eclipse.rdf4j.query.algebra.Intersection; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.SingletonSet; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Union; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * A query optimizer that prunes query model trees by removing superfluous parts + * and/or by reducing complex parts with simpler parts. + * + * @author Arjohn Kampman + * @deprecated Replaced by {@link QueryModelNormalizer}. + */ +@Deprecated +public class QueryModelPruner implements QueryOptimizer { + + public QueryModelPruner() { + } + + /** + * Applies generally applicable optimizations: path expressions are sorted + * from more to less specific. + * + * @param tupleExpr + */ + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new TreeSanitizer()); + } + + protected static class TreeSanitizer extends AbstractQueryModelVisitor { + + @Override + public void meet(Join join) { + super.meet(join); + + TupleExpr leftArg = join.getLeftArg(); + TupleExpr rightArg = join.getRightArg(); + + if (leftArg instanceof EmptySet || rightArg instanceof EmptySet) { + join.replaceWith(new EmptySet()); + } + else if (leftArg instanceof SingletonSet) { + join.replaceWith(rightArg); + } + else if (rightArg instanceof SingletonSet) { + join.replaceWith(leftArg); + } + } + + @Override + public void meet(LeftJoin leftJoin) { + super.meet(leftJoin); + + TupleExpr leftArg = leftJoin.getLeftArg(); + TupleExpr rightArg = leftJoin.getRightArg(); + ValueExpr condition = leftJoin.getCondition(); + + if (leftArg instanceof EmptySet) { + leftJoin.replaceWith(leftArg); + } + else if (rightArg instanceof EmptySet) { + leftJoin.replaceWith(leftArg); + } + else if (rightArg instanceof SingletonSet) { + leftJoin.replaceWith(leftArg); + } + else if (condition instanceof ValueConstant) { + boolean conditionValue; + try { + conditionValue = QueryEvaluationUtil.getEffectiveBooleanValue(((ValueConstant)condition).getValue()); + } + catch (ValueExprEvaluationException e) { + conditionValue = false; + } + + if (conditionValue == false) { + // Constraint is always false + leftJoin.replaceWith(leftArg); + } + else { + leftJoin.setCondition(null); + } + } + } + + @Override + public void meet(Union union) { + super.meet(union); + + TupleExpr leftArg = union.getLeftArg(); + TupleExpr rightArg = union.getRightArg(); + + if (leftArg instanceof EmptySet) { + union.replaceWith(rightArg); + } + else if (rightArg instanceof EmptySet) { + union.replaceWith(leftArg); + } + else if (leftArg instanceof SingletonSet && rightArg instanceof SingletonSet) { + union.replaceWith(leftArg); + } + } + + @Override + public void meet(Difference difference) { + super.meet(difference); + + TupleExpr leftArg = difference.getLeftArg(); + TupleExpr rightArg = difference.getRightArg(); + + if (leftArg instanceof EmptySet) { + difference.replaceWith(leftArg); + } + else if (rightArg instanceof EmptySet) { + difference.replaceWith(leftArg); + } + else if (leftArg instanceof SingletonSet && rightArg instanceof SingletonSet) { + difference.replaceWith(new EmptySet()); + } + } + + @Override + public void meet(Intersection intersection) { + super.meet(intersection); + + TupleExpr leftArg = intersection.getLeftArg(); + TupleExpr rightArg = intersection.getRightArg(); + + if (leftArg instanceof EmptySet || rightArg instanceof EmptySet) { + intersection.replaceWith(new EmptySet()); + } + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SameTermFilterOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SameTermFilterOptimizer.java new file mode 100644 index 00000000000..e5f5b9e2f2f --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SameTermFilterOptimizer.java @@ -0,0 +1,231 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.ArbitraryLengthPath; +import org.eclipse.rdf4j.query.algebra.BindingSetAssignment; +import org.eclipse.rdf4j.query.algebra.EmptySet; +import org.eclipse.rdf4j.query.algebra.Extension; +import org.eclipse.rdf4j.query.algebra.ExtensionElem; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.ProjectionElem; +import org.eclipse.rdf4j.query.algebra.SameTerm; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * A query optimizer that embeds {@link Filter}s with {@link SameTerm} operators + * in statement patterns as much as possible. Operators like sameTerm(X, Y) are + * processed by renaming X to Y (or vice versa). Operators like sameTerm(X, + * ) are processed by assigning the URI to all occurring variables with + * name X. + * + * @author Arjohn Kampman + * @author James Leigh + */ +public class SameTermFilterOptimizer implements QueryOptimizer { + + /** + * Applies generally applicable optimizations to the supplied query: variable + * assignments are inlined. + */ + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new SameTermFilterVisitor()); + } + + protected static class SameTermFilterVisitor extends AbstractQueryModelVisitor { + + @Override + public void meet(Filter filter) { + super.meet(filter); + + if (filter.getCondition() instanceof SameTerm) { + // SameTerm applies to the filter's argument + SameTerm sameTerm = (SameTerm)filter.getCondition(); + TupleExpr filterArg = filter.getArg(); + + ValueExpr leftArg = sameTerm.getLeftArg(); + ValueExpr rightArg = sameTerm.getRightArg(); + + // Verify that vars are (potentially) bound by filterArg + Set bindingNames = filterArg.getBindingNames(); + if (isUnboundVar(leftArg, bindingNames) || isUnboundVar(rightArg, bindingNames)) { + // One or both var(s) are unbound, this expression will never + // return any results + filter.replaceWith(new EmptySet()); + return; + } + + Set assuredBindingNames = filterArg.getAssuredBindingNames(); + if (isUnboundVar(leftArg, assuredBindingNames) || isUnboundVar(rightArg, assuredBindingNames)) { + // One or both var(s) are potentially unbound, inlining could + // invalidate the result e.g. in case of left joins + return; + } + + if (leftArg instanceof Var || rightArg instanceof Var) { + if (filterArg instanceof ArbitraryLengthPath && leftArg instanceof Var && rightArg instanceof Var) { + final ArbitraryLengthPath alp = (ArbitraryLengthPath)filterArg; + final List sameTermArgs = Arrays.asList((Var)leftArg, (Var)rightArg); + + if (sameTermArgs.contains(alp.getSubjectVar()) && sameTermArgs.contains(alp.getObjectVar())) { + // SameTerm provides a deferred mapping to allow arbitrary-length property path to produce cyclic paths. See SES-1685. + // we can not inline. + return; + } + } + + BindingSetAssignmentCollector collector = new BindingSetAssignmentCollector(); + filterArg.visit(collector); + + for (BindingSetAssignment bsa : collector.getBindingSetAssignments()) { + // check if the VALUES clause / bindingsetassignment contains + // one of the arguments of the sameTerm. + // if so, we can not inline. + Set names = bsa.getAssuredBindingNames(); + if (leftArg instanceof Var) { + if (names.contains(((Var)leftArg).getName())) { + return; + } + } + if (rightArg instanceof Var) { + if (names.contains(((Var)rightArg).getName())) { + return; + } + } + } + } + + Value leftValue = getValue(leftArg); + Value rightValue = getValue(rightArg); + + if (leftValue != null && rightValue != null) { + // ConstantOptimizer should have taken care of this + } + else if (leftValue != null && rightArg instanceof Var) { + bindVar((Var)rightArg, leftValue, filter); + } + else if (rightValue != null && leftArg instanceof Var) { + bindVar((Var)leftArg, rightValue, filter); + } + else if (leftArg instanceof Var && rightArg instanceof Var) { + // Two unbound variables, rename rightArg to leftArg + renameVar((Var)rightArg, (Var)leftArg, filter); + } + } + } + + private boolean isUnboundVar(ValueExpr valueExpr, Set bindingNames) { + if (valueExpr instanceof Var) { + Var var = (Var)valueExpr; + return !var.hasValue() && !bindingNames.contains(var.getName()); + } + return false; + } + + private Value getValue(ValueExpr valueExpr) { + if (valueExpr instanceof ValueConstant) { + return ((ValueConstant)valueExpr).getValue(); + } + else if (valueExpr instanceof Var) { + return ((Var)valueExpr).getValue(); + } + else { + return null; + } + } + + private void renameVar(Var oldVar, Var newVar, Filter filter) { + filter.getArg().visit(new VarRenamer(oldVar, newVar)); + + // TODO: skip this step if old variable name is not used + // Replace SameTerm-filter with an Extension, the old variable name + // might still be relevant to nodes higher in the tree + Extension extension = new Extension(filter.getArg()); + extension.addElement(new ExtensionElem(new Var(newVar.getName()), oldVar.getName())); + filter.replaceWith(extension); + } + + private void bindVar(Var var, Value value, Filter filter) { + // Set the value on all occurences of the variable + filter.getArg().visit(new VarBinder(var.getName(), value)); + } + } + + protected static class VarRenamer extends AbstractQueryModelVisitor { + private final Var oldVar; + + private final Var newVar; + + public VarRenamer(Var oldVar, Var newVar) { + this.oldVar = oldVar; + this.newVar = newVar; + } + + @Override + public void meet(Var var) { + if (var.equals(oldVar)) { + var.replaceWith(newVar.clone()); + } + } + + @Override + public void meet(ProjectionElem projElem) + throws RuntimeException + { + if (projElem.getSourceName().equals(oldVar.getName())) { + projElem.setSourceName(newVar.getName()); + } + } + } + + protected static class BindingSetAssignmentCollector extends AbstractQueryModelVisitor { + + private List assignments = new ArrayList(); + + @Override + public void meet(BindingSetAssignment bsa) { + assignments.add(bsa); + } + + public List getBindingSetAssignments() { + return assignments; + } + } + + protected static class VarBinder extends AbstractQueryModelVisitor { + + private final String varName; + + private final Value value; + + public VarBinder(String varName, Value value) { + this.varName = varName; + this.value = value; + } + + @Override + public void meet(Var var) { + if (var.getName().equals(varName)) { + var.setValue(value); + } + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SimpleEvaluationStrategy.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SimpleEvaluationStrategy.java new file mode 100644 index 00000000000..91a9f99cc1f --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SimpleEvaluationStrategy.java @@ -0,0 +1,1967 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration; +import org.eclipse.rdf4j.common.iteration.ConvertingIteration; +import org.eclipse.rdf4j.common.iteration.DelayedIteration; +import org.eclipse.rdf4j.common.iteration.DistinctIteration; +import org.eclipse.rdf4j.common.iteration.EmptyIteration; +import org.eclipse.rdf4j.common.iteration.FilterIteration; +import org.eclipse.rdf4j.common.iteration.IntersectIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.common.iteration.LimitIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.common.iteration.OffsetIteration; +import org.eclipse.rdf4j.common.iteration.ReducedIteration; +import org.eclipse.rdf4j.common.iteration.SingletonIteration; +import org.eclipse.rdf4j.common.iteration.UnionIteration; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.impl.BooleanLiteral; +import org.eclipse.rdf4j.model.util.URIUtil; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.SESAME; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.And; +import org.eclipse.rdf4j.query.algebra.ArbitraryLengthPath; +import org.eclipse.rdf4j.query.algebra.BNodeGenerator; +import org.eclipse.rdf4j.query.algebra.BinaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.BindingSetAssignment; +import org.eclipse.rdf4j.query.algebra.Bound; +import org.eclipse.rdf4j.query.algebra.Coalesce; +import org.eclipse.rdf4j.query.algebra.Compare; +import org.eclipse.rdf4j.query.algebra.CompareAll; +import org.eclipse.rdf4j.query.algebra.CompareAny; +import org.eclipse.rdf4j.query.algebra.Datatype; +import org.eclipse.rdf4j.query.algebra.DescribeOperator; +import org.eclipse.rdf4j.query.algebra.Difference; +import org.eclipse.rdf4j.query.algebra.Distinct; +import org.eclipse.rdf4j.query.algebra.EmptySet; +import org.eclipse.rdf4j.query.algebra.Exists; +import org.eclipse.rdf4j.query.algebra.Extension; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.FunctionCall; +import org.eclipse.rdf4j.query.algebra.Group; +import org.eclipse.rdf4j.query.algebra.IRIFunction; +import org.eclipse.rdf4j.query.algebra.If; +import org.eclipse.rdf4j.query.algebra.In; +import org.eclipse.rdf4j.query.algebra.Intersection; +import org.eclipse.rdf4j.query.algebra.IsBNode; +import org.eclipse.rdf4j.query.algebra.IsLiteral; +import org.eclipse.rdf4j.query.algebra.IsNumeric; +import org.eclipse.rdf4j.query.algebra.IsResource; +import org.eclipse.rdf4j.query.algebra.IsURI; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.Label; +import org.eclipse.rdf4j.query.algebra.Lang; +import org.eclipse.rdf4j.query.algebra.LangMatches; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.Like; +import org.eclipse.rdf4j.query.algebra.ListMemberOperator; +import org.eclipse.rdf4j.query.algebra.LocalName; +import org.eclipse.rdf4j.query.algebra.MathExpr; +import org.eclipse.rdf4j.query.algebra.MultiProjection; +import org.eclipse.rdf4j.query.algebra.Namespace; +import org.eclipse.rdf4j.query.algebra.Not; +import org.eclipse.rdf4j.query.algebra.Or; +import org.eclipse.rdf4j.query.algebra.Order; +import org.eclipse.rdf4j.query.algebra.Projection; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.QueryRoot; +import org.eclipse.rdf4j.query.algebra.Reduced; +import org.eclipse.rdf4j.query.algebra.Regex; +import org.eclipse.rdf4j.query.algebra.SameTerm; +import org.eclipse.rdf4j.query.algebra.Service; +import org.eclipse.rdf4j.query.algebra.SingletonSet; +import org.eclipse.rdf4j.query.algebra.Slice; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.Str; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.UnaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.Union; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.ZeroLengthPath; +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; +import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.TripleSource; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedService; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.ServiceJoinIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.function.FunctionRegistry; +import org.eclipse.rdf4j.query.algebra.evaluation.function.datetime.Now; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.BadlyDesignedLeftJoinIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.DescribeIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.ExtensionIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.FilterIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.GroupIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.HashJoinIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.JoinIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.LeftJoinIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.MultiProjectionIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.OrderIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.PathIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.ProjectionIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.SPARQLMinusIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.SilentIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.ZeroLengthPathIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.util.EvaluationStrategies; +import org.eclipse.rdf4j.query.algebra.evaluation.util.MathUtil; +import org.eclipse.rdf4j.query.algebra.evaluation.util.OrderComparator; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; +import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; +import org.eclipse.rdf4j.query.algebra.helpers.TupleExprs; +import org.eclipse.rdf4j.query.algebra.helpers.VarNameCollector; +import org.eclipse.rdf4j.query.impl.MapBindingSet; + +/** + * Default evaluation strategy for Sesame queries, to evaluate one + * {@link TupleExpr} on the given {@link TripleSource}, optionally using the + * given {@link Dataset}. + * + * @author Jeen Broekstra + * @author James Leigh + * @author Arjohn Kampman + * @author David Huynh + * @author Andreas Schwarte + */ +public class SimpleEvaluationStrategy implements EvaluationStrategy { + + /*-----------* + * Constants * + *-----------*/ + + protected final TripleSource tripleSource; + + protected final Dataset dataset; + + protected final FederatedServiceResolver serviceResolver; + + // shared return value for successive calls of the NOW() function within the + // same query. Will be reset upon each new query being evaluated. See + // SES-869. + private Value sharedValueOfNow; + + private final long iterationCacheSyncThreshold; + + /*--------------* + * Constructors * + *--------------*/ + + public SimpleEvaluationStrategy(TripleSource tripleSource, FederatedServiceResolver serviceResolver) { + this(tripleSource, null, serviceResolver); + } + + public SimpleEvaluationStrategy(TripleSource tripleSource, Dataset dataset, + FederatedServiceResolver serviceResolver) + { + this(tripleSource, dataset, serviceResolver, 0); + } + + public SimpleEvaluationStrategy(TripleSource tripleSource, Dataset dataset, + FederatedServiceResolver serviceResolver, long iterationCacheSyncTreshold) + { + this.tripleSource = tripleSource; + this.dataset = dataset; + this.serviceResolver = serviceResolver; + this.iterationCacheSyncThreshold = iterationCacheSyncTreshold; + + EvaluationStrategies.register(this); + } + + /*---------* + * Methods * + *---------*/ + + public FederatedService getService(String serviceUrl) + throws QueryEvaluationException + { + return serviceResolver.getService(serviceUrl); + } + + @Override + public CloseableIteration evaluate(TupleExpr expr, + BindingSet bindings) + throws QueryEvaluationException + { + if (expr instanceof StatementPattern) { + return evaluate((StatementPattern)expr, bindings); + } + else if (expr instanceof UnaryTupleOperator) { + return evaluate((UnaryTupleOperator)expr, bindings); + } + else if (expr instanceof BinaryTupleOperator) { + return evaluate((BinaryTupleOperator)expr, bindings); + } + else if (expr instanceof SingletonSet) { + return evaluate((SingletonSet)expr, bindings); + } + else if (expr instanceof EmptySet) { + return evaluate((EmptySet)expr, bindings); + } + else if (expr instanceof ExternalSet) { + return evaluate((ExternalSet)expr, bindings); + } + else if (expr instanceof ZeroLengthPath) { + return evaluate((ZeroLengthPath)expr, bindings); + } + else if (expr instanceof ArbitraryLengthPath) { + return evaluate((ArbitraryLengthPath)expr, bindings); + } + else if (expr instanceof BindingSetAssignment) { + return evaluate((BindingSetAssignment)expr, bindings); + } + else if (expr == null) { + throw new IllegalArgumentException("expr must not be null"); + } + else { + throw new QueryEvaluationException("Unsupported tuple expr type: " + expr.getClass()); + } + } + + public CloseableIteration evaluate(ArbitraryLengthPath alp, + final BindingSet bindings) + throws QueryEvaluationException + { + final Scope scope = alp.getScope(); + final Var subjectVar = alp.getSubjectVar(); + final TupleExpr pathExpression = alp.getPathExpression(); + final Var objVar = alp.getObjectVar(); + final Var contextVar = alp.getContextVar(); + final long minLength = alp.getMinLength(); + + return new PathIteration(this, scope, subjectVar, pathExpression, objVar, contextVar, minLength, + bindings); + } + + public CloseableIteration evaluate(ZeroLengthPath zlp, + final BindingSet bindings) + throws QueryEvaluationException + { + + final Var subjectVar = zlp.getSubjectVar(); + final Var objVar = zlp.getObjectVar(); + final Var contextVar = zlp.getContextVar(); + + Value subj = null; + try { + subj = evaluate(subjectVar, bindings); + } + catch (QueryEvaluationException e) { + } + + Value obj = null; + try { + obj = evaluate(objVar, bindings); + } + catch (QueryEvaluationException e) { + } + + if (subj != null && obj != null) { + if (!subj.equals(obj)) { + return new EmptyIteration(); + } + } + + return getZeroLengthPathIterator(bindings, subjectVar, objVar, contextVar, subj, obj); + } + + protected ZeroLengthPathIteration getZeroLengthPathIterator(final BindingSet bindings, + final Var subjectVar, final Var objVar, final Var contextVar, Value subj, Value obj) + { + return new ZeroLengthPathIteration(this, subjectVar, objVar, subj, obj, contextVar, bindings); + } + + @Override + public CloseableIteration evaluate(Service service, + String serviceUri, CloseableIteration bindings) + throws QueryEvaluationException + { + try { + FederatedService fs = serviceResolver.getService(serviceUri); + return fs.evaluate(service, bindings, service.getBaseURI()); + } + catch (QueryEvaluationException e) { + // suppress exceptions if silent + if (service.isSilent()) { + return bindings; + } + else { + throw new QueryEvaluationException(e); + } + } + } + + public CloseableIteration evaluate(Service service, + BindingSet bindings) + throws QueryEvaluationException + { + Var serviceRef = service.getServiceRef(); + + String serviceUri; + if (serviceRef.hasValue()) + serviceUri = serviceRef.getValue().stringValue(); + else { + if (bindings != null && bindings.hasBinding(serviceRef.getName())) { + serviceUri = bindings.getBinding(serviceRef.getName()).getValue().stringValue(); + } + else { + throw new QueryEvaluationException("SERVICE variables must be bound at evaluation time."); + } + } + + try { + + FederatedService fs = serviceResolver.getService(serviceUri); + + // create a copy of the free variables, and remove those for which + // bindings are available (we can set them as constraints!) + Set freeVars = new HashSet(service.getServiceVars()); + freeVars.removeAll(bindings.getBindingNames()); + + // Get bindings from values pre-bound into variables. + MapBindingSet allBindings = new MapBindingSet(); + for (Binding binding : bindings) { + allBindings.addBinding(binding.getName(), binding.getValue()); + } + + Set boundVars = getBoundVariables(service); + for (Var boundVar : boundVars) { + freeVars.remove(boundVar.getName()); + allBindings.addBinding(boundVar.getName(), boundVar.getValue()); + } + bindings = allBindings; + + String baseUri = service.getBaseURI(); + + // special case: no free variables => perform ASK query + if (freeVars.size() == 0) { + boolean exists = fs.ask(service, bindings, baseUri); + + // check if triples are available (with inserted bindings) + if (exists) + return new SingletonIteration(bindings); + else + return new EmptyIteration(); + + } + + // otherwise: perform a SELECT query + CloseableIteration result = fs.select(service, freeVars, + bindings, baseUri); + + if (service.isSilent()) + return new SilentIteration(result); + else + return result; + + } + catch (QueryEvaluationException e) { + // suppress exceptions if silent + if (service.isSilent()) { + return new SingletonIteration(bindings); + } + else { + throw e; + } + } + catch (RuntimeException e) { + // suppress special exceptions (e.g. UndeclaredThrowable with wrapped + // QueryEval) if silent + if (service.isSilent()) { + return new SingletonIteration(bindings); + } + else { + throw e; + } + } + } + + private Set getBoundVariables(Service service) { + BoundVarVisitor visitor = new BoundVarVisitor(); + visitor.meet(service); + return visitor.boundVars; + } + + private static class BoundVarVisitor extends AbstractQueryModelVisitor { + + private final Set boundVars = new HashSet(); + + @Override + public void meet(Var var) { + if (var.hasValue()) { + boundVars.add(var); + } + } + } + + public CloseableIteration evaluate(DescribeOperator operator, + final BindingSet bindings) + throws QueryEvaluationException + { + CloseableIteration iter = evaluate(operator.getArg(), bindings); + return new DescribeIteration(iter, this, operator.getBindingNames(), bindings); + } + + public CloseableIteration evaluate(StatementPattern sp, + final BindingSet bindings) + throws QueryEvaluationException + { + final Var subjVar = sp.getSubjectVar(); + final Var predVar = sp.getPredicateVar(); + final Var objVar = sp.getObjectVar(); + final Var conVar = sp.getContextVar(); + + final Value subjValue = getVarValue(subjVar, bindings); + final Value predValue = getVarValue(predVar, bindings); + final Value objValue = getVarValue(objVar, bindings); + final Value contextValue = getVarValue(conVar, bindings); + + CloseableIteration stIter = null; + + try { + Resource[] contexts; + + Set graphs = null; + boolean emptyGraph = false; + + if (dataset != null) { + if (sp.getScope() == Scope.DEFAULT_CONTEXTS) { + graphs = dataset.getDefaultGraphs(); + emptyGraph = graphs.isEmpty() && !dataset.getNamedGraphs().isEmpty(); + } + else { + graphs = dataset.getNamedGraphs(); + emptyGraph = graphs.isEmpty() && !dataset.getDefaultGraphs().isEmpty(); + } + } + + if (emptyGraph) { + // Search zero contexts + return new EmptyIteration(); + } + else if (graphs == null || graphs.isEmpty()) { + // store default behaivour + if (contextValue != null) { + contexts = new Resource[] { (Resource)contextValue }; + } + /* TODO activate this to have an exclusive (rather than inclusive) interpretation of the default graph in SPARQL querying. + else if (sp.getScope() == Scope.DEFAULT_CONTEXTS ) { + contexts = new Resource[] { (Resource)null }; + } + */ + else { + contexts = new Resource[0]; + } + } + else if (contextValue != null) { + if (graphs.contains(contextValue)) { + contexts = new Resource[] { (Resource)contextValue }; + } + else { + // Statement pattern specifies a context that is not part of + // the dataset + return new EmptyIteration(); + } + } + else { + contexts = new Resource[graphs.size()]; + int i = 0; + for (IRI graph : graphs) { + IRI context = null; + if (!SESAME.NIL.equals(graph)) { + context = graph; + } + contexts[i++] = context; + } + } + + stIter = tripleSource.getStatements((Resource)subjValue, (IRI)predValue, objValue, contexts); + + if (contexts.length == 0 && sp.getScope() == Scope.NAMED_CONTEXTS) { + // Named contexts are matched by retrieving all statements from + // the store and filtering out the statements that do not have a + // context. + stIter = new FilterIteration(stIter) { + + @Override + protected boolean accept(Statement st) { + return st.getContext() != null; + } + + }; // end anonymous class + } + } + catch (ClassCastException e) { + // Invalid value type for subject, predicate and/or context + return new EmptyIteration(); + } + + // The same variable might have been used multiple times in this + // StatementPattern, verify value equality in those cases. + // TODO: skip this filter if not necessary + stIter = new FilterIteration(stIter) { + + @Override + protected boolean accept(Statement st) { + Resource subj = st.getSubject(); + IRI pred = st.getPredicate(); + Value obj = st.getObject(); + Resource context = st.getContext(); + + if (subjVar != null && subjValue == null) { + if (subjVar.equals(predVar) && !subj.equals(pred)) { + return false; + } + if (subjVar.equals(objVar) && !subj.equals(obj)) { + return false; + } + if (subjVar.equals(conVar) && !subj.equals(context)) { + return false; + } + } + + if (predVar != null && predValue == null) { + if (predVar.equals(objVar) && !pred.equals(obj)) { + return false; + } + if (predVar.equals(conVar) && !pred.equals(context)) { + return false; + } + } + + if (objVar != null && objValue == null) { + if (objVar.equals(conVar) && !obj.equals(context)) { + return false; + } + } + + return true; + } + }; + + // Return an iterator that converts the statements to var bindings + return new ConvertingIteration(stIter) { + + @Override + protected BindingSet convert(Statement st) { + QueryBindingSet result = new QueryBindingSet(bindings); + + if (subjVar != null && !subjVar.isConstant() && !result.hasBinding(subjVar.getName())) { + result.addBinding(subjVar.getName(), st.getSubject()); + } + if (predVar != null && !predVar.isConstant() && !result.hasBinding(predVar.getName())) { + result.addBinding(predVar.getName(), st.getPredicate()); + } + if (objVar != null && !objVar.isConstant() && !result.hasBinding(objVar.getName())) { + result.addBinding(objVar.getName(), st.getObject()); + } + if (conVar != null && !conVar.isConstant() && !result.hasBinding(conVar.getName()) + && st.getContext() != null) + { + result.addBinding(conVar.getName(), st.getContext()); + } + + return result; + } + }; + } + + protected Value getVarValue(Var var, BindingSet bindings) { + if (var == null) { + return null; + } + else if (var.hasValue()) { + return var.getValue(); + } + else { + return bindings.getValue(var.getName()); + } + } + + public CloseableIteration evaluate(UnaryTupleOperator expr, + BindingSet bindings) + throws QueryEvaluationException + { + if (expr instanceof Projection) { + return evaluate((Projection)expr, bindings); + } + else if (expr instanceof MultiProjection) { + return evaluate((MultiProjection)expr, bindings); + } + else if (expr instanceof Filter) { + return evaluate((Filter)expr, bindings); + } + else if (expr instanceof Service) { + return evaluate((Service)expr, bindings); + } + else if (expr instanceof Slice) { + return evaluate((Slice)expr, bindings); + } + else if (expr instanceof Extension) { + return evaluate((Extension)expr, bindings); + } + else if (expr instanceof Distinct) { + return evaluate((Distinct)expr, bindings); + } + else if (expr instanceof Reduced) { + return evaluate((Reduced)expr, bindings); + } + else if (expr instanceof Group) { + return evaluate((Group)expr, bindings); + } + else if (expr instanceof Order) { + return evaluate((Order)expr, bindings); + } + else if (expr instanceof QueryRoot) { + // new query, reset shared return value for successive calls of NOW() + this.sharedValueOfNow = null; + return evaluate(((QueryRoot)expr).getArg(), bindings); + } + else if (expr instanceof DescribeOperator) { + return evaluate((DescribeOperator)expr, bindings); + } + else if (expr == null) { + throw new IllegalArgumentException("expr must not be null"); + } + else { + throw new QueryEvaluationException("Unknown unary tuple operator type: " + expr.getClass()); + } + } + + public CloseableIteration evaluate(BindingSetAssignment bsa, + BindingSet bindings) + throws QueryEvaluationException + { + final Iterator iter = bsa.getBindingSets().iterator(); + if (bindings.size() == 0) { // empty binding set + return new CloseableIteratorIteration(iter); + } + + CloseableIteration result; + + final QueryBindingSet b = new QueryBindingSet(bindings); + + result = new LookAheadIteration() { + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + QueryBindingSet result = null; + while (result == null && iter.hasNext()) { + final BindingSet assignedBindings = iter.next(); + for (String name : assignedBindings.getBindingNames()) { + final Value assignedValue = assignedBindings.getValue(name); + if (assignedValue != null) { // can be null if set to UNDEF + // check that the binding assignment does not overwrite + // existing bindings. + Value bValue = b.getValue(name); + if (bValue == null || assignedValue.equals(bValue)) { + if (result == null) { + result = new QueryBindingSet(b); + } + if (bValue == null) { + // we are not overwriting an existing binding. + result.addBinding(name, assignedValue); + } + } + else { + // if values are not equal there is no compatible + // merge and we should return no next element. + result = null; + break; + } + } + } + } + return result; + } + + }; + + return result; + } + + public CloseableIteration evaluate(Projection projection, + BindingSet bindings) + throws QueryEvaluationException + { + CloseableIteration result; + + result = this.evaluate(projection.getArg(), bindings); + result = new ProjectionIterator(projection, result, bindings); + return result; + } + + public CloseableIteration evaluate(MultiProjection multiProjection, + BindingSet bindings) + throws QueryEvaluationException + { + CloseableIteration result; + result = this.evaluate(multiProjection.getArg(), bindings); + result = new MultiProjectionIterator(multiProjection, result, bindings); + return result; + } + + public CloseableIteration evaluate(Filter filter, BindingSet bindings) + throws QueryEvaluationException + { + CloseableIteration result; + result = this.evaluate(filter.getArg(), bindings); + result = new FilterIterator(filter, result, this); + return result; + } + + public CloseableIteration evaluate(Slice slice, BindingSet bindings) + throws QueryEvaluationException + { + CloseableIteration result = evaluate(slice.getArg(), bindings); + + if (slice.hasOffset()) { + result = new OffsetIteration(result, slice.getOffset()); + } + + if (slice.hasLimit()) { + result = new LimitIteration(result, slice.getLimit()); + } + + return result; + } + + public CloseableIteration evaluate(Extension extension, + BindingSet bindings) + throws QueryEvaluationException + { + CloseableIteration result; + try { + result = this.evaluate(extension.getArg(), bindings); + } + catch (ValueExprEvaluationException e) { + // a type error in an extension argument should be silently ignored and + // result in zero bindings. + result = new EmptyIteration(); + } + + result = new ExtensionIterator(extension, result, this); + return result; + } + + public CloseableIteration evaluate(Distinct distinct, + BindingSet bindings) + throws QueryEvaluationException + { + return new DistinctIteration( + evaluate(distinct.getArg(), bindings)); + } + + public CloseableIteration evaluate(Reduced reduced, + BindingSet bindings) + throws QueryEvaluationException + { + return new ReducedIteration(evaluate(reduced.getArg(), bindings)); + } + + public CloseableIteration evaluate(Group node, BindingSet bindings) + throws QueryEvaluationException + { + return new GroupIterator(this, node, bindings, iterationCacheSyncThreshold); + } + + public CloseableIteration evaluate(Order node, BindingSet bindings) + throws QueryEvaluationException + { + ValueComparator vcmp = new ValueComparator(); + OrderComparator cmp = new OrderComparator(this, node, vcmp); + boolean reduced = isReducedOrDistinct(node); + long limit = getLimit(node); + return new OrderIterator(evaluate(node.getArg(), bindings), cmp, limit, reduced, + iterationCacheSyncThreshold); + } + + public CloseableIteration evaluate(BinaryTupleOperator expr, + BindingSet bindings) + throws QueryEvaluationException + { + if (expr instanceof Join) { + return evaluate((Join)expr, bindings); + } + else if (expr instanceof LeftJoin) { + return evaluate((LeftJoin)expr, bindings); + } + else if (expr instanceof Union) { + return evaluate((Union)expr, bindings); + } + else if (expr instanceof Intersection) { + return evaluate((Intersection)expr, bindings); + } + else if (expr instanceof Difference) { + return evaluate((Difference)expr, bindings); + } + else if (expr == null) { + throw new IllegalArgumentException("expr must not be null"); + } + else { + throw new QueryEvaluationException("Unsupported binary tuple operator type: " + expr.getClass()); + } + } + + public CloseableIteration evaluate(Join join, BindingSet bindings) + throws QueryEvaluationException + { + // efficient computation of a SERVICE join using vectored evaluation + // TODO maybe we can create a ServiceJoin node already in the parser? + if (join.getRightArg() instanceof Service) { + CloseableIteration leftIter = evaluate(join.getLeftArg(), + bindings); + return new ServiceJoinIterator(leftIter, (Service)join.getRightArg(), bindings, this); + } + + if (TupleExprs.containsProjection(join.getRightArg())) { + return new HashJoinIteration(this, join, bindings); + } + else { + return new JoinIterator(this, join, bindings); + } + } + + public CloseableIteration evaluate(LeftJoin leftJoin, + final BindingSet bindings) + throws QueryEvaluationException + { + // Check whether optional join is "well designed" as defined in section + // 4.2 of "Semantics and Complexity of SPARQL", 2006, Jorge Pérez et al. + VarNameCollector optionalVarCollector = new VarNameCollector(); + leftJoin.getRightArg().visit(optionalVarCollector); + if (leftJoin.hasCondition()) { + leftJoin.getCondition().visit(optionalVarCollector); + } + + Set problemVars = optionalVarCollector.getVarNames(); + problemVars.removeAll(leftJoin.getLeftArg().getBindingNames()); + problemVars.retainAll(bindings.getBindingNames()); + + if (problemVars.isEmpty()) { + // left join is "well designed" + return new LeftJoinIterator(this, leftJoin, bindings); + } + else { + return new BadlyDesignedLeftJoinIterator(this, leftJoin, bindings, problemVars); + } + } + + @SuppressWarnings("unchecked") + public CloseableIteration evaluate(final Union union, + final BindingSet bindings) + throws QueryEvaluationException + { + Iteration leftArg, rightArg; + + leftArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(union.getLeftArg(), bindings); + } + }; + + rightArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(union.getRightArg(), bindings); + } + }; + + return new UnionIteration(leftArg, rightArg); + } + + public CloseableIteration evaluate(final Intersection intersection, + final BindingSet bindings) + throws QueryEvaluationException + { + Iteration leftArg, rightArg; + + leftArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(intersection.getLeftArg(), bindings); + } + }; + + rightArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(intersection.getRightArg(), bindings); + } + }; + + return new IntersectIteration(leftArg, rightArg); + } + + public CloseableIteration evaluate(final Difference difference, + final BindingSet bindings) + throws QueryEvaluationException + { + Iteration leftArg, rightArg; + + leftArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(difference.getLeftArg(), bindings); + } + }; + + rightArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(difference.getRightArg(), bindings); + } + }; + + return new SPARQLMinusIteration(leftArg, rightArg); + } + + public CloseableIteration evaluate(SingletonSet singletonSet, + BindingSet bindings) + throws QueryEvaluationException + { + return new SingletonIteration(bindings); + } + + public CloseableIteration evaluate(EmptySet emptySet, + BindingSet bindings) + throws QueryEvaluationException + { + return new EmptyIteration(); + } + + public CloseableIteration evaluate(ExternalSet external, + BindingSet bindings) + throws QueryEvaluationException + { + return external.evaluate(bindings); + } + + @Override + public Value evaluate(ValueExpr expr, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + if (expr instanceof Var) { + return evaluate((Var)expr, bindings); + } + else if (expr instanceof ValueConstant) { + return evaluate((ValueConstant)expr, bindings); + } + else if (expr instanceof BNodeGenerator) { + return evaluate((BNodeGenerator)expr, bindings); + } + else if (expr instanceof Bound) { + return evaluate((Bound)expr, bindings); + } + else if (expr instanceof Str) { + return evaluate((Str)expr, bindings); + } + else if (expr instanceof Label) { + return evaluate((Label)expr, bindings); + } + else if (expr instanceof Lang) { + return evaluate((Lang)expr, bindings); + } + else if (expr instanceof LangMatches) { + return evaluate((LangMatches)expr, bindings); + } + else if (expr instanceof Datatype) { + return evaluate((Datatype)expr, bindings); + } + else if (expr instanceof Namespace) { + return evaluate((Namespace)expr, bindings); + } + else if (expr instanceof LocalName) { + return evaluate((LocalName)expr, bindings); + } + else if (expr instanceof IsResource) { + return evaluate((IsResource)expr, bindings); + } + else if (expr instanceof IsURI) { + return evaluate((IsURI)expr, bindings); + } + else if (expr instanceof IsBNode) { + return evaluate((IsBNode)expr, bindings); + } + else if (expr instanceof IsLiteral) { + return evaluate((IsLiteral)expr, bindings); + } + else if (expr instanceof IsNumeric) { + return evaluate((IsNumeric)expr, bindings); + } + else if (expr instanceof IRIFunction) { + return evaluate((IRIFunction)expr, bindings); + } + else if (expr instanceof Regex) { + return evaluate((Regex)expr, bindings); + } + else if (expr instanceof Coalesce) { + return evaluate((Coalesce)expr, bindings); + } + else if (expr instanceof Like) { + return evaluate((Like)expr, bindings); + } + else if (expr instanceof FunctionCall) { + return evaluate((FunctionCall)expr, bindings); + } + else if (expr instanceof And) { + return evaluate((And)expr, bindings); + } + else if (expr instanceof Or) { + return evaluate((Or)expr, bindings); + } + else if (expr instanceof Not) { + return evaluate((Not)expr, bindings); + } + else if (expr instanceof SameTerm) { + return evaluate((SameTerm)expr, bindings); + } + else if (expr instanceof Compare) { + return evaluate((Compare)expr, bindings); + } + else if (expr instanceof MathExpr) { + return evaluate((MathExpr)expr, bindings); + } + else if (expr instanceof In) { + return evaluate((In)expr, bindings); + } + else if (expr instanceof CompareAny) { + return evaluate((CompareAny)expr, bindings); + } + else if (expr instanceof CompareAll) { + return evaluate((CompareAll)expr, bindings); + } + else if (expr instanceof Exists) { + return evaluate((Exists)expr, bindings); + } + else if (expr instanceof If) { + return evaluate((If)expr, bindings); + } + else if (expr instanceof ListMemberOperator) { + return evaluate((ListMemberOperator)expr, bindings); + } + else if (expr == null) { + throw new IllegalArgumentException("expr must not be null"); + } + else { + throw new QueryEvaluationException("Unsupported value expr type: " + expr.getClass()); + } + } + + public Value evaluate(Var var, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value value = var.getValue(); + + if (value == null) { + value = bindings.getValue(var.getName()); + } + + if (value == null) { + throw new ValueExprEvaluationException(); + } + + return value; + } + + public Value evaluate(ValueConstant valueConstant, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + return valueConstant.getValue(); + } + + public Value evaluate(BNodeGenerator node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + ValueExpr nodeIdExpr = node.getNodeIdExpr(); + + if (nodeIdExpr != null) { + Value nodeId = evaluate(nodeIdExpr, bindings); + + if (nodeId instanceof Literal) { + String nodeLabel = ((Literal)nodeId).getLabel() + (bindings.toString().hashCode()); + return tripleSource.getValueFactory().createBNode(nodeLabel); + } + else { + throw new ValueExprEvaluationException("BNODE function argument must be a literal"); + } + } + return tripleSource.getValueFactory().createBNode(); + } + + public Value evaluate(Bound node, BindingSet bindings) + throws QueryEvaluationException + { + try { + Value argValue = evaluate(node.getArg(), bindings); + return BooleanLiteral.valueOf(argValue != null); + } + catch (ValueExprEvaluationException e) { + return BooleanLiteral.FALSE; + } + } + + public Value evaluate(Str node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + + if (argValue instanceof IRI) { + return tripleSource.getValueFactory().createLiteral(argValue.toString()); + } + else if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + if (QueryEvaluationUtil.isSimpleLiteral(literal)) { + return literal; + } + else { + return tripleSource.getValueFactory().createLiteral(literal.getLabel()); + } + } + else { + throw new ValueExprEvaluationException(); + } + } + + public Value evaluate(Label node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + // FIXME: deprecate Label in favour of Str(?) + Value argValue = evaluate(node.getArg(), bindings); + + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + + if (QueryEvaluationUtil.isSimpleLiteral(literal)) { + return literal; + } + else { + return tripleSource.getValueFactory().createLiteral(literal.getLabel()); + } + } + else { + throw new ValueExprEvaluationException(); + } + } + + public Value evaluate(Lang node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + + if (argValue instanceof Literal) { + Literal literal = (Literal)argValue; + return tripleSource.getValueFactory().createLiteral(literal.getLanguage().orElse("")); + } + + throw new ValueExprEvaluationException(); + } + + public Value evaluate(Datatype node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value v = evaluate(node.getArg(), bindings); + + if (v instanceof Literal) { + Literal literal = (Literal)v; + + if (literal.getDatatype() != null) { + // literal with datatype + return literal.getDatatype(); + } + else if (literal.getLanguage().isPresent()) { + return RDF.LANGSTRING; + } + else { + // simple literal + return XMLSchema.STRING; + } + + } + + throw new ValueExprEvaluationException(); + } + + public Value evaluate(Namespace node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + + if (argValue instanceof IRI) { + IRI uri = (IRI)argValue; + return tripleSource.getValueFactory().createIRI(uri.getNamespace()); + } + else { + throw new ValueExprEvaluationException(); + } + } + + public Value evaluate(LocalName node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + + if (argValue instanceof IRI) { + IRI uri = (IRI)argValue; + return tripleSource.getValueFactory().createLiteral(uri.getLocalName()); + } + else { + throw new ValueExprEvaluationException(); + } + } + + /** + * Determines whether the operand (a variable) contains a Resource. + * + * @return true if the operand contains a Resource, false + * otherwise. + */ + public Value evaluate(IsResource node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + return BooleanLiteral.valueOf(argValue instanceof Resource); + } + + /** + * Determines whether the operand (a variable) contains a URI. + * + * @return true if the operand contains a URI, false + * otherwise. + */ + public Value evaluate(IsURI node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + return BooleanLiteral.valueOf(argValue instanceof IRI); + } + + /** + * Determines whether the operand (a variable) contains a BNode. + * + * @return true if the operand contains a BNode, false + * otherwise. + */ + public Value evaluate(IsBNode node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + return BooleanLiteral.valueOf(argValue instanceof BNode); + } + + /** + * Determines whether the operand (a variable) contains a Literal. + * + * @return true if the operand contains a Literal, false + * otherwise. + */ + public Value evaluate(IsLiteral node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + return BooleanLiteral.valueOf(argValue instanceof Literal); + } + + /** + * Determines whether the operand (a variable) contains a numeric datatyped + * literal, i.e. a literal with datatype xsd:float, xsd:double, xsd:decimal, + * or a derived datatype of xsd:decimal. + * + * @return true if the operand contains a numeric datatyped literal, + * false otherwise. + */ + public Value evaluate(IsNumeric node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + + if (argValue instanceof Literal) { + Literal lit = (Literal)argValue; + IRI datatype = lit.getDatatype(); + + return BooleanLiteral.valueOf(XMLDatatypeUtil.isNumericDatatype(datatype)); + } + else { + return BooleanLiteral.FALSE; + } + + } + + /** + * Creates a URI from the operand value (a plain literal or a URI). + * + * @param node + * represents an invocation of the SPARQL IRI function + * @param bindings + * used to generate the value that the URI is based on + * @return a URI generated from the given arguments + * @throws ValueExprEvaluationException + * @throws QueryEvaluationException + */ + public IRI evaluate(IRIFunction node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + + if (argValue instanceof Literal) { + final Literal lit = (Literal)argValue; + + String uriString = lit.getLabel(); + final String baseURI = node.getBaseURI(); + + if (!URIUtil.isValidURIReference(uriString)) { + // uri string may be a relative reference. Try appending base URI + if (baseURI != null) { + uriString = baseURI + uriString; + if (!URIUtil.isValidURIReference(uriString)) { + throw new ValueExprEvaluationException("not a valid URI reference: " + uriString); + } + } + else { + throw new ValueExprEvaluationException("not a valid URI reference: " + uriString); + } + } + + IRI result = null; + + try { + result = tripleSource.getValueFactory().createIRI(uriString); + } + catch (IllegalArgumentException e) { + throw new ValueExprEvaluationException(e.getMessage()); + } + return result; + } + else if (argValue instanceof IRI) { + return ((IRI)argValue); + } + + throw new ValueExprEvaluationException(); + } + + /** + * Determines whether the two operands match according to the + * regex operator. + * + * @return true if the operands match according to the + * regex operator, false otherwise. + */ + public Value evaluate(Regex node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value arg = evaluate(node.getArg(), bindings); + Value parg = evaluate(node.getPatternArg(), bindings); + Value farg = null; + ValueExpr flagsArg = node.getFlagsArg(); + if (flagsArg != null) { + farg = evaluate(flagsArg, bindings); + } + + if (QueryEvaluationUtil.isStringLiteral(arg) && QueryEvaluationUtil.isSimpleLiteral(parg) + && (farg == null || QueryEvaluationUtil.isSimpleLiteral(farg))) + { + String text = ((Literal)arg).getLabel(); + String ptn = ((Literal)parg).getLabel(); + String flags = ""; + if (farg != null) { + flags = ((Literal)farg).getLabel(); + } + // TODO should this Pattern be cached? + int f = 0; + for (char c : flags.toCharArray()) { + switch (c) { + case 's': + f |= Pattern.DOTALL; + break; + case 'm': + f |= Pattern.MULTILINE; + break; + case 'i': + f |= Pattern.CASE_INSENSITIVE; + break; + case 'x': + f |= Pattern.COMMENTS; + break; + case 'd': + f |= Pattern.UNIX_LINES; + break; + case 'u': + f |= Pattern.UNICODE_CASE; + break; + default: + throw new ValueExprEvaluationException(flags); + } + } + Pattern pattern = Pattern.compile(ptn, f); + boolean result = pattern.matcher(text).find(); + return BooleanLiteral.valueOf(result); + } + + throw new ValueExprEvaluationException(); + } + + public Value evaluate(LangMatches node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value langTagValue = evaluate(node.getLeftArg(), bindings); + Value langRangeValue = evaluate(node.getRightArg(), bindings); + + if (QueryEvaluationUtil.isSimpleLiteral(langTagValue) + && QueryEvaluationUtil.isSimpleLiteral(langRangeValue)) + { + String langTag = ((Literal)langTagValue).getLabel(); + String langRange = ((Literal)langRangeValue).getLabel(); + + boolean result = false; + if (langRange.equals("*")) { + result = langTag.length() > 0; + } + else if (langTag.length() == langRange.length()) { + result = langTag.equalsIgnoreCase(langRange); + } + else if (langTag.length() > langRange.length()) { + // check if the range is a prefix of the tag + String prefix = langTag.substring(0, langRange.length()); + result = prefix.equalsIgnoreCase(langRange) && langTag.charAt(langRange.length()) == '-'; + } + + return BooleanLiteral.valueOf(result); + } + + throw new ValueExprEvaluationException(); + + } + + /** + * Determines whether the two operands match according to the + * like operator. The operator is defined as a string comparison + * with the possible use of an asterisk (*) at the end and/or the start of + * the second operand to indicate substring matching. + * + * @return true if the operands match according to the like + * operator, false otherwise. + */ + public Value evaluate(Like node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value val = evaluate(node.getArg(), bindings); + String strVal = null; + + if (val instanceof IRI) { + strVal = ((IRI)val).toString(); + } + else if (val instanceof Literal) { + strVal = ((Literal)val).getLabel(); + } + + if (strVal == null) { + throw new ValueExprEvaluationException(); + } + + if (!node.isCaseSensitive()) { + // Convert strVal to lower case, just like the pattern has been done + strVal = strVal.toLowerCase(); + } + + int valIndex = 0; + int prevPatternIndex = -1; + int patternIndex = node.getOpPattern().indexOf('*'); + + if (patternIndex == -1) { + // No wildcards + return BooleanLiteral.valueOf(node.getOpPattern().equals(strVal)); + } + + String snippet; + + if (patternIndex > 0) { + // Pattern does not start with a wildcard, first part must match + snippet = node.getOpPattern().substring(0, patternIndex); + if (!strVal.startsWith(snippet)) { + return BooleanLiteral.FALSE; + } + + valIndex += snippet.length(); + prevPatternIndex = patternIndex; + patternIndex = node.getOpPattern().indexOf('*', patternIndex + 1); + } + + while (patternIndex != -1) { + // Get snippet between previous wildcard and this wildcard + snippet = node.getOpPattern().substring(prevPatternIndex + 1, patternIndex); + + // Search for the snippet in the value + valIndex = strVal.indexOf(snippet, valIndex); + if (valIndex == -1) { + return BooleanLiteral.FALSE; + } + + valIndex += snippet.length(); + prevPatternIndex = patternIndex; + patternIndex = node.getOpPattern().indexOf('*', patternIndex + 1); + } + + // Part after last wildcard + snippet = node.getOpPattern().substring(prevPatternIndex + 1); + + if (snippet.length() > 0) { + // Pattern does not end with a wildcard. + + // Search last occurence of the snippet. + valIndex = strVal.indexOf(snippet, valIndex); + int i; + while ((i = strVal.indexOf(snippet, valIndex + 1)) != -1) { + // A later occurence was found. + valIndex = i; + } + + if (valIndex == -1) { + return BooleanLiteral.FALSE; + } + + valIndex += snippet.length(); + + if (valIndex < strVal.length()) { + // Some characters were not matched + return BooleanLiteral.FALSE; + } + } + + return BooleanLiteral.TRUE; + } + + /** + * Evaluates a function. + */ + public Value evaluate(FunctionCall node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Function function = FunctionRegistry.getInstance().get(node.getURI()).orElseThrow( + () -> new QueryEvaluationException("Unknown function '" + node.getURI() + "'")); + + // the NOW function is a special case as it needs to keep a shared return + // value for the duration of the query. + if (function instanceof Now) { + return evaluate((Now)function, bindings); + } + + List args = node.getArgs(); + + Value[] argValues = new Value[args.size()]; + + for (int i = 0; i < args.size(); i++) { + argValues[i] = evaluate(args.get(i), bindings); + } + + return function.evaluate(tripleSource.getValueFactory(), argValues); + + } + + public Value evaluate(And node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + try { + Value leftValue = evaluate(node.getLeftArg(), bindings); + if (QueryEvaluationUtil.getEffectiveBooleanValue(leftValue) == false) { + // Left argument evaluates to false, we don't need to look any + // further + return BooleanLiteral.FALSE; + } + } + catch (ValueExprEvaluationException e) { + // Failed to evaluate the left argument. Result is 'false' when + // the right argument evaluates to 'false', failure otherwise. + Value rightValue = evaluate(node.getRightArg(), bindings); + if (QueryEvaluationUtil.getEffectiveBooleanValue(rightValue) == false) { + return BooleanLiteral.FALSE; + } + else { + throw new ValueExprEvaluationException(); + } + } + + // Left argument evaluated to 'true', result is determined + // by the evaluation of the right argument. + Value rightValue = evaluate(node.getRightArg(), bindings); + return BooleanLiteral.valueOf(QueryEvaluationUtil.getEffectiveBooleanValue(rightValue)); + } + + public Value evaluate(Or node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + try { + Value leftValue = evaluate(node.getLeftArg(), bindings); + if (QueryEvaluationUtil.getEffectiveBooleanValue(leftValue) == true) { + // Left argument evaluates to true, we don't need to look any + // further + return BooleanLiteral.TRUE; + } + } + catch (ValueExprEvaluationException e) { + // Failed to evaluate the left argument. Result is 'true' when + // the right argument evaluates to 'true', failure otherwise. + Value rightValue = evaluate(node.getRightArg(), bindings); + if (QueryEvaluationUtil.getEffectiveBooleanValue(rightValue) == true) { + return BooleanLiteral.TRUE; + } + else { + throw new ValueExprEvaluationException(); + } + } + + // Left argument evaluated to 'false', result is determined + // by the evaluation of the right argument. + Value rightValue = evaluate(node.getRightArg(), bindings); + return BooleanLiteral.valueOf(QueryEvaluationUtil.getEffectiveBooleanValue(rightValue)); + } + + public Value evaluate(Not node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value argValue = evaluate(node.getArg(), bindings); + boolean argBoolean = QueryEvaluationUtil.getEffectiveBooleanValue(argValue); + return BooleanLiteral.valueOf(!argBoolean); + } + + public Value evaluate(Now node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + if (sharedValueOfNow == null) { + sharedValueOfNow = node.evaluate(tripleSource.getValueFactory()); + } + return sharedValueOfNow; + } + + public Value evaluate(SameTerm node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value leftVal = evaluate(node.getLeftArg(), bindings); + Value rightVal = evaluate(node.getRightArg(), bindings); + + return BooleanLiteral.valueOf(leftVal != null && leftVal.equals(rightVal)); + } + + public Value evaluate(Coalesce node, BindingSet bindings) + throws ValueExprEvaluationException + { + Value result = null; + + for (ValueExpr expr : node.getArguments()) { + try { + result = evaluate(expr, bindings); + + // return first result that does not produce an error on evaluation. + break; + } + catch (ValueExprEvaluationException e) { + continue; + } + catch (QueryEvaluationException e) { + continue; + } + } + + if (result == null) { + throw new ValueExprEvaluationException("COALESCE arguments do not evaluate to a value: " + + node.getSignature()); + } + + return result; + } + + public Value evaluate(Compare node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value leftVal = evaluate(node.getLeftArg(), bindings); + Value rightVal = evaluate(node.getRightArg(), bindings); + + return BooleanLiteral.valueOf(QueryEvaluationUtil.compare(leftVal, rightVal, node.getOperator())); + } + + public Value evaluate(MathExpr node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + // Do the math + Value leftVal = evaluate(node.getLeftArg(), bindings); + Value rightVal = evaluate(node.getRightArg(), bindings); + + if (leftVal instanceof Literal && rightVal instanceof Literal) { + return MathUtil.compute((Literal)leftVal, (Literal)rightVal, node.getOperator()); + } + + throw new ValueExprEvaluationException("Both arguments must be numeric literals"); + } + + public Value evaluate(If node, BindingSet bindings) + throws QueryEvaluationException + { + Value result = null; + + boolean conditionIsTrue; + + try { + Value value = evaluate(node.getCondition(), bindings); + conditionIsTrue = QueryEvaluationUtil.getEffectiveBooleanValue(value); + } + catch (ValueExprEvaluationException e) { + // in case of type error, if-construction should result in empty + // binding. + return null; + } + + if (conditionIsTrue) { + result = evaluate(node.getResult(), bindings); + } + else { + result = evaluate(node.getAlternative(), bindings); + } + return result; + } + + public Value evaluate(In node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value leftValue = evaluate(node.getArg(), bindings); + + // Result is false until a match has been found + boolean result = false; + + // Use first binding name from tuple expr to compare values + String bindingName = node.getSubQuery().getBindingNames().iterator().next(); + + CloseableIteration iter = evaluate(node.getSubQuery(), bindings); + try { + while (result == false && iter.hasNext()) { + BindingSet bindingSet = iter.next(); + + Value rightValue = bindingSet.getValue(bindingName); + + result = leftValue == null && rightValue == null || leftValue != null + && leftValue.equals(rightValue); + } + } + finally { + iter.close(); + } + + return BooleanLiteral.valueOf(result); + } + + public Value evaluate(ListMemberOperator node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + List args = node.getArguments(); + Value leftValue = evaluate(args.get(0), bindings); + + boolean result = false; + ValueExprEvaluationException typeError = null; + for (int i = 1; i < args.size(); i++) { + ValueExpr arg = args.get(i); + try { + Value rightValue = evaluate(arg, bindings); + result = leftValue == null && rightValue == null; + if (!result) { + result = QueryEvaluationUtil.compare(leftValue, rightValue, CompareOp.EQ); + } + if (result) { + break; + } + } + catch (ValueExprEvaluationException caught) { + typeError = caught; + } + } + + if (typeError != null && !result) { + // cf. SPARQL spec a type error is thrown if the value is not in the + // list and one of the list members caused a type error in the + // comparison. + throw typeError; + } + + return BooleanLiteral.valueOf(result); + } + + public Value evaluate(CompareAny node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value leftValue = evaluate(node.getArg(), bindings); + + // Result is false until a match has been found + boolean result = false; + + // Use first binding name from tuple expr to compare values + String bindingName = node.getSubQuery().getBindingNames().iterator().next(); + + CloseableIteration iter = evaluate(node.getSubQuery(), bindings); + try { + while (result == false && iter.hasNext()) { + BindingSet bindingSet = iter.next(); + + Value rightValue = bindingSet.getValue(bindingName); + + try { + result = QueryEvaluationUtil.compare(leftValue, rightValue, node.getOperator()); + } + catch (ValueExprEvaluationException e) { + // ignore, maybe next value will match + } + } + } + finally { + iter.close(); + } + + return BooleanLiteral.valueOf(result); + } + + public Value evaluate(CompareAll node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + Value leftValue = evaluate(node.getArg(), bindings); + + // Result is true until a mismatch has been found + boolean result = true; + + // Use first binding name from tuple expr to compare values + String bindingName = node.getSubQuery().getBindingNames().iterator().next(); + + CloseableIteration iter = evaluate(node.getSubQuery(), bindings); + try { + while (result == true && iter.hasNext()) { + BindingSet bindingSet = iter.next(); + + Value rightValue = bindingSet.getValue(bindingName); + + try { + result = QueryEvaluationUtil.compare(leftValue, rightValue, node.getOperator()); + } + catch (ValueExprEvaluationException e) { + // Exception thrown by ValueCompare.isTrue(...) + result = false; + } + } + } + finally { + iter.close(); + } + + return BooleanLiteral.valueOf(result); + } + + public Value evaluate(Exists node, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + CloseableIteration iter = evaluate(node.getSubQuery(), bindings); + try { + return BooleanLiteral.valueOf(iter.hasNext()); + } + finally { + iter.close(); + } + } + + @Override + public boolean isTrue(ValueExpr expr, BindingSet bindings) + throws QueryEvaluationException + { + try { + Value value = evaluate(expr, bindings); + return QueryEvaluationUtil.getEffectiveBooleanValue(value); + } + catch (ValueExprEvaluationException e) { + return false; + } + } + + protected boolean isReducedOrDistinct(QueryModelNode node) { + QueryModelNode parent = node.getParentNode(); + if (parent instanceof Slice) { + return isReducedOrDistinct(parent); + } + return parent instanceof Distinct || parent instanceof Reduced; + } + + /** + * Returns the limit of the current variable bindings before any further + * projection. + */ + protected long getLimit(QueryModelNode node) { + long offset = 0; + if (node instanceof Slice) { + Slice slice = (Slice)node; + if (slice.hasOffset() && slice.hasLimit()) { + return slice.getOffset() + slice.getLimit(); + } + else if (slice.hasLimit()) { + return slice.getLimit(); + } + else if (slice.hasOffset()) { + offset = slice.getOffset(); + } + } + QueryModelNode parent = node.getParentNode(); + if (parent instanceof Distinct || parent instanceof Reduced || parent instanceof Slice) { + long limit = getLimit(parent); + if (offset > 0L && limit < Long.MAX_VALUE) { + return offset + limit; + } + else { + return limit; + } + } + return Long.MAX_VALUE; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BadlyDesignedLeftJoinIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BadlyDesignedLeftJoinIterator.java new file mode 100644 index 00000000000..6bc74e8cc7e --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BadlyDesignedLeftJoinIterator.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.Set; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; + +/** + * @author Arjohn Kampman + */ +public class BadlyDesignedLeftJoinIterator extends LeftJoinIterator { + + /*-----------* + * Variables * + *-----------*/ + + private final BindingSet inputBindings; + + private final Set problemVars; + + /*--------------* + * Constructors * + *--------------*/ + + public BadlyDesignedLeftJoinIterator(EvaluationStrategy strategy, LeftJoin join, BindingSet inputBindings, + Set problemVars) + throws QueryEvaluationException + { + super(strategy, join, getFilteredBindings(inputBindings, problemVars)); + this.inputBindings = inputBindings; + this.problemVars = problemVars; + } + + /*---------* + * Methods * + *---------*/ + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + BindingSet result = super.getNextElement(); + + // Ignore all results that are not compatible with the input bindings + while (result != null && !QueryResults.bindingSetsCompatible(inputBindings, result)) { + result = super.getNextElement(); + } + + if (result != null) { + // Make sure the provided problemVars are part of the returned results + // (necessary in case of e.g. LeftJoin and Union arguments) + QueryBindingSet extendedResult = null; + + for (String problemVar : problemVars) { + if (!result.hasBinding(problemVar)) { + if (extendedResult == null) { + extendedResult = new QueryBindingSet(result); + } + extendedResult.addBinding(problemVar, inputBindings.getValue(problemVar)); + } + } + + if (extendedResult != null) { + result = extendedResult; + } + } + + return result; + } + + /*--------------------* + * Static util method * + *--------------------*/ + + private static QueryBindingSet getFilteredBindings(BindingSet bindings, Set problemVars) { + QueryBindingSet filteredBindings = new QueryBindingSet(bindings); + filteredBindings.removeAll(problemVars); + return filteredBindings; + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BindingSetHashKey.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BindingSetHashKey.java new file mode 100644 index 00000000000..d8ab2ca60a8 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BindingSetHashKey.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.io.Serializable; +import java.util.Arrays; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; + +/** + * Compact and efficient representation of a binding set for use as a key in + * hash maps. + * + * @author MJAHale + */ +public class BindingSetHashKey implements Serializable { + + private static final long serialVersionUID = 6407405580643353289L; + + public static final BindingSetHashKey EMPTY = new BindingSetHashKey(new Value[0]); + + private final Value[] values; + + private transient int hashcode; + + public static BindingSetHashKey create(String[] varNames, BindingSet bindings) { + BindingSetHashKey key; + int varNameSize = varNames.length; + if (varNameSize > 0) { + Value[] keyValues = new Value[varNameSize]; + for (int i = 0; i < varNameSize; i++) { + Value value = bindings.getValue(varNames[i]); + keyValues[i] = value; + } + key = new BindingSetHashKey(keyValues); + } + else { + key = BindingSetHashKey.EMPTY; + } + return key; + } + + private BindingSetHashKey(Value[] values) { + this.values = values; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof BindingSetHashKey)) { + return false; + } + + BindingSetHashKey jk = (BindingSetHashKey)o; + if (this.values.length != jk.values.length) { + return false; + } + + for (int i = values.length - 1; i >= 0; i--) { + final Value v1 = this.values[i]; + final Value v2 = jk.values[i]; + + if (v1 == null) { + if (v2 != null) { + return false; + } + } + else { + if (!v1.equals(v2)) { + return false; + } + } + } + return true; + } + + @Override + public int hashCode() { + if (hashcode == 0) { + hashcode = Arrays.hashCode(values); + } + return hashcode; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BottomUpJoinIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BottomUpJoinIterator.java new file mode 100644 index 00000000000..b76681166cd --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BottomUpJoinIterator.java @@ -0,0 +1,276 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; + +/** + * Join Iterator that executes a basic bottom-up hash-join algorithm. To be used + * in cases where interleaved iteration joining is not appropriate (e.g. when + * the join arguments are subselects). + * + * @author jeen + * @deprecated replaced by HashJoinIteration + */ +@Deprecated +public class BottomUpJoinIterator extends LookAheadIteration { + + /*-----------* + * Variables * + *-----------*/ + + private final CloseableIteration leftIter; + + private volatile CloseableIteration rightIter; + + private List scanList; + + private CloseableIteration restIter; + + private Map> hashTable; + + private Set joinAttributes; + + private BindingSet currentScanElem; + + private List hashTableValues; + + /*--------------* + * Constructors * + *--------------*/ + + public BottomUpJoinIterator(EvaluationStrategy strategy, Join join, BindingSet bindings) + throws QueryEvaluationException + { + leftIter = strategy.evaluate(join.getLeftArg(), bindings); + rightIter = strategy.evaluate(join.getRightArg(), bindings); + + joinAttributes = join.getLeftArg().getBindingNames(); + joinAttributes.retainAll(join.getRightArg().getBindingNames()); + + hashTable = null; + } + + /*---------* + * Methods * + *---------*/ + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + if (hashTable == null) { + setupHashTable(); + } + + while (currentScanElem == null) { + if (scanList.size() > 0) { + currentScanElem = removeFirstElement(scanList); + } + else { + if (restIter.hasNext()) { + currentScanElem = restIter.next(); + } + else { + // no more elements available + return null; + } + } + + if (currentScanElem instanceof EmptyBindingSet) { + // the empty bindingset should be merged with all bindingset in the + // hash table + hashTableValues = makeList(); + for (Map.Entry> key : hashTable.entrySet()) { + addAll(hashTableValues, key.getValue()); + } + } + else { + BindingSet key = calcKey(currentScanElem, joinAttributes); + + if (hashTable.containsKey(key)) { + hashTableValues = makeList(hashTable.get(key)); + } + else { + currentScanElem = null; + hashTableValues = null; + } + } + } + + BindingSet nextHashTableValue = removeFirstElement(hashTableValues); + + QueryBindingSet result = new QueryBindingSet(currentScanElem); + + for (String name : nextHashTableValue.getBindingNames()) { + Binding b = nextHashTableValue.getBinding(name); + if (!result.hasBinding(name)) { + result.addBinding(b); + } + } + + if (hashTableValues.size() == 0) { + // we've exhausted the current scanlist entry + currentScanElem = null; + hashTableValues = null; + } + + return result; + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + super.handleClose(); + + leftIter.close(); + rightIter.close(); + + hashTable = null; + hashTableValues = null; + scanList = null; + } + + /** + * @return the size that the hashtable had before clearing it. + */ + protected long clearHashTable() { + int size = hashTable.size(); + hashTable.clear(); + return size; + } + + private BindingSet calcKey(BindingSet bindings, Set commonVars) { + QueryBindingSet q = new QueryBindingSet(); + for (String varName : commonVars) { + Binding b = bindings.getBinding(varName); + if (b != null) { + q.addBinding(b); + } + } + return q; + } + + private void setupHashTable() + throws QueryEvaluationException + { + + hashTable = makeMap(); + + List leftArgResults = makeList(); + List rightArgResults = makeList(); + + while (leftIter.hasNext() && rightIter.hasNext()) { + add(leftArgResults, leftIter.next()); + add(rightArgResults, rightIter.next()); + } + + List smallestResult = null; + + if (leftIter.hasNext()) { // leftArg is the greater relation + smallestResult = rightArgResults; + scanList = leftArgResults; + restIter = leftIter; + } + else { // rightArg is the greater relation (or they are equal) + smallestResult = leftArgResults; + scanList = rightArgResults; + restIter = rightIter; + } + + // create the hash table for our join + for (BindingSet b : smallestResult) { + BindingSet hashKey = calcKey(b, joinAttributes); + + List hashValue = null; + if (hashTable.containsKey(hashKey)) { + hashValue = hashTable.get(hashKey); + } + else { + hashValue = makeList(); + } + add(hashValue, b); + put(hashTable, hashKey, hashValue); + } + + } + + protected void put(Map> hashTable, BindingSet hashKey, + List hashValue) + throws QueryEvaluationException + { + hashTable.put(hashKey, hashValue); + } + + protected void addAll(List hashTableValues, List values) + throws QueryEvaluationException + { + hashTableValues.addAll(values); + } + + protected void add(List leftArgResults, BindingSet b) + throws QueryEvaluationException + { + leftArgResults.add(b); + } + + /** + * Utility methods to make it easier to inserted custom store dependent maps + * + * @return map + */ + protected Map> makeMap() { + return new HashMap>(); + } + + /** + * Utility methods to make it easier to inserted custom store dependent list + * + * @return list + */ + protected List makeList() { + return new ArrayList(); + } + + /** + * Utility methods to make it easier to inserted custom store dependent list + * + * @return list + */ + protected List makeList(List key) { + return new ArrayList(key); + } + + /** + * Remove the first (0 index) element from a BindingSet list. + * + * @param list + * which is worked on. + * @return the removed BindingSet + */ + protected BindingSet removeFirstElement(List list) + throws QueryEvaluationException + { + return list.remove(0); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CollectionIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CollectionIteration.java new file mode 100644 index 00000000000..0871ed2068c --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CollectionIteration.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.Collection; +import java.util.Iterator; + +import org.eclipse.rdf4j.common.iteration.AbstractCloseableIteration; + +/** + * An iteration to access a materialized {@link Collection} of BindingSets. + * + * @author Andreas Schwarte + */ +public class CollectionIteration extends AbstractCloseableIteration { + + + protected final Collection collection; + protected Iterator iterator; + + /** + * @param collection + */ + public CollectionIteration(Collection collection) { + super(); + this.collection = collection; + iterator = collection.iterator(); + } + + + public boolean hasNext() throws X { + return iterator.hasNext(); + } + + public E next() throws X { + return iterator.next(); + } + + public void remove() throws X { + throw new UnsupportedOperationException("Remove not supported on CollectionIteration"); + } + + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CompatibleBindingSetFilter.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CompatibleBindingSetFilter.java new file mode 100644 index 00000000000..8515adcc84e --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CompatibleBindingSetFilter.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.FilterIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryResults; + +/** + * @author Arjohn Kampman + * @deprecated + */ +@Deprecated +public class CompatibleBindingSetFilter extends FilterIteration { + + private final BindingSet inputBindings; + + public CompatibleBindingSetFilter(CloseableIteration iter, + BindingSet inputBindings) + { + super(iter); + + assert inputBindings != null; + this.inputBindings = inputBindings; + } + + @Override + protected boolean accept(BindingSet outputBindings) + throws QueryEvaluationException + { + return QueryResults.bindingSetsCompatible(inputBindings, outputBindings); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CrossProductIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CrossProductIteration.java new file mode 100644 index 00000000000..f426c492650 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/CrossProductIteration.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; + +/** + * Iteration which forms the cross product of a list of materialized input bindings + * with each result obtained from the inner iteration. + * + * Example: + * + * inputBindings := {b1, b2, ...} + * resultIteration := {r1, r2, ...} + * + * getNextElement() returns (r1,b1), (r1, b2), ..., (r2, b1), (r2, b2), ... + * + * i.e. compute the cross product per result binding + * + * + * + * @author Andreas Schwarte + */ +public class CrossProductIteration extends LookAheadIteration { + + protected final List inputBindings; + protected final CloseableIteration resultIteration; + + protected Iterator inputBindingsIterator = null; + protected BindingSet currentInputBinding = null; + + public CrossProductIteration( + CloseableIteration resultIteration, + List inputBindings) { + super(); + this.resultIteration = resultIteration; + this.inputBindings = inputBindings; + } + + @Override + protected BindingSet getNextElement() throws QueryEvaluationException { + + if (currentInputBinding==null) { + inputBindingsIterator = inputBindings.iterator(); + if (resultIteration.hasNext()) + currentInputBinding = resultIteration.next(); + else + return null; // no more results + } + + if (inputBindingsIterator.hasNext()) { + BindingSet next = inputBindingsIterator.next(); + QueryBindingSet res = new QueryBindingSet(next.size() + currentInputBinding.size() ); + res.addAll(next); + res.addAll(currentInputBinding); + if (!inputBindingsIterator.hasNext()) + currentInputBinding = null; + return res; + } + + return null; + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/DescribeIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/DescribeIteration.java new file mode 100644 index 00000000000..1f81304561d --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/DescribeIteration.java @@ -0,0 +1,230 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Queue; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.EmptyIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; + +/** + * Iteration that implements a simplified version of Symmetric Concise Bounded + * Description (omitting reified statements). + * + * @author Jeen Broekstra + * @since 2.7.4 + * @see Concise Bounded Description - alternatives + */ +public class DescribeIteration extends LookAheadIteration { + + private final static String VARNAME_SUBJECT = "subject"; + + private final static String VARNAME_PREDICATE = "predicate"; + + private final static String VARNAME_OBJECT = "object"; + + private final List describeExprNames; + + private final EvaluationStrategy strategy; + + private Value startValue; + + private final Queue nodeQueue = new ArrayDeque(); + + private final Set processedNodes = new HashSet(); + + private CloseableIteration currentDescribeExprIter; + + private enum Mode { + OUTGOING_LINKS, + INCOMING_LINKS + } + + private Mode currentMode = Mode.OUTGOING_LINKS; + + private Iteration sourceIter; + + public DescribeIteration(Iteration sourceIter, + EvaluationStrategy strategy, Set describeExprNames, BindingSet parentBindings) + { + this.strategy = strategy; + this.sourceIter = sourceIter; + this.describeExprNames = new ArrayList(describeExprNames); + this.parentBindings = parentBindings; + } + + private BindingSet currentBindings; + + private int describeExprsIndex; + + private BindingSet parentBindings; + + + private void resetCurrentDescribeExprIter() throws QueryEvaluationException { + while (currentDescribeExprIter == null) { + if (currentBindings == null && startValue == null) { + if (sourceIter.hasNext()) { + currentBindings = sourceIter.next(); + } + else { + // no more bindings, therefore no more results to return. + return; + } + } + + if (startValue == null) { + String nextValueExpr = describeExprNames.get(describeExprsIndex++); + if (nextValueExpr != null) { + startValue = currentBindings.getValue(nextValueExpr); + if (describeExprsIndex == describeExprNames.size()) { + // reached the end of the list of valueExprs, reset to + // read next value from source iterator if any. + currentBindings = null; + describeExprsIndex = 0; + } + currentMode = Mode.OUTGOING_LINKS; + } + } + + switch (currentMode) { + case OUTGOING_LINKS: + currentDescribeExprIter = createNextIteration(startValue, null); + if (!currentDescribeExprIter.hasNext()) { + // start value has no outgoing links. + currentDescribeExprIter.close(); + currentDescribeExprIter = null; + currentMode = Mode.INCOMING_LINKS; + } + break; + case INCOMING_LINKS: + currentDescribeExprIter = createNextIteration(null, startValue); + if (!currentDescribeExprIter.hasNext()) { + // no incoming links for this start value. + currentDescribeExprIter.close(); + currentDescribeExprIter = null; + startValue = null; + currentMode = Mode.OUTGOING_LINKS; + } + break; + } + } // end while + } + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + resetCurrentDescribeExprIter(); + if (currentDescribeExprIter == null) { + return null; + } + + while (!currentDescribeExprIter.hasNext() && !nodeQueue.isEmpty()) { + // process next node in queue + BNode nextNode = nodeQueue.poll(); + currentDescribeExprIter.close(); + switch (currentMode) { + case OUTGOING_LINKS: + currentDescribeExprIter = createNextIteration(nextNode, null); + break; + case INCOMING_LINKS: + currentDescribeExprIter = createNextIteration(null, nextNode); + break; + + } + processedNodes.add(nextNode); + + if (nodeQueue.isEmpty() && !currentDescribeExprIter.hasNext()) { + // we have hit a blank node that has no further expansion. reset to + // initialize next in value expression queue. + currentDescribeExprIter.close(); + currentDescribeExprIter = null; + + if (currentMode == Mode.OUTGOING_LINKS) { + currentMode = Mode.INCOMING_LINKS; + } + else { + // done with this valueExpr, reset to initialize next in value + // expression queue. + currentMode = Mode.OUTGOING_LINKS; + startValue = null; + } + + resetCurrentDescribeExprIter(); + if (currentDescribeExprIter == null) { + return null; + } + } + + } + + if (currentDescribeExprIter.hasNext()) { + BindingSet bs = currentDescribeExprIter.next(); + + String varname = currentMode == Mode.OUTGOING_LINKS ? VARNAME_OBJECT : VARNAME_SUBJECT; + + Value v = bs.getValue(varname); + if (v instanceof BNode) { + if (!processedNodes.contains(v)) { // duplicate/cycle detection + nodeQueue.add((BNode)v); + } + } + + if (!currentDescribeExprIter.hasNext() && nodeQueue.isEmpty()) { + currentDescribeExprIter.close(); + currentDescribeExprIter = null; + + if (currentMode == Mode.OUTGOING_LINKS) { + currentMode = Mode.INCOMING_LINKS; + } + else { + // done with this valueExpr, reset to initialize next in value + // expression queue. + currentMode = Mode.OUTGOING_LINKS; + startValue = null; + } + } + + return bs; + } + + return null; + } + + private CloseableIteration createNextIteration(Value subject, + Value object) + throws QueryEvaluationException + { + if (subject == null && object == null) { + return new EmptyIteration(); + } + + Var subjVar = new Var(VARNAME_SUBJECT, subject); + Var predVar = new Var(VARNAME_PREDICATE); + Var objVar = new Var(VARNAME_OBJECT, object); + + StatementPattern pattern = new StatementPattern(subjVar, predVar, objVar); + return strategy.evaluate(pattern, parentBindings); + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ExtensionIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ExtensionIterator.java new file mode 100644 index 00000000000..e2370691d3f --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ExtensionIterator.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.ConvertingIteration; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.AggregateOperator; +import org.eclipse.rdf4j.query.algebra.Extension; +import org.eclipse.rdf4j.query.algebra.ExtensionElem; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; + +public class ExtensionIterator extends ConvertingIteration { + + private final Extension extension; + + private final EvaluationStrategy strategy; + + public ExtensionIterator(Extension extension, + CloseableIteration iter, EvaluationStrategy strategy) + throws QueryEvaluationException + { + super(iter); + this.extension = extension; + this.strategy = strategy; + } + + @Override + public BindingSet convert(BindingSet sourceBindings) + throws QueryEvaluationException + { + QueryBindingSet targetBindings = new QueryBindingSet(sourceBindings); + + for (ExtensionElem extElem : extension.getElements()) { + ValueExpr expr = extElem.getExpr(); + if (!(expr instanceof AggregateOperator)) { + try { + // we evaluate each extension element over the targetbindings, so that bindings from + // a previous extension element in this same extension can be used by other extension elements. + // e.g. if a projection contains (?a + ?b as ?c) (?c * 2 as ?d) + Value targetValue = strategy.evaluate(extElem.getExpr(), targetBindings); + + if (targetValue != null) { + // Potentially overwrites bindings from super + targetBindings.setBinding(extElem.getName(), targetValue); + } + } + catch (ValueExprEvaluationException e) { + // silently ignore type errors in extension arguments. They should not cause the + // query to fail but just result in no additional binding. + } + } + } + + return targetBindings; + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/FilterIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/FilterIterator.java new file mode 100644 index 00000000000..9c79dede1b8 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/FilterIterator.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.FilterIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.SubQueryValueOperator; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; + +public class FilterIterator extends FilterIteration { + + /*-----------* + * Constants * + *-----------*/ + + private final Filter filter; + + private final EvaluationStrategy strategy; + + /** + * The set of binding names that are "in scope" for the filter. The filter + * must not include bindings that are (only) included because of the + * depth-first evaluation strategy in the evaluation of the constraint. + */ + private final Set scopeBindingNames; + + /*--------------* + * Constructors * + *--------------*/ + + public FilterIterator(Filter filter, CloseableIteration iter, + EvaluationStrategy strategy) + throws QueryEvaluationException + { + super(iter); + this.filter = filter; + this.strategy = strategy; + this.scopeBindingNames = filter.getBindingNames(); + + } + + /*---------* + * Methods * + *---------*/ + + private boolean isPartOfSubQuery(QueryModelNode node) { + if (node instanceof SubQueryValueOperator) { + return true; + } + + QueryModelNode parent = node.getParentNode(); + if (parent == null) { + return false; + } + else { + return isPartOfSubQuery(parent); + } + } + + @Override + protected boolean accept(BindingSet bindings) + throws QueryEvaluationException + { + try { + // Limit the bindings to the ones that are in scope for this filter + QueryBindingSet scopeBindings = new QueryBindingSet(bindings); + + // FIXME J1 scopeBindingNames should include bindings from superquery if the filter + // is part of a subquery. This is a workaround: we should fix the settings of scopeBindingNames, + // rather than skipping the limiting of bindings. + if (!isPartOfSubQuery(filter)) { + scopeBindings.retainAll(scopeBindingNames); + } + + return strategy.isTrue(filter.getCondition(), scopeBindings); + } + catch (ValueExprEvaluationException e) { + // failed to evaluate condition + return false; + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java new file mode 100644 index 00000000000..437a23168f1 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java @@ -0,0 +1,740 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration; +import org.eclipse.rdf4j.common.lang.ObjectUtil; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.AbstractAggregateOperator; +import org.eclipse.rdf4j.query.algebra.AggregateOperator; +import org.eclipse.rdf4j.query.algebra.Avg; +import org.eclipse.rdf4j.query.algebra.Count; +import org.eclipse.rdf4j.query.algebra.Group; +import org.eclipse.rdf4j.query.algebra.GroupConcat; +import org.eclipse.rdf4j.query.algebra.GroupElem; +import org.eclipse.rdf4j.query.algebra.Max; +import org.eclipse.rdf4j.query.algebra.Min; +import org.eclipse.rdf4j.query.algebra.Sample; +import org.eclipse.rdf4j.query.algebra.Sum; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.MathExpr.MathOp; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.MathUtil; +import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.mapdb.DB; +import org.mapdb.DBMaker; + +/** + * @author David Huynh + * @author Arjohn Kampman + * @author Jeen Broekstra + * @author James Leigh + */ +public class GroupIterator extends CloseableIteratorIteration { + + /*-----------* + * Constants * + *-----------*/ + + private final SimpleValueFactory vf = SimpleValueFactory.getInstance(); + + private final EvaluationStrategy strategy; + + private final BindingSet parentBindings; + + private final Group group; + + private boolean initialized = false; + + private final Object lock = new Object(); + + private final File tempFile; + + private final DB db; + + /** + * Number of items cached before internal collections are synced to disk. If + * set to 0, no disk-syncing is done and all internal caching is kept in + * memory. + */ + private final long iterationCacheSyncThreshold; + + /*--------------* + * Constructors * + *--------------*/ + + public GroupIterator(EvaluationStrategy strategy, Group group, BindingSet parentBindings) + throws QueryEvaluationException + { + this(strategy, group, parentBindings, 0); + } + + public GroupIterator(EvaluationStrategy strategy, Group group, BindingSet parentBindings, + long iterationCacheSyncThreshold) + throws QueryEvaluationException + { + this.strategy = strategy; + this.group = group; + this.parentBindings = parentBindings; + this.iterationCacheSyncThreshold = iterationCacheSyncThreshold; + + if (this.iterationCacheSyncThreshold > 0) { + try { + this.tempFile = File.createTempFile("group-eval", null); + } + catch (IOException e) { + throw new QueryEvaluationException("could not initialize temp db", e); + } + this.db = DBMaker.newFileDB(tempFile).deleteFilesAfterClose().closeOnJvmShutdown().make(); + } + else { + this.tempFile = null; + this.db = null; + } + } + + /*---------* + * Methods * + *---------*/ + + @Override + public boolean hasNext() + throws QueryEvaluationException + { + if (!initialized) { + synchronized (lock) { + if (!initialized) { + super.setIterator(createIterator()); + initialized = true; + } + } + } + return super.hasNext(); + } + + @Override + public BindingSet next() + throws QueryEvaluationException + { + if (!initialized) { + synchronized (lock) { + if (!initialized) { + super.setIterator(createIterator()); + initialized = true; + } + } + } + return super.next(); + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + super.handleClose(); + if (this.db != null) { + this.db.close(); + } + } + + private Set createSet(String setName) { + if (db != null) { + return db.getHashSet(setName); + } + else { + return new HashSet(); + } + } + + private Iterator createIterator() + throws QueryEvaluationException + { + Collection entries = buildEntries(); + Set bindingSets = createSet("bindingsets"); + + for (Entry entry : entries) { + QueryBindingSet sol = new QueryBindingSet(parentBindings); + + for (String name : group.getGroupBindingNames()) { + BindingSet prototype = entry.getPrototype(); + if (prototype != null) { + Value value = prototype.getValue(name); + if (value != null) { + // Potentially overwrites bindings from super + sol.setBinding(name, value); + } + } + } + + entry.bindSolution(sol); + + bindingSets.add(sol); + } + + return bindingSets.iterator(); + } + + private Collection buildEntries() + throws QueryEvaluationException + { + CloseableIteration iter; + iter = strategy.evaluate(group.getArg(), parentBindings); + + try { + Map entries = new LinkedHashMap(); + + if (!iter.hasNext()) { + // no solutions, still need to process aggregates to produce a + // zero-result. + entries.put(new Key(EmptyBindingSet.getInstance()), new Entry(EmptyBindingSet.getInstance())); + } + + // long count = 0; + + while (iter.hasNext()) { + BindingSet sol; + try { + sol = iter.next(); + } + catch (NoSuchElementException e) { + break; // closed + } + Key key = new Key(sol); + Entry entry = entries.get(key); + + if (entry == null) { + entry = new Entry(sol); + entries.put(key, entry); + } + + entry.addSolution(sol); + } + + return entries.values(); + } + finally { + iter.close(); + } + + } + + /** + * A unique key for a set of existing bindings. + * + * @author David Huynh + */ + protected class Key implements Serializable { + + private static final long serialVersionUID = 4461951265373324084L; + + private BindingSet bindingSet; + + private int hash; + + public Key(BindingSet bindingSet) { + this.bindingSet = bindingSet; + + for (String name : group.getGroupBindingNames()) { + Value value = bindingSet.getValue(name); + if (value != null) { + this.hash ^= value.hashCode(); + } + } + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object other) { + if (other instanceof Key && other.hashCode() == hash) { + BindingSet otherSolution = ((Key)other).bindingSet; + + for (String name : group.getGroupBindingNames()) { + Value v1 = bindingSet.getValue(name); + Value v2 = otherSolution.getValue(name); + + if (!ObjectUtil.nullEquals(v1, v2)) { + return false; + } + } + + return true; + } + + return false; + } + } + + private class Entry { + + private BindingSet prototype; + + private Map aggregates; + + public Entry(BindingSet prototype) + throws ValueExprEvaluationException, QueryEvaluationException + { + this.prototype = prototype; + + } + + private Map getAggregates() + throws ValueExprEvaluationException, QueryEvaluationException + { + if (this.aggregates == null) { + this.aggregates = new LinkedHashMap(); + for (GroupElem ge : group.getGroupElements()) { + Aggregate create = create(ge.getOperator()); + if (create != null) { + aggregates.put(ge.getName(), create); + } + } + } + return this.aggregates; + } + + public BindingSet getPrototype() { + return prototype; + } + + public void addSolution(BindingSet bindingSet) + throws QueryEvaluationException + { + for (Aggregate aggregate : getAggregates().values()) { + aggregate.processAggregate(bindingSet); + } + } + + public void bindSolution(QueryBindingSet sol) + throws QueryEvaluationException + { + for (String name : getAggregates().keySet()) { + try { + Value value = getAggregates().get(name).getValue(); + if (value != null) { + // Potentially overwrites bindings from super + sol.setBinding(name, value); + } + } + catch (ValueExprEvaluationException ex) { + // There was a type error when calculating the value of the + // aggregate. + // We silently ignore the error, resulting in no result value + // being bound. + } + } + } + + private Aggregate create(AggregateOperator operator) + throws ValueExprEvaluationException, QueryEvaluationException + { + if (operator instanceof Count) { + return new CountAggregate((Count)operator); + } + else if (operator instanceof Min) { + return new MinAggregate((Min)operator); + } + else if (operator instanceof Max) { + return new MaxAggregate((Max)operator); + } + else if (operator instanceof Sum) { + return new SumAggregate((Sum)operator); + } + else if (operator instanceof Avg) { + return new AvgAggregate((Avg)operator); + } + else if (operator instanceof Sample) { + return new SampleAggregate((Sample)operator); + } + else if (operator instanceof GroupConcat) { + return new ConcatAggregate((GroupConcat)operator); + } + return null; + } + } + + private abstract class Aggregate { + + private final Set distinctValues; + + private final ValueExpr arg; + + public Aggregate(AbstractAggregateOperator operator) { + this.arg = operator.getArg(); + + if (operator.isDistinct()) { + distinctValues = createSet("distinct-values-" + this.hashCode()); + } + else { + distinctValues = null; + } + } + + public abstract Value getValue() + throws ValueExprEvaluationException; + + public abstract void processAggregate(BindingSet bindingSet) + throws QueryEvaluationException; + + protected boolean distinctValue(Value value) { + if (distinctValues == null) { + return true; + } + + final boolean result = distinctValues.add(value); + if (db != null && distinctValues.size() % iterationCacheSyncThreshold == 0) { + // write to disk every $iterationCacheSyncThreshold items + db.commit(); + } + + return result; + } + + protected ValueExpr getArg() { + return arg; + } + + protected Value evaluate(BindingSet s) + throws QueryEvaluationException + { + try { + return strategy.evaluate(getArg(), s); + } + catch (ValueExprEvaluationException e) { + return null; // treat missing or invalid expressions as null + } + } + } + + private class CountAggregate extends Aggregate { + + private long count = 0; + + private final Set distinctBindingSets; + + public CountAggregate(Count operator) { + super(operator); + + // for a wildcarded count with a DISTINCT clause we need to filter on + // distinct bindingsets rather than individual values. + if (operator.isDistinct() && getArg() == null) { + distinctBindingSets = createSet("distinct-bs-" + this.hashCode()); + } + else { + distinctBindingSets = null; + } + } + + @Override + public void processAggregate(BindingSet s) + throws QueryEvaluationException + { + if (getArg() != null) { + Value value = evaluate(s); + if (value != null && distinctValue(value)) { + count++; + } + } + else { + // wildcard count + if (distinctBindingSet(s)) { + count++; + } + } + } + + protected boolean distinctBindingSet(BindingSet s) { + if (distinctBindingSets == null) { + return true; + } + + final boolean result = distinctBindingSets.add(s); + if (db != null && distinctBindingSets.size() % iterationCacheSyncThreshold == 0) { + // write to disk every + db.commit(); + } + + return result; + } + + @Override + public Value getValue() { + return vf.createLiteral(Long.toString(count), XMLSchema.INTEGER); + } + } + + private class MinAggregate extends Aggregate { + + private final ValueComparator comparator = new ValueComparator(); + + private Value min = null; + + public MinAggregate(Min operator) { + super(operator); + } + + @Override + public void processAggregate(BindingSet s) + throws QueryEvaluationException + { + Value v = evaluate(s); + if (distinctValue(v)) { + if (min == null) { + min = v; + } + else if (comparator.compare(v, min) < 0) { + min = v; + } + } + } + + @Override + public Value getValue() { + return min; + } + } + + private class MaxAggregate extends Aggregate { + + private final ValueComparator comparator = new ValueComparator(); + + private Value max = null; + + public MaxAggregate(Max operator) { + super(operator); + } + + @Override + public void processAggregate(BindingSet s) + throws QueryEvaluationException + { + Value v = evaluate(s); + if (distinctValue(v)) { + if (max == null) { + max = v; + } + else if (comparator.compare(v, max) > 0) { + max = v; + } + } + } + + @Override + public Value getValue() { + return max; + } + } + + private class SumAggregate extends Aggregate { + + private Literal sum = vf.createLiteral("0", XMLSchema.INTEGER); + + private ValueExprEvaluationException typeError = null; + + public SumAggregate(Sum operator) { + super(operator); + } + + @Override + public void processAggregate(BindingSet s) + throws QueryEvaluationException + { + if (typeError != null) { + // halt further processing if a type error has been raised + return; + } + + Value v = evaluate(s); + if (distinctValue(v)) { + if (v instanceof Literal) { + Literal nextLiteral = (Literal)v; + if (nextLiteral.getDatatype() != null + && XMLDatatypeUtil.isNumericDatatype(nextLiteral.getDatatype())) + { + sum = MathUtil.compute(sum, nextLiteral, MathOp.PLUS); + } + else { + typeError = new ValueExprEvaluationException("not a number: " + v); + } + } + else if (v != null) { + typeError = new ValueExprEvaluationException("not a number: " + v); + } + } + } + + @Override + public Value getValue() + throws ValueExprEvaluationException + { + if (typeError != null) { + throw typeError; + } + + return sum; + } + } + + private class AvgAggregate extends Aggregate { + + private long count = 0; + + private Literal sum = vf.createLiteral("0", XMLSchema.INTEGER); + + private ValueExprEvaluationException typeError = null; + + public AvgAggregate(Avg operator) { + super(operator); + } + + @Override + public void processAggregate(BindingSet s) + throws QueryEvaluationException + { + if (typeError != null) { + // Prevent calculating the aggregate further if a type error has + // occured. + return; + } + + Value v = evaluate(s); + if (distinctValue(v)) { + if (v instanceof Literal) { + Literal nextLiteral = (Literal)v; + // check if the literal is numeric. + if (nextLiteral.getDatatype() != null + && XMLDatatypeUtil.isNumericDatatype(nextLiteral.getDatatype())) + { + sum = MathUtil.compute(sum, nextLiteral, MathOp.PLUS); + } + else { + typeError = new ValueExprEvaluationException("not a number: " + v); + } + count++; + } + else if (v != null) { + // we do not actually throw the exception yet, but record it and + // stop further processing. The exception will be thrown when + // getValue() is invoked. + typeError = new ValueExprEvaluationException("not a number: " + v); + } + } + } + + @Override + public Value getValue() + throws ValueExprEvaluationException + { + if (typeError != null) { + // a type error occurred while processing the aggregate, throw it + // now. + throw typeError; + } + + if (count == 0) { + return vf.createLiteral(0.0d); + } + + Literal sizeLit = vf.createLiteral(count); + return MathUtil.compute(sum, sizeLit, MathOp.DIVIDE); + } + } + + private class SampleAggregate extends Aggregate { + + private Value sample = null; + + private Random random; + + public SampleAggregate(Sample operator) { + super(operator); + random = new Random(System.currentTimeMillis()); + } + + @Override + public void processAggregate(BindingSet s) + throws QueryEvaluationException + { + // we flip a coin to determine if we keep the current value or set a + // new value to report. + if (sample == null || random.nextFloat() < 0.5f) { + sample = evaluate(s); + } + } + + @Override + public Value getValue() { + return sample; + } + } + + private class ConcatAggregate extends Aggregate { + + private StringBuilder concatenated = new StringBuilder(); + + private String separator = " "; + + public ConcatAggregate(GroupConcat groupConcatOp) + throws ValueExprEvaluationException, QueryEvaluationException + { + super(groupConcatOp); + ValueExpr separatorExpr = groupConcatOp.getSeparator(); + if (separatorExpr != null) { + Value separatorValue = strategy.evaluate(separatorExpr, parentBindings); + separator = separatorValue.stringValue(); + } + } + + @Override + public void processAggregate(BindingSet s) + throws QueryEvaluationException + { + Value v = evaluate(s); + if (v != null && distinctValue(v)) { + concatenated.append(v.stringValue()); + concatenated.append(separator); + } + } + + @Override + public Value getValue() { + if (concatenated.length() == 0) { + return vf.createLiteral(""); + } + + // remove separator at the end. + int len = concatenated.length() - separator.length(); + return vf.createLiteral(concatenated.substring(0, len)); + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIteration.java new file mode 100644 index 00000000000..2a7f94159bf --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIteration.java @@ -0,0 +1,350 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.common.iterator.UnionIterator; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; + +/** + * Generic hash join implementation suitable for use by Sail implementations. + * @author MJAHale + */ +public class HashJoinIteration extends LookAheadIteration { + + /*-----------* + * Variables * + *-----------*/ + + private final CloseableIteration leftIter; + + private volatile CloseableIteration rightIter; + + private Iterator scanList; + + private CloseableIteration restIter; + + private Map> hashTable; + + protected final String[] joinAttributes; + + private BindingSet currentScanElem; + + private Iterator hashTableValues; + + private final boolean leftJoin; + + /*--------------* + * Constructors * + *--------------*/ + + public HashJoinIteration(EvaluationStrategy strategy, Join join, BindingSet bindings) + throws QueryEvaluationException + { + this(strategy, join.getLeftArg(), join.getRightArg(), bindings, false); + } + + public HashJoinIteration(EvaluationStrategy strategy, LeftJoin join, BindingSet bindings) + throws QueryEvaluationException + { + this(strategy, join.getLeftArg(), join.getRightArg(), bindings, true); + } + + public HashJoinIteration(EvaluationStrategy strategy, TupleExpr left, TupleExpr right, BindingSet bindings, boolean leftJoin) + throws QueryEvaluationException + { + leftIter = strategy.evaluate(left, bindings); + rightIter = strategy.evaluate(right, bindings); + + Set joinAttributeNames = left.getBindingNames(); + joinAttributeNames.retainAll(right.getBindingNames()); + joinAttributes = joinAttributeNames.toArray(new String[joinAttributeNames.size()]); + + this.leftJoin = leftJoin; + } + + /*---------* + * Methods * + *---------*/ + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + if (hashTable == null) { + setupHashTable(); + } + + while (currentScanElem == null) { + if (scanList.hasNext()) { + currentScanElem = nextFromCache(scanList); + } + else { + disposeCache(scanList); // exhausted so can free + + if (restIter.hasNext()) { + currentScanElem = restIter.next(); + } + else { + // no more elements available + return null; + } + } + + if (currentScanElem instanceof EmptyBindingSet) { + // the empty bindingset should be merged with all bindingset in the + // hash table + hashTableValues = new UnionIterator(hashTable.values()); + if(!hashTableValues.hasNext()) { + currentScanElem = null; + closeHashValue(hashTableValues); + hashTableValues = null; + } + } + else { + BindingSetHashKey key = BindingSetHashKey.create(joinAttributes, currentScanElem); + List hashValue = hashTable.get(key); + if (hashValue != null && !hashValue.isEmpty()) { + hashTableValues = hashValue.iterator(); + } + else if(leftJoin) { + hashTableValues = Collections.singletonList(EmptyBindingSet.getInstance()).iterator(); + } + else { + currentScanElem = null; + closeHashValue(hashTableValues); + hashTableValues = null; + } + } + } + + BindingSet nextHashTableValue = hashTableValues.next(); + + QueryBindingSet result = new QueryBindingSet(currentScanElem); + + for (String name : nextHashTableValue.getBindingNames()) { + if (!result.hasBinding(name)) { + Value v = nextHashTableValue.getValue(name); + if(v != null) + { + result.addBinding(name, v); + } + } + } + + if (!hashTableValues.hasNext()) { + // we've exhausted the current scanlist entry + currentScanElem = null; + closeHashValue(hashTableValues); + hashTableValues = null; + } + + return result; + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + super.handleClose(); + + leftIter.close(); + rightIter.close(); + + if(hashTableValues != null) + { + closeHashValue(hashTableValues); + hashTableValues = null; + } + if(scanList != null) + { + disposeCache(scanList); + scanList = null; + } + if(hashTable != null) + { + disposeHashTable(hashTable); + hashTable = null; + } + } + + private void setupHashTable() + throws QueryEvaluationException + { + + Collection leftArgResults; + Collection rightArgResults = makeIterationCache(rightIter); + if(!leftJoin) + { + leftArgResults = makeIterationCache(leftIter); + + while (leftIter.hasNext() && rightIter.hasNext()) { + add(leftArgResults, leftIter.next()); + add(rightArgResults, rightIter.next()); + } + } + else + { + leftArgResults = Collections.emptyList(); + + while (rightIter.hasNext()) { + add(rightArgResults, rightIter.next()); + } + } + + Collection smallestResult = null; + + if (leftJoin || leftIter.hasNext()) { // leftArg is the greater relation + smallestResult = rightArgResults; + scanList = leftArgResults.iterator(); + restIter = leftIter; + } + else { // rightArg is the greater relation (or they are equal) + smallestResult = leftArgResults; + scanList = rightArgResults.iterator(); + restIter = rightIter; + } + + // help free memory before allocating the hash table + leftArgResults = null; + rightArgResults = null; + + // create the hash table for our join + // hash table will never be any bigger than smallestResult.size() + hashTable = makeHashTable(smallestResult.size()); + int maxListSize = 1; + for (BindingSet b : smallestResult) { + BindingSetHashKey hashKey = BindingSetHashKey.create(joinAttributes, b); + + List hashValue = hashTable.get(hashKey); + boolean newEntry = (hashValue == null); + if (newEntry) { + hashValue = makeHashValue(maxListSize); + } + add(hashValue, b); + // always do a put() in case the map implementation is not memory-based + // e.g. it serializes the values + putHashTableEntry(hashTable, hashKey, hashValue, newEntry); + + maxListSize = Math.max(maxListSize, hashValue.size()); + } + + } + + protected void putHashTableEntry(Map> hashTable, BindingSetHashKey hashKey, + List hashValue, boolean newEntry) + throws QueryEvaluationException + { + // by default, we use a standard memory hash map + // so we only need to do the put() if the list is new + if(newEntry) + { + hashTable.put(hashKey, hashValue); + } + } + + /** + * Utility methods to make it easier to inserted custom store dependent list + * + * @return list + */ + protected Collection makeIterationCache(CloseableIteration iter) { + return new ArrayList(); + } + + /** + * Utility methods to make it easier to inserted custom store dependent maps + * + * @return map + */ + protected Map> makeHashTable(int initialSize) { + Map> hashTable; + if(joinAttributes.length > 0) + { + // we should probably adjust for the load factor + // but we are only one rehash away and this might save a bit of memory + // when we have more than one value per entry + hashTable = new HashMap>(initialSize); + } + else + { + List l = (initialSize > 0) ? new ArrayList(initialSize) : null; + hashTable = Collections.>singletonMap(BindingSetHashKey.EMPTY, l); + } + return hashTable; + } + + /** + * Utility methods to make it easier to inserted custom store dependent list + * + * @return list + */ + protected List makeHashValue(int currentMaxListSize) { + // we pick an initial size that means we may only have to resize once + // while saving memory in the case that the list doesn't reach max size + return new ArrayList(currentMaxListSize/2+1); + } + + /** + * Utility methods to clear-up in case not using in-memory cache. + */ + protected void disposeCache(Iterator iter) + { + } + + /** + * Utility methods to clear-up in case not using in-memory hash table. + */ + protected void disposeHashTable(Map> map) + { + } + + /** + * Utility methods to clear-up in case not using in-memory hash table. + */ + protected void closeHashValue(Iterator iter) + { + } + + // hooks for LimitedSizeHashJoinIterator + + protected E nextFromCache(Iterator iter) + { + return iter.next(); + } + + protected void add(Collection col, E value) + throws QueryEvaluationException + { + col.add(value); + } + + protected void addAll(Collection col, List values) + throws QueryEvaluationException + { + col.addAll(values); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIterator.java new file mode 100644 index 00000000000..8a9df801092 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIterator.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.NoSuchElementException; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.EmptyIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; + +public class JoinIterator extends LookAheadIteration { + + /*-----------* + * Variables * + *-----------*/ + + private final EvaluationStrategy strategy; + + private final Join join; + + private final CloseableIteration leftIter; + + private volatile CloseableIteration rightIter; + + /*--------------* + * Constructors * + *--------------*/ + + public JoinIterator(EvaluationStrategy strategy, Join join, BindingSet bindings) + throws QueryEvaluationException + { + this.strategy = strategy; + this.join = join; + + leftIter = strategy.evaluate(join.getLeftArg(), bindings); + + // Initialize with empty iteration so that var is never null + rightIter = new EmptyIteration(); + } + + /*---------* + * Methods * + *---------*/ + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + try { + while (rightIter.hasNext() || leftIter.hasNext()) { + if (rightIter.hasNext()) { + return rightIter.next(); + } + + // Right iteration exhausted + rightIter.close(); + + if (leftIter.hasNext()) { + rightIter = strategy.evaluate(join.getRightArg(), leftIter.next()); + } + } + } + catch (NoSuchElementException ignore) { + // probably, one of the iterations has been closed concurrently in + // handleClose() + } + + return null; + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + super.handleClose(); + + leftIter.close(); + rightIter.close(); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java new file mode 100644 index 00000000000..9206f7fa2a1 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.NoSuchElementException; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.EmptyIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; + +public class LeftJoinIterator extends LookAheadIteration { + + /*-----------* + * Variables * + *-----------*/ + + private EvaluationStrategy strategy; + + private final LeftJoin join; + + /** + * The set of binding names that are "in scope" for the filter. The filter + * must not include bindings that are (only) included because of the + * depth-first evaluation strategy in the evaluation of the constraint. + */ + private final Set scopeBindingNames; + + private final CloseableIteration leftIter; + + private volatile CloseableIteration rightIter; + + /*--------------* + * Constructors * + *--------------*/ + + public LeftJoinIterator(EvaluationStrategy strategy, LeftJoin join, BindingSet bindings) + throws QueryEvaluationException + { + this.strategy = strategy; + this.join = join; + this.scopeBindingNames = join.getBindingNames(); + + leftIter = strategy.evaluate(join.getLeftArg(), bindings); + + // Initialize with empty iteration so that var is never null + rightIter = new EmptyIteration(); + } + + /*---------* + * Methods * + *---------*/ + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + try { + while (rightIter.hasNext() || leftIter.hasNext()) { + BindingSet leftBindings = null; + + if (!rightIter.hasNext()) { + // Use left arg's bindings in case join fails + leftBindings = leftIter.next(); + + rightIter.close(); + rightIter = strategy.evaluate(join.getRightArg(), leftBindings); + } + + while (rightIter.hasNext()) { + BindingSet rightBindings = rightIter.next(); + + try { + if (join.getCondition() == null) { + return rightBindings; + } + else { + // Limit the bindings to the ones that are in scope for + // this filter + QueryBindingSet scopeBindings = new QueryBindingSet(rightBindings); + scopeBindings.retainAll(scopeBindingNames); + + if (strategy.isTrue(join.getCondition(), scopeBindings)) { + return rightBindings; + } + } + } + catch (ValueExprEvaluationException e) { + // Ignore, condition not evaluated successfully + } + } + + if (leftBindings != null) { + // Join failed, return left arg's bindings + return leftBindings; + } + } + } + catch (NoSuchElementException ignore) { + // probably, one of the iterations has been closed concurrently in + // handleClose() + } + + return null; + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + super.handleClose(); + + leftIter.close(); + rightIter.close(); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/MultiProjectionIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/MultiProjectionIterator.java new file mode 100644 index 00000000000..c63274f2c8d --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/MultiProjectionIterator.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.MultiProjection; +import org.eclipse.rdf4j.query.algebra.ProjectionElemList; + +/** + * @author Arjohn Kampman + * @author James Leigh + */ +public class MultiProjectionIterator extends LookAheadIteration { + + /*------------* + * Attributes * + *------------*/ + + private final List projections; + + private final CloseableIteration iter; + + private final BindingSet parentBindings; + + private final BindingSet[] previousBindings; + + private BindingSet currentBindings; + + private volatile int nextProjectionIdx; + + /*--------------* + * Constructors * + *--------------*/ + + public MultiProjectionIterator(MultiProjection multiProjection, + CloseableIteration iter, BindingSet bindings) + { + this.projections = multiProjection.getProjections(); + this.iter = iter; + this.parentBindings = bindings; + this.previousBindings = new BindingSet[projections.size()]; + + // initialize out-of-range to enforce a fetch of the first result upon + // first use + nextProjectionIdx = projections.size(); + } + + /*---------* + * Methods * + *---------*/ + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + while (true) { + int projIdx = nextProjectionIdx; + + if (projIdx < projections.size()) { + // Apply next projection in the list + ProjectionElemList projection = projections.get(projIdx); + BindingSet result = ProjectionIterator.project(projection, currentBindings, parentBindings); + + nextProjectionIdx++; + + // ignore duplicates + if (!result.equals(previousBindings[projIdx])) { + previousBindings[projIdx] = result; + return result; + } + } + else if (iter.hasNext()) { + // Continue with the next result + currentBindings = iter.next(); + nextProjectionIdx = 0; + } + else { + // no more results + return null; + } + } + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + super.handleClose(); + iter.close(); + nextProjectionIdx = projections.size(); + Arrays.fill(previousBindings, null); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java new file mode 100644 index 00000000000..4cb7aaeb2b6 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java @@ -0,0 +1,237 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.io.File; +import java.io.IOError; +import java.io.IOException; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; +import java.util.TreeMap; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.DelayedIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.mapdb.DB; +import org.mapdb.DBMaker; + +/** + * Sorts the input and optionally applies limit and distinct. + * + * @author James Leigh + * @author Arjohn Kampman + */ +public class OrderIterator extends DelayedIteration { + + /*-----------* + * Variables * + *-----------*/ + + private final CloseableIteration iter; + + private final Comparator comparator; + + private final long limit; + + private final boolean distinct; + + private final File tempFile; + + private final DB db; + + /** + * Number of items cached before internal collection is synced to disk. If + * set to 0, no disk-syncing is done and all internal caching is kept in + * memory. + */ + private final long iterationSyncThreshold; + + /*--------------* + * Constructors * + *--------------*/ + + public OrderIterator(CloseableIteration iter, + Comparator comparator) + { + this(iter, comparator, Integer.MAX_VALUE, false); + } + + public OrderIterator(CloseableIteration iter, + Comparator comparator, long limit, boolean distinct) + { + this(iter, comparator, limit, distinct, 0); + } + + public OrderIterator(CloseableIteration iter, + Comparator comparator, long limit, boolean distinct, long iterationSyncThreshold) + { + this.iter = iter; + this.comparator = comparator; + this.limit = limit; + this.distinct = distinct; + this.iterationSyncThreshold = iterationSyncThreshold; + + if (iterationSyncThreshold > 0) { + try { + this.tempFile = File.createTempFile("order-eval", null); + } + catch (IOException e) { + throw new IOError(e); + } + this.db = DBMaker.newFileDB(tempFile).deleteFilesAfterClose().closeOnJvmShutdown().make(); + } + else { + this.tempFile = null; + this.db = null; + } + } + + /*---------* + * Methods * + *---------*/ + + protected NavigableMap makeOrderedMap() { + if (db == null) { + // no disk-syncing - we use a simple in-memory TreeMap instead. + return new TreeMap(comparator); + } + else { + return db.createTreeMap("iteration").comparator(comparator).makeOrGet(); + } + } + + protected Iteration createIteration() + throws QueryEvaluationException + { + final NavigableMap map = makeOrderedMap(); + long size = 0; + + try { + while (iter.hasNext()) { + BindingSet next = iter.next(); + + // Add this binding set if the limit hasn't been reached yet, or if + // it is sorted before the current lowest value + if (size < limit || comparator.compare(next, map.lastKey()) < 0) { + + Integer count = map.get(next); + + if (count == null) { + put(map, next, 1); + size++; + } + else if (!distinct) { + put(map, next, ++count); + size++; + } + + if (db != null && size % iterationSyncThreshold == 0L) { + // sync collection to disk every X new entries (where X is a + // multiple of the cache size) + db.commit(); + } + + if (size > limit) { + // Discard binding set that is currently sorted last + BindingSet lastKey = map.lastKey(); + + Integer lastCount = map.get(lastKey); + if (lastCount > 1) { + put(map, lastKey, --lastCount); + } + else { + removeLast(map.navigableKeySet()); + } + size--; + } + } + } + } + finally { + iter.close(); + } + + return new LookAheadIteration() { + + private volatile Iterator iterator = map.keySet().iterator(); + + private volatile BindingSet currentBindingSet = null; + + private volatile int count = 0; + + protected BindingSet getNextElement() { + + if (count == 0 && iterator.hasNext()) { + currentBindingSet = iterator.next(); + count = map.get(currentBindingSet); + } + + if (count > 0) { + count--; + return currentBindingSet; + } + + return null; + } + }; + } + + protected void removeLast(Collection lastResults) { + if (lastResults instanceof LinkedList) { + ((LinkedList)lastResults).removeLast(); + } + else if (lastResults instanceof List) { + ((List)lastResults).remove(lastResults.size() - 1); + } + else { + Iterator iter = lastResults.iterator(); + while (iter.hasNext()) { + iter.next(); + } + iter.remove(); + } + } + + protected boolean add(BindingSet next, Collection list) + throws QueryEvaluationException + { + return list.add(next); + } + + protected Integer put(NavigableMap map, BindingSet set, int count) + throws QueryEvaluationException + { + return map.put(set, count); + } + + @Override + public void remove() + throws QueryEvaluationException + { + throw new UnsupportedOperationException(); + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + iter.close(); + if (db != null) { + this.db.close(); + } + super.handleClose(); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/PathIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/PathIteration.java new file mode 100644 index 00000000000..d4c55364fbd --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/PathIteration.java @@ -0,0 +1,447 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.ArrayDeque; +import java.util.HashSet; +import java.util.Queue; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.EmptyIteration; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.ZeroLengthPath; +import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +public class PathIteration extends LookAheadIteration { + + /** + * + */ + private final SimpleEvaluationStrategy evaluationStrategyImpl; + + private long currentLength; + + private CloseableIteration currentIter; + + private BindingSet bindings; + + private Scope scope; + + private Var startVar; + + private Var endVar; + + private final boolean startVarFixed; + + private final boolean endVarFixed; + + private Queue valueQueue; + + private final Set reportedValues; + + private final Set unreportedValues;; + + private TupleExpr pathExpression; + + private Var contextVar; + + private ValuePair currentVp; + + private static final String JOINVAR_PREFIX = "intermediate-join-"; + + public PathIteration(SimpleEvaluationStrategy evaluationStrategyImpl, Scope scope, Var startVar, + TupleExpr pathExpression, Var endVar, Var contextVar, long minLength, BindingSet bindings) + throws QueryEvaluationException + { + this.evaluationStrategyImpl = evaluationStrategyImpl; + this.scope = scope; + this.startVar = startVar; + this.endVar = endVar; + + this.startVarFixed = startVar.hasValue() || bindings.hasBinding(startVar.getName()); + this.endVarFixed = endVar.hasValue() || bindings.hasBinding(endVar.getName()); + + this.pathExpression = pathExpression; + this.contextVar = contextVar; + + this.currentLength = minLength; + this.bindings = bindings; + + this.reportedValues = makeSet(); + this.unreportedValues = makeSet(); + this.valueQueue = makeQueue(); + + createIteration(); + } + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + again: while (true) { + while (!currentIter.hasNext()) { + Iterations.closeCloseable(currentIter); + createIteration(); + // stop condition: if the iter is an EmptyIteration + if (currentIter instanceof EmptyIteration) { + break; + } + } + + while (currentIter.hasNext()) { + BindingSet nextElement = currentIter.next(); + + if (!startVarFixed && !endVarFixed && currentVp != null) { + Value startValue = currentVp.getStartValue(); + + if (startValue != null) { + nextElement = new QueryBindingSet(nextElement); + ((QueryBindingSet)nextElement).addBinding(startVar.getName(), startValue); + } + } + + Value v1, v2; + + if (startVarFixed && endVarFixed && currentLength > 2) { + v1 = getVarValue(startVar, startVarFixed, nextElement); + v2 = nextElement.getValue("END_" + JOINVAR_PREFIX + pathExpression.hashCode()); + } + else if (startVarFixed && endVarFixed && currentLength == 2) { + v1 = getVarValue(startVar, startVarFixed, nextElement); + v2 = nextElement.getValue(JOINVAR_PREFIX + (currentLength - 1) + "-" + + pathExpression.hashCode()); + } + else { + v1 = getVarValue(startVar, startVarFixed, nextElement); + v2 = getVarValue(endVar, endVarFixed, nextElement); + } + + if (!isCyclicPath(v1, v2)) { + + ValuePair vp = new ValuePair(v1, v2); + if (reportedValues.contains(vp)) { + // new arbitrary-length path semantics: filter out + // duplicates + if (currentIter.hasNext()) { + continue; + } + else { + // if the current iter is exhausted, we need to check + // that no further paths of greater length still exists. + continue again; + } + } + + if (startVarFixed && endVarFixed) { + Value endValue = getVarValue(endVar, endVarFixed, nextElement); + if (endValue.equals(v2)) { + add(reportedValues, vp); + if (!v1.equals(v2)) { + addToQueue(valueQueue, vp); + } + if (!nextElement.hasBinding(startVar.getName())) { + ((QueryBindingSet)nextElement).addBinding(startVar.getName(), v1); + } + if (!nextElement.hasBinding(endVar.getName())) { + ((QueryBindingSet)nextElement).addBinding(endVar.getName(), v2); + } + return nextElement; + } + else { + if (add(unreportedValues, vp)) { + if (!v1.equals(v2)) { + addToQueue(valueQueue, vp); + } + } + continue again; + } + } + else { + add(reportedValues, vp); + if (!v1.equals(v2)) { + addToQueue(valueQueue, vp); + } + if (!nextElement.hasBinding(startVar.getName())) { + ((QueryBindingSet)nextElement).addBinding(startVar.getName(), v1); + } + if (!nextElement.hasBinding(endVar.getName())) { + ((QueryBindingSet)nextElement).addBinding(endVar.getName(), v2); + } + return nextElement; + } + } + else { + continue again; + } + } + + // if we're done, throw away the cached lists of values to avoid + // hogging resources + reportedValues.clear(); + unreportedValues.clear(); + valueQueue.clear(); + return null; + } + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + Iterations.closeCloseable(currentIter); + super.handleClose(); + } + + /** + * @param valueQueue2 + * @param vp + */ + protected boolean addToQueue(Queue valueQueue2, ValuePair vp) + throws QueryEvaluationException + { + return valueQueue2.add(vp); + } + + /** + * @param valueSet + * @param vp + */ + protected boolean add(Set valueSet, ValuePair vp) + throws QueryEvaluationException + { + return valueSet.add(vp); + } + + private Value getVarValue(Var var, boolean fixedValue, BindingSet bindingSet) { + Value v; + if (fixedValue) { + v = var.getValue(); + if (v == null) { + v = this.bindings.getValue(var.getName()); + } + } + else { + v = bindingSet.getValue(var.getName()); + } + + return v; + } + + private boolean isCyclicPath(Value v1, Value v2) { + if (currentLength <= 2) { + return false; + } + + return reportedValues.contains(new ValuePair(v1, v2)); + + } + + private void createIteration() + throws QueryEvaluationException + { + + if (currentLength == 0L) { + ZeroLengthPath zlp = new ZeroLengthPath(scope, startVar, endVar, contextVar); + currentIter = this.evaluationStrategyImpl.evaluate(zlp, bindings); + currentLength++; + } + else if (currentLength == 1) { + TupleExpr pathExprClone = pathExpression.clone(); + + if (startVarFixed && endVarFixed) { + Var replacement = createAnonVar(JOINVAR_PREFIX + currentLength + "-" + pathExpression.hashCode()); + + VarReplacer replacer = new VarReplacer(endVar, replacement, 0, false); + pathExprClone.visit(replacer); + } + currentIter = this.evaluationStrategyImpl.evaluate(pathExprClone, bindings); + currentLength++; + } + else { + + currentVp = valueQueue.poll(); + + if (currentVp != null) { + + TupleExpr pathExprClone = pathExpression.clone(); + + if (startVarFixed && endVarFixed) { + + Var startReplacement = createAnonVar(JOINVAR_PREFIX + currentLength + "-" + + pathExpression.hashCode()); + Var endReplacement = createAnonVar("END_" + JOINVAR_PREFIX + pathExpression.hashCode()); + startReplacement.setAnonymous(false); + endReplacement.setAnonymous(false); + + Value v = currentVp.getEndValue(); + startReplacement.setValue(v); + + VarReplacer replacer = new VarReplacer(startVar, startReplacement, 0, false); + pathExprClone.visit(replacer); + + replacer = new VarReplacer(endVar, endReplacement, 0, false); + pathExprClone.visit(replacer); + } + else { + Var toBeReplaced; + Value v; + if (!endVarFixed) { + toBeReplaced = startVar; + v = currentVp.getEndValue(); + } + else { + toBeReplaced = endVar; + v = currentVp.getStartValue(); + } + + Var replacement = createAnonVar(JOINVAR_PREFIX + currentLength + "-" + + pathExpression.hashCode()); + replacement.setValue(v); + + VarReplacer replacer = new VarReplacer(toBeReplaced, replacement, 0, false); + pathExprClone.visit(replacer); + } + + currentIter = this.evaluationStrategyImpl.evaluate(pathExprClone, bindings); + } + else { + currentIter = new EmptyIteration(); + } + currentLength++; + + } + } + + protected Set makeSet() { + return new HashSet(64, 0.9f); + } + + protected Queue makeQueue() { + return new ArrayDeque(); + } + + protected static class ValuePair { + + private final Value startValue; + + private final Value endValue; + + public ValuePair(Value startValue, Value endValue) { + this.startValue = startValue; + this.endValue = endValue; + } + + /** + * @return Returns the startValue. + */ + public Value getStartValue() { + return startValue; + } + + /** + * @return Returns the endValue. + */ + public Value getEndValue() { + return endValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((endValue == null) ? 0 : endValue.hashCode()); + result = prime * result + ((startValue == null) ? 0 : startValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof ValuePair)) { + return false; + } + ValuePair other = (ValuePair)obj; + if (endValue == null) { + if (other.endValue != null) { + return false; + } + } + else if (!endValue.equals(other.endValue)) { + return false; + } + if (startValue == null) { + if (other.startValue != null) { + return false; + } + } + else if (!startValue.equals(other.startValue)) { + return false; + } + return true; + } + } + + class VarReplacer extends AbstractQueryModelVisitor { + + private Var toBeReplaced; + + private Var replacement; + + private long index; + + private boolean replaceAnons; + + public VarReplacer(Var toBeReplaced, Var replacement, long index, boolean replaceAnons) { + this.toBeReplaced = toBeReplaced; + this.replacement = replacement; + this.index = index; + this.replaceAnons = replaceAnons; + } + + @Override + public void meet(Var var) { + if (toBeReplaced.equals(var) + || (toBeReplaced.isAnonymous() && var.isAnonymous() && (toBeReplaced.hasValue() && toBeReplaced.getValue().equals( + var.getValue())))) + { + QueryModelNode parent = var.getParentNode(); + parent.replaceChildNode(var, replacement); + replacement.setParentNode(parent); + } + else if (replaceAnons && var.isAnonymous() && !var.hasValue()) { + Var replacementVar = createAnonVar("anon-replace-" + var.getName() + index); + QueryModelNode parent = var.getParentNode(); + parent.replaceChildNode(var, replacementVar); + replacementVar.setParentNode(parent); + } + } + + } + + public Var createAnonVar(String varName) { + Var var = new Var(varName); + var.setAnonymous(true); + return var; + } +} \ No newline at end of file diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ProjectionIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ProjectionIterator.java new file mode 100644 index 00000000000..863f21a412b --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ProjectionIterator.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.ConvertingIteration; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Projection; +import org.eclipse.rdf4j.query.algebra.ProjectionElem; +import org.eclipse.rdf4j.query.algebra.ProjectionElemList; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; + +public class ProjectionIterator extends ConvertingIteration +{ + + /*-----------* + * Constants * + *-----------*/ + + private final Projection projection; + + private final BindingSet parentBindings; + + /*--------------* + * Constructors * + *--------------*/ + + public ProjectionIterator(Projection projection, + CloseableIteration iter, BindingSet parentBindings) + throws QueryEvaluationException + { + super(iter); + this.projection = projection; + this.parentBindings = parentBindings; + } + + /*---------* + * Methods * + *---------*/ + + @Override + protected BindingSet convert(BindingSet sourceBindings) + throws QueryEvaluationException + { + + return project(projection.getProjectionElemList(), sourceBindings, parentBindings); + } + + public static BindingSet project(ProjectionElemList projElemList, BindingSet sourceBindings, + BindingSet parentBindings) + { + QueryBindingSet resultBindings = new QueryBindingSet(); + + for (ProjectionElem pe : projElemList.getElements()) { + Value targetValue = sourceBindings.getValue(pe.getSourceName()); + if (targetValue == null) { + targetValue = parentBindings.getValue(pe.getSourceName()); + } + if (targetValue != null) { + resultBindings.setBinding(pe.getTargetName(), targetValue); + } + } + + return resultBindings; + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SPARQLMinusIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SPARQLMinusIteration.java new file mode 100644 index 00000000000..cc951dab40c --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SPARQLMinusIteration.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.FilterIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryResults; + +/** + * An Iteration that returns the results of an Iteration (the left argument) + * MINUS any results that are compatible with results of another Iteration (the + * right argument) or that have no shared variables. This iteration uses the + * formal definition of the SPARQL 1.1 MINUS operator to determine which + * BindingSets to return. + * + * @see SPARQL + * Algebra Documentation + * @author Jeen + */ +public class SPARQLMinusIteration extends FilterIteration { + + /*-----------* + * Variables * + *-----------*/ + + private final Iteration rightArg; + + private final boolean distinct; + + private boolean initialized; + + private Set excludeSet; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new MinusIteration that returns the results of the left argument + * minus the results of the right argument. By default, duplicates are + * not filtered from the results. + * + * @param leftArg + * An Iteration containing the main set of elements. + * @param rightArg + * An Iteration containing the set of elements that should be filtered + * from the main set. + */ + public SPARQLMinusIteration(Iteration leftArg, Iteration rightArg) { + this(leftArg, rightArg, false); + } + + /** + * Creates a new MinusIteration that returns the results of the left argument + * minus the results of the right argument. + * + * @param leftArg + * An Iteration containing the main set of elements. + * @param rightArg + * An Iteration containing the set of elements that should be filtered + * from the main set. + * @param distinct + * Flag indicating whether duplicate elements should be filtered from + * the result. + */ + public SPARQLMinusIteration(Iteration leftArg, Iteration rightArg, + boolean distinct) + { + super(leftArg); + + assert rightArg != null; + + this.rightArg = rightArg; + this.distinct = distinct; + this.initialized = false; + } + + /*--------------* + * Constructors * + *--------------*/ + + // implements LookAheadIteration.getNextElement() + protected boolean accept(BindingSet object) + throws X + { + if (!initialized) { + // Build set of elements-to-exclude from right argument + excludeSet = makeSet(getRightArg()); + initialized = true; + } + + boolean compatible = false; + + for (BindingSet excluded : excludeSet) { + + // build set of shared variable names + Set sharedBindingNames = makeSet(excluded.getBindingNames()); + sharedBindingNames.retainAll(object.getBindingNames()); + + // two bindingsets that share no variables are compatible by + // definition, however, the formal + // definition of SPARQL MINUS indicates that such disjoint sets should + // be filtered out. + // See http://www.w3.org/TR/sparql11-query/#sparqlAlgebra + if (!sharedBindingNames.isEmpty()) { + if (QueryResults.bindingSetsCompatible(excluded, object)) { + // at least one compatible bindingset has been found in the + // exclude set, therefore the object is compatible, therefore it + // should not be accepted. + compatible = true; + break; + } + } + } + + return !compatible; + } + + protected Set makeSet() + throws X + { + return new LinkedHashSet(); + } + + protected Set makeSet(Set set) + throws X + { + return new HashSet(set); + } + + protected Set makeSet(Iteration rightArg2) + throws X + { + return Iterations.addAll(rightArg, makeSet()); + } + + @Override + protected void handleClose() + throws X + { + super.handleClose(); + Iterations.closeCloseable(getRightArg()); + } + + /** + * @return Returns the rightArg. + */ + protected Iteration getRightArg() { + return rightArg; + } + + protected long clearExcludeSet() { + int size = excludeSet.size(); + excludeSet.clear(); + return size; + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SilentIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SilentIteration.java new file mode 100644 index 00000000000..39b3d8393f8 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SilentIteration.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * Wrap an inner iteration and suppress exceptions silently + * + * @author Andreas Schwarte + */ +public class SilentIteration extends LookAheadIteration { + + protected CloseableIteration iter; + + public SilentIteration(CloseableIteration iter) { + super(); + this.iter = iter; + } + + + @Override + protected BindingSet getNextElement() throws QueryEvaluationException { + + try { + if (iter.hasNext()) + return iter.next(); + } catch (Exception e) { + // suppress + } + + return null; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIteration.java new file mode 100644 index 00000000000..31e11e4d6a0 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIteration.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.impl.ValueFactoryImpl; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; + +public class ZeroLengthPathIteration extends LookAheadIteration { + /** + * We potentially have to fit all resources in this set + * so let's start of with a reasonably big size. + */ + private static final int INITIAL_CAPACITY = 10000; + private static final String ANON_SUBJECT_VAR = "zero-length-internal-start"; + private static final String ANON_PREDICATE_VAR = "zero-length-internal-pred"; + private static final String ANON_OBJECT_VAR = "zero-length-internal-end"; + private static final String ANON_SEQUENCE_VAR = "zero-length-internal-seq"; + + private QueryBindingSet result; + + private Var subjectVar; + + private Var objVar; + + private Value subj; + + private Value obj; + + private BindingSet bindings; + + private CloseableIteration iter; + + private Set reportedValues; + + private Var contextVar; + + private final EvaluationStrategy evaluationStrategy; + + public ZeroLengthPathIteration(SimpleEvaluationStrategy evaluationStrategyImpl, Var subjectVar, Var objVar, + Value subj, Value obj, Var contextVar, BindingSet bindings) + { + this.evaluationStrategy = evaluationStrategyImpl; + result = new QueryBindingSet(bindings); + this.subjectVar = subjectVar; + this.objVar = objVar; + this.contextVar = contextVar; + this.subj = subj; + this.obj = obj; + this.bindings = bindings; + } + + @Override + protected BindingSet getNextElement() + throws QueryEvaluationException + { + if (subj == null && obj == null) { + if (this.reportedValues == null) { + reportedValues = makeSet(); + } + if (this.iter == null) { + // join with a sequence so we iterate over every entry twice + QueryBindingSet bs1 = new QueryBindingSet(1); + bs1.addBinding(ANON_SEQUENCE_VAR, ValueFactoryImpl.getInstance().createLiteral("subject")); + QueryBindingSet bs2 = new QueryBindingSet(1); + bs2.addBinding(ANON_SEQUENCE_VAR, ValueFactoryImpl.getInstance().createLiteral("object")); + List seqList = Arrays.asList(bs1, bs2); + iter = new CrossProductIteration(createIteration(), seqList); + } + + while (iter.hasNext()) { + BindingSet bs = iter.next(); + + boolean isSubjOrObj = bs.getValue(ANON_SEQUENCE_VAR).stringValue().equals("subject"); + String endpointVarName = isSubjOrObj ? ANON_SUBJECT_VAR : ANON_OBJECT_VAR; + Value v = bs.getValue(endpointVarName); + + if (add(reportedValues, v)) { + QueryBindingSet next = new QueryBindingSet(); + next.addBinding(subjectVar.getName(), v); + next.addBinding(objVar.getName(), v); + if (contextVar != null) { + Value context = bs.getValue(contextVar.getName()); + if (context != null) { + next.addBinding(contextVar.getName(), context); + } + } + return next; + } + } + iter.close(); + + // if we're done, throw away the cached list of values to avoid hogging + // resources + reportedValues = null; + return null; + } + else { + if (result != null) { + if (obj == null && subj != null) { + result.addBinding(objVar.getName(), subj); + } + else if (subj == null && obj != null) { + result.addBinding(subjectVar.getName(), obj); + } + else if (subj != null && subj.equals(obj)) { + // empty bindings + // (result but nothing to bind as subjectVar and objVar are both fixed) + } + else { + result = null; + } + } + + QueryBindingSet next = result; + result = null; + return next; + } + } + + /** + * add param v to the set reportedValues2 + * + * @param reportedValues2 + * @param v + * @return true if v added to set and not yet present + */ + protected boolean add(Set reportedValues2, Value v) + throws QueryEvaluationException + { + return reportedValues2.add(v); + } + + private CloseableIteration createIteration() + throws QueryEvaluationException + { + Var startVar = createAnonVar(ANON_SUBJECT_VAR); + Var predicate = createAnonVar(ANON_PREDICATE_VAR); + Var endVar = createAnonVar(ANON_OBJECT_VAR); + + StatementPattern subjects = new StatementPattern(startVar, predicate, endVar); + + if (contextVar != null) { + subjects.setScope(Scope.NAMED_CONTEXTS); + subjects.setContextVar(contextVar); + } + CloseableIteration iter = evaluationStrategy.evaluate( + subjects, bindings); + + return iter; + } + + private Set makeSet() { + return new HashSet(INITIAL_CAPACITY); + } + + public Var createAnonVar(String varName) { + Var var = new Var(varName); + var.setAnonymous(true); + return var; + } +} \ No newline at end of file diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/LimitedSizeEvaluationStrategy.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/LimitedSizeEvaluationStrategy.java new file mode 100644 index 00000000000..4fa69e41752 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/LimitedSizeEvaluationStrategy.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited; + +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.DelayedIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.ArbitraryLengthPath; +import org.eclipse.rdf4j.query.algebra.Difference; +import org.eclipse.rdf4j.query.algebra.Distinct; +import org.eclipse.rdf4j.query.algebra.Intersection; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.Order; +import org.eclipse.rdf4j.query.algebra.Service; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope; +import org.eclipse.rdf4j.query.algebra.evaluation.TripleSource; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.ServiceJoinIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.JoinIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.ZeroLengthPathIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator.LimitedSizeDistinctIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator.LimitedSizeHashJoinIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator.LimitedSizeIntersectIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator.LimitedSizeOrderIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator.LimitedSizePathIterator; +import org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator.LimitedSizeSPARQLMinusIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator.LimitedSizeZeroLengthPathIteration; +import org.eclipse.rdf4j.query.algebra.evaluation.util.OrderComparator; +import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator; +import org.eclipse.rdf4j.query.algebra.helpers.TupleExprs; + +/** + * @author Jerven Bolleman, SIB Swiss Institute of Bioinformatics + */ +public class LimitedSizeEvaluationStrategy extends SimpleEvaluationStrategy { + + private final AtomicLong used = new AtomicLong(); + + private long maxSize; + + /** + * @param tripleSource + */ + public LimitedSizeEvaluationStrategy(TripleSource tripleSource, long maxSize, + FederatedServiceResolver serviceManager) + { + super(tripleSource, serviceManager); + this.maxSize = maxSize; + } + + /** + * @param tripleSource + * @param dataset + * @param maxCollectionsSize + */ + public LimitedSizeEvaluationStrategy(TripleSource tripleSource, Dataset dataset, + int maxCollectionsSize, FederatedServiceResolver serviceManager) + { + super(tripleSource, dataset, serviceManager); + this.maxSize = maxCollectionsSize; + } + + @Override + public CloseableIteration evaluate(Distinct distinct, + BindingSet bindings) + throws QueryEvaluationException + { + return new LimitedSizeDistinctIteration(evaluate(distinct.getArg(), bindings), used, maxSize); + } + + public CloseableIteration evaluate(final Difference difference, + final BindingSet bindings) + throws QueryEvaluationException + { + Iteration leftArg, rightArg; + + leftArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(difference.getLeftArg(), bindings); + } + }; + + rightArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(difference.getRightArg(), bindings); + } + }; + + return new LimitedSizeSPARQLMinusIteration(leftArg, rightArg, used, maxSize); + } + + @Override + public CloseableIteration evaluate(final Intersection intersection, + final BindingSet bindings) + throws QueryEvaluationException + { + Iteration leftArg, rightArg; + + leftArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(intersection.getLeftArg(), bindings); + } + }; + + rightArg = new DelayedIteration() { + + @Override + protected Iteration createIteration() + throws QueryEvaluationException + { + return evaluate(intersection.getRightArg(), bindings); + } + }; + + return new LimitedSizeIntersectIteration(leftArg, rightArg, used, maxSize); + } + + public CloseableIteration evaluate(Join join, BindingSet bindings) + throws QueryEvaluationException + { + // efficient computation of a SERVICE join using vectored evaluation + // TODO maybe we can create a ServiceJoin node already in the parser? + if (join.getRightArg() instanceof Service) { + CloseableIteration leftIter = evaluate(join.getLeftArg(), + bindings); + return new ServiceJoinIterator(leftIter, (Service)join.getRightArg(), bindings, this); + } + + if (TupleExprs.containsProjection(join.getRightArg())) { + return new LimitedSizeHashJoinIteration(this, join, bindings, used, maxSize); + } + else { + return new JoinIterator(this, join, bindings); + } + } + + @Override + public CloseableIteration evaluate(ArbitraryLengthPath alp, + final BindingSet bindings) + throws QueryEvaluationException + { + final Scope scope = alp.getScope(); + final Var subjectVar = alp.getSubjectVar(); + final TupleExpr pathExpression = alp.getPathExpression(); + final Var objVar = alp.getObjectVar(); + final Var contextVar = alp.getContextVar(); + final long minLength = alp.getMinLength(); + + return new LimitedSizePathIterator(this, scope, subjectVar, pathExpression, objVar, contextVar, minLength, bindings, used, maxSize); + } + @Override + protected ZeroLengthPathIteration getZeroLengthPathIterator(BindingSet bindings, Var subjectVar, + Var objVar, Var contextVar, Value subj, Value obj) + { + return new LimitedSizeZeroLengthPathIteration(this, subjectVar, objVar, subj, obj, contextVar, + bindings, used, maxSize); + } + + @Override + public CloseableIteration evaluate(Order node, BindingSet bindings) + throws QueryEvaluationException + { + ValueComparator vcmp = new ValueComparator(); + OrderComparator cmp = new OrderComparator(this, node, vcmp); + boolean reduced = isReducedOrDistinct(node); + long limit = getLimit(node); + return new LimitedSizeOrderIteration(evaluate(node.getArg(), bindings), cmp, limit, reduced, used, maxSize); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeBottomUpJoinIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeBottomUpJoinIterator.java new file mode 100644 index 00000000000..ee1fe645a0d --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeBottomUpJoinIterator.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.BottomUpJoinIterator; + +/** + * @author Jerven Bolleman, SIB Swiss Institute of Bioinformatics + * @deprecated replaced by LimitedSizeHashJoinIteration + */ +@Deprecated +public class LimitedSizeBottomUpJoinIterator extends BottomUpJoinIterator { + + private static final String SIZE_LIMIT_REACHED = "Size limited reached inside bottom up join operator, max size is:"; + private AtomicLong used; + + private long maxSize; + + /** + * @param limitedSizeEvaluationStrategy + * @param join + * @param bindings + * @param used + * @param maxSize + * @throws QueryEvaluationException + */ + public LimitedSizeBottomUpJoinIterator(EvaluationStrategy limitedSizeEvaluationStrategy, + Join join, BindingSet bindings, AtomicLong used, long maxSize) + throws QueryEvaluationException + { + super(limitedSizeEvaluationStrategy, join, bindings); + this.used = used; + this.maxSize = maxSize; + } + + @Override + protected void addAll(List hashTableValues, List values) + throws QueryEvaluationException + { + Iterator iter = values.iterator(); + while (iter.hasNext()) { + if (hashTableValues.add(iter.next()) && used.incrementAndGet() > maxSize) { + throw new QueryEvaluationException(SIZE_LIMIT_REACHED+maxSize); + } + } + } + + @Override + protected void add(List leftArgResults, BindingSet b) + throws QueryEvaluationException + { + if (leftArgResults.add(b) && used.incrementAndGet() > maxSize) { + throw new QueryEvaluationException(SIZE_LIMIT_REACHED+maxSize); + } + } + + @Override + protected BindingSet removeFirstElement(List list) + throws QueryEvaluationException + { + used.decrementAndGet(); + return super.removeFirstElement(list); + } + + @Override + protected void put(Map> hashTable, BindingSet hashKey, + List hashValue) + throws QueryEvaluationException + { + List put = hashTable.put(hashKey, hashValue); + if (put == null && used.incrementAndGet() > maxSize) { + throw new QueryEvaluationException(SIZE_LIMIT_REACHED+maxSize); + } + } + + @Override + protected void handleClose() + throws QueryEvaluationException + { + long htvSize = clearHashTable(); + super.handleClose(); + used.addAndGet(-htvSize); + } + + + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeDistinctIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeDistinctIteration.java new file mode 100644 index 00000000000..8f179d1fa27 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeDistinctIteration.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator; + +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.common.iteration.DistinctIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * @author Jerven Bolleman, SIB Swiss Institute of Bioinformatics + */ +public class LimitedSizeDistinctIteration extends DistinctIteration { + + private final AtomicLong used; + + private final long maxSize; + + /** + * @param iter + */ + public LimitedSizeDistinctIteration( + Iteration iter, AtomicLong used, + long maxSize) + { + super(iter); + this.used = used; + this.maxSize = maxSize; + } + + @Override + protected boolean add(BindingSet object) + throws QueryEvaluationException + { + boolean add = super.add(object); + if (add && used.incrementAndGet() > maxSize) + throw new QueryEvaluationException("Size limited reached inside query operator."); + return add; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeHashJoinIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeHashJoinIteration.java new file mode 100644 index 00000000000..b505264d07f --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeHashJoinIteration.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.BindingSetHashKey; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.HashJoinIteration; + + +/** + * + * @author MJAHale + */ +public class LimitedSizeHashJoinIteration extends HashJoinIteration { + private static final String SIZE_LIMIT_REACHED = "Size limited reached inside bottom up join operator, max size is:"; + private AtomicLong used; + + private long maxSize; + + public LimitedSizeHashJoinIteration(EvaluationStrategy limitedSizeEvaluationStrategy, + Join join, BindingSet bindings, AtomicLong used, long maxSize) + throws QueryEvaluationException + { + super(limitedSizeEvaluationStrategy, join, bindings); + this.used = used; + this.maxSize = maxSize; + } + + + protected E nextFromCache(Iterator iter) + { + E v = iter.next(); + used.decrementAndGet(); + iter.remove(); + return v; + } + + protected void add(Collection col, E value) + throws QueryEvaluationException + { + if (col.add(value) && used.incrementAndGet() > maxSize) { + throw new QueryEvaluationException(SIZE_LIMIT_REACHED+maxSize); + } + } + + protected void addAll(Collection col, List values) + throws QueryEvaluationException + { + for (E v : values) { + add(col, v); + } + } + + protected void putHashTableEntry(Map> hashTable, BindingSetHashKey hashKey, + List hashValue) + throws QueryEvaluationException + { + List put = hashTable.put(hashKey, hashValue); + if (put == null && used.incrementAndGet() > maxSize) { + throw new QueryEvaluationException(SIZE_LIMIT_REACHED+maxSize); + } + } + + @Override + protected void disposeHashTable(Map> map) + { + long htvSize = map.size(); + map.clear(); + used.addAndGet(-htvSize); + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeIntersectIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeIntersectIteration.java new file mode 100644 index 00000000000..513d793a3f8 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeIntersectIteration.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator; + +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.common.iteration.IntersectIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * @author Jerven Bolleman, SIB Swiss Institute of Bioinformatics + */ +public class LimitedSizeIntersectIteration extends IntersectIteration { + + private final AtomicLong used; + + private final long maxSize; + + /** + * Creates a new IntersectIteration that returns the intersection of the + * results of two Iterations. By default, duplicates are not + * filtered from the results. + * + * @param arg1 + * An Iteration containing the first set of elements. + * @param arg2 + * An Iteration containing the second set of elements. + * @param used + * An atomic long used to monitor how many elements are in the set + * collections. + * @param maxSize + * Maximum size allowed by the sum of all collections used by the + * LimitedSizeQueryEvaluatlion. + */ + public LimitedSizeIntersectIteration( + Iteration arg1, + Iteration arg2, AtomicLong used, + long maxSize) + { + this(arg1, arg2, false, used, maxSize); + + } + + public LimitedSizeIntersectIteration( + Iteration arg1, + Iteration arg2, boolean distinct, + AtomicLong used, long maxSize) + { + super(arg1, arg2, distinct); + this.used = used; + this.maxSize = maxSize; + } + + @Override + public Set addSecondSet( + Iteration arg2, Set set) + throws QueryEvaluationException + { + + LimitedSizeIteratorUtil.addAll(arg2, set, used, maxSize); + return set; + } + + /** + * After closing the set is cleared and any "used" capacity for collections + * is returned. + */ + @Override + protected void handleClose() + throws QueryEvaluationException + { + + long size = clearIncludeSet(); + used.addAndGet(-size); + super.handleClose(); + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeIteratorUtil.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeIteratorUtil.java new file mode 100644 index 00000000000..a496010eae4 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeIteratorUtil.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator; + +import java.util.Collection; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * @author Jerven Bolleman, SIB Swiss Institute of Bioinformatics + */ +public class LimitedSizeIteratorUtil { + + /** + * + * @param arg2 the iteration with elements to add to the includeSet + * @param includeSet the set that should have all unique elements of arg2 + * @param used the collection size counter of all collections used in answering a query + * @param maxSize the point at which we throw a new query exception + * @return the includeSet + * @throws QueryEvaluationException trigerred when maxSize is smaller than the used value + */ + public static Set addAll(Iteration arg2, + Set includeSet, AtomicLong used, long maxSize) + throws QueryEvaluationException + { + while (arg2.hasNext()) { + if (includeSet.add(arg2.next()) && used.incrementAndGet() > maxSize) + throw new QueryEvaluationException("Size limited reached inside intersect operator"); + } + return includeSet; + } + + /** + * @param object + * object to put in set if not there already. + * @param excludeSet + * set that we need to store object in. + * @param used + * AtomicLong tracking how many elements we have in storage. + * @param maxSize + * @throws QueryEvaluationException + * when the object is added to the set and the total elements in all + * limited size collections exceed the allowed maxSize. + */ + public static boolean add(V object, Collection excludeSet, AtomicLong used, long maxSize) + throws QueryEvaluationException + { + boolean add = excludeSet.add(object); + if (add && used.incrementAndGet() > maxSize) + throw new QueryEvaluationException("Size limited reached inside query operator."); + return add; + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeOrderIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeOrderIteration.java new file mode 100644 index 00000000000..bdfb528bc56 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeOrderIteration.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.OrderIterator; + +/** + * @author Jerven Bolleman, SIB Swiss Institute of Bioinformatics + */ +public class LimitedSizeOrderIteration extends OrderIterator { + + private final AtomicLong used; + + private final long maxSize; + + /** + * @param iter + * @param comparator + */ + public LimitedSizeOrderIteration(CloseableIteration iter, + Comparator comparator, AtomicLong used, long maxSize) + { + this(iter, comparator, Integer.MAX_VALUE, false, used, maxSize); + } + + public LimitedSizeOrderIteration(CloseableIteration iter, + Comparator comparator, long limit, boolean distinct, AtomicLong used, long maxSize) + { + super(iter, comparator, limit, distinct); + this.used = used; + this.maxSize = maxSize; + } + + @Override + protected void removeLast(Collection lastResults) { + super.removeLast(lastResults); + used.decrementAndGet(); + } + + @Override + protected boolean add(BindingSet next, Collection list) + throws QueryEvaluationException + { + + return LimitedSizeIteratorUtil.add(next, list, used, maxSize); + } + + @Override + protected Integer put(NavigableMap map, BindingSet next, int count) + throws QueryEvaluationException + { + final Integer i = map.get(next); + final int oldCount = i == null ? 0 : i; + + final Integer put = super.put(map, next, count); + + if (oldCount < count) { + if (used.incrementAndGet() > maxSize) { + throw new QueryEvaluationException( + "Size limited reached inside order operator query, max size is:" + maxSize); + } + } + else if (oldCount > count) { + used.decrementAndGet(); + } + + return put; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizePathIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizePathIterator.java new file mode 100644 index 00000000000..867517878ac --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizePathIterator.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator; + +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.PathIteration; + +/** + * @author Jerven Bolleman, SIB Swiss Institute of Bioinformatics + */ +public class LimitedSizePathIterator extends PathIteration { + + private final AtomicLong used; + private final long maxSize; + + /** + * @param evaluationStrategyImpl + * @param scope + * @param startVar + * @param pathExpression + * @param endVar + * @param contextVar + * @param minLength + * @param bindings + * @throws QueryEvaluationException + */ + public LimitedSizePathIterator(SimpleEvaluationStrategy evaluationStrategyImpl, Scope scope, Var startVar, + TupleExpr pathExpression, Var endVar, Var contextVar, long minLength, BindingSet bindings, + AtomicLong used, long maxSize) + throws QueryEvaluationException + { + super(evaluationStrategyImpl, scope, startVar, pathExpression, endVar, contextVar, minLength, bindings); + this.used = used; + this.maxSize = maxSize; + } + + @Override + protected boolean add(Set valueSet, ValuePair vp) + throws QueryEvaluationException + { + return LimitedSizeIteratorUtil.add(vp, valueSet, used, maxSize); + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeSPARQLMinusIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeSPARQLMinusIteration.java new file mode 100644 index 00000000000..447cb315981 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeSPARQLMinusIteration.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator; + +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.common.iteration.Iteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.SPARQLMinusIteration; + +/** + * @author Jerven Bolleman, SIB Swiss Institute of Bioinformatics + */ +public class LimitedSizeSPARQLMinusIteration extends SPARQLMinusIteration { + + private AtomicLong used; + + private long maxSize; + + /** + * Creates a new MinusIteration that returns the results of the left argument + * minus the results of the right argument. By default, duplicates are + * not filtered from the results. + * + * @param leftArg + * An Iteration containing the main set of elements. + * @param rightArg + * An Iteration containing the set of elements that should be filtered + * from the main set. * @param used An atomic long used to monitor how + * many elements are in the set collections. + * @param used + * An atomic long used to monitor how many elements are in the set + * collections. + * @param maxSize + * Maximum size allowed by the sum of all collections used by the + * LimitedSizeQueryEvaluatlion. + */ + public LimitedSizeSPARQLMinusIteration(Iteration leftArg, + Iteration rightArg, AtomicLong used, long maxSize) + { + this(leftArg, rightArg, false, used, maxSize); + } + + /** + * Creates a new SPARQLMinusIteration that returns the results of the left argument + * minus the results of the right argument. + * + * @param leftArg + * An Iteration containing the main set of elements. + * @param rightArg + * An Iteration containing the set of elements that should be filtered + * from the main set. + * @param distinct + * Flag indicating whether duplicate elements should be filtered from + * the result. + * @param used + * An atomic long used to monitor how many elements are in the set + * collections. + * @param maxSize + * Maximum size allowed by the sum of all collections used by the + * LimitedSizeQueryEvaluatlion. + */ + public LimitedSizeSPARQLMinusIteration(Iteration leftArg, + Iteration rightArg, boolean distinct, AtomicLong used, + long maxSize) + { + super(leftArg, rightArg, distinct); + this.used = used; + this.maxSize = maxSize; + } + + @Override + protected Set makeSet(Iteration rightArg2) + throws QueryEvaluationException { + return LimitedSizeIteratorUtil.addAll(rightArg2, makeSet(),used, maxSize); + } + + /** + * After closing the set is cleared and any "used" capacity for collections is returned. + */ + @Override + protected void handleClose() + throws QueryEvaluationException + { + long size = clearExcludeSet(); + super.handleClose(); + used.addAndGet(-size); + } + + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeZeroLengthPathIteration.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeZeroLengthPathIteration.java new file mode 100644 index 00000000000..a451599af7f --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/limited/iterator/LimitedSizeZeroLengthPathIteration.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.limited.iterator; + +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.ZeroLengthPathIteration; + +/** + * @author Jerven Bolleman, SIB Swiss Institute of Bioinformatics + */ +public class LimitedSizeZeroLengthPathIteration extends ZeroLengthPathIteration { + + private final AtomicLong used; + + private final long maxSize; + + /** + * @param evaluationStrategyImpl + * @param subjectVar + * @param objVar + * @param subj + * @param obj + * @param contextVar + * @param bindings + */ + public LimitedSizeZeroLengthPathIteration(SimpleEvaluationStrategy evaluationStrategyImpl, Var subjectVar, + Var objVar, Value subj, Value obj, Var contextVar, BindingSet bindings, AtomicLong used, long maxSize) + { + super(evaluationStrategyImpl, subjectVar, objVar, subj, obj, contextVar, bindings); + this.used = used; + this.maxSize = maxSize; + } + + @Override + protected boolean add(Set reportedValues2, Value v) + throws QueryEvaluationException + { + return LimitedSizeIteratorUtil.add(v, reportedValues2, used, maxSize); + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/EvaluationStrategies.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/EvaluationStrategies.java new file mode 100644 index 00000000000..d82db21a188 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/EvaluationStrategies.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import java.util.Map; +import java.util.UUID; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; + +/** + * Registry for currently active {@link EvaluationStrategy} objects. The + * internal registry uses soft references to allow entries to be + * garbage-collected when no longer used. Currently, the primary purpose of this + * is to support (de)serialization of objects (over the lifetime of the VM) that + * depend on an EvaluationStrategy + * + * @author Jeen Broekstra + */ +public class EvaluationStrategies { + + private static final Cache registry = CacheBuilder.newBuilder().weakValues().build(); + + /** + * Retrieve the EvaluationStrategy registered with the supplied key. + * + * @param key + * the key + * @return the registered EvaluationStrategy, or null if no + * matching EvaluationStrategy can be found. + */ + public static final EvaluationStrategy get(UUID key) { + return registry.getIfPresent(key); + } + + /** + * Retrieve the registry key for the given EvaluationStrategy + * + * @param strategy + * the EvaluationStrategy for which to retrieve the registry key + * @return the registry key with which the supplied strategy can be + * retrieved, or null if the supplied strategy is not in + * the registry. + */ + public static final UUID getKey(EvaluationStrategy strategy) { + final Map map = registry.asMap(); + + // we could make this lookup more efficient with a WeakHashMap-based + // reverse index, but we currently prefer this slower but more robust + // approach (less chance of accidental lingering references that prevent + // GC) + for (UUID key : map.keySet()) { + // we use identity comparison in line with how guava caches behave + // when softValues are used. + if (strategy == map.get(key)) { + return key; + } + } + return null; + } + + /** + * Add a strategy to the registry and returns the registry key. If the + * strategy is already present, the operation simply returns the key with + * which it is currently registered. + * + * @param strategy + * the EvaluationStrategy to register + * @return the key with which the strategy is registered. + */ + public static final UUID register(EvaluationStrategy strategy) { + UUID key = getKey(strategy); + if (key == null) { + key = UUID.randomUUID(); + registry.put(key, strategy); + } + return key; + } + + /** + * Prevent instantiation: util class + */ + private EvaluationStrategies() { + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/MathUtil.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/MathUtil.java new file mode 100644 index 00000000000..3a449ff0eef --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/MathUtil.java @@ -0,0 +1,219 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.impl.DecimalLiteral; +import org.eclipse.rdf4j.model.impl.IntegerLiteral; +import org.eclipse.rdf4j.model.impl.NumericLiteral; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.MathExpr.MathOp; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; + +/** + * A utility class for evaluation of mathematical expressions on RDF literals. + * + * @author Jeen Broekstra + */ +public class MathUtil { + + /** + * The default expansion scale used in division operations resulting + * in a decimal value with non-terminating decimal expansion. The OpenRDF + * default is 24 digits, a value used in various other SPARQL + * implementations, to make comparison between these systems easy. + */ + public static final int DEFAULT_DECIMAL_EXPANSION_SCALE = 24; + + private static int decimalExpansionScale = DEFAULT_DECIMAL_EXPANSION_SCALE; + + /** + * Computes the result of applying the supplied math operator on the supplied + * left and right operand. + * + * @param leftLit + * a numeric datatype literal + * @param rightLit + * a numeric datatype literal + * @param op + * a mathematical operator, as definied by MathExpr.MathOp. + * @return a numeric datatype literal containing the result of the operation. + * The result will be datatype according to the most specific data + * type the two operands have in common per the SPARQL/XPath spec. + * @throws ValueExprEvaluationException + */ + public static Literal compute(Literal leftLit, Literal rightLit, MathOp op) + throws ValueExprEvaluationException + { + final ValueFactory vf = SimpleValueFactory.getInstance(); + + IRI leftDatatype = leftLit.getDatatype(); + IRI rightDatatype = rightLit.getDatatype(); + + // Only numeric value can be used in math expressions + if (!XMLDatatypeUtil.isNumericDatatype(leftDatatype)) { + throw new ValueExprEvaluationException("Not a number: " + leftLit); + } + if (!XMLDatatypeUtil.isNumericDatatype(rightDatatype)) { + throw new ValueExprEvaluationException("Not a number: " + rightLit); + } + + // Determine most specific datatype that the arguments have in common, + // choosing from xsd:integer, xsd:decimal, xsd:float and xsd:double as + // per the SPARQL/XPATH spec + IRI commonDatatype; + + if (leftDatatype.equals(XMLSchema.DOUBLE) || rightDatatype.equals(XMLSchema.DOUBLE)) { + commonDatatype = XMLSchema.DOUBLE; + } + else if (leftDatatype.equals(XMLSchema.FLOAT) || rightDatatype.equals(XMLSchema.FLOAT)) { + commonDatatype = XMLSchema.FLOAT; + } + else if (leftDatatype.equals(XMLSchema.DECIMAL) || rightDatatype.equals(XMLSchema.DECIMAL)) { + commonDatatype = XMLSchema.DECIMAL; + } + else if (op == MathOp.DIVIDE) { + // Result of integer divide is decimal and requires the arguments to + // be handled as such, see for details: + // http://www.w3.org/TR/xpath-functions/#func-numeric-divide + commonDatatype = XMLSchema.DECIMAL; + } + else { + commonDatatype = XMLSchema.INTEGER; + } + + // Note: Java already handles cases like divide-by-zero appropriately + // for floats and doubles, see: + // http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Tech/ + // Chapter02/floatingPt2.html + + try { + if (commonDatatype.equals(XMLSchema.DOUBLE)) { + double left = leftLit.doubleValue(); + double right = rightLit.doubleValue(); + + switch (op) { + case PLUS: + return vf.createLiteral(left + right); + case MINUS: + return vf.createLiteral(left - right); + case MULTIPLY: + return vf.createLiteral(left * right); + case DIVIDE: + return vf.createLiteral(left / right); + default: + throw new IllegalArgumentException("Unknown operator: " + op); + } + } + else if (commonDatatype.equals(XMLSchema.FLOAT)) { + float left = leftLit.floatValue(); + float right = rightLit.floatValue(); + + switch (op) { + case PLUS: + return vf.createLiteral(left + right); + case MINUS: + return vf.createLiteral(left - right); + case MULTIPLY: + return vf.createLiteral(left * right); + case DIVIDE: + return vf.createLiteral(left / right); + default: + throw new IllegalArgumentException("Unknown operator: " + op); + } + } + else if (commonDatatype.equals(XMLSchema.DECIMAL)) { + BigDecimal left = leftLit.decimalValue(); + BigDecimal right = rightLit.decimalValue(); + + switch (op) { + case PLUS: + return vf.createLiteral(left.add(right)); + case MINUS: + return vf.createLiteral(left.subtract(right)); + case MULTIPLY: + return vf.createLiteral(left.multiply(right)); + case DIVIDE: + // Divide by zero handled through NumberFormatException + BigDecimal result = null; + try { + // try to return the exact quotient if possible. + result = left.divide(right, MathContext.UNLIMITED); + } + catch (ArithmeticException e) { + // non-terminating decimal expansion in quotient, using + // scaling and rounding. + result = left.setScale(getDecimalExpansionScale(), RoundingMode.HALF_UP).divide(right, + RoundingMode.HALF_UP); + } + + return vf.createLiteral(result); + default: + throw new IllegalArgumentException("Unknown operator: " + op); + } + } + else { // XMLSchema.INTEGER + BigInteger left = leftLit.integerValue(); + BigInteger right = rightLit.integerValue(); + + switch (op) { + case PLUS: + return vf.createLiteral(left.add(right)); + case MINUS: + return vf.createLiteral(left.subtract(right)); + case MULTIPLY: + return vf.createLiteral(left.multiply(right)); + case DIVIDE: + throw new RuntimeException("Integer divisions should be processed as decimal divisions"); + default: + throw new IllegalArgumentException("Unknown operator: " + op); + } + } + } + catch (NumberFormatException e) { + throw new ValueExprEvaluationException(e); + } + catch (ArithmeticException e) { + throw new ValueExprEvaluationException(e); + } + } + + /** + * Returns the decimal expansion scale used in division operations resulting + * in a decimal value with non-terminating decimal expansion. By default, + * this value is set to 24. + * + * @return The decimal expansion scale. + */ + public static int getDecimalExpansionScale() { + return decimalExpansionScale; + } + + /** + * Sets the decimal expansion scale used in divisions resulting in a decimal + * value with non-terminating decimal expansion. + * + * @param decimalExpansionScale + * The decimal expansion scale to set. Note that a mimimum of 18 is + * required to stay compliant with the XPath specification of + * xsd:decimal operations. + */ + public static void setDecimalExpansionScale(int decimalExpansionScale) { + MathUtil.decimalExpansionScale = decimalExpansionScale; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java new file mode 100644 index 00000000000..8720d027173 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.UUID; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Order; +import org.eclipse.rdf4j.query.algebra.OrderElem; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A {@link Comparator} on {@link BindingSet}s that imposes a total ordering by + * examining supplied {@link Order} elements (i.e. the elements of an ORDER BY + * clause), falling back on a custom predictable ordering for BindingSet + * elements if no ordering is established on the basis of the Order elements. + * + * @author James Leigh + * @author Jeen Broekstra + */ +public class OrderComparator implements Comparator, Serializable { + + /** + * + */ + private static final long serialVersionUID = -7002730491398949902L; + + private final transient Logger logger = LoggerFactory.getLogger(OrderComparator.class); + + private transient EvaluationStrategy strategy; + + private UUID strategyKey; + + private final Order order; + + private transient ValueComparator cmp; + + public OrderComparator(EvaluationStrategy strategy, Order order, ValueComparator vcmp) { + this.strategy = strategy; + this.order = order; + this.cmp = vcmp; + } + + public int compare(BindingSet o1, BindingSet o2) { + + try { + + for (OrderElem element : order.getElements()) { + Value v1 = evaluate(element.getExpr(), o1); + Value v2 = evaluate(element.getExpr(), o2); + + int compare = cmp.compare(v1, v2); + + if (compare != 0) { + return element.isAscending() ? compare : -compare; + } + } + + // On the basis of the order clause elements the two binding sets are + // unordered. + // We now need to impose a total ordering (as per the + // contract of java.util.Comparator). We order by + // size first, then by binding names, then finally by values. + + // null check + if (o1 == null || o2 == null) { + if (o1 == null) { + return o2 == null ? 0 : 1; + } + if (o2 == null) { + return o1 == null ? 0 : -1; + } + } + + if (o2.size() != o1.size()) { + return o1.size() < o2.size() ? 1 : -1; + } + + // we create an ordered list of binding names (using natural string order) to use for + // consistent iteration over binding names and binding values. + final ArrayList o1bindingNamesOrdered = new ArrayList(o1.getBindingNames()); + Collections.sort(o1bindingNamesOrdered); + + // binding set sizes are equal. compare on binding names. + if (!o1.getBindingNames().equals(o2.getBindingNames())) { + + final ArrayList o2bindingNamesOrdered = new ArrayList(o2.getBindingNames()); + Collections.sort(o2bindingNamesOrdered); + + for (int i = 0; i < o1bindingNamesOrdered.size(); i++) { + String o1bn = o1bindingNamesOrdered.get(i); + String o2bn = o2bindingNamesOrdered.get(i); + int compare = o1bn.compareTo(o2bn); + if (compare != 0) { + return compare; + } + } + } + + // binding names equal. compare on all values. + for (String bindingName: o1bindingNamesOrdered) { + final Value v1 = o1.getValue(bindingName); + final Value v2 = o2.getValue(bindingName); + + final int compare = cmp.compare(v1, v2); + if (compare != 0) { + return compare; + } + } + + return 0; + } + catch (QueryEvaluationException e) { + logger.debug(e.getMessage(), e); + return 0; + } + catch (IllegalArgumentException e) { + logger.debug(e.getMessage(), e); + return 0; + } + } + + private Value evaluate(ValueExpr valueExpr, BindingSet o) + throws QueryEvaluationException + { + try { + return strategy.evaluate(valueExpr, o); + } + catch (ValueExprEvaluationException exc) { + return null; + } + } + + private void writeObject(ObjectOutputStream out) + throws IOException + { + this.strategyKey = EvaluationStrategies.register(strategy); + out.defaultWriteObject(); + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException + { + in.defaultReadObject(); + this.strategy = EvaluationStrategies.get(this.strategyKey); + this.cmp = new ValueComparator(); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtil.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtil.java new file mode 100644 index 00000000000..7f9f1a31d2c --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtil.java @@ -0,0 +1,434 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.util.Literals; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; + +/** + * @author Arjohn Kampman + */ +public class QueryEvaluationUtil { + + /** + * Determines the effective boolean value (EBV) of the supplied value as + * defined in the SPARQL + * specification: + *
      + *
    • The EBV of any literal whose type is xsd:boolean or numeric is false + * if the lexical form is not valid for that datatype (e.g. + * "abc"^^xsd:integer). + *
    • If the argument is a typed literal with a datatype of xsd:boolean, the + * EBV is the value of that argument. + *
    • If the argument is a plain literal or a typed literal with a datatype + * of xsd:string, the EBV is false if the operand value has zero length; + * otherwise the EBV is true. + *
    • If the argument is a numeric type or a typed literal with a datatype + * derived from a numeric type, the EBV is false if the operand value is NaN + * or is numerically equal to zero; otherwise the EBV is true. + *
    • All other arguments, including unbound arguments, produce a type + * error. + *
    + * + * @param value + * Some value. + * @return The EBV of value. + * @throws ValueExprEvaluationException + * In case the application of the EBV algorithm results in a type + * error. + */ + public static boolean getEffectiveBooleanValue(Value value) + throws ValueExprEvaluationException + { + if (value instanceof Literal) { + Literal literal = (Literal)value; + String label = literal.getLabel(); + IRI datatype = literal.getDatatype(); + + if (datatype.equals(XMLSchema.STRING)) { + return label.length() > 0; + } + else if (datatype.equals(XMLSchema.BOOLEAN)) { + if ("true".equals(label) || "1".equals(label)) { + return true; + } + else { + // also false for illegal values + return false; + } + } + else if (datatype.equals(XMLSchema.DECIMAL)) { + try { + String normDec = XMLDatatypeUtil.normalizeDecimal(label); + return !normDec.equals("0.0"); + } + catch (IllegalArgumentException e) { + return false; + } + } + else if (XMLDatatypeUtil.isIntegerDatatype(datatype)) { + try { + String normInt = XMLDatatypeUtil.normalize(label, datatype); + return !normInt.equals("0"); + } + catch (IllegalArgumentException e) { + return false; + } + } + else if (XMLDatatypeUtil.isFloatingPointDatatype(datatype)) { + try { + String normFP = XMLDatatypeUtil.normalize(label, datatype); + return !normFP.equals("0.0E0") && !normFP.equals("NaN"); + } + catch (IllegalArgumentException e) { + return false; + } + } + } + + throw new ValueExprEvaluationException(); + } + + public static boolean compare(Value leftVal, Value rightVal, CompareOp operator) + throws ValueExprEvaluationException + { + if (leftVal instanceof Literal && rightVal instanceof Literal) { + // Both left and right argument is a Literal + return compareLiterals((Literal)leftVal, (Literal)rightVal, operator); + } + else { + // All other value combinations + switch (operator) { + case EQ: + return valuesEqual(leftVal, rightVal); + case NE: + return !valuesEqual(leftVal, rightVal); + default: + throw new ValueExprEvaluationException( + "Only literals with compatible, ordered datatypes can be compared using <, <=, > and >= operators"); + } + } + } + + private static boolean valuesEqual(Value leftVal, Value rightVal) { + return leftVal != null && rightVal != null && leftVal.equals(rightVal); + } + + public static boolean compareLiterals(Literal leftLit, Literal rightLit, CompareOp operator) + throws ValueExprEvaluationException + { + // type precendence: + // - simple literal + // - numeric + // - xsd:boolean + // - xsd:dateTime + // - xsd:string + // - RDF term (equal and unequal only) + + IRI leftDatatype = leftLit.getDatatype(); + IRI rightDatatype = rightLit.getDatatype(); + + boolean leftLangLit = Literals.isLanguageLiteral(leftLit); + boolean rightLangLit = Literals.isLanguageLiteral(rightLit); + + // for purposes of query evaluation in SPARQL, simple literals and + // string-typed literals with the same + // lexical value are considered equal. + IRI commonDatatype = null; + if (QueryEvaluationUtil.isSimpleLiteral(leftLit) && QueryEvaluationUtil.isSimpleLiteral(rightLit)) { + commonDatatype = XMLSchema.STRING; + } + + Integer compareResult = null; + + if (QueryEvaluationUtil.isSimpleLiteral(leftLit) && QueryEvaluationUtil.isSimpleLiteral(rightLit)) { + compareResult = leftLit.getLabel().compareTo(rightLit.getLabel()); + } + else if ((!leftLangLit && !rightLangLit) || commonDatatype != null) { + if (commonDatatype == null) { + if (leftDatatype.equals(rightDatatype)) { + commonDatatype = leftDatatype; + } + else if (XMLDatatypeUtil.isNumericDatatype(leftDatatype) + && XMLDatatypeUtil.isNumericDatatype(rightDatatype)) + { + // left and right arguments have different datatypes, try to find + // a + // more general, shared datatype + if (leftDatatype.equals(XMLSchema.DOUBLE) || rightDatatype.equals(XMLSchema.DOUBLE)) { + commonDatatype = XMLSchema.DOUBLE; + } + else if (leftDatatype.equals(XMLSchema.FLOAT) || rightDatatype.equals(XMLSchema.FLOAT)) { + commonDatatype = XMLSchema.FLOAT; + } + else if (leftDatatype.equals(XMLSchema.DECIMAL) || rightDatatype.equals(XMLSchema.DECIMAL)) { + commonDatatype = XMLSchema.DECIMAL; + } + else { + commonDatatype = XMLSchema.INTEGER; + } + } + } + + if (commonDatatype != null) { + try { + if (commonDatatype.equals(XMLSchema.DOUBLE)) { + compareResult = Double.compare(leftLit.doubleValue(), rightLit.doubleValue()); + } + else if (commonDatatype.equals(XMLSchema.FLOAT)) { + compareResult = Float.compare(leftLit.floatValue(), rightLit.floatValue()); + } + else if (commonDatatype.equals(XMLSchema.DECIMAL)) { + compareResult = leftLit.decimalValue().compareTo(rightLit.decimalValue()); + } + else if (XMLDatatypeUtil.isIntegerDatatype(commonDatatype)) { + compareResult = leftLit.integerValue().compareTo(rightLit.integerValue()); + } + else if (commonDatatype.equals(XMLSchema.BOOLEAN)) { + Boolean leftBool = Boolean.valueOf(leftLit.booleanValue()); + Boolean rightBool = Boolean.valueOf(rightLit.booleanValue()); + compareResult = leftBool.compareTo(rightBool); + } + else if (XMLDatatypeUtil.isCalendarDatatype(commonDatatype)) { + XMLGregorianCalendar left = leftLit.calendarValue(); + XMLGregorianCalendar right = rightLit.calendarValue(); + + compareResult = left.compare(right); + + // Note: XMLGregorianCalendar.compare() returns compatible + // values + // (-1, 0, 1) but INDETERMINATE needs special treatment + if (compareResult == DatatypeConstants.INDETERMINATE) { + throw new ValueExprEvaluationException("Indeterminate result for date/time comparison"); + } + } + else if (commonDatatype.equals(XMLSchema.STRING)) { + compareResult = leftLit.getLabel().compareTo(rightLit.getLabel()); + } + } + catch (IllegalArgumentException e) { + // One of the basic-type method calls failed, try syntactic match + // before throwing an error + if (leftLit.equals(rightLit)) { + switch (operator) { + case EQ: + return true; + case NE: + return false; + } + } + + throw new ValueExprEvaluationException(e); + } + } + } + + if (compareResult != null) { + // Literals have compatible ordered datatypes + switch (operator) { + case LT: + return compareResult.intValue() < 0; + case LE: + return compareResult.intValue() <= 0; + case EQ: + return compareResult.intValue() == 0; + case NE: + return compareResult.intValue() != 0; + case GE: + return compareResult.intValue() >= 0; + case GT: + return compareResult.intValue() > 0; + default: + throw new IllegalArgumentException("Unknown operator: " + operator); + } + } + else { + // All other cases, e.g. literals with languages, unequal or + // unordered datatypes, etc. These arguments can only be compared + // using the operators 'EQ' and 'NE'. See SPARQL's RDFterm-equal + // operator + + boolean literalsEqual = leftLit.equals(rightLit); + + if (!literalsEqual) { + if (!leftLangLit && !rightLangLit && isSupportedDatatype(leftDatatype) + && isSupportedDatatype(rightDatatype)) + { + // left and right arguments have incompatible but supported + // datatypes + + // we need to check that the lexical-to-value mapping for both + // datatypes succeeds + if (!XMLDatatypeUtil.isValidValue(leftLit.getLabel(), leftDatatype)) { + throw new ValueExprEvaluationException("not a valid datatype value: " + leftLit); + } + + if (!XMLDatatypeUtil.isValidValue(rightLit.getLabel(), rightDatatype)) { + throw new ValueExprEvaluationException("not a valid datatype value: " + rightLit); + } + boolean leftString = leftDatatype.equals(XMLSchema.STRING); + boolean rightString = rightDatatype.equals(XMLSchema.STRING); + boolean leftNumeric = XMLDatatypeUtil.isNumericDatatype(leftDatatype); + boolean rightNumeric = XMLDatatypeUtil.isNumericDatatype(rightDatatype); + boolean leftDate = XMLDatatypeUtil.isCalendarDatatype(leftDatatype); + boolean rightDate = XMLDatatypeUtil.isCalendarDatatype(rightDatatype); + + if(leftString != rightString) { + throw new ValueExprEvaluationException("Unable to compare strings with other supported types"); + } + if(leftNumeric != rightNumeric) { + throw new ValueExprEvaluationException("Unable to compare numeric types with other supported types"); + } + if(leftDate != rightDate) { + throw new ValueExprEvaluationException("Unable to compare date types with other supported types"); + } + } + else if (!leftLangLit && !rightLangLit) + { + // For literals with unsupported datatypes we don't know if their + // values are equal + throw new ValueExprEvaluationException("Unable to compare literals with unsupported types"); + } + } + + switch (operator) { + case EQ: + return literalsEqual; + case NE: + return !literalsEqual; + case LT: + case LE: + case GE: + case GT: + throw new ValueExprEvaluationException( + "Only literals with compatible, ordered datatypes can be compared using <, <=, > and >= operators"); + default: + throw new IllegalArgumentException("Unknown operator: " + operator); + } + } + } + + /** + * Checks whether the supplied value is a "plain literal". A "plain literal" + * is a literal with no datatype and optionally a language tag. + * + * @see RDF + * Literal Documentation + */ + public static boolean isPlainLiteral(Value v) { + if (v instanceof Literal) { + Literal l = (Literal)v; + return (l.getDatatype().equals(XMLSchema.STRING)); + } + return false; + } + + /** + * Checks whether the supplied value is a "simple literal". A + * "simple literal" is a literal with no language tag nor datatype. + * + * @see SPARQL + * Simple Literal Documentation + */ + public static boolean isSimpleLiteral(Value v) { + if (v instanceof Literal) { + return isSimpleLiteral((Literal)v); + } + + return false; + } + + /** + * Checks whether the supplied literal is a "simple literal". A + * "simple literal" is a literal with no language tag and the datatype + * {@link XMLSchema#STRING}. + * + * @see SPARQL + * Simple Literal Documentation + */ + public static boolean isSimpleLiteral(Literal l) { + return !Literals.isLanguageLiteral(l) && l.getDatatype().equals(XMLSchema.STRING); + } + + /** + * Checks whether the supplied literal is a "string literal". A "string + * literal" is either a simple literal, a plain literal with language tag, or + * a literal with datatype xsd:string. + * + * @see SPARQL + * Functions on Strings Documentation + */ + public static boolean isStringLiteral(Value v) { + if (v instanceof Literal) { + return isStringLiteral((Literal)v); + } + + return false; + } + + /** + * Checks whether the supplied two literal arguments are 'argument + * compatible' according to the SPARQL definition. + * + * @param arg1 + * the first argument + * @param arg2 + * the second argument + * @return true iff the two supplied arguments are argument compatible, false + * otherwise + * @since 2.7.0 + * @see SPARQL + * Argument Compatibility Rules + */ + public static boolean compatibleArguments(Literal arg1, Literal arg2) { + boolean arg1Language = Literals.isLanguageLiteral(arg1); + boolean arg2Language = Literals.isLanguageLiteral(arg2); + boolean arg1Simple = isSimpleLiteral(arg1); + boolean arg2Simple = isSimpleLiteral(arg2); + // 1. The arguments are literals typed as xsd:string + // 2. The arguments are language literals with identical language tags + // 3. The first argument is a language literal and the second + // argument is a literal typed as xsd:string + + boolean compatible = + + (arg1Simple && arg2Simple) + || (arg1Language && arg2Language && arg1.getLanguage().equals(arg2.getLanguage())) + || (arg1Language && arg2Simple); + + return compatible; + } + + /** + * Checks whether the supplied literal is a "string literal". A "string + * literal" is either a simple literal, a plain literal with language tag, or + * a literal with datatype xsd:string. + * + * @see SPARQL + * Functions on Strings Documentation + */ + public static boolean isStringLiteral(Literal l) { + IRI datatype = l.getDatatype(); + return Literals.isLanguageLiteral(l) || datatype.equals(XMLSchema.STRING); + } + + private static boolean isSupportedDatatype(IRI datatype) { + return (XMLSchema.STRING.equals(datatype) || XMLDatatypeUtil.isNumericDatatype(datatype) || XMLDatatypeUtil.isCalendarDatatype(datatype)); + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryOptimizerList.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryOptimizerList.java new file mode 100644 index 00000000000..3cf3a30770e --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryOptimizerList.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; + +/** + * A query optimizer that contains a list of other query optimizers, which are + * called consecutively when the list's {@link #optimize(TupleExpr, Dataset, BindingSet)} + * method is called. + * + * @author Arjohn Kampman + */ +public class QueryOptimizerList implements QueryOptimizer { + + protected List optimizers; + + public QueryOptimizerList() { + this.optimizers = new ArrayList(8); + } + + public QueryOptimizerList(List optimizers) { + this.optimizers = new ArrayList(optimizers); + } + + public QueryOptimizerList(QueryOptimizer... optimizers) { + this.optimizers = new ArrayList(optimizers.length); + for (QueryOptimizer optimizer : optimizers) { + this.optimizers.add(optimizer); + } + } + + public void add(QueryOptimizer optimizer) { + optimizers.add(optimizer); + } + + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + for (QueryOptimizer optimizer : optimizers) { + optimizer.optimize(tupleExpr, dataset, bindings); + } + } +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java new file mode 100644 index 00000000000..16ba3631548 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import java.util.Comparator; +import java.util.Optional; + +import org.eclipse.rdf4j.common.lang.ObjectUtil; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; + +/** + * A comparator that compares values according the SPARQL value ordering as + * specified in SPARQL Query + * Language for RDF. + * + * @author james + * @author Arjohn Kampman + */ +public class ValueComparator implements Comparator { + + public int compare(Value o1, Value o2) { + // check equality + if (ObjectUtil.nullEquals(o1, o2)) { + return 0; + } + + // 1. (Lowest) no value assigned to the variable + if (o1 == null) { + return -1; + } + if (o2 == null) { + return 1; + } + + // 2. Blank nodes + boolean b1 = o1 instanceof BNode; + boolean b2 = o2 instanceof BNode; + if (b1 && b2) { + return compareBNodes((BNode)o1, (BNode)o2); + } + if (b1) { + return -1; + } + if (b2) { + return 1; + } + + // 3. IRIs + boolean u1 = o1 instanceof IRI; + boolean u2 = o2 instanceof IRI; + if (u1 && u2) { + return compareURIs((IRI)o1, (IRI)o2); + } + if (u1) { + return -1; + } + if (u2) { + return 1; + } + + // 4. RDF literals + return compareLiterals((Literal)o1, (Literal)o2); + } + + private int compareBNodes(BNode leftBNode, BNode rightBNode) { + return leftBNode.getID().compareTo(rightBNode.getID()); + } + + private int compareURIs(IRI leftURI, IRI rightURI) { + return leftURI.toString().compareTo(rightURI.toString()); + } + + private int compareLiterals(Literal leftLit, Literal rightLit) { + // Additional constraint for ORDER BY: "A plain literal is lower + // than an RDF literal with type xsd:string of the same lexical + // form." + if (!(QueryEvaluationUtil.isPlainLiteral(leftLit) || QueryEvaluationUtil.isPlainLiteral(rightLit))) { + try { + boolean isSmaller = QueryEvaluationUtil.compareLiterals(leftLit, rightLit, CompareOp.LT); + + if (isSmaller) { + return -1; + } + else { + boolean isEquivalent = QueryEvaluationUtil.compareLiterals(leftLit, rightLit, CompareOp.EQ); + if (isEquivalent) { + return 0; + } + return 1; + } + } + catch (ValueExprEvaluationException e) { + // literals cannot be compared using the '<' operator, continue + // below + } + } + + int result = 0; + + // FIXME: Confirm these rules work with RDF-1.1 + // Sort by datatype first, plain literals come before datatyped literals + IRI leftDatatype = leftLit.getDatatype(); + IRI rightDatatype = rightLit.getDatatype(); + + if (leftDatatype != null) { + if (rightDatatype != null) { + // Both literals have datatypes + result = compareDatatypes(leftDatatype, rightDatatype); + } + else { + result = 1; + } + } + else if (rightDatatype != null) { + result = -1; + } + + if (result == 0) { + // datatypes are equal or both literals are untyped; sort by language + // tags, simple literals come before literals with language tags + Optional leftLanguage = leftLit.getLanguage(); + Optional rightLanguage = rightLit.getLanguage(); + + if (leftLanguage.isPresent()) { + if (rightLanguage.isPresent()) { + result = leftLanguage.get().compareTo(rightLanguage.get()); + } + else { + result = 1; + } + } + else if (rightLanguage.isPresent()) { + result = -1; + } + } + + if (result == 0) { + // Literals are equal as fas as their datatypes and language tags are + // concerned, compare their labels + result = leftLit.getLabel().compareTo(rightLit.getLabel()); + } + + return result; + } + + /** + * Compares two literal datatypes and indicates if one should be ordered + * after the other. This algorithm ensures that compatible ordered datatypes + * (numeric and date/time) are grouped together so that + * {@link QueryEvaluationUtil#compareLiterals(Literal, Literal, CompareOp)} + * is used in consecutive ordering steps. + */ + private int compareDatatypes(IRI leftDatatype, IRI rightDatatype) { + if (XMLDatatypeUtil.isNumericDatatype(leftDatatype)) { + if (XMLDatatypeUtil.isNumericDatatype(rightDatatype)) { + // both are numeric datatypes + return compareURIs(leftDatatype, rightDatatype); + } + else { + return -1; + } + } + else if (XMLDatatypeUtil.isNumericDatatype(rightDatatype)) { + return 1; + } + else if (XMLDatatypeUtil.isCalendarDatatype(leftDatatype)) { + if (XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) { + // both are calendar datatypes + return compareURIs(leftDatatype, rightDatatype); + } + else { + return -1; + } + } + else if (XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) { + return 1; + } + else { + // incompatible or unordered datatypes + return compareURIs(leftDatatype, rightDatatype); + } + } +} \ No newline at end of file diff --git a/core/queryalgebra/evaluation/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function b/core/queryalgebra/evaluation/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function new file mode 100644 index 00000000000..213ad6bc0ee --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function @@ -0,0 +1,42 @@ +org.openrdf.query.algebra.evaluation.function.StringCast +org.openrdf.query.algebra.evaluation.function.FloatCast +org.openrdf.query.algebra.evaluation.function.DoubleCast +org.openrdf.query.algebra.evaluation.function.DecimalCast +org.openrdf.query.algebra.evaluation.function.IntegerCast +org.openrdf.query.algebra.evaluation.function.BooleanCast +org.openrdf.query.algebra.evaluation.function.DateTimeCast +org.openrdf.query.algebra.evaluation.function.datetime.Day +org.openrdf.query.algebra.evaluation.function.datetime.Hours +org.openrdf.query.algebra.evaluation.function.datetime.Minutes +org.openrdf.query.algebra.evaluation.function.datetime.Month +org.openrdf.query.algebra.evaluation.function.datetime.Now +org.openrdf.query.algebra.evaluation.function.datetime.Seconds +org.openrdf.query.algebra.evaluation.function.datetime.Timezone +org.openrdf.query.algebra.evaluation.function.datetime.Tz +org.openrdf.query.algebra.evaluation.function.datetime.Year +org.openrdf.query.algebra.evaluation.function.hash.MD5 +org.openrdf.query.algebra.evaluation.function.hash.SHA1 +org.openrdf.query.algebra.evaluation.function.hash.SHA256 +org.openrdf.query.algebra.evaluation.function.hash.SHA384 +org.openrdf.query.algebra.evaluation.function.hash.SHA512 +org.openrdf.query.algebra.evaluation.function.numeric.Abs +org.openrdf.query.algebra.evaluation.function.numeric.Ceil +org.openrdf.query.algebra.evaluation.function.numeric.Floor +org.openrdf.query.algebra.evaluation.function.numeric.Rand +org.openrdf.query.algebra.evaluation.function.numeric.Round +org.openrdf.query.algebra.evaluation.function.rdfterm.StrDt +org.openrdf.query.algebra.evaluation.function.rdfterm.StrLang +org.openrdf.query.algebra.evaluation.function.rdfterm.UUID +org.openrdf.query.algebra.evaluation.function.rdfterm.STRUUID +org.openrdf.query.algebra.evaluation.function.string.Concat +org.openrdf.query.algebra.evaluation.function.string.Contains +org.openrdf.query.algebra.evaluation.function.string.EncodeForUri +org.openrdf.query.algebra.evaluation.function.string.LowerCase +org.openrdf.query.algebra.evaluation.function.string.Replace +org.openrdf.query.algebra.evaluation.function.string.StrAfter +org.openrdf.query.algebra.evaluation.function.string.StrBefore +org.openrdf.query.algebra.evaluation.function.string.StrEnds +org.openrdf.query.algebra.evaluation.function.string.StrLen +org.openrdf.query.algebra.evaluation.function.string.StrStarts +org.openrdf.query.algebra.evaluation.function.string.Substring +org.openrdf.query.algebra.evaluation.function.string.UpperCase \ No newline at end of file diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestDateTimeCast.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestDateTimeCast.java new file mode 100644 index 00000000000..5927be40242 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestDateTimeCast.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.DateTimeCast; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class TestDateTimeCast { + + private DateTimeCast dtCast; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + dtCast = new DateTimeCast(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testCastPlainLiteral() { + Literal plainLit = f.createLiteral("1999-09-09T00:00:01"); + try { + Literal result = dtCast.evaluate(f, plainLit); + assertNotNull(result); + assertEquals(XMLSchema.DATETIME, result.getDatatype()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testCastDateLiteral() { + Literal dateLit = f.createLiteral("1999-09-09", XMLSchema.DATE); + try { + Literal result = dtCast.evaluate(f, dateLit); + assertNotNull(result); + assertEquals(XMLSchema.DATETIME, result.getDatatype()); + + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testCastDateTimeLiteral() { + String lexVal = "2000-01-01T00:00:00"; + Literal dtLit = f.createLiteral(XMLDatatypeUtil.parseCalendar(lexVal)); + try { + Literal result = dtCast.evaluate(f, dtLit); + assertNotNull(result); + assertEquals(XMLSchema.DATETIME, result.getDatatype()); + assertFalse(result.getLanguage().isPresent()); + assertEquals(lexVal, result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestIntegerCast.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestIntegerCast.java new file mode 100644 index 00000000000..447968d515e --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestIntegerCast.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.ValueFactoryImpl; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.IntegerCast; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class TestIntegerCast { + + private IntegerCast ic; + + private ValueFactory f = new ValueFactoryImpl(); + + @Before + public void setUp() + throws Exception + { + this.ic = new IntegerCast(); + } + + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testCastDouble() { + Literal dbl = f.createLiteral(100.01d); + try { + Literal result = ic.evaluate(f, dbl); + assertNotNull(result); + assertEquals(XMLSchema.INTEGER, result.getDatatype()); + assertEquals(100, result.intValue()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testCastDoubleWithLargeFraction() { + Literal dbl = f.createLiteral(100.987456d); + try { + Literal result = ic.evaluate(f, dbl); + assertNotNull(result); + assertEquals(XMLSchema.INTEGER, result.getDatatype()); + assertEquals(100, result.intValue()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestStringCast.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestStringCast.java new file mode 100644 index 00000000000..f62fa8ab2af --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/TestStringCast.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.StringCast; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class TestStringCast { + + private StringCast stringCast; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + stringCast = new StringCast(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testCastPlainLiteral() { + Literal plainLit = f.createLiteral("foo"); + try { + Literal result = stringCast.evaluate(f, plainLit); + assertNotNull(result); + assertEquals(XMLSchema.STRING, result.getDatatype()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testCastLangtagLiteral() { + Literal langLit = f.createLiteral("foo", "en"); + try { + Literal result = stringCast.evaluate(f, langLit); + fail("casting of language-tagged literal to xsd:string should result in type error"); + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } + + @Test + public void testCastIntegerLiteral() { + Literal intLit = f.createLiteral(10); + try { + Literal result = stringCast.evaluate(f, intLit); + assertNotNull(result); + assertEquals(XMLSchema.STRING, result.getDatatype()); + assertFalse(result.getLanguage().isPresent()); + assertEquals("10", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testCastDateTimeLiteral() { + String lexVal = "2000-01-01T00:00:00"; + Literal dtLit = f.createLiteral(XMLDatatypeUtil.parseCalendar(lexVal)); + try { + Literal result = stringCast.evaluate(f, dtLit); + assertNotNull(result); + assertEquals(XMLSchema.STRING, result.getDatatype()); + assertFalse(result.getLanguage().isPresent()); + assertEquals(lexVal, result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testCastUnknownDatatypedLiteral() { + String lexVal = "foobar"; + Literal dtLit = f.createLiteral(lexVal, f.createIRI("foo:unknownDt")); + try { + Literal result = stringCast.evaluate(f, dtLit); + assertNotNull(result); + assertEquals(XMLSchema.STRING, result.getDatatype()); + assertFalse(result.getLanguage().isPresent()); + assertEquals(lexVal, result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/TimezoneTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/TimezoneTest.java new file mode 100644 index 00000000000..4cc8f9a31a4 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/TimezoneTest.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.datetime.Timezone; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class TimezoneTest { + + private Timezone timezone; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + timezone = new Timezone(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluate1() { + try { + + Literal result = timezone.evaluate(f, + f.createLiteral("2011-01-10T14:45:13.815-05:00", XMLSchema.DATETIME)); + + assertNotNull(result); + assertEquals(XMLSchema.DAYTIMEDURATION, result.getDatatype()); + + assertEquals("-PT5H", result.getLabel()); + + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() { + try { + + Literal result = timezone.evaluate(f, + f.createLiteral("2011-01-10T14:45:13.815Z", XMLSchema.DATETIME)); + + assertNotNull(result); + assertEquals(XMLSchema.DAYTIMEDURATION, result.getDatatype()); + + assertEquals("PT0S", result.getLabel()); + + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() { + try { + + timezone.evaluate(f, f.createLiteral("2011-01-10T14:45:13.815", XMLSchema.DATETIME)); + + fail("should have resulted in a type error"); + + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/TzTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/TzTest.java new file mode 100644 index 00000000000..5af00327050 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/datetime/TzTest.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.datetime; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.datetime.Tz; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class TzTest { + + private Tz tz; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + tz = new Tz(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluate1() { + try { + + Literal result = tz.evaluate(f, f.createLiteral("2011-01-10T14:45:13.815-05:00", XMLSchema.DATETIME)); + + assertNotNull(result); + assertEquals(XMLSchema.STRING, result.getDatatype()); + + assertEquals("-05:00", result.getLabel()); + + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() { + try { + + Literal result = tz.evaluate(f, f.createLiteral("2011-01-10T14:45:13.815Z", XMLSchema.DATETIME)); + + assertNotNull(result); + assertEquals(XMLSchema.STRING, result.getDatatype()); + + assertEquals("Z", result.getLabel()); + + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() { + try { + + Literal result = tz.evaluate(f, f.createLiteral("2011-01-10T14:45:13.815", XMLSchema.DATETIME)); + + assertNotNull(result); + assertEquals(XMLSchema.STRING, result.getDatatype()); + + assertEquals("", result.getLabel()); + + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/HashFunctionTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/HashFunctionTest.java new file mode 100644 index 00000000000..6dcadea01a7 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/HashFunctionTest.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.hash.HashFunction; +import org.junit.Test; + +/** + * @author jeen + */ +public abstract class HashFunctionTest { + + private HashFunction hashFunction; + + private String toHash; + + private String expectedDigest; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + @Test + public void testEvaluate() { + try { + Literal hash = getHashFunction().evaluate(f, f.createLiteral(getToHash())); + + assertNotNull(hash); + assertEquals(XMLSchema.STRING, hash.getDatatype()); + + assertEquals(hash.getLabel(), getExpectedDigest()); + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() { + try { + Literal hash = getHashFunction().evaluate(f, f.createLiteral(getToHash(), XMLSchema.STRING)); + + assertNotNull(hash); + assertEquals(XMLSchema.STRING, hash.getDatatype()); + + assertEquals(hash.getLabel(), getExpectedDigest()); + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() { + try { + getHashFunction().evaluate(f, f.createLiteral("4", XMLSchema.INTEGER)); + + fail("incompatible operand should have resulted in type error."); + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } + + /** + * @param hashFunction + * The hashFunction to set. + */ + public void setHashFunction(HashFunction hashFunction) { + this.hashFunction = hashFunction; + } + + /** + * @return Returns the hashFunction. + */ + public HashFunction getHashFunction() { + return hashFunction; + } + + /** + * @param expectedDigest + * The expectedDigest to set. + */ + public void setExpectedDigest(String expectedDigest) { + this.expectedDigest = expectedDigest; + } + + /** + * @return Returns the expectedDigest. + */ + public String getExpectedDigest() { + return expectedDigest; + } + + /** + * @param toHash + * The toHash to set. + */ + public void setToHash(String toHash) { + this.toHash = toHash; + } + + /** + * @return Returns the toHash. + */ + public String getToHash() { + return toHash; + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5Test.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5Test.java new file mode 100644 index 00000000000..7ef5583b116 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5Test.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + + +import org.eclipse.rdf4j.query.algebra.evaluation.function.hash.MD5; +import org.junit.Before; + +/** + * @author jeen + */ +public class MD5Test extends HashFunctionTest { + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + setHashFunction(new MD5()); + setToHash("abc"); + setExpectedDigest("900150983cd24fb0d6963f7d28e17f72"); + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1Test.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1Test.java new file mode 100644 index 00000000000..d5da8893895 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1Test.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import org.eclipse.rdf4j.query.algebra.evaluation.function.hash.SHA1; +import org.junit.Before; + +/** + * @author jeen + */ +public class SHA1Test extends HashFunctionTest { + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + setHashFunction(new SHA1()); + setToHash("abc"); + setExpectedDigest("a9993e364706816aba3e25717850c26c9cd0d89d"); + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256Test.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256Test.java new file mode 100644 index 00000000000..005771cc061 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256Test.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import org.eclipse.rdf4j.query.algebra.evaluation.function.hash.SHA256; +import org.junit.Before; + +/** + * @author jeen + */ +public class SHA256Test extends HashFunctionTest { + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + setHashFunction(new SHA256()); + setToHash("abc"); + setExpectedDigest("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384Test.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384Test.java new file mode 100644 index 00000000000..fb8cfb64ecc --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384Test.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import org.eclipse.rdf4j.query.algebra.evaluation.function.hash.SHA384; +import org.junit.Before; + +/** + * @author jeen + */ +public class SHA384Test extends HashFunctionTest { + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + setHashFunction(new SHA384()); + setToHash("abc"); + setExpectedDigest("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"); + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512Test.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512Test.java new file mode 100644 index 00000000000..b60be3b20ef --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512Test.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.hash; + +import org.eclipse.rdf4j.query.algebra.evaluation.function.hash.SHA512; +import org.junit.Before; + +/** + * @author jeen + */ +public class SHA512Test extends HashFunctionTest { + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + setHashFunction(new SHA512()); + setToHash("abc"); + setExpectedDigest("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/RandTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/RandTest.java new file mode 100644 index 00000000000..ab6a0314c3b --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/RandTest.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.numeric; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.numeric.Rand; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class RandTest { + + private Rand rand; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + rand = new Rand(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluate() { + try { + Literal random = rand.evaluate(f); + + assertNotNull(random); + assertEquals(XMLSchema.DOUBLE, random.getDatatype()); + + double randomValue = random.doubleValue(); + + assertTrue(randomValue >= 0.0d); + assertTrue(randomValue < 1.0d); + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/RoundTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/RoundTest.java new file mode 100644 index 00000000000..f980e87136f --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/RoundTest.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.numeric; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.math.BigDecimal; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.numeric.Round; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class RoundTest { + + private Round round; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + round = new Round(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluateDouble() { + try { + double dVal = 1.6; + Literal rounded = round.evaluate(f, f.createLiteral(dVal)); + + double roundValue = rounded.doubleValue(); + + assertEquals((double)2.0, roundValue, 0.001d); + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + public void testEvaluateInt() { + try { + int iVal = 1; + Literal rounded = round.evaluate(f, f.createLiteral(iVal)); + + int roundValue = rounded.intValue(); + + assertEquals(iVal, roundValue); + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + public void testEvaluateBigDecimal() { + try { + BigDecimal bd = new BigDecimal(1234567.567); + + Literal rounded = round.evaluate(f, f.createLiteral(bd.toPlainString(), XMLSchema.DECIMAL)); + + BigDecimal roundValue = rounded.decimalValue(); + + assertEquals(new BigDecimal(1234568.0), roundValue); + } + catch (ValueExprEvaluationException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCaseTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCaseTest.java new file mode 100644 index 00000000000..c4ee8798257 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCaseTest.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.string.LowerCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class LowerCaseTest { + + private LowerCase lcaseFunc; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + lcaseFunc = new LowerCase(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluate1() { + + Literal pattern = f.createLiteral("foobar"); + + try { + Literal result = lcaseFunc.evaluate(f, pattern); + + assertTrue(result.getLabel().equals("foobar")); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() { + + Literal pattern = f.createLiteral("FooBar"); + + try { + Literal result = lcaseFunc.evaluate(f, pattern); + + assertTrue(result.getLabel().equals("foobar")); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() { + + Literal pattern = f.createLiteral("FooBar"); + Literal startIndex = f.createLiteral(4); + + try { + lcaseFunc.evaluate(f, pattern, startIndex); + fail("illegal number of parameters"); + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/RegexTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/RegexTest.java new file mode 100644 index 00000000000..64f0b3e272f --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/RegexTest.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Regex; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolverImpl; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.EmptyTripleSource; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author james + */ +public class RegexTest { + private ValueFactory vf = SimpleValueFactory.getInstance(); + private FederatedServiceResolverImpl serviceResolver; + + @Before + public void setUp() { + serviceResolver = new FederatedServiceResolverImpl(); + } + + @After + public void tearDown() { + serviceResolver.shutDown(); + } + + @Test + public void testEvaluate1() throws QueryEvaluationException { + + Literal expr = vf.createLiteral("foobar"); + Literal pattern = vf.createLiteral("foobar"); + + try { + Literal result = evaluate(expr, pattern); + + assertTrue(result.booleanValue()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() throws QueryEvaluationException { + + Literal expr = vf.createLiteral("foobar"); + Literal pattern = vf.createLiteral("FooBar"); + Literal flags = vf.createLiteral("i"); + + try { + Literal result = evaluate(expr, pattern, flags); + + assertTrue(result.booleanValue()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() throws QueryEvaluationException { + + Literal pattern = vf.createLiteral("FooBar"); + Literal startIndex = vf.createLiteral(4); + + try { + evaluate(pattern, startIndex, startIndex, startIndex); + fail("illegal number of parameters"); + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } + + @Test + public void testEvaluate4() throws QueryEvaluationException { + + Literal expr = vf.createLiteral("foobar", "en"); + Literal pattern = vf.createLiteral("FooBar"); + Literal flags = vf.createLiteral("i"); + + try { + Literal result = evaluate(expr, pattern, flags); + + assertTrue(result.booleanValue()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate5() throws QueryEvaluationException { + + Literal expr = vf.createLiteral("foobar", XMLSchema.STRING); + Literal pattern = vf.createLiteral("FooBar"); + Literal flags = vf.createLiteral("i"); + + try { + Literal result = evaluate(expr, pattern, flags); + + assertTrue(result.booleanValue()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate6() throws QueryEvaluationException { + + Literal expr = vf.createLiteral("foobar", XMLSchema.TOKEN); + Literal pattern = vf.createLiteral("FooBar"); + Literal flags = vf.createLiteral("i"); + + try { + evaluate(expr, pattern, flags); + fail("Regex should not process typed literals"); + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } + + private Literal evaluate(Value... args) throws ValueExprEvaluationException, QueryEvaluationException { + SimpleEvaluationStrategy strategy = new SimpleEvaluationStrategy(new EmptyTripleSource(vf), serviceResolver); + ValueExpr expr = new Var("expr", args[0]); + ValueExpr pattern = new Var("pattern", args[1]); + ValueExpr flags = null; + if (args.length > 2) { + flags = new Var("flags", args[2]); + } + return (Literal)strategy.evaluate(new Regex(expr, pattern, flags), new EmptyBindingSet()); + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/ReplaceTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/ReplaceTest.java new file mode 100644 index 00000000000..f59f972668e --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/ReplaceTest.java @@ -0,0 +1,170 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.string.Replace; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class ReplaceTest { + + private Replace replaceFunc; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + replaceFunc = new Replace(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluate1() { + + Literal arg = f.createLiteral("foobar"); + Literal pattern = f.createLiteral("ba"); + Literal replacement = f.createLiteral("Z"); + + try { + Literal result = replaceFunc.evaluate(f, arg, pattern, replacement); + + assertEquals("fooZr", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() { + + Literal arg = f.createLiteral("foobar"); + Literal pattern = f.createLiteral("BA"); + Literal replacement = f.createLiteral("Z"); + + try { + Literal result = replaceFunc.evaluate(f, arg, pattern, replacement); + + assertEquals("foobar", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() { + + Literal arg = f.createLiteral("foobar"); + Literal pattern = f.createLiteral("BA"); + Literal replacement = f.createLiteral("Z"); + Literal flags = f.createLiteral("i"); + + try { + Literal result = replaceFunc.evaluate(f, arg, pattern, replacement, flags); + + assertEquals("fooZr", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate4() { + + Literal arg = f.createLiteral(10); + Literal pattern = f.createLiteral("BA"); + Literal replacement = f.createLiteral("Z"); + + try { + Literal result = replaceFunc.evaluate(f, arg, pattern, replacement); + + fail("error expected on incompatible operand"); + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } + + @Test + public void testEvaluate5() { + + Literal arg = f.createLiteral("foobarfoobarbarfoo"); + Literal pattern = f.createLiteral("ba"); + Literal replacement = f.createLiteral("Z"); + + try { + Literal result = replaceFunc.evaluate(f, arg, pattern, replacement); + assertEquals("fooZrfooZrZrfoo", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate6() { + + Literal arg = f.createLiteral("foobarfoobarbarfooba"); + Literal pattern = f.createLiteral("ba."); + Literal replacement = f.createLiteral("Z"); + + try { + Literal result = replaceFunc.evaluate(f, arg, pattern, replacement); + assertEquals("fooZfooZZfooba", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate7() { + + Literal arg = f.createLiteral("日本語", "ja"); + Literal pattern = f.createLiteral("[^a-zA-Z0-9]"); + Literal replacement = f.createLiteral("-"); + + try { + Literal result = replaceFunc.evaluate(f, arg, pattern, replacement); + assertEquals("---", result.getLabel()); + assertEquals("ja", result.getLanguage().orElse(null)); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfterTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfterTest.java new file mode 100644 index 00000000000..e30727338b8 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfterTest.java @@ -0,0 +1,262 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.string.StrAfter; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class StrAfterTest { + + private StrAfter strAfterFunc; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + strAfterFunc = new StrAfter(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluate1() { + + Literal leftArg = f.createLiteral("foobar"); + Literal rightArg = f.createLiteral("ba"); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + assertEquals("r", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() { + + Literal leftArg = f.createLiteral("foobar"); + Literal rightArg = f.createLiteral("xyz"); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + assertEquals("", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() { + + Literal leftArg = f.createLiteral("foobar", "en"); + Literal rightArg = f.createLiteral("b"); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + assertEquals("ar", result.getLabel()); + assertEquals("en", result.getLanguage().orElse(null)); + assertEquals(RDF.LANGSTRING, result.getDatatype()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate4() { + + Literal leftArg = f.createLiteral("foobar", XMLSchema.STRING); + Literal rightArg = f.createLiteral("b"); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + assertEquals("ar", result.getLabel()); + assertEquals(XMLSchema.STRING, result.getDatatype()); + + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate4a() { + + Literal leftArg = f.createLiteral("foobar"); + Literal rightArg = f.createLiteral("b", XMLSchema.STRING); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + assertEquals("ar", result.getLabel()); + assertEquals(XMLSchema.STRING, result.getDatatype()); + + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate5() { + + Literal leftArg = f.createLiteral("foobar", XMLSchema.STRING); + Literal rightArg = f.createLiteral("b", XMLSchema.DATE); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + fail("operand with incompatible datatype, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals( + "incompatible operands for STRAFTER: \"foobar\"^^, \"b\"^^", + e.getMessage()); + } + } + + @Test + public void testEvaluate6() { + + Literal leftArg = f.createLiteral(10); + Literal rightArg = f.createLiteral("b"); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + fail("operand with incompatible datatype, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals( + "incompatible operands for STRAFTER: \"10\"^^, \"b\"^^", + e.getMessage()); + } + } + + @Test + public void testEvaluate7() { + + IRI leftArg = f.createIRI("http://example.org/foobar"); + Literal rightArg = f.createLiteral("b"); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + fail("operand of incompatible type, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals( + "incompatible operands for STRAFTER: http://example.org/foobar, \"b\"^^", + e.getMessage()); + } + } + + @Test + public void testEvaluate8() { + Literal leftArg = f.createLiteral("foobar", "en"); + Literal rightArg = f.createLiteral("b", "nl"); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + fail("operand of incompatible type, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals("incompatible operands for STRAFTER: \"foobar\"@en, \"b\"@nl", e.getMessage()); + } + } + + @Test + public void testEvaluate9() { + Literal leftArg = f.createLiteral("foobar"); + Literal rightArg = f.createLiteral("b", "nl"); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + fail("operand of incompatible type, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals( + "incompatible operands for STRAFTER: \"foobar\"^^, \"b\"@nl", + e.getMessage()); + } + } + + @Test + public void testEvaluate10() { + Literal leftArg = f.createLiteral("foobar", "en"); + Literal rightArg = f.createLiteral("b", XMLSchema.STRING); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + assertEquals("ar", result.getLabel()); + assertEquals(RDF.LANGSTRING, result.getDatatype()); + assertEquals("en", result.getLanguage().orElse(null)); + + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate11() { + Literal leftArg = f.createLiteral("foobar", "nl"); + Literal rightArg = f.createLiteral("b", "nl"); + + try { + Literal result = strAfterFunc.evaluate(f, leftArg, rightArg); + + assertEquals("ar", result.getLabel()); + assertEquals(RDF.LANGSTRING, result.getDatatype()); + assertEquals("nl", result.getLanguage().orElse(null)); + + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBeforeTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBeforeTest.java new file mode 100644 index 00000000000..aeee3529523 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBeforeTest.java @@ -0,0 +1,258 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.string.StrBefore; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class StrBeforeTest { + + private StrBefore strBeforeFunc; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + strBeforeFunc = new StrBefore(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluate1() { + + Literal leftArg = f.createLiteral("foobar"); + Literal rightArg = f.createLiteral("ba"); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + assertEquals("foo", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() { + + Literal leftArg = f.createLiteral("foobar"); + Literal rightArg = f.createLiteral("xyz"); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + assertEquals("", result.getLabel()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() { + + Literal leftArg = f.createLiteral("foobar", "en"); + Literal rightArg = f.createLiteral("b"); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + assertEquals("foo", result.getLabel()); + assertEquals("en", result.getLanguage().orElse(null)); + assertEquals(RDF.LANGSTRING, result.getDatatype()); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate4() { + + Literal leftArg = f.createLiteral("foobar", XMLSchema.STRING); + Literal rightArg = f.createLiteral("b"); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + assertEquals("foo", result.getLabel()); + assertEquals(XMLSchema.STRING, result.getDatatype()); + + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate4a() { + + Literal leftArg = f.createLiteral("foobar"); + Literal rightArg = f.createLiteral("b", XMLSchema.STRING); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + assertEquals("foo", result.getLabel()); + assertEquals(XMLSchema.STRING, result.getDatatype()); + + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + + @Test + public void testEvaluate5() { + + Literal leftArg = f.createLiteral("foobar", XMLSchema.STRING); + Literal rightArg = f.createLiteral("b", XMLSchema.DATE); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + fail("operand with incompatible datatype, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals("incompatible operands for STRBEFORE: \"foobar\"^^, \"b\"^^", e.getMessage()); + } + } + + @Test + public void testEvaluate6() { + + Literal leftArg = f.createLiteral(10); + Literal rightArg = f.createLiteral("b"); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + fail("operand with incompatible datatype, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals("incompatible operands for STRBEFORE: \"10\"^^, \"b\"^^", e.getMessage()); + } + } + + + @Test + public void testEvaluate7() { + + IRI leftArg = f.createIRI("http://example.org/foobar"); + Literal rightArg = f.createLiteral("b"); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + fail("operand of incompatible type, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals("incompatible operands for STRBEFORE: http://example.org/foobar, \"b\"^^", e.getMessage()); + } + } + + @Test + public void testEvaluate8() { + Literal leftArg = f.createLiteral("foobar", "en"); + Literal rightArg = f.createLiteral("b", "nl"); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + fail("operand of incompatible type, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals("incompatible operands for STRBEFORE: \"foobar\"@en, \"b\"@nl", e.getMessage()); + } + } + + + @Test + public void testEvaluate9() { + Literal leftArg = f.createLiteral("foobar"); + Literal rightArg = f.createLiteral("b", "nl"); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + fail("operand of incompatible type, should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + assertEquals("incompatible operands for STRBEFORE: \"foobar\"^^, \"b\"@nl", e.getMessage()); + } + } + + @Test + public void testEvaluate10() { + Literal leftArg = f.createLiteral("foobar", "en"); + Literal rightArg = f.createLiteral("b", XMLSchema.STRING); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + assertEquals("foo", result.getLabel()); + assertEquals(RDF.LANGSTRING, result.getDatatype()); + assertEquals("en", result.getLanguage().orElse(null)); + + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate11() { + Literal leftArg = f.createLiteral("foobar", "nl"); + Literal rightArg = f.createLiteral("b", "nl"); + + try { + Literal result = strBeforeFunc.evaluate(f, leftArg, rightArg); + + assertEquals("foo", result.getLabel()); + assertEquals(RDF.LANGSTRING, result.getDatatype()); + assertEquals("nl", result.getLanguage().orElse(null)); + + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/SubstringTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/SubstringTest.java new file mode 100644 index 00000000000..780f7a23d42 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/SubstringTest.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.string.Substring; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class SubstringTest { + + private Substring substrFunc; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + substrFunc = new Substring(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluate1() { + + Literal pattern = f.createLiteral("foobar"); + Literal startIndex = f.createLiteral(4); + + try { + Literal result = substrFunc.evaluate(f, pattern, startIndex); + + assertTrue(result.getLabel().equals("bar")); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() { + + Literal pattern = f.createLiteral("foobar"); + Literal startIndex = f.createLiteral(4); + Literal length = f.createLiteral(2); + + try { + Literal result = substrFunc.evaluate(f, pattern, startIndex, length); + + assertTrue(result.getLabel().equals("ba")); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() { + + Literal pattern = f.createLiteral("foobar"); + Literal startIndex = f.createLiteral(4); + Literal length = f.createLiteral(5); + + try { + substrFunc.evaluate(f, pattern, startIndex, length); + fail("illegal length spec should have resulted in error"); + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } + + + @Test + public void testEvaluate4() { + + Literal pattern = f.createLiteral("foobar"); + + try { + substrFunc.evaluate(f, pattern); + fail("illegal number of args hould have resulted in error"); + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCaseTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCaseTest.java new file mode 100644 index 00000000000..d8e73fd58f9 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCaseTest.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.string.UpperCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author jeen + */ +public class UpperCaseTest { + + private UpperCase ucaseFunc; + + private ValueFactory f = SimpleValueFactory.getInstance(); + + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + ucaseFunc = new UpperCase(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + } + + @Test + public void testEvaluate1() { + + Literal pattern = f.createLiteral("foobar"); + + try { + Literal result = ucaseFunc.evaluate(f, pattern); + + assertTrue(result.getLabel().equals("FOOBAR")); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate2() { + + Literal pattern = f.createLiteral("FooBar"); + + try { + Literal result = ucaseFunc.evaluate(f, pattern); + + assertTrue(result.getLabel().equals("FOOBAR")); + } + catch (ValueExprEvaluationException e) { + fail(e.getMessage()); + } + } + + @Test + public void testEvaluate3() { + + Literal pattern = f.createLiteral("FooBar"); + Literal startIndex = f.createLiteral(4); + + try { + ucaseFunc.evaluate(f, pattern, startIndex); + fail("illegal number of parameters"); + } + catch (ValueExprEvaluationException e) { + // do nothing, expected + } + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizerTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizerTest.java new file mode 100644 index 00000000000..49144d76746 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizerTest.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import static org.junit.Assert.assertEquals; + +import java.util.Set; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.impl.ValueFactoryImpl; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.algebra.QueryRoot; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.BindingAssigner; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.ConstantOptimizer; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.eclipse.rdf4j.query.parser.ParsedQuery; +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.junit.Test; + + +/** + */ +public class ConstantOptimizerTest { + @Test + public void testAndOptimization() throws OpenRDFException { + String query = "prefix ex: " + + "select ?a ?b ?c\n" + + "where {\n" + + " bind((?a && ?b) as ?c) \n" + + "}"; + + QueryBindingSet bs = new QueryBindingSet(); + bs.addBinding("a", ValueFactoryImpl.getInstance().createLiteral(true)); + bs.addBinding("b", ValueFactoryImpl.getInstance().createLiteral(true)); + + testOptimizer(query, bs); + } + + @Test + public void testBoundOptimization() throws OpenRDFException { + String query = "prefix ex: " + + "select ?a ?c\n" + + "where {\n" + + " bind(bound(?a) as ?c) \n" + + "}"; + + QueryBindingSet bs = new QueryBindingSet(); + bs.addBinding("a", ValueFactoryImpl.getInstance().createLiteral("foo")); + + testOptimizer(query, bs); + } + + @Test + public void testFunctionOptimization() throws OpenRDFException { + String query = "prefix ex: " + + "construct {\n" + + "ex:a rdfs:label ?a .\n" + + "ex:b rdfs:label ?b .\n" + + "ex:c rdfs:label ?c .\n" + + "} where {\n" + + " bind(concat(?a, ?b) as ?c) \n" + + "}"; + + QueryBindingSet bs = new QueryBindingSet(); + bs.addBinding("a", ValueFactoryImpl.getInstance().createLiteral("foo")); + bs.addBinding("b", ValueFactoryImpl.getInstance().createLiteral("bah")); + + testOptimizer(query, bs); + } + + private void testOptimizer(String query, BindingSet bs) + throws OpenRDFException + { + ParsedQuery pq = QueryParserUtil.parseQuery(QueryLanguage.SPARQL, query, null); + EvaluationStrategy strategy = new SimpleEvaluationStrategy(new EmptyTripleSource(), null); + TupleExpr opt = optimize(pq.getTupleExpr().clone(), bs, strategy); + Set expected = Iterations.asSet(strategy.evaluate(pq.getTupleExpr(), bs)); + Set actual = Iterations.asSet(strategy.evaluate(opt, EmptyBindingSet.getInstance())); + assertEquals(expected, actual); + } + + private TupleExpr optimize(TupleExpr expr, BindingSet bs, EvaluationStrategy strategy) + { + QueryRoot optRoot = new QueryRoot(expr); + new BindingAssigner().optimize(optRoot, null, bs); + new ConstantOptimizer(strategy).optimize(optRoot, null, bs); + return optRoot; + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EmptyTripleSource.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EmptyTripleSource.java new file mode 100644 index 00000000000..52acc72b9e7 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EmptyTripleSource.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.EmptyIteration; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.TripleSource; + +public class EmptyTripleSource implements TripleSource { + + private final ValueFactory vf; + + public EmptyTripleSource() { + this(SimpleValueFactory.getInstance()); + } + + public EmptyTripleSource(ValueFactory vf) { + this.vf = vf; + } + + @Override + public ValueFactory getValueFactory() { + return vf; + } + + @Override + public CloseableIteration getStatements(Resource subj, + IRI pred, Value obj, Resource... contexts) + throws QueryEvaluationException + { + return new EmptyIteration(); + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizerTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizerTest.java new file mode 100644 index 00000000000..a1d86269107 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizerTest.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import static org.junit.Assert.assertEquals; + +import org.eclipse.rdf4j.OpenRDFException; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.QueryRoot; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryJoinOptimizer; +import org.eclipse.rdf4j.query.parser.ParsedQuery; +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.junit.Test; + + +/** + * Tests to monitor QueryJoinOptimizer behaviour. + * @author Mark + */ +public class QueryJoinOptimizerTest { + @Test + public void testBindingSetAssignmentOptimization() throws OpenRDFException { + String query = "prefix ex: " + + "select ?s ?p ?o ?x where {" + + " ex:s1 ex:pred ?v. " + + " ex:s2 ex:pred 'bah'. {" + + " ?s ?p ?o. " + + " optional {" + + " values ?x {ex:a ex:b ex:c ex:d ex:e ex:f ex:g}. " + + " }" + + " }" + + "}"; + // optimal order should be existence check of first statement + // followed by left join evaluation + String expectedQuery = "prefix ex: " + + "select ?s ?p ?o ?x where {" + + " ex:s2 ex:pred 'bah'. {" + + " ex:s1 ex:pred ?v. {" + + " ?s ?p ?o. " + + " optional {" + + " values ?x {ex:a ex:b ex:c ex:d ex:e ex:f ex:g}. " + + " }" + + " }" + + " }" + + "}"; + + testOptimizer(expectedQuery, query); + } + + @Test(expected=AssertionError.class) + public void testContextOptimization() + throws OpenRDFException + { + String query = "prefix ex: " + + "select ?x ?y ?z ?g ?p ?o where {" + + " graph ?g {" + + " ex:s ?sp ?so. " + + " ?ps ex:p ?po. " + + " ?os ?op 'ex:o'. " + + " }" + + " ?x ?y ?z. " + + "}"; + // optimal order should be ?g graph first + // as it is all statements about a subject in all graphs + // rather than all subjects in the default graph: + // card(?g) << card(?x) + // and assuming named graph has same access cost as default graph + String expectedQuery = "prefix ex: " + + "select ?x ?y ?z ?g ?p ?o where {" + + " graph ?g {" + + " ex:s ?sp ?so. " + + " ?ps ex:p ?po. " + + " ?os ?op 'ex:o'. " + + " }" + + " ?x ?y ?z. " + + "}"; + + testOptimizer(expectedQuery, query); + } + + private void testOptimizer(String expectedQuery, String actualQuery) + throws MalformedQueryException, UnsupportedQueryLanguageException + { + ParsedQuery pq = QueryParserUtil.parseQuery(QueryLanguage.SPARQL, actualQuery, null); + QueryJoinOptimizer opt = new QueryJoinOptimizer(); + QueryRoot optRoot = new QueryRoot(pq.getTupleExpr()); + opt.optimize(optRoot, null, null); + + ParsedQuery expectedParsedQuery = QueryParserUtil.parseQuery(QueryLanguage.SPARQL, expectedQuery, null); + QueryRoot root = new QueryRoot(expectedParsedQuery.getTupleExpr()); + assertQueryModelTrees(root, optRoot); + } + + private void assertQueryModelTrees(QueryModelNode expected, QueryModelNode actual) { + assertEquals(expected, actual); + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BindingSetSize.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BindingSetSize.java new file mode 100644 index 00000000000..3aa0f9ebf04 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BindingSetSize.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; + +class BindingSetSize implements BindingSet { + + private static final long serialVersionUID = -7968068342865378845L; + + private final int size; + + public BindingSetSize(int size) { + super(); + this.size = size; + } + + public Binding getBinding(String bindingName) { + throw new UnsupportedOperationException(); + } + + public Set getBindingNames() { + throw new UnsupportedOperationException(); + } + + public Value getValue(String bindingName) { + throw new UnsupportedOperationException(); + } + + public boolean hasBinding(String bindingName) { + throw new UnsupportedOperationException(); + } + + public Iterator iterator() { + throw new UnsupportedOperationException(); + } + + public int size() { + return size; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + size; + } +} \ No newline at end of file diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIterationTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIterationTest.java new file mode 100644 index 00000000000..f1f40fdb080 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIterationTest.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.Arrays; + +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.ValueFactoryImpl; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.BindingSetAssignment; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.HashJoinIteration; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * + * @author MJAHale + */ +public class HashJoinIterationTest { + private final ValueFactory vf = ValueFactoryImpl.getInstance(); + private final EvaluationStrategy evaluator = new SimpleEvaluationStrategy(null, null); + + @Test + public void testCartesianJoin() throws QueryEvaluationException { + BindingSetAssignment left = new BindingSetAssignment(); + { + QueryBindingSet leftb = new QueryBindingSet(); + leftb.addBinding("a", vf.createLiteral("1")); + left.setBindingSets(Arrays.asList(leftb)); + } + + BindingSetAssignment right = new BindingSetAssignment(); + { + QueryBindingSet rightb = new QueryBindingSet(); + rightb.addBinding("b", vf.createLiteral("2")); + right.setBindingSets(Arrays.asList(rightb)); + } + + HashJoinIteration iter = new HashJoinIteration(evaluator, left, right, EmptyBindingSet.getInstance(), false); + BindingSet actual = iter.next(); + + assertEquals("1", actual.getValue("a").stringValue()); + assertEquals("2", actual.getValue("b").stringValue()); + } + + @Test + public void testInnerJoin() throws QueryEvaluationException { + BindingSetAssignment left = new BindingSetAssignment(); + { + QueryBindingSet leftb = new QueryBindingSet(); + leftb.addBinding("a", vf.createLiteral("1")); + leftb.addBinding("i", vf.createLiteral("x")); + left.setBindingSets(Arrays.asList(leftb)); + } + + BindingSetAssignment right = new BindingSetAssignment(); + { + QueryBindingSet rightb = new QueryBindingSet(); + rightb.addBinding("b", vf.createLiteral("2")); + rightb.addBinding("i", vf.createLiteral("x")); + right.setBindingSets(Arrays.asList(rightb)); + } + + HashJoinIteration iter = new HashJoinIteration(evaluator, left, right, EmptyBindingSet.getInstance(), false); + BindingSet actual = iter.next(); + + assertEquals("1", actual.getValue("a").stringValue()); + assertEquals("2", actual.getValue("b").stringValue()); + assertEquals("x", actual.getValue("i").stringValue()); + } + + @Test + public void testLeftJoin() throws QueryEvaluationException { + BindingSetAssignment left = new BindingSetAssignment(); + { + QueryBindingSet leftb = new QueryBindingSet(); + leftb.addBinding("a", vf.createLiteral("1")); + leftb.addBinding("i", vf.createLiteral("x")); + left.setBindingSets(Arrays.asList(leftb)); + } + + BindingSetAssignment right = new BindingSetAssignment(); + { + QueryBindingSet rightb = new QueryBindingSet(); + rightb.addBinding("b", vf.createLiteral("2")); + rightb.addBinding("i", vf.createLiteral("y")); + right.setBindingSets(Arrays.asList(rightb)); + } + + HashJoinIteration iter = new HashJoinIteration(evaluator, left, right, EmptyBindingSet.getInstance(), true); + BindingSet actual = iter.next(); + + assertEquals("1", actual.getValue("a").stringValue()); + assertEquals("x", actual.getValue("i").stringValue()); + assertFalse(actual.hasBinding("b")); + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/IterationStub.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/IterationStub.java new file mode 100644 index 00000000000..2ae831fc77f --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/IterationStub.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.io.Serializable; +import java.util.Iterator; + +import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; + +class IterationStub extends CloseableIteratorIteration implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + int hasNextCount = 0; + + int nextCount = 0; + + int removeCount = 0; + + @Override + public void setIterator(Iterator iter) { + super.setIterator(iter); + } + + @Override + public boolean hasNext() + throws QueryEvaluationException + { + hasNextCount++; + return super.hasNext(); + } + + @Override + public BindingSet next() + throws QueryEvaluationException + { + nextCount++; + return super.next(); + } + + @Override + public void remove() { + removeCount++; + } +} \ No newline at end of file diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIteratorTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIteratorTest.java new file mode 100644 index 00000000000..235c44596f7 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIteratorTest.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.ValueFactoryImpl; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.BindingSetAssignment; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.SimpleEvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.JoinIterator; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.junit.Test; + +/** + * + * @author MJAHale + */ +public class JoinIteratorTest { + private final ValueFactory vf = ValueFactoryImpl.getInstance(); + private final EvaluationStrategy evaluator = new SimpleEvaluationStrategy(null, null); + + /** + * Tests joins between two different BindingSetAssignments with the same BindingSets but ordered differently. + */ + @Test + public void testBindingSetAssignmentJoin() throws QueryEvaluationException { + testBindingSetAssignmentJoin(5, 5, EmptyBindingSet.getInstance()); + + { + QueryBindingSet b = new QueryBindingSet(); + b.addBinding("a", vf.createLiteral(2)); + testBindingSetAssignmentJoin(1, 5, b); + } + + { + QueryBindingSet b = new QueryBindingSet(); + b.addBinding("x", vf.createLiteral("foo")); + testBindingSetAssignmentJoin(5, 5, b); + } + } + + private void testBindingSetAssignmentJoin(int expectedSize, int n, BindingSet bindings) throws QueryEvaluationException { + BindingSetAssignment left = new BindingSetAssignment(); + { + List leftb = new ArrayList(); + for(int i=0; i rightb = new ArrayList(); + for(int i=n; i>=0; i--) + { + QueryBindingSet b = new QueryBindingSet(); + b.addBinding("a", vf.createLiteral(i)); + rightb.add(b); + } + right.setBindingSets(rightb); + } + + JoinIterator lrIter = new JoinIterator(evaluator, new Join(left, right), bindings); + Set lr = Iterations.asSet(lrIter); + assertEquals(expectedSize, lr.size()); + + JoinIterator rlIter = new JoinIterator(evaluator, new Join(right, left), bindings); + Set rl = Iterations.asSet(rlIter); + assertEquals(expectedSize, rl.size()); + + assertEquals(lr, rl); + + // check bindings + for(BindingSet b : lr) { + for(String name : bindings.getBindingNames()) { + assertEquals(bindings.getValue(name), b.getValue(name)); + } + } + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIteratorTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIteratorTest.java new file mode 100644 index 00000000000..ba74ddaf47e --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIteratorTest.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.iterator.OrderIterator; + +import junit.framework.TestCase; + + +/** + * + * @author james + * + */ +public class OrderIteratorTest extends TestCase { + class IterationStub extends + CloseableIteratorIteration { + int hasNextCount = 0; + + int nextCount = 0; + + int removeCount = 0; + + @Override + public void setIterator(Iterator iter) { + super.setIterator(iter); + } + + @Override + public boolean hasNext() throws QueryEvaluationException { + hasNextCount++; + return super.hasNext(); + } + + @Override + public BindingSet next() throws QueryEvaluationException { + nextCount++; + return super.next(); + } + + @Override + public void remove() { + removeCount++; + } + } + + class SizeComparator implements Comparator { + public int compare(BindingSet o1, BindingSet o2) { + return Integer.valueOf(o1.size()).compareTo( + Integer.valueOf(o2.size())); + } + } + + class BindingSetSize implements BindingSet { + + private static final long serialVersionUID = -7968068342865378845L; + + private final int size; + + public BindingSetSize(int size) { + super(); + this.size = size; + } + + public Binding getBinding(String bindingName) { + throw new UnsupportedOperationException(); + } + + public Set getBindingNames() { + throw new UnsupportedOperationException(); + } + + public Value getValue(String bindingName) { + throw new UnsupportedOperationException(); + } + + public boolean hasBinding(String bindingName) { + throw new UnsupportedOperationException(); + } + + public Iterator iterator() { + throw new UnsupportedOperationException(); + } + + public int size() { + return size; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + size; + } + } + + private IterationStub iteration; + + private OrderIterator order; + + private List list; + + private BindingSet b1 = new BindingSetSize(1); + + private BindingSet b2 = new BindingSetSize(2); + + private BindingSet b3 = new BindingSetSize(3); + + private BindingSet b4 = new BindingSetSize(4); + + private BindingSet b5 = new BindingSetSize(5); + + private SizeComparator cmp; + + public void testFirstHasNext() throws Exception { + order.hasNext(); + assertEquals(list.size() + 1, iteration.hasNextCount); + assertEquals(list.size(), iteration.nextCount); + assertEquals(0, iteration.removeCount); + } + + public void testHasNext() throws Exception { + order.hasNext(); + order.next(); + order.hasNext(); + assertEquals(list.size() + 1, iteration.hasNextCount); + assertEquals(list.size(), iteration.nextCount); + assertEquals(0, iteration.removeCount); + } + + public void testFirstNext() throws Exception { + order.next(); + assertEquals(list.size() + 1, iteration.hasNextCount); + assertEquals(list.size(), iteration.nextCount); + assertEquals(0, iteration.removeCount); + } + + public void testNext() throws Exception { + order.next(); + order.next(); + assertEquals(list.size() + 1, iteration.hasNextCount); + assertEquals(list.size(), iteration.nextCount); + assertEquals(0, iteration.removeCount); + } + + public void testRemove() throws Exception { + try { + order.remove(); + fail(); + } catch (UnsupportedOperationException e) { + } + + } + + public void testSorting() throws Exception { + List sorted = new ArrayList(list); + Collections.sort(sorted, cmp); + for (BindingSet b : sorted) { + assertEquals(b, order.next()); + } + assertFalse(order.hasNext()); + } + + @Override + protected void setUp() throws Exception { + list = Arrays.asList(b3, b5, b2, b1, b4, b2); + cmp = new SizeComparator(); + iteration = new IterationStub(); + iteration.setIterator(list.iterator()); + order = new OrderIterator(iteration, cmp); + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SizeComparator.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SizeComparator.java new file mode 100644 index 00000000000..8b019ef6336 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SizeComparator.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.iterator; + +import java.io.Serializable; +import java.util.Comparator; + +import org.eclipse.rdf4j.query.BindingSet; + +class SizeComparator implements Comparator, Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public int compare(BindingSet o1, BindingSet o2) { + return Integer.valueOf(o1.size()).compareTo(Integer.valueOf(o2.size())); + } +} \ No newline at end of file diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/LiteralComparatorTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/LiteralComparatorTest.java new file mode 100644 index 00000000000..1df483e2b44 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/LiteralComparatorTest.java @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator; +import org.junit.Before; +import org.junit.Test; + +/** + * + * @author james + * + */ +public class LiteralComparatorTest { + + private ValueFactory vf = SimpleValueFactory.getInstance(); + + private Literal one = vf.createLiteral(1); + + private Literal ten = vf.createLiteral(10); + + private Literal a = vf.createLiteral("a"); + + private Literal b = vf.createLiteral("b"); + + private Literal la = vf.createLiteral("a", "en"); + + private Literal lb = vf.createLiteral("b", "en"); + + private Literal lf = vf.createLiteral("a", "fr"); + + private Literal f = vf.createLiteral(false); + + private Literal t = vf.createLiteral(true); + + private Literal date1; + + private Literal date2; + + private Literal simple1 = vf.createLiteral("http://script.example/Latin"); + + private Literal simple2 = vf.createLiteral("http://script.example/Кириллица"); + + private Literal typed1 = vf.createLiteral("http://script.example/Latin", XMLSchema.STRING); + + private ValueComparator cmp = new ValueComparator(); + + @Test + public void testNumeric() + throws Exception + { + assertTrue(cmp.compare(one, one) == 0); + assertTrue(cmp.compare(one, ten) < 0); + assertTrue(cmp.compare(ten, one) > 0); + assertTrue(cmp.compare(ten, ten) == 0); + } + + @Test + public void testString() + throws Exception + { + assertTrue(cmp.compare(a, a) == 0); + assertTrue(cmp.compare(a, b) < 0); + assertTrue(cmp.compare(b, a) > 0); + assertTrue(cmp.compare(b, b) == 0); + } + + @Test + public void testSameLanguage() + throws Exception + { + assertTrue(cmp.compare(la, la) == 0); + assertTrue(cmp.compare(la, lb) < 0); + assertTrue(cmp.compare(lb, la) > 0); + assertTrue(cmp.compare(lb, lb) == 0); + } + + @Test + public void testDifferentLanguage() + throws Exception + { + cmp.compare(la, lf); + } + + @Test + public void testBoolean() + throws Exception + { + assertTrue(cmp.compare(f, f) == 0); + assertTrue(cmp.compare(f, t) < 0); + assertTrue(cmp.compare(t, f) > 0); + assertTrue(cmp.compare(t, t) == 0); + } + + @Test + public void testDateTime() + throws Exception + { + assertTrue(cmp.compare(date1, date1) == 0); + assertTrue(cmp.compare(date1, date2) < 0); + assertTrue(cmp.compare(date2, date1) > 0); + assertTrue(cmp.compare(date2, date2) == 0); + } + + @Test + public void testBothSimple() + throws Exception + { + assertTrue(cmp.compare(simple1, simple1) == 0); + assertTrue(cmp.compare(simple1, simple2) < 0); + assertTrue(cmp.compare(simple2, simple1) > 0); + assertTrue(cmp.compare(simple2, simple2) == 0); + } + + @Test + public void testLeftSimple() + throws Exception + { + assertTrue(cmp.compare(simple1, typed1) == 0); + } + + @Test + public void testRightSimple() + throws Exception + { + assertTrue(cmp.compare(typed1, simple1) == 0); + } + + @Test + public void testOrder() + throws Exception + { + Literal en4 = vf.createLiteral("4", "en"); + Literal nine = vf.createLiteral(9); + List list = new ArrayList(); + list.add(ten); + list.add(en4); + list.add(nine); + Collections.sort(list, cmp); + assertTrue(list.indexOf(nine) < list.indexOf(ten)); + } + + @Before + public void setUp() + throws Exception + { + DatatypeFactory factory = DatatypeFactory.newInstance(); + XMLGregorianCalendar mar = factory.newXMLGregorianCalendar("2000-03-04T20:00:00Z"); + XMLGregorianCalendar oct = factory.newXMLGregorianCalendar("2002-10-10T12:00:00-05:00"); + date1 = vf.createLiteral(mar); + date2 = vf.createLiteral(oct); + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparatorTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparatorTest.java new file mode 100644 index 00000000000..6e844370420 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparatorTest.java @@ -0,0 +1,209 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Iterator; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.impl.ValueFactoryImpl; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Order; +import org.eclipse.rdf4j.query.algebra.OrderElem; +import org.eclipse.rdf4j.query.algebra.Service; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedService; +import org.eclipse.rdf4j.query.algebra.evaluation.util.OrderComparator; +import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator; +import org.junit.Before; +import org.junit.Test; + +/** + * @author james + */ +public class OrderComparatorTest { + + class EvaluationStrategyStub implements EvaluationStrategy { + + public CloseableIteration evaluate(Service expr, + String serviceUri, CloseableIteration bindings) + throws QueryEvaluationException + { + throw new UnsupportedOperationException(); + } + + public CloseableIteration evaluate(TupleExpr expr, + BindingSet bindings) + throws QueryEvaluationException + { + throw new UnsupportedOperationException(); + } + + public Value evaluate(ValueExpr expr, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + return null; + } + + public boolean isTrue(ValueExpr expr, BindingSet bindings) + throws ValueExprEvaluationException, QueryEvaluationException + { + throw new UnsupportedOperationException(); + } + + public FederatedService getService(String serviceUrl) + throws QueryEvaluationException + { + throw new UnsupportedOperationException(); + } + } + + class ComparatorStub extends ValueComparator { + + Iterator iter; + + public void setIterator(Iterator iter) { + this.iter = iter; + } + + @Override + public int compare(Value o1, Value o2) { + return iter.next(); + } + } + + private EvaluationStrategyStub strategy = new EvaluationStrategyStub(); + + private Order order = new Order(); + + private OrderElem asc = new OrderElem(); + + private OrderElem desc = new OrderElem(); + + private ComparatorStub cmp = new ComparatorStub(); + + private int ZERO = 0; + + private int POS = 378; + + private int NEG = -7349; + + @Test + public void testEquals() + throws Exception + { + order.addElement(asc); + cmp.setIterator(Arrays.asList(ZERO).iterator()); + OrderComparator sud = new OrderComparator(strategy, order, cmp); + assertTrue(sud.compare(null, null) == 0); + } + + @Test + public void testZero() + throws Exception + { + order.addElement(asc); + order.addElement(asc); + cmp.setIterator(Arrays.asList(ZERO, POS).iterator()); + OrderComparator sud = new OrderComparator(strategy, order, cmp); + assertTrue(sud.compare(null, null) > 0); + } + + @Test + public void testTerm() + throws Exception + { + order.addElement(asc); + order.addElement(asc); + cmp.setIterator(Arrays.asList(POS, NEG).iterator()); + OrderComparator sud = new OrderComparator(strategy, order, cmp); + assertTrue(sud.compare(null, null) > 0); + } + + @Test + public void testAscLessThan() + throws Exception + { + order.addElement(asc); + cmp.setIterator(Arrays.asList(NEG).iterator()); + OrderComparator sud = new OrderComparator(strategy, order, cmp); + assertTrue(sud.compare(null, null) < 0); + } + + @Test + public void testAscGreaterThan() + throws Exception + { + order.addElement(asc); + cmp.setIterator(Arrays.asList(POS).iterator()); + OrderComparator sud = new OrderComparator(strategy, order, cmp); + assertTrue(sud.compare(null, null) > 0); + } + + @Test + public void testDescLessThan() + throws Exception + { + order.addElement(desc); + cmp.setIterator(Arrays.asList(NEG).iterator()); + OrderComparator sud = new OrderComparator(strategy, order, cmp); + assertTrue(sud.compare(null, null) > 0); + } + + @Test + public void testDescGreaterThan() + throws Exception + { + order.addElement(desc); + cmp.setIterator(Arrays.asList(POS).iterator()); + OrderComparator sud = new OrderComparator(strategy, order, cmp); + assertTrue(sud.compare(null, null) < 0); + } + + @Test + public void testDisjunctBindingNames() + throws Exception + { + OrderComparator sud = new OrderComparator(strategy, order, cmp); + QueryBindingSet a = new QueryBindingSet(); + QueryBindingSet b = new QueryBindingSet(); + a.addBinding("a", ValueFactoryImpl.getInstance().createLiteral("a")); + b.addBinding("b", ValueFactoryImpl.getInstance().createLiteral("b")); + assertTrue(sud.compare(a, b) != 0); + assertTrue(sud.compare(a, b) != sud.compare(b, a)); + } + + @Test + public void testEqualBindingNamesUnequalValues() { + OrderComparator sud = new OrderComparator(strategy, order, new ValueComparator()); + QueryBindingSet a = new QueryBindingSet(); + QueryBindingSet b = new QueryBindingSet(); + a.addBinding("a", ValueFactoryImpl.getInstance().createLiteral("ab")); + a.addBinding("b", ValueFactoryImpl.getInstance().createLiteral("b")); + b.addBinding("b", ValueFactoryImpl.getInstance().createLiteral("b")); + b.addBinding("a", ValueFactoryImpl.getInstance().createLiteral("ac")); + assertTrue(sud.compare(a, b) < 0); + assertTrue(sud.compare(a, b) != sud.compare(b, a)); + } + + @Before + public void setUp() + throws Exception + { + asc.setAscending(true); + desc.setAscending(false); + } +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtilTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtilTest.java new file mode 100644 index 00000000000..284ab8cd8ba --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtilTest.java @@ -0,0 +1,258 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import static org.eclipse.rdf4j.query.algebra.Compare.CompareOp.*; +import static org.junit.Assert.*; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; +import org.junit.Before; +import org.junit.Test; + +/** + * @author Jeen Broekstra + */ +public class QueryEvaluationUtilTest { + + private ValueFactory f = SimpleValueFactory.getInstance(); + + private Literal arg1simple; + + private Literal arg2simple; + + private Literal arg1en; + + private Literal arg2en; + + private Literal arg1cy; + + private Literal arg2cy; + + private Literal arg1string; + + private Literal arg2string; + + private Literal arg1int; + + private Literal arg2int; + + private Literal arg1year; + + private Literal arg2year; + + @Before + public void setUp() + throws Exception + { + arg1simple = f.createLiteral("abc"); + arg2simple = f.createLiteral("b"); + + arg1en = f.createLiteral("abc", "en"); + arg2en = f.createLiteral("b", "en"); + + arg1cy = f.createLiteral("abc", "cy"); + arg2cy = f.createLiteral("b", "cy"); + + arg1string = f.createLiteral("abc", XMLSchema.STRING); + arg2string = f.createLiteral("b", XMLSchema.STRING); + + arg1year = f.createLiteral("2007", XMLSchema.GYEAR); + arg2year = f.createLiteral("2009", XMLSchema.GYEAR); + + arg1int = f.createLiteral(10); + arg2int = f.createLiteral(1); + } + + @Test + public void testCompatibleArguments() + throws Exception + { + + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1simple, arg2simple)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1simple, arg2en)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1simple, arg2cy)); + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1simple, arg2string)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1simple, arg2int)); + + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1en, arg2simple)); + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1en, arg2en)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg2en, arg2cy)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1en, arg2cy)); + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1en, arg2string)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1en, arg2int)); + + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1cy, arg2simple)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1cy, arg2en)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg2cy, arg2en)); + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1cy, arg2cy)); + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1cy, arg2string)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1cy, arg2int)); + + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1string, arg2simple)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1string, arg2en)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1string, arg2cy)); + assertTrue(QueryEvaluationUtil.compatibleArguments(arg1string, arg2string)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1string, arg2int)); + + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1int, arg2simple)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1int, arg2en)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1int, arg2cy)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1int, arg2string)); + assertFalse(QueryEvaluationUtil.compatibleArguments(arg1int, arg2int)); + + } + + @Test + public void testCompareEQ() + throws Exception + { + assertCompareFalse(arg1simple, arg2simple, EQ); + assertCompareFalse(arg1simple, arg2en, EQ); + assertCompareFalse(arg1simple, arg2cy, EQ); + assertCompareFalse(arg1simple, arg2string, EQ); + assertCompareException(arg1simple, arg2int, EQ); + assertCompareException(arg1simple, arg2year, EQ); + + assertCompareFalse(arg1en, arg2simple, EQ); + assertCompareFalse(arg1en, arg2en, EQ); + assertCompareFalse(arg2en, arg2cy, EQ); + assertCompareFalse(arg1en, arg2cy, EQ); + assertCompareFalse(arg1en, arg2string, EQ); + assertCompareFalse(arg1en, arg2int, EQ); + + assertCompareFalse(arg1cy, arg2simple, EQ); + assertCompareFalse(arg1cy, arg2en, EQ); + assertCompareFalse(arg2cy, arg2en, EQ); + assertCompareFalse(arg1cy, arg2cy, EQ); + assertCompareFalse(arg1cy, arg2string, EQ); + assertCompareFalse(arg1cy, arg2int, EQ); + + assertCompareFalse(arg1string, arg2simple, EQ); + assertCompareFalse(arg1string, arg2en, EQ); + assertCompareFalse(arg1string, arg2cy, EQ); + assertCompareFalse(arg1string, arg2string, EQ); + assertCompareException(arg1string, arg2int, EQ); + assertCompareException(arg1string, arg2year, EQ); + + assertCompareException(arg1int, arg2simple, EQ); + assertCompareFalse(arg1int, arg2en, EQ); + assertCompareFalse(arg1int, arg2cy, EQ); + assertCompareException(arg1int, arg2string, EQ); + assertCompareFalse(arg1int, arg2int, EQ); + assertCompareException(arg1int, arg2year, EQ); + + } + + @Test + public void testCompareNE() + throws Exception + { + assertCompareTrue(arg1simple, arg2simple, NE); + assertCompareTrue(arg1simple, arg2en, NE); + assertCompareTrue(arg1simple, arg2cy, NE); + assertCompareTrue(arg1simple, arg2string, NE); + assertCompareException(arg1simple, arg2int, NE); + assertCompareException(arg1simple, arg2year, NE); + + assertCompareTrue(arg1en, arg2simple, NE); + assertCompareTrue(arg1en, arg2en, NE); + assertCompareTrue(arg2en, arg2cy, NE); + assertCompareTrue(arg1en, arg2cy, NE); + assertCompareTrue(arg1en, arg2string, NE); + assertCompareTrue(arg1en, arg2int, NE); + + assertCompareTrue(arg1cy, arg2simple, NE); + assertCompareTrue(arg1cy, arg2en, NE); + assertCompareTrue(arg2cy, arg2en, NE); + assertCompareTrue(arg1cy, arg2cy, NE); + assertCompareTrue(arg1cy, arg2string, NE); + assertCompareTrue(arg1cy, arg2int, NE); + + assertCompareTrue(arg1string, arg2simple, NE); + assertCompareTrue(arg1string, arg2en, NE); + assertCompareTrue(arg1string, arg2cy, NE); + assertCompareTrue(arg1string, arg2string, NE); + assertCompareException(arg1string, arg2int, NE); + assertCompareException(arg1string, arg2year, NE); + + assertCompareException(arg1int, arg2simple, NE); + assertCompareTrue(arg1int, arg2en, NE); + assertCompareTrue(arg1int, arg2cy, NE); + assertCompareException(arg1int, arg2string, NE); + assertCompareTrue(arg1int, arg2int, NE); + assertCompareException(arg1int, arg2year, NE); + + } + + /** + * Assert that there is an exception as a result of comparing the two + * literals with the given operator. + * + * @param lit1 + * The left literal + * @param lit2 + * The right literal + * @param op + * The operator for the comparison + */ + private void assertCompareException(Literal lit1, Literal lit2, CompareOp op) + throws Exception + { + try { + boolean returnValue = QueryEvaluationUtil.compareLiterals(lit1, lit2, op); + fail("Did not receive expected ValueExprEvaluationException (return value was " + returnValue + + ") for " + lit1.toString() + op.getSymbol() + lit2.toString()); + } + catch (ValueExprEvaluationException e) { + // Expected exception + } + } + + /** + * Assert that there is no exception as a result of comparing the two + * literals with the given operator and it returns false. + * + * @param lit1 + * The left literal + * @param lit2 + * The right literal + * @param op + * The operator for the comparison + */ + private void assertCompareFalse(Literal lit1, Literal lit2, CompareOp op) + throws Exception + { + assertFalse("Compare did not return false for " + lit1.toString() + op.getSymbol() + lit2.toString(), + QueryEvaluationUtil.compareLiterals(lit1, lit2, op)); + } + + /** + * Assert that there is no exception as a result of comparing the two + * literals with the given operator and it returns true. + * + * @param lit1 + * The left literal + * @param lit2 + * The right literal + * @param op + * The operator for the comparison + */ + private void assertCompareTrue(Literal lit1, Literal lit2, CompareOp op) + throws Exception + { + assertTrue("Compare did not return true for " + lit1.toString() + op.getSymbol() + lit2.toString(), + QueryEvaluationUtil.compareLiterals(lit1, lit2, op)); + } + +} diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparatorTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparatorTest.java new file mode 100644 index 00000000000..fdc4fd4dedf --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparatorTest.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.util; + +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator; +import org.junit.Test; + +/** + * + * @author james + * + */ +public class ValueComparatorTest { + + private ValueFactory vf = SimpleValueFactory.getInstance(); + + private BNode bnode1 = vf.createBNode(); + + private BNode bnode2 = vf.createBNode(); + + private IRI uri1 = vf.createIRI("http://script.example/Latin"); + + private IRI uri2 = vf.createIRI("http://script.example/Кириллица"); + + private IRI uri3 = vf.createIRI("http://script.example/日本語"); + + private Literal typed1 = vf.createLiteral("http://script.example/Latin", XMLSchema.STRING); + + private ValueComparator cmp = new ValueComparator(); + + @Test + public void testBothNull() + throws Exception + { + assertTrue(cmp.compare(null, null) == 0); + } + + @Test + public void testLeftNull() + throws Exception + { + assertTrue(cmp.compare(null, typed1) < 0); + } + + @Test + public void testRightNull() + throws Exception + { + assertTrue(cmp.compare(typed1, null) > 0); + } + + @Test + public void testBothBnode() + throws Exception + { + assertTrue(cmp.compare(bnode1, bnode1) == 0); + assertTrue(cmp.compare(bnode2, bnode2) == 0); + assertTrue(cmp.compare(bnode1, bnode2) != cmp.compare(bnode2, bnode1)); + assertTrue(cmp.compare(bnode1, bnode2) == -1 * cmp.compare(bnode2, bnode1)); + } + + @Test + public void testLeftBnode() + throws Exception + { + assertTrue(cmp.compare(bnode1, typed1) < 0); + } + + @Test + public void testRightBnode() + throws Exception + { + assertTrue(cmp.compare(typed1, bnode1) > 0); + } + + @Test + public void testBothURI() + throws Exception + { + assertTrue(cmp.compare(uri1, uri1) == 0); + assertTrue(cmp.compare(uri1, uri2) < 0); + assertTrue(cmp.compare(uri1, uri3) < 0); + assertTrue(cmp.compare(uri2, uri1) > 0); + assertTrue(cmp.compare(uri2, uri2) == 0); + assertTrue(cmp.compare(uri2, uri3) < 0); + assertTrue(cmp.compare(uri3, uri1) > 0); + assertTrue(cmp.compare(uri3, uri2) > 0); + assertTrue(cmp.compare(uri3, uri3) == 0); + } + + @Test + public void testLeftURI() + throws Exception + { + assertTrue(cmp.compare(uri1, typed1) < 0); + } + + @Test + public void testRightURI() + throws Exception + { + assertTrue(cmp.compare(typed1, uri1) > 0); + } + + /** + * Tests whether xsd:int's are properly sorted in a list with mixed value + * types. + */ + @Test + public void testOrder1() + throws Exception + { + Literal en4 = vf.createLiteral("4", "en"); + Literal int10 = vf.createLiteral(10); + Literal int9 = vf.createLiteral(9); + + List valueList = Arrays.asList(en4, int10, int9); + Collections.sort(valueList, cmp); + + assertTrue(valueList.indexOf(int9) < valueList.indexOf(int10)); + } + + /** + * Tests whether various numerics are properly sorted in a list with mixed + * value types. + */ + @Test + public void testOrder2() + throws Exception + { + Literal en4 = vf.createLiteral("4", "en"); + Literal int10 = vf.createLiteral(10); + Literal int9 = vf.createLiteral(9); + Literal plain9 = vf.createLiteral("9"); + Literal integer5 = vf.createLiteral("5", XMLSchema.INTEGER); + Literal float9 = vf.createLiteral(9f); + Literal plain4 = vf.createLiteral("4"); + Literal plain10 = vf.createLiteral("10"); + + List valueList = Arrays.asList(en4, int10, int9, plain9, integer5, float9, plain4, plain10); + Collections.sort(valueList, cmp); + + assertTrue(valueList.indexOf(integer5) < valueList.indexOf(float9)); + assertTrue(valueList.indexOf(integer5) < valueList.indexOf(int9)); + assertTrue(valueList.indexOf(integer5) < valueList.indexOf(int10)); + assertTrue(valueList.indexOf(float9) < valueList.indexOf(int10)); + assertTrue(valueList.indexOf(int9) < valueList.indexOf(int10)); + assertTrue(valueList.indexOf(int9) < valueList.indexOf(int10)); + } + + /** + * Tests whether numerics of different types are properly sorted. The list + * also contains a datatype that would be sorted between the numerics if the + * datatypes were to be sorted alphabetically. + */ + @Test + public void testOrder3() + throws Exception + { + Literal year1234 = vf.createLiteral("1234", XMLSchema.GYEAR); + Literal float2000 = vf.createLiteral(2000f); + Literal int1000 = vf.createLiteral(1000); + + List valueList = Arrays.asList(year1234, float2000, int1000); + Collections.sort(valueList, cmp); + assertTrue(valueList.indexOf(int1000) < valueList.indexOf(float2000)); + } +} diff --git a/core/queryalgebra/evaluation/src/test/resources/logback-test.xml b/core/queryalgebra/evaluation/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..4a6f17fbfa4 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + diff --git a/core/queryalgebra/geosparql/pom.xml b/core/queryalgebra/geosparql/pom.xml new file mode 100644 index 00000000000..89d20bd5f44 --- /dev/null +++ b/core/queryalgebra/geosparql/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-queryalgebra + 4.1.0-SNAPSHOT + + + rdf4j-queryalgebra-geosparql + + RDF4J: Query algebra - GeoSPARQL + Query algbebra implementations to support the evaluation of GeoSPARQL. + + + + ${project.groupId} + rdf4j-queryalgebra-evaluation + ${project.version} + + + com.spatial4j + spatial4j + + + + junit + junit + + + + diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Boundary.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Boundary.java new file mode 100644 index 00000000000..f13c770297a --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Boundary.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:boundary, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class Boundary extends GeometricUnaryFunction { + + @Override + public String getURI() { + return GEOF.BOUNDARY.stringValue(); + } + + @Override + protected Shape operation(Shape s) { + return SpatialSupport.getSpatialAlgebra().boundary(s); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Buffer.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Buffer.java new file mode 100644 index 00000000000..40392f41876 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Buffer.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import java.io.IOException; + +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.GEO; +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:buffer, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class Buffer implements Function { + + @Override + public String getURI() { + return GEOF.BUFFER.stringValue(); + } + + @Override + public Value evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 3) { + throw new ValueExprEvaluationException(getURI() + " requires exactly 3 arguments, got " + + args.length); + } + + SpatialContext geoContext = SpatialSupport.getSpatialContext(); + Shape geom = FunctionArguments.getShape(this, args[0], geoContext); + double radiusUom = FunctionArguments.getDouble(this, args[1]); + URI units = FunctionArguments.getUnits(this, args[2]); + double radiusDegs = FunctionArguments.convertToDegrees(radiusUom, units); + + Shape buffered = geom.getBuffered(radiusDegs, geoContext); + + String wkt; + try { + wkt = SpatialSupport.getWktWriter().toWkt(buffered); + } + catch (IOException ioe) { + throw new ValueExprEvaluationException(ioe); + } + return valueFactory.createLiteral(wkt, GEO.WKT_LITERAL); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/ConvexHull.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/ConvexHull.java new file mode 100644 index 00000000000..238758839cd --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/ConvexHull.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:convexHull, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class ConvexHull extends GeometricUnaryFunction { + + @Override + public String getURI() { + return GEOF.CONVEX_HULL.stringValue(); + } + + @Override + protected Shape operation(Shape s) { + return SpatialSupport.getSpatialAlgebra().convexHull(s); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultSpatialAlgebra.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultSpatialAlgebra.java new file mode 100644 index 00000000000..ff19a639297 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultSpatialAlgebra.java @@ -0,0 +1,262 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import java.util.Arrays; +import java.util.Collections; + +import com.spatial4j.core.shape.Point; +import com.spatial4j.core.shape.Shape; +import com.spatial4j.core.shape.ShapeCollection; +import com.spatial4j.core.shape.SpatialRelation; +import com.spatial4j.core.shape.impl.BufferedLineString; + +final class DefaultSpatialAlgebra implements SpatialAlgebra { + + private T notSupported() { + throw new UnsupportedOperationException( + "Not supported due to licensing issues. Feel free to provide your own implementation by using something like JTS."); + } + + private Shape createEmptyPoint() { + return SpatialSupport.getSpatialContext().makePoint(Double.NaN, Double.NaN); + } + + private Shape createEmptyGeometry() { + return new ShapeCollection(Collections. emptyList(), SpatialSupport.getSpatialContext()); + } + + @Override + public Shape convexHull(Shape s) { + if (s instanceof Point) { + return s; + } + else if (s instanceof ShapeCollection) { + return new BufferedLineString((ShapeCollection)s, 0.0, SpatialSupport.getSpatialContext()); + } + return notSupported(); + } + + @Override + public Shape boundary(Shape s) { + if (s instanceof Point) { + // points have no boundary so return empty shape + return createEmptyGeometry(); + } + else if (s instanceof ShapeCollection) { + ShapeCollection col = (ShapeCollection)s; + if (col.isEmpty()) { + return createEmptyGeometry(); + } + for (Shape p : col) { + if (!(p instanceof Point)) { + return notSupported(); + } + } + return createEmptyGeometry(); + } + return notSupported(); + } + + @Override + public Shape envelope(Shape s) { + if (s instanceof Point) { + return s; + } + return notSupported(); + } + + @Override + public Shape union(Shape s1, Shape s2) { + if (s1 instanceof Point && s2 instanceof Point) { + Point p1 = (Point)s1; + Point p2 = (Point)s2; + int diff = compare(p2, p1); + if (diff == 0) { + return s1; + } + else if (diff < 0) { + p1 = p2; + p2 = (Point)s1; + } + return new ShapeCollection(Arrays.asList(p1, p2), SpatialSupport.getSpatialContext()); + } + return notSupported(); + } + + private int compare(Point p1, Point p2) { + int diff = Double.compare(p1.getX(), p2.getX()); + if (diff == 0) { + diff = Double.compare(p1.getY(), p2.getY()); + } + return diff; + } + + @Override + public Shape intersection(Shape s1, Shape s2) { + if (s1 instanceof Point && s2 instanceof Point) { + Point p1 = (Point)s1; + Point p2 = (Point)s2; + int diff = compare(p2, p1); + if (diff == 0) { + return s1; + } + else { + return createEmptyPoint(); + } + } + return notSupported(); + } + + @Override + public Shape symDifference(Shape s1, Shape s2) { + if (s1 instanceof Point && s2 instanceof Point) { + Point p1 = (Point)s1; + Point p2 = (Point)s2; + int diff = compare(p2, p1); + if (diff == 0) { + return createEmptyPoint(); + } + else if (diff < 0) { + p1 = p2; + p2 = (Point)s1; + } + return new ShapeCollection(Arrays.asList(p1, p2), SpatialSupport.getSpatialContext()); + } + return notSupported(); + } + + @Override + public Shape difference(Shape s1, Shape s2) { + if (s1 instanceof Point && s2 instanceof Point) { + Point p1 = (Point)s1; + Point p2 = (Point)s2; + int diff = compare(p2, p1); + if (diff == 0) { + return createEmptyPoint(); + } + return s1; + } + return notSupported(); + } + + @Override + public boolean relate(Shape s1, Shape s2, String intersectionPattern) { + return notSupported(); + } + + @Override + public boolean equals(Shape s1, Shape s2) { + return s1.equals(s2); + } + + @Override + public boolean sfDisjoint(Shape s1, Shape s2) { + return SpatialRelation.DISJOINT == s1.relate(s2); + } + + @Override + public boolean sfIntersects(Shape s1, Shape s2) { + return SpatialRelation.INTERSECTS == s1.relate(s2); + } + + @Override + public boolean sfTouches(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean sfCrosses(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean sfWithin(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean sfContains(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean sfOverlaps(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean ehDisjoint(Shape s1, Shape s2) { + return SpatialRelation.DISJOINT == s1.relate(s2); + } + + @Override + public boolean ehMeet(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean ehOverlap(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean ehCovers(Shape s1, Shape s2) { + return SpatialRelation.CONTAINS == s1.relate(s2); + } + + @Override + public boolean ehCoveredBy(Shape s1, Shape s2) { + return SpatialRelation.WITHIN == s1.relate(s2); + } + + @Override + public boolean ehInside(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean ehContains(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean rcc8dc(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean rcc8ec(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean rcc8po(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean rcc8tppi(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean rcc8tpp(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean rcc8ntpp(Shape s1, Shape s2) { + return notSupported(); + } + + @Override + public boolean rcc8ntppi(Shape s1, Shape s2) { + return notSupported(); + } +} \ No newline at end of file diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultWktWriter.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultWktWriter.java new file mode 100644 index 00000000000..c4875356a2a --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultWktWriter.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import java.io.IOException; + +import com.spatial4j.core.shape.Point; +import com.spatial4j.core.shape.Shape; +import com.spatial4j.core.shape.ShapeCollection; +import com.spatial4j.core.shape.impl.BufferedLineString; + +final class DefaultWktWriter implements WktWriter { + + private String notSupported(Shape s) { + throw new UnsupportedOperationException( + "This shape is not supported due to licensing issues. Feel free to provide your own implementation by using something like JTS: " + + s.getClass().getName()); + } + + @Override + public String toWkt(Shape shape) + throws IOException + { + if (shape instanceof Point) { + Point p = (Point)shape; + return "POINT " + toCoords(p); + } + else if (shape instanceof ShapeCollection) { + ShapeCollection col = (ShapeCollection)shape; + if (col.isEmpty()) { + return "GEOMETRYCOLLECTION EMPTY"; + } + Class elementType = null; + StringBuilder buf = new StringBuilder(" ("); + String sep = ""; + for (Shape s : col) { + if (elementType == null) { + elementType = s.getClass(); + } + else if (!elementType.equals(s.getClass())) { + elementType = Shape.class; + } + buf.append(sep).append(toCoords(s)); + sep = ", "; + } + buf.append(")"); + if (Point.class.isAssignableFrom(elementType)) { + buf.insert(0, "MULTIPOINT"); + } + else if (elementType == Shape.class) { + buf.insert(0, "GEOMETRYCOLLECTION"); + } + else { + return notSupported(shape); + } + return buf.toString(); + } + else if (shape instanceof BufferedLineString) { + BufferedLineString ls = (BufferedLineString)shape; + return "LINESTRING " + toCoords(ls); + } + return notSupported(shape); + } + + private String toCoords(Shape shape) + throws IOException + { + if (shape instanceof Point) { + Point p = (Point)shape; + return toCoords(p); + } + else if (shape instanceof BufferedLineString) { + BufferedLineString ls = (BufferedLineString)shape; + return toCoords(ls); + } + return notSupported(shape); + } + + private String toCoords(Point p) + throws IOException + { + if (p.isEmpty()) { + return "EMPTY"; + } + else { + return "(" + p.getX() + " " + p.getY() + ")"; + } + } + + private String toCoords(BufferedLineString shape) + throws IOException + { + double buffer = shape.getBuf(); + if (buffer != 0.0) { + return notSupported(shape); + } + StringBuilder buf = new StringBuilder("("); + String sep = ""; + for (Point p : shape.getPoints()) { + buf.append(sep); + buf.append(p.getX()).append(" ").append(p.getY()); + sep = ", "; + } + buf.append(")"); + return buf.toString(); + } +} \ No newline at end of file diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Difference.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Difference.java new file mode 100644 index 00000000000..24ef86431e0 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Difference.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:difference, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class Difference extends GeometricBinaryFunction { + + @Override + public String getURI() { + return GEOF.DIFFERENCE.stringValue(); + } + + @Override + protected Shape operation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().difference(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Distance.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Distance.java new file mode 100644 index 00000000000..01359524add --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Distance.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.shape.Point; + +/** + * The GeoSPARQL {@link Function} geof:distance, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class Distance implements Function { + + @Override + public String getURI() { + return GEOF.DISTANCE.stringValue(); + } + + @Override + public Value evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 3) { + throw new ValueExprEvaluationException(getURI() + " requires exactly 3 arguments, got " + + args.length); + } + + SpatialContext geoContext = SpatialSupport.getSpatialContext(); + Point p1 = FunctionArguments.getPoint(this, args[0], geoContext); + Point p2 = FunctionArguments.getPoint(this, args[1], geoContext); + URI units = FunctionArguments.getUnits(this, args[2]); + + double distDegs = geoContext.calcDistance(p1, p2); + double distUom = FunctionArguments.convertFromDegrees(distDegs, units); + + return valueFactory.createLiteral(distUom); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhContains.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhContains.java new file mode 100644 index 00000000000..03ff6bd26d9 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhContains.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:ehContains, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class EhContains extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.EH_CONTAINS.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().ehContains(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhCoveredBy.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhCoveredBy.java new file mode 100644 index 00000000000..ded4bee7f60 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhCoveredBy.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:ehCoveredBy, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class EhCoveredBy extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.EH_COVERED_BY.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().ehCoveredBy(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhCovers.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhCovers.java new file mode 100644 index 00000000000..e0960e8236b --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhCovers.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:ehCovers, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class EhCovers extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.EH_COVERS.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().ehCovers(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhDisjoint.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhDisjoint.java new file mode 100644 index 00000000000..67be3de819d --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhDisjoint.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:ehDisjoint, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class EhDisjoint extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.EH_DISJOINT.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().ehDisjoint(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhEquals.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhEquals.java new file mode 100644 index 00000000000..78c2a5b460c --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhEquals.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:ehEquals, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class EhEquals extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.EH_EQUALS.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().equals(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhInside.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhInside.java new file mode 100644 index 00000000000..83bea8f334f --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhInside.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:ehInside, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class EhInside extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.EH_INSIDE.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().ehInside(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhMeet.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhMeet.java new file mode 100644 index 00000000000..d7eff07ce06 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhMeet.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:ehMeet, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class EhMeet extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.EH_MEET.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().ehMeet(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhOverlap.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhOverlap.java new file mode 100644 index 00000000000..d092e8f18ae --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/EhOverlap.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:ehOverlap, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class EhOverlap extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.EH_OVERLAP.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().ehOverlap(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Envelope.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Envelope.java new file mode 100644 index 00000000000..3361dc0542f --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Envelope.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:envelope, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class Envelope extends GeometricUnaryFunction { + + @Override + public String getURI() { + return GEOF.ENVELOPE.stringValue(); + } + + @Override + protected Shape operation(Shape s) { + return SpatialSupport.getSpatialAlgebra().envelope(s); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/FunctionArguments.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/FunctionArguments.java new file mode 100644 index 00000000000..3ce2098fcb5 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/FunctionArguments.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import java.text.ParseException; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.URI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.vocabulary.GEO; +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.distance.DistanceUtils; +import com.spatial4j.core.shape.Point; +import com.spatial4j.core.shape.Shape; + +class FunctionArguments { + + private FunctionArguments() { + } + + public static double getDouble(Function func, Value v) + throws ValueExprEvaluationException + { + Literal l = getLiteral(func, v, XMLSchema.DOUBLE); + return l.doubleValue(); + } + + public static String getString(Function func, Value v) + throws ValueExprEvaluationException + { + Literal l = getLiteral(func, v, XMLSchema.STRING); + return l.stringValue(); + } + + public static Shape getShape(Function func, Value v, SpatialContext context) + throws ValueExprEvaluationException + { + Literal wktLiteral = getLiteral(func, v, GEO.WKT_LITERAL); + try { + return context.readShapeFromWkt(wktLiteral.getLabel()); + } + catch (ParseException e) { + throw new ValueExprEvaluationException("Invalid argument for " + func.getURI() + ": " + wktLiteral, + e); + } + } + + public static Point getPoint(Function func, Value v, SpatialContext geoContext) + throws ValueExprEvaluationException + { + Shape p = FunctionArguments.getShape(func, v, geoContext); + if (!(p instanceof Point)) { + throw new ValueExprEvaluationException("Invalid argument for " + func.getURI() + " (not a point): " + + v); + } + return (Point)p; + } + + public static Literal getLiteral(Function func, Value v, URI expectedDatatype) + throws ValueExprEvaluationException + { + if (!(v instanceof Literal)) { + throw new ValueExprEvaluationException("Invalid argument for " + func.getURI() + ": " + v); + } + Literal lit = (Literal)v; + if (!expectedDatatype.equals(lit.getDatatype())) { + throw new ValueExprEvaluationException("Invalid datatype " + lit.getDatatype() + " for " + + func.getURI() + ": " + v); + } + return lit; + } + + public static URI getUnits(Function func, Value v) + throws ValueExprEvaluationException + { + if (!(v instanceof URI)) { + throw new ValueExprEvaluationException("Invalid argument for " + func.getURI() + ": " + v); + } + URI unitUri = (URI)v; + if (!unitUri.getNamespace().equals(GEOF.UOM_NAMESPACE)) { + throw new ValueExprEvaluationException("Invalid unit of measurement URI for " + func.getURI() + ": " + + v); + } + return unitUri; + } + + public static double convertFromDegrees(double degs, URI units) + throws ValueExprEvaluationException + { + double v; + if (GEOF.UOM_DEGREE.equals(units)) { + v = degs; + } + else if (GEOF.UOM_RADIAN.equals(units)) { + v = DistanceUtils.toRadians(degs); + } + else if (GEOF.UOM_UNITY.equals(units)) { + v = degs / 180.0; + } + else if (GEOF.UOM_METRE.equals(units)) { + v = DistanceUtils.degrees2Dist(degs, DistanceUtils.EARTH_MEAN_RADIUS_KM) * 1000.0; + } + else { + throw new ValueExprEvaluationException("Invalid unit of measurement: " + units); + } + return v; + } + + public static double convertToDegrees(double v, URI units) + throws ValueExprEvaluationException + { + double degs; + if (GEOF.UOM_DEGREE.equals(units)) { + degs = v; + } + else if (GEOF.UOM_RADIAN.equals(units)) { + degs = DistanceUtils.toDegrees(v); + } + else if (GEOF.UOM_UNITY.equals(units)) { + degs = v * 180.0; + } + else if (GEOF.UOM_METRE.equals(units)) { + degs = DistanceUtils.dist2Degrees(v / 1000.0, DistanceUtils.EARTH_MEAN_RADIUS_KM); + } + else { + throw new ValueExprEvaluationException("Invalid unit of measurement: " + units); + } + return degs; + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricBinaryFunction.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricBinaryFunction.java new file mode 100644 index 00000000000..6c8746dd7cd --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricBinaryFunction.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import java.io.IOException; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.GEO; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.shape.Shape; + +abstract class GeometricBinaryFunction implements Function { + + @Override + public Value evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 2) { + throw new ValueExprEvaluationException(getURI() + " requires exactly 2 arguments, got " + + args.length); + } + + SpatialContext geoContext = SpatialSupport.getSpatialContext(); + Shape geom1 = FunctionArguments.getShape(this, args[0], geoContext); + Shape geom2 = FunctionArguments.getShape(this, args[1], geoContext); + Shape result = operation(geom1, geom2); + + String wkt; + try { + wkt = SpatialSupport.getWktWriter().toWkt(result); + } + catch (IOException ioe) { + throw new ValueExprEvaluationException(ioe); + } + return valueFactory.createLiteral(wkt, GEO.WKT_LITERAL); + } + + protected abstract Shape operation(Shape g1, Shape g2); +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricRelationFunction.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricRelationFunction.java new file mode 100644 index 00000000000..e19036438a3 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricRelationFunction.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.shape.Shape; + +abstract class GeometricRelationFunction implements Function { + + @Override + public Value evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 2) { + throw new ValueExprEvaluationException(getURI() + " requires exactly 2 arguments, got " + + args.length); + } + + SpatialContext geoContext = SpatialSupport.getSpatialContext(); + Shape geom1 = FunctionArguments.getShape(this, args[0], geoContext); + Shape geom2 = FunctionArguments.getShape(this, args[1], geoContext); + boolean result = relation(geom1, geom2); + + return valueFactory.createLiteral(result); + } + + protected abstract boolean relation(Shape g1, Shape g2); +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricUnaryFunction.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricUnaryFunction.java new file mode 100644 index 00000000000..09370202dc5 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricUnaryFunction.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import java.io.IOException; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.GEO; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.shape.Shape; + +abstract class GeometricUnaryFunction implements Function { + + @Override + public Value evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException(getURI() + " requires exactly 1 argument, got " + args.length); + } + + SpatialContext geoContext = SpatialSupport.getSpatialContext(); + Shape geom = FunctionArguments.getShape(this, args[0], geoContext); + Shape result = operation(geom); + + String wkt; + try { + wkt = SpatialSupport.getWktWriter().toWkt(result); + } + catch (IOException ioe) { + throw new ValueExprEvaluationException(ioe); + } + return valueFactory.createLiteral(wkt, GEO.WKT_LITERAL); + } + + protected abstract Shape operation(Shape g); +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Intersection.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Intersection.java new file mode 100644 index 00000000000..13d021a7341 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Intersection.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:intersection, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class Intersection extends GeometricBinaryFunction { + + @Override + public String getURI() { + return GEOF.INTERSECTION.stringValue(); + } + + @Override + protected Shape operation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().intersection(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8DC.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8DC.java new file mode 100644 index 00000000000..e63202f5a9b --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8DC.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:rcc8dc, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class RCC8DC extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.RCC8_DC.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().rcc8dc(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8EC.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8EC.java new file mode 100644 index 00000000000..fe7ff8dbe37 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8EC.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:rcc8ec, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class RCC8EC extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.RCC8_EC.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().rcc8ec(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8EQ.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8EQ.java new file mode 100644 index 00000000000..df2a67d61bf --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8EQ.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:rcc8eq, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class RCC8EQ extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.RCC8_EQ.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().equals(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8NTPP.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8NTPP.java new file mode 100644 index 00000000000..5f83960b03b --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8NTPP.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:rcc8ntpp, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class RCC8NTPP extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.RCC8_NTPP.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().rcc8ntpp(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8NTPPI.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8NTPPI.java new file mode 100644 index 00000000000..4eaca1927dc --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8NTPPI.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:rcc8ntppi, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class RCC8NTPPI extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.RCC8_NTPPI.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().rcc8ntppi(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8PO.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8PO.java new file mode 100644 index 00000000000..16effc92f24 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8PO.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:rcc8po, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class RCC8PO extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.RCC8_PO.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().rcc8po(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8TPP.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8TPP.java new file mode 100644 index 00000000000..c6cd62986c4 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8TPP.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:rcc8tpp, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class RCC8TPP extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.RCC8_TPP.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().rcc8tpp(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8TPPI.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8TPPI.java new file mode 100644 index 00000000000..821e8fc13f0 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/RCC8TPPI.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:rcc8tppi, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class RCC8TPPI extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.RCC8_TPPI.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().rcc8tppi(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Relate.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Relate.java new file mode 100644 index 00000000000..8d292cfcea6 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Relate.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:relate, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class Relate implements Function { + + @Override + public String getURI() { + return GEOF.RELATE.stringValue(); + } + + @Override + public Value evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 3) { + throw new ValueExprEvaluationException(getURI() + " requires exactly 3 arguments, got " + + args.length); + } + + SpatialContext geoContext = SpatialSupport.getSpatialContext(); + Shape geom1 = FunctionArguments.getShape(this, args[0], geoContext); + Shape geom2 = FunctionArguments.getShape(this, args[1], geoContext); + String pattern = FunctionArguments.getString(this, args[2]); + boolean result = SpatialSupport.getSpatialAlgebra().relate(geom1, geom2, pattern); + + return valueFactory.createLiteral(result); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SRID.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SRID.java new file mode 100644 index 00000000000..cd89d78fc40 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SRID.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.GEO; +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +/** + * The GeoSPARQL {@link Function} geof:getSRID, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SRID implements Function { + + @Override + public String getURI() { + return GEOF.GET_SRID.stringValue(); + } + + @Override + public Value evaluate(ValueFactory valueFactory, Value... args) + throws ValueExprEvaluationException + { + if (args.length != 1) { + throw new ValueExprEvaluationException(getURI() + " requires exactly 1 argument, got " + args.length); + } + + Literal geom = FunctionArguments.getLiteral(this, args[0], GEO.WKT_LITERAL); + String wkt = geom.getLabel(); + String srid; + int sep = wkt.indexOf(' '); + if (sep != -1 && wkt.charAt(0) == '<' && wkt.charAt(sep - 1) == '>') { + srid = wkt.substring(1, sep - 1); + } + else { + srid = GEO.DEFAULT_SRID; + } + + return valueFactory.createLiteral(srid, XMLSchema.ANYURI); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfContains.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfContains.java new file mode 100644 index 00000000000..4eac37b868d --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfContains.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:sfContains, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SfContains extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.SF_CONTAINS.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().sfContains(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfCrosses.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfCrosses.java new file mode 100644 index 00000000000..9d71ca18755 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfCrosses.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:sfCrosses, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SfCrosses extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.SF_CROSSES.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().sfCrosses(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfDisjoint.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfDisjoint.java new file mode 100644 index 00000000000..771b6f0c6ad --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfDisjoint.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:sfDisjoint, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SfDisjoint extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.SF_DISJOINT.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().sfDisjoint(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfEquals.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfEquals.java new file mode 100644 index 00000000000..976340e8e59 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfEquals.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:sfEquals, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SfEquals extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.SF_EQUALS.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().equals(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfIntersects.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfIntersects.java new file mode 100644 index 00000000000..2aa121f73ef --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfIntersects.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:sfIntersects, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SfIntersects extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.SF_INTERSECTS.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().sfIntersects(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfOverlaps.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfOverlaps.java new file mode 100644 index 00000000000..775ff6c88cd --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfOverlaps.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:sfOverlaps, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SfOverlaps extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.SF_OVERLAPS.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().sfOverlaps(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfTouches.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfTouches.java new file mode 100644 index 00000000000..32d8c992f0d --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfTouches.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:sfTouches, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SfTouches extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.SF_TOUCHES.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().sfTouches(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfWithin.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfWithin.java new file mode 100644 index 00000000000..8cab3df49af --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SfWithin.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:sfWithin, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SfWithin extends GeometricRelationFunction { + + @Override + public String getURI() { + return GEOF.SF_WITHIN.stringValue(); + } + + @Override + protected boolean relation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().sfWithin(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SpatialAlgebra.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SpatialAlgebra.java new file mode 100644 index 00000000000..53240ebae13 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SpatialAlgebra.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import com.spatial4j.core.shape.Shape; + +public interface SpatialAlgebra { + + Shape convexHull(Shape s); + + Shape boundary(Shape s); + + Shape envelope(Shape s); + + Shape union(Shape s1, Shape s2); + + Shape intersection(Shape s1, Shape s2); + + Shape symDifference(Shape s1, Shape s2); + + Shape difference(Shape s1, Shape s2); + + boolean relate(Shape s1, Shape s2, String intersectionPattern); + + boolean equals(Shape s1, Shape s2); + + boolean sfDisjoint(Shape s1, Shape s2); + + boolean sfIntersects(Shape s1, Shape s2); + + boolean sfTouches(Shape s1, Shape s2); + + boolean sfCrosses(Shape s1, Shape s2); + + boolean sfWithin(Shape s1, Shape s2); + + boolean sfContains(Shape s1, Shape s2); + + boolean sfOverlaps(Shape s1, Shape s2); + + boolean ehDisjoint(Shape s1, Shape s2); + + boolean ehMeet(Shape s1, Shape s2); + + boolean ehOverlap(Shape s1, Shape s2); + + boolean ehCovers(Shape s1, Shape s2); + + boolean ehCoveredBy(Shape s1, Shape s2); + + boolean ehInside(Shape s1, Shape s2); + + boolean ehContains(Shape s1, Shape s2); + + boolean rcc8dc(Shape s1, Shape s2); + + boolean rcc8ec(Shape s1, Shape s2); + + boolean rcc8po(Shape s1, Shape s2); + + boolean rcc8tppi(Shape s1, Shape s2); + + boolean rcc8tpp(Shape s1, Shape s2); + + boolean rcc8ntpp(Shape s1, Shape s2); + + boolean rcc8ntppi(Shape s1, Shape s2); +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SpatialSupport.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SpatialSupport.java new file mode 100644 index 00000000000..af822e75ca9 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SpatialSupport.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import java.util.HashMap; +import java.util.Map; + +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.context.SpatialContextFactory; + +/** + * This class is responsible for creating the + * {@link com.spatial4j.core.context.SpatialContext}, {@link SpatialAlegbra} and + * {@link WktWriter} that will be used. It will first try to load a subclass of + * itself called + * "org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql.SpatialSupportInitializer" + * . This is not provided, and is primarily intended as a way to inject JTS + * support. If this fails then the following fall-backs are used: + *
      + *
    • a SpatialContext created by passing system properties with the prefix + * "spatialSupport." to {@link com.spatial4j.core.context.SpatialContextFactory} + * . The prefix is stripped from the system property name to form the + * SpatialContextFactory argument name.
    • + *
    • a SpatialAlgebra that does not support any operation.
    • + *
    • a WktWriter that only supports points
    • . + *
    + */ +abstract class SpatialSupport { + + private static final SpatialContext spatialContext; + + private static final SpatialAlgebra spatialAlgebra; + + private static final WktWriter wktWriter; + + static { + SpatialSupport support; + try { + Class cls = Class.forName( + "org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql.SpatialSupportInitializer", true, + Thread.currentThread().getContextClassLoader()); + support = (SpatialSupport)cls.newInstance(); + } + catch (Exception e) { + support = new DefaultSpatialSupport(); + } + spatialContext = support.createSpatialContext(); + spatialAlgebra = support.createSpatialAlgebra(); + wktWriter = support.createWktWriter(); + } + + static SpatialContext getSpatialContext() { + return spatialContext; + } + + static SpatialAlgebra getSpatialAlgebra() { + return spatialAlgebra; + } + + static WktWriter getWktWriter() { + return wktWriter; + } + + protected abstract SpatialContext createSpatialContext(); + + protected abstract SpatialAlgebra createSpatialAlgebra(); + + protected abstract WktWriter createWktWriter(); + + private static final class DefaultSpatialSupport extends SpatialSupport { + + private static final String SYSTEM_PROPERTY_PREFIX = "spatialSupport."; + + @Override + protected SpatialContext createSpatialContext() { + Map args = new HashMap(); + for (String key : System.getProperties().stringPropertyNames()) { + if (key.startsWith(SYSTEM_PROPERTY_PREFIX)) { + args.put(key.substring(SYSTEM_PROPERTY_PREFIX.length()), System.getProperty(key)); + } + } + return SpatialContextFactory.makeSpatialContext(args, Thread.currentThread().getContextClassLoader()); + } + + @Override + protected SpatialAlgebra createSpatialAlgebra() { + return new DefaultSpatialAlgebra(); + } + + @Override + protected WktWriter createWktWriter() { + return new DefaultWktWriter(); + } + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SymmetricDifference.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SymmetricDifference.java new file mode 100644 index 00000000000..cdbf29d8d40 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/SymmetricDifference.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:symDifference, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class SymmetricDifference extends GeometricBinaryFunction { + + @Override + public String getURI() { + return GEOF.SYM_DIFFERENCE.stringValue(); + } + + @Override + protected Shape operation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().symDifference(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Union.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Union.java new file mode 100644 index 00000000000..a708aa2f677 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/Union.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; + +import com.spatial4j.core.shape.Shape; + +/** + * The GeoSPARQL {@link Function} geof:union, as defined in OGC GeoSPARQL - A + * Geographic Query Language for RDF Data. + */ +public class Union extends GeometricBinaryFunction { + + @Override + public String getURI() { + return GEOF.UNION.stringValue(); + } + + @Override + protected Shape operation(Shape s1, Shape s2) { + return SpatialSupport.getSpatialAlgebra().union(s1, s2); + } +} diff --git a/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/WktWriter.java b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/WktWriter.java new file mode 100644 index 00000000000..f4f1ac86113 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/WktWriter.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.geosparql; + +import java.io.IOException; + +import com.spatial4j.core.shape.Shape; + +public interface WktWriter { + + String toWkt(Shape shape) + throws IOException; +} diff --git a/core/queryalgebra/geosparql/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function b/core/queryalgebra/geosparql/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function new file mode 100644 index 00000000000..f1a666dced1 --- /dev/null +++ b/core/queryalgebra/geosparql/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function @@ -0,0 +1,35 @@ +org.openrdf.query.algebra.evaluation.function.geosparql.Distance +org.openrdf.query.algebra.evaluation.function.geosparql.Buffer +org.openrdf.query.algebra.evaluation.function.geosparql.ConvexHull +org.openrdf.query.algebra.evaluation.function.geosparql.Intersection +org.openrdf.query.algebra.evaluation.function.geosparql.Union +org.openrdf.query.algebra.evaluation.function.geosparql.Difference +org.openrdf.query.algebra.evaluation.function.geosparql.SymmetricDifference +org.openrdf.query.algebra.evaluation.function.geosparql.Envelope +org.openrdf.query.algebra.evaluation.function.geosparql.Boundary +org.openrdf.query.algebra.evaluation.function.geosparql.SRID +org.openrdf.query.algebra.evaluation.function.geosparql.Relate +org.openrdf.query.algebra.evaluation.function.geosparql.SfContains +org.openrdf.query.algebra.evaluation.function.geosparql.SfCrosses +org.openrdf.query.algebra.evaluation.function.geosparql.SfDisjoint +org.openrdf.query.algebra.evaluation.function.geosparql.SfEquals +org.openrdf.query.algebra.evaluation.function.geosparql.SfIntersects +org.openrdf.query.algebra.evaluation.function.geosparql.SfOverlaps +org.openrdf.query.algebra.evaluation.function.geosparql.SfTouches +org.openrdf.query.algebra.evaluation.function.geosparql.SfWithin +org.openrdf.query.algebra.evaluation.function.geosparql.EhContains +org.openrdf.query.algebra.evaluation.function.geosparql.EhCoveredBy +org.openrdf.query.algebra.evaluation.function.geosparql.EhCovers +org.openrdf.query.algebra.evaluation.function.geosparql.EhDisjoint +org.openrdf.query.algebra.evaluation.function.geosparql.EhEquals +org.openrdf.query.algebra.evaluation.function.geosparql.EhInside +org.openrdf.query.algebra.evaluation.function.geosparql.EhMeet +org.openrdf.query.algebra.evaluation.function.geosparql.EhOverlap +org.openrdf.query.algebra.evaluation.function.geosparql.RCC8DC +org.openrdf.query.algebra.evaluation.function.geosparql.RCC8EC +org.openrdf.query.algebra.evaluation.function.geosparql.RCC8EQ +org.openrdf.query.algebra.evaluation.function.geosparql.RCC8NTPP +org.openrdf.query.algebra.evaluation.function.geosparql.RCC8NTPPI +org.openrdf.query.algebra.evaluation.function.geosparql.RCC8PO +org.openrdf.query.algebra.evaluation.function.geosparql.RCC8TPP +org.openrdf.query.algebra.evaluation.function.geosparql.RCC8TPPI \ No newline at end of file diff --git a/core/queryalgebra/model/pom.xml b/core/queryalgebra/model/pom.xml new file mode 100644 index 00000000000..064a5e64c92 --- /dev/null +++ b/core/queryalgebra/model/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-queryalgebra + 4.1.0-SNAPSHOT + + + rdf4j-queryalgebra-model + + RDF4J: Query algebra - model + A generic query algebra for RDF queries. + + + + ${project.groupId} + rdf4j-model + ${project.version} + + + ${project.groupId} + rdf4j-query + ${project.version} + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AbstractAggregateOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AbstractAggregateOperator.java new file mode 100644 index 00000000000..5d1a84d9faf --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AbstractAggregateOperator.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * Base class for shared functionality of aggregate operators (e.g. DISTINCT + * setting) + * + * @author Jeen Broekstra + */ +public abstract class AbstractAggregateOperator extends UnaryValueOperator implements AggregateOperator { + + private static final long serialVersionUID = 4016064683034358205L; + + private boolean distinct = false; + + public AbstractAggregateOperator(ValueExpr arg) { + this(arg, false); + } + + public AbstractAggregateOperator(ValueExpr arg, boolean distinct) { + super(); + if (arg != null) { + setArg(arg); + } + setDistinct(distinct); + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + public boolean isDistinct() { + return this.distinct; + } + + @Override + public int hashCode() { + int distHash = (isDistinct() ? 1 : 0); + if (arg == null) { + return 73 + distHash; + } else { + return arg.hashCode() + distHash; + } + } + + @Override + public AbstractAggregateOperator clone() { + return (AbstractAggregateOperator)super.clone(); + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AbstractQueryModelNode.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AbstractQueryModelNode.java new file mode 100644 index 00000000000..89498c2a503 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AbstractQueryModelNode.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.List; +import java.util.ListIterator; + +import org.eclipse.rdf4j.query.algebra.helpers.QueryModelTreePrinter; + +/** + * Base implementation of {@link QueryModelNode}. + */ +public abstract class AbstractQueryModelNode implements QueryModelNode { + + /*-----------* + * Variables * + *-----------*/ + + private static final long serialVersionUID = 3006199552086476178L; + + private QueryModelNode parent; + + /*---------* + * Methods * + *---------*/ + + public QueryModelNode getParentNode() { + return parent; + } + + public void setParentNode(QueryModelNode parent) { + this.parent = parent; + } + + /** + * Dummy implementation of {@link QueryModelNode#visitChildren} that does + * nothing. Subclasses should override this method when they have child + * nodes. + */ + public void visitChildren(QueryModelVisitor visitor) + throws X + { + } + + /** + * Default implementation of + * {@link QueryModelNode#replaceChildNode(QueryModelNode, QueryModelNode)} + * that throws an {@link IllegalArgumentException} indicating that + * current is not a child node of this node. + */ + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + throw new IllegalArgumentException("Node is not a child node: " + current); + } + + /** + * Default implementation of + * {@link QueryModelNode#replaceWith(QueryModelNode)} that throws an + * {@link IllegalArgumentException} indicating that current is not a + * child node of this node. + */ + public void replaceWith(QueryModelNode replacement) { + if (parent == null) { + throw new IllegalStateException("Node has no parent"); + } + + parent.replaceChildNode(this, replacement); + } + + /** + * Default implementation of {@link QueryModelNode#getSignature()} that + * prints the name of the node's class. + */ + public String getSignature() { + return this.getClass().getSimpleName(); + } + + @Override + public String toString() { + QueryModelTreePrinter treePrinter = new QueryModelTreePrinter(); + this.visit(treePrinter); + return treePrinter.getTreeString(); + } + + @Override + public AbstractQueryModelNode clone() { + try { + return (AbstractQueryModelNode)super.clone(); + } + catch (CloneNotSupportedException e) { + throw new RuntimeException("Query model nodes are required to be cloneable", e); + } + } + + protected boolean replaceNodeInList(List list, QueryModelNode current, QueryModelNode replacement) { + ListIterator iter = list.listIterator(); + while (iter.hasNext()) { + if (iter.next() == current) { + iter.set((T)replacement); + replacement.setParentNode(this); + return true; + } + } + + return false; + } + + protected boolean nullEquals(Object o1, Object o2) { + return o1 == o2 || o1 != null && o1.equals(o2); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Add.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Add.java new file mode 100644 index 00000000000..c5166d9128f --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Add.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author jeen + */ +public class Add extends AbstractQueryModelNode implements UpdateExpr { + + private ValueConstant sourceGraph; + + private ValueConstant destinationGraph; + + private boolean silent; + + public Add() { + super(); + } + + public Add(ValueConstant graph) { + super(); + setSourceGraph(graph); + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (sourceGraph != null) { + sourceGraph.visit(visitor); + } + if (destinationGraph != null) { + destinationGraph.visit(visitor); + } + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (sourceGraph == current) { + setSourceGraph((ValueConstant)replacement); + } + else if (destinationGraph == current) { + setDestinationGraph((ValueConstant)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if(other instanceof Add) { + Add o = (Add)other; + return silent == o.silent + && nullEquals(sourceGraph, o.sourceGraph) + && nullEquals(destinationGraph, o.destinationGraph); + } + return false; + } + + @Override + public int hashCode() { + int result = silent ? 1 :0; + if(sourceGraph != null) { + result ^= sourceGraph.hashCode(); + } + if(destinationGraph != null) { + result ^= destinationGraph.hashCode(); + } + return result; + } + + @Override + public Add clone() { + Add clone = new Add(); + clone.setSilent(isSilent()); + if (getSourceGraph() != null) { + clone.setSourceGraph(getSourceGraph().clone()); + } + return clone; + } + + /** + * @param graph + * The graph to set. + */ + public void setSourceGraph(ValueConstant graph) { + this.sourceGraph = graph; + } + + /** + * The named graph from which to add. If null, the default graph should be + * used. + * + * @return Returns the graph. + */ + public ValueConstant getSourceGraph() { + return sourceGraph; + } + + /** + * @param silent + * The silent to set. + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + /** + * @return Returns the silent. + */ + @Override + public boolean isSilent() { + return silent; + } + + /** + * @param destinationGraph + * The destinationGraph to set. + */ + public void setDestinationGraph(ValueConstant destinationGraph) { + this.destinationGraph = destinationGraph; + } + + /** + * The named graph to which to add. If null, the default graph should be + * used. + * + * @return Returns the destinationGraph. + */ + public ValueConstant getDestinationGraph() { + return destinationGraph; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AggregateOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AggregateOperator.java new file mode 100644 index 00000000000..feea7f02e2b --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AggregateOperator.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * An operator that returns aggregates values. + * + * @author David Huynh + */ +public interface AggregateOperator extends ValueExpr { + + public boolean isDistinct(); + + public void setDistinct(boolean distinct); + + public AggregateOperator clone(); + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AggregateOperatorBase.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AggregateOperatorBase.java new file mode 100644 index 00000000000..c66a3fc5e5b --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/AggregateOperatorBase.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @deprecated since 4.0. Use {@link AbstractAggregateOperator} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class AggregateOperatorBase extends AbstractAggregateOperator { + + private static final long serialVersionUID = 1L; + + public AggregateOperatorBase(ValueExpr arg) { + super(arg); + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/And.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/And.java new file mode 100644 index 00000000000..4aeb0b95693 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/And.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * A boolean AND operator operating on two boolean expressions. + */ +public class And extends BinaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public And() { + } + + public And(ValueExpr leftArg, ValueExpr rightArg) { + super(leftArg, rightArg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof And && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "And".hashCode(); + } + + @Override + public And clone() { + return (And)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ArbitraryLengthPath.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ArbitraryLengthPath.java new file mode 100644 index 00000000000..8e27abf15d8 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ArbitraryLengthPath.java @@ -0,0 +1,274 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope; + +/** + * A tuple expression that matches a path of arbitrary length against an RDF graph. + * They can can be targeted at one of three context scopes: all + * contexts, null context only, or named contexts only. + */ +public class ArbitraryLengthPath extends AbstractQueryModelNode implements TupleExpr { + + /*-----------* + * Variables * + *-----------*/ + + private Scope scope; + + private Var subjectVar; + + private TupleExpr pathExpression; + + private Var objectVar; + + private Var contextVar; + + private long minLength; + + /*--------------* + * Constructors * + *--------------*/ + + public ArbitraryLengthPath() { + } + + /** + * Creates a arbitrary-length path that matches a subject-, predicate- and object + * variable against statements from all contexts. + */ + public ArbitraryLengthPath(Var subject, TupleExpr pathExpression, Var object, long minLength) { + this(Scope.DEFAULT_CONTEXTS, subject, pathExpression, object, minLength); + } + + /** + * Creates a arbitrary-length path that matches a subject-, predicate- and object + * variable against statements from the specified context scope. + */ + public ArbitraryLengthPath(Scope scope, Var subject,TupleExpr pathExpression, Var object, long minLength) { + this(scope, subject, pathExpression, object, null, minLength); + } + + /** + * Creates a arbitrary-length path that matches a subject-, predicate-, object- + * and context variable against statements from all contexts. + */ + public ArbitraryLengthPath(Var subject, TupleExpr pathExpression, Var object, Var context, long minLength) { + this(Scope.DEFAULT_CONTEXTS, subject, pathExpression, object, context, minLength); + } + + /** + * Creates a arbitrary-length path that matches a subject-, predicate-, object- + * and context variable against statements from the specified context scope. + */ + public ArbitraryLengthPath(Scope scope, Var subjVar,TupleExpr pathExpression, Var objVar, Var conVar, long minLength) { + setScope(scope); + setSubjectVar(subjVar); + setPathExpression(pathExpression); + setObjectVar(objVar); + setContextVar(conVar); + setMinLength(minLength); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the context scope for the arbitrary-length path. + */ + public Scope getScope() { + return scope; + } + + /** + * Sets the context scope for the arbitrary-length path + */ + public void setScope(Scope scope) { + assert scope != null : "scope must not be null"; + this.scope = scope; + } + + public Var getSubjectVar() { + return subjectVar; + } + + public void setSubjectVar(Var subject) { + assert subject != null : "subject must not be null"; + subject.setParentNode(this); + subjectVar = subject; + } + + public TupleExpr getPathExpression() { + return pathExpression; + } + + public void setPathExpression(TupleExpr pathExpression) { + pathExpression.setParentNode(this); + this.pathExpression = pathExpression; + } + + public Var getObjectVar() { + return objectVar; + } + + public void setObjectVar(Var object) { + assert object != null : "object must not be null"; + object.setParentNode(this); + objectVar = object; + } + + public void setMinLength(long minLength) { + this.minLength = minLength; + } + + public long getMinLength() { + return minLength; + } + + /** + * Returns the context variable, if available. + */ + public Var getContextVar() { + return contextVar; + } + + public void setContextVar(Var context) { + if (context != null) { + context.setParentNode(this); + } + contextVar = context; + } + + public Set getBindingNames() { + return getAssuredBindingNames(); + } + + public Set getAssuredBindingNames() { + Set bindingNames = new HashSet(8); + + if (subjectVar != null) { + bindingNames.add(subjectVar.getName()); + } + if (pathExpression != null) { + bindingNames.addAll(pathExpression.getAssuredBindingNames()); + } + if (objectVar != null) { + bindingNames.add(objectVar.getName()); + } + if (contextVar != null) { + bindingNames.add(contextVar.getName()); + } + + return bindingNames; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (subjectVar != null) { + subjectVar.visit(visitor); + } + if (pathExpression != null) { + pathExpression.visit(visitor); + } + if (objectVar != null) { + objectVar.visit(visitor); + } + if (contextVar != null) { + contextVar.visit(visitor); + } + + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (subjectVar == current) { + setSubjectVar((Var)replacement); + } + else if (pathExpression == current) { + setPathExpression((TupleExpr)replacement); + } + else if (objectVar == current) { + setObjectVar((Var)replacement); + } + else if (contextVar == current) { + setContextVar((Var)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public String getSignature() { + StringBuilder sb = new StringBuilder(128); + + sb.append(super.getSignature()); + + if (scope == Scope.NAMED_CONTEXTS) { + sb.append(" FROM NAMED CONTEXT"); + } + + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof ArbitraryLengthPath) { + ArbitraryLengthPath o = (ArbitraryLengthPath)other; + return subjectVar.equals(o.getSubjectVar()) && pathExpression.equals(o.getPathExpression()) + && objectVar.equals(o.getObjectVar()) && nullEquals(contextVar, o.getContextVar()) + && scope.equals(o.getScope()); + } + return false; + } + + @Override + public int hashCode() { + int result = subjectVar.hashCode(); + result ^= pathExpression.hashCode(); + result ^= objectVar.hashCode(); + if (contextVar != null) { + result ^= contextVar.hashCode(); + } + if (scope == Scope.NAMED_CONTEXTS) { + result = ~result; + } + return result; + } + + @Override + public ArbitraryLengthPath clone() { + ArbitraryLengthPath clone = (ArbitraryLengthPath)super.clone(); + clone.setSubjectVar(getSubjectVar().clone()); + clone.setPathExpression(getPathExpression().clone()); + clone.setObjectVar(getObjectVar().clone()); + + if (getContextVar() != null) { + clone.setContextVar(getContextVar().clone()); + } + + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Avg.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Avg.java new file mode 100644 index 00000000000..9ad30ed2b42 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Avg.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The AVG operator as defined in + * http://www.w3.org/TR/sparql11-query/#aggregates. + *

    + * Note that we introduce AVG as a first-class object into the algebra, + * despite it being defined as a compound of other operators (namely, SUM and + * COUNT). This allows us to more easily optimize evaluation. + * + * @author Jeen Broekstra + */ +public class Avg extends AbstractAggregateOperator { + + public Avg(ValueExpr arg) { + super(arg); + } + + public Avg(ValueExpr arg, boolean distinct) { + super(arg, distinct); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Avg && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Avg".hashCode(); + } + + @Override + public Avg clone() { + return (Avg)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BNodeGenerator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BNodeGenerator.java new file mode 100644 index 00000000000..04c56122c91 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BNodeGenerator.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * A BNode generator, which generates a new BNode each time it needs to supply a + * value. + */ +public class BNodeGenerator extends AbstractQueryModelNode implements ValueExpr { + + private ValueExpr nodeIdExpr = null; + + /*--------------* + * Constructors * + *--------------*/ + + public BNodeGenerator() { + super(); + } + public BNodeGenerator(ValueExpr nodeIdExpr) { + super(); + setNodeIdExpr(nodeIdExpr); + } + /*---------* + * Methods * + *---------*/ + + public ValueExpr getNodeIdExpr() { + return nodeIdExpr; + } + + public void setNodeIdExpr(ValueExpr nodeIdExpr) { + this.nodeIdExpr = nodeIdExpr; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof BNodeGenerator; + } + + @Override + public int hashCode() { + return "BNodeGenerator".hashCode(); + } + + @Override + public BNodeGenerator clone() { + return (BNodeGenerator)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BinaryTupleOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BinaryTupleOperator.java new file mode 100644 index 00000000000..77ffcdf32b5 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BinaryTupleOperator.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * An abstract superclass for binary tuple operators which, by definition, has + * two arguments. + */ +public abstract class BinaryTupleOperator extends AbstractQueryModelNode implements TupleExpr { + + /*-----------* + * Variables * + *-----------*/ + + /** + * The operator's left argument. + */ + protected TupleExpr leftArg; + + /** + * The operator's right argument. + */ + protected TupleExpr rightArg; + + /*--------------* + * Constructors * + *--------------*/ + + public BinaryTupleOperator() { + } + + /** + * Creates a new binary tuple operator. + * + * @param leftArg + * The operator's left argument, must not be null. + * @param rightArg + * The operator's right argument, must not be null. + */ + public BinaryTupleOperator(TupleExpr leftArg, TupleExpr rightArg) { + setLeftArg(leftArg); + setRightArg(rightArg); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the left argument of this binary tuple operator. + * + * @return The operator's left argument. + */ + public TupleExpr getLeftArg() { + return leftArg; + } + + /** + * Sets the left argument of this binary tuple operator. + * + * @param leftArg + * The (new) left argument for this operator, must not be + * null. + */ + public void setLeftArg(TupleExpr leftArg) { + assert leftArg != null : "leftArg must not be null"; + leftArg.setParentNode(this); + this.leftArg = leftArg; + } + + /** + * Gets the right argument of this binary tuple operator. + * + * @return The operator's right argument. + */ + public TupleExpr getRightArg() { + return rightArg; + } + + /** + * Sets the right argument of this binary tuple operator. + * + * @param rightArg + * The (new) right argument for this operator, must not be + * null. + */ + public void setRightArg(TupleExpr rightArg) { + assert rightArg != null : "rightArg must not be null"; + rightArg.setParentNode(this); + this.rightArg = rightArg; + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + leftArg.visit(visitor); + rightArg.visit(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (leftArg == current) { + setLeftArg((TupleExpr)replacement); + } + else if (rightArg == current) { + setRightArg((TupleExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof BinaryTupleOperator) { + BinaryTupleOperator o = (BinaryTupleOperator)other; + return leftArg.equals(o.getLeftArg()) && rightArg.equals(o.getRightArg()); + } + + return false; + } + + @Override + public int hashCode() { + return leftArg.hashCode() ^ rightArg.hashCode(); + } + + @Override + public BinaryTupleOperator clone() { + BinaryTupleOperator clone = (BinaryTupleOperator)super.clone(); + clone.setLeftArg(getLeftArg().clone()); + clone.setRightArg(getRightArg().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BinaryValueOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BinaryValueOperator.java new file mode 100644 index 00000000000..4ddfbee7eba --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BinaryValueOperator.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * An abstract superclass for binary value operators which, by definition, has + * two arguments. + */ +public abstract class BinaryValueOperator extends AbstractQueryModelNode implements ValueExpr { + + /*-----------* + * Variables * + *-----------*/ + + /** + * The operator's left argument. + */ + protected ValueExpr leftArg; + + /** + * The operator's right argument. + */ + protected ValueExpr rightArg; + + /*--------------* + * Constructors * + *--------------*/ + + public BinaryValueOperator() { + } + + /** + * Creates a new binary value operator. + * + * @param leftArg + * The operator's left argument, must not be null. + * @param rightArg + * The operator's right argument, must not be null. + */ + public BinaryValueOperator(ValueExpr leftArg, ValueExpr rightArg) { + setLeftArg(leftArg); + setRightArg(rightArg); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the left argument of this binary value operator. + * + * @return The operator's left argument. + */ + public ValueExpr getLeftArg() { + return leftArg; + } + + /** + * Sets the left argument of this binary value operator. + * + * @param leftArg + * The (new) left argument for this operator, must not be + * null. + */ + public void setLeftArg(ValueExpr leftArg) { + assert leftArg != null : "leftArg must not be null"; + leftArg.setParentNode(this); + this.leftArg = leftArg; + } + + /** + * Gets the right argument of this binary value operator. + * + * @return The operator's right argument. + */ + public ValueExpr getRightArg() { + return rightArg; + } + + /** + * Sets the right argument of this binary value operator. + * + * @param rightArg + * The (new) right argument for this operator, must not be + * null. + */ + public void setRightArg(ValueExpr rightArg) { + assert rightArg != null : "rightArg must not be null"; + rightArg.setParentNode(this); + this.rightArg = rightArg; + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + leftArg.visit(visitor); + rightArg.visit(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (leftArg == current) { + setLeftArg((ValueExpr)replacement); + } + else if (rightArg == current) { + setRightArg((ValueExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof BinaryValueOperator) { + BinaryValueOperator o = (BinaryValueOperator)other; + return leftArg.equals(o.getLeftArg()) && rightArg.equals(o.getRightArg()); + } + + return false; + } + + @Override + public int hashCode() { + return leftArg.hashCode() ^ rightArg.hashCode(); + } + + @Override + public BinaryValueOperator clone() { + BinaryValueOperator clone = (BinaryValueOperator)super.clone(); + clone.setLeftArg(getLeftArg().clone()); + clone.setRightArg(getRightArg().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BindingSetAssignment.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BindingSetAssignment.java new file mode 100644 index 00000000000..b0f5ed3ab4c --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/BindingSetAssignment.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.rdf4j.query.BindingSet; + +/** + */ +public class BindingSetAssignment extends AbstractQueryModelNode implements TupleExpr { + + private Set bindingNames; + private Iterable bindingSets; + + @Override + public Set getBindingNames() { + return getAssuredBindingNames(); + } + + @Override + public Set getAssuredBindingNames() { + if(bindingNames == null) { + bindingNames = findBindingNames(); + } + return bindingNames; + } + + private Set findBindingNames() { + Set result = new HashSet(); + if (bindingSets != null) { + for (BindingSet set: bindingSets) { + result.addAll(set.getBindingNames()); + } + } + return result; + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof BindingSetAssignment; + } + + @Override + public int hashCode() { + return "BindingSetAssignment".hashCode(); + } + + @Override + public BindingSetAssignment clone() { + return (BindingSetAssignment)super.clone(); + } + + /** + * @param bindingNames The bindingNames to set if known. + */ + public void setBindingNames(Set bindingNames) { + this.bindingNames = bindingNames; + } + + /** + * @param bindingSets The bindingSets to set. + */ + public void setBindingSets(Iterable bindingSets) { + this.bindingSets = bindingSets; + } + + /** + * @return Returns the bindingSets. + */ + public Iterable getBindingSets() { + return bindingSets; + } + + @Override + public String getSignature() { + String signature = super.getSignature(); + + signature += " (" + this.getBindingSets().toString() + ")"; + + return signature; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Bound.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Bound.java new file mode 100644 index 00000000000..1691836d920 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Bound.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The BOUND function, as defined in SPARQL Query + * Language for RDF; checks if a variable is bound. + * + * @author Arjohn Kampman + */ +public class Bound extends AbstractQueryModelNode implements ValueExpr { + + /*-----------* + * Variables * + *-----------*/ + + /** + * The operator's argument. + */ + protected Var arg; + + /*--------------* + * Constructors * + *--------------*/ + + public Bound() { + } + + public Bound(Var arg) { + setArg(arg); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the argument of this unary value operator. + * + * @return The operator's argument. + */ + public Var getArg() { + return arg; + } + + /** + * Sets the argument of this unary value operator. + * + * @param arg + * The (new) argument for this operator, must not be null. + */ + public void setArg(Var arg) { + assert arg != null : "arg must not be null"; + arg.setParentNode(this); + this.arg = arg; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + arg.visit(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (arg == current) { + setArg((Var)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof Bound) { + Bound o = (Bound)other; + return arg.equals(o.getArg()); + } + return false; + } + + @Override + public int hashCode() { + return arg.hashCode() ^ "Bound".hashCode(); + } + + @Override + public Bound clone() { + Bound clone = (Bound)super.clone(); + clone.setArg(getArg().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Clear.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Clear.java new file mode 100644 index 00000000000..0408ead8ffb --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Clear.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope; + +/** + * @author jeen + */ +public class Clear extends AbstractQueryModelNode implements UpdateExpr { + + private ValueConstant graph; + + private boolean silent; + + private Scope scope; + + public Clear() { + super(); + } + + public Clear(ValueConstant graph) { + super(); + setGraph(graph); + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (graph != null) { + graph.visit(visitor); + } + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (graph == current) { + setGraph((ValueConstant)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if(other instanceof Clear) { + Clear o = (Clear)other; + return silent == o.silent + && nullEquals(graph, o.graph) + && nullEquals(scope, o.scope); + } + return false; + } + + @Override + public int hashCode() { + int result = silent ? 1 :0; + if(graph != null) { + result ^= graph.hashCode(); + } + if(scope != null) { + result ^= scope.hashCode(); + } + return result; + } + + @Override + public Clear clone() { + Clear clone = new Clear(); + clone.setSilent(isSilent()); + if (getGraph() != null) { + clone.setGraph(getGraph().clone()); + } + return clone; + } + + /** + * @param graph + * The graph to set. + */ + public void setGraph(ValueConstant graph) { + this.graph = graph; + } + + /** + * @return Returns the graph. + */ + public ValueConstant getGraph() { + return graph; + } + + /** + * @param silent The silent to set. + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + /** + * @return Returns the silent. + */ + @Override + public boolean isSilent() { + return silent; + } + + /** + * @param scope The scope to set. + */ + public void setScope(Scope scope) { + this.scope = scope; + } + + /** + * @return Returns the scope. + */ + public Scope getScope() { + return scope; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Coalesce.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Coalesce.java new file mode 100644 index 00000000000..40065bcfc24 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Coalesce.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + + +/** + * + * @author Jeen + */ +public class Coalesce extends NAryValueOperator { + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Compare.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Compare.java new file mode 100644 index 00000000000..d5b3a964db4 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Compare.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * A comparison between two values. + */ +public class Compare extends BinaryValueOperator { + + /*---------------* + * enum Operator * + *---------------*/ + + public enum CompareOp { + /** equal to */ + EQ("="), + + /** not equal to */ + NE("!="), + + /** lower than */ + LT("<"), + + /** lower than or equal to */ + LE("<="), + + /** greater than or equal to */ + GE(">="), + + /** greater than */ + GT(">"); + + private String symbol; + + CompareOp(String symbol) { + this.symbol = symbol; + } + + public String getSymbol() { + return symbol; + } + } + + /*-----------* + * Variables * + *-----------*/ + + private CompareOp operator; + + /*--------------* + * Constructors * + *--------------*/ + + public Compare() { + } + + public Compare(ValueExpr leftArg, ValueExpr rightArg) { + this(leftArg, rightArg, CompareOp.EQ); + } + + public Compare(ValueExpr leftArg, ValueExpr rightArg, CompareOp operator) { + super(leftArg, rightArg); + setOperator(operator); + } + + /*---------* + * Methods * + *---------*/ + + public CompareOp getOperator() { + return operator; + } + + public void setOperator(CompareOp operator) { + assert operator != null : "operator must not be null"; + this.operator = operator; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public String getSignature() { + return super.getSignature() + " (" + operator.getSymbol() + ")"; + } + + @Override + public boolean equals(Object other) { + if (other instanceof Compare && super.equals(other)) { + Compare o = (Compare)other; + return operator.equals(o.getOperator()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ operator.hashCode(); + } + + @Override + public Compare clone() { + return (Compare)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareAll.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareAll.java new file mode 100644 index 00000000000..1cf59fb3ab3 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareAll.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; + +/** + */ +public class CompareAll extends CompareSubQueryValueOperator { + + /*-----------* + * Variables * + *-----------*/ + + private CompareOp operator; + + /*--------------* + * Constructors * + *--------------*/ + + public CompareAll() { + } + + public CompareAll(ValueExpr valueExpr, TupleExpr subQuery, CompareOp operator) { + super(valueExpr, subQuery); + setOperator(operator); + } + + /*---------* + * Methods * + *---------*/ + + public CompareOp getOperator() { + return operator; + } + + public void setOperator(CompareOp operator) { + assert operator != null : "operator must not be null"; + this.operator = operator; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public String getSignature() { + return super.getSignature() + " (" + operator.getSymbol() + ")"; + } + + @Override + public boolean equals(Object other) { + if (other instanceof CompareAll && super.equals(other)) { + CompareAll o = (CompareAll)other; + return operator.equals(o.getOperator()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ operator.hashCode() ^ "CompareAll".hashCode(); + } + + @Override + public CompareAll clone() { + return (CompareAll)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareAny.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareAny.java new file mode 100644 index 00000000000..fdf25fba877 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareAny.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; + +/** + */ +public class CompareAny extends CompareSubQueryValueOperator { + + /*-----------* + * Variables * + *-----------*/ + + private CompareOp operator; + + /*--------------* + * Constructors * + *--------------*/ + + public CompareAny() { + } + + public CompareAny(ValueExpr valueExpr, TupleExpr subQuery, CompareOp operator) { + super(valueExpr, subQuery); + setOperator(operator); + } + + /*---------* + * Methods * + *---------*/ + + public CompareOp getOperator() { + return operator; + } + + public void setOperator(CompareOp operator) { + assert operator != null : "operator must not be null"; + this.operator = operator; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public String getSignature() { + return super.getSignature() + " (" + operator.getSymbol() + ")"; + } + + @Override + public boolean equals(Object other) { + if (other instanceof CompareAny && super.equals(other)) { + CompareAny o = (CompareAny)other; + return operator.equals(o.getOperator()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ operator.hashCode() ^ "CompareAny".hashCode(); + } + + @Override + public CompareAny clone() { + return (CompareAny)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareSubQueryValueOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareSubQueryValueOperator.java new file mode 100644 index 00000000000..1166d6410f0 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/CompareSubQueryValueOperator.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public abstract class CompareSubQueryValueOperator extends SubQueryValueOperator { + + /*-----------* + * Variables * + *-----------*/ + + protected ValueExpr arg; + + /*--------------* + * Constructors * + *--------------*/ + + public CompareSubQueryValueOperator() { + } + + public CompareSubQueryValueOperator(ValueExpr valueExpr, TupleExpr subQuery) { + super(subQuery); + setArg(valueExpr); + } + + /*---------* + * Methods * + *---------*/ + + public ValueExpr getArg() { + return arg; + } + + public void setArg(ValueExpr arg) { + assert arg != null : "arg must not be null"; + arg.setParentNode(this); + this.arg = arg; + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + arg.visit(visitor); + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (arg == current) { + setArg((ValueExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof CompareSubQueryValueOperator && super.equals(other)) { + CompareSubQueryValueOperator o = (CompareSubQueryValueOperator)other; + return arg.equals(o.getArg()); + } + + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ arg.hashCode(); + } + + @Override + public CompareSubQueryValueOperator clone() { + CompareSubQueryValueOperator clone = (CompareSubQueryValueOperator)super.clone(); + clone.setArg(getArg().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Copy.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Copy.java new file mode 100644 index 00000000000..5b35b3636c9 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Copy.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author jeen + */ +public class Copy extends AbstractQueryModelNode implements UpdateExpr { + + private ValueConstant sourceGraph; + + private ValueConstant destinationGraph; + + private boolean silent; + + public Copy() { + super(); + } + + public Copy(ValueConstant graph) { + super(); + setSourceGraph(graph); + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (sourceGraph != null) { + sourceGraph.visit(visitor); + } + if (destinationGraph != null) { + destinationGraph.visit(visitor); + } + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (sourceGraph == current) { + setSourceGraph((ValueConstant)replacement); + } + else if (destinationGraph == current) { + setDestinationGraph((ValueConstant)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if(other instanceof Copy) { + Copy o = (Copy)other; + return silent == o.silent + && nullEquals(sourceGraph, o.sourceGraph) + && nullEquals(destinationGraph, o.destinationGraph); + } + return false; + } + + @Override + public int hashCode() { + int result = silent ? 1 :0; + if(sourceGraph != null) { + result ^= sourceGraph.hashCode(); + } + if(destinationGraph != null) { + result ^= destinationGraph.hashCode(); + } + return result; + } + + @Override + public Copy clone() { + Copy clone = new Copy(); + clone.setSilent(isSilent()); + if (getSourceGraph() != null) { + clone.setSourceGraph(getSourceGraph().clone()); + } + return clone; + } + + /** + * @param graph + * The graph to set. + */ + public void setSourceGraph(ValueConstant graph) { + this.sourceGraph = graph; + } + + /** + * The named graph from which to copy. If null, the default graph should be + * used. + * + * @return Returns the graph. + */ + public ValueConstant getSourceGraph() { + return sourceGraph; + } + + /** + * @param silent + * The silent to set. + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + /** + * @return Returns the silent. + */ + @Override + public boolean isSilent() { + return silent; + } + + /** + * @param destinationGraph + * The destinationGraph to set. + */ + public void setDestinationGraph(ValueConstant destinationGraph) { + this.destinationGraph = destinationGraph; + } + + /** + * The named graph to which to copy. If null, the default graph should be + * used. + * + * @return Returns the destinationGraph. + */ + public ValueConstant getDestinationGraph() { + return destinationGraph; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Count.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Count.java new file mode 100644 index 00000000000..429bea5755d --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Count.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author David Huynh + * @author Jeen Broekstra + */ +public class Count extends AbstractAggregateOperator { + + public Count(ValueExpr arg) { + super(arg); + } + + public Count(ValueExpr arg, boolean distinct) { + super(arg, distinct); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Count && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Count".hashCode(); + } + + @Override + public Count clone() { + return (Count)super.clone(); + } + + @Override + public String getSignature() { + String signature = super.getSignature(); + if (isDistinct()) { + signature += " (Distinct)"; + } + return signature; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Create.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Create.java new file mode 100644 index 00000000000..b2990b4a9cd --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Create.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + + +/** + * @author jeen + */ +public class Create extends AbstractQueryModelNode implements UpdateExpr { + + private ValueConstant graph; + + private boolean silent; + + public Create() { + super(); + } + + public Create(ValueConstant graph) { + super(); + setGraph(graph); + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (graph != null) { + graph.visit(visitor); + } + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (graph == current) { + setGraph((ValueConstant)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if(other instanceof Create) { + Create o = (Create)other; + return silent == o.silent + && nullEquals(graph, o.graph); + } + return false; + } + + @Override + public int hashCode() { + int result = silent ? 1 :0; + if(graph != null) { + result ^= graph.hashCode(); + } + return result; + } + + @Override + public Create clone() { + Create clone = new Create(); + clone.setSilent(isSilent()); + if (getGraph() != null) { + clone.setGraph(getGraph().clone()); + } + return clone; + } + + /** + * @param graph + * The graph to set. + */ + public void setGraph(ValueConstant graph) { + this.graph = graph; + } + + /** + * @return Returns the graph. + */ + public ValueConstant getGraph() { + return graph; + } + + /** + * @param silent The silent to set. + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + /** + * @return Returns the silent. + */ + @Override + public boolean isSilent() { + return silent; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Datatype.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Datatype.java new file mode 100644 index 00000000000..c0744371dbe --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Datatype.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The DATATYPE function, as defined in SPARQL Query + * Language for RDF. + * + * @author Arjohn Kampman + */ +public class Datatype extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Datatype() { + } + + public Datatype(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Datatype && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Datatype".hashCode(); + } + + @Override + public Datatype clone() { + return (Datatype)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/DeleteData.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/DeleteData.java new file mode 100644 index 00000000000..4b820488d31 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/DeleteData.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author jeen + */ +public class DeleteData extends AbstractQueryModelNode implements UpdateExpr { + + private final String dataBlock; + + public DeleteData(String dataBlock) { + this.dataBlock = dataBlock; + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + public String getDataBlock() { + return dataBlock; + } + + @Override + public boolean equals(Object other) { + if(other instanceof DeleteData) { + DeleteData o = (DeleteData)other; + return dataBlock.equals(o.dataBlock); + } + return false; + } + + @Override + public int hashCode() { + return dataBlock.hashCode(); + } + + @Override + public DeleteData clone() { + return new DeleteData(dataBlock); + } + + @Override + public boolean isSilent() { + return false; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/DescribeOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/DescribeOperator.java new file mode 100644 index 00000000000..1be8dcb9cf8 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/DescribeOperator.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author Jeen Broekstra + */ +public class DescribeOperator extends UnaryTupleOperator { + + public DescribeOperator(TupleExpr arg) { + super(arg); + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Difference.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Difference.java new file mode 100644 index 00000000000..00acffa1a15 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Difference.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.Set; + +/** + * The MINUS set operator, which returns the result of the left tuple + * expression, except for the results that are also returned by the right tuple + * expression. + */ +public class Difference extends BinaryTupleOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Difference() { + } + + /** + * Creates a new minus operator that operates on the two specified arguments. + * + * @param leftArg + * The left argument of the minus operator. + * @param rightArg + * The right argument of the minus operator. + */ + public Difference(TupleExpr leftArg, TupleExpr rightArg) { + super(leftArg, rightArg); + } + + /*---------* + * Methods * + *---------*/ + + public Set getBindingNames() { + return getLeftArg().getBindingNames(); + } + + public Set getAssuredBindingNames() { + return getLeftArg().getAssuredBindingNames(); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Difference && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Difference".hashCode(); + } + + @Override + public Difference clone() { + return (Difference)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Distinct.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Distinct.java new file mode 100644 index 00000000000..95125d29054 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Distinct.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public class Distinct extends UnaryTupleOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Distinct() { + } + + public Distinct(TupleExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Distinct && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Distinct".hashCode(); + } + + @Override + public Distinct clone() { + return (Distinct)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/EmptySet.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/EmptySet.java new file mode 100644 index 00000000000..c5063725074 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/EmptySet.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.Collections; +import java.util.Set; + +/** + * A tuple expression that contains zero solutions. + */ +public class EmptySet extends AbstractQueryModelNode implements TupleExpr { + + public Set getBindingNames() { + return getAssuredBindingNames(); + } + + public Set getAssuredBindingNames() { + return Collections.emptySet(); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof EmptySet; + } + + @Override + public int hashCode() { + return "EmptySet".hashCode(); + } + + @Override + public EmptySet clone() { + return (EmptySet)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Exists.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Exists.java new file mode 100644 index 00000000000..a2847bba4ec --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Exists.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * Checks whether the wrapped Query produces any results. + */ +public class Exists extends SubQueryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Exists() { + } + + public Exists(TupleExpr subQuery) { + super(subQuery); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Exists && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Exists".hashCode(); + } + + @Override + public Exists clone() { + return (Exists)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Extension.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Extension.java new file mode 100644 index 00000000000..bb6805f0f10 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Extension.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +/** + * An extension operator that can be used to add bindings to solutions whose + * values are defined by {@link ValueExpr value expressions}. + */ +public class Extension extends UnaryTupleOperator { + + /*-----------* + * Variables * + *-----------*/ + + private List elements = new ArrayList(); + + /*--------------* + * Constructors * + *--------------*/ + + public Extension() { + } + + public Extension(TupleExpr arg) { + super(arg); + } + + public Extension(TupleExpr arg, ExtensionElem... elements) { + this(arg); + addElements(elements); + } + + public Extension(TupleExpr arg, Iterable elements) { + this(arg); + addElements(elements); + } + + /*---------* + * Methods * + *---------*/ + + public List getElements() { + return elements; + } + + public void setElements(Iterable elements) { + this.elements.clear(); + addElements(elements); + } + + public void addElements(ExtensionElem... elements) { + for (ExtensionElem pe : elements) { + addElement(pe); + } + } + + public void addElements(Iterable elements) { + for (ExtensionElem pe : elements) { + addElement(pe); + } + } + + public void addElement(ExtensionElem pe) { + elements.add(pe); + pe.setParentNode(this); + } + + @Override + public Set getBindingNames() { + Set bindingNames = new LinkedHashSet(arg.getBindingNames()); + + for (ExtensionElem pe : elements) { + bindingNames.add(pe.getName()); + } + + return bindingNames; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + for (ExtensionElem elem : elements) { + elem.visit(visitor); + } + + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (replaceNodeInList(elements, current, replacement)) { + return; + } + super.replaceChildNode(current, replacement); + } + + @Override + public boolean equals(Object other) { + if (other instanceof Extension && super.equals(other)) { + Extension o = (Extension)other; + return elements.equals(o.getElements()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ elements.hashCode(); + } + + @Override + public Extension clone() { + Extension clone = (Extension)super.clone(); + + clone.elements = new ArrayList(getElements().size()); + for (ExtensionElem elem : getElements()) { + clone.addElement(elem.clone()); + } + + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ExtensionElem.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ExtensionElem.java new file mode 100644 index 00000000000..1df60f01266 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ExtensionElem.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public class ExtensionElem extends AbstractQueryModelNode { + + /*-----------* + * Variables * + *-----------*/ + + private ValueExpr expr; + + private String name; + + /*--------------* + * Constructors * + *--------------*/ + + public ExtensionElem() { + } + + public ExtensionElem(ValueExpr expr, String name) { + setExpr(expr); + setName(name); + } + + /*---------* + * Methods * + *---------*/ + + public ValueExpr getExpr() { + return expr; + } + + public void setExpr(ValueExpr expr) { + assert expr != null : "expr must not be null"; + expr.setParentNode(this); + this.expr = expr; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + expr.visit(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (expr == current) { + setExpr((ValueExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public String getSignature() { + return super.getSignature() + " (" + name + ")"; + } + + @Override + public boolean equals(Object other) { + if (other instanceof ExtensionElem) { + ExtensionElem o = (ExtensionElem)other; + return name.equals(o.getName()) && expr.equals(o.getExpr()); + } + return false; + } + + @Override + public int hashCode() { + return name.hashCode() ^ expr.hashCode(); + } + + @Override + public ExtensionElem clone() { + ExtensionElem clone = (ExtensionElem)super.clone(); + clone.setExpr(getExpr().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Filter.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Filter.java new file mode 100644 index 00000000000..a5683dd9b62 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Filter.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The FILTER operator, as defined in SPARQL Query + * Language for RDF. The FILTER operator filters specific results from the + * underlying tuple expression based on a configurable condition. + * + * @author Arjohn Kampman + */ +public class Filter extends UnaryTupleOperator { + + /*-----------* + * Variables * + *-----------*/ + + private ValueExpr condition; + + /*--------------* + * Constructors * + *--------------*/ + + public Filter() { + } + + public Filter(TupleExpr arg, ValueExpr condition) { + super(arg); + setCondition(condition); + } + + /*---------* + * Methods * + *---------*/ + + public ValueExpr getCondition() { + return condition; + } + + public void setCondition(ValueExpr condition) { + assert condition != null : "condition must not be null"; + condition.setParentNode(this); + this.condition = condition; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + condition.visit(visitor); + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (condition == current) { + setCondition((ValueExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof Filter && super.equals(other)) { + Filter o = (Filter)other; + return condition.equals(o.getCondition()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ condition.hashCode(); + } + + @Override + public Filter clone() { + Filter clone = (Filter)super.clone(); + clone.setCondition(getCondition().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/FunctionCall.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/FunctionCall.java new file mode 100644 index 00000000000..bff9bc1c91d --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/FunctionCall.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.List; + +/** + * A call to an (external) function that operates on zero or more arguments. + * + * @author Arjohn Kampman + */ +public class FunctionCall extends AbstractQueryModelNode implements ValueExpr { + + /*-----------* + * Variables * + *-----------*/ + + protected String uri; + + /** + * The operator's argument. + */ + protected List args = new ArrayList(); + + /*--------------* + * Constructors * + *--------------*/ + + public FunctionCall() { + } + + /** + * Creates a new unary value operator. + * + * @param args + * The operator's argument, must not be null. + */ + public FunctionCall(String uri, ValueExpr... args) { + setURI(uri); + addArgs(args); + } + + public FunctionCall(String uri, Iterable args) { + setURI(uri); + addArgs(args); + } + + /*---------* + * Methods * + *---------*/ + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public List getArgs() { + return args; + } + + public void setArgs(Iterable args) { + this.args.clear(); + addArgs(args); + } + + public void addArgs(ValueExpr... args) { + for (ValueExpr arg : args) { + addArg(arg); + } + } + + public void addArgs(Iterable args) { + for (ValueExpr arg : args) { + addArg(arg); + } + } + + public void addArg(ValueExpr arg) { + assert arg != null : "arg must not be null"; + args.add(arg); + arg.setParentNode(this); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + for (ValueExpr arg : args) { + arg.visit(visitor); + } + + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (replaceNodeInList(args, current, replacement)) { + return; + } + super.replaceChildNode(current, replacement); + } + + @Override + public boolean equals(Object other) { + if (other instanceof FunctionCall) { + FunctionCall o = (FunctionCall)other; + return uri.equals(o.getURI()) && args.equals(o.getArgs()); + } + return false; + } + + @Override + public int hashCode() { + return uri.hashCode() ^ args.hashCode(); + } + + @Override + public FunctionCall clone() { + FunctionCall clone = (FunctionCall)super.clone(); + + clone.args = new ArrayList(getArgs().size()); + for (ValueExpr arg : getArgs()) { + clone.addArg(arg.clone()); + } + + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Group.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Group.java new file mode 100644 index 00000000000..df5cd339b52 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Group.java @@ -0,0 +1,188 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.util.iterators.Iterators; + +/** + * A tuple operator that groups tuples that have a specific set of equivalent + * variable bindings, and that can apply aggregate functions on the grouped + * results. + * + * @author David Huynh + * @author Arjohn Kampman + */ +public class Group extends UnaryTupleOperator { + + /*-----------* + * Variables * + *-----------*/ + + private Set groupBindings = new LinkedHashSet(); + + private List groupElements = new ArrayList(); + + /*--------------* + * Constructors * + *--------------*/ + + public Group(TupleExpr arg) { + super(arg); + } + + public Group(TupleExpr arg, Iterable groupBindingNames) { + this(arg); + setGroupBindingNames(groupBindingNames); + } + + public Group(TupleExpr arg, Iterable groupBindingNames, Iterable groupElements) { + this(arg, groupBindingNames); + setGroupElements(groupElements); + } + + /*---------* + * Methods * + *---------*/ + + public Set getGroupBindingNames() { + return Collections.unmodifiableSet(groupBindings); + } + + public void addGroupBindingName(String bindingName) { + groupBindings.add(bindingName); + } + + public void setGroupBindingNames(Iterable bindingNames) { + groupBindings.clear(); + Iterators.addAll(bindingNames.iterator(), groupBindings); + } + + public List getGroupElements() { + return Collections.unmodifiableList(groupElements); + } + + public void addGroupElement(GroupElem groupElem) { + groupElements.add(groupElem); + } + + public void setGroupElements(Iterable elements) { + this.groupElements.clear(); + Iterators.addAll(elements.iterator(), this.groupElements); + } + + public Set getAggregateBindingNames() { + Set bindings = new HashSet(); + + for (GroupElem binding : groupElements) { + bindings.add(binding.getName()); + } + + return bindings; + } + + @Override + public Set getBindingNames() { + Set bindingNames = new LinkedHashSet(); + + bindingNames.addAll(getGroupBindingNames()); + bindingNames.addAll(getAggregateBindingNames()); + + return bindingNames; + } + + @Override + public Set getAssuredBindingNames() { + Set bindingNames = new LinkedHashSet(); + + bindingNames.addAll(getGroupBindingNames()); + bindingNames.retainAll(getArg().getAssuredBindingNames()); + + return bindingNames; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + super.visitChildren(visitor); + + for (GroupElem ge : groupElements) { + ge.visit(visitor); + } + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + + if (replaceNodeInList(groupElements, current, replacement)) { + return; + } + super.replaceChildNode(current, replacement); + } + + @Override + public boolean equals(Object other) { + if (other instanceof Group && super.equals(other)) { + Group o = (Group)other; + return groupBindings.equals(o.getGroupBindingNames()) + && groupElements.equals(o.getGroupElements()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ groupBindings.hashCode() ^ groupElements.hashCode(); + } + + @Override + public Group clone() { + Group clone = (Group)super.clone(); + + clone.groupBindings = new LinkedHashSet(getGroupBindingNames()); + + clone.groupElements = new ArrayList(getGroupElements().size()); + for (GroupElem ge : getGroupElements()) { + clone.addGroupElement(ge.clone()); + } + + return clone; + } + + @Override + public String getSignature() { + StringBuilder b = new StringBuilder(); + b.append(this.getClass().getSimpleName()); + b.append(" ("); + + Set bindingNames = getGroupBindingNames(); + int count = 0; + for (String name: bindingNames) { + b.append(name); + count++; + if (count < bindingNames.size()) { + b.append(", "); + } + } + b.append(")"); + return b.toString(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/GroupConcat.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/GroupConcat.java new file mode 100644 index 00000000000..54226096815 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/GroupConcat.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The GROUP_CONCAT operator as defined in http://www.w3.org/TR/sparql11-query/#aggregates + * + * @author Jeen Broekstra + */ +public class GroupConcat extends AbstractAggregateOperator { + + private ValueExpr separator; + + public GroupConcat(ValueExpr arg) { + super(arg); + } + + public GroupConcat(ValueExpr arg, boolean distinct) { + super(arg, distinct); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof GroupConcat && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Group_Concat".hashCode(); + } + + @Override + public GroupConcat clone() { + return (GroupConcat)super.clone(); + } + + public ValueExpr getSeparator() { + return separator; + } + + public void setSeparator(ValueExpr separator) { + this.separator = separator; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/GroupElem.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/GroupElem.java new file mode 100644 index 00000000000..35121937470 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/GroupElem.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * A tuple operator that groups tuples that have a specific set of equivalent + * variable bindings, and that can apply aggregate functions on the grouped + * results. + * + * @author David Huynh + * @author Arjohn Kampman + */ +public class GroupElem extends AbstractQueryModelNode { + + /*-----------* + * Variables * + *-----------*/ + + private String name; + + private AggregateOperator operator; + + /*--------------* + * Constructors * + *--------------*/ + + public GroupElem(String name, AggregateOperator operator) { + setName(name); + setOperator(operator); + } + + /*---------* + * Methods * + *---------*/ + + public String getName() { + return name; + } + + public void setName(String name) { + assert name != null : "name must not be null"; + this.name = name; + } + + public AggregateOperator getOperator() { + return operator; + } + + public void setOperator(AggregateOperator operator) { + assert operator != null : "operator must not be null"; + this.operator = operator; + operator.setParentNode(this); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + operator.visit(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (operator == current) { + setOperator((AggregateOperator)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof GroupElem) { + GroupElem o = (GroupElem)other; + return name.equals(o.getName()) && operator.equals(o.getOperator()); + } + return false; + } + + @Override + public int hashCode() { + return name.hashCode() ^ operator.hashCode(); + } + + @Override + public GroupElem clone() { + GroupElem clone = (GroupElem)super.clone(); + clone.setOperator(getOperator().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IRIFunction.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IRIFunction.java new file mode 100644 index 00000000000..0c85484e63c --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IRIFunction.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The IRI function, as defined in SPARQL 1.1 Query + * Language for RDF. + * + * @author Jeen Broekstra + */ +public class IRIFunction extends UnaryValueOperator { + + private String baseURI; + + /*--------------* + * Constructors * + *--------------*/ + + public IRIFunction() { + } + + public IRIFunction(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof IRIFunction && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "IRI".hashCode(); + } + + @Override + public IRIFunction clone() { + return (IRIFunction)super.clone(); + } + + /** + * @param baseURI The baseURI to set. + */ + public void setBaseURI(String baseURI) { + this.baseURI = baseURI; + } + + /** + * @return Returns the baseURI. + */ + public String getBaseURI() { + return baseURI; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/If.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/If.java new file mode 100644 index 00000000000..b55aef8aa4f --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/If.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The IF function, as defined in SPARQL 1.1 Query. + * + * @author Jeen Broekstra + */ +public class If extends AbstractQueryModelNode implements ValueExpr { + + /*-----------* + * Variables * + *-----------*/ + + /** + * The operator's arguments. + */ + private ValueExpr condition; + + private ValueExpr result; + + private ValueExpr alternative; + + /*--------------* + * Constructors * + *--------------*/ + + public If() { + } + + public If(ValueExpr condition) { + setCondition(condition); + } + + public If(ValueExpr condition, ValueExpr result) { + setCondition(condition); + setResult(result); + } + + public If(ValueExpr condition, ValueExpr result, ValueExpr alternative) { + setCondition(condition); + setResult(result); + setAlternative(alternative); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the argument of this unary value operator. + * + * @return The operator's argument. + */ + public ValueExpr getCondition() { + return condition; + } + + /** + * Sets the condition argument of this unary value operator. + * + * @param condition + * The (new) condition argument for this operator, must not be + * null. + */ + public void setCondition(ValueExpr condition) { + assert condition != null : "arg must not be null"; + condition.setParentNode(this); + this.condition = condition; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + condition.visit(visitor); + if (result != null) { + result.visit(visitor); + } + if (alternative != null) { + alternative.visit(visitor); + } + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (condition == current) { + setCondition((ValueExpr)replacement); + } + else if (result == current) { + setResult((ValueExpr)replacement); + } + else if (alternative == current) { + setAlternative((ValueExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof If) { + If o = (If)other; + + boolean equal = condition.equals(o.getCondition()); + if (!equal) { + return equal; + } + + equal = (result == null) ? o.getResult() == null : result.equals(o.getResult()); + if (!equal) { + return equal; + } + + equal = (alternative == null) ? o.getAlternative() == null : alternative.equals(o.getAlternative()); + + return equal; + } + return false; + } + + @Override + public int hashCode() { + int hashCode = condition.hashCode(); + + if (result != null) { + hashCode = hashCode ^ result.hashCode(); + } + if (alternative != null) { + hashCode = hashCode ^ alternative.hashCode(); + } + + hashCode = hashCode ^ "If".hashCode(); + + return hashCode; + } + + @Override + public If clone() { + If clone = (If)super.clone(); + clone.setCondition(condition.clone()); + if (result != null) { + clone.setResult(result.clone()); + } + if (alternative != null) { + clone.setAlternative(alternative.clone()); + } + return clone; + } + + /** + * @param result + * The result to set. + */ + public void setResult(ValueExpr result) { + result.setParentNode(this); + this.result = result; + + } + + /** + * @return Returns the result. + */ + public ValueExpr getResult() { + return result; + } + + /** + * @param alternative + * The alternative to set. + */ + public void setAlternative(ValueExpr alternative) { + alternative.setParentNode(this); + this.alternative = alternative; + } + + /** + * @return Returns the alternative. + */ + public ValueExpr getAlternative() { + return alternative; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/In.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/In.java new file mode 100644 index 00000000000..4ee7c5f279d --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/In.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * Checks whether a certain value is contained in a set of results produced by a + * query. + */ +public class In extends CompareSubQueryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public In() { + } + + public In(ValueExpr valueExpr, TupleExpr subQuery) { + super(valueExpr, subQuery); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof In && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "In".hashCode(); + } + + @Override + public In clone() { + return (In)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/InsertData.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/InsertData.java new file mode 100644 index 00000000000..be75f18c115 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/InsertData.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author jeen + */ +public class InsertData extends AbstractQueryModelNode implements UpdateExpr { + + private final String dataBlock; + + public InsertData(String dataBlock) { + this.dataBlock = dataBlock; + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + public String getDataBlock() { + return dataBlock; + } + + + @Override + public boolean equals(Object other) { + if(other instanceof InsertData) { + InsertData o = (InsertData)other; + return dataBlock.equals(o.dataBlock); + } + return false; + } + + @Override + public int hashCode() { + return dataBlock.hashCode(); + } + + @Override + public InsertData clone() { + return new InsertData(dataBlock); + } + + @Override + public boolean isSilent() { + return false; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Intersection.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Intersection.java new file mode 100644 index 00000000000..cc3b9d21d3e --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Intersection.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * The INTERSECT set operator, which returns the intersection of the result sets + * of two tuple expressions. + */ +public class Intersection extends BinaryTupleOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Intersection() { + } + + /** + * Creates a new intersection operator that operates on the two specified + * arguments. + * + * @param leftArg + * The left argument of the intersection operator. + * @param rightArg + * The right argument of the intersection operator. + */ + public Intersection(TupleExpr leftArg, TupleExpr rightArg) { + super(leftArg, rightArg); + } + + /*---------* + * Methods * + *---------*/ + + public Set getBindingNames() { + Set bindingNames = new LinkedHashSet(16); + bindingNames.addAll(getLeftArg().getBindingNames()); + bindingNames.retainAll(getRightArg().getBindingNames()); + return bindingNames; + } + + public Set getAssuredBindingNames() { + Set bindingNames = new LinkedHashSet(16); + bindingNames.addAll(getLeftArg().getAssuredBindingNames()); + bindingNames.retainAll(getRightArg().getAssuredBindingNames()); + return bindingNames; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Intersection && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Intersection".hashCode(); + } + + @Override + public Intersection clone() { + return (Intersection)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsBNode.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsBNode.java new file mode 100644 index 00000000000..5a57c388b96 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsBNode.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public class IsBNode extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public IsBNode() { + } + + public IsBNode(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof IsBNode && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "IsBNode".hashCode(); + } + + @Override + public IsBNode clone() { + return (IsBNode)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsLiteral.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsLiteral.java new file mode 100644 index 00000000000..5268f6882c7 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsLiteral.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public class IsLiteral extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public IsLiteral() { + } + + public IsLiteral(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof IsLiteral && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "IsLiteral".hashCode(); + } + + @Override + public IsLiteral clone() { + return (IsLiteral)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsNumeric.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsNumeric.java new file mode 100644 index 00000000000..0b178a4b9c4 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsNumeric.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * IsNumeric - Boolean operator determining if the supplied expression + * represents a numeric value. + * + * @author Jeen + */ +public class IsNumeric extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public IsNumeric() { + } + + public IsNumeric(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof IsNumeric && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "IsNumeric".hashCode(); + } + + @Override + public IsNumeric clone() { + return (IsNumeric)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsResource.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsResource.java new file mode 100644 index 00000000000..88702752453 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsResource.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public class IsResource extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public IsResource() { + } + + public IsResource(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof IsResource && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() & "IsResource".hashCode(); + } + + @Override + public IsResource clone() { + return (IsResource)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsURI.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsURI.java new file mode 100644 index 00000000000..a476a8fc8d8 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/IsURI.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public class IsURI extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public IsURI() { + } + + public IsURI(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof IsURI && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "IsURI".hashCode(); + } + + @Override + public IsURI clone() { + return (IsURI)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Join.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Join.java new file mode 100644 index 00000000000..22a57667157 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Join.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; +import org.eclipse.rdf4j.query.algebra.helpers.TupleExprs; + +/** + * A natural join between two tuple expressions. + */ +public class Join extends BinaryTupleOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Join() { + } + + /** + * Creates a new natural join operator. + */ + public Join(TupleExpr leftArg, TupleExpr rightArg) { + super(leftArg, rightArg); + } + + /*---------* + * Methods * + *---------*/ + + /** + * @deprecated Since 2.7.3. Use + * {@link TupleExprs#containsProjection(TupleExpr)} instead. + * @return true if the right argument of this Join contains a + * projection, false otherwise. + */ + @Deprecated + public boolean hasSubSelectInRightArg() { + return TupleExprs.containsProjection(rightArg); + } + + public Set getBindingNames() { + Set bindingNames = new LinkedHashSet(16); + bindingNames.addAll(getLeftArg().getBindingNames()); + bindingNames.addAll(getRightArg().getBindingNames()); + return bindingNames; + } + + public Set getAssuredBindingNames() { + Set bindingNames = new LinkedHashSet(16); + bindingNames.addAll(getLeftArg().getAssuredBindingNames()); + bindingNames.addAll(getRightArg().getAssuredBindingNames()); + return bindingNames; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Join && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Join".hashCode(); + } + + @Override + public Join clone() { + return (Join)super.clone(); + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Label.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Label.java new file mode 100644 index 00000000000..57375398d1e --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Label.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The LABEL function, which selects the label of literals. + * + * @author Arjohn Kampman + */ +public class Label extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Label() { + } + + public Label(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Label && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Label".hashCode(); + } + + @Override + public Label clone() { + return (Label)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Lang.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Lang.java new file mode 100644 index 00000000000..12964ec7213 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Lang.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The LANG function, as defined in SPARQL Query Language + * for RDF. + * + * @author Arjohn Kampman + */ +public class Lang extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Lang() { + } + + public Lang(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Lang && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Lang".hashCode(); + } + + @Override + public Lang clone() { + return (Lang)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LangMatches.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LangMatches.java new file mode 100644 index 00000000000..d0413456ada --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LangMatches.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * Checks whether a language tag (e.g. "en-US") matches some language range + * (e.g. "en" or "*"). + */ +public class LangMatches extends BinaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public LangMatches() { + } + + public LangMatches(ValueExpr leftArg, ValueExpr rightArg) { + super(leftArg, rightArg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof LangMatches && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "LangMatches".hashCode(); + } + + @Override + public LangMatches clone() { + return (LangMatches)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LeftJoin.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LeftJoin.java new file mode 100644 index 00000000000..da12e97182b --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LeftJoin.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * The LeftJoin operator, as defined in SPARQL Query + * Language for RDF. + * + * @author Arjohn Kampman + */ +public class LeftJoin extends BinaryTupleOperator { + + /*-----------* + * Variables * + *-----------*/ + + private ValueExpr condition; + + /*--------------* + * Constructors * + *--------------*/ + + public LeftJoin() { + } + + public LeftJoin(TupleExpr leftArg, TupleExpr rightArg) { + super(leftArg, rightArg); + } + + public LeftJoin(TupleExpr leftArg, TupleExpr rightArg, ValueExpr condition) { + this(leftArg, rightArg); + setCondition(condition); + } + + /*---------* + * Methods * + *---------*/ + + public ValueExpr getCondition() { + return condition; + } + + public void setCondition(ValueExpr condition) { + if (condition != null) { + condition.setParentNode(this); + } + this.condition = condition; + } + + public boolean hasCondition() { + return condition != null; + } + + public Set getBindingNames() { + Set bindingNames = new LinkedHashSet(16); + bindingNames.addAll(getLeftArg().getBindingNames()); + bindingNames.addAll(getRightArg().getBindingNames()); + return bindingNames; + } + + public Set getAssuredBindingNames() { + return getLeftArg().getAssuredBindingNames(); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (condition != null) { + condition.visit(visitor); + } + + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (condition == current) { + setCondition((ValueExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof LeftJoin && super.equals(other)) { + ValueExpr oCond = ((LeftJoin)other).getCondition(); + return nullEquals(condition, oCond); + } + + return false; + } + + @Override + public int hashCode() { + int result = super.hashCode() ^ "LeftJoin".hashCode(); + if (hasCondition()) { + result ^= getCondition().hashCode(); + } + return result; + } + + @Override + public LeftJoin clone() { + LeftJoin clone = (LeftJoin)super.clone(); + if (hasCondition()) { + clone.setCondition(getCondition().clone()); + } + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Like.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Like.java new file mode 100644 index 00000000000..e6de8752f75 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Like.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * Compares the string representation of a value expression to a pattern. + */ +public class Like extends UnaryValueOperator { + + /*-----------* + * Variables * + *-----------*/ + + private String pattern; + + private boolean caseSensitive; + + /** + * Operational pattern, equal to pattern but converted to lower case when not + * case sensitive. + */ + private String opPattern; + + /*--------------* + * Constructors * + *--------------*/ + + public Like() { + } + + public Like(ValueExpr expr, String pattern, boolean caseSensitive) { + super(expr); + setPattern(pattern, caseSensitive); + } + + /*---------* + * Methods * + *---------*/ + + public void setPattern(String pattern, boolean caseSensitive) { + assert pattern != null : "pattern must not be null"; + this.pattern = pattern; + this.caseSensitive = caseSensitive; + opPattern = caseSensitive ? pattern : pattern.toLowerCase(); + } + + public String getPattern() { + return pattern; + } + + public boolean isCaseSensitive() { + return caseSensitive; + } + + public String getOpPattern() { + return opPattern; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public String getSignature() { + StringBuilder sb = new StringBuilder(128); + + sb.append(super.getSignature()); + sb.append(" \""); + sb.append(pattern); + sb.append("\""); + + if (caseSensitive) { + sb.append(" IGNORE CASE"); + } + + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof Like && super.equals(other)) { + Like o = (Like)other; + return caseSensitive == o.isCaseSensitive() && opPattern.equals(o.getOpPattern()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ opPattern.hashCode(); + } + + @Override + public Like clone() { + return (Like)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ListMemberOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ListMemberOperator.java new file mode 100644 index 00000000000..175a298b2ce --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ListMemberOperator.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * ValueOperator that verifies if the first of its arguments occurs in any of + * the subsequent arguments. + * + * @since 2.7.4 + * @author Jeen Broekstra + */ +public class ListMemberOperator extends NAryValueOperator { + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof ListMemberOperator && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "ListMemberOperator".hashCode(); + } + + @Override + public ListMemberOperator clone() { + return (ListMemberOperator)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Load.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Load.java new file mode 100644 index 00000000000..142c64abcf3 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Load.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author jeen + */ +public class Load extends AbstractQueryModelNode implements UpdateExpr { + + private ValueConstant source; + + private ValueConstant graph; + + private boolean silent; + + public Load(ValueConstant source) { + setSource(source); + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (source != null) { + source.visit(visitor); + } + if (graph != null) { + graph.visit(visitor); + } + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (source == current) { + setSource((ValueConstant)current); + } + else if (graph == current) { + setGraph((ValueConstant)current); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if(other instanceof Load) { + Load o = (Load)other; + return silent == o.silent + && nullEquals(source, o.source) + && nullEquals(graph, o.graph); + } + return false; + } + + @Override + public int hashCode() { + int result = silent ? 1 :0; + if(source != null) { + result ^= source.hashCode(); + } + if(graph != null) { + result ^= graph.hashCode(); + } + return result; + } + + @Override + public Load clone() { + Load clone = new Load(source.clone()); + clone.setSilent(isSilent()); + if (getGraph() != null) { + clone.setGraph(getGraph().clone()); + } + return clone; + } + + /** + * @param graph + * The graph to set. + */ + public void setGraph(ValueConstant graph) { + this.graph = graph; + } + + /** + * @return Returns the graph. + */ + public ValueConstant getGraph() { + return graph; + } + + /** + * @param source + * The source to set. + */ + public void setSource(ValueConstant source) { + this.source = source; + } + + /** + * @return Returns the source. + */ + public ValueConstant getSource() { + return source; + } + + /** + * @param silent The silent to set. + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + /** + * @return Returns the silent. + */ + @Override + public boolean isSilent() { + return silent; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LocalName.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LocalName.java new file mode 100644 index 00000000000..7b85c4a5bff --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/LocalName.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The LOCAL NAME function, which selects the local name of URIs. + * + * @author Arjohn Kampman + */ +public class LocalName extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public LocalName() { + } + + public LocalName(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof LocalName && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "LocalName".hashCode(); + } + + @Override + public LocalName clone() { + return (LocalName)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/MathExpr.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/MathExpr.java new file mode 100644 index 00000000000..8859f9968ff --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/MathExpr.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * A mathematical expression consisting an operator and two arguments. + */ +public class MathExpr extends BinaryValueOperator { + + /*---------------* + * enum Operator * + *---------------*/ + + public enum MathOp { + PLUS("+"), + MINUS("-"), + MULTIPLY("*"), + DIVIDE("/"); + + private String symbol; + + MathOp(String symbol) { + this.symbol = symbol; + } + + public String getSymbol() { + return symbol; + } + } + + /*-----------* + * Variables * + *-----------*/ + + private MathOp operator; + + /*--------------* + * Constructors * + *--------------*/ + + public MathExpr() { + } + + public MathExpr(ValueExpr leftArg, ValueExpr rightArg, MathOp operator) { + super(leftArg, rightArg); + setOperator(operator); + } + + /*---------* + * Methods * + *---------*/ + + public MathOp getOperator() { + return operator; + } + + public void setOperator(MathOp operator) { + assert operator != null : "operator must not be null"; + this.operator = operator; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public String getSignature() { + return super.getSignature() + " (" + operator.getSymbol() + ")"; + } + + @Override + public boolean equals(Object other) { + if (other instanceof MathExpr && super.equals(other)) { + MathExpr o = (MathExpr)other; + return operator.equals(o.getOperator()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ operator.hashCode(); + } + + @Override + public MathExpr clone() { + return (MathExpr)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Max.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Max.java new file mode 100644 index 00000000000..63dab028c3a --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Max.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author David Huynh + */ +public class Max extends AbstractAggregateOperator { + + public Max(ValueExpr arg) { + super(arg); + } + + public Max(ValueExpr arg, boolean distinct) { + super(arg, distinct); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Max && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Max".hashCode(); + } + + @Override + public Max clone() { + return (Max)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Min.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Min.java new file mode 100644 index 00000000000..a907c8cf09c --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Min.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author David Huynh + */ +public class Min extends AbstractAggregateOperator { + + public Min(ValueExpr arg) { + super(arg); + } + + public Min(ValueExpr arg, boolean distinct) { + super(arg, distinct); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Min && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Min".hashCode(); + } + + @Override + public Min clone() { + return (Min)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Modify.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Modify.java new file mode 100644 index 00000000000..e63aff2663a --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Modify.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author jeen + */ +public class Modify extends AbstractQueryModelNode implements UpdateExpr { + + private TupleExpr deleteExpr; + + private TupleExpr insertExpr; + + private TupleExpr whereExpr; + + public Modify(TupleExpr deleteExpr, TupleExpr insertExpr) { + this(deleteExpr, insertExpr, null); + } + + public Modify(TupleExpr deleteExpr, TupleExpr insertExpr, TupleExpr whereExpr) { + setDeleteExpr(deleteExpr); + setInsertExpr(insertExpr); + setWhereExpr(whereExpr); + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (deleteExpr != null) { + deleteExpr.visit(visitor); + } + if (insertExpr != null) { + insertExpr.visit(visitor); + } + if (whereExpr != null) { + whereExpr.visit(visitor); + } + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (deleteExpr == current) { + setDeleteExpr((TupleExpr)replacement); + } + else if (insertExpr == current) { + setInsertExpr((TupleExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if(other instanceof Modify) { + Modify o = (Modify)other; + return nullEquals(deleteExpr, o.deleteExpr) + && nullEquals(insertExpr, o.insertExpr) + && nullEquals(whereExpr, o.whereExpr); + } + return false; + } + + @Override + public int hashCode() { + int result = 0; + if(deleteExpr != null) { + result ^= deleteExpr.hashCode(); + } + if(insertExpr != null) { + result ^= insertExpr.hashCode(); + } + if(whereExpr != null) { + result ^= whereExpr.hashCode(); + } + return result; + } + + @Override + public Modify clone() { + + TupleExpr deleteClone = deleteExpr != null ? deleteExpr.clone() : null; + TupleExpr insertClone = insertExpr != null ? insertExpr.clone() : null; + TupleExpr whereClone = whereExpr != null ? whereExpr.clone() : null; + return new Modify(deleteClone, insertClone, whereClone); + } + + /** + * @param deleteExpr + * The deleteExpr to set. + */ + public void setDeleteExpr(TupleExpr deleteExpr) { + this.deleteExpr = deleteExpr; + } + + /** + * @return Returns the deleteExpr. + */ + public TupleExpr getDeleteExpr() { + return deleteExpr; + } + + /** + * @param insertExpr + * The insertExpr to set. + */ + public void setInsertExpr(TupleExpr insertExpr) { + this.insertExpr = insertExpr; + } + + /** + * @return Returns the insertExpr. + */ + public TupleExpr getInsertExpr() { + return insertExpr; + } + + /** + * @param whereExpr The whereExpr to set. + */ + public void setWhereExpr(TupleExpr whereExpr) { + this.whereExpr = whereExpr; + } + + /** + * @return Returns the whereExpr. + */ + public TupleExpr getWhereExpr() { + return whereExpr; + } + + @Override + public boolean isSilent() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Move.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Move.java new file mode 100644 index 00000000000..f8caea6b279 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Move.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author jeen + */ +public class Move extends AbstractQueryModelNode implements UpdateExpr { + + private ValueConstant sourceGraph; + + private ValueConstant destinationGraph; + + private boolean silent; + + public Move() { + super(); + } + + public Move(ValueConstant graph) { + super(); + setSourceGraph(graph); + } + + @Override + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (sourceGraph != null) { + sourceGraph.visit(visitor); + } + if (destinationGraph != null) { + destinationGraph.visit(visitor); + } + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (sourceGraph == current) { + setSourceGraph((ValueConstant)replacement); + } + else if (destinationGraph == current) { + setDestinationGraph((ValueConstant)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if(other instanceof Move) { + Move o = (Move)other; + return silent == o.silent + && nullEquals(sourceGraph, o.sourceGraph) + && nullEquals(destinationGraph, o.destinationGraph); + } + return false; + } + + @Override + public int hashCode() { + int result = silent ? 1 :0; + if(sourceGraph != null) { + result ^= sourceGraph.hashCode(); + } + if(destinationGraph != null) { + result ^= destinationGraph.hashCode(); + } + return result; + } + + @Override + public Move clone() { + Move clone = new Move(); + clone.setSilent(isSilent()); + if (getSourceGraph() != null) { + clone.setSourceGraph(getSourceGraph().clone()); + } + return clone; + } + + /** + * @param graph + * The graph to set. + */ + public void setSourceGraph(ValueConstant graph) { + this.sourceGraph = graph; + } + + /** + * The named graph from which to copy. If null, the default graph should be + * used. + * + * @return Returns the graph. + */ + public ValueConstant getSourceGraph() { + return sourceGraph; + } + + /** + * @param silent + * The silent to set. + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + /** + * @return Returns the silent. + */ + @Override + public boolean isSilent() { + return silent; + } + + /** + * @param destinationGraph + * The destinationGraph to set. + */ + public void setDestinationGraph(ValueConstant destinationGraph) { + this.destinationGraph = destinationGraph; + } + + /** + * The named graph to which to copy. If null, the default graph should be + * used. + * + * @return Returns the destinationGraph. + */ + public ValueConstant getDestinationGraph() { + return destinationGraph; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/MultiProjection.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/MultiProjection.java new file mode 100644 index 00000000000..80bac447188 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/MultiProjection.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * A "multi-projection" that can produce multiple solutions from a single set of + * bindings. + */ +public class MultiProjection extends UnaryTupleOperator { + + /*-----------* + * Variables * + *-----------*/ + + /** + * The lists of projections. + */ + private List projections = new ArrayList(); + + /*--------------* + * Constructors * + *--------------*/ + + public MultiProjection() { + } + + public MultiProjection(TupleExpr arg) { + super(arg); + } + + public MultiProjection(TupleExpr arg, Iterable projections) { + this(arg); + addProjections(projections); + } + + /*---------* + * Methods * + *---------*/ + + public List getProjections() { + return Collections.unmodifiableList(projections); + } + + public void setProjections(Iterable projections) { + this.projections.clear(); + addProjections(projections); + } + + public void addProjections(Iterable projections) { + for (ProjectionElemList projection : projections) { + addProjection(projection); + } + } + + public void addProjection(ProjectionElemList projection) { + assert projection != null : "projection must not be null"; + projections.add(projection); + projection.setParentNode(this); + } + + @Override + public Set getBindingNames() { + Set bindingNames = new HashSet(); + + for (ProjectionElemList projElemList : projections) { + bindingNames.addAll(projElemList.getTargetNames()); + } + + return bindingNames; + } + + @Override + public Set getAssuredBindingNames() { + Set bindingNames = new HashSet(); + + if (projections.size() >= 1) { + Set assuredSourceNames = getArg().getAssuredBindingNames(); + + bindingNames.addAll(projections.get(0).getTargetNamesFor(assuredSourceNames)); + + for (int i = 1; i < projections.size(); i++) { + bindingNames.retainAll(projections.get(i).getTargetNamesFor(assuredSourceNames)); + } + } + + return bindingNames; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + for (ProjectionElemList projElemList : projections) { + projElemList.visit(visitor); + } + + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (replaceNodeInList(projections, current, replacement)) { + return; + } + super.replaceChildNode(current, replacement); + } + + @Override + public boolean equals(Object other) { + if (other instanceof MultiProjection && super.equals(other)) { + MultiProjection o = (MultiProjection)other; + return projections.equals(o.getProjections()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ projections.hashCode(); + } + + @Override + public MultiProjection clone() { + MultiProjection clone = (MultiProjection)super.clone(); + + clone.projections = new ArrayList(getProjections().size()); + for (ProjectionElemList pe : getProjections()) { + clone.addProjection(pe.clone()); + } + + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/NAryValueOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/NAryValueOperator.java new file mode 100644 index 00000000000..991fdb4093d --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/NAryValueOperator.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.List; + +/** + * An abstract superclass for N-ary value operators. + * + * @author Jeen + */ +public abstract class NAryValueOperator extends AbstractQueryModelNode implements ValueExpr { + + /*-----------* + * Variables * + *-----------*/ + + /** + * The operator's arguments. + */ + protected List args; + + /*--------------* + * Constructors * + *--------------*/ + + public NAryValueOperator() { + } + + /** + * Creates a new N-Ary value operator. + * + * @param args + * The operator's list of arguments, must not be null. + */ + public NAryValueOperator(List args) { + setArguments(args); + } + + /*---------* + * Methods * + *---------*/ + + public void setArguments(List args) { + this.args = args; + } + + public List getArguments() { + return this.args; + } + + public void addArgument(ValueExpr arg) { + if (args == null) { + args = new ArrayList(); + } + args.add(arg); + arg.setParentNode(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + for(ValueExpr arg: args) { + arg.visit(visitor); + } + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + + boolean replaced = false; + + for (int i =0 ; i < args.size(); i++ ) { + ValueExpr arg = args.get(i); + if (arg == current) { + args.remove(i); + args.add(i, (ValueExpr)replacement); + replaced = true; + } + } + + if (!replaced) { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof NAryValueOperator) { + NAryValueOperator o = (NAryValueOperator)other; + + return getArguments().equals(o.getArguments()); + } + + return false; + } + + @Override + public int hashCode() { + return getArguments().hashCode(); + } + + @Override + public NAryValueOperator clone() { + NAryValueOperator clone = (NAryValueOperator)super.clone(); + + clone.setArguments(new ArrayList()); + + for(ValueExpr arg: getArguments()) { + clone.addArgument(arg.clone()); + } + + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Namespace.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Namespace.java new file mode 100644 index 00000000000..6a202efde29 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Namespace.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The NAMESPACE function, which selects the namespace of URIs. + * + * @author Arjohn Kampman + */ +public class Namespace extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Namespace() { + } + + public Namespace(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Namespace && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Namespace".hashCode(); + } + + @Override + public Namespace clone() { + return (Namespace)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Not.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Not.java new file mode 100644 index 00000000000..6e8f9c87f7e --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Not.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * A boolean NOT operator operating on a boolean expressions. + */ +public class Not extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Not() { + } + + public Not(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Not && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Not".hashCode(); + } + + @Override + public Not clone() { + return (Not)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Or.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Or.java new file mode 100644 index 00000000000..05472f8b707 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Or.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * A boolean OR operator operating on two boolean expressions. + */ +public class Or extends BinaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Or() { + } + + public Or(ValueExpr leftArg, ValueExpr rightArg) { + super(leftArg, rightArg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Or && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Or".hashCode(); + } + + @Override + public Or clone() { + return (Or)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Order.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Order.java new file mode 100644 index 00000000000..24f6d0357ad --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Order.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.List; + +/** + * An order operator that can be used to order bindings as specified by a set of + * value expressions. + * + * @author Arjohn Kampman + */ +public class Order extends UnaryTupleOperator { + + /*-----------* + * Variables * + *-----------*/ + + private List elements = new ArrayList(); + + /*--------------* + * Constructors * + *--------------*/ + + public Order() { + } + + public Order(TupleExpr arg) { + super(arg); + } + + public Order(TupleExpr arg, OrderElem... elements) { + this(arg); + addElements(elements); + } + + public Order(TupleExpr arg, Iterable elements) { + this(arg); + addElements(elements); + } + + /*---------* + * Methods * + *---------*/ + + public List getElements() { + return elements; + } + + public void setElements(List elements) { + this.elements = elements; + } + + public void addElements(OrderElem... elements) { + for (OrderElem pe : elements) { + addElement(pe); + } + } + + public void addElements(Iterable elements) { + for (OrderElem pe : elements) { + addElement(pe); + } + } + + public void addElement(OrderElem pe) { + elements.add(pe); + pe.setParentNode(this); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + for (OrderElem elem : elements) { + elem.visit(visitor); + } + + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (replaceNodeInList(elements, current, replacement)) { + return; + } + super.replaceChildNode(current, replacement); + } + + @Override + public boolean equals(Object other) { + if (other instanceof Order && super.equals(other)) { + Order o = (Order)other; + return elements.equals(o.getElements()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ elements.hashCode(); + } + + @Override + public Order clone() { + Order clone = (Order)super.clone(); + + clone.elements = new ArrayList(getElements().size()); + for (OrderElem elem : getElements()) { + clone.addElement(elem.clone()); + } + + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/OrderElem.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/OrderElem.java new file mode 100644 index 00000000000..f439e01e396 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/OrderElem.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @author Arjohn Kampman + */ +public class OrderElem extends AbstractQueryModelNode { + + /*-----------* + * Variables * + *-----------*/ + + /** + * + */ + private static final long serialVersionUID = -6573481604435459287L; + + private ValueExpr expr; + + private boolean ascending = true; + + /*--------------* + * Constructors * + *--------------*/ + + public OrderElem() { + } + + public OrderElem(ValueExpr expr) { + this(expr, true); + } + + public OrderElem(ValueExpr expr, boolean ascending) { + setExpr(expr); + setAscending(ascending); + } + + /*---------* + * Methods * + *---------*/ + + public ValueExpr getExpr() { + return expr; + } + + public void setExpr(ValueExpr expr) { + assert expr != null : "expr must not be null"; + expr.setParentNode(this); + this.expr = expr; + } + + public boolean isAscending() { + return ascending; + } + + public void setAscending(boolean ascending) { + this.ascending = ascending; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + expr.visit(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (expr == current) { + setExpr((ValueExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public String getSignature() { + return super.getSignature() + " (" + (ascending ? "ASC" : "DESC") + ")"; + } + + @Override + public boolean equals(Object other) { + if (other instanceof OrderElem) { + OrderElem o = (OrderElem)other; + return ascending == o.isAscending() && expr.equals(o.getExpr()); + } + return false; + } + + @Override + public int hashCode() { + int result = expr.hashCode(); + if (ascending) { + result = ~result; + } + return result; + } + + @Override + public OrderElem clone() { + OrderElem clone = (OrderElem)super.clone(); + clone.setExpr(getExpr().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Projection.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Projection.java new file mode 100644 index 00000000000..13f3c09eb8a --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Projection.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.Set; + +/** + * A generalized projection (allowing the bindings to be renamed) on a tuple + * expression. + */ +public class Projection extends UnaryTupleOperator { + + /*-----------* + * Variables * + *-----------*/ + + private ProjectionElemList projElemList = new ProjectionElemList(); + + private Var projectionContext = null; + + /*--------------* + * Constructors * + *--------------*/ + + public Projection() { + } + + public Projection(TupleExpr arg) { + super(arg); + } + + public Projection(TupleExpr arg, ProjectionElemList elements) { + this(arg); + setProjectionElemList(elements); + } + + /*---------* + * Methods * + *---------*/ + + public ProjectionElemList getProjectionElemList() { + return projElemList; + } + + public void setProjectionElemList(ProjectionElemList projElemList) { + this.projElemList = projElemList; + projElemList.setParentNode(this); + } + + @Override + public Set getBindingNames() { + return projElemList.getTargetNames(); + } + + @Override + public Set getAssuredBindingNames() { + // Return all target binding names for which the source binding is assured + // by the argument + return projElemList.getTargetNamesFor(getArg().getAssuredBindingNames()); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + projElemList.visit(visitor); + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (projElemList == current) { + setProjectionElemList((ProjectionElemList)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof Projection && super.equals(other)) { + Projection o = (Projection)other; + return projElemList.equals(o.getProjectionElemList()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ projElemList.hashCode(); + } + + @Override + public Projection clone() { + Projection clone = (Projection)super.clone(); + clone.setProjectionElemList(getProjectionElemList().clone()); + return clone; + } + + /** + * @return Returns the projectionContext. + */ + public Var getProjectionContext() { + return projectionContext; + } + + /** + * @param projectionContext The projectionContext to set. + */ + public void setProjectionContext(Var projectionContext) { + this.projectionContext = projectionContext; + } + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ProjectionElem.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ProjectionElem.java new file mode 100644 index 00000000000..e507eb8c126 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ProjectionElem.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public class ProjectionElem extends AbstractQueryModelNode { + + /*-----------* + * Variables * + *-----------*/ + + private String sourceName; + + private String targetName; + + private boolean aggregateOperatorInExpression; + + private ExtensionElem sourceExpression; + + /*--------------* + * Constructors * + *--------------*/ + + public ProjectionElem() { + } + + public ProjectionElem(String name) { + this(name, name); + } + + public ProjectionElem(String sourceName, String targetName) { + setSourceName(sourceName); + setTargetName(targetName); + } + + /*---------* + * Methods * + *---------*/ + + public String getSourceName() { + return sourceName; + } + + public void setSourceName(String sourceName) { + assert sourceName != null : "sourceName must not be null"; + this.sourceName = sourceName; + } + + public String getTargetName() { + return targetName; + } + + public void setTargetName(String targetName) { + assert targetName != null : "targetName must not be null"; + this.targetName = targetName; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public String getSignature() { + StringBuilder sb = new StringBuilder(32); + sb.append(super.getSignature()); + + sb.append(" \""); + sb.append(sourceName); + sb.append("\""); + + if (!sourceName.equals(targetName)) { + sb.append(" AS \"").append(targetName).append("\""); + } + + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof ProjectionElem) { + ProjectionElem o = (ProjectionElem)other; + return sourceName.equals(o.getSourceName()) && targetName.equals(o.getTargetName()); + } + return false; + } + + @Override + public int hashCode() { + // Note: don't xor source and target since they will often be equal + return targetName.hashCode(); + } + + @Override + public ProjectionElem clone() { + return (ProjectionElem)super.clone(); + } + + /** + * @return Returns the aggregateOperatorInExpression. + */ + public boolean hasAggregateOperatorInExpression() { + return aggregateOperatorInExpression; + } + + /** + * @param aggregateOperatorInExpression The aggregateOperatorInExpression to set. + */ + public void setAggregateOperatorInExpression(boolean aggregateOperatorInExpression) { + this.aggregateOperatorInExpression = aggregateOperatorInExpression; + } + + /** + * @return Returns the sourceExpression. + */ + public ExtensionElem getSourceExpression() { + return sourceExpression; + } + + /** + * @param sourceExpression The sourceExpression to set. + */ + public void setSourceExpression(ExtensionElem sourceExpression) { + this.sourceExpression = sourceExpression; + } + + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ProjectionElemList.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ProjectionElemList.java new file mode 100644 index 00000000000..f27594b13c3 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ProjectionElemList.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +/** + */ +public class ProjectionElemList extends AbstractQueryModelNode { + + /*-----------* + * Variables * + *-----------*/ + + private List elements = new ArrayList(); + + /*--------------* + * Constructors * + *--------------*/ + + public ProjectionElemList() { + } + + public ProjectionElemList(ProjectionElem... elements) { + addElements(elements); + } + + public ProjectionElemList(Iterable elements) { + addElements(elements); + } + + /*---------* + * Methods * + *---------*/ + + public List getElements() { + return elements; + } + + public void setElements(List elements) { + this.elements = elements; + } + + public void addElements(ProjectionElem... elements) { + for (ProjectionElem pe : elements) { + addElement(pe); + } + } + + public void addElements(Iterable elements) { + for (ProjectionElem pe : elements) { + addElement(pe); + } + } + + public void addElement(ProjectionElem pe) { + assert pe != null : "pe must not be null"; + elements.add(pe); + pe.setParentNode(this); + } + + public Set getTargetNames() { + Set targetNames = new LinkedHashSet(elements.size()); + + for (ProjectionElem pe : elements) { + targetNames.add(pe.getTargetName()); + } + + return targetNames; + } + + public Set getTargetNamesFor(Collection sourceNames) { + Set targetNames = new LinkedHashSet(elements.size()); + + for (ProjectionElem pe : elements) { + if (sourceNames.contains(pe.getSourceName())) { + targetNames.add(pe.getTargetName()); + } + } + + return targetNames; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + for (ProjectionElem pe : elements) { + pe.visit(visitor); + } + + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (replaceNodeInList(elements, current, replacement)) { + return; + } + super.replaceChildNode(current, replacement); + } + + @Override + public boolean equals(Object other) { + if (other instanceof ProjectionElemList) { + ProjectionElemList o = (ProjectionElemList)other; + return elements.equals(o.getElements()); + } + return false; + } + + @Override + public int hashCode() { + return elements.hashCode(); + } + + @Override + public ProjectionElemList clone() { + ProjectionElemList clone = (ProjectionElemList)super.clone(); + + clone.elements = new ArrayList(getElements().size()); + for (ProjectionElem pe : getElements()) { + clone.addElement(pe.clone()); + } + + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelNode.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelNode.java new file mode 100644 index 00000000000..19c0a9282ee --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelNode.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.io.Serializable; + +/** + * Main interface for all query model nodes. + */ +public interface QueryModelNode extends Cloneable, Serializable { + + /** + * Visits this node. The node reports itself to the visitor with the proper + * runtime type. + */ + public void visit(QueryModelVisitor visitor) + throws X; + + /** + * Visits the children of this node. The node calls + * {@link #visit(QueryModelVisitor)} on all of its child nodes. + */ + public void visitChildren(QueryModelVisitor visitor) + throws X; + + /** + * Gets the node's parent. + * + * @return The parent node, if any. + */ + public QueryModelNode getParentNode(); + + /** + * Sets the node's parent. + * + * @param parent + * The parent node for this node. + */ + public void setParentNode(QueryModelNode parent); + + /** + * Replaces one of the child nodes with a new node. + * + * @param current + * The current child node. + * @param replacement + * The new child node. + * @throws IllegalArgumentException + * If current is not one of node's children. + * @throws ClassCastException + * If replacement is of an incompatible type. + */ + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement); + + /** + * Substitutes this node with a new node in the query model tree. + * + * @param replacement + * The new node. + * @throws IllegalStateException + * If this node does not have a parent node. + * @throws ClassCastException + * If replacement is of an incompatible type. + */ + public void replaceWith(QueryModelNode replacement); + + /** + * Returns true if this query model node and its children are + * recursively equal to o and its children. + */ + public boolean equals(Object o); + + /** + * Returns an indented print of the node tree, starting from this node. + */ + public String toString(); + + /** + * Returns the signature of this query model node. Signatures normally + * include the node's name and any parameters, but not parent or child nodes. + * This method is used by {@link #toString()}. + * + * @return The node's signature, e.g. SLICE (offset=10, limit=10). + */ + public String getSignature(); + + /** + * Returns a (deep) clone of this query model node. This method recursively + * clones the entire node tree, starting from this nodes. + * + * @return A deep clone of this query model node. + */ + public QueryModelNode clone(); +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelNodeBase.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelNodeBase.java new file mode 100644 index 00000000000..134902861ff --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelNodeBase.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * @deprecated since 4.0. Use {@link AbstractQueryModelNode} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class QueryModelNodeBase extends AbstractQueryModelNode { + + private static final long serialVersionUID = 1L; + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelVisitor.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelVisitor.java new file mode 100644 index 00000000000..3ca4b85c1c0 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryModelVisitor.java @@ -0,0 +1,257 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * An interface for query model visitors, implementing the Visitor pattern. Core + * query model nodes will call their type-specific method when + * {@link QueryModelNode#visit(QueryModelVisitor)} is called. The method + * {@link #meetOther(QueryModelNode)} is provided as a hook for foreign query + * model nodes. + */ +public interface QueryModelVisitor { + + public void meet(QueryRoot node) + throws X; + + + public void meet(Add add) + throws X; + + + public void meet(And node) + throws X; + + public void meet(ArbitraryLengthPath node) + throws X; + + public void meet(Avg node) + throws X; + + public void meet(BindingSetAssignment node) + throws X; + + public void meet(BNodeGenerator node) + throws X; + + public void meet(Bound node) + throws X; + + public void meet(Clear clear) + throws X; + + public void meet(Coalesce node) + throws X; + + public void meet(Compare node) + throws X; + + public void meet(CompareAll node) + throws X; + + public void meet(CompareAny node) + throws X; + + public void meet(DescribeOperator node) + throws X; + + public void meet(Copy copy) + throws X; + + public void meet(Count node) + throws X; + + public void meet(Create create) + throws X; + + public void meet(Datatype node) + throws X; + + public void meet(DeleteData deleteData) + throws X; + + public void meet(Difference node) + throws X; + + public void meet(Distinct node) + throws X; + + public void meet(EmptySet node) + throws X; + + public void meet(Exists node) + throws X; + + public void meet(Extension node) + throws X; + + public void meet(ExtensionElem node) + throws X; + + public void meet(Filter node) + throws X; + + public void meet(FunctionCall node) + throws X; + + public void meet(Group node) + throws X; + + public void meet(GroupConcat node) + throws X; + + public void meet(GroupElem node) + throws X; + + public void meet(If node) + throws X; + + public void meet(In node) + throws X; + + public void meet(InsertData insertData) + throws X; + + public void meet(Intersection node) + throws X; + + public void meet(IRIFunction node) + throws X; + + public void meet(IsBNode node) + throws X; + + public void meet(IsLiteral node) + throws X; + + public void meet(IsNumeric node) + throws X; + + public void meet(IsResource node) + throws X; + + public void meet(IsURI node) + throws X; + + public void meet(Join node) + throws X; + + public void meet(Label node) + throws X; + + public void meet(Lang node) + throws X; + + public void meet(LangMatches node) + throws X; + + public void meet(LeftJoin node) + throws X; + + public void meet(Like node) + throws X; + + public void meet(Load load) + throws X; + + public void meet(LocalName node) + throws X; + + public void meet(MathExpr node) + throws X; + + public void meet(Max node) + throws X; + + public void meet(Min node) + throws X; + + public void meet(Modify modify) + throws X; + + public void meet(Move move) + throws X; + + public void meet(MultiProjection node) + throws X; + + public void meet(Namespace node) + throws X; + + public void meet(Not node) + throws X; + + public void meet(Or node) + throws X; + + public void meet(Order node) + throws X; + + public void meet(OrderElem node) + throws X; + + public void meet(Projection node) + throws X; + + public void meet(ProjectionElem node) + throws X; + + public void meet(ProjectionElemList node) + throws X; + + public void meet(Reduced node) + throws X; + + public void meet(Regex node) + throws X; + + public void meet(SameTerm node) + throws X; + + public void meet(Sample node) + throws X; + + public void meet(Service node) + throws X; + + public void meet(SingletonSet node) + throws X; + + public void meet(Slice node) + throws X; + + public void meet(StatementPattern node) + throws X; + + public void meet(Str node) + throws X; + + public void meet(Sum node) + throws X; + + public void meet(Union node) + throws X; + + public void meet(ValueConstant node) + throws X; + + /** + * @since 2.7.4 + */ + public void meet(ListMemberOperator node) + throws X; + + public void meet(Var node) + throws X; + + public void meet(ZeroLengthPath node) + throws X; + + public void meetOther(QueryModelNode node) + throws X; +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryRoot.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryRoot.java new file mode 100644 index 00000000000..f9612e37e6f --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/QueryRoot.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * A semantics-less query model node that is used as the root of query model + * trees. This is a placeholder that facilitates modifications to query model + * trees, including the replacement of the actual (semantically relevant) root + * node with another root node. + * + * @author Arjohn Kampman + */ +public class QueryRoot extends UnaryTupleOperator { + + private QueryModelNode parent; + + public QueryRoot() { + super(); + } + + public QueryRoot(TupleExpr tupleExpr) { + super(tupleExpr); + } + + @Override + public void setParentNode(QueryModelNode parent) { + if (parent instanceof QueryRoot) { + this.parent = parent; + } + else { + throw new UnsupportedOperationException("Not allowed to set a parent on a QueryRoot object"); + } + } + + @Override + public QueryModelNode getParentNode() { + return this.parent; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof QueryRoot && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "QueryRoot".hashCode(); + } + + @Override + public QueryRoot clone() { + return (QueryRoot)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Reduced.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Reduced.java new file mode 100644 index 00000000000..9ff16c2c5d5 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Reduced.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public class Reduced extends UnaryTupleOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Reduced() { + } + + public Reduced(TupleExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Reduced && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Reduced".hashCode(); + } + + @Override + public Reduced clone() { + return (Reduced)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Regex.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Regex.java new file mode 100644 index 00000000000..1b817424f79 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Regex.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * Compares the string representation of a value expression to a pattern. + */ +public class Regex extends BinaryValueOperator { + + /*-----------* + * Variables * + *-----------*/ + + private ValueExpr flagsArg; + + /*--------------* + * Constructors * + *--------------*/ + + public Regex() { + } + + public Regex(ValueExpr expr, ValueExpr pattern, ValueExpr flags) { + super(expr, pattern); + setFlagsArg(flags); + } + + /*---------* + * Methods * + *---------*/ + + public ValueExpr getArg() { + return super.getLeftArg(); + } + + public void setArg(ValueExpr leftArg) { + super.setLeftArg(leftArg); + } + + public ValueExpr getPatternArg() { + return super.getRightArg(); + } + + public void setPatternArg(ValueExpr rightArg) { + super.setRightArg(rightArg); + } + + public void setFlagsArg(ValueExpr flags) { + this.flagsArg = flags; + } + + public ValueExpr getFlagsArg() { + return flagsArg; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + super.visitChildren(visitor); + if (flagsArg != null) { + flagsArg.visit(visitor); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof Regex && super.equals(other)) { + Regex o = (Regex)other; + return nullEquals(flagsArg, o.getFlagsArg()); + } + return false; + } + + @Override + public int hashCode() { + int result = super.hashCode() ^ "Regex".hashCode(); + if (flagsArg != null) { + result ^= flagsArg.hashCode(); + } + return result; + } + + @Override + public Regex clone() { + Regex clone = (Regex)super.clone(); + if (flagsArg != null) { + clone.setFlagsArg(flagsArg.clone()); + } + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SameTerm.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SameTerm.java new file mode 100644 index 00000000000..cec3b8360bf --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SameTerm.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * Checks RDF term equality. + */ +public class SameTerm extends BinaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public SameTerm() { + } + + public SameTerm(ValueExpr leftArg, ValueExpr rightArg) { + super(leftArg, rightArg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof SameTerm && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "SameTerm".hashCode(); + } + + @Override + public SameTerm clone() { + return (SameTerm)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Sample.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Sample.java new file mode 100644 index 00000000000..ecb4456ffd3 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Sample.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The SAMPLE operator as defined in http://www.w3.org/TR/sparql11-query/#aggregates + * + * @author Jeen Broekstra + */ +public class Sample extends AbstractAggregateOperator { + + public Sample(ValueExpr arg) { + super(arg); + } + + public Sample(ValueExpr arg, boolean distinct) { + super(arg, distinct); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Sample && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Sample".hashCode(); + } + + @Override + public Sample clone() { + return (Sample)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Service.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Service.java new file mode 100644 index 00000000000..7a768caefaf --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Service.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * The SERVICE keyword as defined in SERVICE + * definition. The service expression is evaluated at the specified service + * URI. If the service reference is a variable, a value for this variable must + * be available at evaluation time (e.g. from earlier computations). + * + * @author Andreas Schwarte + */ +public class Service extends UnaryTupleOperator { + + /*-----------* + * Variables * + *-----------*/ + + private Var serviceRef; + + /* a string representation of the inner expression (e.g. extracted during parsing) */ + private String serviceExpressionString; + + private Set serviceVars; + + /* the prefix declarations, potentially null */ + private Map prefixDeclarations; + + private String baseURI; + + /* prepared queries, including prefix. Contains %PROJECTION_VARS% to be replaced + * at evaluation time. see + */ + private String preparedSelectQueryString; + + private String preparedAskQueryString; + + private boolean silent; + + /*--------------* + * Constructors * + *--------------*/ + + public Service(Var serviceRef, TupleExpr serviceExpr, String serviceExpressionString, + Map prefixDeclarations, String baseURI, boolean silent) + { + super(serviceExpr); + setServiceRef(serviceRef); + setExpressionString(serviceExpressionString); + this.serviceVars = computeServiceVars(serviceExpr); + setPrefixDeclarations(prefixDeclarations); + setBaseURI(baseURI); + initPreparedQueryString(); + this.silent = silent; + } + + /*---------* + * Methods * + *---------*/ + + public Var getServiceRef() { + return this.serviceRef; + } + + public TupleExpr getServiceExpr() { + return this.arg; + } + + public void setServiceRef(Var serviceRef) { + this.serviceRef = serviceRef; + } + + /** + * @return Returns the silent. + */ + public boolean isSilent() { + return silent; + } + + /** + * @return Returns the prefixDeclarations. + */ + public Map getPrefixDeclarations() { + return prefixDeclarations; + } + + /** + * @param prefixDeclarations + * The prefixDeclarations to set. + */ + public void setPrefixDeclarations(Map prefixDeclarations) { + this.prefixDeclarations = prefixDeclarations; + } + + /** + * The SERVICE expression, either complete or just the expression e.g. + * "SERVICE { ... }" becomes " ... " + * + * @param serviceExpressionString + * the inner expression as SPARQL String representation + */ + public void setExpressionString(String serviceExpressionString) { + this.serviceExpressionString = parseServiceExpression(serviceExpressionString); + } + + /** + * @return Returns the serviceExpressionString. + */ + public String getServiceExpressionString() { + return serviceExpressionString; + } + + /** + * Returns an ASK query string using no projection vars. + * + * @return an ASK query string + */ + public String getAskQueryString() { + return preparedAskQueryString; + } + + /** + * Returns a SELECT query string using the provided projection vars. The variables are + * inserted into the preparedSelectQueryString in the SELECT clause. + * + * @param projectionVars + * @return SELECT query string, utilizing the given projection variables + */ + public String getSelectQueryString(Set projectionVars) { + if (projectionVars.size() == 0) + return preparedSelectQueryString.replace("%PROJECTION_VARS%", "*"); + StringBuilder sb = new StringBuilder(); + for (String var : projectionVars) + sb.append(" ?").append(var); + return preparedSelectQueryString.replace("%PROJECTION_VARS%", sb.toString()); + } + + /** + * @return Returns the serviceVars. + */ + public Set getServiceVars() { + return serviceVars; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + serviceRef.visit(visitor); + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (serviceRef == current) { + setServiceRef((Var)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof Service && super.equals(other)) { + Service o = (Service)other; + return serviceRef.equals(o.getServiceRef()); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() ^ serviceRef.hashCode(); + } + + @Override + public Service clone() { + Service clone = (Service)super.clone(); + clone.setServiceRef(serviceRef.clone()); + return clone; + } + + /** + * Compute the variable names occurring in the service expression using tree + * traversal, since these are necessary for building the SPARQL query. + * + * @return the set of variable names in the given service expression + */ + private Set computeServiceVars(TupleExpr serviceExpression) { + final Set res = new HashSet(); + serviceExpression.visit(new AbstractQueryModelVisitor() { + + @Override + public void meet(Var node) + throws RuntimeException + { + // take only real vars, i.e. ignore blank nodes + if (!node.hasValue() && !node.isAnonymous()) + res.add(node.getName()); + } + // TODO maybe stop tree traversal in nested SERVICE? + // TODO special case handling for BIND + }); + return res; + } + + private static Pattern subselectPattern = Pattern.compile("SELECT.*", Pattern.CASE_INSENSITIVE + | Pattern.DOTALL); + + private void initPreparedQueryString() { + + serviceExpressionString = serviceExpressionString.trim(); + String prefixString = computePrefixString(prefixDeclarations); + + // build the raw SELECT query string + StringBuilder sb = new StringBuilder(); + sb.append(prefixString); + if (subselectPattern.matcher(serviceExpressionString).matches()) { + sb.append(serviceExpressionString); + } + else { + sb.append("SELECT %PROJECTION_VARS% WHERE { "); + sb.append(serviceExpressionString); + sb.append(" }"); + } + preparedSelectQueryString = sb.toString(); + + // build the raw ASK query string + sb = new StringBuilder(); + sb.append(prefixString); + sb.append("ASK {"); + sb.append(serviceExpressionString); + sb.append(" }"); + preparedAskQueryString = sb.toString(); + } + + /** + * Compute the prefix string only once to avoid computation overhead during + * evaluation. + * + * @param prefixDeclarations + * @return a Prefix String or an empty string if there are no prefixes + */ + private String computePrefixString(Map prefixDeclarations) { + if (prefixDeclarations == null) + return ""; + + StringBuilder sb = new StringBuilder(); + for (String prefix : prefixDeclarations.keySet()) { + String uri = prefixDeclarations.get(prefix); + sb.append("PREFIX ").append(prefix).append(":").append(" <").append(uri).append("> "); + } + return sb.toString(); + } + + /** + * Parses a service expression to just have the inner expression, e.g. from + * something like "SERVICE <url> { ... }" becomes " ... ", also applies + * {@link String#trim()} to remove leading/tailing space + * + * @param serviceExpression + * @return the inner expression of the given service expression + */ + private String parseServiceExpression(String serviceExpression) { + + if (serviceExpression.toLowerCase().startsWith("service")) { + return serviceExpression.substring(serviceExpression.indexOf("{") + 1, + serviceExpression.lastIndexOf("}")).trim(); + } + return serviceExpression; + } + + /** + * @param baseURI + * The baseURI to set. + */ + public void setBaseURI(String baseURI) { + this.baseURI = baseURI; + } + + /** + * @return Returns the baseURI. + */ + public String getBaseURI() { + return baseURI; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SingletonSet.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SingletonSet.java new file mode 100644 index 00000000000..8dc8ecb1fae --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SingletonSet.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.Collections; +import java.util.Set; + +/** + * A tuple expression that contains exactly one solution with zero bindings. + */ +public class SingletonSet extends AbstractQueryModelNode implements TupleExpr { + + public Set getBindingNames() { + return getAssuredBindingNames(); + } + + public Set getAssuredBindingNames() { + return Collections.emptySet(); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof SingletonSet; + } + + @Override + public int hashCode() { + return "SingletonSet".hashCode(); + } + + @Override + public SingletonSet clone() { + return (SingletonSet)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Slice.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Slice.java new file mode 100644 index 00000000000..f5f3e774bd4 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Slice.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The SLICE operator, as defined in SPARQL Query + * Language for RDF. The SLICE operator selects specific results from the + * underlying tuple expression based on an offset and limit value (both + * optional). + * + * @author Arjohn Kampman + */ +public class Slice extends UnaryTupleOperator { + + /*-----------* + * Variables * + *-----------*/ + + private long offset; + + private long limit; + + /*--------------* + * Constructors * + *--------------*/ + + public Slice() { + } + + public Slice(TupleExpr arg) { + this(arg, 0, -1); + } + + public Slice(TupleExpr arg, long offset2, long limit2) { + super(arg); + setOffset(offset2); + setLimit(limit2); + } + + /*---------* + * Methods * + *---------*/ + + public long getOffset() { + return offset; + } + + public void setOffset(long offset) { + this.offset = offset; + } + + /** + * Checks whether the row selection has a (valid) offset. + * + * @return true when offset > 0 + */ + public boolean hasOffset() { + return offset > 0L; + } + + public long getLimit() { + return limit; + } + + public void setLimit(long limit) { + this.limit = limit; + } + + /** + * Checks whether the row selection has a (valid) limit. + * + * @return true when offset >= 0 + */ + public boolean hasLimit() { + return limit >= 0L; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public String getSignature() { + StringBuilder sb = new StringBuilder(256); + + sb.append(super.getSignature()); + sb.append(" ( "); + + if (hasLimit()) { + sb.append("limit=").append(getLimit()); + } + if (hasOffset()) { + sb.append("offset=").append(getOffset()); + } + + sb.append(" )"); + + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof Slice && super.equals(other)) { + Slice o = (Slice)other; + return offset == o.getOffset() && limit == o.getLimit(); + } + return false; + } + + @Override + public int hashCode() { + // casting long to int is not safe, but shouldn't matter for hashcode, should it? + return super.hashCode() ^ (int)offset ^ (int)limit; + } + + @Override + public Slice clone() { + return (Slice)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/StatementPattern.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/StatementPattern.java new file mode 100644 index 00000000000..d14abc37c06 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/StatementPattern.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * A tuple expression that matches a statement pattern against an RDF graph. + * Statement patterns can be targeted at one of three context scopes: all + * contexts, null context only, or named contexts only. + */ +public class StatementPattern extends AbstractQueryModelNode implements TupleExpr { + + /*------------* + * enum Scope * + *------------*/ + + /** + * Indicates the scope of the statement pattern. + */ + public enum Scope { + /** + * Scope for patterns that should be matched against statements from the + * default contexts. + */ + DEFAULT_CONTEXTS, + + /** + * Scope for patterns that should be matched against statements from named + * contexts only. + */ + NAMED_CONTEXTS + } + + /*-----------* + * Variables * + *-----------*/ + + private Scope scope; + + private Var subjectVar; + + private Var predicateVar; + + private Var objectVar; + + private Var contextVar; + + /*--------------* + * Constructors * + *--------------*/ + + public StatementPattern() { + } + + /** + * Creates a statement pattern that matches a subject-, predicate- and object + * variable against statements from all contexts. + */ + public StatementPattern(Var subject, Var predicate, Var object) { + this(Scope.DEFAULT_CONTEXTS, subject, predicate, object); + } + + /** + * Creates a statement pattern that matches a subject-, predicate- and object + * variable against statements from the specified context scope. + */ + public StatementPattern(Scope scope, Var subject, Var predicate, Var object) { + this(scope, subject, predicate, object, null); + } + + /** + * Creates a statement pattern that matches a subject-, predicate-, object- + * and context variable against statements from all contexts. + */ + public StatementPattern(Var subject, Var predicate, Var object, Var context) { + this(Scope.DEFAULT_CONTEXTS, subject, predicate, object, context); + } + + /** + * Creates a statement pattern that matches a subject-, predicate-, object- + * and context variable against statements from the specified context scope. + */ + public StatementPattern(Scope scope, Var subjVar, Var predVar, Var objVar, Var conVar) { + setScope(scope); + setSubjectVar(subjVar); + setPredicateVar(predVar); + setObjectVar(objVar); + setContextVar(conVar); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the context scope for the statement pattern. + */ + public Scope getScope() { + return scope; + } + + /** + * Sets the context scope for the statement pattern. + */ + public void setScope(Scope scope) { + assert scope != null : "scope must not be null"; + this.scope = scope; + } + + public Var getSubjectVar() { + return subjectVar; + } + + public void setSubjectVar(Var subject) { + assert subject != null : "subject must not be null"; + subject.setParentNode(this); + subjectVar = subject; + } + + public Var getPredicateVar() { + return predicateVar; + } + + public void setPredicateVar(Var predicate) { + assert predicate != null : "predicate must not be null"; + predicate.setParentNode(this); + predicateVar = predicate; + } + + public Var getObjectVar() { + return objectVar; + } + + public void setObjectVar(Var object) { + assert object != null : "object must not be null"; + object.setParentNode(this); + objectVar = object; + } + + /** + * Returns the context variable, if available. + */ + public Var getContextVar() { + return contextVar; + } + + public void setContextVar(Var context) { + if (context != null) { + context.setParentNode(this); + } + contextVar = context; + } + + public Set getBindingNames() { + return getAssuredBindingNames(); + } + + public Set getAssuredBindingNames() { + Set bindingNames = new HashSet(8); + + if (subjectVar != null) { + bindingNames.add(subjectVar.getName()); + } + if (predicateVar != null) { + bindingNames.add(predicateVar.getName()); + } + if (objectVar != null) { + bindingNames.add(objectVar.getName()); + } + if (contextVar != null) { + bindingNames.add(contextVar.getName()); + } + + return bindingNames; + } + + public List getVarList() { + return getVars(new ArrayList(4)); + } + + /** + * Adds the variables of this statement pattern to the supplied collection. + */ + public > L getVars(L varCollection) { + if (subjectVar != null) { + varCollection.add(subjectVar); + } + if (predicateVar != null) { + varCollection.add(predicateVar); + } + if (objectVar != null) { + varCollection.add(objectVar); + } + if (contextVar != null) { + varCollection.add(contextVar); + } + + return varCollection; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (subjectVar != null) { + subjectVar.visit(visitor); + } + if (predicateVar != null) { + predicateVar.visit(visitor); + } + if (objectVar != null) { + objectVar.visit(visitor); + } + if (contextVar != null) { + contextVar.visit(visitor); + } + + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (subjectVar == current) { + setSubjectVar((Var)replacement); + } + else if (predicateVar == current) { + setPredicateVar((Var)replacement); + } + else if (objectVar == current) { + setObjectVar((Var)replacement); + } + else if (contextVar == current) { + setContextVar((Var)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public String getSignature() { + StringBuilder sb = new StringBuilder(128); + + sb.append(super.getSignature()); + + if (scope == Scope.NAMED_CONTEXTS) { + sb.append(" FROM NAMED CONTEXT"); + } + + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof StatementPattern) { + StatementPattern o = (StatementPattern)other; + return subjectVar.equals(o.getSubjectVar()) && predicateVar.equals(o.getPredicateVar()) + && objectVar.equals(o.getObjectVar()) && nullEquals(contextVar, o.getContextVar()) + && scope.equals(o.getScope()); + } + return false; + } + + @Override + public int hashCode() { + int result = subjectVar.hashCode(); + result ^= predicateVar.hashCode(); + result ^= objectVar.hashCode(); + if (contextVar != null) { + result ^= contextVar.hashCode(); + } + if (scope == Scope.NAMED_CONTEXTS) { + result = ~result; + } + return result; + } + + @Override + public StatementPattern clone() { + StatementPattern clone = (StatementPattern)super.clone(); + clone.setSubjectVar(getSubjectVar().clone()); + clone.setPredicateVar(getPredicateVar().clone()); + clone.setObjectVar(getObjectVar().clone()); + + if (getContextVar() != null) { + clone.setContextVar(getContextVar().clone()); + } + + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Str.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Str.java new file mode 100644 index 00000000000..b31f3f23f6d --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Str.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The STR function, as defined in SPARQL Query Language + * for RDF; returns the label of literals or the string representation of + * URIs. + * + * @author Arjohn Kampman + */ +public class Str extends UnaryValueOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Str() { + } + + public Str(ValueExpr arg) { + super(arg); + } + + /*---------* + * Methods * + *---------*/ + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Str && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Str".hashCode(); + } + + @Override + public Str clone() { + return (Str)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SubQueryValueOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SubQueryValueOperator.java new file mode 100644 index 00000000000..f986e4073f2 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/SubQueryValueOperator.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +public abstract class SubQueryValueOperator extends AbstractQueryModelNode implements ValueExpr { + + /*-----------* + * Variables * + *-----------*/ + + protected TupleExpr subQuery; + + /*--------------* + * Constructors * + *--------------*/ + + public SubQueryValueOperator() { + } + + public SubQueryValueOperator(TupleExpr subQuery) { + setSubQuery(subQuery); + } + + /*---------* + * Methods * + *---------*/ + + public TupleExpr getSubQuery() { + return subQuery; + } + + public void setSubQuery(TupleExpr subQuery) { + assert subQuery != null : "subQuery must not be null"; + subQuery.setParentNode(this); + this.subQuery = subQuery; + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + subQuery.visit(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (subQuery == current) { + setSubQuery((TupleExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof SubQueryValueOperator) { + SubQueryValueOperator o = (SubQueryValueOperator)other; + return subQuery.equals(o.getSubQuery()); + } + + return false; + } + + @Override + public int hashCode() { + return subQuery.hashCode(); + } + + @Override + public SubQueryValueOperator clone() { + SubQueryValueOperator clone = (SubQueryValueOperator)super.clone(); + clone.setSubQuery(getSubQuery().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Sum.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Sum.java new file mode 100644 index 00000000000..b9558aabea2 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Sum.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * The SUM operator as defined in http://www.w3.org/TR/sparql11-query/#aggregates + * + * @author Jeen Broekstra + */ +public class Sum extends AbstractAggregateOperator { + + public Sum(ValueExpr arg) { + super(arg); + } + + public Sum(ValueExpr arg, boolean distinct) { + super(arg, distinct); + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Sum && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Sum".hashCode(); + } + + @Override + public Sum clone() { + return (Sum)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/TupleExpr.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/TupleExpr.java new file mode 100644 index 00000000000..19bec8900c4 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/TupleExpr.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.Set; + +/** + * An expression that evaluates to RDF tuples. + */ +public interface TupleExpr extends QueryModelNode { + + /** + * Gets the names of the bindings that are, or can be, returned by this tuple + * expression when it is evaluated. + * + * @return A set of binding names. + */ + public Set getBindingNames(); + + /** + * Gets the names of the bindings that are guaranteed to be present in the + * results produced by this tuple expression. + * + * @return A set of binding names. + */ + public Set getAssuredBindingNames(); + + public TupleExpr clone(); +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UnaryTupleOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UnaryTupleOperator.java new file mode 100644 index 00000000000..28177f78d7b --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UnaryTupleOperator.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.Set; + +/** + * An abstract superclass for unary tuple operators which, by definition, has + * one argument. + */ +public abstract class UnaryTupleOperator extends AbstractQueryModelNode implements TupleExpr { + + /*-----------* + * Variables * + *-----------*/ + + /** + * The operator's argument. + */ + protected TupleExpr arg; + + /*--------------* + * Constructors * + *--------------*/ + + public UnaryTupleOperator() { + } + + /** + * Creates a new unary tuple operator. + * + * @param arg + * The operator's argument, must not be null. + */ + public UnaryTupleOperator(TupleExpr arg) { + setArg(arg); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the argument of this unary tuple operator. + * + * @return The operator's argument. + */ + public TupleExpr getArg() { + return arg; + } + + /** + * Sets the argument of this unary tuple operator. + * + * @param arg + * The (new) argument for this operator, must not be null. + */ + public void setArg(TupleExpr arg) { + assert arg != null : "arg must not be null"; + arg.setParentNode(this); + this.arg = arg; + } + + public Set getBindingNames() { + return getArg().getBindingNames(); + } + + public Set getAssuredBindingNames() { + return getArg().getAssuredBindingNames(); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + arg.visit(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (arg == current) { + setArg((TupleExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof UnaryTupleOperator) { + UnaryTupleOperator o = (UnaryTupleOperator)other; + return arg.equals(o.getArg()); + } + + return false; + } + + @Override + public int hashCode() { + return arg.hashCode(); + } + + @Override + public UnaryTupleOperator clone() { + UnaryTupleOperator clone = (UnaryTupleOperator)super.clone(); + clone.setArg(getArg().clone()); + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UnaryValueOperator.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UnaryValueOperator.java new file mode 100644 index 00000000000..0ffc0aa9bf9 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UnaryValueOperator.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * An abstract superclass for unary value operators which, by definition, has + * one argument. + */ +public abstract class UnaryValueOperator extends AbstractQueryModelNode implements ValueExpr { + + /*-----------* + * Variables * + *-----------*/ + + /** + * The operator's argument. + */ + protected ValueExpr arg; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new empty unary value operator. + */ + public UnaryValueOperator() { + } + + /** + * Creates a new unary value operator. + * + * @param arg + * The operator's argument, must not be null. + */ + public UnaryValueOperator(ValueExpr arg) { + setArg(arg); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the argument of this unary value operator. + * + * @return The operator's argument. + */ + public ValueExpr getArg() { + return arg; + } + + /** + * Sets the argument of this unary value operator. + * + * @param arg + * The (new) argument for this operator, must not be null. + */ + public void setArg(ValueExpr arg) { + assert arg != null : "arg must not be null"; + arg.setParentNode(this); + this.arg = arg; + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (arg != null) { + arg.visit(visitor); + } + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (arg == current) { + setArg((ValueExpr)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof UnaryValueOperator) { + UnaryValueOperator o = (UnaryValueOperator)other; + return (arg == null && o.getArg() == null) || (arg != null && arg.equals(o.getArg())); + } + + return false; + } + + @Override + public int hashCode() { + return arg.hashCode(); + } + + @Override + public UnaryValueOperator clone() { + UnaryValueOperator clone = (UnaryValueOperator)super.clone(); + if (getArg() != null) { + clone.setArg(getArg().clone()); + } + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Union.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Union.java new file mode 100644 index 00000000000..09d846c1410 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Union.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * The UNION set operator, which return the union of the result sets of two + * tuple expressions. + */ +public class Union extends BinaryTupleOperator { + + /*--------------* + * Constructors * + *--------------*/ + + public Union() { + } + + /** + * Creates a new union operator that operates on the two specified arguments. + * + * @param leftArg + * The left argument of the union operator. + * @param rightArg + * The right argument of the union operator. + */ + public Union(TupleExpr leftArg, TupleExpr rightArg) { + super(leftArg, rightArg); + } + + /*---------* + * Methods * + *---------*/ + + public Set getBindingNames() { + Set bindingNames = new LinkedHashSet(16); + bindingNames.addAll(getLeftArg().getBindingNames()); + bindingNames.addAll(getRightArg().getBindingNames()); + return bindingNames; + } + + public Set getAssuredBindingNames() { + Set bindingNames = new LinkedHashSet(16); + bindingNames.addAll(getLeftArg().getAssuredBindingNames()); + bindingNames.retainAll(getRightArg().getAssuredBindingNames()); + return bindingNames; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public boolean equals(Object other) { + return other instanceof Union && super.equals(other); + } + + @Override + public int hashCode() { + return super.hashCode() ^ "Union".hashCode(); + } + + @Override + public Union clone() { + return (Union)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UpdateExpr.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UpdateExpr.java new file mode 100644 index 00000000000..3e88d5b764d --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/UpdateExpr.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * An expression that executes an update. + */ +public interface UpdateExpr extends QueryModelNode { + + public UpdateExpr clone(); + + /** + * @return Returns the silent. + */ + public boolean isSilent(); +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ValueConstant.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ValueConstant.java new file mode 100644 index 00000000000..434d87aa098 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ValueConstant.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import org.eclipse.rdf4j.model.Value; + +/** + * A ValueExpr with a constant value. + */ +public class ValueConstant extends AbstractQueryModelNode implements ValueExpr { + + /*-----------* + * Variables * + *-----------*/ + + private Value value; + + /*--------------* + * Constructors * + *--------------*/ + + public ValueConstant() { + } + + public ValueConstant(Value value) { + setValue(value); + } + + /*---------* + * Methods * + *---------*/ + + public Value getValue() { + return value; + } + + public void setValue(Value value) { + assert value != null : "value must not be null"; + this.value = value; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public String getSignature() { + StringBuilder sb = new StringBuilder(64); + + sb.append(super.getSignature()); + sb.append(" (value="); + sb.append(value.toString()); + sb.append(")"); + + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof ValueConstant) { + ValueConstant o = (ValueConstant)other; + return value.equals(o.getValue()); + } + return false; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public ValueConstant clone() { + return (ValueConstant)super.clone(); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ValueExpr.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ValueExpr.java new file mode 100644 index 00000000000..3f832904bd5 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ValueExpr.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +/** + * An expressions that evaluates to Value objects. + */ +public interface ValueExpr extends QueryModelNode { + + public ValueExpr clone(); +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Var.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Var.java new file mode 100644 index 00000000000..b1203f417d6 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/Var.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import org.eclipse.rdf4j.model.Value; + +/** + * A variable that can contain a Value. + */ +public class Var extends AbstractQueryModelNode implements ValueExpr { + + /*-----------* + * Variables * + *-----------*/ + + private String name; + + private Value value; + + private boolean anonymous = false; + + private boolean constant = false; + + /*--------------* + * Constructors * + *--------------*/ + + public Var() { + } + + public Var(String name) { + setName(name); + } + + public Var(String name, Value value) { + this(name); + setValue(value); + } + + /*---------* + * Methods * + *---------*/ + + public void setAnonymous(boolean anonymous) { + this.anonymous = anonymous; + } + + public boolean isAnonymous() { + return anonymous; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setValue(Value value) { + this.value = value; + } + + public boolean hasValue() { + return value != null; + } + + public Value getValue() { + return value; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public String getSignature() { + StringBuilder sb = new StringBuilder(64); + + sb.append(super.getSignature()); + + sb.append(" (name=").append(name); + + if (value != null) { + sb.append(", value=").append(value.toString()); + } + + if (anonymous) { + sb.append(", anonymous"); + } + + sb.append(")"); + + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof Var) { + Var o = (Var)other; + return name.equals(o.getName()) && nullEquals(value, o.getValue()) && anonymous == o.isAnonymous(); + } + return false; + } + + @Override + public int hashCode() { + int result = name.hashCode(); + if (value != null) { + result ^= value.hashCode(); + } + if (anonymous) { + result = ~result; + } + return result; + } + + @Override + public Var clone() { + return (Var)super.clone(); + } + + /** + * @return Returns the constant. + */ + public boolean isConstant() { + return constant; + } + + /** + * @param constant The constant to set. + */ + public void setConstant(boolean constant) { + this.constant = constant; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ZeroLengthPath.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ZeroLengthPath.java new file mode 100644 index 00000000000..b206a4ecc78 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/ZeroLengthPath.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope; + +/** + * A tuple expression that matches a path of length zero against an RDF graph. + * They can can be targeted at one of three context scopes: all contexts, null + * context only, or named contexts only. + */ +public class ZeroLengthPath extends AbstractQueryModelNode implements TupleExpr { + + /*-----------* + * Variables * + *-----------*/ + + private Scope scope; + + private Var subjectVar; + + private Var objectVar; + + private Var contextVar; + + /*--------------* + * Constructors * + *--------------*/ + + public ZeroLengthPath() { + } + + /** + * Creates a zero-length path that matches a subject-, predicate- and object + * variable against statements from all contexts. + */ + public ZeroLengthPath(Var subject, Var object) { + this(Scope.DEFAULT_CONTEXTS, subject, object); + } + + /** + * Creates a zero-length path that matches a subject-, predicate- and object + * variable against statements from the specified context scope. + */ + public ZeroLengthPath(Scope scope, Var subject, Var object) { + this(scope, subject, object, null); + } + + /** + * Creates a zero-length path that matches a subject-, predicate-, object- + * and context variable against statements from all contexts. + */ + public ZeroLengthPath(Var subject, Var object, Var context) { + this(Scope.DEFAULT_CONTEXTS, subject, object, context); + } + + /** + * Creates a zero-length path that matches a subject-, predicate-, object- + * and context variable against statements from the specified context scope. + */ + public ZeroLengthPath(Scope scope, Var subjVar, Var objVar, Var conVar) { + setScope(scope); + setSubjectVar(subjVar); + setObjectVar(objVar); + setContextVar(conVar); + } + + /*---------* + * Methods * + *---------*/ + + /** + * Gets the context scope for the zero-length path. + */ + public Scope getScope() { + return scope; + } + + /** + * Sets the context scope for the zero-length path + */ + public void setScope(Scope scope) { + assert scope != null : "scope must not be null"; + this.scope = scope; + } + + public Var getSubjectVar() { + return subjectVar; + } + + public void setSubjectVar(Var subject) { + assert subject != null : "subject must not be null"; + subject.setParentNode(this); + subjectVar = subject; + } + + public Var getObjectVar() { + return objectVar; + } + + public void setObjectVar(Var object) { + assert object != null : "object must not be null"; + object.setParentNode(this); + objectVar = object; + } + + /** + * Returns the context variable, if available. + */ + public Var getContextVar() { + return contextVar; + } + + public void setContextVar(Var context) { + if (context != null) { + context.setParentNode(this); + } + contextVar = context; + } + + public Set getBindingNames() { + return getAssuredBindingNames(); + } + + public Set getAssuredBindingNames() { + Set bindingNames = new HashSet(8); + + if (subjectVar != null) { + bindingNames.add(subjectVar.getName()); + } + if (objectVar != null) { + bindingNames.add(objectVar.getName()); + } + if (contextVar != null) { + bindingNames.add(contextVar.getName()); + } + + return bindingNames; + } + + public List getVarList() { + return getVars(new ArrayList(4)); + } + + /** + * Adds the variables of this statement pattern to the supplied collection. + */ + public > L getVars(L varCollection) { + if (subjectVar != null) { + varCollection.add(subjectVar); + } + if (objectVar != null) { + varCollection.add(objectVar); + } + if (contextVar != null) { + varCollection.add(contextVar); + } + + return varCollection; + } + + public void visit(QueryModelVisitor visitor) + throws X + { + visitor.meet(this); + } + + @Override + public void visitChildren(QueryModelVisitor visitor) + throws X + { + if (subjectVar != null) { + subjectVar.visit(visitor); + } + if (objectVar != null) { + objectVar.visit(visitor); + } + if (contextVar != null) { + contextVar.visit(visitor); + } + + super.visitChildren(visitor); + } + + @Override + public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) { + if (subjectVar == current) { + setSubjectVar((Var)replacement); + } + else if (objectVar == current) { + setObjectVar((Var)replacement); + } + else if (contextVar == current) { + setContextVar((Var)replacement); + } + else { + super.replaceChildNode(current, replacement); + } + } + + @Override + public String getSignature() { + StringBuilder sb = new StringBuilder(128); + + sb.append(super.getSignature()); + + if (scope == Scope.NAMED_CONTEXTS) { + sb.append(" FROM NAMED CONTEXT"); + } + + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof ZeroLengthPath) { + ZeroLengthPath o = (ZeroLengthPath)other; + return subjectVar.equals(o.getSubjectVar()) + && objectVar.equals(o.getObjectVar()) && nullEquals(contextVar, o.getContextVar()) + && scope.equals(o.getScope()); + } + return false; + } + + @Override + public int hashCode() { + int result = subjectVar.hashCode(); + result ^= objectVar.hashCode(); + if (contextVar != null) { + result ^= contextVar.hashCode(); + } + if (scope == Scope.NAMED_CONTEXTS) { + result = ~result; + } + return result; + } + + @Override + public ZeroLengthPath clone() { + ZeroLengthPath clone = (ZeroLengthPath)super.clone(); + clone.setSubjectVar(getSubjectVar().clone()); + clone.setObjectVar(getObjectVar().clone()); + + if (getContextVar() != null) { + clone.setContextVar(getContextVar().clone()); + } + + return clone; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedService.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedService.java new file mode 100644 index 00000000000..d96e2bb2d76 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedService.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.Service; + +/** + * FederatedService to allow for customized evaluation of SERVICE expression. By + * default {@link SPARQLFederatedService} is used. + * + * @author Andreas Schwarte + * @author James Leigh + * @see SPARQLFederatedService + */ +public interface FederatedService { + + /** + *

    + * Evaluate the provided SPARQL ASK query at this federated service. + *

    + * + *
    +	 * Expected behavior: evaluate boolean query using the bindings as constraints
    +	 * 
    + * + * @param service + * the reference to the service node, contains additional meta + * information (vars, prefixes) + * @param bindings + * the bindings serving as additional constraints + * @param baseUri + * @return true if at least one result exists + * @throws QueryEvaluationException + * If there was an exception generated while evaluating the query. + */ + public boolean ask(Service service, BindingSet bindings, String baseUri) + throws QueryEvaluationException; + + /** + *

    + * Evaluate the provided SPARQL query at this federated service. + *

    + *

    + * Important: The original bindings need to be inserted into the + * result. + *

    + * + *
    +	 * Expected behavior: evaluate the given SPARQL query using the bindings as constraints
    +	 * 
    + * + * @param service + * the reference to the service node, contains additional meta + * information (vars, prefixes) + * @param projectionVars + * The variables with unknown value that should be projected from this + * evaluation + * @param bindings + * the bindings serving as additional constraints + * @param baseUri + * @return an iteration over the results of the query + * @throws QueryEvaluationException + * If there was an exception generated while evaluating the query. + */ + public CloseableIteration select(Service service, + Set projectionVars, BindingSet bindings, String baseUri) + throws QueryEvaluationException; + + /** + * Evaluate the provided SPARQL query at this federated service, + * possibilities for vectored evaluation. + *

    + * Contracts: + *

      + *
    • The original bindings need to be inserted into the result
    • + *
    • SILENT service must be dealt with in the method
    • + *
    + *

    + * Compare {@link SPARQLFederatedService} for a reference implementation + *

    + * + * @param service + * the reference to the service node, contains information to + * construct the query + * @param bindings + * the bindings serving as additional constraints (for vectored + * evaluation) + * @param baseUri + * the baseUri + * @return the result of evaluating the query using bindings as constraints, + * the original bindings need to be inserted into the results! + * @throws QueryEvaluationException + * If there was an exception generated while evaluating the query. + */ + public CloseableIteration evaluate(Service service, + CloseableIteration bindings, String baseUri) + throws QueryEvaluationException; + + /** + * Method to check if {@link #initialize()} had been called. + */ + public boolean isInitialized(); + + /** + * Method to perform any initializations, invoked after construction. + * + * @throws QueryEvaluationException + * If there was an exception generated while initializing the + * service. + */ + public void initialize() + throws QueryEvaluationException; + + /** + * Method to perform any shutDown code, invoked at unregistering. + * + * @throws QueryEvaluationException + * If there was an exception generated while shutting down the + * service. + */ + public void shutdown() + throws QueryEvaluationException; +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolver.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolver.java new file mode 100644 index 00000000000..02f6aff3754 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolver.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +import org.eclipse.rdf4j.query.QueryEvaluationException; + +/** + * The {@link FederatedServiceResolver} is used to manage a set of + * {@link FederatedService} instances, which are used to evaluate SERVICE + * expressions for particular service Urls. + *

    + * Lookup can be done via the serviceUrl using the method + * {@link #getService(String)}. + * + * @author Andreas Schwarte + * @author James Leigh + */ +public interface FederatedServiceResolver { + + /** + * Retrieve the {@link FederatedService} registered for serviceUrl. If there + * is no service registered for serviceUrl, a new + * {@link SPARQLFederatedService} is created and registered. + * + * @param serviceUrl + * locator for the federation service + * @return the {@link FederatedService}, created fresh if necessary + * @throws QueryEvaluationException + * If there was an exception generated while retrieving the service. + */ + FederatedService getService(String serviceUrl) + throws QueryEvaluationException; + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverClient.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverClient.java new file mode 100644 index 00000000000..eb9efd26c0f --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/FederatedServiceResolverClient.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.federation; + +/** + * Interface used by {@link org.eclipse.rdf4j.sail.config.SailFactory} and + * {@link org.eclipse.rdf4j.repository.config.RepositoryFactory} that can make + * external SERVICE calls. + * + * @author James Leigh + */ +public interface FederatedServiceResolverClient { + + /** + * Sets the {@link FederatedServiceResolver} to use for this client. + * + * @param resolver + * The resolver to use. + */ + void setFederatedServiceResolver(FederatedServiceResolver resolver); +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/AbstractQueryModelVisitor.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/AbstractQueryModelVisitor.java new file mode 100644 index 00000000000..3fa9d4a1ff0 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/AbstractQueryModelVisitor.java @@ -0,0 +1,724 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.helpers; + +import org.eclipse.rdf4j.query.algebra.Add; +import org.eclipse.rdf4j.query.algebra.And; +import org.eclipse.rdf4j.query.algebra.ArbitraryLengthPath; +import org.eclipse.rdf4j.query.algebra.Avg; +import org.eclipse.rdf4j.query.algebra.BNodeGenerator; +import org.eclipse.rdf4j.query.algebra.BinaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.BinaryValueOperator; +import org.eclipse.rdf4j.query.algebra.BindingSetAssignment; +import org.eclipse.rdf4j.query.algebra.Bound; +import org.eclipse.rdf4j.query.algebra.Clear; +import org.eclipse.rdf4j.query.algebra.Coalesce; +import org.eclipse.rdf4j.query.algebra.Compare; +import org.eclipse.rdf4j.query.algebra.CompareAll; +import org.eclipse.rdf4j.query.algebra.CompareAny; +import org.eclipse.rdf4j.query.algebra.CompareSubQueryValueOperator; +import org.eclipse.rdf4j.query.algebra.Copy; +import org.eclipse.rdf4j.query.algebra.Count; +import org.eclipse.rdf4j.query.algebra.Create; +import org.eclipse.rdf4j.query.algebra.Datatype; +import org.eclipse.rdf4j.query.algebra.DeleteData; +import org.eclipse.rdf4j.query.algebra.DescribeOperator; +import org.eclipse.rdf4j.query.algebra.Difference; +import org.eclipse.rdf4j.query.algebra.Distinct; +import org.eclipse.rdf4j.query.algebra.EmptySet; +import org.eclipse.rdf4j.query.algebra.Exists; +import org.eclipse.rdf4j.query.algebra.Extension; +import org.eclipse.rdf4j.query.algebra.ExtensionElem; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.FunctionCall; +import org.eclipse.rdf4j.query.algebra.Group; +import org.eclipse.rdf4j.query.algebra.GroupConcat; +import org.eclipse.rdf4j.query.algebra.GroupElem; +import org.eclipse.rdf4j.query.algebra.IRIFunction; +import org.eclipse.rdf4j.query.algebra.If; +import org.eclipse.rdf4j.query.algebra.In; +import org.eclipse.rdf4j.query.algebra.InsertData; +import org.eclipse.rdf4j.query.algebra.Intersection; +import org.eclipse.rdf4j.query.algebra.IsBNode; +import org.eclipse.rdf4j.query.algebra.IsLiteral; +import org.eclipse.rdf4j.query.algebra.IsNumeric; +import org.eclipse.rdf4j.query.algebra.IsResource; +import org.eclipse.rdf4j.query.algebra.IsURI; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.Label; +import org.eclipse.rdf4j.query.algebra.Lang; +import org.eclipse.rdf4j.query.algebra.LangMatches; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.Like; +import org.eclipse.rdf4j.query.algebra.ListMemberOperator; +import org.eclipse.rdf4j.query.algebra.Load; +import org.eclipse.rdf4j.query.algebra.LocalName; +import org.eclipse.rdf4j.query.algebra.MathExpr; +import org.eclipse.rdf4j.query.algebra.Max; +import org.eclipse.rdf4j.query.algebra.Min; +import org.eclipse.rdf4j.query.algebra.Modify; +import org.eclipse.rdf4j.query.algebra.Move; +import org.eclipse.rdf4j.query.algebra.MultiProjection; +import org.eclipse.rdf4j.query.algebra.NAryValueOperator; +import org.eclipse.rdf4j.query.algebra.Namespace; +import org.eclipse.rdf4j.query.algebra.Not; +import org.eclipse.rdf4j.query.algebra.Or; +import org.eclipse.rdf4j.query.algebra.Order; +import org.eclipse.rdf4j.query.algebra.OrderElem; +import org.eclipse.rdf4j.query.algebra.Projection; +import org.eclipse.rdf4j.query.algebra.ProjectionElem; +import org.eclipse.rdf4j.query.algebra.ProjectionElemList; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.QueryModelVisitor; +import org.eclipse.rdf4j.query.algebra.QueryRoot; +import org.eclipse.rdf4j.query.algebra.Reduced; +import org.eclipse.rdf4j.query.algebra.Regex; +import org.eclipse.rdf4j.query.algebra.SameTerm; +import org.eclipse.rdf4j.query.algebra.Sample; +import org.eclipse.rdf4j.query.algebra.Service; +import org.eclipse.rdf4j.query.algebra.SingletonSet; +import org.eclipse.rdf4j.query.algebra.Slice; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.Str; +import org.eclipse.rdf4j.query.algebra.SubQueryValueOperator; +import org.eclipse.rdf4j.query.algebra.Sum; +import org.eclipse.rdf4j.query.algebra.UnaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.UnaryValueOperator; +import org.eclipse.rdf4j.query.algebra.Union; +import org.eclipse.rdf4j.query.algebra.UpdateExpr; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.ZeroLengthPath; + +/** + * Base class for {@link QueryModelVisitor}s. This class implements all + * meet(... node) methods from the visitor interface, forwarding the + * call to a method for the node's supertype. This is done recursively until + * {@link #meetNode} is reached. This allows subclasses to easily define default + * behaviour for visited nodes of a certain type. The default implementation of + * {@link #meetNode} is to visit the node's children. + */ +public abstract class AbstractQueryModelVisitor implements QueryModelVisitor { + + public void meet(Add node) + throws X + { + meetUpdateExpr(node); + } + + public void meet(And node) + throws X + { + meetBinaryValueOperator(node); + } + + public void meet(ArbitraryLengthPath node) + throws X + { + meetNode(node); + } + + public void meet(Avg node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(BindingSetAssignment node) + throws X + { + meetNode(node); + } + + public void meet(BNodeGenerator node) + throws X + { + meetNode(node); + } + + public void meet(Bound node) + throws X + { + meetNode(node); + } + + public void meet(Clear node) + throws X + { + meetUpdateExpr(node); + } + + public void meet(Coalesce node) + throws X + { + meetNAryValueOperator(node); + } + + public void meet(Compare node) + throws X + { + meetBinaryValueOperator(node); + } + + public void meet(CompareAll node) + throws X + { + meetCompareSubQueryValueOperator(node); + } + + public void meet(CompareAny node) + throws X + { + meetCompareSubQueryValueOperator(node); + } + + public void meet(DescribeOperator node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(Copy node) + throws X + { + meetUpdateExpr(node); + } + + public void meet(Count node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Create node) + throws X + { + meetUpdateExpr(node); + } + + public void meet(Datatype node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(DeleteData node) + throws X + { + meetUpdateExpr(node); + } + + public void meet(Difference node) + throws X + { + meetBinaryTupleOperator(node); + } + + public void meet(Distinct node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(EmptySet node) + throws X + { + meetNode(node); + } + + public void meet(Exists node) + throws X + { + meetSubQueryValueOperator(node); + } + + public void meet(Extension node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(ExtensionElem node) + throws X + { + meetNode(node); + } + + public void meet(Filter node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(FunctionCall node) + throws X + { + meetNode(node); + } + + public void meet(Group node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(GroupConcat node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(GroupElem node) + throws X + { + meetNode(node); + } + + public void meet(If node) + throws X + { + meetNode(node); + } + + public void meet(In node) + throws X + { + meetCompareSubQueryValueOperator(node); + } + + public void meet(InsertData node) + throws X + { + meetUpdateExpr(node); + } + + public void meet(Intersection node) + throws X + { + meetBinaryTupleOperator(node); + } + + public void meet(IRIFunction node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(IsBNode node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(IsLiteral node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(IsNumeric node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(IsResource node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(IsURI node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Join node) + throws X + { + meetBinaryTupleOperator(node); + } + + public void meet(Label node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Lang node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(LangMatches node) + throws X + { + meetBinaryValueOperator(node); + } + + public void meet(LeftJoin node) + throws X + { + meetBinaryTupleOperator(node); + } + + public void meet(Like node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Load node) + throws X + { + meetUpdateExpr(node); + } + + public void meet(LocalName node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(MathExpr node) + throws X + { + meetBinaryValueOperator(node); + } + + public void meet(Max node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Min node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Modify node) + throws X + { + meetUpdateExpr(node); + } + + public void meet(Move node) + throws X + { + meetUpdateExpr(node); + } + + public void meet(MultiProjection node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(Namespace node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Not node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Or node) + throws X + { + meetBinaryValueOperator(node); + } + + public void meet(Order node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(OrderElem node) + throws X + { + meetNode(node); + } + + public void meet(Projection node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(ProjectionElem node) + throws X + { + meetNode(node); + } + + public void meet(ProjectionElemList node) + throws X + { + meetNode(node); + } + + public void meet(QueryRoot node) + throws X + { + meetNode(node); + } + + public void meet(Reduced node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(Regex node) + throws X + { + meetBinaryValueOperator(node); + } + + public void meet(SameTerm node) + throws X + { + meetBinaryValueOperator(node); + } + + public void meet(Sample node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Service node) + throws X + { + meetNode(node); + } + + public void meet(SingletonSet node) + throws X + { + meetNode(node); + } + + public void meet(Slice node) + throws X + { + meetUnaryTupleOperator(node); + } + + public void meet(StatementPattern node) + throws X + { + meetNode(node); + } + + public void meet(Str node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Sum node) + throws X + { + meetUnaryValueOperator(node); + } + + public void meet(Union node) + throws X + { + meetBinaryTupleOperator(node); + } + + public void meet(ValueConstant node) + throws X + { + meetNode(node); + } + + public void meet(ListMemberOperator node) + throws X + { + meetNAryValueOperator(node); + } + + public void meet(Var node) + throws X + { + meetNode(node); + } + + public void meet(ZeroLengthPath node) + throws X + { + meetNode(node); + } + + public void meetOther(QueryModelNode node) + throws X + { + if (node instanceof UnaryTupleOperator) { + meetUnaryTupleOperator((UnaryTupleOperator)node); + } + else if (node instanceof BinaryTupleOperator) { + meetBinaryTupleOperator((BinaryTupleOperator)node); + } + else if (node instanceof CompareSubQueryValueOperator) { + meetCompareSubQueryValueOperator((CompareSubQueryValueOperator)node); + } + else if (node instanceof SubQueryValueOperator) { + meetSubQueryValueOperator((SubQueryValueOperator)node); + } + else if (node instanceof UnaryValueOperator) { + meetUnaryValueOperator((UnaryValueOperator)node); + } + else if (node instanceof BinaryValueOperator) { + meetBinaryValueOperator((BinaryValueOperator)node); + } + else if (node instanceof UpdateExpr) { + meetUpdateExpr((UpdateExpr)node); + } + else { + meetNode(node); + } + } + + /** + * Method called by all meet methods with a + * {@link BinaryTupleOperator} node as argument. Forwards the call to + * {@link #meetNode} by default. + * + * @param node + * The node that is being visited. + */ + protected void meetBinaryTupleOperator(BinaryTupleOperator node) + throws X + { + meetNode(node); + } + + /** + * Method called by all meet methods with a + * {@link BinaryValueOperator} node as argument. Forwards the call to + * {@link #meetNode} by default. + * + * @param node + * The node that is being visited. + */ + protected void meetBinaryValueOperator(BinaryValueOperator node) + throws X + { + meetNode(node); + } + + /** + * Method called by all meet methods with a + * {@link CompareSubQueryValueOperator} node as argument. Forwards the call + * to {@link #meetSubQueryValueOperator} by default. + * + * @param node + * The node that is being visited. + */ + protected void meetCompareSubQueryValueOperator(CompareSubQueryValueOperator node) + throws X + { + meetSubQueryValueOperator(node); + } + + /** + * Method called by all meet methods with a + * {@link org.eclipse.rdf4j.query.algebra.NAryValueOperator} node as argument. + * Forwards the call to {@link #meetNode} by default. + * + * @param node + * The node that is being visited. + */ + protected void meetNAryValueOperator(NAryValueOperator node) + throws X + { + meetNode(node); + } + + /** + * Method called by all of the other meet methods that are not + * overridden in subclasses. This method can be overridden in subclasses to + * define default behaviour when visiting nodes. The default behaviour of + * this method is to visit the node's children. + * + * @param node + * The node that is being visited. + */ + protected void meetNode(QueryModelNode node) + throws X + { + node.visitChildren(this); + } + + /** + * Method called by all meet methods with a + * {@link SubQueryValueOperator} node as argument. Forwards the call to + * {@link #meetNode} by default. + * + * @param node + * The node that is being visited. + */ + protected void meetSubQueryValueOperator(SubQueryValueOperator node) + throws X + { + meetNode(node); + } + + /** + * Method called by all meet methods with a + * {@link UnaryTupleOperator} node as argument. Forwards the call to + * {@link #meetNode} by default. + * + * @param node + * The node that is being visited. + */ + protected void meetUnaryTupleOperator(UnaryTupleOperator node) + throws X + { + meetNode(node); + } + + /** + * Method called by all meet methods with a + * {@link UnaryValueOperator} node as argument. Forwards the call to + * {@link #meetNode} by default. + * + * @param node + * The node that is being visited. + */ + protected void meetUnaryValueOperator(UnaryValueOperator node) + throws X + { + meetNode(node); + } + + /** + * Method called by all meet methods with a {@link UpdateExpr} node + * as argument. Forwards the call to {@link #meetNode} by default. + * + * @param node + * The node that is being visited. + */ + protected void meetUpdateExpr(UpdateExpr node) + throws X + { + meetNode(node); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelNodeReplacer.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelNodeReplacer.java new file mode 100644 index 00000000000..3585447befb --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelNodeReplacer.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.helpers; + +import org.eclipse.rdf4j.query.algebra.BinaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.BinaryValueOperator; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.UnaryTupleOperator; +import org.eclipse.rdf4j.query.algebra.UnaryValueOperator; +import org.eclipse.rdf4j.query.algebra.ValueExpr; + +@Deprecated +public class QueryModelNodeReplacer extends AbstractQueryModelVisitor { + + private QueryModelNode former; + + private QueryModelNode replacement; + + public void replaceChildNode(QueryModelNode parent, QueryModelNode former, QueryModelNode replacement) { + this.former = former; + this.replacement = replacement; + parent.visit(this); + } + + public void replaceNode(QueryModelNode former, QueryModelNode replacement) { + replaceChildNode(former.getParentNode(), former, replacement); + } + + public void removeChildNode(QueryModelNode parent, QueryModelNode former) { + replaceChildNode(parent, former, null); + } + + public void removeNode(QueryModelNode former) { + replaceChildNode(former.getParentNode(), former, null); + } + + @Override + public void meet(Filter node) + { + if (replacement == null) { + replaceNode(node, node.getArg()); + } + else if (replacement instanceof ValueExpr) { + assert former == node.getCondition(); + node.setCondition((ValueExpr)replacement); + } + else { + assert former == node.getArg(); + node.setArg((TupleExpr)replacement); + } + } + + @Override + protected void meetBinaryTupleOperator(BinaryTupleOperator node) + { + if (node.getLeftArg() == former) { + if (replacement == null) { + replaceNode(node, node.getRightArg()); + } + else { + node.setLeftArg((TupleExpr)replacement); + } + } + else { + assert former == node.getRightArg(); + if (replacement == null) { + replaceNode(node, node.getLeftArg()); + } + else { + node.setRightArg((TupleExpr)replacement); + } + } + } + + @Override + protected void meetBinaryValueOperator(BinaryValueOperator node) + { + if (former == node.getLeftArg()) { + if (replacement == null) { + replaceNode(node, node.getRightArg()); + } + else { + node.setLeftArg((ValueExpr)replacement); + } + } + else { + assert former == node.getRightArg(); + if (replacement == null) { + replaceNode(node, node.getLeftArg()); + } + else { + node.setRightArg((ValueExpr)replacement); + } + } + } + + @Override + protected void meetUnaryTupleOperator(UnaryTupleOperator node) + { + assert former == node.getArg(); + if (replacement == null) { + removeNode(node); + } + else { + node.setArg((TupleExpr)replacement); + } + } + + @Override + protected void meetUnaryValueOperator(UnaryValueOperator node) + { + assert former == node.getArg(); + if (replacement == null) { + removeNode(node); + } + else { + node.setArg((ValueExpr)replacement); + } + } + + @Override + protected void meetNode(QueryModelNode node) + { + throw new IllegalArgumentException("Unhandled Node: " + node); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelTreePrinter.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelTreePrinter.java new file mode 100644 index 00000000000..dcf94a9f31b --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelTreePrinter.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.helpers; + +import org.eclipse.rdf4j.query.algebra.QueryModelNode; + +/** + * QueryModelVisitor implementation that "prints" a tree representation of a + * query model. The tree representations is printed to an internal character + * buffer and can be retrieved using {@link #getTreeString()}. As an + * alternative, the static utility method {@link #printTree(QueryModelNode)} can + * be used. + */ +public class QueryModelTreePrinter extends AbstractQueryModelVisitor { + + /*-----------* + * Constants * + *-----------*/ + + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + /*-----------* + * Constants * + *-----------*/ + + public static String printTree(QueryModelNode node) { + QueryModelTreePrinter treePrinter = new QueryModelTreePrinter(); + node.visit(treePrinter); + return treePrinter.getTreeString(); + } + + /*-----------* + * Variables * + *-----------*/ + + private String indentString = " "; + + private StringBuilder buf; + + private int indentLevel = 0; + + /*--------------* + * Constructors * + *--------------*/ + + public QueryModelTreePrinter() { + buf = new StringBuilder(256); + } + + /*---------* + * Methods * + *---------*/ + + public String getTreeString() { + return buf.toString(); + } + + @Override + protected void meetNode(QueryModelNode node) + { + for (int i = 0; i < indentLevel; i++) { + buf.append(indentString); + } + + buf.append(node.getSignature()); + buf.append(LINE_SEPARATOR); + + indentLevel++; + + super.meetNode(node); + + indentLevel--; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelVisitorBase.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelVisitorBase.java new file mode 100644 index 00000000000..2dc6d636b27 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/QueryModelVisitorBase.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.helpers; + +/** + * @deprecated since 4.0. Use {@link AbstractQueryModelVisitor} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class QueryModelVisitorBase extends AbstractQueryModelVisitor { + +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/StatementPatternCollector.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/StatementPatternCollector.java new file mode 100644 index 00000000000..ddf016997c1 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/StatementPatternCollector.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.helpers; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * A QueryModelVisitor that collects StatementPattern's from a query model. + * StatementPatterns thet are part of filters/constraints are not included in + * the result. + */ +public class StatementPatternCollector extends AbstractQueryModelVisitor { + + public static List process(QueryModelNode node) { + StatementPatternCollector collector = new StatementPatternCollector(); + node.visit(collector); + return collector.getStatementPatterns(); + } + + private List stPatterns = new ArrayList(); + + public List getStatementPatterns() { + return stPatterns; + } + + @Override + public void meet(Filter node) + { + // Skip boolean constraints + node.getArg().visit(this); + } + + @Override + public void meet(StatementPattern node) + { + stPatterns.add(node); + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/TupleExprs.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/TupleExprs.java new file mode 100644 index 00000000000..95af713e8f9 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/TupleExprs.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.helpers; + +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.Projection; +import org.eclipse.rdf4j.query.algebra.TupleExpr; + +/** + * Utility methods for {@link TupleExpr} objects. + * + * @author Jeen Broekstra + * @since 2.7.3 + */ +public class TupleExprs { + + /** + * Verifies if the supplied {@link TupleExpr} contains a {@link Projection}. + * If the supplied TupleExpr is a {@link Join} or contains a {@link Join}, + * projections inside that Join's arguments will not be taken into + * account. + * + * @param t + * a tuple expression. + * @return true if the TupleExpr contains a projection (outside + * of a Join), false otherwise. + * @since 2.7.3 + */ + public static boolean containsProjection(TupleExpr t) { + @SuppressWarnings("serial") + class VisitException extends Exception { + } + final boolean[] result = new boolean[1]; + try { + t.visit(new AbstractQueryModelVisitor() { + + @Override + public void meet(Projection node) + throws VisitException + { + result[0] = true; + throw new VisitException(); + } + + @Override + public void meet(Join node) + throws VisitException + { + // projections already inside a Join need not be + // taken into account + result[0] = false; + throw new VisitException(); + } + }); + } + catch (VisitException ex) { + // Do nothing. We have thrown this exception on the first + // meeting of Projection or Join. + } + return result[0]; + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/VarNameCollector.java b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/VarNameCollector.java new file mode 100644 index 00000000000..395f5b5778d --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/helpers/VarNameCollector.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.helpers; + +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.Var; + +/** + * A QueryModelVisitor that collects the names of (non-constant) variables that + * are used in a query model. + */ +public class VarNameCollector extends AbstractQueryModelVisitor { + + public static Set process(QueryModelNode node) { + VarNameCollector collector = new VarNameCollector(); + node.visit(collector); + return collector.getVarNames(); + } + + private Set varNames = new LinkedHashSet(); + + public Set getVarNames() { + return varNames; + } + + @Override + public void meet(Var var) { + if (!var.hasValue()) { + varNames.add(var.getName()); + } + } +} diff --git a/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/package.html b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/package.html new file mode 100644 index 00000000000..bb5cbbdaa70 --- /dev/null +++ b/core/queryalgebra/model/src/main/java/org/eclipse/rdf4j/query/algebra/package.html @@ -0,0 +1,5 @@ + + +Query Algebra + + diff --git a/core/queryalgebra/pom.xml b/core/queryalgebra/pom.xml new file mode 100644 index 00000000000..5edf15e818c --- /dev/null +++ b/core/queryalgebra/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-core + 4.1.0-SNAPSHOT + + + rdf4j-queryalgebra + pom + + RDF4J: Query algebra + Query algebra model and evaluation. + + + model + evaluation + geosparql + + + diff --git a/core/queryparser/api/pom.xml b/core/queryparser/api/pom.xml new file mode 100644 index 00000000000..1074a4ead49 --- /dev/null +++ b/core/queryparser/api/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-queryparser + 4.1.0-SNAPSHOT + + + rdf4j-queryparser-api + + RDF4J: Query parser - API + Query language parsers API. + + + + ${project.groupId} + rdf4j-query + ${project.version} + + + ${project.groupId} + rdf4j-queryalgebra-model + ${project.version} + + + ${project.groupId} + rdf4j-util + ${project.version} + + + junit + junit + + + + diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedBooleanQuery.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedBooleanQuery.java new file mode 100644 index 00000000000..369ce35f855 --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedBooleanQuery.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import org.eclipse.rdf4j.query.algebra.TupleExpr; + +/** + * A query formulated in the OpenRDF query algebra that produces a boolean value + * as its result. + * + * @author Arjohn Kampman + */ +public class ParsedBooleanQuery extends ParsedQuery { + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new boolean query. To complete this query, a tuple expression + * needs to be supplied to it using {@link #setTupleExpr(TupleExpr)}. + */ + public ParsedBooleanQuery() { + super(); + } + + /** + * Creates a new boolean query for the supplied tuple expression. + * + * @param tupleExpr + * A tuple expression representing the query, formulated in OpenRDF + * Query Algebra objects. + */ + public ParsedBooleanQuery(TupleExpr tupleExpr) { + super(tupleExpr); + } + + /** + * Creates a new boolean query for the supplied tuple expression. + * + * @param tupleExpr + * A tuple expression representing the query, formulated in OpenRDF + * Query Algebra objects. + */ + public ParsedBooleanQuery(String sourceString, TupleExpr tupleExpr) { + super(sourceString, tupleExpr); + } +} diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedGraphQuery.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedGraphQuery.java new file mode 100644 index 00000000000..612f5aea9c9 --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedGraphQuery.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import java.util.Collections; +import java.util.Map; + +import org.eclipse.rdf4j.query.algebra.TupleExpr; + +/** + * A query forumalated in the OpenRDF query algebra that produces an RDF graph + * (a set of statements) as its result. + * + * @author Arjohn Kampman + */ +public class ParsedGraphQuery extends ParsedQuery { + + /*-----------* + * Variables * + *-----------*/ + + private Map queryNamespaces; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new graph query. To complete this query, a tuple expression + * needs to be supplied to it using {@link #setTupleExpr(TupleExpr)}. + */ + public ParsedGraphQuery() { + super(); + } + + /** + * Creates a new graph query. To complete this query, a tuple expression + * needs to be supplied to it using {@link #setTupleExpr(TupleExpr)}. + * + * @param namespaces + * A mapping of namespace prefixes to namespace names representing the + * namespaces that are used in the query. + */ + public ParsedGraphQuery(Map namespaces) { + super(); + queryNamespaces = namespaces; + } + + /** + * Creates a new graph query for the supplied tuple expression. + * + * @param tupleExpr + * A tuple expression representing the query, formulated in Sail Query + * Model objects. + */ + public ParsedGraphQuery(TupleExpr tupleExpr) { + super(tupleExpr); + } + + + /** + * Creates a new graph query for the supplied tuple expression. + * + * @param tupleExpr + * A tuple expression representing the query, formulated in Sail Query + * Model objects. + */ + public ParsedGraphQuery(String sourceString, TupleExpr tupleExpr) { + super(sourceString, tupleExpr); + } + + /** + * Creates a new graph query. + * + * @param tupleExpr + * A tuple expression representing the query, formulated in Sail Query + * Model objects. + * @param namespaces + * A mapping of namespace prefixes to namespace names representing the + * namespaces that are used in the query. + */ + public ParsedGraphQuery(TupleExpr tupleExpr, Map namespaces) { + this(tupleExpr); + queryNamespaces = namespaces; + } + + /** + * Creates a new graph query. + * + * @param tupleExpr + * A tuple expression representing the query, formulated in Sail Query + * Model objects. + * @param namespaces + * A mapping of namespace prefixes to namespace names representing the + * namespaces that are used in the query. + */ + public ParsedGraphQuery(String sourceString, TupleExpr tupleExpr, Map namespaces) { + this(sourceString, tupleExpr); + queryNamespaces = namespaces; + } + + /*---------* + * Methods * + *---------*/ + + public Map getQueryNamespaces() { + if (queryNamespaces != null) { + return queryNamespaces; + } + else { + return Collections.emptyMap(); + } + } +} diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedOperation.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedOperation.java new file mode 100644 index 00000000000..00953eceef8 --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedOperation.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + + +/** + * Abstract superclass of all operations that can be formulated in a query + * language and parsed by the query parser. + * + * @author Jeen Broekstra + */ +public abstract class ParsedOperation { + + + /** + * The source string (e.g. SPARQL query) that produced this operation. + */ + private final String sourceString; + + public ParsedOperation() { + this(null); + } + + public ParsedOperation(String sourceString) { + super(); + this.sourceString = sourceString; + } + + + + /** + * @return Returns the sourceString. + */ + public String getSourceString() { + return sourceString; + } + +} diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedQuery.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedQuery.java new file mode 100644 index 00000000000..7f839d8eeec --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedQuery.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.TupleExpr; + +/** + * Abstract super class of all query types that a query parser can generate. + * + * @author Arjohn Kampman + */ +public abstract class ParsedQuery extends ParsedOperation { + + /*-----------* + * Variables * + *-----------*/ + + private TupleExpr tupleExpr; + + /** + * The dataset that was specified in the operation, if any. + */ + private Dataset dataset; + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new query object. To complete this query, a tuple expression + * needs to be supplied to it using {@link #setTupleExpr(TupleExpr)}. + */ + public ParsedQuery() { + super(); + } + + /** + * Creates a new query object. To complete this query, a tuple expression + * needs to be supplied to it using {@link #setTupleExpr(TupleExpr)}. + */ + public ParsedQuery(String sourceString) { + super(sourceString); + } + + /** + * Creates a new query object. + * + * @param tupleExpr + * The tuple expression underlying this query. + */ + public ParsedQuery(String sourceString, TupleExpr tupleExpr) { + this(sourceString); + setTupleExpr(tupleExpr); + } + + /** + * Creates a new query object. + * + * @param tupleExpr + * The tuple expression underlying this query. + */ + public ParsedQuery(TupleExpr tupleExpr) { + this(null, tupleExpr); + } + + /** + * Creates a new query object. + * + * @param tupleExpr + * The tuple expression underlying this query. + */ + public ParsedQuery(TupleExpr tupleExpr, Dataset dataset) { + this(null, tupleExpr, dataset); + } + + /** + * Creates a new query object. + * + * @param tupleExpr + * The tuple expression underlying this query. + */ + public ParsedQuery(String sourceString, TupleExpr tupleExpr, Dataset dataset) { + this(sourceString, tupleExpr); + setDataset(dataset); + } + + /*---------* + * Methods * + *---------*/ + + public Dataset getDataset() { + return dataset; + } + + public void setDataset(Dataset dataset) { + this.dataset = dataset; + } + + /** + * Gets the tuple expression underlying this operation. + */ + public void setTupleExpr(TupleExpr tupleExpr) { + assert tupleExpr != null : "tupleExpr must not be null"; + this.tupleExpr = tupleExpr; + } + + /** + * Gets the tuple expression underlying this operation. + */ + public TupleExpr getTupleExpr() { + return tupleExpr; + } + + @Override + public String toString() { + if (getDataset() != null) { + return getDataset().toString() + getTupleExpr().toString(); + } + else { + return getTupleExpr().toString(); + } + } + +} diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedTupleQuery.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedTupleQuery.java new file mode 100644 index 00000000000..7a0bbec6f70 --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedTupleQuery.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import org.eclipse.rdf4j.query.algebra.TupleExpr; + +/** + * A query formulated in the OpenRDF query algebra that produces a set of tuples + * as its result. + * + * @author Arjohn Kampman + */ +public class ParsedTupleQuery extends ParsedQuery { + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new tuple query. To complete this query, a tuple expression + * needs to be supplied to it using {@link #setTupleExpr(TupleExpr)}. + */ + public ParsedTupleQuery() { + super(); + } + + /** + * Creates a new tuple query for the supplied tuple expression. + * + * @param tupleExpr + * A tuple expression representing the query, formulated in OpenRDF + * Query Algebra objects. + */ + public ParsedTupleQuery(TupleExpr tupleExpr) { + super(tupleExpr); + } + + /** + * Creates a new tuple query for the supplied tuple expression. + * + * @param tupleExpr + * A tuple expression representing the query, formulated in OpenRDF + * Query Algebra objects. + */ + public ParsedTupleQuery(String sourceString, TupleExpr tupleExpr) { + super(sourceString, tupleExpr); + } +} diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedUpdate.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedUpdate.java new file mode 100644 index 00000000000..8ea23833602 --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/ParsedUpdate.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.UpdateExpr; + +/** + * A parsed update sequence formulated in the OpenRDF query algebra. + * + * @author Jeen Broekstra + */ +public class ParsedUpdate extends ParsedOperation { + + /*-----------* + * Variables * + *-----------*/ + + private Map namespaces; + + private List updateExprs = new ArrayList(); + + private Map datasetMapping = new IdentityHashMap(); + + /*--------------* + * Constructors * + *--------------*/ + + /** + * Creates a new update sequence. To complete this update sequence, one or + * more update expressions need to be supplied to it using + * {@link #addUpdateExpr(UpdateExpr)}. + */ + public ParsedUpdate() { + super(); + } + + public ParsedUpdate(String sourceString) { + super(sourceString); + } + + public ParsedUpdate(String sourceString, Map namespaces) { + super(sourceString); + this.namespaces = namespaces; + } + + /** + * Creates a new update sequence. To complete this update sequence, one or + * update expressions need to be supplied to it using + * {@link #addUpdateExpr(UpdateExpr)}. + * + * @param namespaces + * A mapping of namespace prefixes to namespace names representing the + * namespaces that are used in the update. + */ + public ParsedUpdate(Map namespaces) { + super(); + this.namespaces = namespaces; + } + + /*---------* + * Methods * + *---------*/ + + public Map getNamespaces() { + if (namespaces != null) { + return namespaces; + } + else { + return Collections.emptyMap(); + } + } + + public void addUpdateExpr(UpdateExpr updateExpr) { + updateExprs.add(updateExpr); + } + + public List getUpdateExprs() { + return updateExprs; + } + + /** + * @param updateExpr + * The updateExpr to map to a dataset. + * @param dataset + * the dataset that applies to the updateExpr. May be null. + */ + public void map(UpdateExpr updateExpr, Dataset dataset) { + datasetMapping.put(updateExpr, dataset); + } + + /** + * @return Returns the map of update expressions and associated datasets. + */ + public Map getDatasetMapping() { + return datasetMapping; + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + // TODO visualize dataset in toString()? + for (UpdateExpr updateExpr : updateExprs) { + stringBuilder.append(updateExpr.toString()); + stringBuilder.append("; "); + } + return stringBuilder.toString(); + } +} diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParser.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParser.java new file mode 100644 index 00000000000..f10b57157ed --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParser.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import java.util.List; + +import org.eclipse.rdf4j.query.MalformedQueryException; + +/** + * An RDF query parser translate query strings in some query language to OpenRDF + * query models. + */ +public interface QueryParser { + + public ParsedUpdate parseUpdate(String updateStr, String baseURI) + throws MalformedQueryException; + + public ParsedQuery parseQuery(String queryStr, String baseURI) + throws MalformedQueryException; +} diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserFactory.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserFactory.java new file mode 100644 index 00000000000..efb586c91b7 --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserFactory.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import org.eclipse.rdf4j.query.QueryLanguage; + +/** + * A QueryParserFactory returns {@link QueryParser}s for a specific query + * language. + * + * @author Arjohn Kampman + */ +public interface QueryParserFactory { + + /** + * Returns the query language for this factory. + */ + public QueryLanguage getQueryLanguage(); + + /** + * Returns a QueryParser instance. + */ + public QueryParser getParser(); +} diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserRegistry.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserRegistry.java new file mode 100644 index 00000000000..01c9a2bf36c --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserRegistry.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import org.eclipse.rdf4j.common.lang.service.ServiceRegistry; +import org.eclipse.rdf4j.query.QueryLanguage; + +/** + * A registry that keeps track of the available {@link QueryParserFactory}s. + * + * @author Arjohn Kampman + */ +public class QueryParserRegistry extends ServiceRegistry { + + /** + * Internal helper class to avoid continuous synchronized checking. + */ + private static class QueryParserRegistryHolder { + + public static final QueryParserRegistry instance = new QueryParserRegistry(); + } + + /** + * Gets the default QueryParserRegistry. + * + * @return The default registry. + */ + public static QueryParserRegistry getInstance() { + return QueryParserRegistryHolder.instance; + } + + public QueryParserRegistry() { + super(QueryParserFactory.class); + } + + @Override + protected QueryLanguage getKey(QueryParserFactory factory) { + return factory.getQueryLanguage(); + } +} \ No newline at end of file diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserUtil.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserUtil.java new file mode 100644 index 00000000000..93ab4e36c57 --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryParserUtil.java @@ -0,0 +1,222 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.query.parser.QueryPrologLexer.Token; + +/** + * Utility class for creating query parsers and parsing queries in various query + * languages. + */ +public class QueryParserUtil { + + public static QueryParser createParser(QueryLanguage ql) + throws UnsupportedQueryLanguageException + { + QueryParserFactory factory = QueryParserRegistry.getInstance().get(ql).orElseThrow( + () -> new UnsupportedQueryLanguageException("No factory available for query language " + ql)); + return factory.getParser(); + } + + /** + * Parses the supplied operation into a query model. + * + * @param ql + * The language in which the operation is formulated. + * @param operation + * The operation. + * @param baseURI + * The base URI to resolve any relative URIs that are in the operation + * against, can be null if the operation does not contain any + * relative URIs. + * @return The model for the parsed operation. + * @throws MalformedQueryException + * If the supplied operation was malformed. + * @throws UnsupportedQueryLanguageException + * If the specified query language is not supported. + */ + public static ParsedOperation parseOperation(QueryLanguage ql, String operation, String baseURI) + throws MalformedQueryException + { + ParsedOperation parsedOperation = null; + QueryParser parser = createParser(ql); + + if (QueryLanguage.SPARQL.equals(ql)) { + String strippedOperation = removeSPARQLQueryProlog(operation).toUpperCase(); + + if (strippedOperation.startsWith("SELECT") || strippedOperation.startsWith("CONSTRUCT") + || strippedOperation.startsWith("DESCRIBE") || strippedOperation.startsWith("ASK")) + { + parsedOperation = parser.parseQuery(operation, baseURI); + } + else { + parsedOperation = parser.parseUpdate(operation, baseURI); + } + } + else { + // SPARQL is the only QL supported by sesame that has update + // operations, so we simply redirect to parseQuery + parsedOperation = parser.parseQuery(operation, baseURI); + } + + return parsedOperation; + } + + /** + * Parses the supplied update operation into a query model. + * + * @param ql + * The language in which the update operation is formulated. + * @param update + * The update operation. + * @param baseURI + * The base URI to resolve any relative URIs that are in the operation + * against, can be null if the update operation does not + * contain any relative URIs. + * @return The model for the parsed update operation. + * @throws MalformedQueryException + * If the supplied update operation was malformed. + * @throws UnsupportedQueryLanguageException + * If the specified query language is not supported. + */ + public static ParsedUpdate parseUpdate(QueryLanguage ql, String update, String baseURI) + throws MalformedQueryException, UnsupportedQueryLanguageException + { + QueryParser parser = createParser(ql); + return parser.parseUpdate(update, baseURI); + } + + /** + * Parses the supplied query into a query model. + * + * @param ql + * The language in which the query is formulated. + * @param query + * The query. + * @param baseURI + * The base URI to resolve any relative URIs that are in the query + * against, can be null if the query does not contain any + * relative URIs. + * @return The query model for the parsed query. + * @throws MalformedQueryException + * If the supplied query was malformed. + * @throws UnsupportedQueryLanguageException + * If the specified query language is not supported. + */ + public static ParsedQuery parseQuery(QueryLanguage ql, String query, String baseURI) + throws MalformedQueryException, UnsupportedQueryLanguageException + { + QueryParser parser = createParser(ql); + return parser.parseQuery(query, baseURI); + } + + /** + * Parses the supplied query into a query model. + * + * @param ql + * The language in which the query is formulated. + * @param query + * The query. + * @return The query model for the parsed query. + * @throws IllegalArgumentException + * If the supplied query is not a tuple query. + * @throws MalformedQueryException + * If the supplied query was malformed. + * @throws UnsupportedQueryLanguageException + * If the specified query language is not supported. + */ + public static ParsedTupleQuery parseTupleQuery(QueryLanguage ql, String query, String baseURI) + throws MalformedQueryException, UnsupportedQueryLanguageException + { + ParsedOperation q = parseQuery(ql, query, baseURI); + + if (q instanceof ParsedTupleQuery) { + return (ParsedTupleQuery)q; + } + + throw new IllegalArgumentException("query is not a tuple query: " + query); + } + + /** + * Parses the supplied query into a query model. + * + * @param ql + * The language in which the query is formulated. + * @param query + * The query. + * @return The query model for the parsed query. + * @throws IllegalArgumentException + * If the supplied query is not a graph query. + * @throws MalformedQueryException + * If the supplied query was malformed. + * @throws UnsupportedQueryLanguageException + * If the specified query language is not supported. + */ + public static ParsedGraphQuery parseGraphQuery(QueryLanguage ql, String query, String baseURI) + throws MalformedQueryException, UnsupportedQueryLanguageException + { + ParsedOperation q = parseQuery(ql, query, baseURI); + + if (q instanceof ParsedGraphQuery) { + return (ParsedGraphQuery)q; + } + + throw new IllegalArgumentException("query is not a graph query: " + query); + } + + /** + * Parses the supplied query into a query model. + * + * @param ql + * The language in which the query is formulated. + * @param query + * The query. + * @return The query model for the parsed query. + * @throws IllegalArgumentException + * If the supplied query is not a graph query. + * @throws MalformedQueryException + * If the supplied query was malformed. + * @throws UnsupportedQueryLanguageException + * If the specified query language is not supported. + */ + public static ParsedBooleanQuery parseBooleanQuery(QueryLanguage ql, String query, String baseURI) + throws MalformedQueryException, UnsupportedQueryLanguageException + { + ParsedOperation q = parseQuery(ql, query, baseURI); + + if (q instanceof ParsedBooleanQuery) { + return (ParsedBooleanQuery)q; + } + + throw new IllegalArgumentException("query is not a boolean query: " + query); + } + + /** + * Removes SPARQL prefix and base declarations, if any, from the supplied + * SPARQL query string. The supplied query string is assumed to be + * syntactically legal. + * + * @param queryString + * a syntactically legal SPARQL query string + * @return a substring of queryString, with prefix and base declarations + * removed. + */ + public static String removeSPARQLQueryProlog(String queryString) { + final Token t = QueryPrologLexer.getRestOfQueryToken(queryString); + if (t != null) { + return t.getStringValue(); + } + else { + return queryString; + } + } + +} diff --git a/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryPrologLexer.java b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryPrologLexer.java new file mode 100644 index 00000000000..5dee12e725b --- /dev/null +++ b/core/queryparser/api/src/main/java/org/eclipse/rdf4j/query/parser/QueryPrologLexer.java @@ -0,0 +1,235 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A simple lexer that tokenizes a syntactically legal input SPARQL query string + * on prolog items (prefixes, base declarations, IRIs, comments, and syntactical + * tokens such as keywords, opening and closing brackets, and hashes). + * + * @author Jeen Broekstra + * @since 2.7.12 + */ +public class QueryPrologLexer { + + public static enum TokenType { + PREFIX_KEYWORD, + PREFIX, + BASE_KEYWORD, + LBRACKET, + RBRACKET, + IRI, + HASH, + COMMENT, + REST_OF_QUERY + } + + private static final Token HASH_TOKEN = new Token(TokenType.HASH, "#"); + + private static final Token PREFIX_KEYWORD_TOKEN = new Token(TokenType.PREFIX_KEYWORD, "PREFIX"); + + private static final Token BASE_KEYWORD_TOKEN = new Token(TokenType.BASE_KEYWORD, "BASE"); + + private static final Token LBRACKET_TOKEN = new Token(TokenType.LBRACKET, "<"); + + private static final Token RBRACKET_TOKEN = new Token(TokenType.RBRACKET, ">"); + + private static final Pattern IRI_PATTERN = Pattern.compile("^<([^>]*)>*"); + + private static final Pattern PREFIX_PATTERN = Pattern.compile("^prefix([^:]+):", Pattern.CASE_INSENSITIVE); + +// private static final Pattern COMMENT_PATTERN = Pattern.compile("^#([^\n]+/)"); + private static final Pattern COMMENT_PATTERN = Pattern.compile("^(#.*((\r)?\n|(\r)?\n*))*"); + + public static class Token { + + public final TokenType t; + + public final String s; + + public Token(TokenType t, String s) { + this.t = t; + this.s = s; + } + + public TokenType getType() { + return t; + } + + /** + * Get the corresponding string value for this token. For example in the + * case of an {@link TokenType#IRI} token, this will return the string + * representation of that IRI. + */ + public String getStringValue() { + return s; + } + + @Override + public String toString() { + return "[" + t.toString() + "] '" + s + "'"; + } + } + + /** + * Tokenizes a syntactically legal input SPARQL query on prolog elements. The + * last token in the returned list is of type {@link TokenType#REST_OF_QUERY} + * and contains the SPARQL query string minus the prolog. + * + * @param input + * a syntactically legal SPARQL query string + * @return a list with tokens for each prolog element. If the input string is + * syntactically legal SPARQL, the final returned token is guaranteed + * to be of type {@link TokenType#REST_OF_QUERY} and to contain the + * SPARQL query string minus the prolog. If the input string is not + * syntactically legal SPARQL, the method will still return normally + * but no guarantees about the returned list are made. + */ + public static List lex(String input) { + final List result = new ArrayList(); + for (int i = 0; i < input.length();) { + char c = input.charAt(i); + switch (c) { + case '#': + result.add(HASH_TOKEN); + String comment = readComment(input, i); + i += comment.length() + 1; // 1 for hash + result.add(new Token(TokenType.COMMENT, comment)); + break; + case 'p': + case 'P': + result.add(PREFIX_KEYWORD_TOKEN); + // read PREFIX + String prefix = readPrefix(input, i); + result.add(new Token(TokenType.PREFIX, prefix.trim())); + i = i + prefix.length() + 7; // 6 for prefix keyword, 1 for ':' + break; + case 'b': + case 'B': + result.add(BASE_KEYWORD_TOKEN); + i += 4; // 4 for base keyword + break; + case '<': + // read IRI + result.add(LBRACKET_TOKEN); + String iri = readIRI(input, i); + result.add(new Token(TokenType.IRI, iri)); + result.add(RBRACKET_TOKEN); + i += iri.length() + 2; // 2 for opening and closing brackets + break; + default: + if (Character.isWhitespace(c)) { + i++; + } + else { + String restOfQuery = input.substring(i); + result.add(new Token(TokenType.REST_OF_QUERY, restOfQuery)); + i += restOfQuery.length(); + } + break; + } + } + + return result; + } + + /** + * Tokenizes the input string on prolog elements and returns the final Token. + * If the input string is a syntactically legal SPARQL query, this Token will + * be of type {@link TokenType#REST_OF_QUERY} and contain the query string + * minus prolog. + * + * @param input + * a syntactically legal SPARQL string + * @return if the input is syntactically legal SPARQL, a Token containing the + * query string without prolog. If the input is not syntactically + * legal, the method will still exist normally, but no guarantees are + * made about the returned object. + */ + public static Token getRestOfQueryToken(String input) { + Token result = null; + for (int i = 0; i < input.length();) { + char c = input.charAt(i); + switch (c) { + case '#': + String comment = readComment(input, i); + i += comment.length() + 1; // 1 for hash + break; + case 'p': + case 'P': + // read PREFIX + String prefix = readPrefix(input, i); + i = i + prefix.length() + 7; // 6 for prefix keyword, 1 for ':' + break; + case 'b': + case 'B': + i += 4; // 4 for base keyword + break; + case '<': + // read IRI + String iri = readIRI(input, i); + i += iri.length() + 2; // 2 for opening and closing brackets + break; + default: + if (Character.isWhitespace(c)) { + i++; + } + else { + String restOfQuery = input.substring(i); + result = (new Token(TokenType.REST_OF_QUERY, restOfQuery)); + i += restOfQuery.length(); + } + break; + } + } + + return result; + } + + /** + * Reads the first comment line from the input, and returns + * the comment line (including the line break character) without + * the leading "#". + * @param input + * @param index + * @return + */ + private static String readComment(String input, int index) { + String comment = null; + Matcher matcher = COMMENT_PATTERN.matcher(input.substring(index)); + if (matcher.find()) { + comment = matcher.group(1); + // the regex group includes the # => just remove it + comment = comment.substring(1); + } + return comment; + } + + private static String readPrefix(String input, int index) { + String prefix = null; + Matcher matcher = PREFIX_PATTERN.matcher(input.substring(index)); + if (matcher.find()) { + prefix = matcher.group(1); + } + return prefix; + } + + private static String readIRI(String input, int index) { + String iri = null; + Matcher matcher = IRI_PATTERN.matcher(input.substring(index)); + if (matcher.find()) { + iri = matcher.group(1); + } + return iri; + } +} diff --git a/core/queryparser/api/src/test/java/org/eclipse/rdf4j/query/parser/QueryParserUtilTest.java b/core/queryparser/api/src/test/java/org/eclipse/rdf4j/query/parser/QueryParserUtilTest.java new file mode 100644 index 00000000000..5e47e4b65be --- /dev/null +++ b/core/queryparser/api/src/test/java/org/eclipse/rdf4j/query/parser/QueryParserUtilTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.junit.Assert; +import org.junit.Test; + + +/** + * + * @author Andreas Schwarte + */ +public class QueryParserUtilTest { + + + @Test + public void testGetRestOfQueryString() throws Exception { + + String queryString = "# this is a comment\n" + + "PREFIX : \n" + + "# one more comment\r\n" + + "SELECT * WHERE { ?s ?p ?o }"; + + String restQuery = QueryParserUtil.removeSPARQLQueryProlog(queryString); + Assert.assertEquals("SELECT * WHERE { ?s ?p ?o }", restQuery); + } +} diff --git a/core/queryparser/api/src/test/java/org/eclipse/rdf4j/query/parser/QueryPrologLexerTest.java b/core/queryparser/api/src/test/java/org/eclipse/rdf4j/query/parser/QueryPrologLexerTest.java new file mode 100644 index 00000000000..fd578c59375 --- /dev/null +++ b/core/queryparser/api/src/test/java/org/eclipse/rdf4j/query/parser/QueryPrologLexerTest.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.eclipse.rdf4j.query.parser.QueryPrologLexer; +import org.eclipse.rdf4j.query.parser.QueryPrologLexer.Token; +import org.eclipse.rdf4j.query.parser.QueryPrologLexer.TokenType; +import org.junit.Test; + +/** + * @author jeen + */ +public class QueryPrologLexerTest { + + @Test + public void testLexEmptyString() { + List tokens = QueryPrologLexer.lex(""); + assertNotNull(tokens); + assertEquals(0, tokens.size()); + + } + + @Test + public void testFinalTokenEmptyString() { + try { + Token t = QueryPrologLexer.getRestOfQueryToken(""); + } + catch (Exception e) { + fail("lexer should not throw exception on malformed input"); + } + } + + @Test + public void testLexNoProlog1() { + List tokens = QueryPrologLexer.lex("SELECT * WHERE {?s ?p ?o} "); + assertNotNull(tokens); + assertEquals(1, tokens.size()); + + Token t = tokens.get(0); + assertTrue(t.getType().equals(TokenType.REST_OF_QUERY)); + } + + @Test + public void testFinalTokenNoProlog1() { + Token t = QueryPrologLexer.getRestOfQueryToken("SELECT * WHERE {?s ?p ?o} "); + assertNotNull(t); + assertTrue(t.getType().equals(TokenType.REST_OF_QUERY)); + } + + @Test + public void testLexWithComment() { + List tokens = QueryPrologLexer.lex("# COMMENT \n SELECT * WHERE {?s ?p ?o} "); + assertNotNull(tokens); + assertEquals(3, tokens.size()); + assertEquals(" COMMENT \n", tokens.get(1).s); + + Token t = tokens.get(tokens.size() - 1); + assertTrue(t.getType().equals(TokenType.REST_OF_QUERY)); + assertEquals("SELECT * WHERE {?s ?p ?o} ", t.s); + } + + @Test + public void testLexWithComment_WindowsLinebreak() { + List tokens = QueryPrologLexer.lex("# COMMENT \r\n SELECT * WHERE {?s ?p ?o} "); + assertNotNull(tokens); + + Token t = tokens.get(tokens.size() - 1); + assertTrue(t.getType().equals(TokenType.REST_OF_QUERY)); + assertEquals("SELECT * WHERE {?s ?p ?o} ", t.s); + } + + @Test + public void testLexWithComment_NoSpaceBeforeQuery() { + List tokens = QueryPrologLexer.lex("# COMMENT \nSELECT * WHERE {?s ?p ?o} "); + assertNotNull(tokens); + + Token t = tokens.get(tokens.size() - 1); + assertTrue(t.getType().equals(TokenType.REST_OF_QUERY)); + assertEquals("SELECT * WHERE {?s ?p ?o} ", t.s); + } + + @Test + public void testFinalTokenWithComment() { + Token t = QueryPrologLexer.getRestOfQueryToken("# COMMENT \n SELECT * WHERE {?s ?p ?o} "); + assertNotNull(t); + assertTrue(t.getType().equals(TokenType.REST_OF_QUERY)); + assertEquals("SELECT * WHERE {?s ?p ?o} ", t.s); + } + + @Test + public void testFinalTokenWithMultilineComment() { + Token t = QueryPrologLexer.getRestOfQueryToken("# COMMENT \n # COMMENT (continued) \n SELECT * WHERE {?s ?p ?o} "); + assertNotNull(t); + assertTrue(t.getType().equals(TokenType.REST_OF_QUERY)); + assertEquals("SELECT * WHERE {?s ?p ?o} ", t.s); + } + + @Test + public void testLexWithBaseAndComment() { + List tokens = QueryPrologLexer.lex("BASE # COMMENT \n SELECT * WHERE {?s ?p ?o} "); + assertNotNull(tokens); + + Token t = tokens.get(tokens.size() - 1); + assertTrue(t.getType().equals(TokenType.REST_OF_QUERY)); + assertEquals("SELECT * WHERE {?s ?p ?o} ", t.s); + } + + @Test + public void testFinalTokenWithBaseAndComment() { + Token t = QueryPrologLexer.getRestOfQueryToken("BASE # COMMENT \n SELECT * WHERE {?s ?p ?o} "); + assertNotNull(t); + assertTrue(t.getType().equals(TokenType.REST_OF_QUERY)); + } + + @Test + public void testLexSyntaxError() { + // all that is guaranteed in queries with syntax errors is that the lexer + // returns. there are no guarantees that the + // last token is the rest of the query in this case. Any syntax errors in + // the query are to be picked up by subsequent processing. + + try { + List tokens = QueryPrologLexer.lex("BASE + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-core + 4.1.0-SNAPSHOT + + + rdf4j-queryparser + pom + + RDF4J: Query parser + Query parser API and implementations. + + + api + serql + sparql + + + diff --git a/core/queryparser/serql/pom.xml b/core/queryparser/serql/pom.xml new file mode 100644 index 00000000000..25ee5428961 --- /dev/null +++ b/core/queryparser/serql/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-queryparser + 4.1.0-SNAPSHOT + + + rdf4j-queryparser-serql + + RDF4J: Query parser - SeRQL + Query language parser implementation for SeRQL. + + + + ${project.groupId} + rdf4j-queryparser-api + ${project.version} + + + ${project.groupId} + rdf4j-query + ${project.version} + + + ${project.groupId} + rdf4j-queryalgebra-model + ${project.version} + + + ${project.groupId} + rdf4j-model + ${project.version} + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + org.slf4j + slf4j-api + + + + diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ASTVisitorBase.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ASTVisitorBase.java new file mode 100644 index 00000000000..2653a15295f --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ASTVisitorBase.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +/** + * @deprecated since 4.0. Use {@link AbstractASTVisitor} instead. + * @author Jeen Broekstra + */ +@Deprecated +public abstract class ASTVisitorBase extends AbstractASTVisitor { + +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/AbstractASTVisitor.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/AbstractASTVisitor.java new file mode 100644 index 00000000000..4541d1bcb00 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/AbstractASTVisitor.java @@ -0,0 +1,476 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import org.eclipse.rdf4j.query.parser.serql.ast.ASTAnd; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTArgList; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBNode; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBasicPathExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBasicPathExprTail; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBooleanConstant; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBound; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTCompOperator; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTCompare; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTCompareAll; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTCompareAny; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTConstruct; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTConstructQuery; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTDatatype; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTEdge; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTExists; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTFrom; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTFunctionCall; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTGraphIntersect; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTGraphMinus; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTGraphUnion; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIn; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTInList; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIsBNode; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIsLiteral; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIsResource; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIsURI; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLabel; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLang; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLangMatches; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLike; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLimit; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLiteral; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLocalName; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNamespace; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNamespaceDecl; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNode; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNodeElem; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNot; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNull; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOffset; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOptPathExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOptPathExprTail; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOrderBy; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOrderExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTPathExprList; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTPathExprUnion; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTProjectionElem; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQName; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQueryBody; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQueryContainer; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTRegex; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTReifiedStat; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSameTerm; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSelect; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSelectQuery; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTStr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTString; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTTupleIntersect; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTTupleMinus; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTTupleUnion; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTURI; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTVar; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTWhere; +import org.eclipse.rdf4j.query.parser.serql.ast.SimpleNode; +import org.eclipse.rdf4j.query.parser.serql.ast.SyntaxTreeBuilderVisitor; +import org.eclipse.rdf4j.query.parser.serql.ast.VisitorException; + +public abstract class AbstractASTVisitor implements SyntaxTreeBuilderVisitor { + + public Object visit(SimpleNode node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTQueryContainer node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTNamespaceDecl node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTTupleUnion node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTTupleMinus node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTTupleIntersect node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTGraphUnion node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTGraphMinus node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTGraphIntersect node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTSelectQuery node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTSelect node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTProjectionElem node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTConstructQuery node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTConstruct node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTQueryBody node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTFrom node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTWhere node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTOrderBy node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTOrderExpr node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTLimit node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTOffset node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTPathExprList node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTPathExprUnion node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTBasicPathExpr node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTOptPathExpr node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTBasicPathExprTail node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTOptPathExprTail node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTEdge node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTNodeElem node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTNode node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTReifiedStat node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTOr node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTAnd node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTBooleanConstant node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTNot node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTBound node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTIsResource node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTIsLiteral node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTIsURI node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTIsBNode node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTLangMatches node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTExists node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTSameTerm node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTCompare node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTCompareAny node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTCompareAll node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTLike node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTRegex node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTIn node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTInList node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTCompOperator node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTVar node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTDatatype node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTLang node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTLabel node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTNamespace node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTLocalName node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTStr node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTFunctionCall node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTArgList node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTURI node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTQName node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTBNode node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTLiteral node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTString node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } + + public Object visit(ASTNull node, Object data) + throws VisitorException + { + return node.childrenAccept(this, data); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/AnonymousVarGenerator.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/AnonymousVarGenerator.java new file mode 100644 index 00000000000..286ba303f8f --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/AnonymousVarGenerator.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import org.eclipse.rdf4j.query.parser.serql.ast.ASTEdge; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNode; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNodeElem; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTReifiedStat; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTVar; +import org.eclipse.rdf4j.query.parser.serql.ast.SyntaxTreeBuilderTreeConstants; +import org.eclipse.rdf4j.query.parser.serql.ast.VisitorException; + +/** + * Inserts anonymous variables into the abstract syntax tree at places where + * such variables are already implicitly present. + */ +public class AnonymousVarGenerator extends AbstractASTVisitor { + + private int anonymousVarNo = 1; + + @Override + public Object visit(ASTNode node, Object data) + throws VisitorException + { + if (node.jjtGetNumChildren() == 0) { + ASTNodeElem nodeElem = createNodeElem(); + nodeElem.jjtSetParent(node); + node.jjtAppendChild(nodeElem); + } + + return super.visit(node, data); + } + + @Override + public Object visit(ASTReifiedStat node, Object data) + throws VisitorException + { + if (node.jjtGetChild(0) instanceof ASTEdge) { + // subject node is missing + ASTNodeElem nodeElem = createNodeElem(); + nodeElem.jjtSetParent(node); + node.jjtInsertChild(nodeElem, 0); + } + + if (node.jjtGetNumChildren() <= 2) { + // object node is missing + ASTNodeElem nodeElem = createNodeElem(); + nodeElem.jjtSetParent(node); + node.jjtAppendChild(nodeElem); + } + + if (node.getID() == null) { + node.setID(createAnonymousVar()); + } + + return super.visit(node, data); + } + + private ASTNodeElem createNodeElem() { + ASTNodeElem nodeElem = new ASTNodeElem(SyntaxTreeBuilderTreeConstants.JJTNODEELEM); + + ASTVar var = createAnonymousVar(); + var.jjtSetParent(nodeElem); + nodeElem.jjtAppendChild(var); + + return nodeElem; + } + + private ASTVar createAnonymousVar() { + ASTVar var = new ASTVar(SyntaxTreeBuilderTreeConstants.JJTVAR); + var.setName("-anon-" + anonymousVarNo++); + var.setAnonymous(true); + return var; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ConstructorBuilder.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ConstructorBuilder.java new file mode 100644 index 00000000000..b423664f0a8 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ConstructorBuilder.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.rdf4j.query.algebra.BNodeGenerator; +import org.eclipse.rdf4j.query.algebra.Distinct; +import org.eclipse.rdf4j.query.algebra.EmptySet; +import org.eclipse.rdf4j.query.algebra.Extension; +import org.eclipse.rdf4j.query.algebra.ExtensionElem; +import org.eclipse.rdf4j.query.algebra.MultiProjection; +import org.eclipse.rdf4j.query.algebra.Projection; +import org.eclipse.rdf4j.query.algebra.ProjectionElem; +import org.eclipse.rdf4j.query.algebra.ProjectionElemList; +import org.eclipse.rdf4j.query.algebra.Reduced; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.helpers.StatementPatternCollector; + +class ConstructorBuilder { + + public TupleExpr buildConstructor(TupleExpr bodyExpr, TupleExpr constructExpr, boolean distinct, + boolean reduced) + { + return buildConstructor(bodyExpr, constructExpr, true, distinct, reduced); + } + + public TupleExpr buildConstructor(TupleExpr bodyExpr, boolean distinct, boolean reduced) { + return buildConstructor(bodyExpr, bodyExpr, false, distinct, reduced); + } + + private TupleExpr buildConstructor(TupleExpr bodyExpr, TupleExpr constructExpr, + boolean explicitConstructor, boolean distinct, boolean reduced) + { + TupleExpr result = bodyExpr; + + // Retrieve all StatementPattern's from the construct expression + List statementPatterns = StatementPatternCollector.process(constructExpr); + + Set constructVars = getConstructVars(statementPatterns); + + // Note: duplicate elimination is a two-step process. The first step + // removes duplicates from the set of constructor variables. After this + // step, any bnodes that need to be generated are added to each solution + // and these solutions are projected to subject-predicate-object bindings. + // Finally, the spo-bindings are again filtered for duplicates. + if (distinct || reduced) { + // Create projection that removes all bindings that are not used in the + // constructor + ProjectionElemList projElemList = new ProjectionElemList(); + + for (Var var : constructVars) { + // Ignore anonymous and constant vars, these will be handled after + // the distinct + if (!var.isAnonymous() && !var.hasValue()) { + projElemList.addElement(new ProjectionElem(var.getName())); + } + } + + result = new Projection(result, projElemList); + + // Filter the duplicates from these projected bindings + if (distinct) { + result = new Distinct(result); + } + else { + result = new Reduced(result); + } + } + + // Create BNodeGenerator's for all anonymous variables + Map extElemMap = new HashMap(); + + for (Var var : constructVars) { + if (var.isAnonymous() && !extElemMap.containsKey(var)) { + ValueExpr valueExpr = null; + + if (var.hasValue()) { + valueExpr = new ValueConstant(var.getValue()); + } + else if (explicitConstructor) { + // only generate bnodes in case of an explicit constructor + valueExpr = new BNodeGenerator(); + } + + if (valueExpr != null) { + extElemMap.put(var, new ExtensionElem(valueExpr, var.getName())); + } + } + } + + if (!extElemMap.isEmpty()) { + result = new Extension(result, extElemMap.values()); + } + + // Create a Projection for each StatementPattern in the constructor + List projections = new ArrayList(); + + for (StatementPattern sp : statementPatterns) { + ProjectionElemList projElemList = new ProjectionElemList(); + + projElemList.addElement(new ProjectionElem(sp.getSubjectVar().getName(), "subject")); + projElemList.addElement(new ProjectionElem(sp.getPredicateVar().getName(), "predicate")); + projElemList.addElement(new ProjectionElem(sp.getObjectVar().getName(), "object")); + + projections.add(projElemList); + } + + if (projections.size() == 1) { + result = new Projection(result, projections.get(0)); + + // Note: no need to apply the second duplicate elimination step if + // there's just one projection + } + else if (projections.size() > 1) { + result = new MultiProjection(result, projections); + + if (distinct) { + // Add another distinct to filter duplicate statements + result = new Distinct(result); + } + else if (reduced) { + result = new Reduced(result); + } + } + else { + // Empty constructor + result = new EmptySet(); + } + + return result; + } + + /** + * Gets the set of variables that are relevant for the constructor. This + * method accumulates all subject, predicate and object variables from the + * supplied statement patterns, but ignores any context variables. + */ + private Set getConstructVars(Collection statementPatterns) { + Set vars = new LinkedHashSet(statementPatterns.size() * 2); + + for (StatementPattern sp : statementPatterns) { + vars.add(sp.getSubjectVar()); + vars.add(sp.getPredicateVar()); + vars.add(sp.getObjectVar()); + } + + return vars; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/GraphPattern.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/GraphPattern.java new file mode 100644 index 00000000000..a142a5dd30c --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/GraphPattern.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.eclipse.rdf4j.query.algebra.And; +import org.eclipse.rdf4j.query.algebra.Filter; +import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.LeftJoin; +import org.eclipse.rdf4j.query.algebra.SingletonSet; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; + +/** + * A graph pattern consisting of (required and optional) tuple expressions and + * boolean constraints. + */ +class GraphPattern { + + /** + * The graph pattern's parent, if any. + */ + private GraphPattern parent = null; + + /** + * The context of this graph pattern. + */ + private Var contextVar; + + /** + * The StatementPattern-scope of this graph pattern. + */ + private StatementPattern.Scope spScope = StatementPattern.Scope.DEFAULT_CONTEXTS; + + /** + * The required tuple expressions in this graph pattern. + */ + private List requiredTEs = new ArrayList(); + + /** + * The optional tuple expressions and their constraints in this graph + * pattern. + */ + private List optionalTEs = new ArrayList(); + + /** + * The boolean constraints in this graph pattern. + */ + private List constraints = new ArrayList(); + + /** + * Creates a new graph pattern. + */ + public GraphPattern() { + } + + /** + * Creates a new graph pattern that inherits the context and scope from a + * parent graph pattern. + */ + public GraphPattern(GraphPattern parent) { + if (parent != null) { + this.parent = parent; + contextVar = parent.contextVar; + spScope = parent.spScope; + } + } + + public GraphPattern getParent() { + return parent; + } + + public void setContextVar(Var contextVar) { + this.contextVar = contextVar; + } + + public Var getContextVar() { + return contextVar; + } + + public void setStatementPatternScope(StatementPattern.Scope spScope) { + this.spScope = spScope; + } + + public StatementPattern.Scope getStatementPatternScope() { + return spScope; + } + + public void addRequiredTE(TupleExpr te) { + requiredTEs.add(te); + } + + public List getRequiredTEs() { + return Collections.unmodifiableList(requiredTEs); + } + + public void addOptionalTE(GraphPattern gp) { + List constraints = gp.removeAllConstraints(); + TupleExpr tupleExpr = gp.buildTupleExpr(); + + OptionalTupleExpr optTE; + + if (constraints.isEmpty()) { + optTE = new OptionalTupleExpr(tupleExpr); + } + else { + ValueExpr constraint = constraints.get(0); + for (int i = 1; i < constraints.size(); i++) { + constraint = new And(constraint, constraints.get(i)); + } + + optTE = new OptionalTupleExpr(tupleExpr, constraint); + } + + optionalTEs.add(optTE); + } + + public List getOptionalTEs() { + return Collections.unmodifiableList(optionalTEs); + } + + public void addConstraint(ValueExpr constraint) { + constraints.add(constraint); + } + + public void addConstraints(Collection constraints) { + this.constraints.addAll(constraints); + } + + public List getConstraints() { + return Collections.unmodifiableList(constraints); + } + + public List removeAllConstraints() { + List constraints = this.constraints; + this.constraints = new ArrayList(); + return constraints; + } + + /** + * Removes all tuple expressions and constraints. + */ + public void clear() { + requiredTEs.clear(); + optionalTEs.clear(); + constraints.clear(); + } + + /** + * Builds a combined tuple expression from the tuple expressions and + * constraints in this graph pattern. + * + * @return A tuple expression for this graph pattern. + */ + public TupleExpr buildTupleExpr() { + TupleExpr result; + + if (requiredTEs.isEmpty()) { + result = new SingletonSet(); + } + else { + result = requiredTEs.get(0); + + for (int i = 1; i < requiredTEs.size(); i++) { + result = new Join(result, requiredTEs.get(i)); + } + } + + for (OptionalTupleExpr optTE : optionalTEs) { + if (optTE.hasConstraint()) { + result = new LeftJoin(result, optTE.getTupleExpr(), optTE.getConstraint()); + } + else { + result = new LeftJoin(result, optTE.getTupleExpr()); + } + } + + for (ValueExpr constraint : constraints) { + result = new Filter(result, constraint); + } + + return result; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/NamespaceDeclProcessor.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/NamespaceDeclProcessor.java new file mode 100644 index 00000000000..ba939a1c621 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/NamespaceDeclProcessor.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.rdf4j.model.vocabulary.OWL; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.model.vocabulary.SESAME; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNamespaceDecl; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQName; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQueryContainer; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTURI; +import org.eclipse.rdf4j.query.parser.serql.ast.SyntaxTreeBuilderTreeConstants; +import org.eclipse.rdf4j.query.parser.serql.ast.VisitorException; + +/** + * Processes the namespace declarations in a SeRQL query model. + * + * @author Arjohn Kampman + */ +class NamespaceDeclProcessor extends AbstractASTVisitor { + + /** + * Processes prefix declarations in queries. This method collects all + * prefixes that are declared in the supplied query, verifies that prefixes + * are not redefined and replaces any {@link ASTQName} nodes in the query + * with equivalent {@link ASTIRI} nodes. + * + * @param qc + * The query that needs to be processed. + * @return A map containing the prefixes that are declared in the query (key) + * and the namespace they map to (value). + * @throws MalformedQueryException + * If the query contains redefined prefixes or qnames that use + * undefined prefixes. + */ + public static Map process(ASTQueryContainer qc) + throws MalformedQueryException + { + List nsDeclList = qc.getNamespaceDeclList(); + + // Build a prefix --> URI map + Map nsMap = new LinkedHashMap(); + for (ASTNamespaceDecl nsDecl : nsDeclList) { + String prefix = nsDecl.getPrefix(); + String uri = nsDecl.getURI().getValue(); + + if (nsMap.containsKey(prefix)) { + // Prefix already defined + if (nsMap.get(prefix).equals(uri)) { + // duplicate, ignore + } + else { + throw new MalformedQueryException("Multiple namespace declarations for prefix '" + prefix + + "'"); + } + } + else { + nsMap.put(prefix, uri); + } + } + + // Use default namespace prefixes when not defined explicitly + if (!nsMap.containsKey("rdf")) { + nsMap.put("rdf", RDF.NAMESPACE); + } + if (!nsMap.containsKey("rdfs")) { + nsMap.put("rdfs", RDFS.NAMESPACE); + } + if (!nsMap.containsKey("xsd")) { + nsMap.put("xsd", XMLSchema.NAMESPACE); + } + if (!nsMap.containsKey("owl")) { + nsMap.put("owl", OWL.NAMESPACE); + } + if (!nsMap.containsKey("sesame")) { + nsMap.put("sesame", SESAME.NAMESPACE); + } + + // For backwards compatibility: + Map extendedNsMap = new HashMap(nsMap); + if (!extendedNsMap.containsKey("serql")) { + extendedNsMap.put("serql", SESAME.NAMESPACE); + } + + // Replace all qnames with URIs + QNameProcessor visitor = new QNameProcessor(extendedNsMap); + try { + qc.jjtAccept(visitor, null); + } + catch (VisitorException e) { + throw new MalformedQueryException(e.getMessage(), e); + } + + return nsMap; + } + + private static class QNameProcessor extends AbstractASTVisitor { + + private Map prefixMap; + + public QNameProcessor(Map prefixMap) { + this.prefixMap = prefixMap; + } + + @Override + public Object visit(ASTQName qnameNode, Object data) + throws VisitorException + { + String qname = qnameNode.getValue(); + + int colonIdx = qname.indexOf(':'); + assert colonIdx >= 0 : "colonIdx should be >= 0: " + colonIdx; + + String prefix = qname.substring(0, colonIdx); + String localName = qname.substring(colonIdx + 1); + + String namespace = prefixMap.get(prefix); + if (namespace == null) { + throw new VisitorException("QName '" + qname + "' uses an undefined prefix"); + } + + // Replace the qname node with a new IRI node in the parent node + ASTURI uriNode = new ASTURI(SyntaxTreeBuilderTreeConstants.JJTURI); + uriNode.setValue(namespace + localName); + qnameNode.jjtReplaceWith(uriNode); + + return null; + } + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/NullProcessor.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/NullProcessor.java new file mode 100644 index 00000000000..95fc5015d84 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/NullProcessor.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import static org.eclipse.rdf4j.query.algebra.Compare.CompareOp.EQ; +import static org.eclipse.rdf4j.query.algebra.Compare.CompareOp.NE; + +import java.util.Iterator; + +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBooleanConstant; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBooleanExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBound; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTCompare; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNot; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNull; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTProjectionElem; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQueryContainer; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSelect; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTValueExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTVar; +import org.eclipse.rdf4j.query.parser.serql.ast.Node; +import org.eclipse.rdf4j.query.parser.serql.ast.VisitorException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Processes {@link ASTNull} nodes in query models. Null's that appear in + * projections are simply removed as that doesn't change the semantics. Null's + * that appear in value comparisons are either replaced with {@link ASTBound} + * nodes or constants. + * + * @author Arjohn Kampman + */ +class NullProcessor { + + /** + * Processes escape sequences in ASTString objects. + * + * @param qc + * The query that needs to be processed. + * @throws MalformedQueryException + * If an invalid escape sequence was found. + */ + public static void process(ASTQueryContainer qc) + throws MalformedQueryException + { + NullVisitor visitor = new NullVisitor(); + try { + qc.jjtAccept(visitor, null); + } + catch (VisitorException e) { + throw new MalformedQueryException(e.getMessage(), e); + } + } + + private static class NullVisitor extends AbstractASTVisitor { + + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + public NullVisitor() { + } + + @Override + public Object visit(ASTSelect selectNode, Object data) + throws VisitorException + { + Iterator iter = selectNode.jjtGetChildren().iterator(); + + while (iter.hasNext()) { + ASTProjectionElem pe = (ASTProjectionElem)iter.next(); + + if (pe.getValueExpr() instanceof ASTNull) { + logger.warn("Use of NULL values in SeRQL queries has been deprecated"); + iter.remove(); + } + } + + return null; + } + + @Override + public Object visit(ASTCompare compareNode, Object data) + throws VisitorException + { + boolean leftIsNull = compareNode.getLeftOperand() instanceof ASTNull; + boolean rightIsNull = compareNode.getRightOperand() instanceof ASTNull; + CompareOp operator = compareNode.getOperator().getValue(); + + if (leftIsNull && rightIsNull) { + switch (operator) { + case EQ: + logger.warn("Use of NULL values in SeRQL queries has been deprecated, use BOUND(...) instead"); + compareNode.jjtReplaceWith(new ASTBooleanConstant(true)); + break; + case NE: + logger.warn("Use of NULL values in SeRQL queries has been deprecated, use BOUND(...) instead"); + compareNode.jjtReplaceWith(new ASTBooleanConstant(false)); + break; + default: + throw new VisitorException( + "Use of NULL values in SeRQL queries has been deprecated, use BOUND(...) instead"); + } + } + else if (leftIsNull || rightIsNull) { + ASTValueExpr valueOperand; + if (leftIsNull) { + valueOperand = compareNode.getRightOperand(); + } + else { + valueOperand = compareNode.getLeftOperand(); + } + + if (valueOperand instanceof ASTVar && operator == EQ || operator == NE) { + ASTBooleanExpr replacementNode = new ASTBound(valueOperand); + + if (operator == EQ) { + replacementNode = new ASTNot(replacementNode); + } + + compareNode.jjtReplaceWith(replacementNode); + + return null; + } + + throw new VisitorException( + "Use of NULL values in SeRQL queries has been deprecated, use BOUND(...) instead"); + } + + return null; + } + + @Override + public Object visit(ASTNull nullNode, Object data) + throws VisitorException + { + throw new VisitorException( + "Use of NULL values in SeRQL queries has been deprecated, use BOUND(...) instead"); + } + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/OptionalTupleExpr.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/OptionalTupleExpr.java new file mode 100644 index 00000000000..6c143d3a653 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/OptionalTupleExpr.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.ValueExpr; + +/** + * @author Arjohn Kampman + */ +class OptionalTupleExpr { + + private final TupleExpr tupleExpr; + + private final ValueExpr constraint; + + public OptionalTupleExpr(TupleExpr tupleExpr) { + this(tupleExpr, null); + } + + public OptionalTupleExpr(TupleExpr tupleExpr, ValueExpr constraint) { + this.tupleExpr = tupleExpr; + this.constraint = constraint; + } + + public TupleExpr getTupleExpr() { + return tupleExpr; + } + + public ValueExpr getConstraint() { + return constraint; + } + + public boolean hasConstraint() { + return constraint != null; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ProjectionAliasProcessor.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ProjectionAliasProcessor.java new file mode 100644 index 00000000000..2458db8c4f3 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ProjectionAliasProcessor.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.rdf4j.query.parser.serql.ast.ASTProjectionElem; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSelect; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTString; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTVar; +import org.eclipse.rdf4j.query.parser.serql.ast.Node; +import org.eclipse.rdf4j.query.parser.serql.ast.SyntaxTreeBuilderTreeConstants; +import org.eclipse.rdf4j.query.parser.serql.ast.VisitorException; + +/** + * Processes projection aliases, verifying that the specified aliases are unique + * and generating aliases for the elements for which no alias has been specified + * but that do require one. + * + * @author Arjohn Kampman + */ +class ProjectionAliasProcessor extends AbstractASTVisitor { + + @Override + public Object visit(ASTSelect node, Object data) + throws VisitorException + { + // Iterate over all projection elements to retrieve the defined aliases + Set aliases = new HashSet(); + List unaliasedNodes = new ArrayList(); + + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + ASTProjectionElem projElem = (ASTProjectionElem)node.jjtGetChild(i); + + String alias = projElem.getAlias(); + if (alias == null && projElem.getValueExpr() instanceof ASTVar) { + alias = ((ASTVar)projElem.getValueExpr()).getName(); + } + + if (alias != null) { + boolean isUnique = aliases.add(alias); + + if (!isUnique) { + throw new VisitorException("Duplicate projection element names: '" + alias + "'"); + } + } + else { + unaliasedNodes.add(projElem); + } + } + + // Iterate over the unaliased nodes and generate aliases for them + int aliasNo = 1; + for (Node projElem : unaliasedNodes) { + // Generate unique alias for projection element + String alias; + while (aliases.contains(alias = "_" + aliasNo++)) { + // try again + } + + aliases.add(alias); + + ASTString aliasNode = new ASTString(SyntaxTreeBuilderTreeConstants.JJTSTRING); + aliasNode.setValue(alias); + aliasNode.jjtSetParent(projElem); + projElem.jjtAppendChild(aliasNode); + } + + return data; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ProjectionProcessor.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ProjectionProcessor.java new file mode 100644 index 00000000000..c15c989bdba --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ProjectionProcessor.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTProjectionElem; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQueryContainer; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSelect; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSelectQuery; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTVar; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTWhere; +import org.eclipse.rdf4j.query.parser.serql.ast.Node; +import org.eclipse.rdf4j.query.parser.serql.ast.SyntaxTreeBuilderTreeConstants; +import org.eclipse.rdf4j.query.parser.serql.ast.VisitorException; + +/** + * Processes projections. 'Wildcard' projections are made explicit by adding + * projection elements with the appropriate variable nodes to them. Explicit + * projections are checked to see if they don't contain any unbound variables. + * + * @author Arjohn Kampman + */ +class ProjectionProcessor extends AbstractASTVisitor { + + public static void process(ASTQueryContainer qc) + throws MalformedQueryException + { + try { + qc.jjtAccept(new ProjectionProcessor(), null); + } + catch (VisitorException e) { + throw new MalformedQueryException(e.getMessage(), e); + } + } + + @Override + public Object visit(ASTSelect selectNode, Object data) + throws VisitorException + { + // Collect all variables used in the body of the select query + Set bodyVars = VariableCollector.process(selectNode.jjtGetParent()); + + if (selectNode.isWildcard()) { + // Make wildcard projection explicit + for (String varName : bodyVars) { + ASTProjectionElem projElemNode = new ASTProjectionElem( + SyntaxTreeBuilderTreeConstants.JJTPROJECTIONELEM); + selectNode.jjtAppendChild(projElemNode); + projElemNode.jjtSetParent(selectNode); + + ASTVar varNode = new ASTVar(SyntaxTreeBuilderTreeConstants.JJTVAR); + varNode.setName(varName); + projElemNode.jjtAppendChild(varNode); + varNode.jjtSetParent(projElemNode); + } + + selectNode.setWildcard(false); + } + else { + // Verify that all projection vars are bound + Set projVars = new LinkedHashSet(); + + for (ASTProjectionElem projElem : selectNode.getProjectionElemList()) { + projVars.addAll(VariableCollector.process(projElem.getValueExpr())); + } + + projVars.removeAll(bodyVars); + + if (!projVars.isEmpty()) { + StringBuilder errMsg = new StringBuilder(64); + errMsg.append("Unbound variable(s) in projection: "); + + Iterator iter = projVars.iterator(); + while (iter.hasNext()) { + errMsg.append(iter.next()); + if (iter.hasNext()) { + errMsg.append(", "); + } + } + + throw new VisitorException(errMsg.toString()); + } + } + + return data; + } + + /*-------------------------------* + * Inner class VariableCollector * + *-------------------------------*/ + + /** + * Collects variable names for 'wildcard' projections. An instance of this + * class should be supplied to a {@link ASTSelectQuery} node. When done, the + * collected variable names can be acquired by calling + * {@link #getVariableNames}. + */ + private static class VariableCollector extends AbstractASTVisitor { + + public static Set process(Node node) + throws VisitorException + { + VariableCollector visitor = new VariableCollector(); + node.jjtAccept(visitor, null); + return visitor.getVariableNames(); + } + + private Set variableNames = new LinkedHashSet(); + + public Set getVariableNames() { + return variableNames; + } + + @Override + public Object visit(ASTSelect node, Object data) + throws VisitorException + { + // Do not visit select clauses + return data; + } + + @Override + public Object visit(ASTWhere node, Object data) + throws VisitorException + { + // Do not visit where clauses + return data; + } + + @Override + public Object visit(ASTVar node, Object data) + throws VisitorException + { + variableNames.add(node.getName()); + return super.visit(node, data); + } + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/QueryModelBuilder.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/QueryModelBuilder.java new file mode 100644 index 00000000000..544fb289d84 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/QueryModelBuilder.java @@ -0,0 +1,1035 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.algebra.And; +import org.eclipse.rdf4j.query.algebra.Bound; +import org.eclipse.rdf4j.query.algebra.Compare; +import org.eclipse.rdf4j.query.algebra.CompareAll; +import org.eclipse.rdf4j.query.algebra.CompareAny; +import org.eclipse.rdf4j.query.algebra.Datatype; +import org.eclipse.rdf4j.query.algebra.Difference; +import org.eclipse.rdf4j.query.algebra.Distinct; +import org.eclipse.rdf4j.query.algebra.Exists; +import org.eclipse.rdf4j.query.algebra.Extension; +import org.eclipse.rdf4j.query.algebra.ExtensionElem; +import org.eclipse.rdf4j.query.algebra.FunctionCall; +import org.eclipse.rdf4j.query.algebra.In; +import org.eclipse.rdf4j.query.algebra.Intersection; +import org.eclipse.rdf4j.query.algebra.IsBNode; +import org.eclipse.rdf4j.query.algebra.IsLiteral; +import org.eclipse.rdf4j.query.algebra.IsResource; +import org.eclipse.rdf4j.query.algebra.IsURI; +import org.eclipse.rdf4j.query.algebra.Label; +import org.eclipse.rdf4j.query.algebra.Lang; +import org.eclipse.rdf4j.query.algebra.LangMatches; +import org.eclipse.rdf4j.query.algebra.Like; +import org.eclipse.rdf4j.query.algebra.LocalName; +import org.eclipse.rdf4j.query.algebra.Namespace; +import org.eclipse.rdf4j.query.algebra.Not; +import org.eclipse.rdf4j.query.algebra.Or; +import org.eclipse.rdf4j.query.algebra.Order; +import org.eclipse.rdf4j.query.algebra.OrderElem; +import org.eclipse.rdf4j.query.algebra.Projection; +import org.eclipse.rdf4j.query.algebra.ProjectionElem; +import org.eclipse.rdf4j.query.algebra.ProjectionElemList; +import org.eclipse.rdf4j.query.algebra.Reduced; +import org.eclipse.rdf4j.query.algebra.Regex; +import org.eclipse.rdf4j.query.algebra.SameTerm; +import org.eclipse.rdf4j.query.algebra.SingletonSet; +import org.eclipse.rdf4j.query.algebra.Slice; +import org.eclipse.rdf4j.query.algebra.StatementPattern; +import org.eclipse.rdf4j.query.algebra.Str; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.Union; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTAnd; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBNode; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBasicPathExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBasicPathExprTail; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBooleanConstant; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBooleanExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTBound; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTCompare; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTCompareAll; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTCompareAny; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTConstruct; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTConstructQuery; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTDatatype; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTEdge; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTExists; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTFrom; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTFunctionCall; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTGraphIntersect; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTGraphMinus; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTGraphUnion; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIn; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTInList; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIsBNode; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIsLiteral; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIsResource; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTIsURI; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLabel; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLang; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLangMatches; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLike; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLimit; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLiteral; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLocalName; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNamespace; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNode; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNodeElem; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNot; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTNull; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOffset; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOptPathExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOptPathExprTail; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOrderBy; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTOrderExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTPathExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTPathExprTail; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTPathExprUnion; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTProjectionElem; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQueryBody; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQueryContainer; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTRegex; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTReifiedStat; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSameTerm; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSelect; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTSelectQuery; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTStr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTString; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTTupleIntersect; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTTupleMinus; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTTupleUnion; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTURI; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTValueExpr; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTVar; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTWhere; +import org.eclipse.rdf4j.query.parser.serql.ast.Node; +import org.eclipse.rdf4j.query.parser.serql.ast.VisitorException; + +class QueryModelBuilder extends AbstractASTVisitor { + + public static TupleExpr buildQueryModel(ASTQueryContainer node, ValueFactory valueFactory) + throws MalformedQueryException + { + try { + QueryModelBuilder qmBuilder = new QueryModelBuilder(valueFactory); + return (TupleExpr)node.jjtAccept(qmBuilder, null); + } + catch (VisitorException e) { + throw new MalformedQueryException(e.getMessage(), e); + } + } + + /*-----------* + * Variables * + *-----------*/ + + private final ValueFactory valueFactory; + + private int constantVarID = 1; + + private GraphPattern graphPattern; + + /*--------------* + * Constructors * + *--------------*/ + + public QueryModelBuilder(ValueFactory valueFactory) { + this.valueFactory = valueFactory; + } + + /*---------* + * Methods * + *---------*/ + + private Var createConstantVar(Value value) { + Var var = new Var("-const-" + constantVarID++); + var.setAnonymous(true); + var.setValue(value); + return var; + } + + private GraphPattern parseGraphPattern(Node node) + throws VisitorException + { + graphPattern = new GraphPattern(graphPattern); + try { + node.jjtAccept(this, null); + return graphPattern; + } + finally { + graphPattern = graphPattern.getParent(); + } + } + + @Override + public TupleExpr visit(ASTQueryContainer node, Object data) + throws VisitorException + { + // Skip the namespace declarations, any information it contains should + // already have been processed + return (TupleExpr)node.getQuery().jjtAccept(this, null); + } + + @Override + public TupleExpr visit(ASTTupleUnion node, Object data) + throws VisitorException + { + TupleExpr leftArg = (TupleExpr)node.getLeftArg().jjtAccept(this, null); + TupleExpr rightArg = (TupleExpr)node.getRightArg().jjtAccept(this, null); + + TupleExpr result = new Union(leftArg, rightArg); + + if (node.isDistinct()) { + result = new Distinct(result); + } + + return result; + } + + @Override + public TupleExpr visit(ASTTupleMinus node, Object data) + throws VisitorException + { + TupleExpr leftArg = (TupleExpr)node.getLeftArg().jjtAccept(this, null); + TupleExpr rightArg = (TupleExpr)node.getRightArg().jjtAccept(this, null); + + return new Difference(leftArg, rightArg); + } + + @Override + public TupleExpr visit(ASTTupleIntersect node, Object data) + throws VisitorException + { + TupleExpr leftArg = (TupleExpr)node.getLeftArg().jjtAccept(this, null); + TupleExpr rightArg = (TupleExpr)node.getRightArg().jjtAccept(this, null); + + return new Intersection(leftArg, rightArg); + } + + @Override + public TupleExpr visit(ASTGraphUnion node, Object data) + throws VisitorException + { + TupleExpr leftArg = (TupleExpr)node.getLeftArg().jjtAccept(this, null); + TupleExpr rightArg = (TupleExpr)node.getRightArg().jjtAccept(this, null); + + TupleExpr result = new Union(leftArg, rightArg); + + if (node.isDistinct()) { + result = new Distinct(result); + } + + return result; + } + + @Override + public TupleExpr visit(ASTGraphMinus node, Object data) + throws VisitorException + { + TupleExpr leftArg = (TupleExpr)node.getLeftArg().jjtAccept(this, null); + TupleExpr rightArg = (TupleExpr)node.getRightArg().jjtAccept(this, null); + + return new Difference(leftArg, rightArg); + } + + @Override + public TupleExpr visit(ASTGraphIntersect node, Object data) + throws VisitorException + { + TupleExpr leftArg = (TupleExpr)node.getLeftArg().jjtAccept(this, null); + TupleExpr rightArg = (TupleExpr)node.getRightArg().jjtAccept(this, null); + + return new Intersection(leftArg, rightArg); + } + + @Override + public TupleExpr visit(ASTSelectQuery node, Object data) + throws VisitorException + { + TupleExpr tupleExpr; + + ASTQueryBody queryBodyNode = node.getQueryBody(); + + if (queryBodyNode != null) { + // Build tuple expression for query body + tupleExpr = (TupleExpr)queryBodyNode.jjtAccept(this, null); + } + else { + tupleExpr = new SingletonSet(); + } + + // Apply result ordering + ASTOrderBy orderByNode = node.getOrderBy(); + if (orderByNode != null) { + List orderElemements = (List)orderByNode.jjtAccept(this, null); + tupleExpr = new Order(tupleExpr, orderElemements); + } + + // Apply projection + tupleExpr = (TupleExpr)node.getSelectClause().jjtAccept(this, tupleExpr); + + // process limit and offset clauses, if present. + ASTLimit limitNode = node.getLimit(); + int limit = -1; + if (limitNode != null) { + limit = (Integer)limitNode.jjtAccept(this, null); + } + + ASTOffset offsetNode = node.getOffset(); + int offset = -1; + if (offsetNode != null) { + offset = (Integer)offsetNode.jjtAccept(this, null); + } + + if (offset >= 1 || limit >= 0) { + tupleExpr = new Slice(tupleExpr, offset, limit); + } + return tupleExpr; + } + + @Override + public TupleExpr visit(ASTSelect node, Object data) + throws VisitorException + { + TupleExpr result = (TupleExpr)data; + + Extension extension = new Extension(); + ProjectionElemList projElemList = new ProjectionElemList(); + + for (ASTProjectionElem projElemNode : node.getProjectionElemList()) { + ValueExpr valueExpr = (ValueExpr)projElemNode.getValueExpr().jjtAccept(this, null); + + String alias = projElemNode.getAlias(); + if (alias != null) { + // aliased projection element + extension.addElement(new ExtensionElem(valueExpr, alias)); + projElemList.addElement(new ProjectionElem(alias)); + } + else if (valueExpr instanceof Var) { + // unaliased variable + Var projVar = (Var)valueExpr; + projElemList.addElement(new ProjectionElem(projVar.getName())); + } + else { + throw new IllegalStateException("required alias for non-Var projection elements not found"); + } + } + + if (!extension.getElements().isEmpty()) { + extension.setArg(result); + result = extension; + } + + result = new Projection(result, projElemList); + + if (node.isDistinct()) { + result = new Distinct(result); + } + else if (node.isReduced()) { + result = new Reduced(result); + } + + return result; + } + + @Override + public TupleExpr visit(ASTConstructQuery node, Object data) + throws VisitorException + { + TupleExpr tupleExpr; + + if (node.hasQueryBody()) { + // Build tuple expression for query body + tupleExpr = (TupleExpr)node.getQueryBody().jjtAccept(this, null); + } + else { + tupleExpr = new SingletonSet(); + } + + // Apply result ordering + ASTOrderBy orderByNode = node.getOrderBy(); + if (orderByNode != null) { + List orderElemements = (List)orderByNode.jjtAccept(this, null); + tupleExpr = new Order(tupleExpr, orderElemements); + } + + // Create constructor + ConstructorBuilder cb = new ConstructorBuilder(); + ASTConstruct constructNode = node.getConstructClause(); + + if (!constructNode.isWildcard()) { + TupleExpr constructExpr = (TupleExpr)constructNode.jjtAccept(this, null); + tupleExpr = cb.buildConstructor(tupleExpr, constructExpr, constructNode.isDistinct(), + constructNode.isReduced()); + } + else if (node.hasQueryBody()) { + tupleExpr = cb.buildConstructor(tupleExpr, constructNode.isDistinct(), constructNode.isReduced()); + } + // else: "construct *" without query body, just return the SingletonSet + + // process limit and offset clauses, if present. + ASTLimit limitNode = node.getLimit(); + int limit = -1; + if (limitNode != null) { + limit = (Integer)limitNode.jjtAccept(this, null); + } + + ASTOffset offsetNode = node.getOffset(); + int offset = -1; + + if (offsetNode != null) { + offset = (Integer)offsetNode.jjtAccept(this, null); + } + + if (offset >= 1 || limit >= 0) { + tupleExpr = new Slice(tupleExpr, offset, limit); + } + + return tupleExpr; + } + + @Override + public TupleExpr visit(ASTConstruct node, Object data) + throws VisitorException + { + assert !node.isWildcard() : "Cannot build constructor for wildcards"; + + return parseGraphPattern(node.getPathExpr()).buildTupleExpr(); + } + + @Override + public TupleExpr visit(ASTQueryBody node, Object data) + throws VisitorException + { + graphPattern = new GraphPattern(graphPattern); + try { + super.visit(node, data); + return graphPattern.buildTupleExpr(); + } + finally { + graphPattern = graphPattern.getParent(); + } + } + + @Override + public Object visit(ASTFrom node, Object data) + throws VisitorException + { + StatementPattern.Scope scope = StatementPattern.Scope.DEFAULT_CONTEXTS; + Var contextVar = null; + + if (node.hasContextID()) { + scope = StatementPattern.Scope.NAMED_CONTEXTS; + ValueExpr contextID = (ValueExpr)node.getContextID().jjtAccept(this, null); + + if (contextID instanceof Var) { + contextVar = (Var)contextID; + } + else if (contextID instanceof ValueConstant) { + ValueConstant vc = (ValueConstant)contextID; + contextVar = createConstantVar(vc.getValue()); + } + else { + throw new IllegalArgumentException("Unexpected contextID result type: " + contextID.getClass()); + } + } + + graphPattern.setStatementPatternScope(scope); + graphPattern.setContextVar(contextVar); + + node.getPathExpr().jjtAccept(this, null); + + return null; + } + + @Override + public Object visit(ASTWhere node, Object data) + throws VisitorException + { + ValueExpr valueExpr = (ValueExpr)node.getCondition().jjtAccept(this, null); + graphPattern.addConstraint(valueExpr); + return null; + } + + @Override + public List visit(ASTOrderBy node, Object data) + throws VisitorException + { + List orderExprList = node.getOrderExprList(); + + List elements = new ArrayList(orderExprList.size()); + + for (ASTOrderExpr orderExpr : orderExprList) { + elements.add((OrderElem)orderExpr.jjtAccept(this, null)); + } + + return elements; + } + + @Override + public OrderElem visit(ASTOrderExpr node, Object data) + throws VisitorException + { + ValueExpr valueExpr = (ValueExpr)node.getValueExpr().jjtAccept(this, null); + return new OrderElem(valueExpr, node.isAscending()); + } + + @Override + public Integer visit(ASTLimit node, Object data) + throws VisitorException + { + return node.getValue(); + } + + @Override + public Integer visit(ASTOffset node, Object data) + throws VisitorException + { + return node.getValue(); + } + + @Override + public Object visit(ASTPathExprUnion node, Object data) + throws VisitorException + { + Iterator args = node.getPathExprList().iterator(); + + // Create new sub-graph pattern for optional path expressions + TupleExpr unionExpr = parseGraphPattern(args.next()).buildTupleExpr(); + + while (args.hasNext()) { + TupleExpr argExpr = parseGraphPattern(args.next()).buildTupleExpr(); + unionExpr = new Union(unionExpr, argExpr); + } + + graphPattern.addRequiredTE(unionExpr); + + return null; + } + + @Override + public Object visit(ASTBasicPathExpr node, Object data) + throws VisitorException + { + // process subject node + List subjVars = (List)node.getHead().jjtAccept(this, null); + + // supply subject vars to tail segment + node.getTail().jjtAccept(this, subjVars); + + return null; + } + + @Override + public Object visit(ASTOptPathExpr node, Object data) + throws VisitorException + { + // Create new sub-graph pattern for optional path expressions + graphPattern = new GraphPattern(graphPattern); + + super.visit(node, data); + + graphPattern.getParent().addOptionalTE(graphPattern); + graphPattern = graphPattern.getParent(); + + return null; + } + + @Override + public Object visit(ASTBasicPathExprTail tailNode, Object data) + throws VisitorException + { + List subjVars = (List)data; + Var predVar = (Var)tailNode.getEdge().jjtAccept(this, null); + List objVars = (List)tailNode.getNode().jjtAccept(this, null); + + Var contextVar = graphPattern.getContextVar(); + StatementPattern.Scope spScope = graphPattern.getStatementPatternScope(); + + for (Var subjVar : subjVars) { + for (Var objVar : objVars) { + StatementPattern sp = new StatementPattern(spScope, subjVar, predVar, objVar, contextVar); + graphPattern.addRequiredTE(sp); + } + } + + // Process next tail segment + ASTPathExprTail nextTailNode = tailNode.getNextTail(); + if (nextTailNode != null) { + List joinVars = nextTailNode.isBranch() ? subjVars : objVars; + nextTailNode.jjtAccept(this, joinVars); + } + + return null; + } + + @Override + public Object visit(ASTOptPathExprTail tailNode, Object data) + throws VisitorException + { + List subjVars = (List)data; + + // Create new sub-graph pattern for optional path expressions + graphPattern = new GraphPattern(graphPattern); + + // optional path expression tail + tailNode.getOptionalTail().jjtAccept(this, subjVars); + + ASTWhere whereNode = tailNode.getWhereClause(); + if (whereNode != null) { + // boolean contraint on optional path expression tail + whereNode.jjtAccept(this, null); + } + + graphPattern.getParent().addOptionalTE(graphPattern); + graphPattern = graphPattern.getParent(); + + ASTPathExprTail nextTailNode = tailNode.getNextTail(); + if (nextTailNode != null) { + // branch after optional path expression tail + nextTailNode.jjtAccept(this, subjVars); + } + + return null; + } + + @Override + public Var visit(ASTEdge node, Object data) + throws VisitorException + { + ValueExpr arg = (ValueExpr)node.getValueExpr().jjtAccept(this, null); + + if (arg instanceof Var) { + return (Var)arg; + } + else if (arg instanceof ValueConstant) { + ValueConstant vc = (ValueConstant)arg; + return createConstantVar(vc.getValue()); + } + else { + throw new IllegalArgumentException("Unexpected edge argument type: " + arg.getClass()); + } + } + + @Override + public List visit(ASTNode node, Object data) + throws VisitorException + { + List nodeVars = new ArrayList(); + + for (ASTNodeElem nodeElem : node.getNodeElemList()) { + Var nodeVar = (Var)nodeElem.jjtAccept(this, null); + nodeVars.add(nodeVar); + } + + // Create any implicit unequalities + for (int i = 0; i < nodeVars.size() - 1; i++) { + Var var1 = nodeVars.get(i); + + for (int j = i + 1; j < nodeVars.size(); j++) { + Var var2 = nodeVars.get(j); + + // At least one of the variables should be non-constant + // for the unequality to make any sense: + if (!var1.hasValue() || !var2.hasValue()) { + graphPattern.addConstraint(new Not(new SameTerm(var1, var2))); + } + } + } + + return nodeVars; + } + + @Override + public Var visit(ASTNodeElem node, Object data) + throws VisitorException + { + ValueExpr valueExpr = (ValueExpr)node.getChild().jjtAccept(this, null); + + if (valueExpr instanceof Var) { + return (Var)valueExpr; + } + else if (valueExpr instanceof ValueConstant) { + ValueConstant vc = (ValueConstant)valueExpr; + return createConstantVar(vc.getValue()); + } + else { + throw new IllegalArgumentException("Unexpected node element result type: " + valueExpr.getClass()); + } + } + + @Override + public Var visit(ASTReifiedStat node, Object data) + throws VisitorException + { + assert node.getID() != null : "ID variable not set"; + + Var subjVar = (Var)node.getSubject().jjtAccept(this, null); + Var predVar = (Var)node.getPredicate().jjtAccept(this, null); + Var objVar = (Var)node.getObject().jjtAccept(this, null); + Var idVar = (Var)node.getID().jjtAccept(this, null); + + Var contextVar = graphPattern.getContextVar(); + StatementPattern.Scope spScope = graphPattern.getStatementPatternScope(); + + Var rdfType = new Var("_rdfType", RDF.TYPE); + Var rdfStatement = new Var("_rdfStatement", RDF.STATEMENT); + Var rdfSubject = new Var("_rdfSubject", RDF.SUBJECT); + Var rdfPredicate = new Var("_rdfPredicate", RDF.PREDICATE); + Var rdfObject = new Var("_rdfObject", RDF.OBJECT); + + graphPattern.addRequiredTE(new StatementPattern(spScope, idVar, rdfType, rdfStatement, contextVar)); + graphPattern.addRequiredTE(new StatementPattern(spScope, idVar, rdfSubject, subjVar, contextVar)); + graphPattern.addRequiredTE(new StatementPattern(spScope, idVar, rdfPredicate, predVar, contextVar)); + graphPattern.addRequiredTE(new StatementPattern(spScope, idVar, rdfObject, objVar, contextVar)); + + return idVar; + } + + @Override + public ValueExpr visit(ASTOr node, Object data) + throws VisitorException + { + Iterator iter = node.getOperandList().iterator(); + + ValueExpr result = (ValueExpr)iter.next().jjtAccept(this, null); + + while (iter.hasNext()) { + ValueExpr operand = (ValueExpr)iter.next().jjtAccept(this, null); + result = new Or(result, operand); + } + + return result; + } + + @Override + public ValueExpr visit(ASTAnd node, Object data) + throws VisitorException + { + Iterator iter = node.getOperandList().iterator(); + + ValueExpr result = (ValueExpr)iter.next().jjtAccept(this, null); + + while (iter.hasNext()) { + ValueExpr operand = (ValueExpr)iter.next().jjtAccept(this, null); + result = new And(result, operand); + } + + return result; + } + + @Override + public ValueConstant visit(ASTBooleanConstant node, Object data) + throws VisitorException + { + return new ValueConstant(valueFactory.createLiteral(node.getValue())); + } + + @Override + public Not visit(ASTNot node, Object data) + throws VisitorException + { + return new Not((ValueExpr)super.visit(node, data)); + } + + @Override + public Bound visit(ASTBound node, Object data) + throws VisitorException + { + return new Bound((Var)super.visit(node, data)); + } + + @Override + public IsResource visit(ASTIsResource node, Object data) + throws VisitorException + { + return new IsResource((ValueExpr)super.visit(node, data)); + } + + @Override + public IsLiteral visit(ASTIsLiteral node, Object data) + throws VisitorException + { + return new IsLiteral((ValueExpr)super.visit(node, data)); + } + + @Override + public IsURI visit(ASTIsURI node, Object data) + throws VisitorException + { + return new IsURI((ValueExpr)super.visit(node, data)); + } + + @Override + public IsBNode visit(ASTIsBNode node, Object data) + throws VisitorException + { + return new IsBNode((ValueExpr)super.visit(node, data)); + } + + @Override + public LangMatches visit(ASTLangMatches node, Object data) + throws VisitorException + { + ValueExpr tag = (ValueExpr)node.getLanguageTag().jjtAccept(this, null); + ValueExpr range = (ValueExpr)node.getLanguageRange().jjtAccept(this, null); + return new LangMatches(tag, range); + } + + @Override + public Exists visit(ASTExists node, Object data) + throws VisitorException + { + return new Exists((TupleExpr)super.visit(node, data)); + } + + @Override + public SameTerm visit(ASTSameTerm node, Object data) + throws VisitorException + { + ValueExpr leftArg = (ValueExpr)node.getLeftOperand().jjtAccept(this, null); + ValueExpr rightArg = (ValueExpr)node.getRightOperand().jjtAccept(this, null); + return new SameTerm(leftArg, rightArg); + } + + @Override + public Compare visit(ASTCompare node, Object data) + throws VisitorException + { + ValueExpr leftArg = (ValueExpr)node.getLeftOperand().jjtAccept(this, null); + ValueExpr rightArg = (ValueExpr)node.getRightOperand().jjtAccept(this, null); + CompareOp operator = node.getOperator().getValue(); + + return new Compare(leftArg, rightArg, operator); + } + + @Override + public CompareAny visit(ASTCompareAny node, Object data) + throws VisitorException + { + ValueExpr valueExpr = (ValueExpr)node.getLeftOperand().jjtAccept(this, null); + TupleExpr tupleExpr = (TupleExpr)node.getRightOperand().jjtAccept(this, null); + CompareOp op = node.getOperator().getValue(); + + return new CompareAny(valueExpr, tupleExpr, op); + } + + @Override + public CompareAll visit(ASTCompareAll node, Object data) + throws VisitorException + { + ValueExpr valueExpr = (ValueExpr)node.getLeftOperand().jjtAccept(this, null); + TupleExpr tupleExpr = (TupleExpr)node.getRightOperand().jjtAccept(this, null); + CompareOp op = node.getOperator().getValue(); + + return new CompareAll(valueExpr, tupleExpr, op); + } + + @Override + public Like visit(ASTLike node, Object data) + throws VisitorException + { + ValueExpr expr = (ValueExpr)node.getValueExpr().jjtAccept(this, null); + String pattern = (String)node.getPattern().jjtAccept(this, null); + boolean caseSensitive = !node.ignoreCase(); + + return new Like(expr, pattern, caseSensitive); + } + + @Override + public Regex visit(ASTRegex node, Object data) + throws VisitorException + { + ValueExpr text = (ValueExpr)node.getText().jjtAccept(this, null); + ValueExpr pattern = (ValueExpr)node.getPattern().jjtAccept(this, null); + ValueExpr flags = null; + if (node.hasFlags()) { + flags = (ValueExpr)node.getFlags().jjtAccept(this, null); + } + + return new Regex(text, pattern, flags); + } + + @Override + public In visit(ASTIn node, Object data) + throws VisitorException + { + ValueExpr valueExpr = (ValueExpr)node.getLeftOperand().jjtAccept(this, null); + TupleExpr tupleExpr = (TupleExpr)node.getRightOperand().jjtAccept(this, null); + return new In(valueExpr, tupleExpr); + } + + @Override + public ValueExpr visit(ASTInList node, Object data) + throws VisitorException + { + ValueExpr leftArg = (ValueExpr)node.getValueExpr().jjtAccept(this, null); + + ValueExpr result = null; + + for (ASTValueExpr argExpr : node.getArgList().getElements()) { + ValueExpr rightArg = (ValueExpr)argExpr.jjtAccept(this, null); + + if (result == null) { + // First argument + result = new SameTerm(leftArg, rightArg); + } + else { + SameTerm sameTerm = new SameTerm(leftArg.clone(), rightArg); + result = new Or(result, sameTerm); + } + } + + assert result != null; + + return result; + } + + @Override + public Var visit(ASTVar node, Object data) + throws VisitorException + { + Var var = new Var(node.getName()); + var.setAnonymous(node.isAnonymous()); + return var; + } + + @Override + public Datatype visit(ASTDatatype node, Object data) + throws VisitorException + { + return new Datatype((ValueExpr)super.visit(node, data)); + } + + @Override + public Lang visit(ASTLang node, Object data) + throws VisitorException + { + return new Lang((ValueExpr)super.visit(node, data)); + } + + @Override + public Label visit(ASTLabel node, Object data) + throws VisitorException + { + return new Label((ValueExpr)super.visit(node, data)); + } + + @Override + public Namespace visit(ASTNamespace node, Object data) + throws VisitorException + { + return new Namespace((ValueExpr)super.visit(node, data)); + } + + @Override + public LocalName visit(ASTLocalName node, Object data) + throws VisitorException + { + return new LocalName((ValueExpr)super.visit(node, data)); + } + + @Override + public Str visit(ASTStr node, Object data) + throws VisitorException + { + return new Str((ValueExpr)super.visit(node, data)); + } + + @Override + public FunctionCall visit(ASTFunctionCall node, Object data) + throws VisitorException + { + ValueConstant vc = (ValueConstant)node.getURI().jjtAccept(this, null); + assert vc.getValue() instanceof IRI; + + FunctionCall functionCall = new FunctionCall(vc.getValue().toString()); + + for (ASTValueExpr argExpr : node.getArgList().getElements()) { + functionCall.addArg((ValueExpr)argExpr.jjtAccept(this, null)); + } + + return functionCall; + } + + @Override + public Object visit(ASTNull node, Object data) + throws VisitorException + { + throw new VisitorException( + "Use of NULL values in SeRQL queries has been deprecated, use BOUND(...) instead"); + } + + @Override + public ValueConstant visit(ASTURI node, Object data) + throws VisitorException + { + return new ValueConstant(valueFactory.createIRI(node.getValue())); + } + + @Override + public ValueConstant visit(ASTBNode node, Object data) + throws VisitorException + { + return new ValueConstant(valueFactory.createBNode(node.getID())); + } + + @Override + public ValueConstant visit(ASTLiteral litNode, Object data) + throws VisitorException + { + IRI datatype = null; + + // Get datatype URI from child URI node, if present + ASTValueExpr dtNode = litNode.getDatatypeNode(); + if (dtNode instanceof ASTURI) { + datatype = valueFactory.createIRI(((ASTURI)dtNode).getValue()); + } + else if (dtNode != null) { + throw new IllegalArgumentException("Unexpected datatype type: " + dtNode.getClass()); + } + + Literal literal; + if (datatype != null) { + literal = valueFactory.createLiteral(litNode.getLabel(), datatype); + } + else if (litNode.hasLang()) { + literal = valueFactory.createLiteral(litNode.getLabel(), litNode.getLang()); + } + else { + literal = valueFactory.createLiteral(litNode.getLabel()); + } + + return new ValueConstant(literal); + } + + @Override + public String visit(ASTString node, Object data) + throws VisitorException + { + return node.getValue(); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParser.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParser.java new file mode 100644 index 00000000000..5f82bd6afd7 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParser.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Map; + +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.parser.ParsedGraphQuery; +import org.eclipse.rdf4j.query.parser.ParsedQuery; +import org.eclipse.rdf4j.query.parser.ParsedTupleQuery; +import org.eclipse.rdf4j.query.parser.ParsedUpdate; +import org.eclipse.rdf4j.query.parser.QueryParser; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTGraphQuery; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQuery; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQueryContainer; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTTupleQuery; +import org.eclipse.rdf4j.query.parser.serql.ast.ParseException; +import org.eclipse.rdf4j.query.parser.serql.ast.SyntaxTreeBuilder; +import org.eclipse.rdf4j.query.parser.serql.ast.TokenMgrError; +import org.eclipse.rdf4j.query.parser.serql.ast.VisitorException; + +public class SeRQLParser implements QueryParser { + + public ParsedQuery parseQuery(String queryStr, String baseURI) + throws MalformedQueryException + { + try { + ASTQueryContainer qc = SyntaxTreeBuilder.parseQuery(queryStr); + + // Replace deprecated NULL nodes with semantically equivalent + // alternatives + NullProcessor.process(qc); + + StringEscapesProcessor.process(qc); + Map namespaces = NamespaceDeclProcessor.process(qc); + ProjectionProcessor.process(qc); + qc.jjtAccept(new ProjectionAliasProcessor(), null); + qc.jjtAccept(new AnonymousVarGenerator(), null); + + // TODO: check use of unbound variables? + + TupleExpr tupleExpr = QueryModelBuilder.buildQueryModel(qc, SimpleValueFactory.getInstance()); + + ASTQuery queryNode = qc.getQuery(); + ParsedQuery query; + if (queryNode instanceof ASTTupleQuery) { + query = new ParsedTupleQuery(tupleExpr); + } + else if (queryNode instanceof ASTGraphQuery) { + query = new ParsedGraphQuery(tupleExpr, namespaces); + } + else { + throw new RuntimeException("Unexpected query type: " + queryNode.getClass()); + } + + return query; + } + catch (ParseException e) { + throw new MalformedQueryException(e.getMessage(), e); + } + catch (TokenMgrError e) { + throw new MalformedQueryException(e.getMessage(), e); + } + catch (VisitorException e) { + throw new MalformedQueryException(e.getMessage(), e); + } + } + + public static void main(String[] args) + throws java.io.IOException + { + System.out.println("Your SeRQL query:"); + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + + StringBuilder buf = new StringBuilder(); + String line = null; + while ((line = in.readLine()) != null) { + if (line.length() > 0) { + buf.append(' ').append(line).append('\n'); + } + else { + String queryStr = buf.toString().trim(); + if (queryStr.length() > 0) { + try { + SeRQLParser parser = new SeRQLParser(); + parser.parseQuery(queryStr, null); + } + catch (Exception e) { + System.err.println(e.getMessage()); + e.printStackTrace(); + } + } + buf.setLength(0); + } + } + } + + public ParsedUpdate parseUpdate(String updateStr, String baseURI) + throws MalformedQueryException + { + throw new UnsupportedOperationException("SeRQL does not support update operations"); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParserFactory.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParserFactory.java new file mode 100644 index 00000000000..e4e2ea0262e --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLParserFactory.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.parser.QueryParser; +import org.eclipse.rdf4j.query.parser.QueryParserFactory; + +/** + * A {@link QueryParserFactory} for SeRQL parsers + * + * @author Arjohn Kampman + */ +public class SeRQLParserFactory implements QueryParserFactory { + + private final SeRQLParser singleton = new SeRQLParser(); + + /** + * Returns {@link QueryLanguage#SERQL}. + */ + public QueryLanguage getQueryLanguage() { + return QueryLanguage.SERQL; + } + + /** + * Returns a shared, thread-safe, instance of SeRQLParser. + */ + public QueryParser getParser() { + return singleton; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLUtil.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLUtil.java new file mode 100644 index 00000000000..c2f333c626e --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/SeRQLUtil.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import org.eclipse.rdf4j.common.text.StringUtil; + +/** + * SeRQL-related utility methods. + * + * @author Arjohn Kampman + */ +public class SeRQLUtil { + + /** + * Encodes the supplied string for inclusion as a 'normal' string in a SeRQL + * query. + */ + public static String encodeString(String s) { + s = StringUtil.gsub("\\", "\\\\", s); + s = StringUtil.gsub("\t", "\\t", s); + s = StringUtil.gsub("\n", "\\n", s); + s = StringUtil.gsub("\r", "\\r", s); + s = StringUtil.gsub("\b", "\\b", s); + s = StringUtil.gsub("\f", "\\f", s); + s = StringUtil.gsub("\"", "\\\"", s); + return s; + } + + /** + * Decodes an encoded SeRQL string. Any \-escape sequences are substituted + * with their decoded value. + * + * @param s + * An encoded SeRQL string. + * @return The unencoded string. + * @exception IllegalArgumentException + * If the supplied string is not a correctly encoded SeRQL + * string. + */ + public static String decodeString(String s) { + int backSlashIdx = s.indexOf('\\'); + + if (backSlashIdx == -1) { + // No escaped characters found + return s; + } + + int startIdx = 0; + int sLength = s.length(); + StringBuilder sb = new StringBuilder(sLength); + + while (backSlashIdx != -1) { + sb.append(s.substring(startIdx, backSlashIdx)); + + if (backSlashIdx + 1 >= sLength) { + throw new IllegalArgumentException("Unescaped backslash in: " + s); + } + + char c = s.charAt(backSlashIdx + 1); + + if (c == 't') { + sb.append('\t'); + startIdx = backSlashIdx + 2; + } + else if (c == 'n') { + sb.append('\n'); + startIdx = backSlashIdx + 2; + } + else if (c == 'r') { + sb.append('\r'); + startIdx = backSlashIdx + 2; + } + else if (c == 'b') { + sb.append('\b'); + startIdx = backSlashIdx + 2; + } + else if (c == 'f') { + sb.append('\f'); + startIdx = backSlashIdx + 2; + } + else if (c == '"') { + sb.append('"'); + startIdx = backSlashIdx + 2; + } + else if (c == '\\') { + sb.append('\\'); + startIdx = backSlashIdx + 2; + } + else if (c == 'u') { + // \\uxxxx + if (backSlashIdx + 5 >= sLength) { + throw new IllegalArgumentException( + "Incomplete Unicode escape sequence in: " + s); + } + String xx = s.substring(backSlashIdx + 2, backSlashIdx + 6); + + try { + c = (char)Integer.parseInt(xx, 16); + sb.append( c ); + + startIdx = backSlashIdx + 6; + } + catch (NumberFormatException e) { + throw new IllegalArgumentException( + "Illegal Unicode escape sequence '\\u" + xx + "' in: " + s); + } + } + else if (c == 'U') { + // \\Uxxxxxxxx + if (backSlashIdx + 9 >= sLength) { + throw new IllegalArgumentException( + "Incomplete Unicode escape sequence in: " + s); + } + String xx = s.substring(backSlashIdx + 2, backSlashIdx + 10); + + try { + c = (char)Integer.parseInt(xx, 16); + sb.append( c ); + + startIdx = backSlashIdx + 10; + } + catch (NumberFormatException e) { + throw new IllegalArgumentException( + "Illegal Unicode escape sequence '\\U" + xx + "' in: " + s); + } + } + else { + throw new IllegalArgumentException("Unescaped backslash in: " + s); + } + + backSlashIdx = s.indexOf('\\', startIdx); + } + + sb.append(s.substring(startIdx)); + + return sb.toString(); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/StringEscapesProcessor.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/StringEscapesProcessor.java new file mode 100644 index 00000000000..e10d34f0ecb --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/StringEscapesProcessor.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql; + +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTLiteral; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTQueryContainer; +import org.eclipse.rdf4j.query.parser.serql.ast.ASTString; +import org.eclipse.rdf4j.query.parser.serql.ast.VisitorException; + +/** + * Processes escape sequences in strings, replacing the escape sequence with + * their actual value. Escape sequences for SPARQL are documented in section A.7 Escape + * sequences in strings. + * + * @author Arjohn Kampman + */ +class StringEscapesProcessor { + + /** + * Processes escape sequences in ASTString objects. + * + * @param qc + * The query that needs to be processed. + * @throws MalformedQueryException + * If an invalid escape sequence was found. + */ + public static void process(ASTQueryContainer qc) + throws MalformedQueryException + { + StringProcessor visitor = new StringProcessor(); + try { + qc.jjtAccept(visitor, null); + } + catch (VisitorException e) { + throw new MalformedQueryException(e.getMessage(), e); + } + } + + private static class StringProcessor extends AbstractASTVisitor { + + public StringProcessor() { + } + + @Override + public Object visit(ASTString stringNode, Object data) + throws VisitorException + { + String value = stringNode.getValue(); + try { + value = SeRQLUtil.decodeString(value); + stringNode.setValue(value); + } + catch (IllegalArgumentException e) { + // Invalid escape sequence + throw new VisitorException(e.getMessage()); + } + + return super.visit(stringNode, data); + } + + @Override + public Object visit(ASTLiteral literalNode, Object data) + throws VisitorException + { + String label = literalNode.getLabel(); + try { + label = SeRQLUtil.decodeString(label); + literalNode.setLabel(label); + } + catch (IllegalArgumentException e) { + // Invalid escape sequence + throw new VisitorException(e.getMessage()); + } + + return super.visit(literalNode, data); + } + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTAnd.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTAnd.java new file mode 100644 index 00000000000..26ef06f3538 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTAnd.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.List; + +public class ASTAnd extends ASTBooleanExpr { + + public ASTAnd(int id) { + super(id); + } + + public ASTAnd(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public List getOperandList() { + return new CastingList(children); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTArgList.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTArgList.java new file mode 100644 index 00000000000..b7dd076b360 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTArgList.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.List; + +public class ASTArgList extends SimpleNode { + + public ASTArgList(int id) { + super(id); + } + + public ASTArgList(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public List getElements() { + return new CastingList(children); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBNode.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBNode.java new file mode 100644 index 00000000000..a76aea12ccc --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBNode.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTBNode extends ASTValue { + + private String id; + + public ASTBNode(int id) { + super(id); + } + + public ASTBNode(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public String getID() { + return id; + } + + public void setID(String id) { + this.id = id; + } + + @Override + public String toString() { + return super.toString() + " (_:" + id + ")"; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBasicPathExpr.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBasicPathExpr.java new file mode 100644 index 00000000000..6d85804bd10 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBasicPathExpr.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTBasicPathExpr extends ASTPathExpr { + + public ASTBasicPathExpr(int id) { + super(id); + } + + public ASTBasicPathExpr(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTNode getHead() { + return (ASTNode)children.get(0); + } + + public ASTBasicPathExprTail getTail() { + return (ASTBasicPathExprTail)children.get(1); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBasicPathExprTail.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBasicPathExprTail.java new file mode 100644 index 00000000000..705d8f3997b --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBasicPathExprTail.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTBasicPathExprTail extends ASTPathExprTail { + + public ASTBasicPathExprTail(int id) { + super(id); + } + + public ASTBasicPathExprTail(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTEdge getEdge() { + return (ASTEdge)children.get(0); + } + + public ASTNode getNode() { + return (ASTNode)children.get(1); + } + + @Override + public ASTPathExprTail getNextTail() { + if (children.size() >= 3) { + return (ASTPathExprTail)children.get(2); + } + + return null; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBooleanConstant.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBooleanConstant.java new file mode 100644 index 00000000000..f509b9766a0 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBooleanConstant.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTBooleanConstant extends ASTBooleanExpr { + + private boolean value; + + public ASTBooleanConstant(int id) { + super(id); + } + + public ASTBooleanConstant(boolean value) { + this(SyntaxTreeBuilderTreeConstants.JJTBOOLEANCONSTANT); + setValue(value); + } + + public ASTBooleanConstant(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public boolean getValue() { + return value; + } + + public void setValue(boolean value) { + this.value = value; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBooleanExpr.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBooleanExpr.java new file mode 100644 index 00000000000..2878064829c --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBooleanExpr.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public abstract class ASTBooleanExpr extends SimpleNode { + + public ASTBooleanExpr(int i) { + super(i); + } + + public ASTBooleanExpr(SyntaxTreeBuilder p, int i) { + super(p, i); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBound.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBound.java new file mode 100644 index 00000000000..ab198c98840 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTBound.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTBound extends ASTBooleanExpr { + + public ASTBound() { + this(SyntaxTreeBuilderTreeConstants.JJTBOUND); + } + + public ASTBound(ASTValueExpr operand) { + this(); + setOperand(operand); + } + + public ASTBound(int id) { + super(id); + } + + public ASTBound(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } + + public void setOperand(ASTValueExpr operand) { + jjtAddChild(operand, 0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompOperator.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompOperator.java new file mode 100644 index 00000000000..efeb53c7624 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompOperator.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; + +public class ASTCompOperator extends SimpleNode { + + private CompareOp value; + + public ASTCompOperator(int id) { + super(id); + } + + public ASTCompOperator(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public CompareOp getValue() { + return value; + } + + public void setValue(CompareOp operator) { + this.value = operator; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompare.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompare.java new file mode 100644 index 00000000000..010cbf6e8b3 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompare.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTCompare extends ASTBooleanExpr { + + public ASTCompare(int id) { + super(id); + } + + public ASTCompare(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getLeftOperand() { + return (ASTValueExpr)children.get(0); + } + + public ASTCompOperator getOperator() { + return (ASTCompOperator)children.get(1); + } + + public ASTValueExpr getRightOperand() { + return (ASTValueExpr)children.get(2); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompareAll.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompareAll.java new file mode 100644 index 00000000000..742c9a385f1 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompareAll.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTCompareAll extends ASTBooleanExpr { + + public ASTCompareAll(int id) { + super(id); + } + + public ASTCompareAll(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getLeftOperand() { + return (ASTValueExpr)children.get(0); + } + + public ASTCompOperator getOperator() { + return (ASTCompOperator)children.get(1); + } + + public ASTTupleQuery getRightOperand() { + return (ASTTupleQuery)children.get(2); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompareAny.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompareAny.java new file mode 100644 index 00000000000..fc4381b5c52 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTCompareAny.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTCompareAny extends ASTBooleanExpr { + + public ASTCompareAny(int id) { + super(id); + } + + public ASTCompareAny(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getLeftOperand() { + return (ASTValueExpr)children.get(0); + } + + public ASTCompOperator getOperator() { + return (ASTCompOperator)children.get(1); + } + + public ASTTupleQuery getRightOperand() { + return (ASTTupleQuery)children.get(2); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTConstruct.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTConstruct.java new file mode 100644 index 00000000000..d3b5f75f3e9 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTConstruct.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + + +public class ASTConstruct extends SimpleNode { + + private boolean distinct = false; + + private boolean reduced = false; + + private boolean wildcard = false; + + public ASTConstruct(int id) { + super(id); + } + + public ASTConstruct(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + public boolean isDistinct() { + return distinct; + } + + public void setReduced(boolean reduced) { + this.reduced = reduced; + } + + public boolean isReduced() { + return reduced; + } + + public boolean isWildcard() { + return wildcard; + } + + public void setWildcard(boolean wildcard) { + this.wildcard = wildcard; + } + + public ASTPathExpr getPathExpr() { + return (ASTPathExpr)children.get(0); + } + + @Override + public String toString() { + String result = super.toString(); + + if (distinct || reduced || wildcard) { + result += " ("; + if (distinct) { + result += " distinct"; + } + if (reduced) { + result += " reduced"; + } + if (wildcard) { + result += " *"; + } + result += " )"; + } + + return result; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTConstructQuery.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTConstructQuery.java new file mode 100644 index 00000000000..f47b4ac1777 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTConstructQuery.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTConstructQuery extends ASTGraphQuery { + + public ASTConstructQuery(int id) { + super(id); + } + + public ASTConstructQuery(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTConstruct getConstructClause() { + return (ASTConstruct)children.get(0); + } + + public boolean hasQueryBody() { + return getQueryBody() != null; + } + + public ASTQueryBody getQueryBody() { + return jjtGetChild(ASTQueryBody.class); + } + + public boolean hasOrderBy() { + return getOrderBy() != null; + } + + public ASTOrderBy getOrderBy() { + return jjtGetChild(ASTOrderBy.class); + } + + public boolean hasLimit() { + return getLimit() != null; + } + + public ASTLimit getLimit() { + return jjtGetChild(ASTLimit.class); + } + + public boolean hasOffset() { + return getOffset() != null; + } + + public ASTOffset getOffset() { + return jjtGetChild(ASTOffset.class); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTDatatype.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTDatatype.java new file mode 100644 index 00000000000..39f903e4508 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTDatatype.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTDatatype extends ASTValueExpr { + + public ASTDatatype(int id) { + super(id); + } + + public ASTDatatype(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTEdge.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTEdge.java new file mode 100644 index 00000000000..80a35ce2b32 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTEdge.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTEdge extends SimpleNode { + + public ASTEdge(int id) { + super(id); + } + + public ASTEdge(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + /** + * Gets the value expression for this edge. + * + * @return An {@link ASTVar}, {@link ASTURI} or {@link ASTQName} object. + */ + public ASTValueExpr getValueExpr() { + return (ASTValueExpr)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTExists.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTExists.java new file mode 100644 index 00000000000..5a43eba512c --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTExists.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTExists extends ASTBooleanExpr { + + public ASTExists(int id) { + super(id); + } + + public ASTExists(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTTupleQuery getOperand() { + return (ASTTupleQuery)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTFrom.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTFrom.java new file mode 100644 index 00000000000..311b34b5f89 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTFrom.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + + +public class ASTFrom extends SimpleNode { + + public ASTFrom(int id) { + super(id); + } + + public ASTFrom(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public boolean hasContextID() { + return getContextID() != null; + } + + public ASTValueExpr getContextID() { + Node firstNode = children.get(0); + + if (firstNode instanceof ASTValueExpr) { + return (ASTValueExpr)firstNode; + } + + return null; + } + + public ASTPathExpr getPathExpr() { + return (ASTPathExpr)children.get(children.size() - 1); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTFunctionCall.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTFunctionCall.java new file mode 100644 index 00000000000..10cd4e745d1 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTFunctionCall.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + + +public class ASTFunctionCall extends ASTValueExpr { + + public ASTFunctionCall(int id) { + super(id); + } + + public ASTFunctionCall(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValue getURI() { + return (ASTValue)children.get(0); + } + + public ASTArgList getArgList() { + return (ASTArgList)children.get(1); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphIntersect.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphIntersect.java new file mode 100644 index 00000000000..99854211439 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphIntersect.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTGraphIntersect extends ASTGraphQuerySet { + + public ASTGraphIntersect(int id) { + super(id); + } + + public ASTGraphIntersect(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphMinus.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphMinus.java new file mode 100644 index 00000000000..b272fae576e --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphMinus.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTGraphMinus extends ASTGraphQuerySet { + + public ASTGraphMinus(int id) { + super(id); + } + + public ASTGraphMinus(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphQuery.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphQuery.java new file mode 100644 index 00000000000..588cccb34e3 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphQuery.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public abstract class ASTGraphQuery extends ASTQuery { + + public ASTGraphQuery(int i) { + super(i); + } + + public ASTGraphQuery(SyntaxTreeBuilder p, int i) { + super(p, i); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphQuerySet.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphQuerySet.java new file mode 100644 index 00000000000..f61264af403 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphQuerySet.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public abstract class ASTGraphQuerySet extends ASTGraphQuery { + + public ASTGraphQuerySet(int i) { + super(i); + } + + public ASTGraphQuerySet(SyntaxTreeBuilder p, int i) { + super(p, i); + } + + public ASTGraphQuery getLeftArg() { + return (ASTGraphQuery)children.get(0); + } + + public ASTGraphQuery getRightArg() { + return (ASTGraphQuery)children.get(1); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphUnion.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphUnion.java new file mode 100644 index 00000000000..1edde207896 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTGraphUnion.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTGraphUnion extends ASTGraphQuerySet { + + private boolean distinct = true; + + public ASTGraphUnion(int id) { + super(id); + } + + public ASTGraphUnion(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public boolean isDistinct() { + return distinct; + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + @Override + public String toString() + { + String result = super.toString(); + + if (distinct) { + result += " (distinct)"; + } + + return result; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIn.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIn.java new file mode 100644 index 00000000000..594783f08b5 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIn.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTIn extends ASTBooleanExpr { + + public ASTIn(int id) { + super(id); + } + + public ASTIn(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getLeftOperand() { + return (ASTValueExpr)children.get(0); + } + + public ASTTupleQuery getRightOperand() { + return (ASTTupleQuery)children.get(1); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTInList.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTInList.java new file mode 100644 index 00000000000..c27d03ec060 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTInList.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTInList extends ASTBooleanExpr { + + public ASTInList(int id) { + super(id); + } + + public ASTInList(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getValueExpr() { + return (ASTValueExpr)children.get(0); + } + + public ASTArgList getArgList() { + return (ASTArgList)children.get(1); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsBNode.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsBNode.java new file mode 100644 index 00000000000..716c8111be9 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsBNode.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTIsBNode extends ASTBooleanExpr { + + public ASTIsBNode(int id) { + super(id); + } + + public ASTIsBNode(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsLiteral.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsLiteral.java new file mode 100644 index 00000000000..48ea3748921 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsLiteral.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTIsLiteral extends ASTBooleanExpr { + + public ASTIsLiteral(int id) { + super(id); + } + + public ASTIsLiteral(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsResource.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsResource.java new file mode 100644 index 00000000000..6ed3440cb21 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsResource.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTIsResource extends ASTBooleanExpr { + + public ASTIsResource(int id) { + super(id); + } + + public ASTIsResource(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsURI.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsURI.java new file mode 100644 index 00000000000..bd59858711e --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTIsURI.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTIsURI extends ASTBooleanExpr { + + public ASTIsURI(int id) { + super(id); + } + + public ASTIsURI(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLabel.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLabel.java new file mode 100644 index 00000000000..55981034a2f --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLabel.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTLabel extends ASTValueExpr { + + public ASTLabel(int id) { + super(id); + } + + public ASTLabel(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLang.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLang.java new file mode 100644 index 00000000000..837ef68e6e6 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLang.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTLang extends ASTValueExpr { + + public ASTLang(int id) { + super(id); + } + + public ASTLang(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLangMatches.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLangMatches.java new file mode 100644 index 00000000000..922ed905d8b --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLangMatches.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTLangMatches extends ASTBooleanExpr { + + public ASTLangMatches(int id) { + super(id); + } + + public ASTLangMatches(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getLanguageTag() { + return (ASTValueExpr)children.get(0); + } + + public ASTValueExpr getLanguageRange() { + return (ASTValueExpr)children.get(1); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLike.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLike.java new file mode 100644 index 00000000000..388933d037d --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLike.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTLike extends ASTBooleanExpr { + + private boolean ignoreCase = false; + + public ASTLike(int id) { + super(id); + } + + public ASTLike(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public boolean ignoreCase() { + return ignoreCase; + } + + public void setIgnoreCase(boolean ignoreCase) { + this.ignoreCase = ignoreCase; + } + + public ASTValueExpr getValueExpr() { + return (ASTValueExpr)children.get(0); + } + + public ASTString getPattern() { + return (ASTString)children.get(1); + } + + @Override + public String toString() + { + String result = super.toString(); + + if (ignoreCase) { + result += " (ignore case)"; + } + + return result; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLimit.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLimit.java new file mode 100644 index 00000000000..465c69db5cb --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLimit.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTLimit extends SimpleNode { + + private int value; + + public ASTLimit(int id) { + super(id); + } + + public ASTLimit(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + @Override + public String toString() + { + return super.toString() + " (" + value + ")"; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLiteral.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLiteral.java new file mode 100644 index 00000000000..b0e87d903bc --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLiteral.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTLiteral extends ASTValue { + + private String label; + + private String lang; + + public ASTLiteral(int id) { + super(id); + } + + public ASTLiteral(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getLang() { + return lang; + } + + public boolean hasLang() { + return lang != null; + } + + public void setLang(String lang) { + this.lang = lang; + } + + public ASTValueExpr getDatatypeNode() { + if (children.size() >= 1) { + return (ASTValueExpr)children.get(0); + } + + return null; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + + sb.append(super.toString()); + + sb.append(" (\"").append(label).append("\""); + + if (lang != null) { + sb.append('@').append(lang); + } + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLocalName.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLocalName.java new file mode 100644 index 00000000000..ce48a8bddd2 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTLocalName.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTLocalName extends ASTValueExpr { + + public ASTLocalName(int id) { + super(id); + } + + public ASTLocalName(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNamespace.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNamespace.java new file mode 100644 index 00000000000..285a4647ed5 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNamespace.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTNamespace extends ASTValueExpr { + + public ASTNamespace(int id) { + super(id); + } + + public ASTNamespace(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getOperand() { + return (ASTVar)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNamespaceDecl.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNamespaceDecl.java new file mode 100644 index 00000000000..a5dae4021d3 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNamespaceDecl.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTNamespaceDecl extends SimpleNode { + + private String prefix; + + public ASTNamespaceDecl(int id) { + super(id); + } + + public ASTNamespaceDecl(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public ASTURI getURI() { + return (ASTURI)jjtGetChild(0); + } + + @Override + public String toString() + { + return super.toString() + " (\"" + prefix + "\")"; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNode.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNode.java new file mode 100644 index 00000000000..6fa125dd9ff --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNode.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.List; + +public class ASTNode extends SimpleNode { + + public ASTNode(int id) { + super(id); + } + + public ASTNode(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public List getNodeElemList() { + return new CastingList(children); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNodeElem.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNodeElem.java new file mode 100644 index 00000000000..26eadf6bb6b --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNodeElem.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTNodeElem extends SimpleNode { + + public ASTNodeElem(int id) { + super(id); + } + + public ASTNodeElem(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + /** + * Gets the node element's child node. + * + * @return A variable, value or reified statement. + */ + public Node getChild() { + return children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNot.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNot.java new file mode 100644 index 00000000000..70befd26dda --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNot.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTNot extends ASTBooleanExpr { + + public ASTNot() { + this(SyntaxTreeBuilderTreeConstants.JJTNOT); + } + + public ASTNot(ASTBooleanExpr operand) { + this(); + setOperand(operand); + } + + public ASTNot(int id) { + super(id); + } + + public ASTNot(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTBooleanExpr getOperand() { + return (ASTBooleanExpr)children.get(0); + } + + public void setOperand(ASTBooleanExpr operand) { + jjtAddChild(operand, 0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNull.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNull.java new file mode 100644 index 00000000000..1c941fc7795 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTNull.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTNull extends ASTValueExpr { + + public ASTNull(int id) { + super(id); + } + + public ASTNull(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOffset.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOffset.java new file mode 100644 index 00000000000..5ca9981086c --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOffset.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTOffset extends SimpleNode { + + private int value; + + public ASTOffset(int id) { + super(id); + } + + public ASTOffset(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + @Override + public String toString() { + return super.toString() + " (" + value + ")"; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOptPathExpr.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOptPathExpr.java new file mode 100644 index 00000000000..17d8c92729d --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOptPathExpr.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + + +public class ASTOptPathExpr extends ASTPathExpr { + + public ASTOptPathExpr(int id) { + super(id); + } + + public ASTOptPathExpr(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTPathExpr getPathExpr() { + return (ASTPathExpr)children.get(0); + } + + /** + * Checks if this optional path expression has a constraint. + */ + public boolean hasConstraint() { + return getWhereClause() != null; + } + + /** + * Returns the where clause on the optional path expression, if present. + * + * @return The where clause, or null if no where clause was + * specified. + */ + public ASTWhere getWhereClause() { + Node lastChildNode = children.get(children.size() - 1); + + if (lastChildNode instanceof ASTWhere) { + return (ASTWhere)lastChildNode; + } + + return null; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOptPathExprTail.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOptPathExprTail.java new file mode 100644 index 00000000000..70aaced3390 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOptPathExprTail.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTOptPathExprTail extends ASTPathExprTail { + + public ASTOptPathExprTail(int id) { + super(id); + } + + public ASTOptPathExprTail(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + /** + * Gets the optional tail part of the path expression. + * + * @return The optional tail part of the path expression. + */ + public ASTBasicPathExprTail getOptionalTail() { + return (ASTBasicPathExprTail)children.get(0); + } + + public boolean hasWhereClause() { + return getWhereClause() != null; + } + + /** + * Gets the where-clause that constrains the results of the optional path + * expression tail, if any. + * + * @return The where-clause, or null if not available. + */ + public ASTWhere getWhereClause() { + if (children.size() >= 2) { + Node node = children.get(1); + + if (node instanceof ASTWhere) { + return (ASTWhere)node; + } + } + + return null; + } + + @Override + public ASTPathExprTail getNextTail() { + if (children.size() >= 2) { + Node node = children.get(children.size() - 1); + + if (node instanceof ASTPathExprTail) { + return (ASTPathExprTail)node; + } + } + + return null; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOr.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOr.java new file mode 100644 index 00000000000..c176836e419 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOr.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.List; + +public class ASTOr extends ASTBooleanExpr { + + public ASTOr(int id) { + super(id); + } + + public ASTOr(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public List getOperandList() { + return new CastingList(children); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOrderBy.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOrderBy.java new file mode 100644 index 00000000000..f3c5ce9aed5 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOrderBy.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.List; + +public class ASTOrderBy extends SimpleNode { + + public ASTOrderBy(int id) { + super(id); + } + + public ASTOrderBy(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public List getOrderExprList() { + return new CastingList(children); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOrderExpr.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOrderExpr.java new file mode 100644 index 00000000000..5370cf2cce1 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTOrderExpr.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTOrderExpr extends SimpleNode { + + private boolean ascending = true; + + public ASTOrderExpr(int id) { + super(id); + } + + public ASTOrderExpr(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getValueExpr() { + return (ASTValueExpr)children.get(0); + } + + public boolean isAscending() { + return ascending; + } + + public void setAscending(boolean ascending) { + this.ascending = ascending; + } + + @Override + public String toString() { + String result = super.toString(); + + if (!ascending) { + result += " (DESC)"; + } + + return result; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExpr.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExpr.java new file mode 100644 index 00000000000..d0460d40649 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExpr.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public abstract class ASTPathExpr extends SimpleNode { + + public ASTPathExpr(int id) { + super(id); + } + + public ASTPathExpr(SyntaxTreeBuilder p, int id) { + super(p, id); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprList.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprList.java new file mode 100644 index 00000000000..c74ab038adc --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprList.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.List; + +public class ASTPathExprList extends ASTPathExpr { + + public ASTPathExprList(int id) { + super(id); + } + + public ASTPathExprList(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public List getPathExprList() { + return new CastingList(children); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprTail.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprTail.java new file mode 100644 index 00000000000..cde5e47127e --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprTail.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public abstract class ASTPathExprTail extends SimpleNode { + + private boolean isBranch = false; + + public ASTPathExprTail(int id) { + super(id); + } + + public ASTPathExprTail(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + public boolean isBranch() { + return isBranch; + } + + public void setBranch(boolean isBranch) { + this.isBranch = isBranch; + } + + public boolean hasNextTail() { + return getNextTail() != null; + } + + /** + * Gets the path epxression tail following this part of the path expression, + * if any. + * + * @return The next part of the path expression, or null if this + * is the last part of the path expression. + */ + public abstract ASTPathExprTail getNextTail(); + + @Override + public String toString() { + String result = super.toString(); + + if (isBranch) { + result += " (branch)"; + } + + return result; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprUnion.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprUnion.java new file mode 100644 index 00000000000..119c2fa29a0 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTPathExprUnion.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.List; + +public class ASTPathExprUnion extends ASTPathExpr { + + public ASTPathExprUnion(int id) { + super(id); + } + + public ASTPathExprUnion(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public List getPathExprList() { + return new CastingList(children); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTProjectionElem.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTProjectionElem.java new file mode 100644 index 00000000000..798230c6f5b --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTProjectionElem.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTProjectionElem extends SimpleNode { + + public ASTProjectionElem(int id) { + super(id); + } + + public ASTProjectionElem(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getValueExpr() { + return (ASTValueExpr)children.get(0); + } + + public boolean hasAlias() { + return getAlias() != null; + } + + public String getAlias() { + if (children.size() >= 2) { + Node aliasNode = children.get(1); + + if (aliasNode instanceof ASTString) { + return ((ASTString)aliasNode).getValue(); + } + else if (aliasNode instanceof ASTVar) { + return ((ASTVar)aliasNode).getName(); + } + } + + return null; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQName.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQName.java new file mode 100644 index 00000000000..2cb8352bba2 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQName.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTQName extends ASTValue { + + private String value; + + public ASTQName(int id) { + super(id); + } + + public ASTQName(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + public ASTQName(int id, String value) { + this(id); + setValue(value); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() + { + return super.toString() + " (" + value + ")"; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQuery.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQuery.java new file mode 100644 index 00000000000..dae570dbc5b --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQuery.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public abstract class ASTQuery extends SimpleNode { + + public ASTQuery(int id) { + super(id); + } + + public ASTQuery(SyntaxTreeBuilder p, int id) { + super(p, id); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQueryBody.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQueryBody.java new file mode 100644 index 00000000000..ccc4ca8f362 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQueryBody.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.ArrayList; +import java.util.List; + +public class ASTQueryBody extends SimpleNode { + + public ASTQueryBody(int id) { + super(id); + } + + public ASTQueryBody(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public List getFromClauseList() { + List fromClauseList = new ArrayList(children.size()); + + for (Node n : children) { + if (n instanceof ASTFrom) { + fromClauseList.add((ASTFrom)n); + } + else { + break; + } + } + + return fromClauseList; + } + + public boolean hasWhereClause() { + return getWhereClause() != null; + } + + public ASTWhere getWhereClause() { + for (Node n : children) { + if (n instanceof ASTWhere) { + return (ASTWhere)n; + } + } + + return null; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQueryContainer.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQueryContainer.java new file mode 100644 index 00000000000..7480e0d4db0 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTQueryContainer.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.List; + +public class ASTQueryContainer extends SimpleNode { + + public ASTQueryContainer(int id) { + super(id); + } + + public ASTQueryContainer(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTQuery getQuery() { + return (ASTQuery)children.get(0); + } + + public boolean hasNamespaceDeclList() { + return children.size() >= 2; + } + + public List getNamespaceDeclList() { + return super.jjtGetChildren(ASTNamespaceDecl.class); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTRegex.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTRegex.java new file mode 100644 index 00000000000..523797df61a --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTRegex.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTRegex extends ASTBooleanExpr { + + public ASTRegex(int id) { + super(id); + } + + public ASTRegex(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getText() { + return (ASTValueExpr)children.get(0); + } + + public ASTValueExpr getPattern() { + return (ASTValueExpr)children.get(1); + } + + public boolean hasFlags() { + return getFlags() != null; + } + + public ASTValueExpr getFlags() { + if (children.size() >= 3) { + return (ASTValueExpr)children.get(2); + } + + return null; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTReifiedStat.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTReifiedStat.java new file mode 100644 index 00000000000..b2e2109297c --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTReifiedStat.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTReifiedStat extends SimpleNode { + + private ASTVar id; + + public ASTReifiedStat(int id) { + super(id); + } + + public ASTReifiedStat(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTVar getID() { + return id; + } + + public void setID(ASTVar id) { + this.id = id; + } + + public ASTNodeElem getSubject() { + return (ASTNodeElem)children.get(0); + } + + public ASTEdge getPredicate() { + return (ASTEdge)children.get(1); + } + + public ASTNodeElem getObject() { + return (ASTNodeElem)children.get(2); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSameTerm.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSameTerm.java new file mode 100644 index 00000000000..c76732377f8 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSameTerm.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTSameTerm extends ASTBooleanExpr { + + public ASTSameTerm(int id) { + super(id); + } + + public ASTSameTerm(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getLeftOperand() { + return (ASTValueExpr)children.get(0); + } + + public ASTValueExpr getRightOperand() { + return (ASTValueExpr)children.get(1); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSelect.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSelect.java new file mode 100644 index 00000000000..6032bdbd22a --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSelect.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.List; + +public class ASTSelect extends SimpleNode { + + private boolean distinct = false; + + private boolean reduced = false; + + private boolean wildcard = false; + + public ASTSelect(int id) { + super(id); + } + + public ASTSelect(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + public boolean isDistinct() { + return distinct; + } + + public void setReduced(boolean reduced) { + this.reduced = reduced; + } + + public boolean isReduced() { + return reduced; + } + + public boolean isWildcard() { + return wildcard; + } + + public void setWildcard(boolean wildcard) { + this.wildcard = wildcard; + } + + public List getProjectionElemList() { + return new CastingList(children); + } + + @Override + public String toString() + { + String result = super.toString(); + + if (distinct || reduced || wildcard) { + result += " ("; + if (distinct) { + result += " distinct"; + } + if (reduced) { + result += " reduced"; + } + if (wildcard) { + result += " *"; + } + result += " )"; + } + + return result; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSelectQuery.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSelectQuery.java new file mode 100644 index 00000000000..0ea747a5530 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTSelectQuery.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTSelectQuery extends ASTTupleQuery { + + public ASTSelectQuery(int id) { + super(id); + } + + public ASTSelectQuery(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTSelect getSelectClause() { + return (ASTSelect)children.get(0); + } + + public boolean hasQueryBody() { + return children.size() >= 2; + } + + public ASTQueryBody getQueryBody() { + if (hasQueryBody()) { + return (ASTQueryBody)children.get(1); + } + + return null; + } + + public boolean hasOrderBy() { + return getOrderBy() != null; + } + + public ASTOrderBy getOrderBy() { + return jjtGetChild(ASTOrderBy.class); + } + + public boolean hasLimit() { + return getLimit() != null; + } + + public ASTLimit getLimit() { + return jjtGetChild(ASTLimit.class); + } + + public boolean hasOffset() { + return getOffset() != null; + } + + public ASTOffset getOffset() { + return jjtGetChild(ASTOffset.class); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTStr.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTStr.java new file mode 100644 index 00000000000..03e10d80fe9 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTStr.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTStr extends ASTValueExpr { + + public ASTStr(int id) { + super(id); + } + + public ASTStr(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTValueExpr getOperand() { + return (ASTValueExpr)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTString.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTString.java new file mode 100644 index 00000000000..0a93f1f06a9 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTString.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTString extends SimpleNode { + + private String value; + + public ASTString(int id) { + super(id); + } + + public ASTString(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() + { + return super.toString() + " (\"" + value + "\")"; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleIntersect.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleIntersect.java new file mode 100644 index 00000000000..7db9a740601 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleIntersect.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTTupleIntersect extends ASTTupleQuerySet { + + public ASTTupleIntersect(int id) { + super(id); + } + + public ASTTupleIntersect(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleMinus.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleMinus.java new file mode 100644 index 00000000000..227229598c6 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleMinus.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTTupleMinus extends ASTTupleQuerySet { + + public ASTTupleMinus(int id) { + super(id); + } + + public ASTTupleMinus(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleQuery.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleQuery.java new file mode 100644 index 00000000000..b77a2f42353 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleQuery.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public abstract class ASTTupleQuery extends ASTQuery { + + public ASTTupleQuery(int i) { + super(i); + } + + public ASTTupleQuery(SyntaxTreeBuilder p, int i) { + super(p, i); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleQuerySet.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleQuerySet.java new file mode 100644 index 00000000000..1681bb7c415 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleQuerySet.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public abstract class ASTTupleQuerySet extends ASTTupleQuery { + + public ASTTupleQuerySet(int i) { + super(i); + } + + public ASTTupleQuerySet(SyntaxTreeBuilder p, int i) { + super(p, i); + } + + public ASTTupleQuery getLeftArg() { + return (ASTTupleQuery)children.get(0); + } + + public ASTTupleQuery getRightArg() { + return (ASTTupleQuery)children.get(1); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleUnion.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleUnion.java new file mode 100644 index 00000000000..4088100dabd --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTTupleUnion.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTTupleUnion extends ASTTupleQuerySet { + + private boolean distinct = true; + + public ASTTupleUnion(int id) { + super(id); + } + + public ASTTupleUnion(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public boolean isDistinct() { + return distinct; + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + @Override + public String toString() + { + String result = super.toString(); + + if (distinct) { + result += " (distinct)"; + } + + return result; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTURI.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTURI.java new file mode 100644 index 00000000000..9d2d7f6625d --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTURI.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTURI extends ASTValue { + + private String value; + + public ASTURI(int id) { + super(id); + } + + public ASTURI(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + public ASTURI(int id, String uri) { + this(id); + setValue(uri); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() + { + return super.toString() + " (" + value + ")"; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTValue.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTValue.java new file mode 100644 index 00000000000..39aeee9284d --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTValue.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +/** + * Abstract super type of all basic values (URIs, QNames, BNodes and Literals). + */ +public abstract class ASTValue extends ASTValueExpr { + + public ASTValue(int i) { + super(i); + } + + public ASTValue(SyntaxTreeBuilder p, int i) { + super(p, i); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTValueExpr.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTValueExpr.java new file mode 100644 index 00000000000..574b43ea20a --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTValueExpr.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + + +public abstract class ASTValueExpr extends SimpleNode { + + public ASTValueExpr(int i) { + super(i); + } + + public ASTValueExpr(SyntaxTreeBuilder p, int i) { + super(p, i); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTVar.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTVar.java new file mode 100644 index 00000000000..9abc2cdef1b --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTVar.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTVar extends ASTValueExpr { + + private String name; + + private boolean anonymous = false; + + public ASTVar(int id) { + super(id); + } + + public ASTVar(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isAnonymous() { + return anonymous; + } + + public void setAnonymous(boolean anonymous) { + this.anonymous = anonymous; + } + + @Override + public String toString() + { + String result = super.toString() + " (" + name + ")"; + + if (anonymous) { + result += " (anonymous)"; + } + + return result; + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTWhere.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTWhere.java new file mode 100644 index 00000000000..9502114399b --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ASTWhere.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class ASTWhere extends SimpleNode { + + public ASTWhere(int id) { + super(id); + } + + public ASTWhere(SyntaxTreeBuilder p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + public ASTBooleanExpr getCondition() { + return (ASTBooleanExpr)children.get(0); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/CastingList.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/CastingList.java new file mode 100644 index 00000000000..0ccd9e63394 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/CastingList.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.util.AbstractList; +import java.util.List; + +/** + * A list that wraps another list and casts its elements to a specific subtype + * of the list's element type. + */ +class CastingList extends AbstractList { + + protected List _elements; + + public CastingList(List elements) { + _elements = elements; + } + + @SuppressWarnings("unchecked") + @Override + public E get(int index) { + return (E) _elements.get(index); + } + + @Override + public int size() { + return _elements.size(); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/JJTSyntaxTreeBuilderState.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/JJTSyntaxTreeBuilderState.java new file mode 100644 index 00000000000..3eaad7423d9 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/JJTSyntaxTreeBuilderState.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JavaCC: Do not edit this line. JJTSyntaxTreeBuilderState.java Version 5.0 */ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public class JJTSyntaxTreeBuilderState { + private java.util.List nodes; + private java.util.List marks; + + private int sp; // number of nodes on stack + private int mk; // current mark + private boolean node_created; + + public JJTSyntaxTreeBuilderState() { + nodes = new java.util.ArrayList(); + marks = new java.util.ArrayList(); + sp = 0; + mk = 0; + } + + /* Determines whether the current node was actually closed and + pushed. This should only be called in the final user action of a + node scope. */ + public boolean nodeCreated() { + return node_created; + } + + /* Call this to reinitialize the node stack. It is called + automatically by the parser's ReInit() method. */ + public void reset() { + nodes.clear(); + marks.clear(); + sp = 0; + mk = 0; + } + + /* Returns the root node of the AST. It only makes sense to call + this after a successful parse. */ + public Node rootNode() { + return nodes.get(0); + } + + /* Pushes a node on to the stack. */ + public void pushNode(Node n) { + nodes.add(n); + ++sp; + } + + /* Returns the node on the top of the stack, and remove it from the + stack. */ + public Node popNode() { + if (--sp < mk) { + mk = marks.remove(marks.size()-1); + } + return nodes.remove(nodes.size()-1); + } + + /* Returns the node currently on the top of the stack. */ + public Node peekNode() { + return nodes.get(nodes.size()-1); + } + + /* Returns the number of children on the stack in the current node + scope. */ + public int nodeArity() { + return sp - mk; + } + + + public void clearNodeScope(Node n) { + while (sp > mk) { + popNode(); + } + mk = marks.remove(marks.size()-1); + } + + + public void openNodeScope(Node n) { + marks.add(mk); + mk = sp; + n.jjtOpen(); + } + + + /* A definite node is constructed from a specified number of + children. That number of nodes are popped from the stack and + made the children of the definite node. Then the definite node + is pushed on to the stack. */ + public void closeNodeScope(Node n, int num) { + mk = marks.remove(marks.size()-1); + while (num-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, num); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } + + + /* A conditional node is constructed if its condition is true. All + the nodes that have been pushed since the node was opened are + made children of the conditional node, which is then pushed + on to the stack. If the condition is false the node is not + constructed and they are left on the stack. */ + public void closeNodeScope(Node n, boolean condition) { + if (condition) { + int a = nodeArity(); + mk = marks.remove(marks.size()-1); + while (a-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, a); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } else { + mk = marks.remove(marks.size()-1); + node_created = false; + } + } +} +/* JavaCC - OriginalChecksum=d31fabe00432249498b2d361c77caf11 (do not edit this line) */ diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/Node.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/Node.java new file mode 100644 index 00000000000..cb72216236e --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/Node.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +/* + * All AST nodes must implement this interface. It provides basic machinery for + * constructing the parent and child relationships between nodes. + */ + +public interface Node { + + /** + * This method is called after the node has been made the current node. It + * indicates that child nodes can now be added to it. + */ + public void jjtOpen(); + + /** + * This method is called after all the child nodes have been added. + */ + public void jjtClose(); + + /** + * This pair of methods are used to inform the node of its parent. + */ + public void jjtSetParent(Node n); + + public Node jjtGetParent(); + + /** + * This method tells the node to add its argument to the node's list of + * children. + */ + public void jjtAddChild(Node n, int i); + + /** + * Adds the supplied node as the last child node to this node. + */ + public void jjtAppendChild(Node n); + + /** + * Adds the supplied node as the i'th child node to this node. + */ + public void jjtInsertChild(Node n, int i); + + /** + * Replaces a child node with a new node. + */ + public void jjtReplaceChild(Node oldNode, Node newNode); + + /** + * This method returns a child node. The children are numbered from zero, + * left to right. + */ + public Node jjtGetChild(int i); + + /** Return the number of children the node has. */ + public int jjtGetNumChildren(); + + /** + * Accept the visitor. + */ + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException; +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ParseException.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ParseException.java new file mode 100644 index 00000000000..5ae28991786 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/ParseException.java @@ -0,0 +1,194 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */ +/* JavaCCOptions:KEEP_LINE_COL=null */ +package org.eclipse.rdf4j.query.parser.serql.ast; + +/** + * This exception is thrown when parse errors are encountered. + * You can explicitly create objects of this exception type by + * calling the method generateParseException in the generated + * parser. + * + * You can modify this class to customize your error reporting + * mechanisms so long as you retain the public fields. + */ +public class ParseException extends Exception { + + /** + * The version identifier for this Serializable class. + * Increment only if the serialized form of the + * class changes. + */ + private static final long serialVersionUID = 1L; + + /** + * This constructor is used by the method "generateParseException" + * in the generated parser. Calling this constructor generates + * a new object of this type with the fields "currentToken", + * "expectedTokenSequences", and "tokenImage" set. + */ + public ParseException(Token currentTokenVal, + int[][] expectedTokenSequencesVal, + String[] tokenImageVal + ) + { + super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal)); + currentToken = currentTokenVal; + expectedTokenSequences = expectedTokenSequencesVal; + tokenImage = tokenImageVal; + } + + /** + * The following constructors are for use by you for whatever + * purpose you can think of. Constructing the exception in this + * manner makes the exception behave in the normal way - i.e., as + * documented in the class "Throwable". The fields "errorToken", + * "expectedTokenSequences", and "tokenImage" do not contain + * relevant information. The JavaCC generated code does not use + * these constructors. + */ + + public ParseException() { + super(); + } + + /** Constructor with message. */ + public ParseException(String message) { + super(message); + } + + + /** + * This is the last token that has been consumed successfully. If + * this object has been created due to a parse error, the token + * followng this token will (therefore) be the first error token. + */ + public Token currentToken; + + /** + * Each entry in this array is an array of integers. Each array + * of integers represents a sequence of tokens (by their ordinal + * values) that is expected at this point of the parse. + */ + public int[][] expectedTokenSequences; + + /** + * This is a reference to the "tokenImage" array of the generated + * parser within which the parse error occurred. This array is + * defined in the generated ...Constants interface. + */ + public String[] tokenImage; + + /** + * It uses "currentToken" and "expectedTokenSequences" to generate a parse + * error message and returns it. If this object has been created + * due to a parse error, and you do not catch it (it gets thrown + * from the parser) the correct error message + * gets displayed. + */ + private static String initialise(Token currentToken, + int[][] expectedTokenSequences, + String[] tokenImage) { + String eol = System.getProperty("line.separator", "\n"); + StringBuffer expected = new StringBuffer(); + int maxSize = 0; + for (int i = 0; i < expectedTokenSequences.length; i++) { + if (maxSize < expectedTokenSequences[i].length) { + maxSize = expectedTokenSequences[i].length; + } + for (int j = 0; j < expectedTokenSequences[i].length; j++) { + expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' '); + } + if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { + expected.append("..."); + } + expected.append(eol).append(" "); + } + String retval = "Encountered \""; + Token tok = currentToken.next; + for (int i = 0; i < maxSize; i++) { + if (i != 0) retval += " "; + if (tok.kind == 0) { + retval += tokenImage[0]; + break; + } + retval += " " + tokenImage[tok.kind]; + retval += " \""; + retval += add_escapes(tok.image); + retval += " \""; + tok = tok.next; + } + retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; + retval += "." + eol; + if (expectedTokenSequences.length == 1) { + retval += "Was expecting:" + eol + " "; + } else { + retval += "Was expecting one of:" + eol + " "; + } + retval += expected.toString(); + return retval; + } + + /** + * The end of line string for this machine. + */ + protected String eol = System.getProperty("line.separator", "\n"); + + /** + * Used to convert raw characters to their escaped version + * when these raw version cannot be used as part of an ASCII + * string literal. + */ + static String add_escapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + +} +/* JavaCC - OriginalChecksum=70fc629ff3ab4c4b2e07533e4a096fd4 (do not edit this line) */ diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SimpleCharStream.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SimpleCharStream.java new file mode 100644 index 00000000000..030e01bb47e --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SimpleCharStream.java @@ -0,0 +1,478 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */ +/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ +package org.eclipse.rdf4j.query.parser.serql.ast; + +/** + * An implementation of interface CharStream, where the stream is assumed to + * contain only ASCII characters (without unicode processing). + */ + +public class SimpleCharStream +{ +/** Whether parser is static. */ + public static final boolean staticFlag = false; + int bufsize; + int available; + int tokenBegin; +/** Position in buffer. */ + public int bufpos = -1; + protected int bufline[]; + protected int bufcolumn[]; + + protected int column = 0; + protected int line = 1; + + protected boolean prevCharIsCR = false; + protected boolean prevCharIsLF = false; + + protected java.io.Reader inputStream; + + protected char[] buffer; + protected int maxNextCharInd = 0; + protected int inBuf = 0; + protected int tabSize = 8; + + protected void setTabSize(int i) { tabSize = i; } + protected int getTabSize(int i) { return tabSize; } + + + protected void ExpandBuff(boolean wrapAround) + { + char[] newbuffer = new char[bufsize + 2048]; + int newbufline[] = new int[bufsize + 2048]; + int newbufcolumn[] = new int[bufsize + 2048]; + + try + { + if (wrapAround) + { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos += (bufsize - tokenBegin)); + } + else + { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos -= tokenBegin); + } + } + catch (Throwable t) + { + throw new Error(t.getMessage()); + } + + + bufsize += 2048; + available = bufsize; + tokenBegin = 0; + } + + protected void FillBuff() throws java.io.IOException + { + if (maxNextCharInd == available) + { + if (available == bufsize) + { + if (tokenBegin > 2048) + { + bufpos = maxNextCharInd = 0; + available = tokenBegin; + } + else if (tokenBegin < 0) + bufpos = maxNextCharInd = 0; + else + ExpandBuff(false); + } + else if (available > tokenBegin) + available = bufsize; + else if ((tokenBegin - available) < 2048) + ExpandBuff(true); + else + available = tokenBegin; + } + + int i; + try { + if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1) + { + inputStream.close(); + throw new java.io.IOException(); + } + else + maxNextCharInd += i; + return; + } + catch(java.io.IOException e) { + --bufpos; + backup(0); + if (tokenBegin == -1) + tokenBegin = bufpos; + throw e; + } + } + +/** Start. */ + public char BeginToken() throws java.io.IOException + { + tokenBegin = -1; + char c = readChar(); + tokenBegin = bufpos; + + return c; + } + + protected void UpdateLineColumn(char c) + { + column++; + + if (prevCharIsLF) + { + prevCharIsLF = false; + line += (column = 1); + } + else if (prevCharIsCR) + { + prevCharIsCR = false; + if (c == '\n') + { + prevCharIsLF = true; + } + else + line += (column = 1); + } + + switch (c) + { + case '\r' : + prevCharIsCR = true; + break; + case '\n' : + prevCharIsLF = true; + break; + case '\t' : + column--; + column += (tabSize - (column % tabSize)); + break; + default : + break; + } + + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + +/** Read a character. */ + public char readChar() throws java.io.IOException + { + if (inBuf > 0) + { + --inBuf; + + if (++bufpos == bufsize) + bufpos = 0; + + return buffer[bufpos]; + } + + if (++bufpos >= maxNextCharInd) + FillBuff(); + + char c = buffer[bufpos]; + + UpdateLineColumn(c); + return c; + } + + @Deprecated + /** + * @deprecated + * @see #getEndColumn + */ + + public int getColumn() { + return bufcolumn[bufpos]; + } + + @Deprecated + /** + * @deprecated + * @see #getEndLine + */ + + public int getLine() { + return bufline[bufpos]; + } + + /** Get token end column number. */ + public int getEndColumn() { + return bufcolumn[bufpos]; + } + + /** Get token end line number. */ + public int getEndLine() { + return bufline[bufpos]; + } + + /** Get token beginning column number. */ + public int getBeginColumn() { + return bufcolumn[tokenBegin]; + } + + /** Get token beginning line number. */ + public int getBeginLine() { + return bufline[tokenBegin]; + } + +/** Backup a number of characters. */ + public void backup(int amount) { + + inBuf += amount; + if ((bufpos -= amount) < 0) + bufpos += bufsize; + } + + /** Constructor. */ + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) + { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + + /** Constructor. */ + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn) + { + this(dstream, startline, startcolumn, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.Reader dstream) + { + this(dstream, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) + { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + if (buffer == null || buffersize != buffer.length) + { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + prevCharIsLF = prevCharIsCR = false; + tokenBegin = inBuf = maxNextCharInd = 0; + bufpos = -1; + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn) + { + ReInit(dstream, startline, startcolumn, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream) + { + ReInit(dstream, 1, 1, 4096); + } + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException + { + this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) + { + this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException + { + this(dstream, encoding, startline, startcolumn, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn) + { + this(dstream, startline, startcolumn, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException + { + this(dstream, encoding, 1, 1, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream) + { + this(dstream, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException + { + ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) + { + ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException + { + ReInit(dstream, encoding, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream) + { + ReInit(dstream, 1, 1, 4096); + } + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException + { + ReInit(dstream, encoding, startline, startcolumn, 4096); + } + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn) + { + ReInit(dstream, startline, startcolumn, 4096); + } + /** Get token literal value. */ + public String GetImage() + { + if (bufpos >= tokenBegin) + return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); + else + return new String(buffer, tokenBegin, bufsize - tokenBegin) + + new String(buffer, 0, bufpos + 1); + } + + /** Get the suffix. */ + public char[] GetSuffix(int len) + { + char[] ret = new char[len]; + + if ((bufpos + 1) >= len) + System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); + else + { + System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, + len - bufpos - 1); + System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); + } + + return ret; + } + + /** Reset buffer when finished. */ + public void Done() + { + buffer = null; + bufline = null; + bufcolumn = null; + } + + /** + * Method to adjust line and column numbers for the start of a token. + */ + public void adjustBeginLineColumn(int newLine, int newCol) + { + int start = tokenBegin; + int len; + + if (bufpos >= tokenBegin) + { + len = bufpos - tokenBegin + inBuf + 1; + } + else + { + len = bufsize - tokenBegin + bufpos + 1 + inBuf; + } + + int i = 0, j = 0, k = 0; + int nextColDiff = 0, columnDiff = 0; + + while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) + { + bufline[j] = newLine; + nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; + bufcolumn[j] = newCol + columnDiff; + columnDiff = nextColDiff; + i++; + } + + if (i < len) + { + bufline[j] = newLine++; + bufcolumn[j] = newCol + columnDiff; + + while (i++ < len) + { + if (bufline[j = start % bufsize] != bufline[++start % bufsize]) + bufline[j] = newLine++; + else + bufline[j] = newLine; + } + } + + line = bufline[j]; + column = bufcolumn[j]; + } + +} +/* JavaCC - OriginalChecksum=197ee92a7c7034357af8be938e20720d (do not edit this line) */ diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SimpleNode.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SimpleNode.java new file mode 100644 index 00000000000..f811889d11f --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SimpleNode.java @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +public class SimpleNode implements Node { + + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + protected Node parent; + + protected List children; + + protected int id; + + protected SyntaxTreeBuilder parser; + + public SimpleNode(int id) { + this.id = id; + children = new ArrayList(); + } + + public SimpleNode(SyntaxTreeBuilder parser, int id) { + this(id); + this.parser = parser; + } + + public void jjtOpen() { + } + + public void jjtClose() { + } + + public void jjtSetParent(Node n) { + parent = n; + } + + public Node jjtGetParent() { + return parent; + } + + public void jjtAddChild(Node n, int i) { + while (i >= children.size()) { + // Add dummy nodes + children.add(null); + } + + children.set(i, n); + } + + public void jjtAppendChild(Node n) { + children.add(n); + } + + public void jjtInsertChild(Node n, int i) { + children.add(i, n); + } + + public void jjtReplaceChild(Node oldNode, Node newNode) { + for (int i = 0; i < children.size(); i++) { + if (children.get(i) == oldNode) { + children.set(i, newNode); + } + } + } + + /** + * Replaces this node with the supplied one in the AST. + * + * @param newNode The replacement node. + */ + public void jjtReplaceWith(Node newNode) { + if (parent != null) { + parent.jjtReplaceChild(this, newNode); + } + + for (Node childNode : children) { + childNode.jjtSetParent(newNode); + } + } + + public List jjtGetChildren() { + return children; + } + + public Node jjtGetChild(int i) { + return children.get(i); + } + + /** + * Gets the (first) child of this node that is of the specific type. + * + * @param type The type of the child node that should be returned. + * @return The (first) child node of the specified type, or null + * if no such child node was found. + */ + public T jjtGetChild(Class type) { + for (Node n : children) { + if (type.isInstance(n)) { + return (T)n; + } + } + + return null; + } + + public List jjtGetChildren(Class type) { + List result = new ArrayList(children.size()); + + for (Node n : children) { + if (type.isInstance(n)) { + result.add((T)n); + } + } + + return result; + } + + public int jjtGetNumChildren() { + return children.size(); + } + + /** Accept the visitor. */ + public Object jjtAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + return visitor.visit(this, data); + } + + /** Accept the visitor. */ + public Object childrenAccept(SyntaxTreeBuilderVisitor visitor, Object data) + throws VisitorException + { + for (Node childNode : children) { + // Note: modified JavaCC code, child's data no longer ignored + data = childNode.jjtAccept(visitor, data); + } + + return data; + } + + /* + * You can override these two methods in subclasses of SimpleNode to + * customize the way the node appears when the tree is dumped. If your output + * uses more than one line you should override toString(String), otherwise + * overriding toString() is probably all you need to do. + */ + + @Override + public String toString() + { + return SyntaxTreeBuilderTreeConstants.jjtNodeName[id]; + } + + public String toString(String prefix) { + return prefix + toString(); + } + + /** + * Writes a tree-like representation of this node and all of its subnodes + * (recursively) to the supplied Appendable. + */ + public void dump(String prefix, Appendable out) + throws IOException + { + out.append(prefix).append(this.toString()); + + for (Node childNode : children) { + if (childNode != null) { + out.append(LINE_SEPARATOR); + ((SimpleNode)childNode).dump(prefix + " ", out); + } + } + } + + /** + * Writes a tree-like representation of this node and all of its subnodes + * (recursively) and returns it as a string. + */ + public String dump(String prefix) { + StringWriter out = new StringWriter(256); + try { + dump(prefix, out); + return out.toString(); + } + catch (IOException e) { + throw new RuntimeException("Unexpected I/O error while writing to StringWriter", e); + } + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilder.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilder.java new file mode 100644 index 00000000000..82a779d15d8 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilder.java @@ -0,0 +1,3329 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JJTree&JavaCC: Do not edit this line. SyntaxTreeBuilder.java */ +package org.eclipse.rdf4j.query.parser.serql.ast; + +import java.io.StringReader; + +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; + +public class SyntaxTreeBuilder/*@bgen(jjtree)*/implements SyntaxTreeBuilderTreeConstants, SyntaxTreeBuilderConstants {/*@bgen(jjtree)*/ + protected JJTSyntaxTreeBuilderState jjtree = new JJTSyntaxTreeBuilderState(); + /** + * Parses the supplied SeRQL query and builds a syntax tree from it. + * + * @param query A SeRQL query string. + * @return The root of the syntax tree. + * @throws TokenMgrError If the query was syntactically incorrect. + * @throws ParseException If the query was syntactically incorrect. + */ + public static ASTQueryContainer parseQuery(String query) + throws TokenMgrError, ParseException + { + SyntaxTreeBuilder stb = new SyntaxTreeBuilder( new StringReader(query) ); + return stb.QueryContainer(); + } + + /** + * Trims the first and last character from the supplied string. + */ + private static String _trimString(String s) { + if (s.length() >= 2) { + s = s.substring(1, s.length() - 1); + } + return s; + } + + final public ASTQueryContainer QueryContainer() throws ParseException { + /*@bgen(jjtree) QueryContainer */ + ASTQueryContainer jjtn000 = new ASTQueryContainer(JJTQUERYCONTAINER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + Query(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case USING: + NamespaceDeclList(); + break; + default: + jj_la1[0] = jj_gen; + ; + } + jj_consume_token(0); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + {if (true) return jjtn000;} + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + throw new Error("Missing return statement in function"); + } + + final public void NamespaceDeclList() throws ParseException { + jj_consume_token(USING); + jj_consume_token(NAMESPACE); + NamespaceDecl(); + label_1: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[1] = jj_gen; + break label_1; + } + jj_consume_token(COMMA); + NamespaceDecl(); + } + } + + final public void NamespaceDecl() throws ParseException { + /*@bgen(jjtree) NamespaceDecl */ + ASTNamespaceDecl jjtn000 = new ASTNamespaceDecl(JJTNAMESPACEDECL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token prefix; + try { + prefix = jj_consume_token(PREFIX_NAME); + jj_consume_token(EQ); + URI(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setPrefix(prefix.image); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Query() throws ParseException { + if (jj_2_1(2147483647)) { + TupleQuerySet(); + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LPAREN: + case CONSTRUCT: + GraphQuerySet(); + break; + default: + jj_la1[2] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + } + + final public void TupleQuerySet() throws ParseException { + boolean distinct = true; + TupleQuery(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case UNION: + case MINUS: + case INTERSECT: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case UNION: + jj_consume_token(UNION); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ALL: + jj_consume_token(ALL); + distinct = false; + break; + default: + jj_la1[3] = jj_gen; + ; + } + TupleQuerySet(); + ASTTupleUnion jjtn001 = new ASTTupleUnion(JJTTUPLEUNION); + boolean jjtc001 = true; + jjtree.openNodeScope(jjtn001); + try { + jjtree.closeNodeScope(jjtn001, 2); + jjtc001 = false; + jjtn001.setDistinct(distinct); + } finally { + if (jjtc001) { + jjtree.closeNodeScope(jjtn001, 2); + } + } + break; + case MINUS: + jj_consume_token(MINUS); + ASTTupleMinus jjtn002 = new ASTTupleMinus(JJTTUPLEMINUS); + boolean jjtc002 = true; + jjtree.openNodeScope(jjtn002); + try { + TupleQuerySet(); + } catch (Throwable jjte002) { + if (jjtc002) { + jjtree.clearNodeScope(jjtn002); + jjtc002 = false; + } else { + jjtree.popNode(); + } + if (jjte002 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte002;} + } + if (jjte002 instanceof ParseException) { + {if (true) throw (ParseException)jjte002;} + } + {if (true) throw (Error)jjte002;} + } finally { + if (jjtc002) { + jjtree.closeNodeScope(jjtn002, 2); + } + } + break; + case INTERSECT: + jj_consume_token(INTERSECT); + ASTTupleIntersect jjtn003 = new ASTTupleIntersect(JJTTUPLEINTERSECT); + boolean jjtc003 = true; + jjtree.openNodeScope(jjtn003); + try { + TupleQuerySet(); + } catch (Throwable jjte003) { + if (jjtc003) { + jjtree.clearNodeScope(jjtn003); + jjtc003 = false; + } else { + jjtree.popNode(); + } + if (jjte003 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte003;} + } + if (jjte003 instanceof ParseException) { + {if (true) throw (ParseException)jjte003;} + } + {if (true) throw (Error)jjte003;} + } finally { + if (jjtc003) { + jjtree.closeNodeScope(jjtn003, 2); + } + } + break; + default: + jj_la1[4] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[5] = jj_gen; + ; + } + } + + final public void GraphQuerySet() throws ParseException { + boolean distinct = true; + GraphQuery(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case UNION: + case MINUS: + case INTERSECT: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case UNION: + jj_consume_token(UNION); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ALL: + jj_consume_token(ALL); + distinct = false; + break; + default: + jj_la1[6] = jj_gen; + ; + } + GraphQuerySet(); + ASTGraphUnion jjtn001 = new ASTGraphUnion(JJTGRAPHUNION); + boolean jjtc001 = true; + jjtree.openNodeScope(jjtn001); + try { + jjtree.closeNodeScope(jjtn001, 2); + jjtc001 = false; + jjtn001.setDistinct(distinct); + } finally { + if (jjtc001) { + jjtree.closeNodeScope(jjtn001, 2); + } + } + break; + case MINUS: + jj_consume_token(MINUS); + ASTGraphMinus jjtn002 = new ASTGraphMinus(JJTGRAPHMINUS); + boolean jjtc002 = true; + jjtree.openNodeScope(jjtn002); + try { + GraphQuerySet(); + } catch (Throwable jjte002) { + if (jjtc002) { + jjtree.clearNodeScope(jjtn002); + jjtc002 = false; + } else { + jjtree.popNode(); + } + if (jjte002 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte002;} + } + if (jjte002 instanceof ParseException) { + {if (true) throw (ParseException)jjte002;} + } + {if (true) throw (Error)jjte002;} + } finally { + if (jjtc002) { + jjtree.closeNodeScope(jjtn002, 2); + } + } + break; + case INTERSECT: + jj_consume_token(INTERSECT); + ASTGraphIntersect jjtn003 = new ASTGraphIntersect(JJTGRAPHINTERSECT); + boolean jjtc003 = true; + jjtree.openNodeScope(jjtn003); + try { + GraphQuerySet(); + } catch (Throwable jjte003) { + if (jjtc003) { + jjtree.clearNodeScope(jjtn003); + jjtc003 = false; + } else { + jjtree.popNode(); + } + if (jjte003 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte003;} + } + if (jjte003 instanceof ParseException) { + {if (true) throw (ParseException)jjte003;} + } + {if (true) throw (Error)jjte003;} + } finally { + if (jjtc003) { + jjtree.closeNodeScope(jjtn003, 2); + } + } + break; + default: + jj_la1[7] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[8] = jj_gen; + ; + } + } + + final public void TupleQuery() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LPAREN: + jj_consume_token(LPAREN); + TupleQuerySet(); + jj_consume_token(RPAREN); + break; + case SELECT: + SelectQuery(); + break; + default: + jj_la1[9] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void GraphQuery() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LPAREN: + jj_consume_token(LPAREN); + GraphQuery(); + jj_consume_token(RPAREN); + break; + case CONSTRUCT: + ConstructQuery(); + break; + default: + jj_la1[10] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void SelectQuery() throws ParseException { + /*@bgen(jjtree) SelectQuery */ + ASTSelectQuery jjtn000 = new ASTSelectQuery(JJTSELECTQUERY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + Select(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case FROM: + QueryBody(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ORDER: + OrderBy(); + break; + default: + jj_la1[11] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LIMIT: + Limit(); + break; + default: + jj_la1[12] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case OFFSET: + Offset(); + break; + default: + jj_la1[13] = jj_gen; + ; + } + break; + default: + jj_la1[14] = jj_gen; + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Select() throws ParseException { + /*@bgen(jjtree) Select */ + ASTSelect jjtn000 = new ASTSelect(JJTSELECT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(SELECT); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DISTINCT: + case REDUCED: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DISTINCT: + jj_consume_token(DISTINCT); + jjtn000.setDistinct(true); + break; + case REDUCED: + jj_consume_token(REDUCED); + jjtn000.setReduced(true); + break; + default: + jj_la1[15] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[16] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case STAR: + jj_consume_token(STAR); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setWildcard(true); + break; + default: + jj_la1[19] = jj_gen; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NAMESPACE: + case LABEL: + case LANG: + case DATATYPE: + case LOCALNAME: + case STR: + case NULL: + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case PREFIX_NAME: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + ProjectionElem(); + label_2: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[17] = jj_gen; + break label_2; + } + jj_consume_token(COMMA); + ProjectionElem(); + } + break; + default: + jj_la1[18] = jj_gen; + ; + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void ProjectionElem() throws ParseException { + /*@bgen(jjtree) ProjectionElem */ + ASTProjectionElem jjtn000 = new ASTProjectionElem(JJTPROJECTIONELEM); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + ValueExprOrNull(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case AS: + jj_consume_token(AS); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case STRING: + String(); + break; + case PREFIX_NAME: + Var(); + break; + default: + jj_la1[20] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[21] = jj_gen; + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void ConstructQuery() throws ParseException { + /*@bgen(jjtree) ConstructQuery */ + ASTConstructQuery jjtn000 = new ASTConstructQuery(JJTCONSTRUCTQUERY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + Construct(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case FROM: + QueryBody(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ORDER: + OrderBy(); + break; + default: + jj_la1[22] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LIMIT: + Limit(); + break; + default: + jj_la1[23] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case OFFSET: + Offset(); + break; + default: + jj_la1[24] = jj_gen; + ; + } + break; + default: + jj_la1[25] = jj_gen; + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Construct() throws ParseException { + /*@bgen(jjtree) Construct */ + ASTConstruct jjtn000 = new ASTConstruct(JJTCONSTRUCT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(CONSTRUCT); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DISTINCT: + case REDUCED: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DISTINCT: + jj_consume_token(DISTINCT); + jjtn000.setDistinct(true); + break; + case REDUCED: + jj_consume_token(REDUCED); + jjtn000.setReduced(true); + break; + default: + jj_la1[26] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[27] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case STAR: + jj_consume_token(STAR); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setWildcard(true); + break; + case LBRACE: + case LPAREN: + case LBRACK: + PathExprList(); + break; + default: + jj_la1[28] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void QueryBody() throws ParseException { + /*@bgen(jjtree) QueryBody */ + ASTQueryBody jjtn000 = new ASTQueryBody(JJTQUERYBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + label_3: + while (true) { + From(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case FROM: + ; + break; + default: + jj_la1[29] = jj_gen; + break label_3; + } + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case WHERE: + Where(); + break; + default: + jj_la1[30] = jj_gen; + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void From() throws ParseException { + /*@bgen(jjtree) From */ + ASTFrom jjtn000 = new ASTFrom(JJTFROM); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(FROM); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case CONTEXT: + jj_consume_token(CONTEXT); + ContextID(); + break; + default: + jj_la1[31] = jj_gen; + ; + } + PathExprList(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Where() throws ParseException { + /*@bgen(jjtree) Where */ + ASTWhere jjtn000 = new ASTWhere(JJTWHERE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(WHERE); + BooleanExpr(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void OrderBy() throws ParseException { + /*@bgen(jjtree) OrderBy */ + ASTOrderBy jjtn000 = new ASTOrderBy(JJTORDERBY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);int limit; + try { + jj_consume_token(ORDER); + jj_consume_token(BY); + OrderExprList(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Limit() throws ParseException { + /*@bgen(jjtree) Limit */ + ASTLimit jjtn000 = new ASTLimit(JJTLIMIT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);int limit; + try { + jj_consume_token(LIMIT); + limit = PosInteger(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(limit); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Offset() throws ParseException { + /*@bgen(jjtree) Offset */ + ASTOffset jjtn000 = new ASTOffset(JJTOFFSET); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);int offset; + try { + jj_consume_token(OFFSET); + offset = PosInteger(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(offset); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void ContextID() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PREFIX_NAME: + Var(); + break; + case URI: + case QNAME: + URIRef(); + break; + case BNODE: + BNode(); + break; + default: + jj_la1[32] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void PathExprList() throws ParseException { + ASTPathExprList jjtn001 = new ASTPathExprList(JJTPATHEXPRLIST); + boolean jjtc001 = true; + jjtree.openNodeScope(jjtn001); + try { + UnionPathExpr(); + label_4: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[33] = jj_gen; + break label_4; + } + jj_consume_token(COMMA); + UnionPathExpr(); + } + } catch (Throwable jjte001) { + if (jjtc001) { + jjtree.clearNodeScope(jjtn001); + jjtc001 = false; + } else { + jjtree.popNode(); + } + if (jjte001 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte001;} + } + if (jjte001 instanceof ParseException) { + {if (true) throw (ParseException)jjte001;} + } + {if (true) throw (Error)jjte001;} + } finally { + if (jjtc001) { + jjtree.closeNodeScope(jjtn001, jjtree.nodeArity() > 1); + } + } + } + + final public void UnionPathExpr() throws ParseException { + ASTPathExprUnion jjtn001 = new ASTPathExprUnion(JJTPATHEXPRUNION); + boolean jjtc001 = true; + jjtree.openNodeScope(jjtn001); + try { + PathExpr(); + label_5: + while (true) { + if (jj_2_2(2147483647)) { + ; + } else { + break label_5; + } + jj_consume_token(UNION); + PathExpr(); + } + } catch (Throwable jjte001) { + if (jjtc001) { + jjtree.clearNodeScope(jjtn001); + jjtc001 = false; + } else { + jjtree.popNode(); + } + if (jjte001 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte001;} + } + if (jjte001 instanceof ParseException) { + {if (true) throw (ParseException)jjte001;} + } + {if (true) throw (Error)jjte001;} + } finally { + if (jjtc001) { + jjtree.closeNodeScope(jjtn001, jjtree.nodeArity() > 1); + } + } + } + + final public void PathExpr() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LBRACE: + BasicPathExpr(); + break; + case LBRACK: + OptPathExpr(); + break; + case LPAREN: + jj_consume_token(LPAREN); + PathExprList(); + jj_consume_token(RPAREN); + break; + default: + jj_la1[34] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void BasicPathExpr() throws ParseException { + /*@bgen(jjtree) BasicPathExpr */ + ASTBasicPathExpr jjtn000 = new ASTBasicPathExpr(JJTBASICPATHEXPR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + Node(); + BasicPathExprTail(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void OptPathExpr() throws ParseException { + /*@bgen(jjtree) OptPathExpr */ + ASTOptPathExpr jjtn000 = new ASTOptPathExpr(JJTOPTPATHEXPR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(LBRACK); + PathExprList(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case WHERE: + Where(); + break; + default: + jj_la1[35] = jj_gen; + ; + } + jj_consume_token(RBRACK); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void PathExprCont() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + PathExprBranch(); + break; + case LBRACK: + case URI: + case QNAME: + case PREFIX_NAME: + PathExprTail(); + break; + default: + jj_la1[36] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void PathExprBranch() throws ParseException { + ASTPathExprTail tail; + jj_consume_token(SEMICOLON); + tail = PathExprTail(); + tail.setBranch(true); + } + + final public ASTPathExprTail PathExprTail() throws ParseException { + ASTPathExprTail result; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case URI: + case QNAME: + case PREFIX_NAME: + result = BasicPathExprTail(); + break; + case LBRACK: + result = OptPathExprTail(); + break; + default: + jj_la1[37] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + {if (true) return result;} + throw new Error("Missing return statement in function"); + } + + final public ASTPathExprTail BasicPathExprTail() throws ParseException { + /*@bgen(jjtree) BasicPathExprTail */ + ASTBasicPathExprTail jjtn000 = new ASTBasicPathExprTail(JJTBASICPATHEXPRTAIL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + Edge(); + Node(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + case LBRACK: + case URI: + case QNAME: + case PREFIX_NAME: + PathExprCont(); + break; + default: + jj_la1[38] = jj_gen; + ; + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + {if (true) return jjtn000;} + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + throw new Error("Missing return statement in function"); + } + + final public ASTPathExprTail OptPathExprTail() throws ParseException { + /*@bgen(jjtree) OptPathExprTail */ + ASTOptPathExprTail jjtn000 = new ASTOptPathExprTail(JJTOPTPATHEXPRTAIL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(LBRACK); + BasicPathExprTail(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case WHERE: + Where(); + break; + default: + jj_la1[39] = jj_gen; + ; + } + jj_consume_token(RBRACK); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + PathExprBranch(); + break; + default: + jj_la1[40] = jj_gen; + ; + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + {if (true) return jjtn000;} + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + throw new Error("Missing return statement in function"); + } + + final public void Edge() throws ParseException { + /*@bgen(jjtree) Edge */ + ASTEdge jjtn000 = new ASTEdge(JJTEDGE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PREFIX_NAME: + Var(); + break; + case URI: + case QNAME: + URIRef(); + break; + default: + jj_la1[41] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Node() throws ParseException { + /*@bgen(jjtree) Node */ + ASTNode jjtn000 = new ASTNode(JJTNODE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LBRACE: + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case PREFIX_NAME: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + NodeElem(); + label_6: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[42] = jj_gen; + break label_6; + } + jj_consume_token(COMMA); + NodeElem(); + } + break; + default: + jj_la1[43] = jj_gen; + ; + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void NodeElem() throws ParseException { + /*@bgen(jjtree) NodeElem */ + ASTNodeElem jjtn000 = new ASTNodeElem(JJTNODEELEM); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PREFIX_NAME: + Var(); + break; + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + Value(); + break; + case LBRACE: + ReifiedStat(); + break; + default: + jj_la1[44] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void ReifiedStat() throws ParseException { + /*@bgen(jjtree) ReifiedStat */ + ASTReifiedStat jjtn000 = new ASTReifiedStat(JJTREIFIEDSTAT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LBRACE: + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case PREFIX_NAME: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + NodeElem(); + break; + default: + jj_la1[45] = jj_gen; + ; + } + jj_consume_token(RBRACE); + Edge(); + jj_consume_token(LBRACE); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LBRACE: + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case PREFIX_NAME: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + NodeElem(); + break; + default: + jj_la1[46] = jj_gen; + ; + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void OrderExprList() throws ParseException { + OrderExpr(); + label_7: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[47] = jj_gen; + break label_7; + } + jj_consume_token(COMMA); + OrderExpr(); + } + } + + final public void OrderExpr() throws ParseException { + /*@bgen(jjtree) OrderExpr */ + ASTOrderExpr jjtn000 = new ASTOrderExpr(JJTORDEREXPR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + ValueExpr(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ASC: + case DESC: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ASC: + jj_consume_token(ASC); + break; + case DESC: + jj_consume_token(DESC); + jjtn000.setAscending(false); + break; + default: + jj_la1[48] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[49] = jj_gen; + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void BooleanExpr() throws ParseException { + Or(); + } + + final public void Or() throws ParseException { + ASTOr jjtn001 = new ASTOr(JJTOR); + boolean jjtc001 = true; + jjtree.openNodeScope(jjtn001); + try { + And(); + label_8: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case OR: + ; + break; + default: + jj_la1[50] = jj_gen; + break label_8; + } + jj_consume_token(OR); + And(); + } + } catch (Throwable jjte001) { + if (jjtc001) { + jjtree.clearNodeScope(jjtn001); + jjtc001 = false; + } else { + jjtree.popNode(); + } + if (jjte001 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte001;} + } + if (jjte001 instanceof ParseException) { + {if (true) throw (ParseException)jjte001;} + } + {if (true) throw (Error)jjte001;} + } finally { + if (jjtc001) { + jjtree.closeNodeScope(jjtn001, jjtree.nodeArity() > 1); + } + } + } + + final public void And() throws ParseException { + ASTAnd jjtn001 = new ASTAnd(JJTAND); + boolean jjtc001 = true; + jjtree.openNodeScope(jjtn001); + try { + BooleanElem(); + label_9: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case AND: + ; + break; + default: + jj_la1[51] = jj_gen; + break label_9; + } + jj_consume_token(AND); + BooleanElem(); + } + } catch (Throwable jjte001) { + if (jjtc001) { + jjtree.clearNodeScope(jjtn001); + jjtc001 = false; + } else { + jjtree.popNode(); + } + if (jjte001 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte001;} + } + if (jjte001 instanceof ParseException) { + {if (true) throw (ParseException)jjte001;} + } + {if (true) throw (Error)jjte001;} + } finally { + if (jjtc001) { + jjtree.closeNodeScope(jjtn001, jjtree.nodeArity() > 1); + } + } + } + + final public void BooleanElem() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LPAREN: + jj_consume_token(LPAREN); + BooleanExpr(); + jj_consume_token(RPAREN); + break; + case TRUE: + case FALSE: + BooleanConstant(); + break; + case NOT: + Not(); + break; + case BOUND: + Bound(); + break; + case SAMETERM: + SameTerm(); + break; + case ISRESOURCE: + IsResource(); + break; + case ISLITERAL: + IsLiteral(); + break; + case ISURI: + IsURI(); + break; + case ISBNODE: + IsBNode(); + break; + case LANGMATCHES: + LangMatches(); + break; + case REGEX: + Regex(); + break; + case EXISTS: + Exists(); + break; + case NAMESPACE: + case LABEL: + case LANG: + case DATATYPE: + case LOCALNAME: + case STR: + case NULL: + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case PREFIX_NAME: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + BooleanValueOp(); + break; + default: + jj_la1[52] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void BooleanConstant() throws ParseException { + /*@bgen(jjtree) BooleanConstant */ + ASTBooleanConstant jjtn000 = new ASTBooleanConstant(JJTBOOLEANCONSTANT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case TRUE: + jj_consume_token(TRUE); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(true); + break; + case FALSE: + jj_consume_token(FALSE); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(false); + break; + default: + jj_la1[53] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Not() throws ParseException { + /*@bgen(jjtree) Not */ + ASTNot jjtn000 = new ASTNot(JJTNOT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(NOT); + BooleanElem(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Bound() throws ParseException { + /*@bgen(jjtree) Bound */ + ASTBound jjtn000 = new ASTBound(JJTBOUND); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(BOUND); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void SameTerm() throws ParseException { + /*@bgen(jjtree) SameTerm */ + ASTSameTerm jjtn000 = new ASTSameTerm(JJTSAMETERM); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(SAMETERM); + jj_consume_token(LPAREN); + ValueExpr(); + jj_consume_token(COMMA); + ValueExpr(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void IsResource() throws ParseException { + /*@bgen(jjtree) IsResource */ + ASTIsResource jjtn000 = new ASTIsResource(JJTISRESOURCE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(ISRESOURCE); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void IsLiteral() throws ParseException { + /*@bgen(jjtree) IsLiteral */ + ASTIsLiteral jjtn000 = new ASTIsLiteral(JJTISLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(ISLITERAL); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void IsURI() throws ParseException { + /*@bgen(jjtree) IsURI */ + ASTIsURI jjtn000 = new ASTIsURI(JJTISURI); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(ISURI); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void IsBNode() throws ParseException { + /*@bgen(jjtree) IsBNode */ + ASTIsBNode jjtn000 = new ASTIsBNode(JJTISBNODE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(ISBNODE); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void LangMatches() throws ParseException { + /*@bgen(jjtree) LangMatches */ + ASTLangMatches jjtn000 = new ASTLangMatches(JJTLANGMATCHES); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(LANGMATCHES); + jj_consume_token(LPAREN); + ValueExpr(); + jj_consume_token(COMMA); + ValueExpr(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Regex() throws ParseException { + /*@bgen(jjtree) Regex */ + ASTRegex jjtn000 = new ASTRegex(JJTREGEX); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(REGEX); + jj_consume_token(LPAREN); + ValueExpr(); + jj_consume_token(COMMA); + ValueExpr(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + ValueExpr(); + break; + default: + jj_la1[54] = jj_gen; + ; + } + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Exists() throws ParseException { + /*@bgen(jjtree) Exists */ + ASTExists jjtn000 = new ASTExists(JJTEXISTS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(EXISTS); + jj_consume_token(LPAREN); + TupleQuerySet(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void BooleanValueOp() throws ParseException { + ValueExprOrNull(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case EQ: + case NE: + case LT: + case LE: + case GE: + case GT: + CompOperator(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NAMESPACE: + case LABEL: + case LANG: + case DATATYPE: + case LOCALNAME: + case STR: + case NULL: + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case PREFIX_NAME: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + ASTCompare jjtn001 = new ASTCompare(JJTCOMPARE); + boolean jjtc001 = true; + jjtree.openNodeScope(jjtn001); + try { + ValueExprOrNull(); + } catch (Throwable jjte001) { + if (jjtc001) { + jjtree.clearNodeScope(jjtn001); + jjtc001 = false; + } else { + jjtree.popNode(); + } + if (jjte001 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte001;} + } + if (jjte001 instanceof ParseException) { + {if (true) throw (ParseException)jjte001;} + } + {if (true) throw (Error)jjte001;} + } finally { + if (jjtc001) { + jjtree.closeNodeScope(jjtn001, 3); + } + } + break; + case ANY: + jj_consume_token(ANY); + jj_consume_token(LPAREN); + TupleQuerySet(); + ASTCompareAny jjtn002 = new ASTCompareAny(JJTCOMPAREANY); + boolean jjtc002 = true; + jjtree.openNodeScope(jjtn002); + try { + jj_consume_token(RPAREN); + } finally { + if (jjtc002) { + jjtree.closeNodeScope(jjtn002, 3); + } + } + break; + case ALL: + jj_consume_token(ALL); + jj_consume_token(LPAREN); + TupleQuerySet(); + ASTCompareAll jjtn003 = new ASTCompareAll(JJTCOMPAREALL); + boolean jjtc003 = true; + jjtree.openNodeScope(jjtn003); + try { + jj_consume_token(RPAREN); + } finally { + if (jjtc003) { + jjtree.closeNodeScope(jjtn003, 3); + } + } + break; + default: + jj_la1[55] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + case LIKE: + jj_consume_token(LIKE); + String(); + ASTLike jjtn004 = new ASTLike(JJTLIKE); + boolean jjtc004 = true; + jjtree.openNodeScope(jjtn004); + try { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IGNORE: + jj_consume_token(IGNORE); + jj_consume_token(CASE); + jjtn004.setIgnoreCase(true); + break; + default: + jj_la1[56] = jj_gen; + ; + } + } finally { + if (jjtc004) { + jjtree.closeNodeScope(jjtn004, 2); + } + } + break; + case IN: + jj_consume_token(IN); + jj_consume_token(LPAREN); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LPAREN: + case SELECT: + ASTIn jjtn005 = new ASTIn(JJTIN); + boolean jjtc005 = true; + jjtree.openNodeScope(jjtn005); + try { + TupleQuerySet(); + } catch (Throwable jjte005) { + if (jjtc005) { + jjtree.clearNodeScope(jjtn005); + jjtc005 = false; + } else { + jjtree.popNode(); + } + if (jjte005 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte005;} + } + if (jjte005 instanceof ParseException) { + {if (true) throw (ParseException)jjte005;} + } + {if (true) throw (Error)jjte005;} + } finally { + if (jjtc005) { + jjtree.closeNodeScope(jjtn005, 2); + } + } + break; + case NAMESPACE: + case LABEL: + case LANG: + case DATATYPE: + case LOCALNAME: + case STR: + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case PREFIX_NAME: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + ASTInList jjtn006 = new ASTInList(JJTINLIST); + boolean jjtc006 = true; + jjtree.openNodeScope(jjtn006); + try { + ArgList(); + } catch (Throwable jjte006) { + if (jjtc006) { + jjtree.clearNodeScope(jjtn006); + jjtc006 = false; + } else { + jjtree.popNode(); + } + if (jjte006 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte006;} + } + if (jjte006 instanceof ParseException) { + {if (true) throw (ParseException)jjte006;} + } + {if (true) throw (Error)jjte006;} + } finally { + if (jjtc006) { + jjtree.closeNodeScope(jjtn006, 2); + } + } + break; + default: + jj_la1[57] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(RPAREN); + break; + default: + jj_la1[58] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void CompOperator() throws ParseException { + /*@bgen(jjtree) CompOperator */ + ASTCompOperator jjtn000 = new ASTCompOperator(JJTCOMPOPERATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case EQ: + jj_consume_token(EQ); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(CompareOp.EQ); + break; + case NE: + jj_consume_token(NE); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(CompareOp.NE); + break; + case LT: + jj_consume_token(LT); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(CompareOp.LT); + break; + case LE: + jj_consume_token(LE); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(CompareOp.LE); + break; + case GE: + jj_consume_token(GE); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(CompareOp.GE); + break; + case GT: + jj_consume_token(GT); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(CompareOp.GT); + break; + default: + jj_la1[59] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + +// For backwards compatibility; NULL will be phased out, use BOUND instead + final public void ValueExprOrNull() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NAMESPACE: + case LABEL: + case LANG: + case DATATYPE: + case LOCALNAME: + case STR: + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case PREFIX_NAME: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + ValueExpr(); + break; + case NULL: + Null(); + break; + default: + jj_la1[60] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void ValueExpr() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PREFIX_NAME: + Var(); + break; + case DATATYPE: + Datatype(); + break; + case LANG: + Lang(); + break; + case LABEL: + Label(); + break; + case NAMESPACE: + Namespace(); + break; + case LOCALNAME: + LocalName(); + break; + case STR: + Str(); + break; + default: + jj_la1[61] = jj_gen; + if (jj_2_3(2)) { + FunctionCall(); + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + Value(); + break; + default: + jj_la1[62] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } + + final public void Var() throws ParseException { + /*@bgen(jjtree) Var */ + ASTVar jjtn000 = new ASTVar(JJTVAR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + t = jj_consume_token(PREFIX_NAME); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setName(t.image); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Datatype() throws ParseException { + /*@bgen(jjtree) Datatype */ + ASTDatatype jjtn000 = new ASTDatatype(JJTDATATYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(DATATYPE); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Lang() throws ParseException { + /*@bgen(jjtree) Lang */ + ASTLang jjtn000 = new ASTLang(JJTLANG); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(LANG); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Label() throws ParseException { + /*@bgen(jjtree) Label */ + ASTLabel jjtn000 = new ASTLabel(JJTLABEL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(LABEL); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Namespace() throws ParseException { + /*@bgen(jjtree) Namespace */ + ASTNamespace jjtn000 = new ASTNamespace(JJTNAMESPACE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(NAMESPACE); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void LocalName() throws ParseException { + /*@bgen(jjtree) LocalName */ + ASTLocalName jjtn000 = new ASTLocalName(JJTLOCALNAME); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(LOCALNAME); + jj_consume_token(LPAREN); + Var(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Str() throws ParseException { + /*@bgen(jjtree) Str */ + ASTStr jjtn000 = new ASTStr(JJTSTR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(STR); + jj_consume_token(LPAREN); + ValueExpr(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void FunctionCall() throws ParseException { + /*@bgen(jjtree) FunctionCall */ + ASTFunctionCall jjtn000 = new ASTFunctionCall(JJTFUNCTIONCALL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + URIRef(); + jj_consume_token(LPAREN); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NAMESPACE: + case LABEL: + case LANG: + case DATATYPE: + case LOCALNAME: + case STR: + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case URI: + case QNAME: + case BNODE: + case PREFIX_NAME: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + ArgList(); + break; + default: + jj_la1[63] = jj_gen; + ; + } + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void ArgList() throws ParseException { + /*@bgen(jjtree) ArgList */ + ASTArgList jjtn000 = new ASTArgList(JJTARGLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + ValueExpr(); + label_10: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[64] = jj_gen; + break label_10; + } + jj_consume_token(COMMA); + ValueExpr(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + {if (true) throw (RuntimeException)jjte000;} + } + if (jjte000 instanceof ParseException) { + {if (true) throw (ParseException)jjte000;} + } + {if (true) throw (Error)jjte000;} + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Value() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case URI: + case QNAME: + URIRef(); + break; + case BNODE: + BNode(); + break; + case LANG_LITERAL: + case DATATYPED_LITERAL: + case STRING: + case POS_INTEGER: + case NEG_INTEGER: + case DECIMAL: + Literal(); + break; + default: + jj_la1[65] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void URIRef() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case URI: + URI(); + break; + case QNAME: + QName(); + break; + default: + jj_la1[66] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void URI() throws ParseException { + /*@bgen(jjtree) URI */ + ASTURI jjtn000 = new ASTURI(JJTURI); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + t = jj_consume_token(URI); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(_trimString(t.image)); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void QName() throws ParseException { + /*@bgen(jjtree) QName */ + ASTQName jjtn000 = new ASTQName(JJTQNAME); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + t = jj_consume_token(QNAME); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(t.image); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void BNode() throws ParseException { + /*@bgen(jjtree) BNode */ + ASTBNode jjtn000 = new ASTBNode(JJTBNODE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + t = jj_consume_token(BNODE); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setID(t.image.substring(2)); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Literal() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case STRING: + SimpleLiteral(); + break; + case LANG_LITERAL: + LangLiteral(); + break; + case DATATYPED_LITERAL: + DatatypedLiteral(); + break; + case POS_INTEGER: + case NEG_INTEGER: + IntegerLiteral(); + break; + case DECIMAL: + DecimalLiteral(); + break; + default: + jj_la1[67] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void SimpleLiteral() throws ParseException { + /*@bgen(jjtree) Literal */ + ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + t = jj_consume_token(STRING); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setLabel(_trimString(t.image)); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void LangLiteral() throws ParseException { + /*@bgen(jjtree) Literal */ + ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + t = jj_consume_token(LANG_LITERAL); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + int atIdx = t.image.lastIndexOf('@'); + jjtn000.setLabel(t.image.substring(1, atIdx - 1)); + jjtn000.setLang(t.image.substring(atIdx + 1)); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void DatatypedLiteral() throws ParseException { + /*@bgen(jjtree) Literal */ + ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + t = jj_consume_token(DATATYPED_LITERAL); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + int dtIdx; + if (t.image.endsWith(">")) { + // URI + dtIdx = t.image.lastIndexOf("<") - 2; + String uri = t.image.substring(dtIdx + 3, t.image.length() - 1); + ASTURI uriNode = new ASTURI(JJTURI, uri); + jjtn000.jjtAddChild(uriNode, 0); + uriNode.jjtSetParent(jjtn000); + } + else { + // QNAME + dtIdx = t.image.lastIndexOf("^^"); + String qname = t.image.substring(dtIdx + 2); + ASTQName qnameNode = new ASTQName(JJTQNAME, qname); + jjtn000.jjtAddChild(qnameNode, 0); + qnameNode.jjtSetParent(jjtn000); + } + + jjtn000.setLabel(t.image.substring(1, dtIdx - 1)); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void IntegerLiteral() throws ParseException { + /*@bgen(jjtree) Literal */ + ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case POS_INTEGER: + t = jj_consume_token(POS_INTEGER); + break; + case NEG_INTEGER: + t = jj_consume_token(NEG_INTEGER); + break; + default: + jj_la1[68] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setLabel(t.image); + + ASTURI uriNode = new ASTURI(JJTURI, XMLSchema.INTEGER.toString()); + jjtn000.jjtAddChild(uriNode, 0); + uriNode.jjtSetParent(jjtn000); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void DecimalLiteral() throws ParseException { + /*@bgen(jjtree) Literal */ + ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + t = jj_consume_token(DECIMAL); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setLabel(t.image); + + ASTURI uriNode = new ASTURI(JJTURI, XMLSchema.DECIMAL.toString()); + jjtn000.jjtAddChild(uriNode, 0); + uriNode.jjtSetParent(jjtn000); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void String() throws ParseException { + /*@bgen(jjtree) String */ + ASTString jjtn000 = new ASTString(JJTSTRING); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000);Token t; + try { + t = jj_consume_token(STRING); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtn000.setValue(_trimString(t.image)); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public void Null() throws ParseException { + /*@bgen(jjtree) Null */ + ASTNull jjtn000 = new ASTNull(JJTNULL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + try { + jj_consume_token(NULL); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + } + } + } + + final public int PosInteger() throws ParseException { + Token t; + t = jj_consume_token(POS_INTEGER); + {if (true) return Integer.parseInt(t.image);} + throw new Error("Missing return statement in function"); + } + + private boolean jj_2_1(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_1(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(0, xla); } + } + + private boolean jj_2_2(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_2(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(1, xla); } + } + + private boolean jj_2_3(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_3(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(2, xla); } + } + + private boolean jj_3_1() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(17)) { jj_scanpos = xsp; break; } + } + if (jj_scan_token(SELECT)) return true; + return false; + } + + private boolean jj_3R_14() { + if (jj_3R_16()) return true; + return false; + } + + private boolean jj_3_2() { + if (jj_scan_token(UNION)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(17)) { jj_scanpos = xsp; break; } + } + xsp = jj_scanpos; + if (jj_scan_token(19)) { + jj_scanpos = xsp; + if (jj_scan_token(15)) return true; + } + return false; + } + + private boolean jj_3R_15() { + if (jj_scan_token(URI)) return true; + return false; + } + + private boolean jj_3R_11() { + if (jj_3R_12()) return true; + if (jj_scan_token(LPAREN)) return true; + return false; + } + + private boolean jj_3_3() { + if (jj_3R_11()) return true; + return false; + } + + private boolean jj_3R_12() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_13()) { + jj_scanpos = xsp; + if (jj_3R_14()) return true; + } + return false; + } + + private boolean jj_3R_13() { + if (jj_3R_15()) return true; + return false; + } + + private boolean jj_3R_16() { + if (jj_scan_token(QNAME)) return true; + return false; + } + + /** Generated Token Manager. */ + public SyntaxTreeBuilderTokenManager token_source; + SimpleCharStream jj_input_stream; + /** Current token. */ + public Token token; + /** Next token. */ + public Token jj_nt; + private int jj_ntk; + private Token jj_scanpos, jj_lastpos; + private int jj_la; + private int jj_gen; + final private int[] jj_la1 = new int[69]; + static private int[] jj_la1_0; + static private int[] jj_la1_1; + static private int[] jj_la1_2; + static { + jj_la1_init_0(); + jj_la1_init_1(); + jj_la1_init_2(); + } + private static void jj_la1_init_0() { + jj_la1_0 = new int[] {0x200000,0x2000,0x1020000,0x0,0x0,0x0,0x0,0x0,0x0,0x820000,0x1020000,0x40000000,0x0,0x0,0x8000000,0x6000000,0x6000000,0x2000,0x400000,0x1000,0x0,0x0,0x40000000,0x0,0x0,0x8000000,0x6000000,0x6000000,0xa9000,0x8000000,0x20000000,0x10000000,0x0,0x2000,0xa8000,0x20000000,0x84000,0x80000,0x84000,0x20000000,0x4000,0x0,0x2000,0x8000,0x8000,0x8000,0x8000,0x2000,0x0,0x0,0x0,0x0,0x420000,0x0,0x2000,0x400000,0x0,0xc20000,0xfc0,0xfc0,0x400000,0x400000,0x0,0x400000,0x2000,0x0,0x0,0x0,0x0,}; + } + private static void jj_la1_init_1() { + jj_la1_1 = new int[] {0x0,0x0,0x0,0x80000000,0x38000000,0x38000000,0x80000000,0x38000000,0x38000000,0x0,0x0,0x0,0x4,0x8,0x0,0x0,0x0,0x0,0x2ec000,0x0,0x0,0x4000000,0x0,0x4,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x3,0x100,0x80,0x3ffe270,0x30,0x0,0xc02ec000,0x800,0xec000,0x400,0x0,0x2ec000,0xec000,0x0,0xec000,0x0,0x0,0x0,0x0,0x0,}; + } + private static void jj_la1_init_2() { + jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fa1c,0x0,0x2010,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3a00,0x0,0x0,0x0,0x2a00,0x2a00,0x2a00,0x0,0x0,0x2a00,0x0,0x1fa1c,0x1fa1c,0x1fa1c,0x1fa1c,0x0,0x0,0x0,0x0,0x0,0x1fa1e,0x0,0x0,0x1fa1c,0x0,0x1fa1c,0x1,0x0,0x1fa1c,0x2000,0x1da1c,0x1fa1c,0x0,0x1da1c,0xa00,0x1c01c,0xc000,}; + } + final private JJCalls[] jj_2_rtns = new JJCalls[3]; + private boolean jj_rescan = false; + private int jj_gc = 0; + + /** Constructor with InputStream. */ + public SyntaxTreeBuilder(java.io.InputStream stream) { + this(stream, null); + } + /** Constructor with InputStream and supplied encoding */ + public SyntaxTreeBuilder(java.io.InputStream stream, String encoding) { + try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } + token_source = new SyntaxTreeBuilderTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 69; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream stream) { + ReInit(stream, null); + } + /** Reinitialise. */ + public void ReInit(java.io.InputStream stream, String encoding) { + try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + jj_gen = 0; + for (int i = 0; i < 69; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Constructor. */ + public SyntaxTreeBuilder(java.io.Reader stream) { + jj_input_stream = new SimpleCharStream(stream, 1, 1); + token_source = new SyntaxTreeBuilderTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 69; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader stream) { + jj_input_stream.ReInit(stream, 1, 1); + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + jj_gen = 0; + for (int i = 0; i < 69; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Constructor with generated Token Manager. */ + public SyntaxTreeBuilder(SyntaxTreeBuilderTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 69; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Reinitialise. */ + public void ReInit(SyntaxTreeBuilderTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + jj_gen = 0; + for (int i = 0; i < 69; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + private Token jj_consume_token(int kind) throws ParseException { + Token oldToken; + if ((oldToken = token).next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + if (token.kind == kind) { + jj_gen++; + if (++jj_gc > 100) { + jj_gc = 0; + for (int i = 0; i < jj_2_rtns.length; i++) { + JJCalls c = jj_2_rtns[i]; + while (c != null) { + if (c.gen < jj_gen) c.first = null; + c = c.next; + } + } + } + return token; + } + token = oldToken; + jj_kind = kind; + throw generateParseException(); + } + + static private final class LookaheadSuccess extends java.lang.Error { } + final private LookaheadSuccess jj_ls = new LookaheadSuccess(); + private boolean jj_scan_token(int kind) { + if (jj_scanpos == jj_lastpos) { + jj_la--; + if (jj_scanpos.next == null) { + jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); + } else { + jj_lastpos = jj_scanpos = jj_scanpos.next; + } + } else { + jj_scanpos = jj_scanpos.next; + } + if (jj_rescan) { + int i = 0; Token tok = token; + while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } + if (tok != null) jj_add_error_token(kind, i); + } + if (jj_scanpos.kind != kind) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; + return false; + } + + +/** Get the next Token. */ + final public Token getNextToken() { + if (token.next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + jj_gen++; + return token; + } + +/** Get the specific Token. */ + final public Token getToken(int index) { + Token t = token; + for (int i = 0; i < index; i++) { + if (t.next != null) t = t.next; + else t = t.next = token_source.getNextToken(); + } + return t; + } + + private int jj_ntk() { + if ((jj_nt=token.next) == null) + return (jj_ntk = (token.next=token_source.getNextToken()).kind); + else + return (jj_ntk = jj_nt.kind); + } + + private java.util.List jj_expentries = new java.util.ArrayList(); + private int[] jj_expentry; + private int jj_kind = -1; + private int[] jj_lasttokens = new int[100]; + private int jj_endpos; + + private void jj_add_error_token(int kind, int pos) { + if (pos >= 100) return; + if (pos == jj_endpos + 1) { + jj_lasttokens[jj_endpos++] = kind; + } else if (jj_endpos != 0) { + jj_expentry = new int[jj_endpos]; + for (int i = 0; i < jj_endpos; i++) { + jj_expentry[i] = jj_lasttokens[i]; + } + jj_entries_loop: for (java.util.Iterator it = jj_expentries.iterator(); it.hasNext();) { + int[] oldentry = (int[])(it.next()); + if (oldentry.length == jj_expentry.length) { + for (int i = 0; i < jj_expentry.length; i++) { + if (oldentry[i] != jj_expentry[i]) { + continue jj_entries_loop; + } + } + jj_expentries.add(jj_expentry); + break jj_entries_loop; + } + } + if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind; + } + } + + /** Generate ParseException. */ + public ParseException generateParseException() { + jj_expentries.clear(); + boolean[] la1tokens = new boolean[92]; + if (jj_kind >= 0) { + la1tokens[jj_kind] = true; + jj_kind = -1; + } + for (int i = 0; i < 69; i++) { + if (jj_la1[i] == jj_gen) { + for (int j = 0; j < 32; j++) { + if ((jj_la1_0[i] & (1< jj_gen) { + jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; + switch (i) { + case 0: jj_3_1(); break; + case 1: jj_3_2(); break; + case 2: jj_3_3(); break; + } + } + p = p.next; + } while (p != null); + } catch(LookaheadSuccess ls) { } + } + jj_rescan = false; + } + + private void jj_save(int index, int xla) { + JJCalls p = jj_2_rtns[index]; + while (p.gen > jj_gen) { + if (p.next == null) { p = p.next = new JJCalls(); break; } + p = p.next; + } + p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla; + } + + static final class JJCalls { + int gen; + Token first; + int arg; + JJCalls next; + } + +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderConstants.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderConstants.java new file mode 100644 index 00000000000..b2b5beb23aa --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderConstants.java @@ -0,0 +1,294 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JJTree&JavaCC: Do not edit this line. SyntaxTreeBuilderConstants.java */ +package org.eclipse.rdf4j.query.parser.serql.ast; + + +/** + * Token literal values and constants. + * Generated by org.javacc.parser.OtherFilesGen#start() + */ +public interface SyntaxTreeBuilderConstants { + + /** End of File. */ + int EOF = 0; + /** RegularExpression Id. */ + int SINGLE_LINE_COMMENT = 5; + /** RegularExpression Id. */ + int EQ = 6; + /** RegularExpression Id. */ + int NE = 7; + /** RegularExpression Id. */ + int LT = 8; + /** RegularExpression Id. */ + int LE = 9; + /** RegularExpression Id. */ + int GE = 10; + /** RegularExpression Id. */ + int GT = 11; + /** RegularExpression Id. */ + int STAR = 12; + /** RegularExpression Id. */ + int COMMA = 13; + /** RegularExpression Id. */ + int SEMICOLON = 14; + /** RegularExpression Id. */ + int LBRACE = 15; + /** RegularExpression Id. */ + int RBRACE = 16; + /** RegularExpression Id. */ + int LPAREN = 17; + /** RegularExpression Id. */ + int RPAREN = 18; + /** RegularExpression Id. */ + int LBRACK = 19; + /** RegularExpression Id. */ + int RBRACK = 20; + /** RegularExpression Id. */ + int USING = 21; + /** RegularExpression Id. */ + int NAMESPACE = 22; + /** RegularExpression Id. */ + int SELECT = 23; + /** RegularExpression Id. */ + int CONSTRUCT = 24; + /** RegularExpression Id. */ + int DISTINCT = 25; + /** RegularExpression Id. */ + int REDUCED = 26; + /** RegularExpression Id. */ + int FROM = 27; + /** RegularExpression Id. */ + int CONTEXT = 28; + /** RegularExpression Id. */ + int WHERE = 29; + /** RegularExpression Id. */ + int ORDER = 30; + /** RegularExpression Id. */ + int BY = 31; + /** RegularExpression Id. */ + int ASC = 32; + /** RegularExpression Id. */ + int DESC = 33; + /** RegularExpression Id. */ + int LIMIT = 34; + /** RegularExpression Id. */ + int OFFSET = 35; + /** RegularExpression Id. */ + int TRUE = 36; + /** RegularExpression Id. */ + int FALSE = 37; + /** RegularExpression Id. */ + int NOT = 38; + /** RegularExpression Id. */ + int AND = 39; + /** RegularExpression Id. */ + int OR = 40; + /** RegularExpression Id. */ + int SAMETERM = 41; + /** RegularExpression Id. */ + int LIKE = 42; + /** RegularExpression Id. */ + int IGNORE = 43; + /** RegularExpression Id. */ + int CASE = 44; + /** RegularExpression Id. */ + int REGEX = 45; + /** RegularExpression Id. */ + int LABEL = 46; + /** RegularExpression Id. */ + int LANG = 47; + /** RegularExpression Id. */ + int LANGMATCHES = 48; + /** RegularExpression Id. */ + int DATATYPE = 49; + /** RegularExpression Id. */ + int LOCALNAME = 50; + /** RegularExpression Id. */ + int STR = 51; + /** RegularExpression Id. */ + int BOUND = 52; + /** RegularExpression Id. */ + int NULL = 53; + /** RegularExpression Id. */ + int ISRESOURCE = 54; + /** RegularExpression Id. */ + int ISBNODE = 55; + /** RegularExpression Id. */ + int ISURI = 56; + /** RegularExpression Id. */ + int ISLITERAL = 57; + /** RegularExpression Id. */ + int AS = 58; + /** RegularExpression Id. */ + int UNION = 59; + /** RegularExpression Id. */ + int MINUS = 60; + /** RegularExpression Id. */ + int INTERSECT = 61; + /** RegularExpression Id. */ + int ANY = 62; + /** RegularExpression Id. */ + int ALL = 63; + /** RegularExpression Id. */ + int IN = 64; + /** RegularExpression Id. */ + int EXISTS = 65; + /** RegularExpression Id. */ + int LANG_LITERAL = 66; + /** RegularExpression Id. */ + int DATATYPED_LITERAL = 67; + /** RegularExpression Id. */ + int STRING = 68; + /** RegularExpression Id. */ + int SAFE_CHAR = 69; + /** RegularExpression Id. */ + int ESCAPED_CHAR = 70; + /** RegularExpression Id. */ + int UNICODE_ESC = 71; + /** RegularExpression Id. */ + int LANG_TAG = 72; + /** RegularExpression Id. */ + int URI = 73; + /** RegularExpression Id. */ + int SCHEME = 74; + /** RegularExpression Id. */ + int QNAME = 75; + /** RegularExpression Id. */ + int BNODE = 76; + /** RegularExpression Id. */ + int PREFIX_NAME = 77; + /** RegularExpression Id. */ + int POS_INTEGER = 78; + /** RegularExpression Id. */ + int NEG_INTEGER = 79; + /** RegularExpression Id. */ + int DECIMAL = 80; + /** RegularExpression Id. */ + int HEX = 81; + /** RegularExpression Id. */ + int ALPHA = 82; + /** RegularExpression Id. */ + int NUM = 83; + /** RegularExpression Id. */ + int NCNAME = 84; + /** RegularExpression Id. */ + int NCNAME_CHAR = 85; + /** RegularExpression Id. */ + int LETTER = 86; + /** RegularExpression Id. */ + int BASECHAR = 87; + /** RegularExpression Id. */ + int IDEOGRAPHIC = 88; + /** RegularExpression Id. */ + int COMBINING_CHAR = 89; + /** RegularExpression Id. */ + int DIGIT = 90; + /** RegularExpression Id. */ + int EXTENDER = 91; + + /** Lexical state. */ + int DEFAULT = 0; + + /** Literal token values. */ + String[] tokenImage = { + "", + "\" \"", + "\"\\t\"", + "\"\\n\"", + "\"\\r\"", + "", + "\"=\"", + "\"!=\"", + "\"<\"", + "\"<=\"", + "\">=\"", + "\">\"", + "\"*\"", + "\",\"", + "\";\"", + "\"{\"", + "\"}\"", + "\"(\"", + "\")\"", + "\"[\"", + "\"]\"", + "\"using\"", + "\"namespace\"", + "\"select\"", + "\"construct\"", + "\"distinct\"", + "\"reduced\"", + "\"from\"", + "\"context\"", + "\"where\"", + "\"order\"", + "\"by\"", + "\"asc\"", + "\"desc\"", + "\"limit\"", + "\"offset\"", + "\"true\"", + "\"false\"", + "\"not\"", + "\"and\"", + "\"or\"", + "\"sameTerm\"", + "\"like\"", + "\"ignore\"", + "\"case\"", + "\"regex\"", + "\"label\"", + "\"lang\"", + "\"langMatches\"", + "\"datatype\"", + "\"localname\"", + "\"str\"", + "\"bound\"", + "\"null\"", + "\"isResource\"", + "\"isBNode\"", + "\"isURI\"", + "\"isLiteral\"", + "\"as\"", + "\"union\"", + "\"minus\"", + "\"intersect\"", + "\"any\"", + "\"all\"", + "\"in\"", + "\"exists\"", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }; + +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderTokenManager.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderTokenManager.java new file mode 100644 index 00000000000..c042a7ae449 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderTokenManager.java @@ -0,0 +1,2217 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JJTree&JavaCC: Do not edit this line. SyntaxTreeBuilderTokenManager.java */ +package org.eclipse.rdf4j.query.parser.serql.ast; +import java.io.StringReader; + +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; + +/** Token Manager. */ +public class SyntaxTreeBuilderTokenManager implements SyntaxTreeBuilderConstants +{ + + /** Debug output. */ + public java.io.PrintStream debugStream = System.out; + /** Set debug output. */ + public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } +private final int jjStopStringLiteralDfa_0(int pos, long active0, long active1) +{ + switch (pos) + { + case 0: + if ((active0 & 0xffffffffffe00000L) != 0L || (active1 & 0x3L) != 0L) + { + jjmatchedKind = 77; + return 114; + } + if ((active0 & 0x300L) != 0L) + return 6; + return -1; + case 1: + if ((active0 & 0x24000101c0000000L) != 0L || (active1 & 0x1L) != 0L) + return 114; + if ((active0 & 0xdbfffefe3fe00000L) != 0L || (active1 & 0x2L) != 0L) + { + if (jjmatchedPos != 1) + { + jjmatchedKind = 77; + jjmatchedPos = 1; + } + return 114; + } + return -1; + case 2: + if ((active0 & 0xc00800c100000000L) != 0L) + return 114; + if ((active0 & 0x3bf7fe3e7fe00000L) != 0L || (active1 & 0x2L) != 0L) + { + jjmatchedKind = 77; + jjmatchedPos = 2; + return 114; + } + return -1; + case 3: + if ((active0 & 0x21941208000000L) != 0L) + return 114; + if ((active0 & 0x3bd66a2c77e00000L) != 0L || (active1 & 0x2L) != 0L) + { + if (jjmatchedPos != 3) + { + jjmatchedKind = 77; + jjmatchedPos = 3; + } + return 114; + } + return -1; + case 4: + if ((active0 & 0x22c70a0817c00000L) != 0L || (active1 & 0x2L) != 0L) + { + jjmatchedKind = 77; + jjmatchedPos = 4; + return 114; + } + if ((active0 & 0x1910602460200000L) != 0L) + return 114; + return -1; + case 5: + if ((active0 & 0x80800800000L) != 0L || (active1 & 0x2L) != 0L) + return 114; + if ((active0 & 0x22c7020017400000L) != 0L) + { + jjmatchedKind = 77; + jjmatchedPos = 5; + return 114; + } + return -1; + case 6: + if ((active0 & 0x80000014000000L) != 0L) + return 114; + if ((active0 & 0x2247020003400000L) != 0L) + { + jjmatchedKind = 77; + jjmatchedPos = 6; + return 114; + } + return -1; + case 7: + if ((active0 & 0x2020002000000L) != 0L) + return 114; + if ((active0 & 0x2245000001400000L) != 0L) + { + jjmatchedKind = 77; + jjmatchedPos = 7; + return 114; + } + return -1; + case 8: + if ((active0 & 0x41000000000000L) != 0L) + { + jjmatchedKind = 77; + jjmatchedPos = 8; + return 114; + } + if ((active0 & 0x2204000001400000L) != 0L) + return 114; + return -1; + case 9: + if ((active0 & 0x40000000000000L) != 0L) + return 114; + if ((active0 & 0x1000000000000L) != 0L) + { + jjmatchedKind = 77; + jjmatchedPos = 9; + return 114; + } + return -1; + default : + return -1; + } +} +private final int jjStartNfa_0(int pos, long active0, long active1) +{ + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1), pos + 1); +} +private int jjStopAtPos(int pos, int kind) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; +} +private int jjMoveStringLiteralDfa0_0() +{ + switch(curChar) + { + case 33: + return jjMoveStringLiteralDfa1_0(0x80L, 0x0L); + case 40: + return jjStopAtPos(0, 17); + case 41: + return jjStopAtPos(0, 18); + case 42: + return jjStopAtPos(0, 12); + case 44: + return jjStopAtPos(0, 13); + case 59: + return jjStopAtPos(0, 14); + case 60: + jjmatchedKind = 8; + return jjMoveStringLiteralDfa1_0(0x200L, 0x0L); + case 61: + return jjStopAtPos(0, 6); + case 62: + jjmatchedKind = 11; + return jjMoveStringLiteralDfa1_0(0x400L, 0x0L); + case 91: + return jjStopAtPos(0, 19); + case 93: + return jjStopAtPos(0, 20); + case 65: + case 97: + return jjMoveStringLiteralDfa1_0(0xc400008100000000L, 0x0L); + case 66: + case 98: + return jjMoveStringLiteralDfa1_0(0x10000080000000L, 0x0L); + case 67: + case 99: + return jjMoveStringLiteralDfa1_0(0x100011000000L, 0x0L); + case 68: + case 100: + return jjMoveStringLiteralDfa1_0(0x2000202000000L, 0x0L); + case 69: + case 101: + return jjMoveStringLiteralDfa1_0(0x0L, 0x2L); + case 70: + case 102: + return jjMoveStringLiteralDfa1_0(0x2008000000L, 0x0L); + case 73: + case 105: + return jjMoveStringLiteralDfa1_0(0x23c0080000000000L, 0x1L); + case 76: + case 108: + return jjMoveStringLiteralDfa1_0(0x5c40400000000L, 0x0L); + case 77: + case 109: + return jjMoveStringLiteralDfa1_0(0x1000000000000000L, 0x0L); + case 78: + case 110: + return jjMoveStringLiteralDfa1_0(0x20004000400000L, 0x0L); + case 79: + case 111: + return jjMoveStringLiteralDfa1_0(0x10840000000L, 0x0L); + case 82: + case 114: + return jjMoveStringLiteralDfa1_0(0x200004000000L, 0x0L); + case 83: + case 115: + return jjMoveStringLiteralDfa1_0(0x8020000800000L, 0x0L); + case 84: + case 116: + return jjMoveStringLiteralDfa1_0(0x1000000000L, 0x0L); + case 85: + case 117: + return jjMoveStringLiteralDfa1_0(0x800000000200000L, 0x0L); + case 87: + case 119: + return jjMoveStringLiteralDfa1_0(0x20000000L, 0x0L); + case 123: + return jjStopAtPos(0, 15); + case 125: + return jjStopAtPos(0, 16); + default : + return jjMoveNfa_0(0, 0); + } +} +private int jjMoveStringLiteralDfa1_0(long active0, long active1) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(0, active0, active1); + return 1; + } + switch(curChar) + { + case 61: + if ((active0 & 0x80L) != 0L) + return jjStopAtPos(1, 7); + else if ((active0 & 0x200L) != 0L) + return jjStopAtPos(1, 9); + else if ((active0 & 0x400L) != 0L) + return jjStopAtPos(1, 10); + break; + case 65: + case 97: + return jjMoveStringLiteralDfa2_0(active0, 0x3d22000400000L, active1, 0L); + case 69: + case 101: + return jjMoveStringLiteralDfa2_0(active0, 0x200204800000L, active1, 0L); + case 70: + case 102: + return jjMoveStringLiteralDfa2_0(active0, 0x800000000L, active1, 0L); + case 71: + case 103: + return jjMoveStringLiteralDfa2_0(active0, 0x80000000000L, active1, 0L); + case 72: + case 104: + return jjMoveStringLiteralDfa2_0(active0, 0x20000000L, active1, 0L); + case 73: + case 105: + return jjMoveStringLiteralDfa2_0(active0, 0x1000040402000000L, active1, 0L); + case 76: + case 108: + return jjMoveStringLiteralDfa2_0(active0, 0x8000000000000000L, active1, 0L); + case 78: + case 110: + if ((active1 & 0x1L) != 0L) + { + jjmatchedKind = 64; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0x6800008000000000L, active1, 0L); + case 79: + case 111: + return jjMoveStringLiteralDfa2_0(active0, 0x14004011000000L, active1, 0L); + case 82: + case 114: + if ((active0 & 0x10000000000L) != 0L) + { + jjmatchedKind = 40; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0x1048000000L, active1, 0L); + case 83: + case 115: + if ((active0 & 0x400000000000000L) != 0L) + { + jjmatchedKind = 58; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0x3c0000100200000L, active1, 0L); + case 84: + case 116: + return jjMoveStringLiteralDfa2_0(active0, 0x8000000000000L, active1, 0L); + case 85: + case 117: + return jjMoveStringLiteralDfa2_0(active0, 0x20000000000000L, active1, 0L); + case 88: + case 120: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x2L); + case 89: + case 121: + if ((active0 & 0x80000000L) != 0L) + return jjStartNfaWithStates_0(1, 31, 114); + break; + default : + break; + } + return jjStartNfa_0(0, active0, active1); +} +private int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(0, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(1, active0, active1); + return 2; + } + switch(curChar) + { + case 66: + case 98: + return jjMoveStringLiteralDfa3_0(active0, 0x80400000000000L, active1, 0L); + case 67: + case 99: + if ((active0 & 0x100000000L) != 0L) + return jjStartNfaWithStates_0(2, 32, 114); + return jjMoveStringLiteralDfa3_0(active0, 0x4000000000000L, active1, 0L); + case 68: + case 100: + if ((active0 & 0x8000000000L) != 0L) + return jjStartNfaWithStates_0(2, 39, 114); + return jjMoveStringLiteralDfa3_0(active0, 0x44000000L, active1, 0L); + case 69: + case 101: + return jjMoveStringLiteralDfa3_0(active0, 0x20000000L, active1, 0L); + case 70: + case 102: + return jjMoveStringLiteralDfa3_0(active0, 0x800000000L, active1, 0L); + case 71: + case 103: + return jjMoveStringLiteralDfa3_0(active0, 0x200000000000L, active1, 0L); + case 73: + case 105: + return jjMoveStringLiteralDfa3_0(active0, 0x800000000200000L, active1, 0x2L); + case 75: + case 107: + return jjMoveStringLiteralDfa3_0(active0, 0x40000000000L, active1, 0L); + case 76: + case 108: + if ((active0 & 0x8000000000000000L) != 0L) + return jjStartNfaWithStates_0(2, 63, 114); + return jjMoveStringLiteralDfa3_0(active0, 0x220002000800000L, active1, 0L); + case 77: + case 109: + return jjMoveStringLiteralDfa3_0(active0, 0x20400400000L, active1, 0L); + case 78: + case 110: + return jjMoveStringLiteralDfa3_0(active0, 0x1001880011000000L, active1, 0L); + case 79: + case 111: + return jjMoveStringLiteralDfa3_0(active0, 0x8000000L, active1, 0L); + case 82: + case 114: + if ((active0 & 0x8000000000000L) != 0L) + return jjStartNfaWithStates_0(2, 51, 114); + return jjMoveStringLiteralDfa3_0(active0, 0x40000000000000L, active1, 0L); + case 83: + case 115: + return jjMoveStringLiteralDfa3_0(active0, 0x100202000000L, active1, 0L); + case 84: + case 116: + if ((active0 & 0x4000000000L) != 0L) + return jjStartNfaWithStates_0(2, 38, 114); + return jjMoveStringLiteralDfa3_0(active0, 0x2002000000000000L, active1, 0L); + case 85: + case 117: + return jjMoveStringLiteralDfa3_0(active0, 0x110001000000000L, active1, 0L); + case 89: + case 121: + if ((active0 & 0x4000000000000000L) != 0L) + return jjStartNfaWithStates_0(2, 62, 114); + break; + default : + break; + } + return jjStartNfa_0(1, active0, active1); +} +private int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(1, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(2, active0, active1); + return 3; + } + switch(curChar) + { + case 65: + case 97: + return jjMoveStringLiteralDfa4_0(active0, 0x6000000000000L, active1, 0L); + case 67: + case 99: + if ((active0 & 0x200000000L) != 0L) + return jjStartNfaWithStates_0(3, 33, 114); + break; + case 69: + case 101: + if ((active0 & 0x1000000000L) != 0L) + return jjStartNfaWithStates_0(3, 36, 114); + else if ((active0 & 0x40000000000L) != 0L) + return jjStartNfaWithStates_0(3, 42, 114); + else if ((active0 & 0x100000000000L) != 0L) + return jjStartNfaWithStates_0(3, 44, 114); + return jjMoveStringLiteralDfa4_0(active0, 0x2040620040c00000L, active1, 0L); + case 71: + case 103: + if ((active0 & 0x800000000000L) != 0L) + { + jjmatchedKind = 47; + jjmatchedPos = 3; + } + return jjMoveStringLiteralDfa4_0(active0, 0x1000000000000L, active1, 0L); + case 73: + case 105: + return jjMoveStringLiteralDfa4_0(active0, 0x200000400000000L, active1, 0L); + case 76: + case 108: + if ((active0 & 0x20000000000000L) != 0L) + return jjStartNfaWithStates_0(3, 53, 114); + break; + case 77: + case 109: + if ((active0 & 0x8000000L) != 0L) + return jjStartNfaWithStates_0(3, 27, 114); + break; + case 78: + case 110: + return jjMoveStringLiteralDfa4_0(active0, 0x90000000200000L, active1, 0L); + case 79: + case 111: + return jjMoveStringLiteralDfa4_0(active0, 0x800080000000000L, active1, 0L); + case 82: + case 114: + return jjMoveStringLiteralDfa4_0(active0, 0x100000020000000L, active1, 0L); + case 83: + case 115: + return jjMoveStringLiteralDfa4_0(active0, 0x2801000000L, active1, 0x2L); + case 84: + case 116: + return jjMoveStringLiteralDfa4_0(active0, 0x12000000L, active1, 0L); + case 85: + case 117: + return jjMoveStringLiteralDfa4_0(active0, 0x1000000004000000L, active1, 0L); + default : + break; + } + return jjStartNfa_0(2, active0, active1); +} +private int jjMoveStringLiteralDfa4_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(2, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(3, active0, active1); + return 4; + } + switch(curChar) + { + case 67: + case 99: + return jjMoveStringLiteralDfa5_0(active0, 0x4800000L, active1, 0L); + case 68: + case 100: + if ((active0 & 0x10000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 52, 114); + break; + case 69: + case 101: + if ((active0 & 0x20000000L) != 0L) + return jjStartNfaWithStates_0(4, 29, 114); + else if ((active0 & 0x2000000000L) != 0L) + return jjStartNfaWithStates_0(4, 37, 114); + return jjMoveStringLiteralDfa5_0(active0, 0x810000000L, active1, 0L); + case 71: + case 103: + if ((active0 & 0x200000L) != 0L) + return jjStartNfaWithStates_0(4, 21, 114); + break; + case 73: + case 105: + if ((active0 & 0x100000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 56, 114); + return jjMoveStringLiteralDfa5_0(active0, 0x2000000L, active1, 0L); + case 76: + case 108: + if ((active0 & 0x400000000000L) != 0L) + return jjStartNfaWithStates_0(4, 46, 114); + return jjMoveStringLiteralDfa5_0(active0, 0x4000000000000L, active1, 0L); + case 77: + case 109: + return jjMoveStringLiteralDfa5_0(active0, 0x1000000000000L, active1, 0L); + case 78: + case 110: + if ((active0 & 0x800000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 59, 114); + break; + case 79: + case 111: + return jjMoveStringLiteralDfa5_0(active0, 0x80000000000000L, active1, 0L); + case 82: + case 114: + if ((active0 & 0x40000000L) != 0L) + return jjStartNfaWithStates_0(4, 30, 114); + return jjMoveStringLiteralDfa5_0(active0, 0x2000080000000000L, active1, 0L); + case 83: + case 115: + if ((active0 & 0x1000000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 60, 114); + return jjMoveStringLiteralDfa5_0(active0, 0x40000000400000L, active1, 0L); + case 84: + case 116: + if ((active0 & 0x400000000L) != 0L) + return jjStartNfaWithStates_0(4, 34, 114); + return jjMoveStringLiteralDfa5_0(active0, 0x202020001000000L, active1, 0x2L); + case 88: + case 120: + if ((active0 & 0x200000000000L) != 0L) + return jjStartNfaWithStates_0(4, 45, 114); + break; + default : + break; + } + return jjStartNfa_0(3, active0, active1); +} +private int jjMoveStringLiteralDfa5_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(3, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(4, active0, active1); + return 5; + } + switch(curChar) + { + case 65: + case 97: + return jjMoveStringLiteralDfa6_0(active0, 0x1000000000000L, active1, 0L); + case 68: + case 100: + return jjMoveStringLiteralDfa6_0(active0, 0x80000000000000L, active1, 0L); + case 69: + case 101: + if ((active0 & 0x80000000000L) != 0L) + return jjStartNfaWithStates_0(5, 43, 114); + return jjMoveStringLiteralDfa6_0(active0, 0x200020004000000L, active1, 0L); + case 78: + case 110: + return jjMoveStringLiteralDfa6_0(active0, 0x4000002000000L, active1, 0L); + case 79: + case 111: + return jjMoveStringLiteralDfa6_0(active0, 0x40000000000000L, active1, 0L); + case 80: + case 112: + return jjMoveStringLiteralDfa6_0(active0, 0x400000L, active1, 0L); + case 82: + case 114: + return jjMoveStringLiteralDfa6_0(active0, 0x1000000L, active1, 0L); + case 83: + case 115: + if ((active1 & 0x2L) != 0L) + return jjStartNfaWithStates_0(5, 65, 114); + return jjMoveStringLiteralDfa6_0(active0, 0x2000000000000000L, active1, 0L); + case 84: + case 116: + if ((active0 & 0x800000L) != 0L) + return jjStartNfaWithStates_0(5, 23, 114); + else if ((active0 & 0x800000000L) != 0L) + return jjStartNfaWithStates_0(5, 35, 114); + break; + case 88: + case 120: + return jjMoveStringLiteralDfa6_0(active0, 0x10000000L, active1, 0L); + case 89: + case 121: + return jjMoveStringLiteralDfa6_0(active0, 0x2000000000000L, active1, 0L); + default : + break; + } + return jjStartNfa_0(4, active0, active1); +} +private int jjMoveStringLiteralDfa6_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(4, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(5, active0, 0L); + return 6; + } + switch(curChar) + { + case 65: + case 97: + return jjMoveStringLiteralDfa7_0(active0, 0x4000000400000L); + case 67: + case 99: + return jjMoveStringLiteralDfa7_0(active0, 0x2000000L); + case 68: + case 100: + if ((active0 & 0x4000000L) != 0L) + return jjStartNfaWithStates_0(6, 26, 114); + break; + case 69: + case 101: + if ((active0 & 0x80000000000000L) != 0L) + return jjStartNfaWithStates_0(6, 55, 114); + return jjMoveStringLiteralDfa7_0(active0, 0x2000000000000000L); + case 80: + case 112: + return jjMoveStringLiteralDfa7_0(active0, 0x2000000000000L); + case 82: + case 114: + return jjMoveStringLiteralDfa7_0(active0, 0x200020000000000L); + case 84: + case 116: + if ((active0 & 0x10000000L) != 0L) + return jjStartNfaWithStates_0(6, 28, 114); + return jjMoveStringLiteralDfa7_0(active0, 0x1000000000000L); + case 85: + case 117: + return jjMoveStringLiteralDfa7_0(active0, 0x40000001000000L); + default : + break; + } + return jjStartNfa_0(5, active0, 0L); +} +private int jjMoveStringLiteralDfa7_0(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_0(5, old0, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(6, active0, 0L); + return 7; + } + switch(curChar) + { + case 65: + case 97: + return jjMoveStringLiteralDfa8_0(active0, 0x200000000000000L); + case 67: + case 99: + return jjMoveStringLiteralDfa8_0(active0, 0x2001000001400000L); + case 69: + case 101: + if ((active0 & 0x2000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 49, 114); + break; + case 77: + case 109: + if ((active0 & 0x20000000000L) != 0L) + return jjStartNfaWithStates_0(7, 41, 114); + return jjMoveStringLiteralDfa8_0(active0, 0x4000000000000L); + case 82: + case 114: + return jjMoveStringLiteralDfa8_0(active0, 0x40000000000000L); + case 84: + case 116: + if ((active0 & 0x2000000L) != 0L) + return jjStartNfaWithStates_0(7, 25, 114); + break; + default : + break; + } + return jjStartNfa_0(6, active0, 0L); +} +private int jjMoveStringLiteralDfa8_0(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_0(6, old0, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(7, active0, 0L); + return 8; + } + switch(curChar) + { + case 67: + case 99: + return jjMoveStringLiteralDfa9_0(active0, 0x40000000000000L); + case 69: + case 101: + if ((active0 & 0x400000L) != 0L) + return jjStartNfaWithStates_0(8, 22, 114); + else if ((active0 & 0x4000000000000L) != 0L) + return jjStartNfaWithStates_0(8, 50, 114); + break; + case 72: + case 104: + return jjMoveStringLiteralDfa9_0(active0, 0x1000000000000L); + case 76: + case 108: + if ((active0 & 0x200000000000000L) != 0L) + return jjStartNfaWithStates_0(8, 57, 114); + break; + case 84: + case 116: + if ((active0 & 0x1000000L) != 0L) + return jjStartNfaWithStates_0(8, 24, 114); + else if ((active0 & 0x2000000000000000L) != 0L) + return jjStartNfaWithStates_0(8, 61, 114); + break; + default : + break; + } + return jjStartNfa_0(7, active0, 0L); +} +private int jjMoveStringLiteralDfa9_0(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_0(7, old0, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(8, active0, 0L); + return 9; + } + switch(curChar) + { + case 69: + case 101: + if ((active0 & 0x40000000000000L) != 0L) + return jjStartNfaWithStates_0(9, 54, 114); + return jjMoveStringLiteralDfa10_0(active0, 0x1000000000000L); + default : + break; + } + return jjStartNfa_0(8, active0, 0L); +} +private int jjMoveStringLiteralDfa10_0(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_0(8, old0, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(9, active0, 0L); + return 10; + } + switch(curChar) + { + case 83: + case 115: + if ((active0 & 0x1000000000000L) != 0L) + return jjStartNfaWithStates_0(10, 48, 114); + break; + default : + break; + } + return jjStartNfa_0(9, active0, 0L); +} +private int jjStartNfaWithStates_0(int pos, int kind, int state) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return pos + 1; } + return jjMoveNfa_0(state, pos + 1); +} +static final long[] jjbitVec0 = { + 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +static final long[] jjbitVec2 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +static final long[] jjbitVec3 = { + 0x1600L, 0x0L, 0x0L, 0x0L +}; +static final long[] jjbitVec4 = { + 0x0L, 0xffc000000000L, 0x0L, 0xffc000000000L +}; +static final long[] jjbitVec5 = { + 0x0L, 0x3ff00000000L, 0x0L, 0x3ff000000000000L +}; +static final long[] jjbitVec6 = { + 0x0L, 0xffc000000000L, 0x0L, 0xff8000000000L +}; +static final long[] jjbitVec7 = { + 0x0L, 0xffc000000000L, 0x0L, 0x0L +}; +static final long[] jjbitVec8 = { + 0x0L, 0x3ff0000L, 0x0L, 0x3ff0000L +}; +static final long[] jjbitVec9 = { + 0x3ff00000000L, 0x0L, 0x0L, 0x0L +}; +static final long[] jjbitVec10 = { + 0x0L, 0xffffffffffffc000L, 0xfffff0007fffffffL, 0x7fffffL +}; +static final long[] jjbitVec11 = { + 0x0L, 0x0L, 0x0L, 0xff7fffffff7fffffL +}; +static final long[] jjbitVec12 = { + 0x7ff3ffffffffffffL, 0x7ffffffffffffdfeL, 0xffffffffffffffffL, 0xfc31ffffffffe00fL +}; +static final long[] jjbitVec13 = { + 0xffffffL, 0xffffffffffff0000L, 0xf80001ffffffffffL, 0x3L +}; +static final long[] jjbitVec14 = { + 0x0L, 0x0L, 0xfffffffbffffd740L, 0xffffffc7f7fffL +}; +static final long[] jjbitVec15 = { + 0xffffffffffffdffeL, 0xffffffffdffeffffL, 0xffffffffffff0003L, 0x33fcfffffff199fL +}; +static final long[] jjbitVec16 = { + 0xfffe000000000000L, 0xfffffffe027fffffL, 0x7fL, 0x707ffffff0000L +}; +static final long[] jjbitVec17 = { + 0x7fffffe00000000L, 0xfffe0000000007feL, 0x7cffffffffffffffL, 0x60002f7fffL +}; +static final long[] jjbitVec18 = { + 0x23ffffffffffffe0L, 0x3ff000000L, 0x3c5fdfffff99fe0L, 0x30003b0000000L +}; +static final long[] jjbitVec19 = { + 0x36dfdfffff987e0L, 0x1c00005e000000L, 0x23edfdfffffbafe0L, 0x100000000L +}; +static final long[] jjbitVec20 = { + 0x23cdfdfffff99fe0L, 0x3b0000000L, 0x3bfc718d63dc7e0L, 0x0L +}; +static final long[] jjbitVec21 = { + 0x3effdfffffddfe0L, 0x300000000L, 0x3effdfffffddfe0L, 0x340000000L +}; +static final long[] jjbitVec22 = { + 0x3fffdfffffddfe0L, 0x300000000L, 0x0L, 0x0L +}; +static final long[] jjbitVec23 = { + 0xd7ffffffffffeL, 0x3fL, 0x200d6caefef02596L, 0x1fL +}; +static final long[] jjbitVec24 = { + 0x0L, 0x3fffffffeffL, 0x0L, 0x0L +}; +static final long[] jjbitVec25 = { + 0x0L, 0x0L, 0xffffffff00000000L, 0x7fffffffff003fL +}; +static final long[] jjbitVec26 = { + 0x500000000007daedL, 0x2c62ab82315001L, 0xf580c90040000000L, 0x201080000000007L +}; +static final long[] jjbitVec27 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffff0fffffffL, 0x3ffffffffffffffL +}; +static final long[] jjbitVec28 = { + 0xffffffff3f3fffffL, 0x3fffffffaaff3f3fL, 0x5fdfffffffffffffL, 0x1fdc1fff0fcf1fdcL +}; +static final long[] jjbitVec29 = { + 0x4c4000000000L, 0x0L, 0x7L, 0x0L +}; +static final long[] jjbitVec30 = { + 0x3fe00000080L, 0xfffffffffffffffeL, 0xfffffffe001fffffL, 0x7ffffffffffffffL +}; +static final long[] jjbitVec31 = { + 0x1fffffffffe0L, 0x0L, 0x0L, 0x0L +}; +static final long[] jjbitVec32 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0x3fffffffffL, 0x0L +}; +static final long[] jjbitVec33 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffL, 0x0L +}; +static final long[] jjbitVec34 = { + 0x0L, 0x0L, 0x80000000000000L, 0xff7fffffff7fffffL +}; +static final long[] jjbitVec35 = { + 0xffffffL, 0xffffffffffff0000L, 0xf80001ffffffffffL, 0x30003L +}; +static final long[] jjbitVec36 = { + 0xffffffffffffffffL, 0x30000003fL, 0xfffffffbffffd7c0L, 0xffffffc7f7fffL +}; +static final long[] jjbitVec37 = { + 0xffffffffffffdffeL, 0xffffffffdffeffffL, 0xffffffffffff007bL, 0x33fcfffffff199fL +}; +static final long[] jjbitVec38 = { + 0xfffe000000000000L, 0xfffffffe027fffffL, 0xbbfffffbfffe007fL, 0x707ffffff0016L +}; +static final long[] jjbitVec39 = { + 0x7fffffe00000000L, 0xffff03ff0007ffffL, 0x7cffffffffffffffL, 0x3ff3dffffef7fffL +}; +static final long[] jjbitVec40 = { + 0xf3ffffffffffffeeL, 0xffcfff1e3fffL, 0xd3c5fdfffff99feeL, 0x3ffcfb080399fL +}; +static final long[] jjbitVec41 = { + 0xd36dfdfffff987e4L, 0x1fffc05e003987L, 0xf3edfdfffffbafeeL, 0xffc100003bbfL +}; +static final long[] jjbitVec42 = { + 0xf3cdfdfffff99feeL, 0xffc3b0c0398fL, 0xc3bfc718d63dc7ecL, 0xff8000803dc7L +}; +static final long[] jjbitVec43 = { + 0xc3effdfffffddfeeL, 0xffc300603ddfL, 0xc3effdfffffddfecL, 0xffc340603ddfL +}; +static final long[] jjbitVec44 = { + 0xc3fffdfffffddfecL, 0xffc300803dcfL, 0x0L, 0x0L +}; +static final long[] jjbitVec45 = { + 0x7ff7ffffffffffeL, 0x3ff7fffL, 0x3bff6caefef02596L, 0x3ff3f5fL +}; +static final long[] jjbitVec46 = { + 0xc2a003ff03000000L, 0xfffe03fffffffeffL, 0x2fe3ffffebf0fdfL, 0x0L +}; +static final long[] jjbitVec47 = { + 0x0L, 0x0L, 0x0L, 0x21fff0000L +}; +static final long[] jjbitVec48 = { + 0x3efffe000000a0L, 0xfffffffffffffffeL, 0xfffffffe661fffffL, 0x77ffffffffffffffL +}; +private int jjMoveNfa_0(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 114; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 0: + if ((0x3ff000000000000L & l) != 0L) + { + if (kind > 78) + kind = 78; + jjCheckNAddStates(0, 2); + } + else if ((0x280000000000L & l) != 0L) + jjCheckNAddTwoStates(20, 21); + else if (curChar == 34) + jjCheckNAddStates(3, 11); + else if (curChar == 46) + jjCheckNAdd(22); + else if (curChar == 60) + jjstateSet[jjnewStateCnt++] = 6; + else if (curChar == 35) + { + if (kind > 5) + kind = 5; + jjCheckNAddStates(12, 14); + } + if (curChar == 45) + jjCheckNAdd(18); + else if (curChar == 43) + jjCheckNAdd(16); + break; + case 114: + if ((0x3ff600000000000L & l) != 0L) + { + if (kind > 77) + kind = 77; + jjCheckNAdd(109); + } + else if (curChar == 58) + { + if (kind > 75) + kind = 75; + jjCheckNAdd(108); + } + if ((0x3ff600000000000L & l) != 0L) + jjCheckNAddTwoStates(106, 107); + break; + case 1: + if ((0xffffffffffffdbffL & l) == 0L) + break; + if (kind > 5) + kind = 5; + jjCheckNAddStates(12, 14); + break; + case 2: + if ((0x2400L & l) != 0L && kind > 5) + kind = 5; + break; + case 3: + if (curChar == 10 && kind > 5) + kind = 5; + break; + case 4: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 3; + break; + case 5: + if (curChar == 60) + jjstateSet[jjnewStateCnt++] = 6; + break; + case 7: + if ((0x3ff680000000000L & l) != 0L) + jjAddStates(15, 16); + break; + case 8: + if (curChar == 58) + jjCheckNAdd(9); + break; + case 9: + if ((0xaffffffa00000000L & l) != 0L) + jjCheckNAddTwoStates(9, 10); + break; + case 10: + if (curChar == 62 && kind > 73) + kind = 73; + break; + case 11: + if (curChar == 58) + jjstateSet[jjnewStateCnt++] = 12; + break; + case 13: + if ((0x3ff600000000000L & l) == 0L) + break; + if (kind > 76) + kind = 76; + jjstateSet[jjnewStateCnt++] = 13; + break; + case 15: + if (curChar == 43) + jjCheckNAdd(16); + break; + case 16: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 78) + kind = 78; + jjCheckNAdd(16); + break; + case 17: + if (curChar == 45) + jjCheckNAdd(18); + break; + case 18: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 79) + kind = 79; + jjCheckNAdd(18); + break; + case 19: + if ((0x280000000000L & l) != 0L) + jjCheckNAddTwoStates(20, 21); + break; + case 20: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(20, 21); + break; + case 21: + if (curChar == 46) + jjCheckNAdd(22); + break; + case 22: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 80) + kind = 80; + jjCheckNAdd(22); + break; + case 23: + if (curChar == 34) + jjCheckNAddStates(3, 11); + break; + case 24: + if ((0xfffffffbffffffffL & l) != 0L) + jjCheckNAddStates(17, 19); + break; + case 25: + if (curChar == 34) + jjstateSet[jjnewStateCnt++] = 26; + break; + case 28: + if (curChar == 45) + jjCheckNAdd(29); + break; + case 29: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 66) + kind = 66; + jjCheckNAddTwoStates(28, 29); + break; + case 31: + if (curChar == 9) + jjCheckNAddStates(17, 19); + break; + case 32: + if (curChar == 13) + jjCheckNAddStates(17, 19); + break; + case 33: + if (curChar == 10) + jjCheckNAddStates(17, 19); + break; + case 34: + if (curChar == 34) + jjCheckNAddStates(17, 19); + break; + case 37: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 38; + break; + case 38: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 39; + break; + case 39: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 40; + break; + case 40: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 41; + break; + case 41: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 42; + break; + case 42: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 43; + break; + case 43: + case 48: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAdd(44); + break; + case 44: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(17, 19); + break; + case 46: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 47; + break; + case 47: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 48; + break; + case 49: + if ((0xfffffffbffffffffL & l) != 0L) + jjCheckNAddStates(20, 22); + break; + case 50: + if (curChar == 34) + jjstateSet[jjnewStateCnt++] = 64; + break; + case 52: + if (curChar == 60) + jjstateSet[jjnewStateCnt++] = 53; + break; + case 54: + if ((0x3ff680000000000L & l) != 0L) + jjAddStates(23, 24); + break; + case 55: + if (curChar == 58) + jjCheckNAdd(56); + break; + case 56: + if ((0xaffffffa00000000L & l) != 0L) + jjCheckNAddTwoStates(56, 57); + break; + case 57: + if (curChar == 62 && kind > 67) + kind = 67; + break; + case 59: + if ((0x3ff600000000000L & l) != 0L) + jjCheckNAddTwoStates(59, 60); + break; + case 60: + if (curChar != 58) + break; + if (kind > 67) + kind = 67; + jjCheckNAdd(61); + break; + case 61: + if ((0x3ff600000000000L & l) == 0L) + break; + if (kind > 67) + kind = 67; + jjCheckNAdd(61); + break; + case 63: + if ((0x3ff600000000000L & l) != 0L) + jjCheckNAddTwoStates(63, 60); + break; + case 66: + if (curChar == 9) + jjCheckNAddStates(20, 22); + break; + case 67: + if (curChar == 13) + jjCheckNAddStates(20, 22); + break; + case 68: + if (curChar == 10) + jjCheckNAddStates(20, 22); + break; + case 69: + if (curChar == 34) + jjCheckNAddStates(20, 22); + break; + case 72: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 73; + break; + case 73: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 74; + break; + case 74: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 75; + break; + case 75: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 76; + break; + case 76: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 77; + break; + case 77: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 78; + break; + case 78: + case 83: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAdd(79); + break; + case 79: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(20, 22); + break; + case 81: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 82; + break; + case 82: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 83; + break; + case 84: + if ((0xfffffffbffffffffL & l) != 0L) + jjCheckNAddStates(25, 27); + break; + case 85: + if (curChar == 34 && kind > 68) + kind = 68; + break; + case 87: + if (curChar == 9) + jjCheckNAddStates(25, 27); + break; + case 88: + if (curChar == 13) + jjCheckNAddStates(25, 27); + break; + case 89: + if (curChar == 10) + jjCheckNAddStates(25, 27); + break; + case 90: + if (curChar == 34) + jjCheckNAddStates(25, 27); + break; + case 93: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 94; + break; + case 94: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 95; + break; + case 95: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 96; + break; + case 96: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 97; + break; + case 97: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 98; + break; + case 98: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 99; + break; + case 99: + case 104: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAdd(100); + break; + case 100: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(25, 27); + break; + case 102: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 103; + break; + case 103: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 104; + break; + case 106: + if ((0x3ff600000000000L & l) != 0L) + jjCheckNAddTwoStates(106, 107); + break; + case 107: + if (curChar != 58) + break; + if (kind > 75) + kind = 75; + jjCheckNAdd(108); + break; + case 108: + if ((0x3ff600000000000L & l) == 0L) + break; + if (kind > 75) + kind = 75; + jjCheckNAdd(108); + break; + case 109: + if ((0x3ff600000000000L & l) == 0L) + break; + if (kind > 77) + kind = 77; + jjCheckNAdd(109); + break; + case 111: + if ((0x3ff600000000000L & l) != 0L) + jjCheckNAddTwoStates(111, 107); + break; + case 112: + if ((0x3ff600000000000L & l) == 0L) + break; + if (kind > 77) + kind = 77; + jjstateSet[jjnewStateCnt++] = 112; + break; + case 113: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 78) + kind = 78; + jjCheckNAddStates(0, 2); + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 0: + if ((0x7fffffe07fffffeL & l) != 0L) + { + if (kind > 77) + kind = 77; + jjCheckNAddStates(28, 30); + } + else if (curChar == 95) + jjCheckNAddTwoStates(111, 112); + if (curChar == 95) + jjstateSet[jjnewStateCnt++] = 11; + break; + case 114: + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 77) + kind = 77; + jjCheckNAdd(109); + } + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(106, 107); + break; + case 1: + if (kind > 5) + kind = 5; + jjAddStates(12, 14); + break; + case 6: + case 7: + if ((0x7fffffe07fffffeL & l) != 0L) + jjCheckNAddTwoStates(7, 8); + break; + case 9: + if ((0xc7fffffeafffffffL & l) != 0L) + jjAddStates(31, 32); + break; + case 12: + case 13: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 76) + kind = 76; + jjCheckNAdd(13); + break; + case 14: + if (curChar == 95) + jjstateSet[jjnewStateCnt++] = 11; + break; + case 24: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(17, 19); + break; + case 26: + if (curChar == 64) + jjCheckNAdd(27); + break; + case 27: + if ((0x7fffffe07fffffeL & l) == 0L) + break; + if (kind > 66) + kind = 66; + jjCheckNAddTwoStates(27, 28); + break; + case 29: + if ((0x7fffffe07fffffeL & l) == 0L) + break; + if (kind > 66) + kind = 66; + jjCheckNAddTwoStates(28, 29); + break; + case 30: + if (curChar == 92) + jjAddStates(33, 39); + break; + case 35: + if (curChar == 92) + jjCheckNAddStates(17, 19); + break; + case 36: + if ((0x20000000200000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 37; + break; + case 37: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 38; + break; + case 38: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 39; + break; + case 39: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 40; + break; + case 40: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 41; + break; + case 41: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 42; + break; + case 42: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 43; + break; + case 43: + case 48: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAdd(44); + break; + case 44: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddStates(17, 19); + break; + case 45: + if ((0x20000000200000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 46; + break; + case 46: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 47; + break; + case 47: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 48; + break; + case 49: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(20, 22); + break; + case 51: + if (curChar == 94) + jjAddStates(40, 42); + break; + case 53: + case 54: + if ((0x7fffffe07fffffeL & l) != 0L) + jjCheckNAddTwoStates(54, 55); + break; + case 56: + if ((0xc7fffffeafffffffL & l) != 0L) + jjAddStates(43, 44); + break; + case 58: + if ((0x7fffffe07fffffeL & l) != 0L) + jjCheckNAddTwoStates(59, 60); + break; + case 59: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(59, 60); + break; + case 61: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 67) + kind = 67; + jjstateSet[jjnewStateCnt++] = 61; + break; + case 62: + if (curChar == 95) + jjCheckNAdd(63); + break; + case 63: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(63, 60); + break; + case 64: + if (curChar == 94) + jjstateSet[jjnewStateCnt++] = 51; + break; + case 65: + if (curChar == 92) + jjAddStates(45, 51); + break; + case 70: + if (curChar == 92) + jjCheckNAddStates(20, 22); + break; + case 71: + if ((0x20000000200000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 72; + break; + case 72: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 73; + break; + case 73: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 74; + break; + case 74: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 75; + break; + case 75: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 76; + break; + case 76: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 77; + break; + case 77: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 78; + break; + case 78: + case 83: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAdd(79); + break; + case 79: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddStates(20, 22); + break; + case 80: + if ((0x20000000200000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 81; + break; + case 81: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 82; + break; + case 82: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 83; + break; + case 84: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(25, 27); + break; + case 86: + if (curChar == 92) + jjAddStates(52, 58); + break; + case 91: + if (curChar == 92) + jjCheckNAddStates(25, 27); + break; + case 92: + if ((0x20000000200000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 93; + break; + case 93: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 94; + break; + case 94: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 95; + break; + case 95: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 96; + break; + case 96: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 97; + break; + case 97: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 98; + break; + case 98: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 99; + break; + case 99: + case 104: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAdd(100); + break; + case 100: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddStates(25, 27); + break; + case 101: + if ((0x20000000200000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 102; + break; + case 102: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 103; + break; + case 103: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 104; + break; + case 105: + if ((0x7fffffe07fffffeL & l) == 0L) + break; + if (kind > 77) + kind = 77; + jjCheckNAddStates(28, 30); + break; + case 106: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(106, 107); + break; + case 108: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 75) + kind = 75; + jjstateSet[jjnewStateCnt++] = 108; + break; + case 109: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 77) + kind = 77; + jjCheckNAdd(109); + break; + case 110: + if (curChar == 95) + jjCheckNAddTwoStates(111, 112); + break; + case 111: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(111, 107); + break; + case 112: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 77) + kind = 77; + jjCheckNAdd(112); + break; + default : break; + } + } while(i != startsAt); + } + else + { + int hiByte = (int)(curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 0: + if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) + break; + if (kind > 77) + kind = 77; + jjCheckNAddStates(28, 30); + break; + case 114: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(106, 107); + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + { + if (kind > 77) + kind = 77; + jjCheckNAdd(109); + } + break; + case 1: + if (!jjCanMove_0(hiByte, i1, i2, l1, l2)) + break; + if (kind > 5) + kind = 5; + jjAddStates(12, 14); + break; + case 7: + if (jjCanMove_1(hiByte, i1, i2, l1, l2)) + jjAddStates(15, 16); + break; + case 9: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(31, 32); + break; + case 12: + if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) + break; + if (kind > 76) + kind = 76; + jjCheckNAdd(13); + break; + case 13: + if (!jjCanMove_3(hiByte, i1, i2, l1, l2)) + break; + if (kind > 76) + kind = 76; + jjCheckNAdd(13); + break; + case 24: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(17, 19); + break; + case 49: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(20, 22); + break; + case 54: + if (jjCanMove_1(hiByte, i1, i2, l1, l2)) + jjAddStates(23, 24); + break; + case 56: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(43, 44); + break; + case 58: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(59, 60); + break; + case 59: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(59, 60); + break; + case 61: + if (!jjCanMove_3(hiByte, i1, i2, l1, l2)) + break; + if (kind > 67) + kind = 67; + jjstateSet[jjnewStateCnt++] = 61; + break; + case 63: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(63, 60); + break; + case 84: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(25, 27); + break; + case 106: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(106, 107); + break; + case 108: + if (!jjCanMove_3(hiByte, i1, i2, l1, l2)) + break; + if (kind > 75) + kind = 75; + jjstateSet[jjnewStateCnt++] = 108; + break; + case 109: + if (!jjCanMove_3(hiByte, i1, i2, l1, l2)) + break; + if (kind > 77) + kind = 77; + jjCheckNAdd(109); + break; + case 111: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(111, 107); + break; + case 112: + if (!jjCanMove_3(hiByte, i1, i2, l1, l2)) + break; + if (kind > 77) + kind = 77; + jjstateSet[jjnewStateCnt++] = 112; + break; + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 114 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +static final int[] jjnextStates = { + 16, 20, 21, 24, 25, 49, 50, 84, 85, 86, 65, 30, 1, 2, 4, 7, + 8, 24, 25, 30, 49, 50, 65, 54, 55, 84, 85, 86, 106, 107, 109, 9, + 10, 31, 32, 33, 34, 35, 36, 45, 52, 58, 62, 56, 57, 66, 67, 68, + 69, 70, 71, 80, 87, 88, 89, 90, 91, 92, 101, +}; +private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 0: + return ((jjbitVec2[i2] & l2) != 0L); + default : + if ((jjbitVec0[i1] & l1) != 0L) + return true; + return false; + } +} +private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 6: + return ((jjbitVec5[i2] & l2) != 0L); + case 11: + return ((jjbitVec6[i2] & l2) != 0L); + case 13: + return ((jjbitVec7[i2] & l2) != 0L); + case 14: + return ((jjbitVec8[i2] & l2) != 0L); + case 15: + return ((jjbitVec9[i2] & l2) != 0L); + default : + if ((jjbitVec3[i1] & l1) != 0L) + if ((jjbitVec4[i2] & l2) == 0L) + return false; + else + return true; + return false; + } +} +private static final boolean jjCanMove_2(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 0: + return ((jjbitVec11[i2] & l2) != 0L); + case 1: + return ((jjbitVec12[i2] & l2) != 0L); + case 2: + return ((jjbitVec13[i2] & l2) != 0L); + case 3: + return ((jjbitVec14[i2] & l2) != 0L); + case 4: + return ((jjbitVec15[i2] & l2) != 0L); + case 5: + return ((jjbitVec16[i2] & l2) != 0L); + case 6: + return ((jjbitVec17[i2] & l2) != 0L); + case 9: + return ((jjbitVec18[i2] & l2) != 0L); + case 10: + return ((jjbitVec19[i2] & l2) != 0L); + case 11: + return ((jjbitVec20[i2] & l2) != 0L); + case 12: + return ((jjbitVec21[i2] & l2) != 0L); + case 13: + return ((jjbitVec22[i2] & l2) != 0L); + case 14: + return ((jjbitVec23[i2] & l2) != 0L); + case 15: + return ((jjbitVec24[i2] & l2) != 0L); + case 16: + return ((jjbitVec25[i2] & l2) != 0L); + case 17: + return ((jjbitVec26[i2] & l2) != 0L); + case 30: + return ((jjbitVec27[i2] & l2) != 0L); + case 31: + return ((jjbitVec28[i2] & l2) != 0L); + case 33: + return ((jjbitVec29[i2] & l2) != 0L); + case 48: + return ((jjbitVec30[i2] & l2) != 0L); + case 49: + return ((jjbitVec31[i2] & l2) != 0L); + case 159: + return ((jjbitVec32[i2] & l2) != 0L); + case 215: + return ((jjbitVec33[i2] & l2) != 0L); + default : + if ((jjbitVec10[i1] & l1) != 0L) + return true; + return false; + } +} +private static final boolean jjCanMove_3(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 0: + return ((jjbitVec34[i2] & l2) != 0L); + case 1: + return ((jjbitVec12[i2] & l2) != 0L); + case 2: + return ((jjbitVec35[i2] & l2) != 0L); + case 3: + return ((jjbitVec36[i2] & l2) != 0L); + case 4: + return ((jjbitVec37[i2] & l2) != 0L); + case 5: + return ((jjbitVec38[i2] & l2) != 0L); + case 6: + return ((jjbitVec39[i2] & l2) != 0L); + case 9: + return ((jjbitVec40[i2] & l2) != 0L); + case 10: + return ((jjbitVec41[i2] & l2) != 0L); + case 11: + return ((jjbitVec42[i2] & l2) != 0L); + case 12: + return ((jjbitVec43[i2] & l2) != 0L); + case 13: + return ((jjbitVec44[i2] & l2) != 0L); + case 14: + return ((jjbitVec45[i2] & l2) != 0L); + case 15: + return ((jjbitVec46[i2] & l2) != 0L); + case 16: + return ((jjbitVec25[i2] & l2) != 0L); + case 17: + return ((jjbitVec26[i2] & l2) != 0L); + case 30: + return ((jjbitVec27[i2] & l2) != 0L); + case 31: + return ((jjbitVec28[i2] & l2) != 0L); + case 32: + return ((jjbitVec47[i2] & l2) != 0L); + case 33: + return ((jjbitVec29[i2] & l2) != 0L); + case 48: + return ((jjbitVec48[i2] & l2) != 0L); + case 49: + return ((jjbitVec31[i2] & l2) != 0L); + case 159: + return ((jjbitVec32[i2] & l2) != 0L); + case 215: + return ((jjbitVec33[i2] & l2) != 0L); + default : + if ((jjbitVec10[i1] & l1) != 0L) + return true; + return false; + } +} + +/** Token literal values. */ +public static final String[] jjstrLiteralImages = { +"", null, null, null, null, null, "\75", "\41\75", "\74", "\74\75", "\76\75", +"\76", "\52", "\54", "\73", "\173", "\175", "\50", "\51", "\133", "\135", null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, }; + +/** Lexer state names. */ +public static final String[] lexStateNames = { + "DEFAULT", +}; +static final long[] jjtoToken = { + 0xffffffffffffffc1L, 0x1fa1fL, +}; +static final long[] jjtoSkip = { + 0x3eL, 0x0L, +}; +static final long[] jjtoSpecial = { + 0x20L, 0x0L, +}; +protected SimpleCharStream input_stream; +private final int[] jjrounds = new int[114]; +private final int[] jjstateSet = new int[228]; +protected char curChar; +/** Constructor. */ +public SyntaxTreeBuilderTokenManager(SimpleCharStream stream){ + if (SimpleCharStream.staticFlag) + throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + input_stream = stream; +} + +/** Constructor. */ +public SyntaxTreeBuilderTokenManager(SimpleCharStream stream, int lexState){ + this(stream); + SwitchTo(lexState); +} + +/** Reinitialise parser. */ +public void ReInit(SimpleCharStream stream) +{ + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); +} +private void ReInitRounds() +{ + int i; + jjround = 0x80000001; + for (i = 114; i-- > 0;) + jjrounds[i] = 0x80000000; +} + +/** Reinitialise parser. */ +public void ReInit(SimpleCharStream stream, int lexState) +{ + ReInit(stream); + SwitchTo(lexState); +} + +/** Switch to specified lex state. */ +public void SwitchTo(int lexState) +{ + if (lexState >= 1 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; +} + +protected Token jjFillToken() +{ + final Token t; + final String curTokenImage; + final int beginLine; + final int endLine; + final int beginColumn; + final int endColumn; + String im = jjstrLiteralImages[jjmatchedKind]; + curTokenImage = (im == null) ? input_stream.GetImage() : im; + beginLine = input_stream.getBeginLine(); + beginColumn = input_stream.getBeginColumn(); + endLine = input_stream.getEndLine(); + endColumn = input_stream.getEndColumn(); + t = Token.newToken(jjmatchedKind, curTokenImage); + + t.beginLine = beginLine; + t.endLine = endLine; + t.beginColumn = beginColumn; + t.endColumn = endColumn; + + return t; +} + +int curLexState = 0; +int defaultLexState = 0; +int jjnewStateCnt; +int jjround; +int jjmatchedPos; +int jjmatchedKind; + +/** Get the next Token. */ +public Token getNextToken() +{ + Token specialToken = null; + Token matchedToken; + int curPos = 0; + + EOFLoop : + for (;;) + { + try + { + curChar = input_stream.BeginToken(); + } + catch(java.io.IOException e) + { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + matchedToken.specialToken = specialToken; + return matchedToken; + } + + try { input_stream.backup(0); + while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) + curChar = input_stream.BeginToken(); + } + catch (java.io.IOException e1) { continue EOFLoop; } + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + if (jjmatchedKind != 0x7fffffff) + { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + matchedToken = jjFillToken(); + matchedToken.specialToken = specialToken; + return matchedToken; + } + else + { + if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + matchedToken = jjFillToken(); + if (specialToken == null) + specialToken = matchedToken; + else + { + matchedToken.specialToken = specialToken; + specialToken = (specialToken.next = matchedToken); + } + } + continue EOFLoop; + } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { input_stream.readChar(); input_stream.backup(1); } + catch (java.io.IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } + else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } +} + +private void jjCheckNAdd(int state) +{ + if (jjrounds[state] != jjround) + { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } +} +private void jjAddStates(int start, int end) +{ + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); +} +private void jjCheckNAddTwoStates(int state1, int state2) +{ + jjCheckNAdd(state1); + jjCheckNAdd(state2); +} + +private void jjCheckNAddStates(int start, int end) +{ + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); +} + +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderTreeConstants.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderTreeConstants.java new file mode 100644 index 00000000000..756447e14c8 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderTreeConstants.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JavaCC: Do not edit this line. SyntaxTreeBuilderTreeConstants.java Version 5.0 */ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public interface SyntaxTreeBuilderTreeConstants +{ + public int JJTQUERYCONTAINER = 0; + public int JJTVOID = 1; + public int JJTNAMESPACEDECL = 2; + public int JJTTUPLEUNION = 3; + public int JJTTUPLEMINUS = 4; + public int JJTTUPLEINTERSECT = 5; + public int JJTGRAPHUNION = 6; + public int JJTGRAPHMINUS = 7; + public int JJTGRAPHINTERSECT = 8; + public int JJTSELECTQUERY = 9; + public int JJTSELECT = 10; + public int JJTPROJECTIONELEM = 11; + public int JJTCONSTRUCTQUERY = 12; + public int JJTCONSTRUCT = 13; + public int JJTQUERYBODY = 14; + public int JJTFROM = 15; + public int JJTWHERE = 16; + public int JJTORDERBY = 17; + public int JJTLIMIT = 18; + public int JJTOFFSET = 19; + public int JJTPATHEXPRLIST = 20; + public int JJTPATHEXPRUNION = 21; + public int JJTBASICPATHEXPR = 22; + public int JJTOPTPATHEXPR = 23; + public int JJTBASICPATHEXPRTAIL = 24; + public int JJTOPTPATHEXPRTAIL = 25; + public int JJTEDGE = 26; + public int JJTNODE = 27; + public int JJTNODEELEM = 28; + public int JJTREIFIEDSTAT = 29; + public int JJTORDEREXPR = 30; + public int JJTOR = 31; + public int JJTAND = 32; + public int JJTBOOLEANCONSTANT = 33; + public int JJTNOT = 34; + public int JJTBOUND = 35; + public int JJTSAMETERM = 36; + public int JJTISRESOURCE = 37; + public int JJTISLITERAL = 38; + public int JJTISURI = 39; + public int JJTISBNODE = 40; + public int JJTLANGMATCHES = 41; + public int JJTREGEX = 42; + public int JJTEXISTS = 43; + public int JJTCOMPARE = 44; + public int JJTCOMPAREANY = 45; + public int JJTCOMPAREALL = 46; + public int JJTLIKE = 47; + public int JJTIN = 48; + public int JJTINLIST = 49; + public int JJTCOMPOPERATOR = 50; + public int JJTVAR = 51; + public int JJTDATATYPE = 52; + public int JJTLANG = 53; + public int JJTLABEL = 54; + public int JJTNAMESPACE = 55; + public int JJTLOCALNAME = 56; + public int JJTSTR = 57; + public int JJTFUNCTIONCALL = 58; + public int JJTARGLIST = 59; + public int JJTURI = 60; + public int JJTQNAME = 61; + public int JJTBNODE = 62; + public int JJTLITERAL = 63; + public int JJTSTRING = 64; + public int JJTNULL = 65; + + + public String[] jjtNodeName = { + "QueryContainer", + "void", + "NamespaceDecl", + "TupleUnion", + "TupleMinus", + "TupleIntersect", + "GraphUnion", + "GraphMinus", + "GraphIntersect", + "SelectQuery", + "Select", + "ProjectionElem", + "ConstructQuery", + "Construct", + "QueryBody", + "From", + "Where", + "OrderBy", + "Limit", + "Offset", + "PathExprList", + "PathExprUnion", + "BasicPathExpr", + "OptPathExpr", + "BasicPathExprTail", + "OptPathExprTail", + "Edge", + "Node", + "NodeElem", + "ReifiedStat", + "OrderExpr", + "Or", + "And", + "BooleanConstant", + "Not", + "Bound", + "SameTerm", + "IsResource", + "IsLiteral", + "IsURI", + "IsBNode", + "LangMatches", + "Regex", + "Exists", + "Compare", + "CompareAny", + "CompareAll", + "Like", + "In", + "InList", + "CompOperator", + "Var", + "Datatype", + "Lang", + "Label", + "Namespace", + "LocalName", + "Str", + "FunctionCall", + "ArgList", + "URI", + "QName", + "BNode", + "Literal", + "String", + "Null", + }; +} +/* JavaCC - OriginalChecksum=57351b205d67e913125abf0f7b92feda (do not edit this line) */ diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderVisitor.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderVisitor.java new file mode 100644 index 00000000000..dc8caf233f1 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/SyntaxTreeBuilderVisitor.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JavaCC: Do not edit this line. SyntaxTreeBuilderVisitor.java Version 5.0 */ +package org.eclipse.rdf4j.query.parser.serql.ast; + +public interface SyntaxTreeBuilderVisitor +{ + public Object visit(SimpleNode node, Object data) throws VisitorException; + public Object visit(ASTQueryContainer node, Object data) throws VisitorException; + public Object visit(ASTNamespaceDecl node, Object data) throws VisitorException; + public Object visit(ASTTupleUnion node, Object data) throws VisitorException; + public Object visit(ASTTupleMinus node, Object data) throws VisitorException; + public Object visit(ASTTupleIntersect node, Object data) throws VisitorException; + public Object visit(ASTGraphUnion node, Object data) throws VisitorException; + public Object visit(ASTGraphMinus node, Object data) throws VisitorException; + public Object visit(ASTGraphIntersect node, Object data) throws VisitorException; + public Object visit(ASTSelectQuery node, Object data) throws VisitorException; + public Object visit(ASTSelect node, Object data) throws VisitorException; + public Object visit(ASTProjectionElem node, Object data) throws VisitorException; + public Object visit(ASTConstructQuery node, Object data) throws VisitorException; + public Object visit(ASTConstruct node, Object data) throws VisitorException; + public Object visit(ASTQueryBody node, Object data) throws VisitorException; + public Object visit(ASTFrom node, Object data) throws VisitorException; + public Object visit(ASTWhere node, Object data) throws VisitorException; + public Object visit(ASTOrderBy node, Object data) throws VisitorException; + public Object visit(ASTLimit node, Object data) throws VisitorException; + public Object visit(ASTOffset node, Object data) throws VisitorException; + public Object visit(ASTPathExprList node, Object data) throws VisitorException; + public Object visit(ASTPathExprUnion node, Object data) throws VisitorException; + public Object visit(ASTBasicPathExpr node, Object data) throws VisitorException; + public Object visit(ASTOptPathExpr node, Object data) throws VisitorException; + public Object visit(ASTBasicPathExprTail node, Object data) throws VisitorException; + public Object visit(ASTOptPathExprTail node, Object data) throws VisitorException; + public Object visit(ASTEdge node, Object data) throws VisitorException; + public Object visit(ASTNode node, Object data) throws VisitorException; + public Object visit(ASTNodeElem node, Object data) throws VisitorException; + public Object visit(ASTReifiedStat node, Object data) throws VisitorException; + public Object visit(ASTOrderExpr node, Object data) throws VisitorException; + public Object visit(ASTOr node, Object data) throws VisitorException; + public Object visit(ASTAnd node, Object data) throws VisitorException; + public Object visit(ASTBooleanConstant node, Object data) throws VisitorException; + public Object visit(ASTNot node, Object data) throws VisitorException; + public Object visit(ASTBound node, Object data) throws VisitorException; + public Object visit(ASTSameTerm node, Object data) throws VisitorException; + public Object visit(ASTIsResource node, Object data) throws VisitorException; + public Object visit(ASTIsLiteral node, Object data) throws VisitorException; + public Object visit(ASTIsURI node, Object data) throws VisitorException; + public Object visit(ASTIsBNode node, Object data) throws VisitorException; + public Object visit(ASTLangMatches node, Object data) throws VisitorException; + public Object visit(ASTRegex node, Object data) throws VisitorException; + public Object visit(ASTExists node, Object data) throws VisitorException; + public Object visit(ASTCompare node, Object data) throws VisitorException; + public Object visit(ASTCompareAny node, Object data) throws VisitorException; + public Object visit(ASTCompareAll node, Object data) throws VisitorException; + public Object visit(ASTLike node, Object data) throws VisitorException; + public Object visit(ASTIn node, Object data) throws VisitorException; + public Object visit(ASTInList node, Object data) throws VisitorException; + public Object visit(ASTCompOperator node, Object data) throws VisitorException; + public Object visit(ASTVar node, Object data) throws VisitorException; + public Object visit(ASTDatatype node, Object data) throws VisitorException; + public Object visit(ASTLang node, Object data) throws VisitorException; + public Object visit(ASTLabel node, Object data) throws VisitorException; + public Object visit(ASTNamespace node, Object data) throws VisitorException; + public Object visit(ASTLocalName node, Object data) throws VisitorException; + public Object visit(ASTStr node, Object data) throws VisitorException; + public Object visit(ASTFunctionCall node, Object data) throws VisitorException; + public Object visit(ASTArgList node, Object data) throws VisitorException; + public Object visit(ASTURI node, Object data) throws VisitorException; + public Object visit(ASTQName node, Object data) throws VisitorException; + public Object visit(ASTBNode node, Object data) throws VisitorException; + public Object visit(ASTLiteral node, Object data) throws VisitorException; + public Object visit(ASTString node, Object data) throws VisitorException; + public Object visit(ASTNull node, Object data) throws VisitorException; +} +/* JavaCC - OriginalChecksum=10d665e0123e9d9d5fe36399a555e821 (do not edit this line) */ diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/Token.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/Token.java new file mode 100644 index 00000000000..6410f976527 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/Token.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */ +/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ +package org.eclipse.rdf4j.query.parser.serql.ast; + +/** + * Describes the input token stream. + */ + +public class Token implements java.io.Serializable { + + /** + * The version identifier for this Serializable class. + * Increment only if the serialized form of the + * class changes. + */ + private static final long serialVersionUID = 1L; + + /** + * An integer that describes the kind of this token. This numbering + * system is determined by JavaCCParser, and a table of these numbers is + * stored in the file ...Constants.java. + */ + public int kind; + + /** The line number of the first character of this Token. */ + public int beginLine; + /** The column number of the first character of this Token. */ + public int beginColumn; + /** The line number of the last character of this Token. */ + public int endLine; + /** The column number of the last character of this Token. */ + public int endColumn; + + /** + * The string image of the token. + */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input + * stream. If this is the last token from the input stream, or if the + * token manager has not read tokens beyond this one, this field is + * set to null. This is true only if this token is also a regular + * token. Otherwise, see below for a description of the contents of + * this field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this + * token, but after the immediately preceding regular (non-special) token. + * If there are no such special tokens, this field is set to null. + * When there are more than one such special token, this field refers + * to the last of these special tokens, which in turn refers to the next + * previous special token through its specialToken field, and so on + * until the first special token (whose specialToken field is null). + * The next fields of special tokens refer to other special tokens that + * immediately follow it (without an intervening regular token). If there + * is no such token, this field is null. + */ + public Token specialToken; + + /** + * An optional attribute value of the Token. + * Tokens which are not used as syntactic sugar will often contain + * meaningful values that will be used later on by the compiler or + * interpreter. This attribute value is often different from the image. + * Any subclass of Token that actually wants to return a non-null value can + * override this method as appropriate. + */ + public Object getValue() { + return null; + } + + /** + * No-argument constructor + */ + public Token() {} + + /** + * Constructs a new token for the specified Image. + */ + public Token(int kind) + { + this(kind, null); + } + + /** + * Constructs a new token for the specified Image and Kind. + */ + public Token(int kind, String image) + { + this.kind = kind; + this.image = image; + } + + /** + * Returns the image. + */ + public String toString() + { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you + * can create and return subclass objects based on the value of ofKind. + * Simply add the cases to the switch for all those special cases. + * For example, if you have a subclass of Token called IDToken that + * you want to create if ofKind is ID, simply add something like : + * + * case MyParserConstants.ID : return new IDToken(ofKind, image); + * + * to the following switch statement. Then you can cast matchedToken + * variable to the appropriate type and use sit in your lexical actions. + */ + public static Token newToken(int ofKind, String image) + { + switch(ofKind) + { + default : return new Token(ofKind, image); + } + } + + public static Token newToken(int ofKind) + { + return newToken(ofKind, null); + } + +} +/* JavaCC - OriginalChecksum=b755056119121fd27db68e1fd476a72d (do not edit this line) */ diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/TokenMgrError.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/TokenMgrError.java new file mode 100644 index 00000000000..9b906be54df --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/TokenMgrError.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */ +/* JavaCCOptions: */ +package org.eclipse.rdf4j.query.parser.serql.ast; + +/** Token Manager Error. */ +public class TokenMgrError extends Error +{ + + /** + * The version identifier for this Serializable class. + * Increment only if the serialized form of the + * class changes. + */ + private static final long serialVersionUID = 1L; + + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** + * Lexical error occurred. + */ + static final int LEXICAL_ERROR = 0; + + /** + * An attempt was made to create a second instance of a static token manager. + */ + static final int STATIC_LEXER_ERROR = 1; + + /** + * Tried to change to an invalid lexical state. + */ + static final int INVALID_LEXICAL_STATE = 2; + + /** + * Detected (and bailed out of) an infinite loop in the token manager. + */ + static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have + * one of the above 4 values. + */ + int errorCode; + + /** + * Replaces unprintable characters by their escaped (or unicode escaped) + * equivalents in the given string + */ + protected static final String addEscapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + + /** + * Returns a detailed message for the Error when it is thrown by the + * token manager to indicate a lexical error. + * Parameters : + * EOFSeen : indicates if EOF caused the lexical error + * curLexState : lexical state in which this error occurred + * errorLine : line number when the error occurred + * errorColumn : column number when the error occurred + * errorAfter : prefix that was seen before this error occurred + * curchar : the offending character + * Note: You can customize the lexical error message by modifying this method. + */ + protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { + return("Lexical error at line " + + errorLine + ", column " + + errorColumn + ". Encountered: " + + (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""); + } + + /** + * You can also modify the body of this method to customize your error messages. + * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not + * of end-users concern, so you can return something like : + * + * "Internal Error : Please file a bug report .... " + * + * from this method for such cases in the release version of your parser. + */ + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + /** No arg constructor. */ + public TokenMgrError() { + } + + /** Constructor with message and reason. */ + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + /** Full Constructor. */ + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { + this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } +} +/* JavaCC - OriginalChecksum=321b0b4e2101fe5bed4f60ea0e155e6d (do not edit this line) */ diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/VisitorException.java b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/VisitorException.java new file mode 100644 index 00000000000..b622bca80ee --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/VisitorException.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.serql.ast; + + +public class VisitorException extends Exception { + + private static final long serialVersionUID = 1998121176957145353L; + + public VisitorException() { + super(); + } + + public VisitorException(String msg) { + super(msg); + } + + public VisitorException(String msg, Throwable t) { + super(msg, t); + } + + public VisitorException(Throwable t) { + super(t); + } +} diff --git a/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/serql.jjt b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/serql.jjt new file mode 100644 index 00000000000..f5ca6b7f858 --- /dev/null +++ b/core/queryparser/serql/src/main/java/org/eclipse/rdf4j/query/parser/serql/ast/serql.jjt @@ -0,0 +1,916 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +/* + * SeRQL JJTree input file for JavaCC, a Java Compiler Compiler. JavaCC can be + * downloaded from https://javacc.dev.java.net/ + */ + +options { + MULTI=true; + VISITOR=true; + VISITOR_EXCEPTION="VisitorException"; + STATIC=false; + IGNORE_CASE=true; + UNICODE_INPUT=true; +} + +PARSER_BEGIN(SyntaxTreeBuilder) + +package org.openrdf.query.parser.serql.ast; + +import java.io.StringReader; + +import org.openrdf.query.algebra.Compare.CompareOp; +import org.openrdf.model.vocabulary.XMLSchema; + +public class SyntaxTreeBuilder { + + /** + * Parses the supplied SeRQL query and builds a syntax tree from it. + * + * @param query A SeRQL query string. + * @return The root of the syntax tree. + * @throws TokenMgrError If the query was syntactically incorrect. + * @throws ParseException If the query was syntactically incorrect. + */ + public static ASTQueryContainer parseQuery(String query) + throws TokenMgrError, ParseException + { + SyntaxTreeBuilder stb = new SyntaxTreeBuilder( new StringReader(query) ); + return stb.QueryContainer(); + } + + /** + * Trims the first and last character from the supplied string. + */ + private static String _trimString(String s) { + if (s.length() >= 2) { + s = s.substring(1, s.length() - 1); + } + return s; + } +} + +PARSER_END(SyntaxTreeBuilder) + +SKIP : +{ + " " +| "\t" +| "\n" +| "\r" +} + +SPECIAL_TOKEN : +{ + +} + +// Comparison operators +TOKEN : +{ + +| ="> +| "> +} + +// Special characters +TOKEN : +{ + +| +| +| +| +| +| +| +| +} + +// Keywords +TOKEN : +{ + +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +} + +// Values +TOKEN : +{ + "@" > +| "^^" (|)> +| |)* "\""> +| <#SAFE_CHAR: (~["\"", "\\"])> +| <#ESCAPED_CHAR: ("\\\\"|"\\\""|"\\\n"|"\\\r"|"\\\t"|)> +| <#UNICODE_ESC: ("\\u" | "\\U" )> + +| <#LANG_TAG: ()+ ("-" (|)+)*> + +| ":" (~["<", ">", "\"", "{", "}", "|", "^", "`", "\\", "\u0000"-"\u0020"])+ ">"> +| <#SCHEME: (||"+"|"-"|".")*> + +| ":" ()*> + +| > + +| ()* | "_" ()+ )> + +| )+> +| )+> +| )* "." ()+> + +| <#HEX: (["A"-"F", "a"-"f"] | )> +| <#ALPHA: ["a"-"z", "A"-"Z"]> +| <#NUM: ["0"-"9"]> + +// Definition of XML's NCName, see http://www.w3.org/TR/REC-xml-names/#NT-NCName +| <#NCNAME: (|"_") ()*> +| <#NCNAME_CHAR: (||"."|"-"|"_"||)> +| <#LETTER: (|)> +| <#BASECHAR: + ["\u0041"-"\u005A"] | ["\u0061"-"\u007A"] | ["\u00C0"-"\u00D6"] | ["\u00D8"-"\u00F6"] | ["\u00F8"-"\u00FF"] + | ["\u0100"-"\u0131"] | ["\u0134"-"\u013E"] | ["\u0141"-"\u0148"] | ["\u014A"-"\u017E"] + | ["\u0180"-"\u01C3"] | ["\u01CD"-"\u01F0"] | ["\u01F4"-"\u01F5"] | ["\u01FA"-"\u0217"] + | ["\u0250"-"\u02A8"] | ["\u02BB"-"\u02C1"] | "\u0386" | ["\u0388"-"\u038A"] | "\u038C" + | ["\u038E"-"\u03A1"] | ["\u03A3"-"\u03CE"] | ["\u03D0"-"\u03D6"] | "\u03DA" | "\u03DC" | "\u03DE" + | "\u03E0" | ["\u03E2"-"\u03F3"] | ["\u0401"-"\u040C"] | ["\u040E"-"\u044F"] | ["\u0451"-"\u045C"] + | ["\u045E"-"\u0481"] | ["\u0490"-"\u04C4"] | ["\u04C7"-"\u04C8"] | ["\u04CB"-"\u04CC"] + | ["\u04D0"-"\u04EB"] | ["\u04EE"-"\u04F5"] | ["\u04F8"-"\u04F9"] | ["\u0531"-"\u0556"] | "\u0559" + | ["\u0561"-"\u0586"] | ["\u05D0"-"\u05EA"] | ["\u05F0"-"\u05F2"] | ["\u0621"-"\u063A"] + | ["\u0641"-"\u064A"] | ["\u0671"-"\u06B7"] | ["\u06BA"-"\u06BE"] | ["\u06C0"-"\u06CE"] + | ["\u06D0"-"\u06D3"] | "\u06D5" | ["\u06E5"-"\u06E6"] | ["\u0905"-"\u0939"] | "\u093D" + | ["\u0958"-"\u0961"] | ["\u0985"-"\u098C"] | ["\u098F"-"\u0990"] | ["\u0993"-"\u09A8"] + | ["\u09AA"-"\u09B0"] | "\u09B2" | ["\u09B6"-"\u09B9"] | ["\u09DC"-"\u09DD"] | ["\u09DF"-"\u09E1"] + | ["\u09F0"-"\u09F1"] | ["\u0A05"-"\u0A0A"] | ["\u0A0F"-"\u0A10"] | ["\u0A13"-"\u0A28"] + | ["\u0A2A"-"\u0A30"] | ["\u0A32"-"\u0A33"] | ["\u0A35"-"\u0A36"] | ["\u0A38"-"\u0A39"] + | ["\u0A59"-"\u0A5C"] | "\u0A5E" | ["\u0A72"-"\u0A74"] | ["\u0A85"-"\u0A8B"] | "\u0A8D" + | ["\u0A8F"-"\u0A91"] | ["\u0A93"-"\u0AA8"] | ["\u0AAA"-"\u0AB0"] | ["\u0AB2"-"\u0AB3"] + | ["\u0AB5"-"\u0AB9"] | "\u0ABD" | "\u0AE0" | ["\u0B05"-"\u0B0C"] | ["\u0B0F"-"\u0B10"] + | ["\u0B13"-"\u0B28"] | ["\u0B2A"-"\u0B30"] | ["\u0B32"-"\u0B33"] | ["\u0B36"-"\u0B39"] | "\u0B3D" + | ["\u0B5C"-"\u0B5D"] | ["\u0B5F"-"\u0B61"] | ["\u0B85"-"\u0B8A"] | ["\u0B8E"-"\u0B90"] + | ["\u0B92"-"\u0B95"] | ["\u0B99"-"\u0B9A"] | "\u0B9C" | ["\u0B9E"-"\u0B9F"] | ["\u0BA3"-"\u0BA4"] + | ["\u0BA8"-"\u0BAA"] | ["\u0BAE"-"\u0BB5"] | ["\u0BB7"-"\u0BB9"] | ["\u0C05"-"\u0C0C"] + | ["\u0C0E"-"\u0C10"] | ["\u0C12"-"\u0C28"] | ["\u0C2A"-"\u0C33"] | ["\u0C35"-"\u0C39"] + | ["\u0C60"-"\u0C61"] | ["\u0C85"-"\u0C8C"] | ["\u0C8E"-"\u0C90"] | ["\u0C92"-"\u0CA8"] + | ["\u0CAA"-"\u0CB3"] | ["\u0CB5"-"\u0CB9"] | "\u0CDE" | ["\u0CE0"-"\u0CE1"] | ["\u0D05"-"\u0D0C"] + | ["\u0D0E"-"\u0D10"] | ["\u0D12"-"\u0D28"] | ["\u0D2A"-"\u0D39"] | ["\u0D60"-"\u0D61"] + | ["\u0E01"-"\u0E2E"] | "\u0E30" | ["\u0E32"-"\u0E33"] | ["\u0E40"-"\u0E45"] | ["\u0E81"-"\u0E82"] + | "\u0E84" | ["\u0E87"-"\u0E88"] | "\u0E8A" | "\u0E8D" | ["\u0E94"-"\u0E97"] | ["\u0E99"-"\u0E9F"] + | ["\u0EA1"-"\u0EA3"] | "\u0EA5" | "\u0EA7" | ["\u0EAA"-"\u0EAB"] | ["\u0EAD"-"\u0EAE"] | "\u0EB0" + | ["\u0EB2"-"\u0EB3"] | "\u0EBD" | ["\u0EC0"-"\u0EC4"] | ["\u0F40"-"\u0F47"] | ["\u0F49"-"\u0F69"] + | ["\u10A0"-"\u10C5"] | ["\u10D0"-"\u10F6"] | "\u1100" | ["\u1102"-"\u1103"] | ["\u1105"-"\u1107"] + | "\u1109" | ["\u110B"-"\u110C"] | ["\u110E"-"\u1112"] | "\u113C" | "\u113E" | "\u1140" | "\u114C" + | "\u114E" | "\u1150" | ["\u1154"-"\u1155"] | "\u1159" | ["\u115F"-"\u1161"] | "\u1163" | "\u1165" + | "\u1167" | "\u1169" | ["\u116D"-"\u116E"] | ["\u1172"-"\u1173"] | "\u1175" | "\u119E" | "\u11A8" + | "\u11AB" | ["\u11AE"-"\u11AF"] | ["\u11B7"-"\u11B8"] | "\u11BA" | ["\u11BC"-"\u11C2"] | "\u11EB" + | "\u11F0" | "\u11F9" | ["\u1E00"-"\u1E9B"] | ["\u1EA0"-"\u1EF9"] | ["\u1F00"-"\u1F15"] + | ["\u1F18"-"\u1F1D"] | ["\u1F20"-"\u1F45"] | ["\u1F48"-"\u1F4D"] | ["\u1F50"-"\u1F57"] | "\u1F59" + | "\u1F5B" | "\u1F5D" | ["\u1F5F"-"\u1F7D"] | ["\u1F80"-"\u1FB4"] | ["\u1FB6"-"\u1FBC"] | "\u1FBE" + | ["\u1FC2"-"\u1FC4"] | ["\u1FC6"-"\u1FCC"] | ["\u1FD0"-"\u1FD3"] | ["\u1FD6"-"\u1FDB"] + | ["\u1FE0"-"\u1FEC"] | ["\u1FF2"-"\u1FF4"] | ["\u1FF6"-"\u1FFC"] | "\u2126" | ["\u212A"-"\u212B"] + | "\u212E" | ["\u2180"-"\u2182"] | ["\u3041"-"\u3094"] | ["\u30A1"-"\u30FA"] | ["\u3105"-"\u312C"] + | ["\uAC00"-"\uD7A3"]> +| <#IDEOGRAPHIC: ["\u4E00"-"\u9FA5"] | "\u3007" | ["\u3021"-"\u3029"]> +| <#COMBINING_CHAR: + ["\u0300"-"\u0345"] | ["\u0360"-"\u0361"] | ["\u0483"-"\u0486"] | ["\u0591"-"\u05A1"] | ["\u05A3"-"\u05B9"] + | ["\u05BB"-"\u05BD"] | "\u05BF" | ["\u05C1"-"\u05C2"] | "\u05C4" | ["\u064B"-"\u0652"] | "\u0670" + | ["\u06D6"-"\u06DC"] | ["\u06DD"-"\u06DF"] | ["\u06E0"-"\u06E4"] | ["\u06E7"-"\u06E8"] + | ["\u06EA"-"\u06ED"] | ["\u0901"-"\u0903"] | "\u093C" | ["\u093E"-"\u094C"] | "\u094D" + | ["\u0951"-"\u0954"] | ["\u0962"-"\u0963"] | ["\u0981"-"\u0983"] | "\u09BC" | "\u09BE" | "\u09BF" + | ["\u09C0"-"\u09C4"] | ["\u09C7"-"\u09C8"] | ["\u09CB"-"\u09CD"] | "\u09D7" | ["\u09E2"-"\u09E3"] + | "\u0A02" | "\u0A3C" | "\u0A3E" | "\u0A3F" | ["\u0A40"-"\u0A42"] | ["\u0A47"-"\u0A48"] + | ["\u0A4B"-"\u0A4D"] | ["\u0A70"-"\u0A71"] | ["\u0A81"-"\u0A83"] | "\u0ABC" | ["\u0ABE"-"\u0AC5"] + | ["\u0AC7"-"\u0AC9"] | ["\u0ACB"-"\u0ACD"] | ["\u0B01"-"\u0B03"] | "\u0B3C" | ["\u0B3E"-"\u0B43"] + | ["\u0B47"-"\u0B48"] | ["\u0B4B"-"\u0B4D"] | ["\u0B56"-"\u0B57"] | ["\u0B82"-"\u0B83"] + | ["\u0BBE"-"\u0BC2"] | ["\u0BC6"-"\u0BC8"] | ["\u0BCA"-"\u0BCD"] | "\u0BD7" | ["\u0C01"-"\u0C03"] + | ["\u0C3E"-"\u0C44"] | ["\u0C46"-"\u0C48"] | ["\u0C4A"-"\u0C4D"] | ["\u0C55"-"\u0C56"] + | ["\u0C82"-"\u0C83"] | ["\u0CBE"-"\u0CC4"] | ["\u0CC6"-"\u0CC8"] | ["\u0CCA"-"\u0CCD"] + | ["\u0CD5"-"\u0CD6"] | ["\u0D02"-"\u0D03"] | ["\u0D3E"-"\u0D43"] | ["\u0D46"-"\u0D48"] + | ["\u0D4A"-"\u0D4D"] | "\u0D57" | "\u0E31" | ["\u0E34"-"\u0E3A"] | ["\u0E47"-"\u0E4E"] | "\u0EB1" + | ["\u0EB4"-"\u0EB9"] | ["\u0EBB"-"\u0EBC"] | ["\u0EC8"-"\u0ECD"] | ["\u0F18"-"\u0F19"] | "\u0F35" + | "\u0F37" | "\u0F39" | "\u0F3E" | "\u0F3F" | ["\u0F71"-"\u0F84"] | ["\u0F86"-"\u0F8B"] + | ["\u0F90"-"\u0F95"] | "\u0F97" | ["\u0F99"-"\u0FAD"] | ["\u0FB1"-"\u0FB7"] | "\u0FB9" + | ["\u20D0"-"\u20DC"] | "\u20E1" | ["\u302A"-"\u302F"] | "\u3099" | "\u309A"> +| <#DIGIT: + ["\u0030"-"\u0039"] | ["\u0660"-"\u0669"] | ["\u06F0"-"\u06F9"] | ["\u0966"-"\u096F"] | ["\u09E6"-"\u09EF"] + | ["\u0A66"-"\u0A6F"] | ["\u0AE6"-"\u0AEF"] | ["\u0B66"-"\u0B6F"] | ["\u0BE7"-"\u0BEF"] + | ["\u0C66"-"\u0C6F"] | ["\u0CE6"-"\u0CEF"] | ["\u0D66"-"\u0D6F"] | ["\u0E50"-"\u0E59"] + | ["\u0ED0"-"\u0ED9"] | ["\u0F20"-"\u0F29"]> +| <#EXTENDER: + "\u00B7" | "\u02D0" | "\u02D1" | "\u0387" | "\u0640" | "\u0E46" | "\u0EC6" | "\u3005" | ["\u3031"-"\u3035"] + | ["\u309D"-"\u309E"] | ["\u30FC"-"\u30FE"]> +} + +ASTQueryContainer QueryContainer() : +{} +{ + Query() [ NamespaceDeclList() ] + { return jjtThis; } +} + +void NamespaceDeclList() #void : +{} +{ + NamespaceDecl() ( NamespaceDecl() )* +} + +void NamespaceDecl() : +{ Token prefix; } +{ + prefix = URI() + { jjtThis.setPrefix(prefix.image); } +} + +void Query() #void : +{} +{ + LOOKAHEAD( ()* + + [ + {jjtThis.setDistinct(true);} + | + {jjtThis.setReduced(true);} + ] + + ( + {jjtThis.setWildcard(true);} + | + [ ProjectionElem() ( ProjectionElem() )* ] + ) +} + +void ProjectionElem() : +{} +{ + ValueExprOrNull() [ ( String() | Var() ) ] +} + +void ConstructQuery() : +{} +{ + Construct() [ QueryBody() [ OrderBy() ] [ Limit() ] [ Offset() ] ] +} + +void Construct() : +{} +{ + + + [ + {jjtThis.setDistinct(true);} + | + {jjtThis.setReduced(true);} + ] + + ( + {jjtThis.setWildcard(true);} + | + PathExprList() + ) +} + +void QueryBody() : +{} +{ + ( From() )+ [ Where() ] +} + +void From() : +{} +{ + [ ContextID() ] PathExprList() +} + +void Where() : +{} +{ + BooleanExpr() +} + +void OrderBy() : +{ int limit; } +{ + OrderExprList() +} + +void Limit() : +{ int limit; } +{ + limit = PosInteger() + { jjtThis.setValue(limit); } +} + +void Offset() : +{ int offset; } +{ + offset = PosInteger() + { jjtThis.setValue(offset); } +} + +void ContextID() #void : +{} +{ + Var() | URIRef() | BNode() +} + +void PathExprList() #void : +{} +{ + ( + UnionPathExpr() ( UnionPathExpr() )* + ) #PathExprList(>1) +} + +void UnionPathExpr() #void : +{} +{ + ( + PathExpr() + ( + // Only when followed by an OptPathExpr or Node (and not a select or construct) + LOOKAHEAD( ()* (|) ) + PathExpr() + )* + ) #PathExprUnion(>1) +} + +void PathExpr() #void : +{} +{ + BasicPathExpr() +| + OptPathExpr() +| + PathExprList() +} + +void BasicPathExpr() : +{} +{ + Node() BasicPathExprTail() +} + +void OptPathExpr() : +{} +{ + PathExprList() [ Where() ] +} + +void PathExprCont() #void : {} +{ + PathExprBranch() +| + PathExprTail() +} + +void PathExprBranch() #void : +{ ASTPathExprTail tail; } +{ + tail = PathExprTail() + { tail.setBranch(true); } +} + +ASTPathExprTail PathExprTail() #void : +{ ASTPathExprTail result; } +{ + ( + result = BasicPathExprTail() + | + result = OptPathExprTail() + ) + + { return result; } +} + +ASTPathExprTail BasicPathExprTail() : +{} +{ + Edge() Node() [ PathExprCont() ] + { return jjtThis; } +} + +ASTPathExprTail OptPathExprTail() : +{} +{ + BasicPathExprTail() [ Where() ] [ PathExprBranch() ] + { return jjtThis; } +} + +void Edge() : +{} +{ + Var() | URIRef() +} + +void Node() : +{} +{ + [ NodeElem() ( NodeElem() )* ] +} + +void NodeElem() : +{} +{ + Var() | Value() | ReifiedStat() +} + +void ReifiedStat() : +{} +{ + [ NodeElem() ] + Edge() + [ NodeElem() ] +} + +void OrderExprList() #void : +{} +{ + OrderExpr() ( OrderExpr() )* +} + +void OrderExpr() : +{} +{ + ValueExpr() + + [ + + | + {jjtThis.setAscending(false);} + ] +} + +void BooleanExpr() #void : +{} +{ + Or() +} + +void Or() #void : +{} +{ + ( + And() ( And() )* + ) #Or(>1) +} + +void And() #void : +{} +{ + ( + BooleanElem() ( BooleanElem() )* + ) #And(>1) +} + +void BooleanElem() #void : +{} +{ + BooleanExpr() +| BooleanConstant() +| Not() +| Bound() +| SameTerm() +| IsResource() +| IsLiteral() +| IsURI() +| IsBNode() +| LangMatches() +| Regex() +| Exists() +| BooleanValueOp() +} + +void BooleanConstant() : +{} +{ + {jjtThis.setValue(true);} +| + {jjtThis.setValue(false);} +} + +void Not() : +{} +{ + BooleanElem() +} + +void Bound(): +{} +{ + Var() +} + +void SameTerm(): +{} +{ + ValueExpr() ValueExpr() +} + +void IsResource() : +{} +{ + Var() +} + +void IsLiteral() : +{} +{ + Var() +} + +void IsURI() : +{} +{ + Var() +} + +void IsBNode() : +{} +{ + Var() +} + +void LangMatches() : +{} +{ + ValueExpr() ValueExpr() +} + +void Regex() : +{} +{ + ValueExpr() ValueExpr() [ ValueExpr() ] +} + +void Exists() : +{} +{ + TupleQuerySet() +} + +void BooleanValueOp() #void : +{} +{ + ValueExprOrNull() + + ( + CompOperator() + ( + ValueExprOrNull() #Compare(3) + | TupleQuerySet() #CompareAny(3) + | TupleQuerySet() #CompareAll(3) + ) + | + String() [ { jjtThis.setIgnoreCase(true); } ] #Like(2) + | + + ( + TupleQuerySet() #In(2) + | ArgList() #InList(2) + ) + + ) +} + +void CompOperator() : +{} +{ + { jjtThis.setValue(CompareOp.EQ); } +| { jjtThis.setValue(CompareOp.NE); } +| { jjtThis.setValue(CompareOp.LT); } +| { jjtThis.setValue(CompareOp.LE); } +| { jjtThis.setValue(CompareOp.GE); } +| { jjtThis.setValue(CompareOp.GT); } +} + +// For backwards compatibility; NULL will be phased out, use BOUND instead +void ValueExprOrNull() #void : +{} +{ + ValueExpr() +| Null() +} + +void ValueExpr() #void : +{} +{ + Var() +| Datatype() +| Lang() +| Label() +| Namespace() +| LocalName() +| Str() +| LOOKAHEAD(2) FunctionCall() +| Value() +} + +void Var(): +{ Token t; } +{ + t = + { jjtThis.setName(t.image); } +} + +void Datatype(): +{} +{ + Var() +} + +void Lang(): +{} +{ + Var() +} + +void Label(): +{} +{ +