 			}
 			return csv;
 		}
-			
+		
+		override public function getHierarchyRoot():IWeaveTreeNode
+		{
+			if (!_rootNode)
+				_rootNode = createCategoryNode();
+			return _rootNode;
+		}
+		
+		public function createCategoryNode(data:Object = null):ColumnTreeNode
+		{
+			if (!data)
+			{
+				var name:String = WeaveAPI.globalHashMap.getName(this);
+				data = {id: 0, name: name};
+			}
+			data[META_CATEGORY_ID] = data.id;
+			return new ColumnTreeNode({
+				dataSource: this,
+				data: data,
+				idFields: [META_CATEGORY_ID],
+				label: data.name,
+				hasChildBranches: true,
+				children: function(node:ColumnTreeNode):Array {
+					var children:Array = [];
+					getJson('category/children', {category_id: node.data.id}, function(result:Object):void {
+						var nodes:Array = [];
+						for each (var item:Object in result.categories)
+							nodes.push(createCategoryNode(item));
+						// put categories first in the list
+						children.splice.apply(null, [0, 0].concat(nodes));
+					});
+					getJson('category/series', {category_id: node.data.id}, function(result:Object):void {
+						for each (var item:Object in result.seriess)
+							children.push(createSeriesNode(item));
+					});
+					return children;
+				}
+			});
+		}
+		
 		public function createSeriesNode(data:Object):IWeaveTreeNode
 		{
+			data[META_SERIES_ID] = data.id;
 			return new ColumnTreeNode({
 				dataSource: this,
 				label: data.title,
 				data: data,
+				idFields: [META_SERIES_ID],
 				hasChildBranches: false,
 				children: function(node:ColumnTreeNode):Array {
 					var csv:CSVDataSource = getObservationsCSV(data.id);

			});
		}
		
        override public function getHierarchyRoot():IWeaveTreeNode
        {
            if (!_rootNode)
                _rootNode = createCategoryNode();
            return _rootNode;
        }
		
		public static const META_SERIES_ID:String = 'FRED_series_id';
		public static const META_COLUMN_NAME:String = 'FRED_column_name';
		
		public static const META_ID_FIELDS:Array = [META_SERIES_ID, META_COLUMN_NAME];
		
		override public function findHierarchyNode(metadata:Object):IWeaveTreeNode
		{
			return null;
		}
		
		override protected function generateHierarchyNode(metadata:Object):IWeaveTreeNode
		{

			jsonCache.getJsonObject(getUrl(method, params), resultHandler, faultHandler);
		}
		
		override protected function refreshHierarchy():void
		{
			for each (var csv:CSVDataSource in csvCache)
				disposeObject(csv);
			csvCache = {};
		}
		
		private var csvCache:Object = {};
