public static function instance()
 {
     if (!isset(self::$instance)) {
         self::$instance = new BlueprintLibrary();
     }
     return self::$instance;
 }
 public static function read($blueprint_file_name)
 {
     $tag = "BlueprintReader->read()";
     Log::debug("{$tag}: <{$blueprint_file_name}>");
     if (substr($blueprint_file_name, 0, 1) != "/") {
         // extract config variables
         $path_blueprints = BPConfig::$path_blueprints;
         // calculate path to blueprint file
         $blueprint_file_path = $path_blueprints . $blueprint_file_name;
     } else {
         // calculate path to blueprint file
         $blueprint_file_path = $blueprint_file_name;
     }
     // Check the library for a copy of this blueprint
     $library = BlueprintLibrary::instance();
     if ($copy = $library->checkOut($blueprint_file_name)) {
         Log::debug("{$tag}: Returning copy from library");
         return $copy;
     }
     if (is_readable($blueprint_file_path)) {
         if ($xml = simplexml_load_file($blueprint_file_path, "SimpleXMLElement", LIBXML_NOCDATA)) {
             $key = (string) $xml['key'];
             $type = (string) $xml['type'];
             Log::debug("{$tag}: Parsing xml for {$type} {$key}");
             switch ($type) {
                 case "filter":
                     $blueprint = self::parseFilterBlueprint($xml);
                     break;
                 case "form":
                     $blueprint = self::parseFormBlueprint($xml);
                     break;
                 case "list":
                     $blueprint = self::parseListBlueprint($xml);
                     break;
                 case "entity":
                     $blueprint = self::parseEntityBlueprint($xml);
                     break;
                 case "join":
                     $blueprint = self::parseJoinBlueprint($xml);
                     break;
                 case "report":
                     $blueprint = self::parseReportBlueprint($xml);
             }
             // Save a copy of the blueprint in the library
             // ?? does this make an actual copy and take extra memory
             // ?? is there a way to save a pointer to the blueprint in the array
             $library->checkIn($blueprint);
             return $blueprint;
         } else {
             // simplexml_load_file() failed
             throw new Exception("Failed to load blueprint xml.");
         }
     } else {
         throw new Exception("Blueprint file is not readable.");
     }
 }