Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пояснювальна записка.docx
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
597.32 Кб
Скачать
  1. Тестування програми

Для організації зручності тестування усі вхідні дані записуються у файл, оскільки у класі що забезпечує це читання (DeclarationReader) вхідний потік з якого здійснюється читання є вхідним параметром, переключатись між зчитуванням інформації з консолі і з файлу досить легко для клієнта класу. Тестування XSD схеми проводилось шляхом введення не правильних даних до XML файлу, будь-яка з таких не вірних змін викликала виключення при запуску методу валідації, що означає що схема правильно підключена, а також працює правильно. Крім того, під час тестування для різних наборів вхідних даних серіалізований об’єкт завжди дорівнював десеріалізованому.

ВИСНОВОК

Розроблена програма призначена для відтворення множини витрат та підрахунку податків з кожного, а також занесення \ зчитування інформації у XML файл відповідає усім пунктам технічного завдання, а також для реалізації використовує лише стандартні засоби мови програмування Java. Крім того, хоча й існує велика кількість бібліотек що беруть на себе майже всю можливу роботу по серіалізації та десеріалізації об’єктів, проте створені у програмі класи є зручної обгорткою вище названих класів, та дають клієнту можливість більш просто виконувати ці ж операції для класів доходів.

СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ

  1. Г. Шилдт «Полное руководство – издательский дом «ВИЛЬЯМС» - ISBN: 978-58459-1759-1

  2. Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес Приемы объетктно-ориентированого проектирования. Паттерны проектирования – СПб «Питер», 2007. С. 366 – ISBN 978-5-469-011136-1.

  3. The Java Tutorials are practical guides for programmers http://docs.oracle.com/javase/tutorial/

  4. JavaTM 2 Platform, Standard Edition, v 1.4.2 API Specification http://docs.oracle.com/javase/1.4.2/docs/api/

  5. Questions on Java http://stackoverflow.com/questions/

  6. Шаблони проектування програмного забезпечення – http://uk.wikipedia.org/wiki/Шаблони проектування програмного забезпечення

  7. XML Schema Structures Second Edition http://www.w3.org/TR/xmlschema-1/

  8. Introduction to XML Schema http://www.w3schools.com/schema/schema_intro.asp

Додаток 1. UML Діаграма пакету edu.kpi.profit

Додаток 2. UML Діаграма пакету edu.kpi.menu

Додаток 3. UML Діаграма пакету edu.kpi.menu

Додаток 4. UML Діаграма пакету edu.kpi.XML

Додаток 5. Документація - пакети програми

Додаток 6. Документація – пакет edu.kpi.declaration

Додаток 7. Документація – пакет edu.kpi.menu

Додаток 8. Документація – пакет edu.kpi.profit

Додаток 9. Документація – пакет edu.kpi.XML

Додаток 10. Документація – внепакетні класи

Додаток 11. Отриманий XML файл

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<declaration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="dec-2324121">

<profits xsi:type="profitPropertySale">

<income>10000.3</income>

<tax>0.0</tax>

<propertyType>OTHER</propertyType>

<isResident>true</isResident>

</profits>

<profits xsi:type="profitGift">

<income>1000.0</income>

<tax>0.0</tax>

<giftType>PRECIOUS_METALS</giftType>

<isResident>false</isResident>

<isCloseRelative>true</isCloseRelative>

</profits>

<profits xsi:type="profitGift">

<income>300.0</income>

<tax>0.0</tax>

<giftType>CURRENCY</giftType>

<isResident>true</isResident>

<isCloseRelative>false</isCloseRelative>

</profits>

<profits xsi:type="profitHonorar">

<income>100.0</income>

<tax>30.000002</tax>

<workType>ARTIST</workType>

</profits>

<profits xsi:type="profitGift">

<income>1000.33</income>

<tax>50.016502</tax>

<giftType>REALTY</giftType>

<isResident>false</isResident>

<isCloseRelative>false</isCloseRelative>

</profits>

<profits xsi:type="profitSubJob">

<income>1000.0</income>

<tax>150.0</tax>

</profits>

<profits xsi:type="profitMaterialAid">

<income>1000.0</income>

<tax>150.0</tax>

<aidType>ENTOMBMENT</aidType>

</profits>

<profits xsi:type="profitPropertySale">

<income>1220.0</income>

<tax>183.0</tax>

<propertyType>OTHER</propertyType>

<isResident>false</isResident>

</profits>

<profits xsi:type="profitChildrenAid">

