/*
 * Copyright 2010-2019 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
package com.hack23.cia.web.impl.ui.application.views.common.chartfactory.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.dussan.vaadin.dcharts.DCharts;
import org.dussan.vaadin.dcharts.base.elements.XYseries;
import org.dussan.vaadin.dcharts.data.DataSeries;
import org.dussan.vaadin.dcharts.options.Series;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.hack23.cia.service.external.esv.api.EsvApi;
import com.hack23.cia.service.external.esv.api.GovernmentBodyAnnualOutcomeSummary;
import com.hack23.cia.service.external.esv.api.GovernmentBodyAnnualSummary;
import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.GovernmentBodyChartDataManager;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.VerticalLayout;

/**
 * The Class GovernmentBodyChartDataManagerImpl.
 */
@Service
public final class GovernmentBodyChartDataManagerImpl extends AbstractChartDataManagerImpl
		implements GovernmentBodyChartDataManager {

	/** The Constant ANSLAGSPOSTSNAMN. */
	private static final String ANSLAGSPOSTSNAMN = "Anslagspostsnamn";

	/** The Constant INKOMSTTITELSNAMN. */
	private static final String INKOMSTTITELSNAMN = "Inkomsttitelsnamn";

	/** The Constant FIRST_JAN_DATA_SUFFIX. */
	private static final String FIRST_JAN_DATA_SUFFIX = "-01-01";

	/** The Constant ANNUAL_EXPENDITURE. */
	private static final String ANNUAL_EXPENDITURE = "Annual Expenditure";

	/** The Constant EXPENDITURE_GROUP_NAME. */
	private static final String EXPENDITURE_GROUP_NAME = "Utgiftsområdesnamn";

	/** The Constant ANNUAL_INCOME. */
	private static final String ANNUAL_INCOME = "Annual Income";

	/** The Constant INKOMSTTITELGRUPPSNAMN. */
	private static final String INKOMSTTITELGRUPPSNAMN = "Inkomsttitelgruppsnamn";

	/** The Constant ANNUAL_HEADCOUNT. */
	private static final String ANNUAL_HEADCOUNT = "Annual headcount";

	/** The Constant ANNUAL_HEADCOUNT_TOTAL_ALL_GOVERNMENT_BODIES. */
	private static final String ANNUAL_HEADCOUNT_TOTAL_ALL_GOVERNMENT_BODIES = "Annual headcount total all government bodies";

	/** The Constant ALL_GOVERNMENT_BODIES. */
	private static final String ALL_GOVERNMENT_BODIES = "All government bodies";

	/** The Constant ANNUAL_HEADCOUNT_SUMMARY_ALL_GOVERNMENT_BODIES. */
	private static final String ANNUAL_HEADCOUNT_SUMMARY_ALL_GOVERNMENT_BODIES = " Annual headcount summary, all government bodies";

	/** The Constant ANNUAL_HEADCOUNT_ALL_MINISTRIES. */
	private static final String ANNUAL_HEADCOUNT_ALL_MINISTRIES = "Annual headcount, all ministries";

	/** The Constant FIRST_OF_JAN. */
	private static final String FIRST_OF_JAN = "01-JAN-";

	/** The esv api. */
	@Autowired
	private EsvApi esvApi;

	/**
	 * Instantiates a new government body chart data manager impl.
	 */
	public GovernmentBodyChartDataManagerImpl() {
		super();
	}

	@Override
	public void createMinistryGovernmentBodyHeadcountSummaryChart(final AbstractOrderedLayout content,
			final String name) {
		final Map<Integer, List<GovernmentBodyAnnualSummary>> map = esvApi.getDataPerMinistry(name);
		final List<String> governmentBodyNames = esvApi.getGovernmentBodyNames(name);

		final DataSeries dataSeries = new DataSeries();
		final Series series = new Series();

		for (final String govBodyName : governmentBodyNames) {

			series.addSeries(new XYseries().setLabel(govBodyName));
			dataSeries.newSeries();

			for (final Entry<Integer, List<GovernmentBodyAnnualSummary>> entry : map.entrySet()) {
				addDataSerieValue(dataSeries, entry, entry.getValue().stream()
						.filter((final GovernmentBodyAnnualSummary p) -> p.getName().equalsIgnoreCase(govBodyName))
						.mapToInt(GovernmentBodyAnnualSummary::getHeadCount).sum());
			}
		}

		addChart(content, name + ANNUAL_HEADCOUNT_SUMMARY_ALL_GOVERNMENT_BODIES,
				new DCharts().setDataSeries(dataSeries)
						.setOptions(getChartOptions().createOptionsXYDateFloatLogYAxisLegendOutside(series)).show(),
				true);

	}

	@Override
	public void createMinistryGovernmentBodyHeadcountSummaryChart(final AbstractOrderedLayout content) {
		final Map<Integer, List<GovernmentBodyAnnualSummary>> map = esvApi.getData();
		final List<String> ministryNames = esvApi.getMinistryNames();

		final DataSeries dataSeries = new DataSeries();
		final Series series = new Series();

		for (final String ministryName : ministryNames) {

			series.addSeries(new XYseries().setLabel(ministryName));
			dataSeries.newSeries();

			for (final Entry<Integer, List<GovernmentBodyAnnualSummary>> entry : map.entrySet()) {
				addDataSerieValue(dataSeries, entry, entry.getValue().stream()
						.filter((final GovernmentBodyAnnualSummary p) -> p.getMinistry().equalsIgnoreCase(ministryName))
						.mapToInt(GovernmentBodyAnnualSummary::getHeadCount).sum());
			}
		}

		addChart(content, ANNUAL_HEADCOUNT_ALL_MINISTRIES,
				new DCharts().setDataSeries(dataSeries)
						.setOptions(getChartOptions().createOptionsXYDateFloatLogYAxisLegendOutside(series)).show(),
				true);

	}

	@Override
	public void createGovernmentBodyHeadcountSummaryChart(final VerticalLayout content) {
		final Map<Integer, List<GovernmentBodyAnnualSummary>> map = esvApi.getData();

		final DataSeries dataSeries = new DataSeries();
		final Series series = new Series();

		series.addSeries(new XYseries().setLabel(ALL_GOVERNMENT_BODIES));
		dataSeries.newSeries();

		for (final Entry<Integer, List<GovernmentBodyAnnualSummary>> entry : map.entrySet()) {
			addDataSerieValue(dataSeries, entry, entry.getValue().stream().mapToInt(GovernmentBodyAnnualSummary::getHeadCount).sum());
		}

		addChart(content, ANNUAL_HEADCOUNT_TOTAL_ALL_GOVERNMENT_BODIES,
				new DCharts().setDataSeries(dataSeries)
						.setOptions(getChartOptions().createOptionsXYDateFloatLogYAxisLegendOutside(series)).show(),
				true);

	}

	@Override
	public void createGovernmentBodyHeadcountSummaryChart(final VerticalLayout content, final String name) {
		final Map<Integer, GovernmentBodyAnnualSummary> map = esvApi.getDataPerGovernmentBody(name);

		final DataSeries dataSeries = new DataSeries();
		final Series series = new Series();

		series.addSeries(new XYseries().setLabel(name));
		dataSeries.newSeries();

		for (final Entry<Integer, GovernmentBodyAnnualSummary> entry : map.entrySet()) {
			addDataSerieValue(dataSeries, entry, entry.getValue().getHeadCount());
		}

		addChart(content, name + ANNUAL_HEADCOUNT,
				new DCharts().setDataSeries(dataSeries)
						.setOptions(getChartOptions().createOptionsXYDateFloatLogYAxisLegendOutside(series)).show(),
				true);
	}

	/**
	 * Adds the data serie value.
	 *
	 * @param dataSeries the data series
	 * @param entry      the entry
	 * @param value      the value
	 */
	private static void addDataSerieValue(final DataSeries dataSeries, final Entry entry,
			final int value) {
		if (entry.getKey() != null && value > 0) {
			dataSeries.add(FIRST_OF_JAN + entry.getKey(), value);
		}
	}

	@Override
	public void createGovernmentBodyIncomeSummaryChart(final VerticalLayout content) {
		addAnnualSummary(esvApi.getGovernmentBodyReportByField(INKOMSTTITELGRUPPSNAMN), content, ANNUAL_INCOME);
	}

	@Override
	public void createGovernmentBodyIncomeSummaryChart(final VerticalLayout content, final String name) {
		final Map<String, List<GovernmentBodyAnnualOutcomeSummary>> collect = esvApi.getGovernmentBodyReport().get(name)
				.stream().filter(p -> p.getDescriptionFields().get(INKOMSTTITELSNAMN) != null)
				.collect(Collectors.groupingBy(t -> t.getDescriptionFields().get(INKOMSTTITELSNAMN)));

		addAnnualData(content, name, ANNUAL_INCOME, collect);

	}

	@Override
	public void createGovernmentBodyExpenditureSummaryChart(final VerticalLayout content) {
		addAnnualSummary(esvApi.getGovernmentBodyReportByField(EXPENDITURE_GROUP_NAME), content, ANNUAL_EXPENDITURE);
	}

	@Override
	public void createGovernmentBodyExpenditureSummaryChart(final VerticalLayout content, final String name) {
		final Map<String, List<GovernmentBodyAnnualOutcomeSummary>> collect = esvApi.getGovernmentBodyReport().get(name)
				.stream().filter(p -> p.getDescriptionFields().get(ANSLAGSPOSTSNAMN) != null)
				.collect(Collectors.groupingBy(t -> t.getDescriptionFields().get(ANSLAGSPOSTSNAMN)));

		addAnnualData(content, name, ANNUAL_EXPENDITURE, collect);
	}

	/**
	 * Adds the annual summary.
	 *
	 * @param report
	 *            the report
	 * @param content
	 *            the content
	 * @param label
	 *            the label
	 */
	private void addAnnualSummary(final Map<String, List<GovernmentBodyAnnualOutcomeSummary>> report, final VerticalLayout content,
			final String label) {

		final DataSeries dataSeries = new DataSeries();
		final Series series = new Series();

		for (final Entry<String, List<GovernmentBodyAnnualOutcomeSummary>> entry : report.entrySet()) {

			final List<GovernmentBodyAnnualOutcomeSummary> allValues = entry.getValue();

			if (!allValues.isEmpty()) {
				addAnnualSummaryData(dataSeries, series, entry, allValues);
			}
		}

		addChart(content, label,
				new DCharts().setDataSeries(dataSeries)
						.setOptions(getChartOptions().createOptionsXYDateFloatLogYAxisLegendOutside(series)).show(),
				true);
	}

	/**
	 * Adds the annual summary data.
	 *
	 * @param dataSeries the data series
	 * @param series     the series
	 * @param entry      the entry
	 * @param allValues  the all values
	 */
	private static void addAnnualSummaryData(final DataSeries dataSeries, final Series series,
			final Entry<String, List<GovernmentBodyAnnualOutcomeSummary>> entry,
			final List<GovernmentBodyAnnualOutcomeSummary> allValues) {
		series.addSeries(new XYseries().setLabel(entry.getKey()).setShowLabel(true));
		dataSeries.newSeries();

		final Map<Integer, List<GovernmentBodyAnnualOutcomeSummary>> map = allValues.stream()
				.collect(Collectors.groupingBy(GovernmentBodyAnnualOutcomeSummary::getYear));

		for (final Entry<Integer, List<GovernmentBodyAnnualOutcomeSummary>> data : map.entrySet()) {
			final List<GovernmentBodyAnnualOutcomeSummary> values = data.getValue();
			final double sum = values.stream().mapToDouble(GovernmentBodyAnnualOutcomeSummary::getYearTotal).sum();
			if (sum > 0) {
				dataSeries.add(data.getKey() + FIRST_JAN_DATA_SUFFIX, (int) sum);
			}
		}
	}

	/**
	 * Adds the annual data.
	 *
	 * @param content
	 *            the content
	 * @param name
	 *            the name
	 * @param label
	 *            the label
	 * @param collect
	 *            the collect
	 */
	private void addAnnualData(final VerticalLayout content, final String name, final String label,
			final Map<String, List<GovernmentBodyAnnualOutcomeSummary>> collect) {
		final DataSeries dataSeries = new DataSeries();
		final Series series = new Series();

		final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd",Locale.ENGLISH);
		for (final Entry<String, List<GovernmentBodyAnnualOutcomeSummary>> entry : collect.entrySet()) {
			series.addSeries(new XYseries().setLabel(entry.getKey()));
			dataSeries.newSeries();

			addEntryData(dataSeries, simpleDateFormat, entry);
		}

		addChart(content, name + label,
				new DCharts().setDataSeries(dataSeries)
						.setOptions(getChartOptions().createOptionsXYDateFloatLogYAxisLegendOutside(series)).show(),
				true);
	}

	/**
	 * Adds the entry data.
	 *
	 * @param dataSeries       the data series
	 * @param simpleDateFormat the simple date format
	 * @param entry            the entry
	 */
	private static void addEntryData(final DataSeries dataSeries, final SimpleDateFormat simpleDateFormat,
			final Entry<String, List<GovernmentBodyAnnualOutcomeSummary>> entry) {
		for (final GovernmentBodyAnnualOutcomeSummary data : entry.getValue()) {
			final Map<Date, Double> valueMap = data.getValueMap();

			for (final Entry<Date, Double> entryData : valueMap.entrySet()) {
				if (entryData.getValue() != null && entryData.getValue().intValue() > 0) {
					dataSeries.add(simpleDateFormat.format(entryData.getKey()) , entryData.getValue().intValue());
				}
			}
		}
	}

	@Override
	public void createMinistryGovernmentBodyIncomeSummaryChart(final AbstractOrderedLayout content) {
		createMinistrySummary(content,INKOMSTTITELGRUPPSNAMN,"MinistryGovernmentBodyIncomeSummaryChart");

	}

	@Override
	public void createMinistryGovernmentBodyExpenditureSummaryChart(final AbstractOrderedLayout content) {
		createMinistrySummary(content,EXPENDITURE_GROUP_NAME,"MinistryGovernmentBodySpendingSummaryChart");
	}

	/**
	 * Creates the ministry summary.
	 *
	 * @param content the content
	 * @param field   the field
	 * @param label   the label
	 */
	private void createMinistrySummary(final AbstractOrderedLayout content, final String field, final String label) {
		final DataSeries dataSeries = new DataSeries();
		final Series series = new Series();

		final Map<String, List<GovernmentBodyAnnualOutcomeSummary>> reportByMinistry = esvApi.getGovernmentBodyReportByMinistry();

		for (final Entry<String, List<GovernmentBodyAnnualOutcomeSummary>> entry : reportByMinistry.entrySet()) {
			series.addSeries(new XYseries().setLabel(entry.getKey()));
			dataSeries.newSeries();
			final Map<Integer, Double> annualSummaryMap = entry.getValue().stream().filter(t -> t.getDescriptionFields().get(field) != null).collect(Collectors.groupingBy(GovernmentBodyAnnualOutcomeSummary::getYear,Collectors.summingDouble(GovernmentBodyAnnualOutcomeSummary::getYearTotal)));

			for (final Entry<Integer, Double> entryData : annualSummaryMap.entrySet()) {
				if (entryData.getValue() != null && entryData.getValue().intValue() > 0) {
					dataSeries.add(entryData.getKey() +1  +"-01-01" , entryData.getValue());
				}
			}
		}

		addChart(content, label,
				new DCharts().setDataSeries(dataSeries)
						.setOptions(getChartOptions().createOptionsXYDateFloatLogYAxisLegendOutside(series)).show(),
				true);
	}

	@Override
	public void createMinistryGovernmentBodyIncomeSummaryChart(final VerticalLayout content, final String name) {
		addAnnualSummary(esvApi.getGovernmentBodyReportByFieldAndMinistry(INKOMSTTITELGRUPPSNAMN,name), content, ANNUAL_INCOME);
	}

	@Override
	public void createMinistryGovernmentBodyExpenditureSummaryChart(final VerticalLayout content, final String name) {
		addAnnualSummary(esvApi.getGovernmentBodyReportByFieldAndMinistry(EXPENDITURE_GROUP_NAME, name), content, ANNUAL_EXPENDITURE);
	}

}


