From 9a7a272f04e54537aaf30c282598c1742fe0ad88 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Wed, 2 Dec 2020 01:21:38 +0100 Subject: [PATCH] Continued: - REFACTURING: added more traits from monolithic BaseFrameworkSystem class MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Roland Häder --- .../classes/class_BaseFrameworkSystem.php | 75 ------------------- .../handler/tasks/class_TaskHandler.php | 4 + .../main/classes/index/class_BaseIndex.php | 4 + .../main/classes/lists/class_BaseList.php | 52 +++++++------ .../classes/registry/class_BaseRegistry.php | 9 +-- .../stacker/file/class_BaseFileStack.php | 4 + .../main/interfaces/lists/class_Listable.php | 8 +- .../traits/iterator/class_IteratorTrait.php | 55 ++++++++++++++ .../stream/input/class_InputStreamTrait.php | 55 ++++++++++++++ .../stream/output/class_OutputStreamTrait.php | 55 ++++++++++++++ 10 files changed, 213 insertions(+), 108 deletions(-) create mode 100644 framework/main/traits/iterator/class_IteratorTrait.php create mode 100644 framework/main/traits/stream/input/class_InputStreamTrait.php create mode 100644 framework/main/traits/stream/output/class_OutputStreamTrait.php diff --git a/framework/main/classes/class_BaseFrameworkSystem.php b/framework/main/classes/class_BaseFrameworkSystem.php index 7195861e..15a9f5fb 100644 --- a/framework/main/classes/class_BaseFrameworkSystem.php +++ b/framework/main/classes/class_BaseFrameworkSystem.php @@ -19,15 +19,12 @@ use Org\Mxchange\CoreFramework\Middleware\Debug\DebugMiddleware; use Org\Mxchange\CoreFramework\Registry\GenericRegistry; use Org\Mxchange\CoreFramework\Result\Database\CachedDatabaseResult; use Org\Mxchange\CoreFramework\State\Stateable; -use Org\Mxchange\CoreFramework\Stream\Input\InputStream; use Org\Mxchange\CoreFramework\Stream\Output\OutputStreamer; -use Org\Mxchange\CoreFramework\Stream\Output\OutputStream; use Org\Mxchange\CoreFramework\Utils\String\StringUtils; // Import SPL stuff use \stdClass; use \InvalidArgumentException; -use \Iterator; use \ReflectionClass; use \SplFileInfo; @@ -70,21 +67,6 @@ abstract class BaseFrameworkSystem extends stdClass implements FrameworkInterfac */ private $realClass = __CLASS__; - /** - * Instance of an Iterator class - */ - private $iteratorInstance = NULL; - - /** - * An instance of a InputStream class - */ - private $inputStreamInstance = NULL; - - /** - * An instance of a OutputStream class - */ - private $outputStreamInstance = NULL; - /** * An instance of a database wrapper class */ @@ -475,63 +457,6 @@ abstract class BaseFrameworkSystem extends stdClass implements FrameworkInterfac return $this->wrapperInstance; } - /** - * Getter for a InputStream instance - * - * @param $inputStreamInstance The InputStream instance - */ - protected final function getInputStreamInstance () { - return $this->inputStreamInstance; - } - - /** - * Setter for a InputStream instance - * - * @param $inputStreamInstance The InputStream instance - * @return void - */ - protected final function setInputStreamInstance (InputStream $inputStreamInstance) { - $this->inputStreamInstance = $inputStreamInstance; - } - - /** - * Getter for a OutputStream instance - * - * @param $outputStreamInstance The OutputStream instance - */ - protected final function getOutputStreamInstance () { - return $this->outputStreamInstance; - } - - /** - * Setter for a OutputStream instance - * - * @param $outputStreamInstance The OutputStream instance - * @return void - */ - protected final function setOutputStreamInstance (OutputStream $outputStreamInstance) { - $this->outputStreamInstance = $outputStreamInstance; - } - - /** - * Setter for Iterator instance - * - * @param $iteratorInstance An instance of an Iterator - * @return void - */ - protected final function setIteratorInstance (Iterator $iteratorInstance) { - $this->iteratorInstance = $iteratorInstance; - } - - /** - * Getter for Iterator instance - * - * @return $iteratorInstance An instance of an Iterator - */ - public final function getIteratorInstance () { - return $this->iteratorInstance; - } - /** * Setter for state instance * diff --git a/framework/main/classes/handler/tasks/class_TaskHandler.php b/framework/main/classes/handler/tasks/class_TaskHandler.php index 4c3eaaad..40badb6f 100644 --- a/framework/main/classes/handler/tasks/class_TaskHandler.php +++ b/framework/main/classes/handler/tasks/class_TaskHandler.php @@ -9,6 +9,7 @@ use Org\Mxchange\CoreFramework\Handler\BaseHandler; use Org\Mxchange\CoreFramework\Lists\Listable; use Org\Mxchange\CoreFramework\Registry\Registerable; use Org\Mxchange\CoreFramework\Task\Taskable; +use Org\Mxchange\CoreFramework\Traits\Iterator\IteratorTrait; use Org\Mxchange\CoreFramework\Visitor\Visitable; use Org\Mxchange\CoreFramework\Visitor\Visitor; @@ -35,6 +36,9 @@ use Org\Mxchange\CoreFramework\Visitor\Visitor; * along with this program. If not, see . */ class TaskHandler extends BaseHandler implements Registerable, HandleableTask { + // Load traits + use IteratorTrait; + // Exception constants const EXCEPTION_TASK_IS_INVALID = 0xb00; diff --git a/framework/main/classes/index/class_BaseIndex.php b/framework/main/classes/index/class_BaseIndex.php index 2b3d13a5..0e2c415c 100644 --- a/framework/main/classes/index/class_BaseIndex.php +++ b/framework/main/classes/index/class_BaseIndex.php @@ -9,6 +9,7 @@ use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException; use Org\Mxchange\CoreFramework\Iterator\Filesystem\SeekableWritableFileIterator; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Traits\Iterator\IteratorTrait; // Import SPL stuff use \SplFileInfo; @@ -37,6 +38,9 @@ use \UnexpectedValueException; * along with this program. If not, see . */ abstract class BaseIndex extends BaseFrameworkSystem { + // Load traits + use IteratorTrait; + /** * Magic for this index */ diff --git a/framework/main/classes/lists/class_BaseList.php b/framework/main/classes/lists/class_BaseList.php index 08d60de8..b3135028 100644 --- a/framework/main/classes/lists/class_BaseList.php +++ b/framework/main/classes/lists/class_BaseList.php @@ -6,6 +6,7 @@ namespace Org\Mxchange\CoreFramework\Lists; use Org\Mxchange\CoreFramework\Factory\ObjectFactory; use Org\Mxchange\CoreFramework\Generic\FrameworkInterface; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; +use Org\Mxchange\CoreFramework\Traits\Iterator\IteratorTrait; use Org\Mxchange\CoreFramework\Visitor\Visitable; // Import SPL stuff @@ -35,6 +36,9 @@ use \Countable; * along with this program. If not, see . */ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate, Countable { + // Load traits + use IteratorTrait; + // Exception constants const EXCEPTION_GROUP_ALREADY_ADDED = 0xf20; const EXCEPTION_GROUP_NOT_FOUND = 0xf21; @@ -82,7 +86,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate // Set it here $this->setIteratorInstance($iteratorInstance); - } // END - if + } // And return it return $iteratorInstance; @@ -94,7 +98,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate * @param $groupName Group to check if found in list * @return $isset Whether the group is valid */ - public function isGroupSet ($groupName) { + public function isGroupSet (string $groupName) { //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-LIST: this=' . $this->__toString() . ',groupName=' . $groupName); return isset($this->listGroups[$groupName]); } @@ -106,13 +110,13 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate * @return void * @throws ListGroupAlreadyAddedException If the given group is already added */ - public function addGroup ($groupName) { + public function addGroup (string $groupName) { //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-LIST: this=' . $this->__toString() . ',groupName=' . $groupName . ' - CALLED!'); // Is the group already added? if ($this->isGroupSet($groupName)) { // Throw the exception here throw new ListGroupAlreadyAddedException(array($this, $groupName), self::EXCEPTION_GROUP_ALREADY_ADDED); - } // END - if + } // Add the group which is a simple array $this->listGroups[$groupName] = ObjectFactory::createObjectByConfiguredName('list_group_class'); @@ -128,7 +132,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate * @return void * @throws NoListGroupException If the given group is not found */ - public function addInstance ($groupName, $subGroup, Visitable $visitableInstance) { + public function addInstance (string $groupName, string $subGroup, Visitable $visitableInstance) { // Debug message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-LIST: this=' . $this->__toString() . ',groupName=' . $groupName . ',subGroup=' . $subGroup . ',visitableInstance=' . $visitableInstance->__toString() . ' - CALLED!'); @@ -136,13 +140,13 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate if (!$this->isGroupSet($groupName)) { // Throw the exception here throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND); - } // END - if + } // Is the sub group there? if (!$this->listGroups[$groupName]->isGroupSet($subGroup)) { // Automatically add it $this->listGroups[$groupName]->addGroup($subGroup); - } // END - if + } // Generate the hash $hash = $this->generateHash($groupName, $subGroup, $visitableInstance); @@ -175,7 +179,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate if ((!is_null($list)) && (!$this->isGroupSet($list))) { // Throw the exception here throw new NoListGroupException(array($this, $list), self::EXCEPTION_GROUP_NOT_FOUND); - } // END - if + } // Init array $array = []; @@ -184,7 +188,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate if (!is_null($list)) { // Then get it as well $array = $this->listGroups[$list]->getArrayFromList(NULL); - } // END - if + } // Walk through all entries foreach ($this->listIndex as $hash) { @@ -196,8 +200,8 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate // Add it array_push($array, $this->listEntries[$hash]); //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-LIST: hash=' . $hash . ',array(' . count($array) . ')=' . print_r($array, true) . ' - ADDED!'); - } // END - if - } // END - foreach + } + } // Debug message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-LIST: this=' . $this->__toString() . ',list[' . gettype($list) . ']=' . $list . ',[]=' . count($array) . ' - EXIT!'); @@ -214,7 +218,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate * @return void * @throws NoListGroupException If the given group is not found */ - public function addEntry ($groupName, $entry) { + public function addEntry (string $groupName, $entry) { // Debug message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-LIST: this=' . $this->__toString() . ',groupName=' . $groupName . ' - CALLED!'); @@ -222,7 +226,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate if (!$this->isGroupSet($groupName)) { // Throw the exception here throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND); - } // END - if + } // Generate hash $hash = $this->generateHash($groupName, $groupName, $entry); @@ -251,7 +255,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate * @return void * @throws NoListGroupException If the given group is not found */ - public function removeEntry ($groupName, $entry) { + public function removeEntry (string $groupName, $entry) { // Debug message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-LIST: this=' . $this->__toString() . ',groupName=' . $groupName . ' - CALLED!'); @@ -259,7 +263,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate if (!$this->isGroupSet($groupName)) { // Throw the exception here throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND); - } // END - if + } // Generate hash $hash = $this->generateHash($groupName, $groupName, $entry); @@ -285,7 +289,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate * @param $entry An entry of any type * @return $hash The generated */ - private function generateHash ($groupName, $subGroup, $entry) { + private function generateHash (string $groupName, string $subGroup, $entry) { // Created entry, 'null' is default $entry2 = 'null'; @@ -336,7 +340,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate foreach ($groupNames as $groupName) { // Clear this group $this->clearGroup($groupName); - } // END - foreach + } } /** @@ -345,12 +349,12 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate * @param $groupName Name of an existing group to clear * @return void */ - protected function clearGroup ($groupName) { + protected function clearGroup (string $groupName) { // Does this group exist? if (!$this->isGroupSet($groupName)) { // Throw the exception here throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND); - } // END - if + } // Then clear this group list $this->listGroups[$groupName]->clearList(); @@ -412,7 +416,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate if (!$this->isHashValid($hash)) { // Throw an exception here throw new InvalidListHashException(array($this, $hash, $hashIndex), self::EXCEPTION_INVALID_HASH); - } // END - if + } // Now copy the entry $entry = $this->listEntries[$hash]; @@ -428,12 +432,12 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate * @return $entries The array with all entries * @throws NoListGroupException If the specified group is invalid */ - public function getArrayFromProtocolInstance ($groupName) { + public function getArrayFromProtocolInstance (string $groupName) { // Is the group valid? if (!$this->isGroupSet($groupName)) { // Throw the exception here throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND); - } // END - if + } // Init the entries' array $entries = []; @@ -460,7 +464,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate // Skip to next one $iteratorInstance->next(); - } // END - while + } // Return the list return $entries; @@ -479,7 +483,7 @@ abstract class BaseList extends BaseFrameworkSystem implements IteratorAggregate if (!$this->isHashValid($hash)) { // Throw an exception here, hashIndex is unknown at this point throw new InvalidListHashException(array($this, $hash, -999), self::EXCEPTION_INVALID_HASH); - } // END - if + } // Set the entry $this->listEntries[$hash] = $entryArray; diff --git a/framework/main/classes/registry/class_BaseRegistry.php b/framework/main/classes/registry/class_BaseRegistry.php index 4613bc1c..d7847063 100644 --- a/framework/main/classes/registry/class_BaseRegistry.php +++ b/framework/main/classes/registry/class_BaseRegistry.php @@ -6,6 +6,7 @@ namespace Org\Mxchange\CoreFramework\Registry; use Org\Mxchange\CoreFramework\Factory\ObjectFactory; use Org\Mxchange\CoreFramework\Generic\NullPointerException; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; +use Org\Mxchange\CoreFramework\Traits\Iterator\IteratorTrait; // Import SPL stuff use \IteratorAggregate; @@ -33,16 +34,14 @@ use \IteratorAggregate; * along with this program. If not, see . */ abstract class BaseRegistry extends BaseFrameworkSystem implements Register, Registerable, IteratorAggregate { + // Load traits + use IteratorTrait; + /** * Glue for generating a registry key */ const REGISTRY_KEY_GLUE = '_'; - /** - * Instance of this class - */ - private static $registryInstance = NULL; - /** * Protected constructor * diff --git a/framework/main/classes/stacker/file/class_BaseFileStack.php b/framework/main/classes/stacker/file/class_BaseFileStack.php index 1960259d..d313f16e 100644 --- a/framework/main/classes/stacker/file/class_BaseFileStack.php +++ b/framework/main/classes/stacker/file/class_BaseFileStack.php @@ -11,6 +11,7 @@ use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException; use Org\Mxchange\CoreFramework\Index\Indexable; use Org\Mxchange\CoreFramework\Iterator\Filesystem\SeekableWritableFileIterator; use Org\Mxchange\CoreFramework\Stacker\BaseStacker; +use Org\Mxchange\CoreFramework\Traits\Iterator\IteratorTrait; use Org\Mxchange\CoreFramework\Utils\String\StringUtils; // Import SPL stuff @@ -40,6 +41,9 @@ use \UnexpectedValueException; * along with this program. If not, see . */ abstract class BaseFileStack extends BaseStacker { + // Load traits + use IteratorTrait; + // Exception codes const EXCEPTION_BAD_MAGIC = 0xe100; diff --git a/framework/main/interfaces/lists/class_Listable.php b/framework/main/interfaces/lists/class_Listable.php index 5eb15229..4844d0a4 100644 --- a/framework/main/interfaces/lists/class_Listable.php +++ b/framework/main/interfaces/lists/class_Listable.php @@ -38,7 +38,7 @@ interface Listable extends FrameworkInterface, IteratorAggregate { * @param $groupName Group to check if found in list * @return $isset Whether the group is valid */ - function isGroupSet ($groupName); + function isGroupSet (string $groupName); /** * Adds the given group or if already added issues a ListGroupAlreadyAddedException @@ -47,7 +47,7 @@ interface Listable extends FrameworkInterface, IteratorAggregate { * @return void * @throws ListGroupAlreadyAddedException If the given group is already added */ - function addGroup ($groupName); + function addGroup (string $groupName); /** * Adds the given instance to list group and sub group @@ -58,7 +58,7 @@ interface Listable extends FrameworkInterface, IteratorAggregate { * @return void * @throws NoListGroupException If the given group is not found */ - function addInstance ($groupName, $subGroup, Visitable $visitableInstance); + function addInstance (string $groupName, string $subGroup, Visitable $visitableInstance); /** * Adds the given entry to list group @@ -68,7 +68,7 @@ interface Listable extends FrameworkInterface, IteratorAggregate { * @return void * @throws NoListGroupException If the given group is not found */ - function addEntry ($groupName, $entry); + function addEntry (string $groupName, $entry); /** * Updates the given entry by hash with given array diff --git a/framework/main/traits/iterator/class_IteratorTrait.php b/framework/main/traits/iterator/class_IteratorTrait.php new file mode 100644 index 00000000..a5df6a6f --- /dev/null +++ b/framework/main/traits/iterator/class_IteratorTrait.php @@ -0,0 +1,55 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team + * @license GNU GPL 3.0 or any newer version + * @link http://www.shipsimu.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +trait IteratorTrait { + /** + * Instance of an Iterator class + */ + private $iteratorInstance = NULL; + + /** + * Setter for Iterator instance + * + * @param $iteratorInstance An instance of an Iterator + * @return void + */ + protected final function setIteratorInstance (Iterator $iteratorInstance) { + $this->iteratorInstance = $iteratorInstance; + } + + /** + * Getter for Iterator instance + * + * @return $iteratorInstance An instance of an Iterator + */ + public final function getIteratorInstance () { + return $this->iteratorInstance; + } + +} diff --git a/framework/main/traits/stream/input/class_InputStreamTrait.php b/framework/main/traits/stream/input/class_InputStreamTrait.php new file mode 100644 index 00000000..495bfa21 --- /dev/null +++ b/framework/main/traits/stream/input/class_InputStreamTrait.php @@ -0,0 +1,55 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team + * @license GNU GPL 3.0 or any newer version + * @link http://www.shipsimu.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +trait InputStreamTrait { + /** + * An instance of a InputStream class + */ + private $inputStreamInstance = NULL; + + /** + * Getter for a InputStream instance + * + * @param $inputStreamInstance An instance of an InputStream class + */ + protected final function getInputStreamInstance () { + return $this->inputStreamInstance; + } + + /** + * Setter for a InputStream instance + * + * @param $inputStreamInstance An instance of an InputStream class + * @return void + */ + protected final function setInputStreamInstance (InputStream $inputStreamInstance) { + $this->inputStreamInstance = $inputStreamInstance; + } + +} diff --git a/framework/main/traits/stream/output/class_OutputStreamTrait.php b/framework/main/traits/stream/output/class_OutputStreamTrait.php new file mode 100644 index 00000000..87919c81 --- /dev/null +++ b/framework/main/traits/stream/output/class_OutputStreamTrait.php @@ -0,0 +1,55 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team + * @license GNU GPL 3.0 or any newer version + * @link http://www.shipsimu.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +trait OutputStreamTrait { + /** + * An instance of a OutputStream class + */ + private $outputStreamInstance = NULL; + + /** + * Getter for a OutputStream instance + * + * @param $outputStreamInstance An instance of an OutputStream class + */ + protected final function getOutputStreamInstance () { + return $this->outputStreamInstance; + } + + /** + * Setter for a OutputStream instance + * + * @param $outputStreamInstance An instance of an OutputStream class + * @return void + */ + protected final function setOutputStreamInstance (OutputStream $outputStreamInstance) { + $this->outputStreamInstance = $outputStreamInstance; + } + +} -- 2.39.2