<income>3000.0</income>

<tax>210.0</tax>

<salary>3000.0</salary>

</profits>

<profits xsi:type="profitMainJob">

<income>2500.0</income>

<tax>375.0</tax>

</profits>

<profits xsi:type="profitMainJob">

<income>3300.35</income>

<tax>495.05252</tax>

</profits>

<profits xsi:type="profitRemittance">

<income>10000.0</income>

<tax>1500.0</tax>

</profits>

</declaration>

Додаток 12. XSD Схема

<?xml version="1.0"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

elementFormDefault="qualified">

<xs:element name="declaration">

<xs:complexType>

<xs:sequence>

<xs:element name="profits" minOccurs="0" maxOccurs="unbounded"/>

</xs:sequence>

<xs:attribute name="id" type="xs:ID" use="required"/>

</xs:complexType>

</xs:element>

<xs:complexType name="profit" abstract="true">

<xs:sequence>

<xs:element name="income" type="nonNegativeDecimal"/>

<xs:element name="tax" type="nonNegativeDecimal"/>

</xs:sequence>

</xs:complexType>

<xs:complexType name="profitChildrenAid">

<xs:complexContent>

<xs:extension base="profit">

<xs:sequence>

<xs:element name="salary" type="nonNegativeDecimal"/>

</xs:sequence>

</xs:extension>

</xs:complexContent>

</xs:complexType>

<xs:complexType name="profitGift">

<xs:complexContent>

<xs:extension base="profit">

<xs:sequence>

<xs:element name="giftType" type="giftType"/>

<xs:element name="isResident" type="xs:boolean"/>

<xs:element name="isCloseRelative" type="xs:boolean"/>

</xs:sequence>

</xs:extension>

</xs:complexContent>

</xs:complexType>

<xs:complexType name="profitHonorar">

<xs:complexContent>

<xs:extension base="profit">

<xs:sequence>

<xs:element name="workType" type="workType"/>

</xs:sequence>

</xs:extension>

</xs:complexContent>

</xs:complexType>

<xs:complexType name="profitMainJob">

<xs:complexContent>

<xs:extension base="profit"/>

</xs:complexContent>

</xs:complexType>

<xs:complexType name="profitMaterialAid">

<xs:complexContent>

<xs:extension base="profit">

<xs:sequence>

<xs:element name="aidType" type="aidType"/>

</xs:sequence>

</xs:extension>

</xs:complexContent>

</xs:complexType>

<xs:complexType name="profitPropertySale">

<xs:complexContent>

<xs:extension base="profit">

<xs:sequence>

<xs:element name="propertyType" type="propertyType"/>

<xs:element name="isResident" type="xs:boolean"/>

</xs:sequence>

</xs:extension>

</xs:complexContent>

</xs:complexType>

<xs:complexType name="profitRemittance">

<xs:complexContent>

<xs:extension base="profit"/>

</xs:complexContent>

</xs:complexType>

<xs:complexType name="profitSubJob">

<xs:complexContent>

<xs:extension base="profit"/>

</xs:complexContent>

</xs:complexType>

<xs:simpleType name="giftType">

<xs:restriction base="xs:string">

<xs:enumeration value="REALTY"/>

<xs:enumeration value="CURRENCY"/>

<xs:enumeration value="PRECIOUS_METALS"/>

<xs:enumeration value="SECURITIES"/>

<xs:enumeration value="OTHER"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="workType">

<xs:restriction base="xs:string">

<xs:enumeration value="LITERATURE"/>

<xs:enumeration value="ARTIST"/>

<xs:enumeration value="OTHER"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="aidType">

<xs:restriction base="xs:string">

<xs:enumeration value="MEDICAL_SERVICE"/>

<xs:enumeration value="ENTOMBMENT"/>

<xs:enumeration value="DISABLED"/>

<xs:enumeration value="REHABILITATION"/>

<xs:enumeration value="OTHER"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="propertyType">

<xs:restriction base="xs:string">

<xs:enumeration value="APARTMENT"/>

<xs:enumeration value="FLAT"/>

<xs:enumeration value="ROOM"/>

<xs:enumeration value="GARDEN_HOUSE"/>

<xs:enumeration value="OTHER"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="nonNegativeDecimal">

<xs:restriction base="xs:decimal">

<xs:minInclusive value="0"/>

</xs:restriction>

</xs:simpleType>

</xs:schema>

Додаток 13. Сирцевий код програмного додатку

