sort_elements: skip elements with children
[id3fs.git] / lib / ID3FS / Path / Node.pm
1 package ID3FS::Path::Node;
2
3 use strict;
4 use warnings;
5
6 sub new
7 {
8     my $proto=shift;
9     my $class=ref($proto) || $proto;
10     my $self={};
11     bless($self,$class);
12
13     $self->left(shift);
14     $self->op(shift);
15     $self->right(shift);
16
17     return $self;
18 }
19
20 sub set
21 {
22     my($self, $name, $val)=@_;
23     if(defined($val))
24     {
25         $self->{$name}=$val;
26     }
27     return $self->{$name};
28 }
29
30 sub left  { return shift->set("left",  shift); }
31 sub right { return shift->set("right", shift); }
32 sub op    { return shift->set("op",    shift); }
33
34 sub print
35 {
36     my($self)=@_;
37     my $op=$self->op();
38     my $left=$self->left();
39     my $right=$self->right();
40     return "" unless($left || $right);
41     my $str .= $self->print_node($left);
42     $str .= (" " . $op->{name} . " ") if($op);
43     $str .= $self->print_node($right);
44     if($op || ($left && $right))
45     {
46         $str="(" . $str . ")";
47     }
48     return $str;
49 }
50
51 sub print_node
52 {
53     my($self, $node)=@_;
54     return "" unless(defined($node));
55     return $node->print() if(ref($node) eq "ID3FS::Path::Node");
56     return $node->{name};
57 }
58
59 sub to_sql
60 {
61     my($self, $parent, $andlevel)=@_;
62     $andlevel=1 unless(defined($andlevel));
63     my ($leftandlevel, $rightandlevel);
64     my ($leftstr, $rightstr);
65     my $op=$self->op();
66     my $left=$self->left();
67     my $right=$self->right();
68     return ("", $andlevel) unless($left || $right);
69     ($leftstr, $leftandlevel) = $self->node_to_sql($left, $parent, $andlevel);
70 #    print "LEFT: $leftstr\n";
71     $andlevel=$self->max($andlevel, $leftandlevel);
72     if($op)
73     {
74         if(ref($op) eq "ID3FS::PathElement::Boolean")
75         {
76 #           print "Op: Bool: ", $op->{name}, "\n";
77         }
78         else
79         {
80 #           print "Op: $op\n";
81         }
82     }
83     if(defined($op) && (($op->{name} eq "AND") || ($op->{name} eq "NOT")))
84     {
85         $andlevel++;
86     }
87     ($rightstr, $rightandlevel) = $self->node_to_sql($right, $parent, $andlevel);
88 #    print "RIGHT: $rightstr\n";
89     my $str=$leftstr;
90     $str .= (" " . $op->{name} . " ") if($op);
91     $str .= $rightstr;
92     if($op || ($left && $right))
93     {
94         $str="(" . $str . ")";
95     }
96 #    print "STR: $str\n";
97     return($str, $self->max($leftandlevel, $rightandlevel));
98 }
99
100 sub node_to_sql
101 {
102     my($self, $node, $parent, $andlevel)=@_;
103     return ("", $andlevel) unless(defined($node));
104     return $node->to_sql($parent, $andlevel) if(ref($node) eq "ID3FS::Path::Node");
105 #    if((ref($node->op()) ne "ID3FS::Path::Element") &&
106 #       $node->op() eq "
107     my $sql;
108 #    print("Hit node: " . $node->{name}. "(" .
109 #         (defined($node->{parents_id}) ? $node->{parents_id} : "") .
110 #         ")\n");
111     if(defined($node->{parents_id}))
112     {
113 #       print "HIT PARENTS_ID: $node->{parents_id}\n";
114         $sql= "(t$andlevel.parents_id='$node->{parents_id}'";
115         $sql .= " AND fxt${andlevel}.tags_id='" . $node->{id} . "')";
116     }
117 #    elsif($parent)
118 #    {
119 #       print "HIT \$parent\n";
120 #       $sql= "(t$andlevel.parents_id='$parent')";
121 #    }
122     else
123     {
124 #       print "HIT NORMAL\n";
125         $sql= "(t$andlevel.parents_id=''";
126         $sql .= " AND fxt${andlevel}.tags_id='" . $node->{id} . "')";
127     }
128     return ($sql, $andlevel);
129 }
130
131 sub used_tags
132 {
133     my($self)=@_;
134     my @used=(grep { defined; }  ($self->node_used_tags($self->left()),
135                                   $self->node_used_tags($self->right())));
136     return(@used);
137 }
138
139 sub node_used_tags
140 {
141     my($self, $node)=@_;
142     return (undef) unless(defined($node));
143     return $node->used_tags() if(ref($node) eq "ID3FS::Path::Node");
144     if(defined($node->{parents_id}))
145     {
146         return([ $node->{parents_id}, $node->{id} ]);
147     }
148     return $node->{id};
149 }
150
151
152 sub max
153 {
154     my($self, $a, $b)=@_;
155     return(($a > $b) ? $a : $b);
156 }
157
158 1;