You need to sign in or sign up before continuing.
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();
}
}
...@@ -57,7 +57,11 @@ public class AuthorizationFilter implements ContainerRequestFilter { ...@@ -57,7 +57,11 @@ 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 { } else {
requestContext.setSecurityContext(new UserSecurityContext(user)); if(isPetsPath(requestContext) && !user.getRole().contentEquals("ADMIN")) {
requestContext.abortWith(createResponse());
} else {
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;
...@@ -10,4 +10,14 @@ CREATE TABLE users ( ...@@ -10,4 +10,14 @@ CREATE TABLE users (
password VARCHAR(64) NOT NULL, password VARCHAR(64) NOT NULL,
role VARCHAR(5) NOT NULL, role VARCHAR(5) NOT NULL,
PRIMARY KEY (login) PRIMARY KEY (login)
); );
\ No newline at end of file
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