Main

import edu.kpi.XML.XMLReader;

import edu.kpi.XML.XMLWriter;

import edu.kpi.declaration.Declaration;

public class Main {

private static String InFile = "declaration.in";

private static String XMLFile = "declaration.xml";

private static String XSDSchema = "declaration.xsd";

public static void main(String[] args){

try{

Declaration declaration = DeclarationReader.read(InFile);

declaration.SortProfitsByTax();

/* edu.kpi.XMLWriter. This is not the default one class */

XMLWriter.write(XMLFile, XSDSchema, declaration);

/* edu.kpi.XMLReader. This is not the default one class */

XMLReader xmlReader = new XMLReader();

Declaration resultDeclaration = xmlReader.read(XMLFile, XSDSchema);

if(resultDeclaration==null)

System.out.println("Файл не був валідований!");

else

System.out.println("Файл успішно зчитаний.");

}catch(Exception e){

e.printStackTrace();

}

}

}

DeclarationReader

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.InputStream;

import java.util.Scanner;

import edu.kpi.declaration.Declaration;

import edu.kpi.menu.*;

import edu.kpi.menu.MenuItemValueRead.ValueType;

import edu.kpi.profit.*;

import edu.kpi.profit.ProfitGift.GiftType;

import edu.kpi.profit.ProfitHonorar.WorkType;

import edu.kpi.profit.ProfitMaterialAid.AidType;

import edu.kpi.profit.ProfitPropertySale.PropertyType;

/**

* This class organizes reading information

* from the specified source and creating the

* declaration class by using methods from MenuItem

* abstract class subclasses.

*

* This class contains only static methods.

*

* @see MenuItem

*/

public class DeclarationReader {

/** Console menu tree */

private static final MenuItem myMenu =

new MenuItemChoose(

"Виберіть що додати до декларації:",

new MenuItem[]{

new MenuItemStepShow(

"1. Доходи з основного місця роботи",

new MenuItem[]{

new MenuItemValueRead(

"Введіть заробітну плату:", ValueType.FLOAT)

}

),

new MenuItemStepShow(

"2. Доходи з додаткового місця роботи",

new MenuItem[]{

new MenuItemValueRead(

"Введіть заробітну плату:",ValueType.FLOAT)

}

),

new MenuItemStepShow(

"3. Авторська винагорода",

new MenuItem[]{

new MenuItemValueRead(

"Введіть розмір гонорару:",ValueType.FLOAT),

new MenuItemValueRead(

"Виберіть тип роботи:\n" +

"1. Літературна робота\n" +

"2. Художньо графічна робота\n"+

"3. Інше\n",ValueType.INTEGER,3),

}

),

new MenuItemStepShow(

"4. Продаж майна",

new MenuItem[]{

new MenuItemValueRead(

"Введіть оціночну вартість:",ValueType.FLOAT),

new MenuItemValueRead(

"Виберіть тип властності:\n" +

"1. Жилий дім\n" +

"2. Квартира\n" +

"3. Кімната\n" +

"4. Садовий дім\n" +

"5. Інше\n",ValueType.INTEGER,5),

new MenuItemValueRead(

"Ви є резидентом?\n" +

"1. Так\n" +

"2. Ні\n",ValueType.INTEGER,2)

}

),

new MenuItemStepShow(

"5. Отримання в подарунок грошей і майна",

new MenuItem[]{

new MenuItemValueRead(

"Введіть вартість подарунку:",ValueType.FLOAT),

new MenuItemValueRead(

"Виберіть тип подарунку:\n" +

"1. Нерухомість\n" +

"2. Валюта\n" +

"3. Цінні метали\n" +

"4. Цінні папери\n" +

"5. Інше\n",ValueType.INTEGER,5),

new MenuItemValueRead(

"Ви є резидентом?\n" +

"1. Так\n" +

"2. Ні\n",ValueType.INTEGER,2),

new MenuItemValueRead(

"Дарувач родич першого порядку?\n" +

"1. Так\n" +

"2. Ні\n",ValueType.INTEGER,2)

}

),

new MenuItemStepShow(

"6. Отримання переводів з-за кордону",

new MenuItem[]{

new MenuItemValueRead(

"Введіть суму переводу",ValueType.FLOAT)

}

),

new MenuItemStepShow(

"7. Отримання допомоги дітей",

new MenuItem[]{

new MenuItemValueRead(

"Введіть розмір допомоги",ValueType.FLOAT),

new MenuItemValueRead(

"Введіть вашу сумарну заробітну плату",ValueType.FLOAT)

}

),

new MenuItemStepShow(

"8. Отримання матеріальної допомоги",

new MenuItem[]{

new MenuItemValueRead(

"Введіть розмір матеріальної допомоги",ValueType.FLOAT),

new MenuItemValueRead(

"Виберіть тип матерільної допомоги:\n" +

"1. На лікування\n" +

"2. Допомога на погребіння\n" +

"3. Непрацездатним\n" +

"4. На реабілітація після лікування\n" +

"5. Інше\n",ValueType.INTEGER,5),

}

)

}

);

public static Declaration read(InputStream source){

Scanner scanner = new Scanner(source);

myMenu.setInputStream(scanner);

System.out.println("Введіть номер декларації:");

Declaration declaration = new Declaration(readPositiveInteger(scanner));

float[] result;

int choice;

do

{

result = myMenu.show();

choice = myMenu.getChosenItem();

if(choice!=0)

declaration.addProfit(ChooseProfitInstance(choice,result));

}while(choice!=0);

scanner.close();

return declaration;

}

public static Declaration read(String filename) throws FileNotFoundException{

return read(new FileInputStream(filename));

}

private static Profit ChooseProfitInstance(int choice,float[] result){

switch(choice){

case 1:

return new ProfitMainJob(result[0]);

case 2:

return new ProfitSubJob(result[0]);

case 3:

return new ProfitHonorar(result[0],WorkType.values()[(int)result[1]-1]);

case 4:

return new ProfitPropertySale(result[0],PropertyType.values()[(int)result[1]-1],bool(result[2]));

case 5:

return new ProfitGift(result[0],GiftType.values()[(int)result[1]-1],bool(result[2]),bool(result[3]));

case 6:

return new ProfitRemittance(result[0]);

case 7:

return new ProfitChildrenAid(result[0],result[1]);

case 8:

return new ProfitMaterialAid(result[0],AidType.values()[(int)result[1]-1]);

}

return null;

}

private static boolean bool(float value){

return (value==1) ? true : false;

}

private static int readPositiveInteger(Scanner sc)

{

boolean valid;

String inputLine;

do

{

inputLine = sc.nextLine();

if(!(valid = inputLine.matches("\\d+")))

System.out.println("Невірний ввід!");

}while(!valid);

return Integer.parseInt(inputLine);

}

}

edu.kpi.declaration.Declaration

package edu.kpi.declaration;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Collections;

import javax.xml.bind.annotation.XmlAttribute;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlRootElement;

import edu.kpi.profit.Profit;

/**

* This class is holder of collection of

* profit abstract class subclasses.

* Also this class has functionality

* for sorting this collection by tax.

*

* @see Profit

*/

@XmlRootElement(namespace="")

public class Declaration {

@XmlElement

private ArrayList<Profit> profits = new ArrayList<Profit>();

@XmlAttribute

private String id;

/** Empty constructor for JABX. Setting it to private to block access for other clients*/

@SuppressWarnings("unused")

private Declaration(){}

public Declaration(int id){

this.id = "dec-"+Integer.toString(id);

}

public void addProfit(Profit profit) {

profits.add(profit);

}

public void addAll(Collection<? extends Profit> c) {

profits.addAll(c);

}

public void addAll(Profit[] profitsArr){

for(int i=0;i<profitsArr.length;i++)

profits.add(profitsArr[i]);

}

public void SortProfitsByTax(){

Collections.sort(profits, new TaxComparator());

}

public Profit[] getProfits() {

// Size = 0, let toArray method find it's size for us

Profit[] arr = new Profit[0];

arr = profits.toArray(arr);

return arr;

}

}

edu.kpi.declaration.package-info

/**

*

* @author Empower

*

*/

@XmlSchema(

xmlns = {

@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi"),

},

location = "",

namespace = "http://www.w3.org/2001/XMLSchema-instance",

elementFormDefault = javax.xml.bind.annotation.XmlNsForm.UNQUALIFIED)

package edu.kpi.declaration;

import javax.xml.bind.annotation.XmlSchema;

import javax.xml.bind.annotation.XmlNs;

edu.kpi.declaration.TaxComparator

package edu.kpi.declaration;

import java.util.Comparator;

import edu.kpi.profit.Profit;

/**

* Comparing Profit class subclasses

* by tax parameter.

*

* @see Profit

*/

public class TaxComparator implements Comparator<Profit>{

@Override

public int compare(Profit a, Profit b) {

Float aTax = a.getTax();

Float bTax = b.getTax();

return aTax.compareTo(bTax);

}

}

edu.kpi.menu.MenuItem

package edu.kpi.menu;

import java.util.Scanner;

/**

* This class contains the menu item and

* it's possible sub menus also it

* has some simple methods

* for handling user menu navigating

* commands.

*

* It's subclasses realizes 3

* menu items behaviors

* on choosing by user by

* overriding execute abstract method.

*

* @see MenuItemChoose

* @see MenuItemStepShow

* @see MenuItemValueRead

*/

public abstract class MenuItem{

protected String text;

protected MenuItem[] childMenus;

protected static float[] info;

protected static int chosenItem;

protected static int currHandled;

private static Scanner sc;

protected final static String exitString = "\n0. Вихід";

private final static String errorMessage = "Невірний ввід!";

public MenuItem(String text,MenuItem[] childMenus){

this.text = text;

this.childMenus = childMenus;

}

public MenuItem(String text){

this(text,null);

}

public void setInputStream(Scanner scanner){

sc = scanner;

}

public int getChosenItem(){

return chosenItem;

}

public float[] show(){

info = new float[4];

currHandled = 0;

execute();

return info;

}

protected int readInteger(Integer maxValid, boolean allowZero)

{

boolean valid;

String inputLine;

do

{

inputLine = sc.nextLine();

valid = inputLine.matches("\\d") && (maxValid==null ||

Integer.parseInt(inputLine)<=maxValid) &&

(allowZero || Integer.parseInt(inputLine)!=0);

if(!valid)

System.out.println(errorMessage);

}while(!valid);

return Integer.parseInt(inputLine);

}

protected float readFloat()

{

boolean valid;

String inputLine;

do

{

inputLine = sc.nextLine();

if(!(valid = inputLine.matches("\\d+(\\.\\d+)?") &&

Float.parseFloat(inputLine)!=0))

System.out.println(errorMessage);

}while(!valid);

return Float.parseFloat(inputLine);

}

protected abstract void execute();

}

edu.kpi.menu.MenuItemChoose

package edu.kpi.menu;

/**

* This MenuItem subclass is

* menu item that is "waiting" for

* user input to execute one of

* it's children.

*

* @see MenuItem

*/

public class MenuItemChoose extends MenuItem {

public MenuItemChoose(String text, MenuItem[] childMenus) {

super(text, childMenus);

}

@Override

protected void execute() {

System.out.println(text+"\n");

for(int i=0;i<childMenus.length;i++)

System.out.println(childMenus[i].text);

System.out.println(exitString);

chosenItem = readInteger(childMenus.length,true);

if(chosenItem!=0)

childMenus[chosenItem-1].execute();

}

}

edu.kpi.menu.MenuItemStepShow

package edu.kpi.menu;

/**

* This MenuItem subclass is

* menu item which is showing

* its children menus one after

* another.

*

* @see MenuItem

*/

public class MenuItemStepShow extends MenuItem {

public MenuItemStepShow(String text, MenuItem[] childMenus) {

super(text, childMenus);

}

@Override

protected void execute() {

for(int i=0;i<childMenus.length;i++)

childMenus[i].execute();

}

}

edu.kpi.menu.MenuItemValueRead

package edu.kpi.menu;

/**

* This MenuItem subclass is

* a dialog for reading users

* input values. Which are

* basically the result of

* work of whole menu tree.

*

* The class is intended to be

* a final stage (a leaf) of

* the tree which means it is not

* executing any other menu items.

*

* @see MenuItem

*/

public class MenuItemValueRead extends MenuItem {

public enum ValueType {FLOAT, INTEGER};

private ValueType valueType;

private Integer maxValue;

public MenuItemValueRead(String text,ValueType valueType,Integer maxValue) {

super(text);

this.valueType = valueType;

this.maxValue = maxValue;

}

public MenuItemValueRead(String text,ValueType valueType) {

this(text,valueType,null);

}

@Override

protected void execute() {

System.out.println(text);

info[currHandled++] = (valueType==ValueType.FLOAT) ? readFloat(): readInteger(maxValue,false);

}

}

edu.kpi.profit.Profit

package edu.kpi.profit;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlSeeAlso;

