Commit 921c7a8b authored by Administrator's avatar Administrator

Adds pets management with tests errors

The system now support complete pets managements. This commit has
some errors in the tests.
parent 51ffbb2d
# General # General
/bak /bak
.DS_Store
# Eclipse # Eclipse
.project .project
......
...@@ -14,7 +14,15 @@ CREATE TABLE `daaexample`.`users` ( ...@@ -14,7 +14,15 @@ CREATE TABLE `daaexample`.`users` (
PRIMARY KEY (`login`) PRIMARY KEY (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE USER 'daa'@'localhost' IDENTIFIED WITH mysql_native_password BY 'daa'; CREATE TABLE `daaexample`.`pet`(
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`animalType` varchar(50) NOT NULL,
`owner_id` int NOT NULL REFERENCES people(`id`) ON DELETE CASCADE,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE USER 'daa'@'localhost' IDENTIFIED BY 'daa';
GRANT ALL ON `daaexample`.* TO 'daa'@'localhost'; GRANT ALL ON `daaexample`.* TO 'daa'@'localhost';
INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Antón','Pérez'); INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Antón','Pérez');
...@@ -26,6 +34,12 @@ INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'María','Nu ...@@ -26,6 +34,12 @@ INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'María','Nu
INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Alba','Fernández'); INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Alba','Fernández');
INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Asunción','Jiménez'); INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Asunción','Jiménez');
INSERT INTO `daaexample`.`pet` (`id`, `name`, `animalType`, `owner_id`) VALUES (0, 'Tafi', 'Perro', 0);
INSERT INTO `daaexample`.`pet` (`id`, `name`, `animalType`, `owner_id`) VALUES (0, 'Tafi1', 'Perro', 0);
INSERT INTO `daaexample`.`pet` (`id`, `name`, `animalType`, `owner_id`) VALUES (0, 'Tafi2', 'Perro', 0);
INSERT INTO `daaexample`.`pet` (`id`, `name`, `animalType`, `owner_id`) VALUES (0, 'Tafi3', 'Perro', 0);
-- The password for each user is its login suffixed with "pass". For example, user "admin" has the password "adminpass". -- The password for each user is its login suffixed with "pass". For example, user "admin" has the password "adminpass".
INSERT INTO `daaexample`.`users` (`login`,`password`,`role`) INSERT INTO `daaexample`.`users` (`login`,`password`,`role`)
VALUES ('admin', '713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca','ADMIN'); VALUES ('admin', '713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca','ADMIN');
......
...@@ -14,5 +14,5 @@ CREATE TABLE `daaexample`.`users` ( ...@@ -14,5 +14,5 @@ CREATE TABLE `daaexample`.`users` (
PRIMARY KEY (`login`) PRIMARY KEY (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE USER 'daa'@'localhost' IDENTIFIED WITH mysql_native_password BY 'daa'; CREATE USER 'daa'@'localhost' IDENTIFIED BY 'daa';
GRANT ALL ON `daaexample`.* TO 'daa'@'localhost'; GRANT ALL ON `daaexample`.* TO 'daa'@'localhost';
This diff is collapsed.
{ {
"name": "daa-example", "name": "daa-example",
"version": "0.2.0-alpha.12", "version": "0.2.0-alpha.11",
"scripts": { "scripts": {
"ng": "./node_modules/.bin/ng", "ng": "./node_modules/.bin/ng",
"start": "./node_modules/.bin/ng serve", "start": "./node_modules/.bin/ng serve",
......
...@@ -46,6 +46,22 @@ const routes: Routes = [ ...@@ -46,6 +46,22 @@ const routes: Routes = [
loadChildren: () => import('./modules/people/people.module').then(m => m.PeopleModule) loadChildren: () => import('./modules/people/people.module').then(m => m.PeopleModule)
} }
] ]
},
{
path: 'pets',
component: MainPanelComponent,
canActivate: [AuthenticatedGuard],
children: [
{
path: '',
redirectTo: 'pet',
pathMatch: 'full'
},
{
path: 'pet',
loadChildren: () => import('./modules/pets/pets.module').then(m => m.PetsModule)
}
]
} }
]; ];
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
<div class="col-sm-3"> <div class="col-sm-3">
<button id="btnSubmit" class="btn btn-primary" <button id="btnSubmit" class="btn btn-primary"
(click)="onModify()">{{person.id === undefined ? 'Crear' : 'Editar'}}</button> (click)="onModify()">{{person.id === undefined ? 'Crear' : 'Editar'}}</button>
<button class="btn btn-primary pets" (click)="onPets(person)">Pets</button>
<button id="btnClear" class="btn" (click)="onClean()">Limpiar</button> <button id="btnClear" class="btn" (click)="onClean()">Limpiar</button>
</div> </div>
</div> </div>
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {PersonModel} from '../../models/person.model'; import {PersonModel} from '../../models/person.model';
import {Router} from '@angular/router';
@Component({ @Component({
selector: 'app-people-form', selector: 'app-people-form',
...@@ -36,9 +37,10 @@ export class PeopleFormComponent { ...@@ -36,9 +37,10 @@ export class PeopleFormComponent {
public name: string; public name: string;
public surname: string; public surname: string;
public constructor() { public constructor(private readonly router: Router) {
this.modify = new EventEmitter<PersonModel>(); this.modify = new EventEmitter<PersonModel>();
this.clean = new EventEmitter<never>(); this.clean = new EventEmitter<never>();
} }
@Input() @Input()
...@@ -60,6 +62,10 @@ export class PeopleFormComponent { ...@@ -60,6 +62,10 @@ export class PeopleFormComponent {
}); });
} }
public onPets(person: PersonModel): void {
this.router.navigate(['/pets']);
}
public onClean() { public onClean() {
this.clean.emit(); this.clean.emit();
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
<td class="col-sm-5 surname">{{person.surname}}</td> <td class="col-sm-5 surname">{{person.surname}}</td>
<td class="col-sm-3"> <td class="col-sm-3">
<button class="btn btn-primary edit" (click)="onEdit(person)">Edit</button> <button class="btn btn-primary edit" (click)="onEdit(person)">Edit</button>
<!--<button class="btn btn-primary pets" (click)="onPets(person)">Pets</button>-->
<button class="btn btn-warning delete" (click)="onDelete(person)">Delete</button> <button class="btn btn-warning delete" (click)="onDelete(person)">Delete</button>
</td> </td>
</tr> </tr>
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {PersonModel} from '../../models/person.model'; import {PersonModel} from '../../models/person.model';
import {PeopleService} from '../../services/people.service'; import {PeopleService} from '../../services/people.service';
//import {Router} from '@angular/router';
@Component({ @Component({
selector: 'app-people-list', selector: 'app-people-list',
...@@ -36,7 +37,7 @@ export class PeopleListComponent { ...@@ -36,7 +37,7 @@ export class PeopleListComponent {
@Output() @Output()
public readonly delete: EventEmitter<PersonModel>; public readonly delete: EventEmitter<PersonModel>;
public constructor() { public constructor(/*private router: Router*/) {
this.edit = new EventEmitter<PersonModel>(); this.edit = new EventEmitter<PersonModel>();
this.delete = new EventEmitter<PersonModel>(); this.delete = new EventEmitter<PersonModel>();
} }
...@@ -45,6 +46,10 @@ export class PeopleListComponent { ...@@ -45,6 +46,10 @@ export class PeopleListComponent {
this.edit.emit(person); this.edit.emit(person);
} }
/*public onPets(person: PersonModel): void {
this.router.navigate(['/pets']);
}*/
public onDelete(person: PersonModel) { public onDelete(person: PersonModel) {
this.delete.emit(person); this.delete.emit(person);
} }
......
...@@ -21,6 +21,7 @@ import { Component, OnInit } from '@angular/core'; ...@@ -21,6 +21,7 @@ import { Component, OnInit } from '@angular/core';
import {PersonModel} from '../../models/person.model'; import {PersonModel} from '../../models/person.model';
import {PeopleService} from '../../services/people.service'; import {PeopleService} from '../../services/people.service';
import {map, mergeMap} from 'rxjs/operators'; import {map, mergeMap} from 'rxjs/operators';
import {Router} from '@angular/router';
@Component({ @Component({
selector: 'app-people-main', selector: 'app-people-main',
...@@ -32,7 +33,8 @@ export class PeopleMainComponent implements OnInit { ...@@ -32,7 +33,8 @@ export class PeopleMainComponent implements OnInit {
public people: PersonModel[]; public people: PersonModel[];
public constructor( public constructor(
private readonly peopleService: PeopleService private readonly peopleService: PeopleService,
private router: Router
) { ) {
this.people = []; this.people = [];
this.clearActivePerson(); this.clearActivePerson();
......
<!--
~ DAA Example
~
~ Copyright (C) 2019 - Miguel Reboiro-Jato.
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<form id="pets-form" class="mb-5 mb-10">
<input name="id" type="hidden" value=""/>
<div class="row">
<div class="col-sm-3">
<input name="name" type="text" value="" placeholder="Nombre" class="form-control" required [(ngModel)]="name"/>
</div>
<div class="col-sm-3">
<input name="animalType" type="text" value="" placeholder="AnimalType" class="form-control" required
[(ngModel)]="animalType"/>
</div>
<select name="miselect" [(ngModel)]="owner_id" *ngIf="pet.id === undefined">
<option [value]="person.id" *ngFor="let person of people">{{person.name}} {{person.surname}}</option>
</select>
<div class="col-sm-3">
<button id="btnSubmit" class="btn btn-primary"
(click)="onModify()">{{pet.id === undefined ? 'Crear' : 'Editar'}}</button>
<button id="btnClear" class="btn" (click)="onClean()">Limpiar</button>
</div>
</div>
</form>
\ No newline at end of file
/*!
* DAA Example
*
* Copyright (C) 2019 - Miguel Reboiro-Jato.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* DAA Example
*
* Copyright (C) 2019 - Miguel Reboiro-Jato.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PetsFormComponent } from './pets-form.component';
describe('PetsFormComponent', () => {
let component: PetsFormComponent;
let fixture: ComponentFixture<PetsFormComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PetsFormComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PetsFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
/*
* DAA Example
*
* Copyright (C) 2019 - Miguel Reboiro-Jato.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {PetModel} from '../../models/pet.model';
import {PersonModel} from '../../../people/models/person.model';
@Component({
selector: 'app-pets-form',
templateUrl: './pets-form.component.html',
styleUrls: ['./pets-form.component.scss']
})
export class PetsFormComponent {
public activePet: PetModel;
@Output()
public readonly modify: EventEmitter<PetModel>;
@Output()
public readonly clean: EventEmitter<never>;
@Input()
public people: PersonModel[] = [];
public name: string;
public animalType: string;
public owner_id: number;
public constructor() {
this.modify = new EventEmitter<PetModel>();
this.clean = new EventEmitter<never>();
}
@Input()
public set pet(pet: PetModel) {
this.activePet = pet;
this.name = pet.name;
this.animalType = pet.animalType;
this.owner_id = pet.ownerId;
}
public get pet(): PetModel {
return this.activePet;
}
public onModify() {
this.modify.emit({
id: this.pet.id,
name: this.name,
animalType: this.animalType,
ownerId: this.owner_id
});
}
public onClean() {
this.clean.emit();
}
}
<!--
~ DAA Example
~
~ Copyright (C) 2019 - Javier Quintas Bergantiño.
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<table id="pets-list" class="table">
<thead>
<tr class="row">
<th class="col-sm-4">Nombre</th>
<th class="col-sm-5">Tipo</th>
<th class="col-sm-3">&nbsp;</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let pet of pets" class="row" id="pet-{{pet.id}}">
<td class="col-sm-4 name">{{pet.name}}</td>
<td class="col-sm-5 animalType">{{pet.animalType}}</td>
<td class="col-sm-3">
<button class="btn btn-primary edit" (click)="onEdit(pet)">Edit</button>
<button class="btn btn-warning delete" (click)="onDelete(pet)">Delete</button>
</td>
</tr>
</tbody>
</table>
\ No newline at end of file
/*!
* DAA Example
*
* Copyright (C) 2019 - Javier Quintas Bergantiño.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* DAA Example
*
* Copyright (C) 2019 - Miguel Reboiro-Jato.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PetsListComponent } from './pets-list.component';
describe('PetsListComponent', () => {
let component: PetsListComponent;
let fixture: ComponentFixture<PetsListComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PetsListComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PetsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
/*
* DAA Example
*
* Copyright (C) 2019 - Miguel Reboiro-Jato.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {PetModel} from '../../models/pet.model';
import {PetsService} from '../../services/pets.service';
@Component({
selector: 'app-pets-list',
templateUrl: './pets-list.component.html',
styleUrls: ['./pets-list.component.scss']
})
export class PetsListComponent {
@Input()
public pets: PetModel[] = [];
@Output()
public readonly edit: EventEmitter<PetModel>;
@Output()
public readonly delete: EventEmitter<PetModel>;
public constructor() {
this.edit = new EventEmitter<PetModel>();
this.delete = new EventEmitter<PetModel>();
}
public onEdit(pet: PetModel) {
this.edit.emit(pet);
}
public onDelete(pet: PetModel) {
this.delete.emit(pet);
}
}
<!--
~ DAA Example
~
~ Copyright (C) 2019 - Javier Quintas Bergantiño.
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<h1 class="display-5 mt-3 mb-3">Pets</h1>
<app-pets-form [pet]="activePet" [people]="people" (clean)="onCleanForm()" (modify)="onModifyForm($event)"></app-pets-form>
<app-pets-list [pets]="pets" (edit)="onEdit($event)" (delete)="onDelete($event)"></app-pets-list>
\ No newline at end of file
/*!
* DAA Example
*
* Copyright (C) 2019 - Javier Quintas Bergantiño.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* DAA Example
*
* Copyright (C) 2019 - Javier Quintas Bergantiño.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PetsMainComponent } from './pets-main.component';
describe('PetsMainComponent', () => {
let component: PetsMainComponent;
let fixture: ComponentFixture<PetsMainComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PetsMainComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PetsMainComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
/*
* DAA Example
*
* Copyright (C) 2019 - Javier Quintas Bergantiño.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, OnInit } from '@angular/core';
import {PetModel} from '../../models/pet.model';
import {PetsService} from '../../services/pets.service';
import {PeopleService} from '../../../people/services/people.service';
import {PersonModel} from '../../../people/models/person.model';
import {map, mergeMap} from 'rxjs/operators';
@Component({
selector: 'app-pets-main',
templateUrl: './pets-main.component.html',
styleUrls: ['./pets-main.component.scss']
})
export class PetsMainComponent implements OnInit {
public activePet: PetModel;
public pets: PetModel[];
public people: PersonModel[];
public constructor(
private readonly petsService: PetsService,
private readonly peopleService: PeopleService
) {
this.pets = [];
this.clearActivePet();
}
public ngOnInit(): void {
this.petsService.list()
.subscribe(pets =>
this.pets = pets
);
this.peopleService.list()
.subscribe(people =>
this.people = people
);
}
public onEdit(pet: PetModel): void {
this.activePet = pet;
}
public onDelete(pet: PetModel): void {
if (confirm(`¿Estás seguro de que deseas eliminar a ${pet.name} ${pet.animalType}?`)) {
this.petsService.delete(pet)
.pipe(
mergeMap(() => this.petsService.list())
)
.subscribe(pets => this.pets = pets);
}
}
public onCleanForm(): void {
this.clearActivePet();
}
public onModifyForm(pet: PetModel): void {
if (pet.id === undefined) {
this.petsService.create(pet)
.pipe(
mergeMap(() => this.petsService.list())
)
.subscribe(pets => {
this.pets = pets;
this.clearActivePet();
});
} else {
this.petsService.modify(pet)
.pipe(
mergeMap(() => this.petsService.list())
)
.subscribe(pets => {
this.pets = pets;
this.clearActivePet();
});
}
}
private clearActivePet(): void {
this.activePet = { id: undefined, name: '', animalType: '', ownerId: undefined };
}
}
/*
* DAA Example
*
* Copyright (C) 2019 - Javier Quintas Bergantiño.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export class PetModel {
id?: number;
name: string;
animalType: string;
ownerId: number;
}
\ No newline at end of file
/*
* DAA Example
*
* Copyright (C) 2019 - Javier Quintas Bergantiño.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {PetsMainComponent} from './components/pets-main/pets-main.component';
const routes: Routes = [
{
path: '',
component: PetsMainComponent
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PetsRoutingModule { }
\ No newline at end of file
/*
* DAA Example
*
* Copyright (C) 2019 - Javier Quintas Bergantiño.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {PetsRoutingModule} from './pets-routing.module';
import {PetsListComponent} from './components/pets-list/pets-list.component';
import {PetsFormComponent} from './components/pets-form/pets-form.component';
import {PetsMainComponent} from './components/pets-main/pets-main.component';
import {FormsModule} from '@angular/forms';
@NgModule({
declarations: [
PetsFormComponent,
PetsListComponent,
PetsMainComponent
],
imports: [
CommonModule,
FormsModule,
PetsRoutingModule
]
})
export class PetsModule {
}
\ No newline at end of file
/*
* DAA Example
*
* Copyright (C) 2019 - Javier Quintas Bergantiño.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { TestBed } from '@angular/core/testing';
import { PetsService } from './pets.service';
describe('PetsService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: PetsService = TestBed.get(PetsService);
expect(service).toBeTruthy();
})
})
\ No newline at end of file
/*
* DAA Example
*
* Copyright (C) 2019 - Javier Quintas Bergantiño.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {Injectable, Inject} from '@angular/core';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {environment} from '../../../../environments/environment';
import {Observable} from 'rxjs';
import {PetModel} from '../models/pet.model';
@Injectable({
providedIn: 'root'
})
export class PetsService{
public constructor(private readonly http: HttpClient) { }
public list(): Observable<PetModel[]> {
return this.http.get<PetModel[]>(`${environment.restApi}/pets`);
}
public create(pet: PetModel): Observable<PetModel> {
const data = new HttpParams()
.set('name', pet.name)
.set('animalType', pet.animalType)
.set('owner_id', pet.ownerId.toString());
return this.http.post<PetModel>(`${environment.restApi}/pets`, data);
}
public modify(pet: PetModel): Observable<PetModel> {
const data = new HttpParams()
.set('name', pet.name)
.set('animalType', pet.animalType)
.set('owner_id', pet.ownerId.toString());
return this.http.put<PetModel>(`${environment.restApi}/pets/${pet.id}`, data);
}
public delete(pet: PetModel): Observable<number> {
return this.http.delete<number>(`${environment.restApi}/pets/${pet.id}`);
}
}
\ No newline at end of file
...@@ -11,6 +11,7 @@ import javax.ws.rs.ApplicationPath; ...@@ -11,6 +11,7 @@ import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application; import javax.ws.rs.core.Application;
import es.uvigo.esei.daa.rest.PeopleResource; import es.uvigo.esei.daa.rest.PeopleResource;
import es.uvigo.esei.daa.rest.PetsResource;
import es.uvigo.esei.daa.rest.UsersResource; import es.uvigo.esei.daa.rest.UsersResource;
/** /**
...@@ -26,7 +27,8 @@ public class DAAExampleApplication extends Application { ...@@ -26,7 +27,8 @@ public class DAAExampleApplication extends Application {
public Set<Class<?>> getClasses() { public Set<Class<?>> getClasses() {
return Stream.of( return Stream.of(
PeopleResource.class, PeopleResource.class,
UsersResource.class UsersResource.class,
PetsResource.class
).collect(toSet()); ).collect(toSet());
} }
......
package es.uvigo.esei.daa.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import es.uvigo.esei.daa.entities.Pet;
/**
* DAO class for the {@link Pets} entities.
*
* @author Javier Quintas Bergantiño
*
*/
public class PetsDAO extends DAO {
private final static Logger LOG = Logger.getLogger(PetsDAO.class.getName());
public Pet get(int id) throws DAOException, IllegalArgumentException {
try (final Connection conn = this.getConnection()) {
final String query = "SELECT * FROM pet WHERE id=?";
try (final PreparedStatement statement = conn.prepareStatement(query)) {
statement.setInt(1, id);
try (final ResultSet result = statement.executeQuery()) {
if (result.next()) {
return rowToEntity(result);
} else {
throw new IllegalArgumentException("Invalid id");
}
}
}
} catch (SQLException e) {
LOG.log(Level.SEVERE, "Error getting a person", e);
throw new DAOException(e);
}
}
public List<Pet> list() throws DAOException {
try (final Connection conn = this.getConnection()) {
final String query = "SELECT * FROM pet";
try (final PreparedStatement statement = conn.prepareStatement(query)) {
try (final ResultSet result = statement.executeQuery()) {
final List<Pet> people = new LinkedList<>();
while (result.next()) {
people.add(rowToEntity(result));
}
return people;
}
}
} catch (SQLException e) {
LOG.log(Level.SEVERE, "Error listing pets", e);
throw new DAOException(e);
}
}
public Pet add(String name, String animalType, Integer owner_id)
throws DAOException, IllegalArgumentException {
if (name == null || owner_id == 0 || animalType == null) {
throw new IllegalArgumentException("name, animalType and owner_id can't be null");
}
try (Connection conn = this.getConnection()) {
final String query = "INSERT INTO pet VALUES(null, ?, ?, ?)";
try (PreparedStatement statement = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) {
statement.setString(1, name);
statement.setString(2, animalType);
statement.setInt(3, owner_id);
if (statement.executeUpdate() == 1) {
try (ResultSet resultKeys = statement.getGeneratedKeys()) {
if (resultKeys.next()) {
return new Pet(resultKeys.getInt(1), name, animalType, owner_id);
} else {
LOG.log(Level.SEVERE, "Error retrieving inserted id");
throw new SQLException("Error retrieving inserted id");
}
}
} else {
LOG.log(Level.SEVERE, "Error inserting value");
throw new SQLException("Error inserting value");
}
}
} catch (SQLException e) {
LOG.log(Level.SEVERE, "Error adding a pet", e);
throw new DAOException(e);
}
}
public void modify(Pet pet)
throws DAOException, IllegalArgumentException {
if (pet == null) {
throw new IllegalArgumentException("pet can't be null");
}
try (Connection conn = this.getConnection()) {
final String query = "UPDATE pet SET name=?, animalType=?, owner_id=? WHERE id=?";
try (PreparedStatement statement = conn.prepareStatement(query)) {
statement.setString(1, pet.getName());
statement.setString(2, pet.getAnimalType());
statement.setInt(3, pet.getOwnerId());
statement.setInt(4, pet.getId());
if (statement.executeUpdate() != 1) {
throw new IllegalArgumentException("name and owner_id can't be null");
}
}
} catch (SQLException e) {
LOG.log(Level.SEVERE, "Error modifying a person", e);
throw new DAOException();
}
}
public void delete(int id)
throws DAOException, IllegalArgumentException {
try (final Connection conn = this.getConnection()) {
final String query = "DELETE FROM pet WHERE id=?";
try (final PreparedStatement statement = conn.prepareStatement(query)) {
statement.setInt(1, id);
if (statement.executeUpdate() != 1) {
throw new IllegalArgumentException("Invalid id");
}
}
} catch (SQLException e) {
LOG.log(Level.SEVERE, "Error deleting a pet", e);
throw new DAOException(e);
}
}
private Pet rowToEntity(ResultSet row) throws SQLException {
return new Pet(
row.getInt("id"),
row.getString("name"),
row.getString("animalType"),
row.getInt("owner_id")
);
}
}
\ No newline at end of file
package es.uvigo.esei.daa.entities;
import static java.util.Objects.requireNonNull;
/**
* An entity that represents a pet.
*
* @author Javier Quintas Bergantiño
*/
public class Pet {
private int id;
private String name;
private String animalType;
private int owner_id;
Pet(){}
public Pet(int id, String name, String animalType, int owner_id) {
this.id = id;
this.setName(name);
this.setAnimalType(animalType);
this.owner_id = owner_id;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = requireNonNull(name, "Name can't be null");
}
public String getAnimalType() {
return animalType;
}
public void setAnimalType(String animalType) {
this.animalType = requireNonNull(animalType, "Animal type can't be null");
}
public int getOwnerId() {
return owner_id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Pet))
return false;
Pet other = (Pet) obj;
if (id != other.id)
return false;
return true;
}
}
\ No newline at end of file
package es.uvigo.esei.daa.rest;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import es.uvigo.esei.daa.dao.DAOException;
import es.uvigo.esei.daa.dao.PetsDAO;
import es.uvigo.esei.daa.entities.Pet;
/**
* REST resource for managing pets.
*
* @author Javier Quintas Bergantiño.
*/
@Path("/pets")
@Produces(MediaType.APPLICATION_JSON)
public class PetsResource {
private final static Logger LOG = Logger.getLogger(PetsResource.class.getName());
private final PetsDAO dao;
public PetsResource() {
this(new PetsDAO());
}
PetsResource(PetsDAO dao) {
this.dao = dao;
}
@GET
@Path("/{id}")
public Response get(
@PathParam("id") int id
) {
try {
final Pet pet = this.dao.get(id);
return Response.ok(pet).build();
} catch (IllegalArgumentException iae) {
LOG.log(Level.FINE, "Invalid pet id in get method", iae);
return Response.status(Response.Status.BAD_REQUEST)
.entity(iae.getMessage())
.build();
} catch (DAOException e) {
LOG.log(Level.SEVERE, "Error getting a pet", e);
return Response.serverError()
.entity(e.getMessage())
.build();
}
}
@GET
public Response list() {
try{
return Response.ok(this.dao.list()).build();
} catch (DAOException e) {
LOG.log(Level.SEVERE, "Error listing pet", e);
return Response.serverError().entity(e.getMessage()).build();
}
}
@POST
public Response add(
@FormParam("name") String name,
@FormParam("animalType") String animalType,
@FormParam("owner_id") Integer owner_id
) {
try {
final Pet newPet = this.dao.add(name, animalType, owner_id);
System.out.println(newPet.getName());
System.out.println(newPet.getAnimalType());
System.out.println(newPet.getOwnerId());
System.out.println(newPet.getId());
System.out.println(Response.ok(newPet).build());
return Response.ok(newPet).build();
} catch (IllegalArgumentException iae) {
LOG.log(Level.FINE, "Invalid pet id in add method", iae);
return Response.status(Response.Status.BAD_REQUEST)
.entity(iae.getMessage())
.build();
} catch (DAOException e) {
LOG.log(Level.SEVERE, "Error adding a pet", e);
return Response.serverError()
.entity(e.getMessage())
.build();
}
}
@PUT
@Path("/{id}")
public Response modify(
@PathParam("id") int id,
@FormParam("name") String name,
@FormParam("animalType") String animalType,
@FormParam("owner_id") int owner_id
) {
try {
final Pet modifiedPet = new Pet(id, name, animalType, owner_id);
this.dao.modify(modifiedPet);
return Response.ok(modifiedPet).build();
} catch (NullPointerException npe) {
final String message = String.format("Invalid data for pet (name: %s, animalType: %s, owner_id: %d", name, animalType, owner_id);
LOG.log(Level.FINE, message);
return Response.status(Response.Status.BAD_REQUEST)
.entity(message)
.build();
} catch (IllegalArgumentException iae) {
LOG.log(Level.FINE, "Invalid pet id in modify method", iae);
return Response.status(Response.Status.BAD_REQUEST)
.entity(iae.getMessage())
.build();
} catch (DAOException e) {
LOG.log(Level.SEVERE, "Error modifying a pet", e);
return Response.serverError()
.entity(e.getMessage())
.build();
}
}
@DELETE
@Path("/{id}")
public Response delete(
@PathParam("id") int id
) {
try {
this.dao.delete(id);
return Response.ok(id).build();
} catch (IllegalArgumentException iae) {
LOG.log(Level.FINE, "Invalid pet id in delete method", iae);
return Response.status(Response.Status.BAD_REQUEST)
.entity(iae.getMessage())
.build();
} catch (DAOException e) {
LOG.log(Level.SEVERE, "Error deleting a pet", e);
return Response.serverError()
.entity(e.getMessage())
.build();
}
}
}
\ No newline at end of file
package es.uvigo.esei.daa.dao;
import static es.uvigo.esei.daa.dataset.PetsDataset.existentId;
import static es.uvigo.esei.daa.dataset.PetsDataset.existentPet;
import static es.uvigo.esei.daa.dataset.PetsDataset.newName;
import static es.uvigo.esei.daa.dataset.PetsDataset.newPet;
import static es.uvigo.esei.daa.dataset.PetsDataset.newAnimalType;
import static es.uvigo.esei.daa.dataset.PetsDataset.nonExistentId;
import static es.uvigo.esei.daa.dataset.PetsDataset.nonExistentPet;
import static es.uvigo.esei.daa.dataset.PetsDataset.pets;
import static es.uvigo.esei.daa.dataset.PetsDataset.petsWithout;
import static es.uvigo.esei.daa.matchers.IsEqualToPet.containsPetsInAnyOrder;
import static es.uvigo.esei.daa.matchers.IsEqualToPet.equalsToPet;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import javax.sql.DataSource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.github.springtestdbunit.annotation.ExpectedDatabase;
import es.uvigo.esei.daa.entities.Pet;
import es.uvigo.esei.daa.listeners.ApplicationContextBinding;
import es.uvigo.esei.daa.listeners.ApplicationContextJndiBindingTestExecutionListener;
import es.uvigo.esei.daa.listeners.DbManagement;
import es.uvigo.esei.daa.listeners.DbManagementTestExecutionListener;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:contexts/mem-context.xml")
@TestExecutionListeners({
DbUnitTestExecutionListener.class,
DbManagementTestExecutionListener.class,
ApplicationContextJndiBindingTestExecutionListener.class
})
@ApplicationContextBinding(
jndiUrl = "java:/comp/env/jdbc/daaexample",
type = DataSource.class
)
@DbManagement(
create = "classpath:db/hsqldb.sql",
drop = "classpath:db/hsqldb-drop.sql"
)
@DatabaseSetup("/datasets/dataset.xml")
@ExpectedDatabase("/datasets/dataset.xml")
public class PetsDAOTest {
private PetsDAO dao;
@Before
public void setUp() throws Exception {
this.dao = new PetsDAO();
}
@Test
public void testList() throws DAOException {
assertThat(this.dao.list(), containsPetsInAnyOrder(pets()));
}
@Test
public void testGet() throws DAOException {
final Pet pet = this.dao.get(existentId());
assertThat(pet, is(equalsToPet(existentPet())));
}
@Test(expected = IllegalArgumentException.class)
public void testGetNonExistentId() throws DAOException {
this.dao.get(nonExistentId());
}
@Test
@ExpectedDatabase("/datasets/dataset-delete.xml")
public void testDelete() throws DAOException {
this.dao.delete(existentId());
assertThat(this.dao.list(), containsPetsInAnyOrder(petsWithout(existentId())));
}
@Test(expected = IllegalArgumentException.class)
public void testDeleteNonExistentId() throws DAOException {
this.dao.delete(nonExistentId());
}
@Test
@ExpectedDatabase("/datasets/dataset-modify-pets.xml")
public void testModify() throws DAOException {
final Pet pet = existentPet();
pet.setName(newName());
pet.setAnimalType(newAnimalType());
this.dao.modify(pet);
final Pet persistentPet = this.dao.get(pet.getId());
assertThat(persistentPet, is(equalsToPet(pet)));
}
@Test(expected = IllegalArgumentException.class)
public void testModifyNonExistentId() throws DAOException {
this.dao.modify(nonExistentPet());
}
@Test(expected = IllegalArgumentException.class)
public void testModifyNullPet() throws DAOException {
this.dao.modify(null);
}
@Test
@ExpectedDatabase("/datasets/dataset-add-pets.xml")
public void testAdd() throws DAOException {
final Pet pet = this.dao.add(newName(), newAnimalType(), 1);
assertThat(pet, is(equalsToPet(newPet())));
final Pet persistentPet = this.dao.get(pet.getId());
assertThat(persistentPet, is(equalsToPet(newPet())));
}
@Test(expected = IllegalArgumentException.class)
public void testAddNullName() throws DAOException {
this.dao.add(null, newAnimalType(), 1);
}
@Test(expected = IllegalArgumentException.class)
public void testAddNullAnimalType() throws DAOException {
this.dao.add(newName(), null, 1);
}
@Test(expected = IllegalArgumentException.class)
public void testAddNullOwnerId() throws DAOException {
this.dao.add(newName(), newAnimalType(), 0);
}
}
package es.uvigo.esei.daa.dao;
import static org.junit.Assert.*;
import static es.uvigo.esei.daa.dataset.PetsDataset.existentId;
import static es.uvigo.esei.daa.dataset.PetsDataset.newName;
import static es.uvigo.esei.daa.dataset.PetsDataset.newPet;
import static es.uvigo.esei.daa.dataset.PetsDataset.newAnimalType;
import static es.uvigo.esei.daa.dataset.PetsDataset.pet;
import static es.uvigo.esei.daa.dataset.PetsDataset.existentPet;
import static es.uvigo.esei.daa.dataset.PetsDataset.pets;
import static es.uvigo.esei.daa.matchers.IsEqualToPet.containsPetsInAnyOrder;
import static es.uvigo.esei.daa.matchers.IsEqualToPet.equalsToPet;
import static org.easymock.EasyMock.anyString;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.reset;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.sql.SQLException;
import org.junit.Test;
import com.mysql.jdbc.Statement;
import es.uvigo.esei.daa.entities.Pet;
import es.uvigo.esei.daa.util.DatabaseQueryUnitTest;
public class PetsDAOUnitTest extends DatabaseQueryUnitTest {
@Test
public void testList() throws Exception {
final Pet[] pets = pets();
for (Pet pet : pets) {
expectPetRow(pet);
}
expect(result.next()).andReturn(false);
result.close();
replayAll();
final PetsDAO petsDAO = new PetsDAO();
assertThat(petsDAO.list(), containsPetsInAnyOrder(pets));
}
@Test(expected = DAOException.class)
public void testListUnexpectedException() throws Exception {
expect(result.next()).andThrow(new SQLException());
result.close();
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.list();
}
@Test
public void testGet() throws Exception {
final Pet existentPet = existentPet();
expectPetRow(existentPet);
result.close();
replayAll();
final PetsDAO petsDAO = new PetsDAO();
assertThat(petsDAO.get(existentId()), is(equalTo(existentPet)));
}
@Test(expected = IllegalArgumentException.class)
public void testGetMissing() throws Exception {
expect(result.next()).andReturn(false);
result.close();
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.get(existentId());
}
@Test(expected = DAOException.class)
public void testGetUnexpectedException() throws Exception {
expect(result.next()).andThrow(new SQLException());
result.close();
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.get(existentId());
}
@Test
public void testAdd() throws Exception {
final Pet pet = newPet();
reset(connection);
expect(connection.prepareStatement(anyString(), eq(Statement.RETURN_GENERATED_KEYS)))
.andReturn(statement);
expect(statement.executeUpdate()).andReturn(1);
expect(statement.getGeneratedKeys()).andReturn(result);
// Key retrieval
expect(result.next()).andReturn(true);
expect(result.getInt(1)).andReturn(pet.getId());
connection.close();
result.close();
replayAll();
final PetsDAO petsDAO = new PetsDAO();
final Pet newPet = petsDAO.add(pet.getName(), pet.getAnimalType(), pet.getOwnerId());
assertThat(newPet, is(equalsToPet(pet)));
}
@Test(expected = IllegalArgumentException.class)
public void testAddNullName() throws Exception {
replayAll();
final PetsDAO petsDAO = new PetsDAO();
resetAll(); // No expectations
petsDAO.add(null, newAnimalType(), 1);
}
@Test(expected = IllegalArgumentException.class)
public void testAddNullAnimalType() throws Exception {
replayAll();
final PetsDAO petsDAO = new PetsDAO();
resetAll(); // No expectations
petsDAO.add(newName(), null, 1);
}
@Test(expected = DAOException.class)
public void testAddZeroUpdatedRows() throws Exception {
reset(connection);
expect(connection.prepareStatement(anyString(), eq(1)))
.andReturn(statement);
expect(statement.executeUpdate()).andReturn(0);
connection.close();
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.add(newName(), newAnimalType(), 1);
}
@Test(expected = DAOException.class)
public void testAddNoGeneratedKey() throws Exception {
reset(connection);
expect(connection.prepareStatement(anyString(), eq(1)))
.andReturn(statement);
expect(statement.executeUpdate()).andReturn(1);
expect(statement.getGeneratedKeys()).andReturn(result);
expect(result.next()).andReturn(false);
result.close();
connection.close();
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.add(newName(), newAnimalType(), 1);
}
@Test(expected = DAOException.class)
public void testAddUnexpectedException() throws Exception {
reset(connection);
expect(connection.prepareStatement(anyString(), eq(1)))
.andReturn(statement);
expect(statement.executeUpdate()).andThrow(new SQLException());
connection.close();
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.add(newName(), newAnimalType(), 1);
}
@Test
public void testDelete() throws Exception {
expect(statement.executeUpdate()).andReturn(1);
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.delete(existentId());
}
@Test(expected = IllegalArgumentException.class)
public void testDeleteInvalidId() throws Exception {
expect(statement.executeUpdate()).andReturn(0);
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.delete(existentId());
}
@Test(expected = DAOException.class)
public void testDeleteUnexpectedException() throws Exception {
expect(statement.executeUpdate()).andThrow(new SQLException());
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.delete(existentId());
}
@Test
public void testModify() throws Exception {
expect(statement.executeUpdate()).andReturn(1);
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.modify(existentPet());
}
@Test(expected = IllegalArgumentException.class)
public void testModifyNullPet() throws Exception {
replayAll();
final PetsDAO petsDAO = new PetsDAO();
resetAll(); // No expectations
petsDAO.modify(null);
}
@Test(expected = IllegalArgumentException.class)
public void testModifyZeroUpdatedRows() throws Exception {
expect(statement.executeUpdate()).andReturn(0);
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.modify(existentPet());
}
@Test(expected = DAOException.class)
public void testModifyUnexpectedException() throws Exception {
expect(statement.executeUpdate()).andThrow(new SQLException());
replayAll();
final PetsDAO petsDAO = new PetsDAO();
petsDAO.modify(existentPet());
}
private void expectPetRow(Pet pet) throws SQLException {
expect(result.next()).andReturn(true);
expect(result.getInt("id")).andReturn(pet.getId());
expect(result.getString("name")).andReturn(pet.getName());
expect(result.getString("animalType")).andReturn(pet.getAnimalType());
expect(result.getInt("owner_id")).andReturn(pet.getOwnerId());
}
}
package es.uvigo.esei.daa.dataset;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.function.Predicate;
import static java.util.Arrays.binarySearch;
import static java.util.Arrays.stream;
import org.junit.Test;
import es.uvigo.esei.daa.entities.Pet;
public class PetsDataset {
private PetsDataset() {}
public static Pet[] pets() {
return new Pet[] {
new Pet(1, "Tafi", "Perro", 1),
new Pet(2, "Tafi1", "Perro1", 1),
new Pet(3, "Tafi2", "Perro2", 1),
new Pet(4, "Tafi3", "Perro3", 1),
new Pet(5, "Tafi4", "Perro4", 1),
new Pet(6, "Tafi5", "Perro5", 1)
};
}
public static Pet[] petsWithout(int ... ids) {
Arrays.sort(ids);
final Predicate<Pet> hasValidId = pet ->
binarySearch(ids, pet.getId()) < 0;
return stream(pets())
.filter(hasValidId)
.toArray(Pet[]::new);
}
public static Pet pet(int id) {
return stream(pets())
.filter(pet -> pet.getId() == id)
.findAny()
.orElseThrow(IllegalArgumentException::new);
}
public static int existentId() {
return 5;
}
public static int nonExistentId() {
return 1234;
}
public static Pet existentPet() {
return pet(existentId());
}
public static Pet nonExistentPet() {
return new Pet(nonExistentId(), "Tafi10", "Perro10", 1);
}
public static String newName() {
return "Tafi7";
}
public static String newAnimalType() {
return "Perro6";
}
public static Pet newPet() {
return new Pet(pets().length + 1, newName(), newAnimalType(), 1);
}
}
package es.uvigo.esei.daa.entities;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import org.junit.Test;
import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;
public class PetUnitTest {
@Test
public void testPetIntStringStringInt() {
final int id = 1;
final String name = "Tafi";
final String animalType = "Perro";
final int owner_id = 1;
final Pet pet = new Pet(id, name, animalType, owner_id);
assertThat(pet.getId(), is(equalTo(id)));
assertThat(pet.getName(), is(equalTo(name)));
assertThat(pet.getAnimalType(), is(equalTo(animalType)));
assertThat(pet.getOwnerId(), is(equalTo(owner_id)));
}
@Test(expected = NullPointerException.class)
public void testPersonIntStringStringIntNullName() {
new Pet(1, null, "Perro", 1);
}
@Test(expected = NullPointerException.class)
public void testPersonIntStringStringIntNullAnimalType() {
new Pet(1, "Tafi", null, 1);
}
@Test(expected = NullPointerException.class)
public void testPersonIntStringStringNullOwnerId() {
Integer own = null;
new Pet(1, "Tafi", "Perro", own);
}
@Test
public void testSetName() {
final int id = 1;
final String animalType = "Perro";
final Pet pet = new Pet(id, "Tafi", animalType, 1);
pet.setName("Sultan");
assertThat(pet.getId(), is(equalTo(id)));
assertThat(pet.getName(), is(equalTo("Sultan")));
assertThat(pet.getAnimalType(), is(equalTo(animalType)));
assertThat(pet.getOwnerId(), is(equalTo(1)));
}
@Test(expected = NullPointerException.class)
public void testSetNullName() {
final Pet pet = new Pet(1, "Tafi", "Perro", 1);
pet.setName(null);
}
@Test
public void testSetAnimalType() {
final int id = 1;
final String name = "Tafi";
final Pet pet = new Pet(id, name, "Perro", 1);
pet.setAnimalType("Elefante");
assertThat(pet.getId(), is(equalTo(id)));
assertThat(pet.getName(), is(equalTo(name)));
assertThat(pet.getAnimalType(), is(equalTo("Elefante")));
assertThat(pet.getOwnerId(), is(equalTo(1)));
}
@Test(expected = NullPointerException.class)
public void testSetNullAnimalType() {
final Pet pet = new Pet(1, "Tafi", "Perro", 1);
pet.setAnimalType(null);
}
@Test
public void testEqualsObject() {
final Pet petA = new Pet(1, "Name A", "AnimalType A", 1);
final Pet petB = new Pet(1, "Name B", "AnimalType B", 1);
assertTrue(petA.equals(petB));
}
@Test
public void testEqualsHashcode() {
EqualsVerifier.forClass(Pet.class)
.withIgnoredFields("name", "animalType", "owner_id")
.suppress(Warning.STRICT_INHERITANCE)
.suppress(Warning.NONFINAL_FIELDS)
.verify();
}
}
...@@ -56,9 +56,13 @@ public class AuthorizationFilter implements ContainerRequestFilter { ...@@ -56,9 +56,13 @@ public class AuthorizationFilter implements ContainerRequestFilter {
if (isPeoplePath(requestContext) && !user.getRole().equals("ADMIN")) { if (isPeoplePath(requestContext) && !user.getRole().equals("ADMIN")) {
requestContext.abortWith(createResponse()); requestContext.abortWith(createResponse());
} else {
if(isPetsPath(requestContext) && !user.getRole().contentEquals("ADMIN")) {
requestContext.abortWith(createResponse());
} else { } else {
requestContext.setSecurityContext(new UserSecurityContext(user)); requestContext.setSecurityContext(new UserSecurityContext(user));
} }
}
} else { } else {
requestContext.abortWith(createResponse()); requestContext.abortWith(createResponse());
} }
...@@ -76,6 +80,11 @@ public class AuthorizationFilter implements ContainerRequestFilter { ...@@ -76,6 +80,11 @@ public class AuthorizationFilter implements ContainerRequestFilter {
return !pathSegments.isEmpty() && pathSegments.get(0).getPath().equals("people"); return !pathSegments.isEmpty() && pathSegments.get(0).getPath().equals("people");
} }
private static boolean isPetsPath(ContainerRequestContext context) {
final List<PathSegment> pathSegments = context.getUriInfo().getPathSegments();
return !pathSegments.isEmpty() && pathSegments.get(0).getPath().contentEquals("pets");
}
private static Response createResponse() { private static Response createResponse() {
return Response.status(Status.UNAUTHORIZED) return Response.status(Status.UNAUTHORIZED)
.header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"DAAExample\"") .header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"DAAExample\"")
......
package es.uvigo.esei.daa.matchers;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import es.uvigo.esei.daa.entities.Person;
import es.uvigo.esei.daa.entities.Pet;
public class IsEqualToPet extends IsEqualToEntity<Pet> {
public IsEqualToPet(Pet entity) {
super(entity);
}
@Override
protected boolean matchesSafely(Pet actual) {
this.clearDescribeTo();
if (actual == null) {
this.addTemplatedDescription("actual", expected.toString());
return false;
} else {
return checkAttribute("id", Pet::getId, actual)
&& checkAttribute("name", Pet::getName, actual)
&& checkAttribute("animalType", Pet::getAnimalType, actual)
&& checkAttribute("owner_id", Pet::getOwnerId, actual);
}
}
/**
* Factory method that creates a new {@link IsEqualToEntity} matcher with
* the provided {@link Person} as the expected value.
*
* @param person the expected person.
* @return a new {@link IsEqualToEntity} matcher with the provided
* {@link Pet} as the expected value.
*/
@Factory
public static IsEqualToPet equalsToPet(Pet pet) {
return new IsEqualToPet(pet);
}
/**
* Factory method that returns a new {@link Matcher} that includes several
* {@link IsEqualToPet} matchers, each one using an {@link Pet} of the
* provided ones as the expected value.
*
* @param persons the persons to be used as the expected values.
* @return a new {@link Matcher} that includes several
* {@link IsEqualToPet} matchers, each one using an {@link Pet} of the
* provided ones as the expected value.
* @see IsEqualToEntity#containsEntityInAnyOrder(java.util.function.Function, Object...)
*/
@Factory
public static Matcher<Iterable<? extends Pet>> containsPetsInAnyOrder(Pet ... pets) {
return containsEntityInAnyOrder(IsEqualToPet::equalsToPet, pets);
}
}
This diff is collapsed.
package es.uvigo.esei.daa.rest;
import static es.uvigo.esei.daa.dataset.PetsDataset.existentId;
import static es.uvigo.esei.daa.dataset.PetsDataset.existentPet;
import static es.uvigo.esei.daa.dataset.PetsDataset.newName;
import static es.uvigo.esei.daa.dataset.PetsDataset.newPet;
import static es.uvigo.esei.daa.dataset.PetsDataset.newAnimalType;
import static es.uvigo.esei.daa.dataset.PetsDataset.pets;
import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasBadRequestStatus;
import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasInternalServerErrorStatus;
import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasOkStatus;
import static es.uvigo.esei.daa.matchers.IsEqualToPet.containsPetsInAnyOrder;
import static es.uvigo.esei.daa.matchers.IsEqualToPet.equalsToPet;
import static java.util.Arrays.asList;
import static org.easymock.EasyMock.anyInt;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.anyString;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
import java.util.List;
import javax.ws.rs.core.Response;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import es.uvigo.esei.daa.dao.DAOException;
import es.uvigo.esei.daa.dao.PetsDAO;
import es.uvigo.esei.daa.entities.Pet;
public class PetsResourceUnitTest {
private PetsDAO daoMock;
private PetsResource resource;
@Before
public void setUp() throws Exception {
daoMock = createMock(PetsDAO.class);
resource = new PetsResource(daoMock);
}
@After
public void tearDown() throws Exception {
try {
verify(daoMock);
} finally {
daoMock = null;
resource = null;
}
}
@Test
@SuppressWarnings("unchecked")
public void testList() throws Exception {
final List<Pet> pets = asList(pets());
expect(daoMock.list()).andReturn(pets);
replay(daoMock);
final Response response = resource.list();
assertThat(response, hasOkStatus());
assertThat((List<Pet>) response.getEntity(), containsPetsInAnyOrder(pets()));
}
@Test
public void testListDAOException() throws Exception {
expect(daoMock.list()).andThrow(new DAOException());
replay(daoMock);
final Response response = resource.list();
assertThat(response, hasInternalServerErrorStatus());
}
@Test
public void testGet() throws Exception {
final Pet pet = existentPet();
expect(daoMock.get(pet.getId())).andReturn(pet);
replay(daoMock);
final Response response = resource.get(pet.getId());
assertThat(response, hasOkStatus());
assertThat((Pet) response.getEntity(), is(equalsToPet(pet)));
}
@Test
public void testGetDAOException() throws Exception {
expect(daoMock.get(anyInt())).andThrow(new DAOException());
replay(daoMock);
final Response response = resource.get(existentId());
assertThat(response, hasInternalServerErrorStatus());
}
@Test
public void testGetIllegalArgumentException() throws Exception {
expect(daoMock.get(anyInt())).andThrow(new IllegalArgumentException());
replay(daoMock);
final Response response = resource.get(existentId());
assertThat(response, hasBadRequestStatus());
}
@Test
public void testDelete() throws Exception {
daoMock.delete(anyInt());
replay(daoMock);
final Response response = resource.delete(1);
assertThat(response, hasOkStatus());
}
@Test
public void testDeleteDAOException() throws Exception {
daoMock.delete(anyInt());
expectLastCall().andThrow(new DAOException());
replay(daoMock);
final Response response = resource.delete(1);
assertThat(response, hasInternalServerErrorStatus());
}
@Test
public void testDeleteIllegalArgumentException() throws Exception {
daoMock.delete(anyInt());
expectLastCall().andThrow(new IllegalArgumentException());
replay(daoMock);
final Response response = resource.delete(1);
assertThat(response, hasBadRequestStatus());
}
@Test
public void testModify() throws Exception {
final Pet pet = existentPet();
pet.setName(newName());
pet.setAnimalType(newAnimalType());
daoMock.modify(pet);
replay(daoMock);
final Response response = resource.modify(
pet.getId(), pet.getName(), pet.getAnimalType(), pet.getOwnerId());
assertThat(response, hasOkStatus());
assertEquals(pet, response.getEntity());
}
@Test
public void testModifyDAOException() throws Exception {
daoMock.modify(anyObject());
expectLastCall().andThrow(new DAOException());
replay(daoMock);
final Response response = resource.modify(existentId(), newName(), newAnimalType(), 1);
assertThat(response, hasInternalServerErrorStatus());
}
@Test
public void testModifyIllegalArgumentException() throws Exception {
daoMock.modify(anyObject());
expectLastCall().andThrow(new IllegalArgumentException());
replay(daoMock);
final Response response = resource.modify(existentId(), newName(), newAnimalType(), 1);
assertThat(response, hasBadRequestStatus());
}
@Test
public void testModifyNullPointerException() throws Exception {
daoMock.modify(anyObject());
expectLastCall().andThrow(new NullPointerException());
replay(daoMock);
final Response response = resource.modify(existentId(), newName(), newAnimalType(), 1);
assertThat(response, hasBadRequestStatus());
}
@Test
public void testAdd() throws Exception {
expect(daoMock.add(newName(), newAnimalType(), 1))
.andReturn(newPet());
replay(daoMock);
final Response response = resource.add(newName(), newAnimalType(), 1);
assertThat(response, hasOkStatus());
assertThat((Pet) response.getEntity(), is(equalsToPet(newPet())));
}
@Test
public void testAddDAOException() throws Exception {
expect(daoMock.add(anyString(), anyString(), anyInt()))
.andThrow(new DAOException());
replay(daoMock);
final Response response = resource.add(newName(), newAnimalType(), 1);
assertThat(response, hasInternalServerErrorStatus());
}
@Test
public void testAddIllegalArgumentException() throws Exception {
expect(daoMock.add(anyString(), anyString(), anyInt()))
.andThrow(new IllegalArgumentException());
replay(daoMock);
final Response response = resource.add(newName(), newAnimalType(), 1);
assertThat(response, hasBadRequestStatus());
}
}
...@@ -7,11 +7,15 @@ import org.junit.runners.Suite.SuiteClasses; ...@@ -7,11 +7,15 @@ import org.junit.runners.Suite.SuiteClasses;
import es.uvigo.esei.daa.dao.PeopleDAOTest; import es.uvigo.esei.daa.dao.PeopleDAOTest;
import es.uvigo.esei.daa.rest.PeopleResourceTest; import es.uvigo.esei.daa.rest.PeopleResourceTest;
import es.uvigo.esei.daa.rest.UsersResourceTest; import es.uvigo.esei.daa.rest.UsersResourceTest;
import es.uvigo.esei.daa.dao.PetsDAOTest;
import es.uvigo.esei.daa.rest.PetsResourceTest;
@SuiteClasses({ @SuiteClasses({
PeopleDAOTest.class, PeopleDAOTest.class,
PeopleResourceTest.class, PeopleResourceTest.class,
UsersResourceTest.class UsersResourceTest.class,
PetsDAOTest.class,
PetsResourceTest.class
}) })
@RunWith(Suite.class) @RunWith(Suite.class)
public class IntegrationTestSuite { public class IntegrationTestSuite {
......
...@@ -8,10 +8,17 @@ import es.uvigo.esei.daa.dao.PeopleDAOUnitTest; ...@@ -8,10 +8,17 @@ import es.uvigo.esei.daa.dao.PeopleDAOUnitTest;
import es.uvigo.esei.daa.entities.PersonUnitTest; import es.uvigo.esei.daa.entities.PersonUnitTest;
import es.uvigo.esei.daa.rest.PeopleResourceUnitTest; import es.uvigo.esei.daa.rest.PeopleResourceUnitTest;
import es.uvigo.esei.daa.dao.PetsDAOUnitTest;
import es.uvigo.esei.daa.entities.PetUnitTest;
import es.uvigo.esei.daa.rest.PetsResourceUnitTest;
@SuiteClasses({ @SuiteClasses({
PersonUnitTest.class, PersonUnitTest.class,
PeopleDAOUnitTest.class, PeopleDAOUnitTest.class,
PeopleResourceUnitTest.class PeopleResourceUnitTest.class,
PetUnitTest.class,
PetsDAOUnitTest.class,
PetsResourceUnitTest.class
}) })
@RunWith(Suite.class) @RunWith(Suite.class)
public class UnitTestSuite { public class UnitTestSuite {
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dataset SYSTEM "dataset.dtd">
<dataset>
<people id="1" name="Antón" surname="Álvarez" />
<people id="2" name="Ana" surname="Amargo" />
<people id="3" name="Manuel" surname="Martínez" />
<people id="4" name="María" surname="Márquez" />
<people id="5" name="Lorenzo" surname="López" />
<people id="6" name="Laura" surname="Laredo" />
<people id="7" name="Perico" surname="Palotes" />
<people id="8" name="Patricia" surname="Pérez" />
<people id="9" name="Julia" surname="Justa" />
<people id="10" name="Juan" surname="Jiménez" />
<users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/>
<users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" />
<pet id="1" name="Tafi" animalType="Perro" owner_id="1"/>
<pet id="2" name="Tafi1" animalType="Perro1" owner_id="1"/>
<pet id="3" name="Tafi2" animalType="Perro2" owner_id="1"/>
<pet id="4" name="Tafi3" animalType="Perro3" owner_id="1"/>
<pet id="5" name="Tafi4" animalType="Perro4" owner_id="1"/>
<pet id="6" name="Tafi5" animalType="Perro5" owner_id="1"/>
<pet id="7" name="Tafi7" animalType="Perro6" owner_id="1"/>
</dataset>
\ No newline at end of file
...@@ -16,4 +16,13 @@ ...@@ -16,4 +16,13 @@
<users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/> <users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/>
<users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" /> <users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" />
<pet id="1" name="Tafi" animalType="Perro" owner_id="1"/>
<pet id="2" name="Tafi1" animalType="Perro1" owner_id="1"/>
<pet id="3" name="Tafi2" animalType="Perro2" owner_id="1"/>
<pet id="4" name="Tafi3" animalType="Perro3" owner_id="1"/>
<pet id="5" name="Tafi4" animalType="Perro4" owner_id="1"/>
<pet id="6" name="Tafi5" animalType="Perro5" owner_id="1"/>
<pet id="7" name="Tafi7" animalType="Perro6" owner_id="1"/>
</dataset> </dataset>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dataset SYSTEM "dataset.dtd">
<dataset>
<people id="1" name="Antón" surname="Álvarez" />
<people id="2" name="Ana" surname="Amargo" />
<people id="3" name="Manuel" surname="Martínez" />
<people id="4" name="María" surname="Márquez" />
<people id="5" name="Lorenzo" surname="López" />
<people id="6" name="Laura" surname="Laredo" />
<people id="7" name="Perico" surname="Palotes" />
<people id="8" name="Patricia" surname="Pérez" />
<people id="9" name="Julia" surname="Justa" />
<people id="10" name="Juan" surname="Jiménez" />
<users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/>
<users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" />
<pet id="1" name="Tafi" animalType="Perro" owner_id="1"/>
<pet id="2" name="Tafi1" animalType="Perro1" owner_id="1"/>
<pet id="3" name="Tafi2" animalType="Perro2" owner_id="1"/>
<pet id="4" name="Tafi3" animalType="Perro3" owner_id="1"/>
<pet id="6" name="Tafi5" animalType="Perro5" owner_id="1"/>
</dataset>
\ No newline at end of file
...@@ -14,4 +14,10 @@ ...@@ -14,4 +14,10 @@
<users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/> <users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/>
<users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" /> <users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" />
<pet id="1" name="Tafi" animalType="Perro" owner_id="1"/>
<pet id="2" name="Tafi1" animalType="Perro1" owner_id="1"/>
<pet id="3" name="Tafi2" animalType="Perro2" owner_id="1"/>
<pet id="4" name="Tafi3" animalType="Perro3" owner_id="1"/>
<pet id="6" name="Tafi5" animalType="Perro5" owner_id="1"/>
</dataset> </dataset>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dataset SYSTEM "dataset.dtd">
<dataset>
<people id="1" name="Antón" surname="Álvarez" />
<people id="2" name="Ana" surname="Amargo" />
<people id="3" name="Manuel" surname="Martínez" />
<people id="4" name="María" surname="Márquez" />
<people id="5" name="Lorenzo" surname="López" />
<people id="6" name="Laura" surname="Laredo" />
<people id="7" name="Perico" surname="Palotes" />
<people id="8" name="Patricia" surname="Pérez" />
<people id="9" name="Julia" surname="Justa" />
<people id="10" name="Juan" surname="Jiménez" />
<users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/>
<users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" />
<pet id="1" name="Tafi" animalType="Perro" owner_id="1"/>
<pet id="2" name="Tafi1" animalType="Perro1" owner_id="1"/>
<pet id="3" name="Tafi2" animalType="Perro2" owner_id="1"/>
<pet id="4" name="Tafi3" animalType="Perro3" owner_id="1"/>
<pet id="5" name="Tafi7" animalType="Perro6" owner_id="1"/>
<pet id="6" name="Tafi5" animalType="Perro5" owner_id="1"/>
</dataset>
\ No newline at end of file
...@@ -15,4 +15,12 @@ ...@@ -15,4 +15,12 @@
<users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/> <users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/>
<users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" /> <users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" />
<pet id="1" name="Tafi" animalType="Perro" owner_id="1"/>
<pet id="2" name="Tafi1" animalType="Perro1" owner_id="1"/>
<pet id="3" name="Tafi2" animalType="Perro2" owner_id="1"/>
<pet id="4" name="Tafi3" animalType="Perro3" owner_id="1"/>
<pet id="5" name="Tafi7" animalType="Perro6" owner_id="1"/>
<pet id="6" name="Tafi5" animalType="Perro5" owner_id="1"/>
</dataset> </dataset>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT dataset (people*, users*)> <!ELEMENT dataset (people*, users*, pet*)>
<!ELEMENT people EMPTY> <!ELEMENT people EMPTY>
<!ELEMENT users EMPTY> <!ELEMENT users EMPTY>
<!ELEMENT pet EMPTY>
<!ATTLIST people <!ATTLIST people
id CDATA #IMPLIED id CDATA #IMPLIED
name CDATA #IMPLIED name CDATA #IMPLIED
...@@ -12,3 +13,9 @@ ...@@ -12,3 +13,9 @@
password CDATA #IMPLIED password CDATA #IMPLIED
role CDATA #IMPLIED role CDATA #IMPLIED
> >
<!ATTLIST pet
id CDATA #IMPLIED
name CDATA #IMPLIED
animalType CDATA #IMPLIED
owner_id CDATA #IMPLIED
>
...@@ -15,4 +15,12 @@ ...@@ -15,4 +15,12 @@
<users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/> <users login="admin" password="713bfda78870bf9d1b261f565286f85e97ee614efe5f0faf7c34e7ca4f65baca" role="ADMIN"/>
<users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" /> <users login="normal" password="7bf24d6ca2242430343ab7e3efb89559a47784eea1123be989c1b2fb2ef66e83" role="USER" />
<pet id="1" name="Tafi" animalType="Perro" owner_id="1"/>
<pet id="2" name="Tafi1" animalType="Perro1" owner_id="1"/>
<pet id="3" name="Tafi2" animalType="Perro2" owner_id="1"/>
<pet id="4" name="Tafi3" animalType="Perro3" owner_id="1"/>
<pet id="5" name="Tafi4" animalType="Perro4" owner_id="1"/>
<pet id="6" name="Tafi5" animalType="Perro5" owner_id="1"/>
</dataset> </dataset>
\ No newline at end of file
DROP TABLE Pet IF EXISTS;
DROP TABLE People IF EXISTS; DROP TABLE People IF EXISTS;
DROP TABLE Users IF EXISTS; DROP TABLE Users IF EXISTS;
...@@ -11,3 +11,13 @@ CREATE TABLE users ( ...@@ -11,3 +11,13 @@ CREATE TABLE users (
role VARCHAR(5) NOT NULL, role VARCHAR(5) NOT NULL,
PRIMARY KEY (login) PRIMARY KEY (login)
); );
CREATE TABLE pet (
id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL,
name VARCHAR(50) NOT NULL,
animalType VARCHAR(50) NOT NULL,
owner_id int NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (owner_id) REFERENCES people(id) ON DELETE CASCADE
);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment