File Coverage

blib/lib/OTRS/OPM/Analyzer/Utils/OPMFile.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package OTRS::OPM::Analyzer::Utils::OPMFile;
2              
3             # ABSTRACT: Parser for the .opm file
4              
5 2     2   49922 use Moose;
  0            
  0            
6             use Moose::Util::TypeConstraints;
7              
8             use MIME::Base64 ();
9             use Path::Class;
10             use Try::Tiny;
11             use XML::LibXML;
12              
13             # define types
14             subtype 'VersionString' =>
15             as 'Str' =>
16             where { $_ =~ m{ \A (?:[0-9]+) (?:\.[0-9]+){0,2} (?:_\d+)? \z }xms };
17              
18             subtype 'FrameworkVersionString' =>
19             as 'Str' =>
20             where { $_ =~ m{ \A (?: (?:x|[0-9]+x?) \. ){2} (?: x | [0-9]+x? ) \z }xms };
21              
22             subtype 'XMLTree' =>
23             as 'Object' =>
24             where { $_->isa( 'XML::LibXML::Document' ) };
25              
26             # declare attributes
27             has name => ( is => 'rw', isa => 'Str', );
28             has version => ( is => 'rw', isa => 'VersionString', );
29             has vendor => ( is => 'rw', isa => 'Str', );
30             has url => ( is => 'rw', isa => 'Str', );
31             has license => ( is => 'rw', isa => 'Str', );
32             has description => ( is => 'rw', isa => 'Str', );
33             has error_string => ( is => 'rw', isa => 'Str', );
34              
35             has tree => (
36             is => 'rw',
37             isa => 'XMLTree',
38             );
39              
40             has opm_file => (
41             is => 'ro',
42             isa => 'Str',
43             required => 1,
44             );
45              
46             has files => (
47             traits => ['Array'],
48             is => 'rw',
49             isa => 'ArrayRef[HashRef]',
50             auto_deref => 1,
51             default => sub{ [] },
52             handles => {
53             add_file => 'push',
54             },
55             );
56              
57             has framework => (
58             traits => ['Array'],
59             is => 'rw',
60             isa => 'ArrayRef[FrameworkVersionString]',
61             auto_deref => 1,
62             default => sub { [] },
63             handles => {
64             add_framework => 'push',
65             },
66             );
67              
68             has dependencies => (
69             traits => ['Array'],
70             is => 'rw',
71             isa => 'ArrayRef[HashRef[Str]]',
72             auto_deref => 1,
73             default => sub { [] },
74             handles => {
75             add_dependency => 'push',
76             },
77             );
78              
79              
80             sub documentation {
81             my ($self,%params) = @_;
82            
83             my $doc_file;
84             my $found_file;
85            
86             for my $file ( $self->files ) {
87             my $filename = $file->{filename};
88             next if $filename !~ m{ \A doc/ }x;
89            
90             if ( !$doc_file ) {
91             $doc_file = $file;
92             $found_file = $filename;
93             }
94            
95             my $lang = $params{lang} || '';
96             next if $lang && $filename !~ m{ \A doc/$lang/ }x;
97            
98             if ( $lang && $found_file !~ m{ \A doc/$lang/ }x ) {
99             $doc_file = $file;
100             $found_file = $filename;
101             }
102            
103             my $type = $params{type} || '';
104             next if $type && $filename !~ m{ \A doc/[^/]+/.*\.$type \z }x;
105            
106             if ( $type && $found_file !~ m{ \A doc/$lang/ }x ) {
107             $doc_file = $file;
108             $found_file = $filename;
109            
110             if ( !$lang || ( $lang && $found_file !~ m{ \A doc/$lang/ }x ) ) {
111             last;
112             }
113             }
114             }
115            
116             return $doc_file;
117             }
118              
119             sub parse {
120             my ($self) = @_;
121              
122             $self->error_string( '' );
123            
124             if ( !-e $self->opm_file ) {
125             $self->error_string( 'File does not exist' );
126             return;
127             }
128            
129             my $tree;
130             try {
131             my $parser = XML::LibXML->new;
132             $tree = $parser->parse_file( $self->opm_file );
133              
134             $self->tree( $tree );
135             }
136             catch {
137             $self->error_string( 'Could not parse .opm: ' . $_ );
138             return;
139             };
140              
141             return if $self->error_string;
142            
143             # check if the opm file is valid.
144             try {
145             my $xsd = do{ local $/; <DATA> };
146             XML::LibXML::Schema->new( string => $xsd )
147             }
148             catch {
149             $self->error_string( 'Could not validate against XML schema: ' . $_ );
150             #return;
151             };
152            
153             my $root = $tree->getDocumentElement;
154            
155             # collect basic data
156             $self->vendor( $root->findvalue( 'Vendor' ) );
157             $self->name( $root->findvalue( 'Name' ) );
158             $self->license( $root->findvalue( 'License' ) );
159             $self->version( $root->findvalue( 'Version' ) );
160             $self->url( $root->findvalue( 'URL' ) );
161            
162             # retrieve framework information
163             my @frameworks = $root->findnodes( 'Framework' );
164            
165             FILE:
166             for my $framework ( @frameworks ) {
167             my $framework_version = $framework->textContent;
168            
169             # push framework info to attribute
170             $self->add_framework( $framework_version );
171             }
172              
173             # retrieve file information
174             my @files = $root->findnodes( 'Filelist/File' );
175            
176             FILE:
177             for my $file ( @files ) {
178             my $name = $file->findvalue( '@Location' );
179            
180             #next FILE if $name !~ m{ \. (?:pl|pm|pod|t) \z }xms;
181             my $encode = $file->findvalue( '@Encode' );
182             next FILE if $encode ne 'Base64';
183            
184             my $content_base64 = $file->textContent;
185             my $content = MIME::Base64::decode( $content_base64 );
186            
187             # push file info to attribute
188             $self->add_file({
189             filename => $name,
190             content => $content,
191             });
192             }
193            
194             # get description - english if available, any other language otherwise
195             my @descriptions = $root->findnodes( 'Description' );
196             my $description_string;
197            
198             DESCRIPTION:
199             for my $description ( @descriptions ) {
200             $description_string = $description->textContent;
201             my $language = $description->findvalue( '@Lang' );
202            
203             last DESCRIPTION if $language eq 'en';
204             }
205            
206             $self->description( $description_string );
207            
208             # get OTRS and CPAN dependencies
209             my @otrs_deps = $root->findnodes( 'PackageRequired' );
210             my @cpan_deps = $root->findnodes( 'ModuleRequired' );
211            
212             my %types = (
213             PackageRequired => 'OTRS',
214             ModuleRequired => 'CPAN',
215             );
216            
217             for my $dep ( @otrs_deps, @cpan_deps ) {
218             my $node_type = $dep->nodeName;
219             my $version = $dep->findvalue( '@Version' );
220             my $dep_name = $dep->textContent;
221             my $dep_type = $types{$node_type};
222            
223             $self->add_dependency({
224             type => $dep_type,
225             version => $version,
226             name => $dep_name,
227             });
228             }
229            
230             return 1;
231             }
232              
233             sub as_sopm {
234             my ($self) = @_;
235              
236             my $tree = $self->tree->cloneNode(1);
237             my $root = $tree->getDocumentElement;
238            
239             my @build_host = $root->findnodes( 'BuildHost' );
240             my @build_date = $root->findnodes( 'BuildDate' );
241            
242             $root->removeChild( $_ ) for @build_host;
243             $root->removeChild( $_ ) for @build_date;
244              
245             #$build_host->unbindNode() if $build_host;
246             #$build_date->unbindNode() if $build_date;
247            
248             my @files = $root->findnodes( 'Filelist/File' );
249             for my $file ( @files ) {
250             my ($encode) = $file->findnodes( '@Encode' );
251             $encode->unbindNode() if $encode;
252            
253             $file->removeChildNodes();
254             }
255            
256             return $tree->toString;
257             }
258              
259             no Moose;
260              
261             1;
262              
263             =pod
264              
265             =head1 NAME
266              
267             OTRS::OPM::Analyzer::Utils::OPMFile - Parser for the .opm file
268              
269             =head1 VERSION
270              
271             version 0.03
272              
273             =head1 SYNOPSIS
274              
275             =head1 METHODS
276              
277             =head2 new
278              
279             =head2 parse
280              
281             =head2 as_sopm
282              
283             =head2 documentation
284              
285             =head1 ATTRIBUTES
286              
287             =over 4
288              
289             =item * opm_file
290              
291             =item * tree
292              
293             =item * framework
294              
295             =item * dependencies
296              
297             =item * files
298              
299             =item * error_string
300              
301             =item * description
302              
303             =item * license
304              
305             =item * url
306              
307             =item * vendor
308              
309             =item * version
310              
311             =item * name
312              
313             =back
314              
315             =head1 AUTHOR
316              
317             Renee Baecker <reneeb@cpan.org>
318              
319             =head1 COPYRIGHT AND LICENSE
320              
321             This software is Copyright (c) 2014 by Renee Baecker.
322              
323             This is free software, licensed under:
324              
325             The Artistic License 2.0 (GPL Compatible)
326              
327             =cut
328              
329             __DATA__
330             <?xml version="1.0" encoding="UTF-8" standalone="no"?>
331             <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
332             <xs:import namespace="http://www.w3.org/XML/1998/namespace"/>
333            
334             <xs:element name="otrs_package">
335             <xs:complexType>
336             <xs:sequence>
337             <xs:element ref="Name" minOccurs="1" maxOccurs="1"/>
338             <xs:element ref="Version"/>
339             <xs:element ref="Vendor"/>
340             <xs:element ref="URL"/>
341             <xs:element ref="License"/>
342             <xs:element ref="ChangeLog" minOccurs="0" maxOccurs="unbounded" />
343             <xs:element ref="Description" maxOccurs="unbounded" />
344             <xs:element ref="Framework" maxOccurs="unbounded" />
345             <xs:element ref="OS" minOccurs="0" maxOccurs="unbounded" />
346             <xs:element ref="IntroInstall" minOccurs="0" maxOccurs="unbounded" />
347             <xs:element ref="IntroUninstall" minOccurs="0" maxOccurs="unbounded" />
348             <xs:element ref="IntroReinstall" minOccurs="0" maxOccurs="unbounded" />
349             <xs:element ref="IntroUpgrade" minOccurs="0" maxOccurs="unbounded" />
350             <xs:element ref="PackageRequired" minOccurs="0" maxOccurs="unbounded" />
351             <xs:element ref="ModuleRequired" minOccurs="0" maxOccurs="unbounded" />
352             <xs:element ref="CodeInstall" minOccurs="0" maxOccurs="unbounded" />
353             <xs:element ref="CodeUpgrade" minOccurs="0" maxOccurs="unbounded" />
354             <xs:element ref="CodeUninstall" minOccurs="0" maxOccurs="unbounded" />
355             <xs:element ref="CodeReinstall" minOccurs="0" maxOccurs="unbounded" />
356             <xs:element ref="BuildDate" minOccurs="0" />
357             <xs:element ref="BuildHost" minOccurs="0" />
358             <xs:element ref="Filelist"/>
359             <xs:element ref="DatabaseInstall" minOccurs="0" maxOccurs="unbounded" />
360             <xs:element ref="DatabaseUpgrade" minOccurs="0" maxOccurs="unbounded" />
361             <xs:element ref="DatabaseReinstall" minOccurs="0" maxOccurs="unbounded" />
362             <xs:element ref="DatabaseUninstall" minOccurs="0" maxOccurs="unbounded" />
363             </xs:sequence>
364             <xs:attribute name="version" use="required" type="xs:anySimpleType"/>
365             </xs:complexType>
366             </xs:element>
367            
368             <xs:element name="ChangeLog">
369             <xs:complexType>
370             <xs:simpleContent>
371             <xs:extension base="xs:string">
372             <xs:attribute name="Date" use="required" type="xs:anySimpleType"/>
373             <xs:attribute name="Version" use="required" type="xs:anySimpleType"/>
374             </xs:extension>
375             </xs:simpleContent>
376             </xs:complexType>
377             </xs:element>
378            
379             <xs:element name="Description">
380             <xs:complexType>
381             <xs:simpleContent>
382             <xs:extension base="xs:string">
383             <xs:attribute name="Lang" use="optional" type="xs:anySimpleType"/>
384             <xs:attribute name="Format" use="optional" type="xs:anySimpleType"/>
385             <xs:attribute name="Translatable" use="optional" type="xs:anySimpleType"/>
386             </xs:extension>
387             </xs:simpleContent>
388             </xs:complexType>
389             </xs:element>
390            
391             <xs:element name="Filelist">
392             <xs:complexType>
393             <xs:sequence>
394             <xs:element ref="File" maxOccurs="unbounded" />
395             </xs:sequence>
396             </xs:complexType>
397             </xs:element>
398            
399             <xs:element name="File">
400             <xs:complexType>
401             <xs:simpleContent>
402             <xs:extension base="xs:string">
403             <xs:attribute name="Location" use="required" type="xs:anySimpleType"/>
404             <xs:attribute name="Permission" use="required" type="xs:anySimpleType"/>
405             <xs:attribute name="Encode" use="required" type="xs:anySimpleType"/>
406             </xs:extension>
407             </xs:simpleContent>
408             </xs:complexType>
409             </xs:element>
410            
411             <xs:element name="PackageRequired">
412             <xs:complexType>
413             <xs:simpleContent>
414             <xs:extension base="xs:string">
415             <xs:attribute name="Version" use="required" type="xs:anySimpleType"/>
416             </xs:extension>
417             </xs:simpleContent>
418             </xs:complexType>
419             </xs:element>
420            
421             <xs:element name="ModuleRequired">
422             <xs:complexType>
423             <xs:simpleContent>
424             <xs:extension base="xs:string">
425             <xs:attribute name="Version" use="required" type="xs:anySimpleType"/>
426             </xs:extension>
427             </xs:simpleContent>
428             </xs:complexType>
429             </xs:element>
430            
431             <xs:element name="IntroInstall">
432             <xs:complexType>
433             <xs:simpleContent>
434             <xs:extension base="xs:string">
435             <xs:attribute name="Type" use="required" type="xs:anySimpleType"/>
436             <xs:attribute name="Lang" use="optional" type="xs:anySimpleType"/>
437             <xs:attribute name="Title" use="optional" type="xs:anySimpleType"/>
438             <xs:attribute name="Translatable" use="optional" type="xs:anySimpleType"/>
439             <xs:attribute name="Format" use="optional" type="xs:anySimpleType"/>
440             </xs:extension>
441             </xs:simpleContent>
442             </xs:complexType>
443             </xs:element>
444             <xs:element name="IntroUninstall">
445             <xs:complexType>
446             <xs:simpleContent>
447             <xs:extension base="xs:string">
448             <xs:attribute name="Type" use="required" type="xs:anySimpleType"/>
449             <xs:attribute name="Lang" use="optional" type="xs:anySimpleType"/>
450             <xs:attribute name="Title" use="optional" type="xs:anySimpleType"/>
451             <xs:attribute name="Translatable" use="optional" type="xs:anySimpleType"/>
452             <xs:attribute name="Format" use="optional" type="xs:anySimpleType"/>
453             </xs:extension>
454             </xs:simpleContent>
455             </xs:complexType>
456             </xs:element>
457             <xs:element name="IntroReinstall">
458             <xs:complexType>
459             <xs:simpleContent>
460             <xs:extension base="xs:string">
461             <xs:attribute name="Type" use="required" type="xs:anySimpleType"/>
462             <xs:attribute name="Lang" use="optional" type="xs:anySimpleType"/>
463             <xs:attribute name="Title" use="optional" type="xs:anySimpleType"/>
464             <xs:attribute name="Translatable" use="optional" type="xs:anySimpleType"/>
465             <xs:attribute name="Format" use="optional" type="xs:anySimpleType"/>
466             </xs:extension>
467             </xs:simpleContent>
468             </xs:complexType>
469             </xs:element>
470             <xs:element name="IntroUpgrade">
471             <xs:complexType>
472             <xs:simpleContent>
473             <xs:extension base="xs:string">
474             <xs:attribute name="Type" use="required" type="xs:anySimpleType"/>
475             <xs:attribute name="Lang" use="optional" type="xs:anySimpleType"/>
476             <xs:attribute name="Title" use="optional" type="xs:anySimpleType"/>
477             <xs:attribute name="Translatable" use="optional" type="xs:anySimpleType"/>
478             <xs:attribute name="Version" use="optional" type="xs:anySimpleType"/>
479             <xs:attribute name="Format" use="optional" type="xs:anySimpleType"/>
480             </xs:extension>
481             </xs:simpleContent>
482             </xs:complexType>
483             </xs:element>
484            
485             <xs:element name="CodeInstall">
486             <xs:complexType>
487             <xs:simpleContent>
488             <xs:extension base="xs:string">
489             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
490             </xs:extension>
491             </xs:simpleContent>
492             </xs:complexType>
493             </xs:element>
494             <xs:element name="CodeUninstall">
495             <xs:complexType>
496             <xs:simpleContent>
497             <xs:extension base="xs:string">
498             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
499             </xs:extension>
500             </xs:simpleContent>
501             </xs:complexType>
502             </xs:element>
503             <xs:element name="CodeReinstall">
504             <xs:complexType>
505             <xs:simpleContent>
506             <xs:extension base="xs:string">
507             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
508             </xs:extension>
509             </xs:simpleContent>
510             </xs:complexType>
511             </xs:element>
512             <xs:element name="CodeUpgrade">
513             <xs:complexType>
514             <xs:simpleContent>
515             <xs:extension base="xs:string">
516             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
517             <xs:attribute name="Version" use="optional" type="xs:anySimpleType"/>
518             </xs:extension>
519             </xs:simpleContent>
520             </xs:complexType>
521             </xs:element>
522            
523             <xs:element name="Name" type="xs:token"/>
524             <xs:element name="Vendor" type="xs:token"/>
525             <xs:element name="URL" type="xs:token"/>
526             <xs:element name="Framework" type="xs:token"/>
527             <xs:element name="Version" type="xs:token"/>
528             <xs:element name="License" type="xs:token"/>
529             <xs:element name="OS" type="xs:token"/>
530             <xs:element name="BuildDate" type="xs:token"/>
531             <xs:element name="BuildHost" type="xs:token"/>
532            
533            
534             <!-- -->
535             <!-- Database stuff -->
536             <!-- -->
537            
538             <xs:element name="DatabaseInstall">
539             <xs:complexType>
540             <xs:choice maxOccurs="unbounded">
541             <xs:element ref="TableCreate" minOccurs="0" maxOccurs="unbounded" />
542             <xs:element ref="TableAlter" minOccurs="0" maxOccurs="unbounded" />
543             <xs:element ref="Insert" minOccurs="0" maxOccurs="unbounded" />
544             </xs:choice>
545             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
546             </xs:complexType>
547             </xs:element>
548             <xs:element name="DatabaseUninstall">
549             <xs:complexType>
550             <xs:choice maxOccurs="unbounded">
551             <xs:element ref="TableDrop" minOccurs="0" maxOccurs="unbounded" />
552             <xs:element ref="TableAlter" minOccurs="0" maxOccurs="unbounded" />
553             </xs:choice>
554             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
555             </xs:complexType>
556             </xs:element>
557             <xs:element name="DatabaseReinstall">
558             <xs:complexType>
559             <xs:simpleContent>
560             <xs:extension base="xs:string">
561             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
562             </xs:extension>
563             </xs:simpleContent>
564             </xs:complexType>
565             </xs:element>
566             <xs:element name="DatabaseUpgrade">
567             <xs:complexType>
568             <xs:choice maxOccurs="unbounded">
569             <xs:element ref="TableCreate" minOccurs="0" maxOccurs="unbounded" />
570             <xs:element ref="TableAlter" minOccurs="0" maxOccurs="unbounded" />
571             <xs:element ref="Insert" minOccurs="0" maxOccurs="unbounded" />
572             </xs:choice>
573             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
574             <xs:attribute name="Version" use="optional" type="xs:anySimpleType"/>
575             </xs:complexType>
576             </xs:element>
577            
578             <xs:element name="TableCreate">
579             <xs:complexType>
580             <xs:choice maxOccurs="unbounded">
581             <xs:element ref="Column" maxOccurs="unbounded" />
582             <xs:element ref="ForeignKey" minOccurs="0" maxOccurs="unbounded" />
583             <xs:element ref="Index" minOccurs="0" maxOccurs="unbounded" />
584             <xs:element ref="Unique" minOccurs="0" maxOccurs="unbounded" />
585             </xs:choice>
586             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
587             <xs:attribute name="Name" use="optional" type="xs:anySimpleType"/>
588             <xs:attribute name="Version" use="optional" type="xs:anySimpleType"/>
589             </xs:complexType>
590             </xs:element>
591            
592             <xs:element name="TableAlter">
593             <xs:complexType>
594             <xs:choice maxOccurs="unbounded">
595             <xs:element ref="ColumnAdd" minOccurs="0" maxOccurs="unbounded" />
596             <xs:element ref="ColumnChange" minOccurs="0" maxOccurs="unbounded" />
597             <xs:element ref="ColumnDrop" minOccurs="0" maxOccurs="unbounded" />
598             <xs:element ref="ForeignKeyCreate" minOccurs="0" maxOccurs="unbounded" />
599             <xs:element ref="ForeignKeyDrop" minOccurs="0" maxOccurs="unbounded" />
600             <xs:element ref="IndexCreate" minOccurs="0" maxOccurs="unbounded" />
601             <xs:element ref="IndexDrop" minOccurs="0" maxOccurs="unbounded" />
602             <xs:element ref="UniqueCreate" minOccurs="0" maxOccurs="unbounded" />
603             <xs:element ref="UniqueDrop" minOccurs="0" maxOccurs="unbounded" />
604             </xs:choice>
605             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
606             <xs:attribute name="Name" use="optional" type="xs:anySimpleType"/>
607             <xs:attribute name="Version" use="optional" type="xs:anySimpleType"/>
608             </xs:complexType>
609             </xs:element>
610            
611             <xs:element name="TableDrop">
612             <xs:complexType>
613             <xs:simpleContent>
614             <xs:extension base="xs:string">
615             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
616             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
617             </xs:extension>
618             </xs:simpleContent>
619             </xs:complexType>
620             </xs:element>
621            
622             <!-- Columns -->
623            
624             <xs:element name="Column">
625             <xs:complexType>
626             <xs:simpleContent>
627             <xs:extension base="xs:string">
628             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
629             <xs:attribute name="AutoIncrement" use="optional" type="xs:anySimpleType"/>
630             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
631             <xs:attribute name="Required" use="optional" type="xs:anySimpleType"/>
632             <xs:attribute name="Size" use="optional" type="xs:anySimpleType"/>
633             <xs:attribute name="PrimaryKey" use="optional" type="xs:anySimpleType"/>
634             <xs:attribute name="Default" use="optional" type="xs:anySimpleType"/>
635             </xs:extension>
636             </xs:simpleContent>
637             </xs:complexType>
638             </xs:element>
639             <xs:element name="ColumnAdd">
640             <xs:complexType>
641             <xs:simpleContent>
642             <xs:extension base="xs:string">
643             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
644             <xs:attribute name="AutoIncrement" use="optional" type="xs:anySimpleType"/>
645             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
646             <xs:attribute name="Required" use="optional" type="xs:anySimpleType"/>
647             <xs:attribute name="Size" use="optional" type="xs:anySimpleType"/>
648             <xs:attribute name="PrimaryKey" use="optional" type="xs:anySimpleType"/>
649             <xs:attribute name="Default" use="optional" type="xs:anySimpleType"/>
650             </xs:extension>
651             </xs:simpleContent>
652             </xs:complexType>
653             </xs:element>
654             <xs:element name="ColumnChange">
655             <xs:complexType>
656             <xs:simpleContent>
657             <xs:extension base="xs:string">
658             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
659             <xs:attribute name="Default" use="optional" type="xs:anySimpleType"/>
660             <xs:attribute name="NameOld" use="optional" type="xs:anySimpleType"/>
661             <xs:attribute name="NameNew" use="optional" type="xs:anySimpleType"/>
662             <xs:attribute name="AutoIncrement" use="optional" type="xs:anySimpleType"/>
663             <xs:attribute name="Required" use="optional" type="xs:anySimpleType"/>
664             <xs:attribute name="Size" use="optional" type="xs:anySimpleType"/>
665             <xs:attribute name="PrimaryKey" use="optional" type="xs:anySimpleType"/>
666             </xs:extension>
667             </xs:simpleContent>
668             </xs:complexType>
669             </xs:element>
670             <xs:element name="ColumnDrop">
671             <xs:complexType>
672             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
673             </xs:complexType>
674             </xs:element>
675            
676             <!-- Foreign Keys -->
677            
678             <xs:element name="ForeignKey">
679             <xs:complexType>
680             <xs:sequence>
681             <xs:element ref="Reference" maxOccurs="unbounded" />
682             </xs:sequence>
683             <xs:attribute name="ForeignTable" use="required" type="xs:anySimpleType"/>
684             </xs:complexType>
685             </xs:element>
686            
687             <xs:element name="ForeignKeyCreate">
688             <xs:complexType>
689             <xs:sequence>
690             <xs:element ref="Reference" maxOccurs="unbounded" />
691             </xs:sequence>
692             <xs:attribute name="ForeignTable" use="required" type="xs:anySimpleType"/>
693             </xs:complexType>
694             </xs:element>
695            
696             <xs:element name="ForeignKeyDrop">
697             <xs:complexType>
698             <xs:sequence>
699             <xs:element ref="Reference" maxOccurs="unbounded" />
700             </xs:sequence>
701             <xs:attribute name="ForeignTable" use="required" type="xs:anySimpleType"/>
702             </xs:complexType>
703             </xs:element>
704            
705             <xs:element name="Reference">
706             <xs:complexType>
707             <xs:simpleContent>
708             <xs:extension base="xs:string">
709             <xs:attribute name="Local" use="required" type="xs:anySimpleType"/>
710             <xs:attribute name="Foreign" use="required" type="xs:anySimpleType"/>
711             </xs:extension>
712             </xs:simpleContent>
713             </xs:complexType>
714             </xs:element>
715            
716             <!-- Unique columns -->
717            
718             <xs:element name="Unique">
719             <xs:complexType>
720             <xs:sequence>
721             <xs:element ref="UniqueColumn" maxOccurs="unbounded" />
722             </xs:sequence>
723             <xs:attribute name="Name" use="optional" type="xs:anySimpleType"/>
724             </xs:complexType>
725             </xs:element>
726            
727             <xs:element name="UniqueColumn">
728             <xs:complexType>
729             <xs:simpleContent>
730             <xs:extension base="xs:string">
731             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
732             </xs:extension>
733             </xs:simpleContent>
734             </xs:complexType>
735             </xs:element>
736            
737             <xs:element name="UniqueCreate">
738             <xs:complexType>
739             <xs:simpleContent>
740             <xs:extension base="xs:string">
741             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
742             </xs:extension>
743             </xs:simpleContent>
744             </xs:complexType>
745             </xs:element>
746            
747             <xs:element name="UniqueDrop">
748             <xs:complexType>
749             <xs:simpleContent>
750             <xs:extension base="xs:string">
751             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
752             </xs:extension>
753             </xs:simpleContent>
754             </xs:complexType>
755             </xs:element>
756            
757             <!-- Index columns -->
758            
759             <xs:element name="Index">
760             <xs:complexType>
761             <xs:sequence>
762             <xs:element ref="IndexColumn" maxOccurs="unbounded" />
763             </xs:sequence>
764             <xs:attribute name="Name" use="optional" type="xs:anySimpleType"/>
765             </xs:complexType>
766             </xs:element>
767            
768             <xs:element name="IndexColumn">
769             <xs:complexType>
770             <xs:simpleContent>
771             <xs:extension base="xs:string">
772             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
773             </xs:extension>
774             </xs:simpleContent>
775             </xs:complexType>
776             </xs:element>
777            
778             <xs:element name="IndexCreate">
779             <xs:complexType>
780             <xs:simpleContent>
781             <xs:extension base="xs:string">
782             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
783             </xs:extension>
784             </xs:simpleContent>
785             </xs:complexType>
786             </xs:element>
787            
788             <xs:element name="IndexDrop">
789             <xs:complexType>
790             <xs:simpleContent>
791             <xs:extension base="xs:string">
792             <xs:attribute name="Name" use="required" type="xs:anySimpleType"/>
793             </xs:extension>
794             </xs:simpleContent>
795             </xs:complexType>
796             </xs:element>
797            
798             <!-- Insert stuff into database -->
799            
800             <xs:element name="Insert">
801             <xs:complexType>
802             <xs:sequence>
803             <xs:element ref="Data" maxOccurs="unbounded" />
804             </xs:sequence>
805             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
806             <xs:attribute name="Table" use="required" type="xs:anySimpleType"/>
807             <xs:attribute name="Version" use="optional" type="xs:anySimpleType"/>
808             </xs:complexType>
809             </xs:element>
810            
811             <xs:element name="Data">
812             <xs:complexType>
813             <xs:simpleContent>
814             <xs:extension base="xs:string">
815             <xs:attribute name="Key" use="optional" type="xs:anySimpleType"/>
816             <xs:attribute name="Type" use="optional" type="xs:anySimpleType"/>
817             </xs:extension>
818             </xs:simpleContent>
819             </xs:complexType>
820             </xs:element>
821            
822             </xs:schema>