/**

* This class is an abstract superclass

* for all the profits intended to the

* program. The common things

* for them like income variable

* and abstract getTax method are taken

*

* @see ProfitChildrenAid

* @see ProfitGift

* @see ProfitHonorar

* @see ProfitMainJob

* @see ProfitMaterialAid

* @see ProfitPropertySale

* @see ProfitRemittance

* @see ProfitSubJob

*/

@XmlSeeAlso({ProfitChildrenAid.class,ProfitGift.class,Profit.class,ProfitHonorar.class,

ProfitMainJob.class,ProfitMaterialAid.class,ProfitPropertySale.class,ProfitRemittance.class,ProfitSubJob.class})

public abstract class Profit {

@XmlElement

protected float income;

protected final static int MINIMAL_SALARY = 1176;

public Profit(float income) {

if(income<0)

throw new IllegalArgumentException("Прибуток має бути невід'ємним числом!");

this.income = income;

}

@XmlElement

public abstract float getTax();

}

edu.kpi.profit.ProfitChildrenAid

package edu.kpi.profit;

import javax.xml.bind.annotation.XmlElement;

/**

* This class realizes children aid

* profit and the way it taxed:

*

* 0%, if salary of client is lower

* then minimal salary multiplied

* by 1.4, otherwise - 7%.

*

* @see Profit

*/

public class ProfitChildrenAid extends Profit{

@XmlElement

private float salary;

private final static float SALARY_MULTIPLAYER = 1.4f;

public ProfitChildrenAid(float income, float salary) {

super(income);

if(salary<0)

throw new IllegalArgumentException("Зарплата має бути невід'ємний числом!");

this.salary = salary;

}

@Override

public float getTax() {

float percent;

if(salary<=SALARY_MULTIPLAYER*MINIMAL_SALARY)

percent = 0;

else

percent = 0.07f;

return percent*income;

}

}

edu.kpi.profit.ProfitGift

package edu.kpi.profit;

import javax.xml.bind.annotation.XmlElement;

/**

* This class realizes a profit

* received as a gift and way it

* is taxed. The tax calculated

* by such a principle:

*

* 0% - if the presenter is a relative

* 5% - if he is living or the country

* 15% - otherwise

*

* @see Profit

*/

public class ProfitGift extends Profit {

public enum GiftType {REALTY, CURRENCY, PRECIOUS_METALS, SECURITIES, OTHER};

@XmlElement

private GiftType giftType;

@XmlElement

private boolean isResident;

@XmlElement

private boolean isCloseRelative;

private static final int MIN_TAXED_SUM = 850;

public ProfitGift(float income, GiftType giftType, boolean isResident, boolean isCloseRelative) {

super(income);

this.giftType = giftType;

this.isResident = isResident;

this.isCloseRelative = isCloseRelative;

}

@Override

public float getTax() {

float percent;

if(isCloseRelative || giftType==GiftType.OTHER || giftType!=GiftType.REALTY && income<=MIN_TAXED_SUM)

percent = 0;

else if(!isResident)

percent = 0.05f;

else

percent = 0.15f;

return percent*income;

}

}

edu.kpi.profit.ProfitHonorar

package edu.kpi.profit;

import javax.xml.bind.annotation.XmlElement;

/**

* This class realizes a profit

* received from a honorar and the

* way it is taxed.

*

* Only two types of honorars are taxed:

* honorars for literature works (20%)

* and artist works (30%).

*

* @see Profit

*/

public class ProfitHonorar extends Profit{

public enum WorkType {LITERATURE, ARTIST, OTHER};

@XmlElement

private WorkType workType;

public ProfitHonorar(float income,WorkType workType) {

super(income);

this.workType = workType;

}

@Override

public float getTax() {

float percent;

if(workType==WorkType.LITERATURE)

percent = 0.2f;

else if(workType==WorkType.ARTIST)

percent = 0.3f;

else

percent = 0;

return percent*income;

}

}

edu.kpi.profit.ProfitMainJob

package edu.kpi.profit;

/**

* This class is a representation

* of profit received from the

* main job and the way it is taxed.

*

* 17% - if the salary is 10 times bigger

* than the minimal one.

* 15% - in other cases.

*

* @see Profit

*/

public class ProfitMainJob extends Profit{

private final static int SALARY_MULTIPLAYER = 10;

public ProfitMainJob(float income) {

super(income);

}

@Override

public float getTax() {

float percent;

if(income>SALARY_MULTIPLAYER*MINIMAL_SALARY)

percent = 0.17f;

else

percent = 0.15f;

return percent*income;

}

}