/*
 * Copyright 2010-2019 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
package com.hack23.cia.web.impl.ui.application.views.user.politician.pagemode;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Component;

import com.hack23.cia.model.external.riksdagen.person.impl.AssignmentData;
import com.hack23.cia.model.external.riksdagen.person.impl.PersonData;
import com.hack23.cia.model.internal.application.data.politician.impl.ViewRiksdagenPolitician;
import com.hack23.cia.web.impl.ui.application.views.common.labelfactory.LabelFactory;
import com.hack23.cia.web.impl.ui.application.views.common.viewnames.PoliticianPageMode;
import com.vaadin.ui.Layout;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.Panel;
import com.vaadin.ui.VerticalLayout;

/**
 * The Class RoleListPageModContentFactoryImpl.
 */
@Component
public final class PoliticianRoleListPageModContentFactoryImpl extends AbstractPoliticianPageModContentFactoryImpl {

	private static final String[] HIDE_COLUMNS = new String[] { "hjid", "intressentId", "orderNumber", "orgCode" };
	private static final String[] COLUMN_ORDER = new String[] { "roleCode", "assignmentType", "status", "detail",
			"orgCode", "fromDate", "toDate" };
	private static final String ASSIGNMENTS = "Assignments";

	/**
	 * Instantiates a new politician role list page mod content factory impl.
	 */
	public PoliticianRoleListPageModContentFactoryImpl() {
		super();
	}

	@Override
	public boolean matches(final String page, final String parameters) {
		return NAME.equals(page) && parameters.contains(PoliticianPageMode.ROLELIST.toString());
	}

	@Secured({ "ROLE_ANONYMOUS", "ROLE_USER", "ROLE_ADMIN" })
	@Override
	public Layout createContent(final String parameters, final MenuBar menuBar, final Panel panel) {
		final VerticalLayout panelContent = createPanelContent();

		final String pageId = getPageId(parameters);
		final ViewRiksdagenPolitician viewRiksdagenPolitician = getItem(parameters);
		getPoliticianMenuItemFactory().createPoliticianMenuBar(menuBar, pageId);
		LabelFactory.createHeader2Label(panelContent, PoliticianPageMode.ROLELIST.toString());

		final PersonData personData = getApplicationManager().getDataContainer(PersonData.class)
				.load(viewRiksdagenPolitician.getPersonId());

		final List<AssignmentData> assignmentList = personData.getPersonAssignmentData().getAssignmentList();

		createRoleList(panelContent, assignmentList);

		pageCompleted(parameters, panel, pageId, viewRiksdagenPolitician);
		return panelContent;

	}

	/**
	 * Creates the role list.
	 *
	 * @param roleSummaryLayoutTabsheet the role summary layout tabsheet
	 * @param assignmentList the assignment list
	 */
	private void createRoleList(final VerticalLayout roleSummaryLayoutTabsheet,
			final List<AssignmentData> assignmentList) {

		final Comparator<AssignmentData> compare = (o1, o2) -> o1.getFromDate().compareTo(o2.getFromDate());

		Collections.sort(assignmentList, compare);

		getGridFactory().createBasicBeanItemGrid(roleSummaryLayoutTabsheet, AssignmentData.class, assignmentList,
				ASSIGNMENTS, COLUMN_ORDER, HIDE_COLUMNS, null, null, null);

	}

}


/*
 * Copyright 2010-2019 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
package com.hack23.cia.service.external.riksdagen.impl;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBElement;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.oxm.Unmarshaller;
import org.springframework.stereotype.Component;

import com.hack23.cia.model.external.riksdagen.documentcontent.impl.DocumentContentData;
import com.hack23.cia.model.external.riksdagen.dokumentlista.impl.DocumentContainerElement;
import com.hack23.cia.model.external.riksdagen.dokumentlista.impl.DocumentElement;
import com.hack23.cia.model.external.riksdagen.dokumentstatus.impl.DocumentStatusContainer;
import com.hack23.cia.model.external.riksdagen.dokumentstatus.impl.DocumentType;
import com.hack23.cia.service.external.common.api.ProcessDataStrategy;
import com.hack23.cia.service.external.common.api.XmlAgent;
import com.hack23.cia.service.external.common.api.XmlAgentException;
import com.hack23.cia.service.external.riksdagen.api.DataFailureException;
import com.hack23.cia.service.external.riksdagen.api.RiksdagenDocumentApi;

/**
 * The Class RiksdagenDocumentApiImpl.
 */
@Component
final class RiksdagenDocumentApiImpl implements RiksdagenDocumentApi {

	/** The Constant CHANGED_SINCE_KEY. */
	private static final String CHANGED_SINCE_KEY = "${CHANGED_SINCE}";

	/** The Constant CHANGED_TO_KEY. */
	private static final String CHANGED_TO_KEY = "${CHANGED_TO}";

	/** The Constant DOC_ID_KEY. */
	private static final String DOC_ID_KEY = "${DOC_ID}";

	/** The Constant DOCUMENT_CONTENT. */
	private static final String DOCUMENT_CONTENT = "https://data.riksdagen.se/dokument/${DOC_ID}/text";

	/** The Constant DOCUMENT_LIST_CHANGED_DATE. */
	private static final String DOCUMENT_LIST_CHANGED_DATE = "https://data.riksdagen.se/dokumentlista/?sok=&doktyp=&rm=&from=${CHANGED_SINCE}&tom=${CHANGED_TO}&ts=&bet=&tempbet=&nr=&org=&iid=&webbtv=&talare=&exakt=&planering=&sort=datum&sortorder=asc&rapport=&utformat=xml&a=";

