public function __get($attrName)
 {
     // If something's been explicitly overridden, return that.
     if (isset($this->components[$attrName])) {
         return $this->components[$attrName];
     }
     // If there's a getter, call it and immediately return.
     $ucfAttrName = ucfirst($attrName);
     $getterMethodName = "get{$ucfAttrName}";
     if (method_exists($this, $getterMethodName)) {
         return $this->{$getterMethodName}();
     }
     // Check the cache.
     if (isset($this->cachedComponents[$attrName])) {
         return $this->cachedComponents[$attrName];
     }
     // If there's a loadX method, use it and cache the result.
     $creatorMethodName = "load{$ucfAttrName}";
     if (method_exists($this, $creatorMethodName)) {
         return $this->cachedComponents[$attrName] = $this->{$creatorMethodName}();
     }
     foreach (self::$funnilyCasedComponentNames as $n) {
         $n = trim($n);
         if (EarthIT_Schema_WordUtil::toCamelCase($n) == $attrName) {
             // Ooh, this is what they want!
             $ucfAttrName = EarthIT_Schema_WordUtil::toPascalCase($n);
             break;
         }
     }
     // If there's a class with a matching name, instantiate it and cache the instance.
     $className = "NodeTemplateProjectNS_{$ucfAttrName}";
     if (class_exists($className, true)) {
         return $this->cachedComponents[$attrName] = new $className($this);
     }
     throw new Exception("Undefined property: " . get_class($this) . "#{$attrName}");
 }
 protected static function findField($fieldRef, EarthIT_Schema_ResourceClass $rc, $fuzzyMatch = false)
 {
     if ($fuzzyMatch) {
         $fieldRef = EarthIT_Schema_WordUtil::minimize($fieldRef);
         foreach ($rc->getFields() as $fn => $f) {
             if ($fieldRef === EarthIT_Schema_WordUtil::minimize($fn)) {
                 return $f;
             }
         }
         return null;
     } else {
         return $rc->getField($fieldRef);
     }
 }