edu.kpi.profit.ProfitMaterialAid

package edu.kpi.profit;

import javax.xml.bind.annotation.XmlElement;

/**

* This is a class of a profit

* from a material aid and the way

* it is taxed.

*

* 17% - if the salary is 10 times bigger

* than the minimal one.

* 15% - in other cases.

*

* @see Profit

*/

public class ProfitMaterialAid extends Profit{

public enum AidType {MEDICAL_SERVICE, ENTOMBMENT, DISABLED, REHABILITATION, OTHER};

@XmlElement

private AidType aidType;

private final static float taxPercent[] = {0.05f, 0.15f, 0.03f, 0.07f, 0.0f};

public ProfitMaterialAid(float income,AidType aidType) {

super(income);

this.aidType = aidType;

}

@Override

public float getTax() {

float percent = taxPercent[aidType.ordinal()];

return percent*income;

}

}

edu.kpi.profit.ProfitPropertySale

package edu.kpi.profit;

import javax.xml.bind.annotation.XmlElement;

/**

* This class represents a profit from

* property sale, and the way it is taxed:

*

* 15% tax if person selling is not liver

* of the country,

* 5% tax if we are selling one of these

* objects:

* - Apartment

* - Flat

* - Room

* - Garden house

* 0% tax otherwise

*

* @see Profit

*/

public class ProfitPropertySale extends Profit{

public enum PropertyType {APARTMENT, FLAT, ROOM, GARDEN_HOUSE, OTHER};

@XmlElement

private PropertyType propertyType;

@XmlElement

private boolean isResident;

public ProfitPropertySale(float income,PropertyType propertyType,boolean isResident) {

super(income);

this.propertyType = propertyType;

this.isResident = isResident;

}

@Override

public float getTax() {

float percent;

if(!isResident)

percent = 0.15f;

else if(propertyType != PropertyType.OTHER)

percent = 0.5f;

else

percent = 0;

return percent*income;

}

}

edu.kpi.profit.ProfitRemittance

package edu.kpi.profit;

/**

* This class represents a profit

* from a foreign payment (remittance)

* and the way it is taxed:

*

* 17% tax if its size is 10 times bigger

* than the minimal salary.

* 15% tax in other cases.

*

*/

public class ProfitRemittance extends Profit{

private final static int SALARY_MULTIPLAYER = 10;

public ProfitRemittance(float income) {

super(income);

}

@Override

public float getTax() {

float percent;

if(income>SALARY_MULTIPLAYER*MINIMAL_SALARY)

percent = 0.17f;

else

percent = 0.15f;

return percent*income;

}

}

edu.kpi.profit.ProfitSubJob

package edu.kpi.profit;

/**

* This class is a representation

* of profit received from the

* sub job and the way it is taxed.

*

* Tax percent is constant here

* it is 15%.

*

* @see Profit

*/

public class ProfitSubJob extends Profit{

public ProfitSubJob(float income) {

super(income);

}

@Override

public float getTax() {

return 0.15f*income;

}

}

edu.kpi.XML.ElementHandler

package edu.kpi.XML;

import java.util.ArrayList;

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

import edu.kpi.declaration.Declaration;

/**

* This class is intended to handle messages

* sent from SaxParser. Basically it "tells"

* XMLReader how to create declaration and profit

* instances depending on the messages received from

* the parser.

*

* This class is designed to be accessed only by

* XMLReader and XMLWriter classes (the constructor

* has only package visibility).

*

* @see Declaration

* @see Profit

*/

class ElementHandler extends DefaultHandler{

private XMLReader reader;

private Boolean isTax = false;

private ArrayList<String> arguments = new ArrayList<String>();

ElementHandler(XMLReader reader) {

this.reader = reader;

}

public void startElement(String uri, String local_name, String raw_name, Attributes amap) throws SAXException {

switch(raw_name){

case "declaration":

reader.startDeclaration(amap.getValue(1));

break;

case "profits":

reader.startProfit(amap.getValue(0));

break;

case "tax":

isTax = true;

break;

}

}

public void endElement(String uri, String local_name, String raw_name) throws SAXException {

switch(raw_name){

case "profits":

reader.endProfit(arguments);

arguments.clear();

break;

case "tax":

isTax = false;

break;

}

}

public void characters(char[] ch, int start, int length) throws SAXException {

String value = new String(ch,start,length);

if (!Character.isISOControl(value.charAt(0)) && !isTax) {

arguments.add(value);

}

}

}