	/** The Constant DOCUMENT_LIST_TYPE. */
	private static final String DOCUMENT_LIST_TYPE = "https://data.riksdagen.se/dokumentlista/?rm=&typ=${TYPE}&d=&ts=&parti=&iid=&bet=&org=&kat=&sz=200&sort=c&utformat=xml";

	/** The Constant DOCUMENT_LIST_YEAR. */
	private static final String DOCUMENT_LIST_YEAR = "https://data.riksdagen.se/dokumentlista/?rm=${YEAR}&typ=&d=&ts=&parti=&iid=&bet=&org=&kat=&sz=200&sort=c&utformat=xml";

	/** The Constant DOCUMENT_STATUS. */
	private static final String DOCUMENT_STATUS = "https://data.riksdagen.se/dokumentstatus/${ID_KEY}/xml";

	/** The Constant ERROR_PROCESSING_DOCUMENT. */
	private static final String ERROR_PROCESSING_DOCUMENT = "Error processing document :{}";

	/**
	 * The Constant HTTP_DOKUMENTLISTA_RIKSDAGEN_EXTERNAL_MODEL_CIA_HACK23_COM_IMPL.
	 */
	private static final String HTTP_DOKUMENTLISTA_RIKSDAGEN_EXTERNAL_MODEL_CIA_HACK23_COM_IMPL = "http://dokumentlista.riksdagen.external.model.cia.hack23.com/impl";

	/**
	 * The Constant
	 * HTTP_DOKUMENTSTATUS_RIKSDAGEN_EXTERNAL_MODEL_CIA_HACK23_COM_IMPL.
	 */
	private static final String HTTP_DOKUMENTSTATUS_RIKSDAGEN_EXTERNAL_MODEL_CIA_HACK23_COM_IMPL = "http://dokumentstatus.riksdagen.external.model.cia.hack23.com/impl";

	/** The Constant ID_KEY. */
	private static final String ID_KEY = "${ID_KEY}";

	/** The Constant LOADING_DOCUMENTS. */
	private static final String LOADING_DOCUMENTS = "Loading documents:{}/{}";

	/** The Constant LOGGER. */
	private static final Logger LOGGER = LoggerFactory.getLogger(RiksdagenDocumentApiImpl.class);

	/** The Constant PAGE_PROPERTY. */
	private static final String PAGE_PROPERTY = "&p=";

	/**
	 * The Constant
	 * PROBLEM_GETTING_DOCUMENT_CONTENT_FOR_ID_S_FROM_DATA_RIKSDAGEN_SE.
	 */
	private static final String PROBLEM_GETTING_DOCUMENT_CONTENT_FOR_ID_S_FROM_DATA_RIKSDAGEN_SE = "Problem getting document content for id:{} from data.riksdagen.se";

	/**
	 * The Constant
	 * PROBLEM_GETTING_DOCUMENT_LIST_CHANGED_SINCE_DATE_S_CHANGED_TO_DATE_S_FROM_DATA_RIKSDAGEN_SE.
	 */
	private static final String PROBLEM_GETTING_DOCUMENT_LIST_CHANGED_SINCE_DATE_S_CHANGED_TO_DATE_S_FROM_DATA_RIKSDAGEN_SE = "Problem getting document list changedSinceDate:{} , changedToDate:{} from data.riksdagen.se";

	/**
	 * The Constant
	 * PROBLEM_GETTING_DOCUMENT_LIST_FOR_DOCUMENT_TYPE_S_MAX_NUMBER_PAGES_S_FROM_DATA_RIKSDAGEN_SE.
	 */
	private static final String PROBLEM_GETTING_DOCUMENT_LIST_FOR_DOCUMENT_TYPE_S_MAX_NUMBER_PAGES_S_FROM_DATA_RIKSDAGEN_SE = "Problem getting document list for documentType:{} , maxNumberPages: {} from data.riksdagen.se";

	/**
	 * The Constant PROBLEM_GETTING_DOCUMENT_LIST_FOR_YEAR_S_FROM_DATA_RIKSDAGEN_SE.
	 */
	private static final String PROBLEM_GETTING_DOCUMENT_LIST_FOR_YEAR_S_FROM_DATA_RIKSDAGEN_SE = "Problem getting document list for year: {} from data.riksdagen.se";

	/** The Constant PROBLEM_GETTING_DOCUMENT_STATUS_ID_S_FROM_DATA_RIKSDAGEN_SE. */
	private static final String PROBLEM_GETTING_DOCUMENT_STATUS_ID_S_FROM_DATA_RIKSDAGEN_SE = "Problem getting document status id:{}  from data.riksdagen.se";

	/**
	 * The Constant
	 * PROBLEM_PROCCESSING_DOCUMENT_BETWEEN_CHANGED_SINCE_DATE_S_AND_CHANGE_TO_DATE.
	 */
	private static final String PROBLEM_PROCCESSING_DOCUMENT_BETWEEN_CHANGED_SINCE_DATE_S_AND_CHANGE_TO_DATE = "Problem proccessing document between changedSinceDate: {} and changeToDate {}";

	/** The Constant TYPE_KEY. */
	private static final String TYPE_KEY = "${TYPE}";

	/** The Constant YEAR_KEY. */
	private static final String YEAR_KEY = "${YEAR}";

	/** The riksdagen document list marshaller. */
	@Autowired
	@Qualifier("riksdagenDocumentListMarshaller")
	private Unmarshaller riksdagenDocumentListMarshaller;

	/** The riksdagen document status marshaller. */
	@Autowired
	@Qualifier("riksdagenDocumentStatusMarshaller")
	private Unmarshaller riksdagenDocumentStatusMarshaller;

	/** The xml agent. */
	private final XmlAgent xmlAgent;

	/**
	 * Instantiates a new riksdagen document api impl.
	 *
	 * @param xmlAgent
	 *            the xml agent
	 */
	@Autowired
	public RiksdagenDocumentApiImpl(final XmlAgent xmlAgent) {
		super();
		this.xmlAgent = xmlAgent;
	}

	/**
	 * Fix broken url.
	 *
	 * @param nextPage
	 *            the next page
	 * @return the string
	 */
	private static String fixBrokenUrl(final String nextPage) {
		if (nextPage.startsWith("//")) {
			return "http:" + nextPage;
		} else {
			return nextPage;
		}
	}

	/**
	 * Process all.
	 *
	 * @param dokument
	 *            the dokument
	 * @param processStrategy
	 *            the process strategy
	 */
	private static void processAll(final List<DocumentElement> dokument,
			final ProcessDataStrategy<DocumentElement> processStrategy) {
		for (final DocumentElement documentElement : dokument) {

			try {
				processStrategy.process(documentElement);
			} catch (final RuntimeException e) {
				LOGGER.warn(ERROR_PROCESSING_DOCUMENT, documentElement.getId(), e);
			}
		}
	}

