/**
  * Short description of method loadProperties
  *
  * @access private
  * @author Joel Bout, <*****@*****.**>
  * @param  boolean force
  * @param  array additionalProperties
  * @return mixed
  */
 private function loadProperties($force = false, $additionalProperties = array())
 {
     if (is_null(self::$_properties) || $force) {
         if (!$force && $this->cacheModes['property'] == self::CACHE_FILE) {
             $serial = 'hard-api-property';
             try {
                 $cache = \common_cache_FileCache::singleton();
                 $properties = $cache->get($serial);
                 self::$_properties = $properties;
             } catch (\common_cache_NotFoundException $e) {
                 // The cache cannot be accessed, build the property cache.
                 // get all the compiled tables
                 $dbWrapper = \core_kernel_classes_DbWrapper::singleton();
                 $tables = array();
                 $query = 'SELECT DISTINCT "id","table" FROM "class_to_table"';
                 $result = $dbWrapper->query($query);
                 while ($row = $result->fetch()) {
                     $tables[$row['id']] = $row['table'];
                 }
                 $additionalPropertiesTable = array();
                 $query = 'SELECT DISTINCT "class_id","property_uri" FROM "class_additional_properties"';
                 $result = $dbWrapper->query($query);
                 while ($row = $result->fetch()) {
                     $additionalPropertiesTable[$row['class_id']][] = new \core_kernel_classes_Property($row['property_uri']);
                 }
                 //retrieve each property by table
                 $this->loadClasses();
                 self::$_properties = array();
                 foreach ($tables as $classId => $table) {
                     //check in $additionalPropertiesTable if current table is concerned by additionnal properties
                     if (isset($additionalPropertiesTable[$classId])) {
                         $additionalProperties = $additionalPropertiesTable[$classId];
                     } else {
                         $additionalProperties = array();
                     }
                     $classUri = Utils::getLongName($table);
                     $class = new \core_kernel_classes_Class($classUri);
                     $topclassUri = self::$_classes[$classUri]['topclass'];
                     $topclass = new \core_kernel_classes_Class($topclassUri);
                     $ps = new PropertySwitcher($class, $topclass);
                     $properties = $ps->getProperties($additionalProperties);
                     foreach ($properties as $property) {
                         $propertyUri = $property->getUri();
                         if ($property->isMultiple() || $property->isLgDependent()) {
                             if (isset(self::$_properties[$propertyUri])) {
                                 if (!in_array("{$table}props", self::$_properties[$propertyUri])) {
                                     self::$_properties[$propertyUri][] = "{$table}props";
                                 }
                             } else {
                                 self::$_properties[$propertyUri] = array("{$table}props");
                             }
                         } else {
                             if (isset(self::$_properties[$propertyUri])) {
                                 if (!in_array("{$table}", self::$_properties[$propertyUri])) {
                                     self::$_properties[$propertyUri][] = "{$table}";
                                 }
                             } else {
                                 self::$_properties[$propertyUri] = array("{$table}");
                             }
                         }
                     }
                 }
                 //saving the properties in the cache file
                 try {
                     $cache = \common_cache_FileCache::singleton();
                     $cache->put(self::$_properties, $serial);
                 } catch (\common_cache_Exception $e) {
                     throw new Exception("cannot write the required property cache file for serial '{$serial}'.");
                 }
             }
         }
     }
 }
 /**
  * Calling this method will transfer all instances of $class from the statements table
  * to specific optimized relational tables.
  * 
  * During optimization, the current user has all privileges on the persistent memory. At
  * the end of the process, the old privileges will be set back.
  * 
  * The $options array can contain the following key => values (all booleans):
  * 
  * - recursive: compile the target class and its subclasses (default: false).
  * - append: append data to the existing optimized table if it already exists (default: false).
  * - rmSources: remove the triples in the statement table after transfer (default: true).
  *
  * @access public
  * @author Bertrand Chevrier, <*****@*****.**>
  * @param  \core_kernel_classes_Class class
  * @param  array options
  * @return boolean Will return true if it succeeds, false otherwise.
  */
 public function hardify(\core_kernel_classes_Class $class, $options = array())
 {
     $returnValue = (bool) false;
     $oldUpdatableModels = core_kernel_persistence_smoothsql_SmoothModel::getUpdatableModelIds();
     try {
         // Give access to all models during hardification.
         core_kernel_persistence_smoothsql_SmoothModel::forceUpdatableModelIds(self::getAllModelIds());
         $classLabel = $class->getLabel();
         \common_Logger::i("Hardifying class {$classLabel}", array("GENERIS"));
         if (defined("DEBUG_PERSISTENCE") && DEBUG_PERSISTENCE) {
             if (in_array($class->getUri(), self::$debug_tables)) {
                 return;
             }
             \common_Logger::d('hardify ' . $class->getUri());
             self::$debug_tables[] = $class->getUri();
             $countStatement = $this->countStatements();
         }
         if (in_array($class->getUri(), self::$blackList)) {
             return $returnValue;
         }
         // ENTER IN SMOOTH SQL MODE
         PersistenceProxy::forceMode(PERSISTENCE_SMOOTH);
         //recursive will hardify the class and it's subclasses in the same table!
         isset($options['recursive']) ? $recursive = $options['recursive'] : ($recursive = false);
         //createForeigns will hardify the class that are range of the properties
         isset($options['createForeigns']) ? $createForeigns = $options['createForeigns'] : ($createForeigns = false);
         //check if we append the data in case the hard table exists or truncate the table and add the new rows
         isset($options['append']) ? $append = $options['append'] : ($append = false);
         //if true, the instances of the class will  be removed from the statements table!
         isset($options['rmSources']) ? $rmSources = (bool) $options['rmSources'] : ($rmSources = false);
         //if defined, we took all the properties of the class and it's parents till the topclass
         isset($options['topclass']) ? $topclass = $options['topclass'] : ($topclass = new \core_kernel_classes_Class(RDFS_RESOURCE));
         //if defined, compile the additional properties
         isset($options['additionalProperties']) ? $additionalProperties = $options['additionalProperties'] : ($additionalProperties = array());
         //if defined, reference the additional class to the table
         isset($options['referencesAllTypes']) ? $referencesAllTypes = $options['referencesAllTypes'] : ($referencesAllTypes = false);
         $tableName = '_' . Utils::getShortName($class);
         $myTableMgr = new TableManager($tableName);
         $referencer = ResourceReferencer::singleton();
         //get the table columns from the class properties
         $columns = array();
         $ps = new PropertySwitcher($class);
         $properties = $ps->getProperties($additionalProperties);
         $columns = $ps->getTableColumns($additionalProperties, self::$blackList);
         //init the count value in hardened classes:
         if (isset($this->hardenedClasses[$class->getUri()])) {
             PersistenceProxy::restoreImplementation();
             return true;
             //already being compiled
         } else {
             $this->hardenedClasses[$class->getUri()] = 0;
         }
         if (!$append || $append && !$myTableMgr->exists()) {
             //create the table
             if ($myTableMgr->exists()) {
                 $myTableMgr->remove();
             }
             $myTableMgr->create($columns);
             //reference the class
             $referencer->referenceClass($class, array("topclass" => $topclass, "additionalProperties" => $additionalProperties));
             if ($referencesAllTypes) {
                 $referencer->referenceInstanceTypes($class);
             }
         }
         //insert the resources
         $startIndex = 0;
         $instancePackSize = 100;
         $instances = $class->getInstances(false, array('offset' => $startIndex, 'limit' => $instancePackSize));
         $count = count($instances);
         $notDeletedInstances = array();
         do {
             //reset timeout:
             //set_time_limit(30);
             \helpers_TimeOutHelper::setTimeOutLimit(\helpers_TimeOutHelper::MEDIUM);
             $rows = array();
             foreach ($instances as $index => $resource) {
                 if ($referencer->isResourceReferenced($resource)) {
                     PersistenceProxy::forceMode(PERSISTENCE_HARD);
                     $resource->delete();
                     PersistenceProxy::restoreImplementation();
                 }
                 $row = array('uri' => $resource->getUri());
                 foreach ($properties as $property) {
                     $propValue = $resource->getOnePropertyValue($property);
                     $row[Utils::getShortName($property)] = $propValue;
                 }
                 $rows[] = $row;
             }
             $rowMgr = new RowManager($tableName, $columns);
             $rowMgr->insertRows($rows);
             foreach ($instances as $resource) {
                 $referencer->referenceResource($resource, $tableName, null, true);
                 if ($rmSources) {
                     //remove exported resources in smooth sql, if required:
                     // Be carefull, the resource can still exist even if
                     // delete returns true. Indeed, modelIds can be mixed between
                     // multiple models and only a part of the triples that consitute
                     // the resource might have been deleted.
                     if (!$resource->delete() || $resource->exists()) {
                         //@TODO : modified resource::delete() because resource not in local modelId cannot be deleted
                         $notDeletedInstances[] = $resource->getUri();
                         $startIndex++;
                     }
                 }
             }
             if (!$rmSources) {
                 //increment start index only if not removed
                 $startIndex += $instancePackSize;
             }
             //record hardened instances number
             if (isset($this->hardenedClasses[$class->getUri()])) {
                 $this->hardenedClasses[$class->getUri()] += $count;
             } else {
                 $this->hardenedClasses[$class->getUri()] = $count;
             }
             //update instance array and count value
             $instances = $class->getInstances(false, array('offset' => $startIndex, 'limit' => $instancePackSize));
             foreach ($notDeletedInstances as $uri) {
                 unset($instances[$uri]);
             }
             $count = count($instances);
             \helpers_TimeOutHelper::reset();
         } while ($count > 0);
         $returnValue = true;
         // Treat subclasses of the current class
         if ($recursive) {
             foreach ($class->getSubClasses(true) as $subClass) {
                 $returnValue = $this->hardify($subClass, array_merge($options, array('recursive' => false, 'append' => true)));
             }
         }
         //reset cache:
         $referencer->clearCaches();
         // EXIT SMOOTH SQL MODE
         PersistenceProxy::restoreImplementation();
         if (defined("DEBUG_PERSISTENCE") && DEBUG_PERSISTENCE) {
             $this->unhardify($class, array_merge($options, array('recursive' => false, 'removeForeigns' => false)));
             \common_Logger::d('unhardened result statements ' . $this->countStatements() . ' / ' . $countStatement);
         }
         // Give the normal rights on models to the session.
         core_kernel_persistence_smoothsql_SmoothModel::forceUpdatableModelIds($oldUpdatableModels);
     } catch (Exception $e) {
         \common_Logger::e('An error occured during hardification: ' . $e->getMessage());
         core_kernel_persistence_smoothsql_SmoothModel::forceUpdatableModelIds($oldUpdatableModels);
     }
     return (bool) $returnValue;
 }