edu.kpi.XML.XMLReader

package edu.kpi.XML;

import java.io.File;

import java.io.IOException;

import java.util.ArrayList;

import javax.xml.XMLConstants;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

import javax.xml.transform.stream.StreamSource;

import javax.xml.validation.Schema;

import javax.xml.validation.SchemaFactory;

import javax.xml.validation.Validator;

import org.xml.sax.SAXException;

import edu.kpi.declaration.Declaration;

import edu.kpi.profit.*;

import edu.kpi.profit.ProfitGift.GiftType;

import edu.kpi.profit.ProfitHonorar.WorkType;

import edu.kpi.profit.ProfitMaterialAid.AidType;

import edu.kpi.profit.ProfitPropertySale.PropertyType;

/**

* This class is for reading XML

* files written by edu.kpi.XMLWriter

* class, which are resenting

* Declaration class instances.

*

* The XML parser type used

* here is SAX parser.

*

* Before reading the XML it is being

* validated by specified XSD schema.

*

* @see Declaration

*/

public class XMLReader {

private Declaration declaration;

private String profitType;

public Declaration read(String filename, String schema) throws ParserConfigurationException, SAXException, IOException{

SAXParserFactory factory = SAXParserFactory.newInstance();

SAXParser parser = factory.newSAXParser();

if(!validate(filename, schema))

return null;

parser.parse(new File(filename), new ElementHandler(this));

return declaration;

}

void startDeclaration(String decId){

int id = Integer.parseInt(decId.substring(4));

declaration = new Declaration(id);

}

void startProfit(String type){

profitType = type;

}

void endProfit(ArrayList<String> values)

{

Profit toAdd = getProfitInstance(values);

declaration.addProfit(toAdd);

}

private boolean validate(String filename,String schemaName) throws IOException, SAXException{

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

Schema schema = schemaFactory.newSchema(new File(schemaName));

Validator validator = schema.newValidator();

StreamSource source = new StreamSource(filename);

try {

validator.validate(source);

} catch (SAXException e) {

return false;

}

return true;

}

private Profit getProfitInstance(ArrayList<String> values){

switch(profitType){

case "profitMainJob":

return new ProfitMainJob(Float.parseFloat(values.get(0)));

case "profitSubJob":

return new ProfitSubJob(Float.parseFloat(values.get(0)));

case "profitHonorar":

return new ProfitHonorar(Float.parseFloat(values.get(0)),WorkType.valueOf(values.get(1)));

case "profitPropertySale":

return new ProfitPropertySale(Float.parseFloat(values.get(0)),PropertyType.valueOf(values.get(1)),bool(values.get(2)));

case "profitGift":

return new ProfitGift(Float.parseFloat(values.get(0)),GiftType.valueOf(values.get(1)),bool(values.get(2)),bool(values.get(3)));

case "profitRemittance":

return new ProfitRemittance(Float.parseFloat(values.get(0)));

case "profitChildrenAid":

return new ProfitChildrenAid(Float.parseFloat(values.get(0)),Float.parseFloat(values.get(1)));

case "profitMaterialAid":

return new ProfitMaterialAid(Float.parseFloat(values.get(0)),AidType.valueOf(values.get(1)));

}

return null;

}

private boolean bool(String value){

return (value.equals("true")) ? true : false;

}

}

edu.kpi.XML.XMLWriter

package edu.kpi.XML;

import java.io.File;

import javax.xml.XMLConstants;

import javax.xml.bind.JAXBContext;

import javax.xml.bind.JAXBException;

import javax.xml.bind.Marshaller;

import javax.xml.validation.Schema;

import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;

import edu.kpi.declaration.Declaration;

/**

* This class writes declaration

* class instances to specified file.

*

* The methods from javax.xml.bind

* library classes are used for

* these actions.

*

* @see Declaration

*/

public class XMLWriter {

public static void write(String dest, String schemaFile, Declaration declaration) throws SAXException,JAXBException{

JAXBContext context = JAXBContext.newInstance(declaration.getClass());

Marshaller m = context.createMarshaller();

// for line indentation, new line delimiters

m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

m.setSchema(createShema(schemaFile));

try{

m.marshal( declaration, new File(dest));

}

catch(JAXBException e){

throw new JAXBException("Документ не пройшов валідацію!");

}

}

private static Schema createShema(String filename) throws SAXException{

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

return schemaFactory.newSchema(new File(filename));

}

}