	/* (non-Javadoc)
	 * @see com.hack23.cia.service.external.riksdagen.api.RiksdagenDocumentApi#getDocumentContent(java.lang.String)
	 */
	@Override
	public DocumentContentData getDocumentContent(final String id) throws DataFailureException {
		try {
			return new DocumentContentData().withId(id)
					.withContent(xmlAgent.retriveContent(DOCUMENT_CONTENT.replace(DOC_ID_KEY, id)));
		} catch (final XmlAgentException e) {
			LOGGER.warn(PROBLEM_GETTING_DOCUMENT_CONTENT_FOR_ID_S_FROM_DATA_RIKSDAGEN_SE, id);
			throw new DataFailureException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.hack23.cia.service.external.riksdagen.api.RiksdagenDocumentApi#getDocumentList(com.hack23.cia.model.external.riksdagen.dokumentstatus.impl.DocumentType, int)
	 */
	@Override
	public List<DocumentElement> getDocumentList(final DocumentType documentType, final int maxNumberPages)
			throws DataFailureException {
		try {
			return loadDocumentList(DOCUMENT_LIST_TYPE.replace(TYPE_KEY, documentType.value()), maxNumberPages);
		} catch (final XmlAgentException e) {
			LOGGER.warn(PROBLEM_GETTING_DOCUMENT_LIST_FOR_DOCUMENT_TYPE_S_MAX_NUMBER_PAGES_S_FROM_DATA_RIKSDAGEN_SE,
					documentType, Integer.toString(maxNumberPages));
			throw new DataFailureException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.hack23.cia.service.external.riksdagen.api.RiksdagenDocumentApi#getDocumentList(java.lang.Integer, int)
	 */
	@Override
	public List<DocumentElement> getDocumentList(final Integer year, final int maxNumberPages)
			throws DataFailureException {
		try {
			return loadDocumentList(DOCUMENT_LIST_YEAR.replace(YEAR_KEY, year.toString()), maxNumberPages);
		} catch (final XmlAgentException e) {
			LOGGER.warn(PROBLEM_GETTING_DOCUMENT_LIST_FOR_YEAR_S_FROM_DATA_RIKSDAGEN_SE, year);
			throw new DataFailureException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.hack23.cia.service.external.riksdagen.api.RiksdagenDocumentApi#getDocumentList(java.lang.String, java.lang.String, int)
	 */
	@Override
	public List<DocumentElement> getDocumentList(final String changedSinceDate, final String changedToDate,
			final int maxNumberPages) throws DataFailureException {
		try {
			return loadDocumentList(DOCUMENT_LIST_CHANGED_DATE.replace(CHANGED_SINCE_KEY, changedSinceDate)
					.replace(CHANGED_TO_KEY, changedToDate), maxNumberPages);
		} catch (final XmlAgentException e) {
			LOGGER.warn(PROBLEM_GETTING_DOCUMENT_LIST_CHANGED_SINCE_DATE_S_CHANGED_TO_DATE_S_FROM_DATA_RIKSDAGEN_SE,
					changedSinceDate, changedToDate);
			throw new DataFailureException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.hack23.cia.service.external.riksdagen.api.RiksdagenDocumentApi#getDocumentStatus(java.lang.String)
	 */
	@Override
	public DocumentStatusContainer getDocumentStatus(final String id) throws DataFailureException {
		try {
			final String url = DOCUMENT_STATUS.replace(ID_KEY, id);
			return ((JAXBElement<DocumentStatusContainer>) xmlAgent.unmarshallXml(riksdagenDocumentStatusMarshaller,
					url, HTTP_DOKUMENTSTATUS_RIKSDAGEN_EXTERNAL_MODEL_CIA_HACK23_COM_IMPL, null, null)).getValue();
		} catch (final XmlAgentException e) {
			LOGGER.warn(PROBLEM_GETTING_DOCUMENT_STATUS_ID_S_FROM_DATA_RIKSDAGEN_SE, id);
			throw new DataFailureException(e);
		}
	}

	/**
	 * Load and process document list.
	 *
	 * @param url
	 *            the url
	 * @param processStrategy
	 *            the process strategy
	 * @throws XmlAgentException
	 *             the xml agent exception
	 */
	private void loadAndProcessDocumentList(final String url,
			final ProcessDataStrategy<DocumentElement> processStrategy) throws XmlAgentException {
		final DocumentContainerElement dokumentLista = ((JAXBElement<DocumentContainerElement>) xmlAgent.unmarshallXml(
				riksdagenDocumentListMarshaller, url, HTTP_DOKUMENTLISTA_RIKSDAGEN_EXTERNAL_MODEL_CIA_HACK23_COM_IMPL,
				null, null)).getValue();

		int resultSize = dokumentLista.getDokument().size();
		processAll(dokumentLista.getDokument(), processStrategy);
		final BigInteger pages = dokumentLista.getTotalPages();
		for (int i = 1; i < pages.intValue(); i++) {
			final DocumentContainerElement otherPagesdokumentLista = ((JAXBElement<DocumentContainerElement>) xmlAgent
					.unmarshallXml(riksdagenDocumentListMarshaller, url + PAGE_PROPERTY + i,
							HTTP_DOKUMENTLISTA_RIKSDAGEN_EXTERNAL_MODEL_CIA_HACK23_COM_IMPL, null, null)).getValue();
			resultSize = resultSize + otherPagesdokumentLista.getDokument().size();
			processAll(otherPagesdokumentLista.getDokument(), processStrategy);
			LOGGER.info(LOADING_DOCUMENTS, resultSize, dokumentLista.getHits());
		}
	}

	/**
	 * Load document list.
	 *
	 * @param url
	 *            the url
	 * @param maxNumberPages
	 *            the max number pages
	 * @return the list
	 * @throws XmlAgentException
	 *             the xml agent exception
	 */
	private List<DocumentElement> loadDocumentList(final String url, final int maxNumberPages) throws XmlAgentException {
		final List<DocumentElement> result = new ArrayList<>();

		DocumentContainerElement dokumentLista = ((JAXBElement<DocumentContainerElement>) xmlAgent.unmarshallXml(
				riksdagenDocumentListMarshaller, url, HTTP_DOKUMENTLISTA_RIKSDAGEN_EXTERNAL_MODEL_CIA_HACK23_COM_IMPL,
				null, null)).getValue();
		result.addAll(dokumentLista.getDokument());
		final BigInteger pages = dokumentLista.getTotalPages();
		for (int i = 1; i < pages.intValue() && i < maxNumberPages; i++) {
			dokumentLista = ((JAXBElement<DocumentContainerElement>) xmlAgent.unmarshallXml(
					riksdagenDocumentListMarshaller, fixBrokenUrl(dokumentLista.getNextPage()),
					HTTP_DOKUMENTLISTA_RIKSDAGEN_EXTERNAL_MODEL_CIA_HACK23_COM_IMPL, null, null)).getValue();
			result.addAll(dokumentLista.getDokument());
			LOGGER.info(LOADING_DOCUMENTS, result.size(), dokumentLista.getHits());
		}

		return result;
	}

	/* (non-Javadoc)
	 * @see com.hack23.cia.service.external.riksdagen.api.RiksdagenDocumentApi#processDocumentList(java.lang.String, java.lang.String, com.hack23.cia.service.external.common.api.ProcessDataStrategy)
	 */
	@Override
	public void processDocumentList(final String changedSinceDate, final String changedToDate,
			final ProcessDataStrategy<DocumentElement> processStrategy) throws DataFailureException {
		try {
			loadAndProcessDocumentList(DOCUMENT_LIST_CHANGED_DATE.replace(CHANGED_SINCE_KEY, changedSinceDate)
					.replace(CHANGED_TO_KEY, changedToDate), processStrategy);
		} catch (final XmlAgentException e) {
			LOGGER.warn(PROBLEM_PROCCESSING_DOCUMENT_BETWEEN_CHANGED_SINCE_DATE_S_AND_CHANGE_TO_DATE, changedSinceDate,
					changedToDate);
			throw new DataFailureException(e);
		}
	}

}


/*
 * Copyright 2010 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.11
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2019.02.24 at 11:39:56 PM CET
//

package com.hack23.cia.model.external.riksdagen.person.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.hack23.cia.model.common.api.ModelObject;

/**
 * The Class PersonDetailData.
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PersonDetailData", propOrder = {
    "detailList"
})
@Entity(name = "PersonDetailData")
@Table(name = "PERSON_DETAIL_DATA")
@Inheritance(strategy = InheritanceType.JOINED)
public class PersonDetailData
    implements ModelObject
{

    /**
	 *
	 */
	private static final long serialVersionUID = 1L;

	/** The detail list. */
    @XmlElement(name = "uppgift", required = true)
    protected List<DetailData> detailList = new ArrayList<>();

    /** The hjid. */
    @XmlAttribute(name = "Hjid")
    protected Long hjid;

    /**
	 * Gets the detail list.
	 *
	 * @return the detail list
	 */
    @OneToMany(targetEntity = DetailData.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "DETAIL_LIST_PERSON_DETAIL_DA_0")
    public List<DetailData> getDetailList() {
        return this.detailList;
    }

    /**
	 * Sets the detail list.
	 *
	 * @param detailList the new detail list
	 */
    public void setDetailList(final List<DetailData> detailList) {
        this.detailList = detailList;
    }

    /**
	 * With detail list.
	 *
	 * @param detailList the detail list
	 * @return the person detail data
	 */
    public PersonDetailData withDetailList(final List<DetailData> detailList) {
        setDetailList(detailList);
        return this;
    }

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public final String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

    /**
	 * Gets the hjid.
	 *
	 * @return the hjid
	 */
    @Id
    @Column(name = "HJID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getHjid() {
        return hjid;
    }

    /**
	 * Sets the hjid.
	 *
	 * @param value the new hjid
	 */
    public void setHjid(final Long value) {
        this.hjid = value;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    public boolean equals(final Object object) {
    	return EqualsBuilder.reflectionEquals(this,object,"hjid");
    }

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public final int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this);
	}

}


/*
 * Copyright 2010-2019 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
package com.hack23.cia.service.external.common.impl;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Locale;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.apache.http.client.fluent.Request;
import org.jdom2.JDOMException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.oxm.Unmarshaller;
import org.springframework.stereotype.Service;

import com.hack23.cia.service.external.common.api.XmlAgent;
import com.hack23.cia.service.external.common.api.XmlAgentException;

/**
 * The Class XmlAgentImpl.
 */
@Service
final class XmlAgentImpl implements XmlAgent {

	/** The Constant LOGGER. */
	private static final Logger LOGGER = LoggerFactory.getLogger(XmlAgentImpl.class);

	/**
	 * Instantiates a new xml agent impl.
	 */
	public XmlAgentImpl() {
		super();
	}

	/**
	 * Read with string buffer.
	 *
	 * @param fr
	 *            the fr
	 * @return the string
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	private static String readWithStringBuffer(final Reader fr) throws IOException {

		final BufferedReader br = new BufferedReader(fr);
		String line;
		final StringBuilder result = new StringBuilder();
		while ((line = br.readLine()) != null) {
			result.append(line);
		}

		return result.toString();
	}

	@Override
	public String retriveContent(final String accessUrl) throws XmlAgentException {
		try {
			final URL url = new URL(accessUrl.replace(" ", ""));

			return readWithStringBuffer(new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)));
		} catch (IOException e) {
			throw new XmlAgentException(e);
		}
	}

	@Override
	public Object unmarshallXml(final Unmarshaller unmarshaller, final String accessUrl) throws XmlAgentException {
		return unmarshallXml(unmarshaller, accessUrl, null, null, null);
	}

	@Override
	public Object unmarshallXml(final Unmarshaller unmarshaller, final String accessUrl, final String nameSpace,
			final String replace, final String with) throws XmlAgentException {

		try {
			LOGGER.info("Calls {}", accessUrl);

			final boolean isWeb = accessUrl.toLowerCase(Locale.ENGLISH).startsWith("http://")
					|| accessUrl.toLowerCase(Locale.ENGLISH).startsWith("https://");

			String xmlContent;
			if (isWeb) {
				xmlContent = Request.Get(accessUrl.replace(" ", "")).execute().returnContent()
						.asString(StandardCharsets.UTF_8);
			} else {
				xmlContent = readInputStream(accessUrl.replace(" ", ""));
			}

			if (replace != null) {
				xmlContent = xmlContent.replace(replace, with);
			}

			final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
					xmlContent.getBytes(StandardCharsets.UTF_8));

			Source source;
			if (nameSpace != null) {
				source = NameSpaceUtil.setNameSpaceOnXmlStream(byteArrayInputStream, nameSpace);
			} else {
				source = new StreamSource(byteArrayInputStream);
			}

			return unmarshaller.unmarshal(source);
		} catch (IOException | JDOMException e) {
			throw new XmlAgentException(e);
		}
	}

	/**
	 * Read input stream.
	 *
	 * @param accessUrl
	 *            the access url
	 * @return the string
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	private static String readInputStream(final String accessUrl) throws IOException {
		final URL url = new URL(accessUrl.replace(" ", ""));
		return readWithStringBuffer(new BufferedReader(new InputStreamReader(url.openConnection().getInputStream(), StandardCharsets.UTF_8)));
	}
}


/*
 * Copyright 2010 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.11
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2019.02.24 at 11:39:59 PM CET
//

package com.hack23.cia.model.external.riksdagen.personlista.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.hack23.cia.model.common.api.ModelObject;

/**
 * The Class PersonContainerElement.
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PersonContainerElement", propOrder = {
    "person"
})
@Entity(name = "PersonContainerElement")
@Table(name = "PERSON_CONTAINER_ELEMENT")
@Inheritance(strategy = InheritanceType.JOINED)
public class PersonContainerElement
    implements ModelObject
{

    /**
	 *
	 */
	private static final long serialVersionUID = 1L;

	/** The person. */
    @XmlElement(required = true)
    protected List<PersonElement> person = new ArrayList<>();

    /** The hjid. */
    @XmlAttribute(name = "Hjid")
    protected Long hjid;

    /**
	 * Gets the person.
	 *
	 * @return the person
	 */
    @OneToMany(targetEntity = PersonElement.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "PERSON_PERSON_CONTAINER_ELEM_0")
    public List<PersonElement> getPerson() {
        return this.person;
    }

    /**
	 * Sets the person.
	 *
	 * @param person the new person
	 */
    public void setPerson(final List<PersonElement> person) {
        this.person = person;
    }

    /**
	 * With person.
	 *
	 * @param person the person
	 * @return the person container element
	 */
    public PersonContainerElement withPerson(final List<PersonElement> person) {
        setPerson(person);
        return this;
    }

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public final String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

    /**
	 * Gets the hjid.
	 *
	 * @return the hjid
	 */
    @Id
    @Column(name = "HJID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getHjid() {
        return hjid;
    }

    /**
	 * Sets the hjid.
	 *
	 * @param value the new hjid
	 */
    public void setHjid(final Long value) {
        this.hjid = value;
    }

	public boolean equals(final Object obj) {
		if (obj == null) {
			return false;
		}
		if (obj == this) {
			return true;
		}
		if (obj.getClass() != getClass()) {
			return false;
		}
		return new EqualsBuilder().append(getPerson().toArray(), ((PersonContainerElement) obj).getPerson().toArray()).isEquals();
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public final int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this);
	}

}


/*
 * Copyright 2010 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.11
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2019.02.24 at 11:40:17 PM CET
//

package com.hack23.cia.model.external.riksdagen.voteringlista.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.hack23.cia.model.common.api.ModelObject;

/**
 * The Class VoteListContainerElement.
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "VoteListContainerElement", propOrder = {
    "votering"
})
@Entity(name = "VoteListContainerElement")
@Table(name = "VOTE_LIST_CONTAINER_ELEMENT")
@Inheritance(strategy = InheritanceType.JOINED)
public class VoteListContainerElement
    implements ModelObject
{

    /**
	 *
	 */
	private static final long serialVersionUID = 1L;

	/** The votering. */
    @XmlElement(required = true)
    protected List<BallotDocumentElement> votering = new ArrayList<>();

    /** The grouping. */
    @XmlAttribute(name = "gruppering", required = true)
    protected String grouping;

    /** The condition. */
    @XmlAttribute(name = "villkor", required = true)
    protected String condition;

    /** The number value. */
    @XmlAttribute(name = "antal", required = true)
    protected String numberValue;

    /** The hjid. */
    @XmlAttribute(name = "Hjid")
    protected Long hjid;

    /**
	 * Gets the votering.
	 *
	 * @return the votering
	 */
    @OneToMany(targetEntity = BallotDocumentElement.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "VOTERING_VOTE_LIST_CONTAINER_0")
    public List<BallotDocumentElement> getVotering() {
        return this.votering;
    }

    /**
	 * Sets the votering.
	 *
	 * @param votering the new votering
	 */
    public void setVotering(final List<BallotDocumentElement> votering) {
        this.votering = votering;
    }

    /**
	 * Gets the grouping.
	 *
	 * @return the grouping
	 */
    @Basic
    @Column(name = "GROUPING_")
    public String getGrouping() {
        return grouping;
    }

    /**
	 * Sets the grouping.
	 *
	 * @param value the new grouping
	 */
    public void setGrouping(final String value) {
        this.grouping = value;
    }

    /**
	 * Gets the condition.
	 *
	 * @return the condition
	 */
    @Basic
    @Column(name = "CONDITION")
    public String getCondition() {
        return condition;
    }

    /**
	 * Sets the condition.
	 *
	 * @param value the new condition
	 */
    public void setCondition(final String value) {
        this.condition = value;
    }

    /**
	 * Gets the number value.
	 *
	 * @return the number value
	 */
    @Basic
    @Column(name = "NUMBER_VALUE")
    public String getNumberValue() {
        return numberValue;
    }

    /**
	 * Sets the number value.
	 *
	 * @param value the new number value
	 */
    public void setNumberValue(final String value) {
        this.numberValue = value;
    }

    /**
	 * With votering.
	 *
	 * @param votering the votering
	 * @return the vote list container element
	 */
    public VoteListContainerElement withVotering(final List<BallotDocumentElement> votering) {
        setVotering(votering);
        return this;
    }

    /**
	 * With grouping.
	 *
	 * @param value the value
	 * @return the vote list container element
	 */
    public VoteListContainerElement withGrouping(final String value) {
        setGrouping(value);
        return this;
    }

    /**
	 * With condition.
	 *
	 * @param value the value
	 * @return the vote list container element
	 */
    public VoteListContainerElement withCondition(final String value) {
        setCondition(value);
        return this;
    }

    /**
	 * With number value.
	 *
	 * @param value the value
	 * @return the vote list container element
	 */
    public VoteListContainerElement withNumberValue(final String value) {
        setNumberValue(value);
        return this;
    }

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public final String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

    /**
	 * Gets the hjid.
	 *
	 * @return the hjid
	 */
    @Id
    @Column(name = "HJID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getHjid() {
        return hjid;
    }

    /**
	 * Sets the hjid.
	 *
	 * @param value the new hjid
	 */
    public void setHjid(final Long value) {
        this.hjid = value;
    }

	public boolean equals(final Object obj) {
		if (obj == null) {
			return false;
		}
		if (obj == this) {
			return true;
		}
		if (obj.getClass() != getClass()) {
			return false;
		}
		return new EqualsBuilder().append(getVotering().toArray(), ((VoteListContainerElement) obj).getVotering().toArray()).isEquals();
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public final int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this);
	}

}


/*
 * Copyright 2010-2019 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
package com.hack23.cia.service.impl.rules;

import java.util.Collections;
import java.util.List;

import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenCommitteeBallotDecisionPartySummary;
import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenVoteDataBallotPartySummaryAnnual;
import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenVoteDataBallotPartySummaryDaily;
import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenVoteDataBallotPartySummaryMonthly;
import com.hack23.cia.model.internal.application.data.party.impl.ViewRiksdagenPartySummary;
import com.hack23.cia.service.api.action.kpi.ResourceType;

/**
 * The Class PartyComplianceCheckImpl.
 */
public final class PartyComplianceCheckImpl extends AbstractComplianceCheckImpl {

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;

	/** The party. */
	private final ViewRiksdagenPartySummary party;

	/** The name. */
	private final String name;

	/** The ballot decisions. */
	private final List<ViewRiksdagenCommitteeBallotDecisionPartySummary> ballotDecisions;

	/** The daily summary. */
	private final ViewRiksdagenVoteDataBallotPartySummaryDaily dailySummary;

	/** The monthly summary. */
	private final ViewRiksdagenVoteDataBallotPartySummaryMonthly monthlySummary;

	/** The annual summary. */
	private final ViewRiksdagenVoteDataBallotPartySummaryAnnual annualSummary;

	/**
	 * Instantiates a new party compliance check impl.
	 *
	 * @param party           the party
	 * @param annualSummary   the annual summary
	 * @param monthlySummary  the monthly summary
	 * @param dailySummary    the daily summary
	 * @param ballotDecisions the ballot decisions
	 */
	public PartyComplianceCheckImpl(final ViewRiksdagenPartySummary party,final ViewRiksdagenVoteDataBallotPartySummaryAnnual annualSummary,final ViewRiksdagenVoteDataBallotPartySummaryMonthly monthlySummary,final ViewRiksdagenVoteDataBallotPartySummaryDaily dailySummary,final List<ViewRiksdagenCommitteeBallotDecisionPartySummary> ballotDecisions) {
		super(ResourceType.PARTY);
		this.party = party;
		this.annualSummary = annualSummary;
		this.monthlySummary = monthlySummary;
		this.dailySummary = dailySummary;
		this.name = party.getParty();
		this.ballotDecisions = Collections.unmodifiableList(ballotDecisions);
	}

	/**
	 * Gets the party.
	 *
	 * @return the party
	 */
	public ViewRiksdagenPartySummary getParty() {
		return party;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public String getId() {
		return party.getParty();
	}

	/**
	 * Supports.
	 *
	 * @param committeeReport the committee report
	 * @param rm              the rm
	 * @return true, if successful
	 */
	public boolean supports(final String committeeReport,final String rm) {
		for (final ViewRiksdagenCommitteeBallotDecisionPartySummary summary : ballotDecisions) {
			if (summary.getRm().equalsIgnoreCase(rm) && summary.getCommitteeReport().equalsIgnoreCase(committeeReport)) {
				return summary.isPartyApproved();
			}
		}
		return false;
	}

	/**
	 * Against.
	 *
	 * @param committeeReport the committee report
	 * @param rm              the rm
	 * @return true, if successful
	 */
	public boolean against(final String committeeReport,final String rm) {
		for (final ViewRiksdagenCommitteeBallotDecisionPartySummary summary : ballotDecisions) {
			if (summary.getRm().equalsIgnoreCase(rm) && summary.getCommitteeReport().equalsIgnoreCase(committeeReport)) {
				return !summary.isPartyApproved();
			}
		}
		return false;
	}

	/**
	 * Gets the daily summary.
	 *
	 * @return the daily summary
	 */
	public ViewRiksdagenVoteDataBallotPartySummaryDaily getDailySummary() {
		return dailySummary;
	}

	/**
	 * Gets the monthly summary.
	 *
	 * @return the monthly summary
	 */
	public ViewRiksdagenVoteDataBallotPartySummaryMonthly getMonthlySummary() {
		return monthlySummary;
	}

	/**
	 * Gets the annual summary.
	 *
	 * @return the annual summary
	 */
	public ViewRiksdagenVoteDataBallotPartySummaryAnnual getAnnualSummary() {
		return annualSummary;
	}

}


/*
 * Copyright 2010-2019 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
package com.hack23.cia.service.external.esv.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.hack23.cia.service.external.esv.api.EsvApi;
import com.hack23.cia.service.external.esv.api.GovernmentBodyAnnualOutcomeSummary;
import com.hack23.cia.service.external.esv.api.GovernmentBodyAnnualSummary;
import com.hack23.cia.service.external.esv.api.GovernmentOperationPeriodOutcome;

/**
 * The Class EsvApiImpl.
 */
@Component
final class EsvApiImpl implements EsvApi {

	/** The Constant GET_GOVERNMENT_BODY_REPORT. */
	private static final String GET_GOVERNMENT_BODY_REPORT = "getGovernmentBodyReport";

	/** The Constant GET_REPORT. */
	private static final String GET_REPORT = "getReport";

	/** The Constant LOGGER. */
	private static final Logger LOGGER = LoggerFactory
			.getLogger(EsvApiImpl.class);

	/** The Constant NO_MINISTRY. */
	private static final String NO_MINISTRY = "Inget departement";

	/** The esv excel reader. */
	private final EsvExcelReader esvExcelReader;

	/** The esv government operations excel reader. */
	private final EsvGovernmentOperationsExcelReader esvGovernmentOperationsExcelReader;

	/** The esv government body operation outcome reader. */
	private final EsvGovernmentBodyOperationOutcomeReader esvGovernmentBodyOperationOutcomeReader;

	/** The all data. */
	private Map<Integer, List<GovernmentBodyAnnualSummary>> allData;

	/**
	 * Instantiates a new esv api impl.
	 *
	 * @param esvExcelReader                          the esv excel reader
	 * @param esvGovernmentOperationsExcelReader      the esv government operations
	 *                                                excel reader
	 * @param esvGovernmentBodyOperationOutcomeReader the esv government body
	 *                                                operation outcome reader
	 */
	@Autowired
	public EsvApiImpl(final EsvExcelReader esvExcelReader,final EsvGovernmentOperationsExcelReader esvGovernmentOperationsExcelReader,final EsvGovernmentBodyOperationOutcomeReader esvGovernmentBodyOperationOutcomeReader) {
		super();
		this.esvExcelReader = esvExcelReader;
		this.esvGovernmentOperationsExcelReader = esvGovernmentOperationsExcelReader;
		this.esvGovernmentBodyOperationOutcomeReader = esvGovernmentBodyOperationOutcomeReader;
	}

	@Override
	public synchronized Map<Integer, List<GovernmentBodyAnnualSummary>> getData() {
	  if (allData == null) {
		allData = esvExcelReader.getDataPerMinistry(null);
	  }
	  return allData;
	}

	@Override
	public Map<Integer, List<GovernmentBodyAnnualSummary>> getDataPerMinistry(final String name) {
		return esvExcelReader.getDataPerMinistry(name);
	}

	@Override
	public List<GovernmentBodyAnnualSummary> getDataPerMinistryAndYear(final String name, final int year) {
		final Map<Integer, List<GovernmentBodyAnnualSummary>> map = getDataPerMinistry(name);

		final List<GovernmentBodyAnnualSummary> list = map.get(year);
		if (list != null) {
			return list;
		} else {
			return new ArrayList<>();
		}
	}

	@Override
	public List<String> getGovernmentBodyNames() {
		final Set<String> governmentBodyNameSet = new HashSet<>();

		final Map<Integer, List<GovernmentBodyAnnualSummary>> data = getData();

		for (final List<GovernmentBodyAnnualSummary> list : data.values()) {
			for (final GovernmentBodyAnnualSummary governmentBodyAnnualSummary : list) {
				if (!governmentBodyNameSet.contains(governmentBodyAnnualSummary.getName())
						&& governmentBodyAnnualSummary.getHeadCount() > 0) {
					governmentBodyNameSet.add(governmentBodyAnnualSummary.getName());
				}
			}
		}
		return new ArrayList<>(governmentBodyNameSet);
	}

	@Override
	public List<String> getGovernmentBodyNames(final String ministry) {
		final Map<String, Set<String>> governmentBodyNameSetMinistryMap = new HashMap<>();

		final Set<String> governmentBodyNameSetMapEntry = new HashSet<>();
		governmentBodyNameSetMinistryMap.put(ministry, governmentBodyNameSetMapEntry);

		final Map<Integer, List<GovernmentBodyAnnualSummary>> data = getData();

		for (final List<GovernmentBodyAnnualSummary> list : data.values()) {
			for (final GovernmentBodyAnnualSummary governmentBodyAnnualSummary : list) {
				if (ministry.equalsIgnoreCase(governmentBodyAnnualSummary.getMinistry())
						&& !governmentBodyNameSetMapEntry.contains(governmentBodyAnnualSummary.getName())
						&& governmentBodyAnnualSummary.getHeadCount() > 0) {
					governmentBodyNameSetMapEntry.add(governmentBodyAnnualSummary.getName());
				}
			}
		}
		return new ArrayList<>(governmentBodyNameSetMinistryMap.get(ministry));
	}

	@Override
	public List<String> getMinistryNames() {
		final Set<String> ministryNameSet = new HashSet<>();

		final Map<Integer, List<GovernmentBodyAnnualSummary>> data = getData();

		for (final List<GovernmentBodyAnnualSummary> list : data.values()) {
			for (final GovernmentBodyAnnualSummary governmentBodyAnnualSummary : list) {
				if (!ministryNameSet.contains(governmentBodyAnnualSummary.getMinistry())
						&& governmentBodyAnnualSummary.getHeadCount() > 0
						&& !NO_MINISTRY.equalsIgnoreCase(governmentBodyAnnualSummary.getMinistry())) {
					ministryNameSet.add(governmentBodyAnnualSummary.getMinistry());
				}
			}
		}
		return new ArrayList<>(ministryNameSet);
	}

	@Override
	public Map<Integer, GovernmentBodyAnnualSummary> getDataPerGovernmentBody(final String name) {
		return esvExcelReader.getDataPerGovernmentBody(name);
	}

	@Override
	public Map<String,List<GovernmentOperationPeriodOutcome>> getReport() {
		try {
			return esvGovernmentOperationsExcelReader.getReport().stream().collect(Collectors.groupingBy(GovernmentOperationPeriodOutcome::getVariableName));
		} catch (final IOException e) {
			LOGGER.error(GET_REPORT,e);
			return new HashMap<>();
		}
	}

	@Override
	public Map<String, List<GovernmentBodyAnnualOutcomeSummary>> getGovernmentBodyReport() {
		final List<GovernmentBodyAnnualOutcomeSummary> result = getGovernmentBodyList();
		return result.stream().collect(Collectors.groupingBy(GovernmentBodyAnnualOutcomeSummary::getGovermentBody));
	}

	@Override
	public Map<String, List<GovernmentBodyAnnualOutcomeSummary>> getGovernmentBodyReportByMinistry() {
		final List<GovernmentBodyAnnualOutcomeSummary> result = getGovernmentBodyList();
		return result.stream().filter(p -> p.getMinistry() != null).collect(Collectors.groupingBy(GovernmentBodyAnnualOutcomeSummary::getMinistry));
	}

	/**
	 * Gets the government body list.
	 *
	 * @return the government body list
	 */
	private List<GovernmentBodyAnnualOutcomeSummary> getGovernmentBodyList() {
		final List<GovernmentBodyAnnualOutcomeSummary> result = new ArrayList<>();
		try {
			result.addAll(esvGovernmentBodyOperationOutcomeReader.readIncomeCsv());
			result.addAll(esvGovernmentBodyOperationOutcomeReader.readOutgoingCsv());
		} catch (final IOException e) {
			LOGGER.error(GET_GOVERNMENT_BODY_REPORT,e);
			return result;
		}
		return result;
	}

	@Override
	public Map<String, List<GovernmentBodyAnnualOutcomeSummary>> getGovernmentBodyReportByField(final String string) {
		final List<GovernmentBodyAnnualOutcomeSummary> result = getGovernmentBodyList();
		return result.stream().filter(p -> p.getDescriptionFields().get(string) != null) .collect(Collectors.groupingBy(t -> t.getDescriptionFields().get(string)));
	}

	@Override
	public Map<String, List<GovernmentBodyAnnualOutcomeSummary>> getGovernmentBodyReportByFieldAndMinistry(final String string,final String ministry) {
		final List<GovernmentBodyAnnualOutcomeSummary> result = getGovernmentBodyList();
		return result.stream().filter(p -> p.getDescriptionFields().get(string) != null && ministry.equalsIgnoreCase(p.getMinistry())) .collect(Collectors.groupingBy(t -> t.getDescriptionFields().get(string)));
	}

}


/*
 * Copyright 2010 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.11
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2019.02.24 at 11:39:59 PM CET
//

package com.hack23.cia.model.external.riksdagen.personlista.impl;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.hack23.cia.model.common.api.ModelObject;

/**
 * The Class PersonElement.
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PersonElement", propOrder = {
    "hangarGuid",
    "id",
    "bornYear",
    "gender",
    "lastName",
    "firstName",
    "place",
    "party",
    "electionRegion",
    "status",
    "imageUrl192",
    "imageUrlMax",
    "imageUrl80",
    "personUrlXml",
    "personAssignmentElement",
    "personDetailElement"
})
@Entity(name = "PersonElement")
@Table(name = "PERSON_ELEMENT")
@Inheritance(strategy = InheritanceType.JOINED)
public class PersonElement
    implements ModelObject
{

    /**
	 *
	 */
	private static final long serialVersionUID = 1L;

	/** The hangar guid. */
    @XmlElement(name = "hangar_guid", required = true)
    protected String hangarGuid;

    /** The id. */
    @XmlElement(name = "intressent_id", required = true)
    protected String id;

    /** The born year. */
    @XmlElement(name = "fodd_ar", required = true)
    protected String bornYear;

    /** The gender. */
    @XmlElement(name = "kon", required = true)
    @XmlSchemaType(name = "string")
    protected SexType gender;

    /** The last name. */
    @XmlElement(name = "efternamn", required = true)
    protected String lastName;

    /** The first name. */
    @XmlElement(name = "tilltalsnamn", required = true)
    protected String firstName;

    /** The place. */
    @XmlElement(name = "iort", required = true)
    protected String place;

    /** The party. */
    @XmlElement(name = "parti", required = true)
    protected String party;

    /** The election region. */
    @XmlElement(name = "valkrets", required = true)
    protected String electionRegion;

    /** The status. */
    @XmlElement(required = true)
    @XmlSchemaType(name = "string")
    protected RoleStatus status;

    /** The image url 192. */
    @XmlElement(name = "bild_url_192", required = true)
    @XmlSchemaType(name = "anyURI")
    protected String imageUrl192;

    /** The image url max. */
    @XmlElement(name = "bild_url_max", required = true)
    @XmlSchemaType(name = "anyURI")
    protected String imageUrlMax;

    /** The image url 80. */
    @XmlElement(name = "bild_url_80", required = true)
    @XmlSchemaType(name = "anyURI")
    protected String imageUrl80;

    /** The person url xml. */
    @XmlElement(name = "person_url_xml", required = true)
    @XmlSchemaType(name = "anyURI")
    protected String personUrlXml;

    /** The person assignment element. */
    @XmlElement(name = "personuppdrag", required = true)
    protected PersonAssignmentElement personAssignmentElement;

    /** The person detail element. */
    @XmlElement(name = "personuppgift", required = true)
    protected PersonDetailElement personDetailElement;

    /**
	 * Gets the hangar guid.
	 *
	 * @return the hangar guid
	 */
    @Basic
    @Column(name = "HANGAR_GUID")
    public String getHangarGuid() {
        return hangarGuid;
    }

    /**
	 * Sets the hangar guid.
	 *
	 * @param value the new hangar guid
	 */
    public void setHangarGuid(final String value) {
        this.hangarGuid = value;
    }

    /**
	 * Gets the id.
	 *
	 * @return the id
	 */
    @Id
    @Column(name = "ID")
    public String getId() {
        return id;
    }

    /**
	 * Sets the id.
	 *
	 * @param value the new id
	 */
    public void setId(final String value) {
        this.id = value;
    }

    /**
	 * Gets the born year.
	 *
	 * @return the born year
	 */
    @Basic
    @Column(name = "BORN_YEAR")
    public String getBornYear() {
        return bornYear;
    }

    /**
	 * Sets the born year.
	 *
	 * @param value the new born year
	 */
    public void setBornYear(final String value) {
        this.bornYear = value;
    }

    /**
	 * Gets the gender.
	 *
	 * @return the gender
	 */
    @Basic
    @Column(name = "GENDER")
    @Enumerated(EnumType.STRING)
    public SexType getGender() {
        return gender;
    }

    /**
	 * Sets the gender.
	 *
	 * @param value the new gender
	 */
    public void setGender(final SexType value) {
        this.gender = value;
    }

    /**
	 * Gets the last name.
	 *
	 * @return the last name
	 */
    @Basic
    @Column(name = "LAST_NAME")
    public String getLastName() {
        return lastName;
    }

    /**
	 * Sets the last name.
	 *
	 * @param value the new last name
	 */
    public void setLastName(final String value) {
        this.lastName = value;
    }

    /**
	 * Gets the first name.
	 *
	 * @return the first name
	 */
    @Basic
    @Column(name = "FIRST_NAME")
    public String getFirstName() {
        return firstName;
    }

    /**
	 * Sets the first name.
	 *
	 * @param value the new first name
	 */
    public void setFirstName(final String value) {
        this.firstName = value;
    }

    /**
	 * Gets the place.
	 *
	 * @return the place
	 */
    @Basic
    @Column(name = "PLACE")
    public String getPlace() {
        return place;
    }

    /**
	 * Sets the place.
	 *
	 * @param value the new place
	 */
    public void setPlace(final String value) {
        this.place = value;
    }

    /**
	 * Gets the party.
	 *
	 * @return the party
	 */
    @Basic
    @Column(name = "PARTY")
    public String getParty() {
        return party;
    }

    /**
	 * Sets the party.
	 *
	 * @param value the new party
	 */
    public void setParty(final String value) {
        this.party = value;
    }

    /**
	 * Gets the election region.
	 *
	 * @return the election region
	 */
    @Basic
    @Column(name = "ELECTION_REGION")
    public String getElectionRegion() {
        return electionRegion;
    }

    /**
	 * Sets the election region.
	 *
	 * @param value the new election region
	 */
    public void setElectionRegion(final String value) {
        this.electionRegion = value;
    }

    /**
	 * Gets the status.
	 *
	 * @return the status
	 */
    @Basic
    @Column(name = "STATUS")
    @Enumerated(EnumType.STRING)
    public RoleStatus getStatus() {
        return status;
    }

    /**
	 * Sets the status.
	 *
	 * @param value the new status
	 */
    public void setStatus(final RoleStatus value) {
        this.status = value;
    }

    /**
	 * Gets the image url 192.
	 *
	 * @return the image url 192
	 */
    @Basic
    @Column(name = "IMAGE_URL_192")
    public String getImageUrl192() {
        return imageUrl192;
    }

    /**
	 * Sets the image url 192.
	 *
	 * @param value the new image url 192
	 */
    public void setImageUrl192(final String value) {
        this.imageUrl192 = value;
    }

    /**
	 * Gets the image url max.
	 *
	 * @return the image url max
	 */
    @Basic
    @Column(name = "IMAGE_URL_MAX")
    public String getImageUrlMax() {
        return imageUrlMax;
    }

    /**
	 * Sets the image url max.
	 *
	 * @param value the new image url max
	 */
    public void setImageUrlMax(final String value) {
        this.imageUrlMax = value;
    }

    /**
	 * Gets the image url 80.
	 *
	 * @return the image url 80
	 */
    @Basic
    @Column(name = "IMAGE_URL_80")
    public String getImageUrl80() {
        return imageUrl80;
    }

    /**
	 * Sets the image url 80.
	 *
	 * @param value the new image url 80
	 */
    public void setImageUrl80(final String value) {
        this.imageUrl80 = value;
    }

    /**
	 * Gets the person url xml.
	 *
	 * @return the person url xml
	 */
    @Basic
    @Column(name = "PERSON_URL_XML")
    public String getPersonUrlXml() {
        return personUrlXml;
    }

    /**
	 * Sets the person url xml.
	 *
	 * @param value the new person url xml
	 */
    public void setPersonUrlXml(final String value) {
        this.personUrlXml = value;
    }

    /**
	 * Gets the person assignment element.
	 *
	 * @return the person assignment element
	 */
    @ManyToOne(targetEntity = PersonAssignmentElement.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "PERSON_ASSIGNMENT_ELEMENT_PE_0")
    public PersonAssignmentElement getPersonAssignmentElement() {
        return personAssignmentElement;
    }

    /**
	 * Sets the person assignment element.
	 *
	 * @param value the new person assignment element
	 */
    public void setPersonAssignmentElement(final PersonAssignmentElement value) {
        this.personAssignmentElement = value;
    }

    /**
	 * Gets the person detail element.
	 *
	 * @return the person detail element
	 */
    @ManyToOne(targetEntity = PersonDetailElement.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "PERSON_DETAIL_ELEMENT_PERSON_0")
    public PersonDetailElement getPersonDetailElement() {
        return personDetailElement;
    }

    /**
	 * Sets the person detail element.
	 *
	 * @param value the new person detail element
	 */
    public void setPersonDetailElement(final PersonDetailElement value) {
        this.personDetailElement = value;
    }

    /**
	 * With hangar guid.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withHangarGuid(final String value) {
        setHangarGuid(value);
        return this;
    }

    /**
	 * With id.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withId(final String value) {
        setId(value);
        return this;
    }

    /**
	 * With born year.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withBornYear(final String value) {
        setBornYear(value);
        return this;
    }

    /**
	 * With gender.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withGender(final SexType value) {
        setGender(value);
        return this;
    }

    /**
	 * With last name.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withLastName(final String value) {
        setLastName(value);
        return this;
    }

    /**
	 * With first name.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withFirstName(final String value) {
        setFirstName(value);
        return this;
    }

    /**
	 * With place.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withPlace(final String value) {
        setPlace(value);
        return this;
    }

    /**
	 * With party.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withParty(final String value) {
        setParty(value);
        return this;
    }

    /**
	 * With election region.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withElectionRegion(final String value) {
        setElectionRegion(value);
        return this;
    }

    /**
	 * With status.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withStatus(final RoleStatus value) {
        setStatus(value);
        return this;
    }

    /**
	 * With image url 192.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withImageUrl192(final String value) {
        setImageUrl192(value);
        return this;
    }

    /**
	 * With image url max.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withImageUrlMax(final String value) {
        setImageUrlMax(value);
        return this;
    }

    /**
	 * With image url 80.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withImageUrl80(final String value) {
        setImageUrl80(value);
        return this;
    }

    /**
	 * With person url xml.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withPersonUrlXml(final String value) {
        setPersonUrlXml(value);
        return this;
    }

    /**
	 * With person assignment element.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withPersonAssignmentElement(final PersonAssignmentElement value) {
        setPersonAssignmentElement(value);
        return this;
    }

    /**
	 * With person detail element.
	 *
	 * @param value the value
	 * @return the person element
	 */
    public PersonElement withPersonDetailElement(final PersonDetailElement value) {
        setPersonDetailElement(value);
        return this;
    }

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public final String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    public boolean equals(final Object object) {
    	return EqualsBuilder.reflectionEquals(this,object);
    }

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public final int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this);
	}

}


/*
 * Copyright 2010-2019 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
package com.hack23.cia.service.impl.action.application;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.UUID;

import org.passay.CharacterRule;
import org.passay.EnglishCharacterData;
import org.passay.LengthRule;
import org.passay.PasswordData;
import org.passay.PasswordValidator;
import org.passay.RuleResult;
import org.passay.WhitespaceRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.hack23.cia.model.internal.application.system.impl.ApplicationConfiguration;
import com.hack23.cia.model.internal.application.system.impl.ApplicationEventGroup;
import com.hack23.cia.model.internal.application.system.impl.ApplicationOperationType;
import com.hack23.cia.model.internal.application.system.impl.ConfigurationGroup;
import com.hack23.cia.model.internal.application.user.impl.UserAccount;
import com.hack23.cia.model.internal.application.user.impl.UserAccount_;
import com.hack23.cia.model.internal.application.user.impl.UserEmailStatus;
import com.hack23.cia.model.internal.application.user.impl.UserLockStatus;
import com.hack23.cia.model.internal.application.user.impl.UserRole;
import com.hack23.cia.model.internal.application.user.impl.UserType;
import com.hack23.cia.service.api.action.application.CreateApplicationEventRequest;
import com.hack23.cia.service.api.action.application.RegisterUserRequest;
import com.hack23.cia.service.api.action.application.RegisterUserResponse;
import com.hack23.cia.service.api.action.common.ServiceResponse.ServiceResult;
import com.hack23.cia.service.data.api.ApplicationConfigurationService;
import com.hack23.cia.service.impl.action.common.AbstractBusinessServiceImpl;
import com.hack23.cia.service.impl.action.common.BusinessService;

/**
 * The Class RegisterUserService.
 */
@Service
@Transactional(propagation = Propagation.REQUIRED)
public final class RegisterUserService extends AbstractBusinessServiceImpl<RegisterUserRequest, RegisterUserResponse>
		implements BusinessService<RegisterUserRequest, RegisterUserResponse> {

	/** The Constant LOGGER. */
	private static final Logger LOGGER = LoggerFactory.getLogger(RegisterUserService.class);

	/** The application configuration service. */
	@Autowired
	private ApplicationConfigurationService applicationConfigurationService;

	/** The password encoder. */
	private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

	/** The password validator. */
	private final PasswordValidator passwordValidator = new PasswordValidator(new LengthRule(8, 64),
			new CharacterRule(EnglishCharacterData.UpperCase, 1), new CharacterRule(EnglishCharacterData.LowerCase, 1),
			new CharacterRule(EnglishCharacterData.Digit, 1), new CharacterRule(EnglishCharacterData.Special, 1),
			new WhitespaceRule());

	/**
	 * Instantiates a new register user service.
	 */
	public RegisterUserService() {
		super(RegisterUserRequest.class);
	}

	@Override
	@Secured({ "ROLE_ANONYMOUS" })
	public RegisterUserResponse processService(final RegisterUserRequest serviceRequest) {
		final RegisterUserResponse inputValidation = inputValidation(serviceRequest);
		if (inputValidation != null) {
			return inputValidation;
		}

		final CreateApplicationEventRequest eventRequest = createApplicationEventForService(serviceRequest);

		RegisterUserResponse response;

		final UserAccount userNameExist = getUserDAO().findFirstByProperty(UserAccount_.username,
				serviceRequest.getUsername());
		final UserAccount userEmailExist = getUserDAO().findFirstByProperty(UserAccount_.email, serviceRequest.getEmail());

		final RuleResult passwordRuleResults = passwordValidator
				.validate(new PasswordData(serviceRequest.getUserpassword()));

		if (userEmailExist == null && userNameExist == null && passwordRuleResults.isValid()) {
			final UserAccount userAccount = createUserAccount(serviceRequest);
			eventRequest.setUserId(userAccount.getUserId());
			response = new RegisterUserResponse(ServiceResult.SUCCESS);
		} else {
			response = new RegisterUserResponse(ServiceResult.FAILURE);
			if (passwordRuleResults.isValid()) {
				response.setErrorMessage(RegisterUserResponse.ErrorMessage.USER_ALREADY_EXIST.toString());
				eventRequest.setErrorMessage(RegisterUserResponse.ErrorMessage.USER_ALREADY_EXIST.toString());
			} else {
				final String errorMessage = passwordValidator.getMessages(passwordRuleResults).toString();
				response.setErrorMessage(errorMessage);
				eventRequest.setErrorMessage(errorMessage);
			}
		}

		eventRequest.setApplicationMessage(response.getResult().toString());
		createApplicationEventService.processService(eventRequest);
		LOGGER.info("Event: {}", eventRequest);
		return response;
	}

	/**
	 * Creates the user account.
	 *
	 * @param serviceRequest the service request
	 * @return the user account
	 */
	private UserAccount createUserAccount(final RegisterUserRequest serviceRequest) {

		final ApplicationConfiguration registeredUsersGetAdminConfig = applicationConfigurationService
				.checkValueOrLoadDefault("Registered User All get Role Admin", "Registered User All get Role Admin",
						ConfigurationGroup.AUTHORIZATION, RegisterUserService.class.getSimpleName(),
						"Register User Service", "Responsible for create of useraccounts", "registered.users.get.admin",
						"true");

		final UserAccount userAccount = new UserAccount();
		userAccount.setCountry(serviceRequest.getCountry());
		userAccount.setEmail(serviceRequest.getEmail());
		userAccount.setUsername(serviceRequest.getUsername());
		userAccount.setUserId(UUID.randomUUID().toString());
		userAccount.setUserpassword(
				passwordEncoder.encode(userAccount.getUserId() + ".uuid" + serviceRequest.getUserpassword()));
		userAccount.setNumberOfVisits(1);

		if ( serviceRequest.getUserType() == null) {
			userAccount.setUserType(UserType.PRIVATE);
		} else {
			userAccount.setUserType(serviceRequest.getUserType());
		}

		userAccount.setUserEmailStatus(UserEmailStatus.UNKNOWN);
		userAccount.setUserLockStatus(UserLockStatus.UNLOCKED);
		userAccount.setCreatedDate(new Date());
		getUserDAO().persist(userAccount);

		final Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
		if ("true".equals(registeredUsersGetAdminConfig.getPropertyValue())) {
			userAccount.setUserRole(UserRole.ADMIN);
			authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
		} else {
			userAccount.setUserRole(UserRole.USER);
			authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
		}

		SecurityContextHolder.getContext().setAuthentication(
				new UsernamePasswordAuthenticationToken(userAccount.getUserId(), "n/a", authorities));
		return userAccount;
	}

	@Override
	protected CreateApplicationEventRequest createApplicationEventForService(
			final RegisterUserRequest serviceRequest) {
		final CreateApplicationEventRequest eventRequest = createBaseApplicationEventRequest();
		eventRequest.setEventGroup(ApplicationEventGroup.USER);
		eventRequest.setApplicationOperation(ApplicationOperationType.CREATE);
		eventRequest.setActionName(RegisterUserRequest.class.getSimpleName());
		eventRequest.setSessionId(serviceRequest.getSessionId());
		eventRequest.setElementId(serviceRequest.getEmail());
		return eventRequest;
	}

	@Override
	protected RegisterUserResponse createErrorResponse() {
		return new RegisterUserResponse(ServiceResult.FAILURE);
	}

}


/*
 * Copyright 2010-2019 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
package com.hack23.cia.web.impl.ui.application.views.common.rows;

import com.hack23.cia.web.impl.ui.application.views.common.sizing.ContentRatio;
import com.jarektoro.responsivelayout.ResponsiveLayout;
import com.jarektoro.responsivelayout.ResponsiveRow;
import com.vaadin.server.Responsive;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Label;

/**
 * The Class RowUtil.
 */
public final class RowUtil {

	/** The Constant TITLE. */
	private static final String TITLE = "title";

	/** The Constant ITEMBOX. */
	private static final String ITEMBOX = "itembox";

	/** The Constant DISPLAY_SIZE_LG_DEVICE. */
	private static final int DISPLAY_SIZE_LG_DEVICE = 4;

	/** The Constant DISPLAY_SIZE_MD_DEVICE. */
	private static final int DISPLAY_SIZE_MD_DEVICE = 4;

	/** The Constant DISPLAYS_SIZE_XM_DEVICE. */
	private static final int DISPLAYS_SIZE_XM_DEVICE = 6;

	/** The Constant DISPLAY_SIZE_XS_DEVICE. */
	private static final int DISPLAY_SIZE_XS_DEVICE = 12;

	/**
	 * Creates the row item.
	 *
	 * @param row         the row
	 * @param button      the button
	 * @param description the description
	 */
	public static void createRowItem(final ResponsiveRow row, final Button button, final String description) {
		final CssLayout layout = new CssLayout();
		layout.addStyleName("v-layout-content-overview-panel-level2");
		Responsive.makeResponsive(layout);
		layout.setSizeUndefined();

		button.addStyleName(ITEMBOX);
		button.addStyleName(TITLE);
		Responsive.makeResponsive(button);
		button.setWidth(100, Unit.PERCENTAGE);
		layout.addComponent(button);

		final Label descriptionLabel = new Label(description);
		descriptionLabel.addStyleName(ITEMBOX);
		Responsive.makeResponsive(descriptionLabel);
		descriptionLabel.setWidth(100, Unit.PERCENTAGE);
		layout.addComponent(descriptionLabel);

		row.addColumn().withDisplayRules(DISPLAY_SIZE_XS_DEVICE, DISPLAYS_SIZE_XM_DEVICE, DISPLAY_SIZE_MD_DEVICE,
				DISPLAY_SIZE_LG_DEVICE).withComponent(layout);
	}

