######################################################################
#
# Perl module: P3P::DataSchema
#
######################################################################
#
# $Id: dataschema.pl,v 1.1 2000/10/16 20:49:35 koike Exp $
# Created by Yuichi Koike (koike@w3.org)
#

use strict;

######################################################################
package P3P::DataSchema;
######################################################################

sub new {
    my ($class, %args) = @_;
	my $self = bless {}, $class;
	my @errors;
	$self->{errors} = \@errors;
	return $self;
}

sub uri {
	my ($self, $arg) = @_;
	if($arg) {
		$self->{uri} = $arg;
	} else {
		return $self->{uri};
	}
}

sub makeDic {
	my ($self) = @_;

	# get XML document root
	my $xml = new P3P::XML;
	$xml->setURI($self->{uri});
	if(! $xml->well_formed) { return 0;}
	my $doc = $xml->{doc};
	if(! $doc) { return 0;}
	my $root = $doc->getDocumentElement;
	if(! $root) { return 0;}
	if($root->getTagName ne "DATASCHEMA") {	return 0;}

	# Loop
	my %struct_dic;
	my $elem = $root->getFirstChild;
	while($elem) {
		my $tag = $elem->getTagName;
		my $name = $elem->getAttribute("name");

		# The structure of struct_dic is:
		# { "certificate" => 
		#	["key", "none", "has_category", "format", "none", "has_category"],
		#	"contact" => 
		#	["postal", "postal", "has_category",,,,,,,,,] }

		if($tag eq "DATA-STRUCT") {
			# extract type ("telecom.mobile" -> "telecom")
			$name =~ /(.*?)\.(.*)/;
			my $type = $1;
			my $prefix = $2;

			# Get the list for the type
			my $list = $struct_dic{$type};
			if(!$list) {
				my @list;
				$list = \@list;
				$struct_dic{$type} = $list;
			}

			# Add the prefix to the list
			push(@{$list}, $prefix);

			# Add the type of the prefix to the list
			my $ref = $elem->getAttribute("structref");
			if(! ($ref =~ s/^#//)) {
				$ref = "none";
			}
			push(@{$list}, $ref);

			# Add the flag whether it has category to the list
			my $flag = P3P::Common::has_category($elem);
			push(@{$list}, $flag);
		}
		$elem = $elem->getNextSibling;
	}

	my %data_dic;
	my $elem = $root->getFirstChild;
	while($elem) {
		my $tag = $elem->getTagName;
		my $name = $elem->getAttribute("name");

		# register the data element into data_dic
		# structure of data_dic is:
		# { "dynamic.cookies" => "no_category", "dynamic.http" => "has_category",,}

		if($tag eq "DATA-DEF") {
			my $ref = $elem->getAttribute("structref");
			if(! ($ref =~ s/^#//)) {
				$ref = "none";
			}

			# Add the flag whether it has category to the list
			my $flag = P3P::Common::has_category($elem);

			my @list;
			push(@list, $name);
			push(@list, $ref);
			push(@list, $flag);

			while($#list > 1) {
				my $dname = shift(@list);
				my $dtype = shift(@list);
				my $dcate = shift(@list);

				$data_dic{$dname} = $dcate;
				my $strinfo = $struct_dic{$dtype};
				if($strinfo) {
					my @list2 = @{$strinfo};
					while($#list2 > 1) {
						my $xname = shift(@list2);
						my $xtype = shift(@list2);
						my $xcate = shift(@list2);
						push(@list, $dname.".".$xname);
						push(@list, $xtype);
						push(@list, $xcate);
					}
				}
			}
		}
		$elem = $elem->getNextSibling;
	}
	$self->{data_dic} = \%data_dic;

	return 1;
}

sub dataExist {
	my ($self, $data) = @_;

	my $ret = ${$self->{data_dic}}{$data};

	return $ret;
}


sub addError {
	my ($self, $status, $mes) = @_;
	my $err = new P3P::Error;
	$err->status($status);
	$err->message($mes);
	push(@{$self->errors}, $err);
}

sub clearError {
	my ($self) = @_;
	my @new_errors;
	$self->{errors} = \@new_errors;
}

sub errors {
	my ($self) = @_;
	return $self->{errors};
}

# module return code
1;

__END__