	/**
	 * Creates the row component.
	 *
	 * @param row         the row
	 * @param component   the component
	 * @param description the description
	 */
	public static void createRowComponent(final ResponsiveRow row, final Component component,
			final String description) {
		final CssLayout layout = new CssLayout();
		layout.addStyleName(".v-layout-content-pagemode-panel-level2");
		Responsive.makeResponsive(layout);
		layout.setSizeUndefined();

		final Label descriptionLabel = new Label(description);
		descriptionLabel.addStyleName(ITEMBOX);
		Responsive.makeResponsive(descriptionLabel);
		descriptionLabel.setWidth(100, Unit.PERCENTAGE);
		layout.addComponent(descriptionLabel);

		component.addStyleName(ITEMBOX);
		component.addStyleName(TITLE);
		Responsive.makeResponsive(component);
		component.setWidth(100, Unit.PERCENTAGE);
		layout.addComponent(component);

		row.addColumn().withDisplayRules(DISPLAY_SIZE_XS_DEVICE, DISPLAYS_SIZE_XM_DEVICE, DISPLAY_SIZE_MD_DEVICE,
				DISPLAY_SIZE_LG_DEVICE).withComponent(layout);
	}

	/**
	 * Creates the grid layout.
	 *
	 * @param panelContent the panel content
	 * @return the responsive row
	 */
	public static ResponsiveRow createGridLayout(final AbstractOrderedLayout panelContent) {
		final ResponsiveLayout layout = new ResponsiveLayout();
		Responsive.makeResponsive(layout);
		layout.addStyleName("v-layout-content-overview-panel-level1");
		layout.setWidth(100, Unit.PERCENTAGE);
		layout.setHeight(100, Unit.PERCENTAGE);
		panelContent.addComponent(layout);
		panelContent.setExpandRatio(layout, ContentRatio.LARGE);
		return layout.addRow();
	}

}


/*
 * Copyright 2010-2019 James Pether Sörling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *	$Id$
 *  $HeadURL$
*/
package com.hack23.cia.service.component.agent.impl.worldbank.workgenerator;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.jms.Destination;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.hack23.cia.model.internal.application.data.impl.WorldBankDataSources;
import com.hack23.cia.model.internal.application.system.impl.ApplicationConfiguration;
import com.hack23.cia.model.internal.application.system.impl.ConfigurationGroup;
import com.hack23.cia.service.data.api.ApplicationConfigurationService;
import com.hack23.cia.service.external.worldbank.api.DataFailureException;
import com.hack23.cia.service.external.worldbank.api.WorldBankIndicatorApi;

/**
 * The Class WorldBankDataWorkGeneratorImpl.
 */
@Service("WorldBankDataWorkGeneratorImpl")
final class WorldBankDataWorkGeneratorImpl extends AbstractWorldBankDataSourcesWorkGenerator {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(WorldBankDataWorkGeneratorImpl.class);

	/** The data workdestination. */
	@Autowired
	@Qualifier("com.hack23.cia.model.external.worldbank.data.impl.Data")
	private Destination dataWorkdestination;

	/** The application configuration service. */
	@Autowired
	private ApplicationConfigurationService applicationConfigurationService;

	@Autowired
	private WorldBankIndicatorApi worldbankIndicatorApi;

	/**
	 * Instantiates a new world bank data work generator impl.
	 */
	public WorldBankDataWorkGeneratorImpl() {
		super(WorldBankDataSources.DATA);
	}

	@Override
	public void generateWorkOrders() {
		final ApplicationConfiguration importDataForCountries = applicationConfigurationService.checkValueOrLoadDefault(
				"Countries to import data from worldbank (isocode) alt comma separated list",
				"Load worldbank data for countries", ConfigurationGroup.AGENT,
				WorldBankCountryWorkGeneratorImpl.class.getSimpleName(), "Worldbank country data loading",
				"Responsible import worldlbank country data", "agent.worldbank.country.data.loadCountries",
				"SE,NO,DK,FI,GB,US");

		try {
			final List<String> indicatorlist = worldbankIndicatorApi.getIndicatorsWithSwedishData();
			final Map<String, String> currentSaved = getImportService().getWorldBankDataMap();

			for (final String country : getImportService().getWorldBankCountryMap().keySet()) {
				if (StringUtils.containsIgnoreCase(importDataForCountries.getPropertyValue(), country)) {
					sendCountryIndicatorWorkOrder(currentSaved, indicatorlist, country);
				}
			}
		} catch (final DataFailureException e) {
			LOGGER.error("Problem generate data workorders", e);
		}
	}

	/**
	 * Send country indicator work order.
	 *
	 * @param currentSaved    the current saved
	 * @param indicators      the indicators
	 * @param countryIso2Code the country iso 2 code
	 */
	private void sendCountryIndicatorWorkOrder(final Map<String, String> currentSaved, final List<String> indicators,
			final String countryIso2Code) {
		for (final String indicator : indicators) {
			if (countryIso2Code != null && countryIso2Code.length() > 0
					&& !currentSaved.containsKey(countryIso2Code + '.' + indicator)) {
				final List<String> load = new ArrayList<>();
				load.add(countryIso2Code);
				load.add(indicator);
				getJmsSender().send(dataWorkdestination, (Serializable) load);
			}
		}

	}

}