/*
 * 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.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.lang3.time.DateUtils;
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.stereotype.Service;

import com.hack23.cia.model.internal.application.data.committee.impl.RiksdagenVoteDataBallotPartyPeriodSummaryEmbeddedId;
import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenVoteDataBallotPartySummaryDaily;
import com.hack23.cia.service.api.DataContainer;
import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.PartyChartDataManager;
import com.vaadin.ui.AbstractOrderedLayout;

/**
 * The Class ChartDataManagerImpl.
 */
@Service
public final class PartyChartDataManagerImpl extends AbstractChartDataManagerImpl implements PartyChartDataManager {

	/** The Constant PARTY_ABSENT. */
	private static final String PARTY_ABSENT = "Party Absent";

	/** The Constant PARTY_WON. */
	private static final String PARTY_WON = "Party Won";

	/** The Constant NUMBER_BALLOTS. */
	private static final String NUMBER_BALLOTS = "Number ballots";

	/** The Constant DD_MMM_YYYY. */
	private static final String DD_MMM_YYYY = "dd-MMM-yyyy";

	/** The party map. */
	private Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> partyMap;

	/**
	 * Instantiates a new party chart data manager impl.
	 */
	public PartyChartDataManagerImpl() {
		super();
	}

	/**
	 * Gets the max size view riksdagen vote data ballot party summary daily.
	 *
	 * @return the max size view riksdagen vote data ballot party summary daily
	 */
	private List<ViewRiksdagenVoteDataBallotPartySummaryDaily> getMaxSizeViewRiksdagenVoteDataBallotPartySummaryDaily() {
		initPartyMap();

		final Optional<Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>>> first = partyMap.entrySet()
				.stream().sorted((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size())

		).findFirst();

		if (first.isPresent()) {
			return first.get().getValue();
		} else {
			return new ArrayList<>();
		}
	}

	/**
	 * Gets the party map.
	 *
	 * @return the party map
	 */
	private Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> getPartyMap() {
		initPartyMap();

		return partyMap;
	}

	/**
	 * Inits the party map.
	 */
	private synchronized void initPartyMap() {
		if (partyMap == null) {
			final DataContainer<ViewRiksdagenVoteDataBallotPartySummaryDaily, RiksdagenVoteDataBallotPartyPeriodSummaryEmbeddedId> partyBallotSummaryDailyDataContainer = getApplicationManager()
					.getDataContainer(ViewRiksdagenVoteDataBallotPartySummaryDaily.class);

			partyMap = partyBallotSummaryDailyDataContainer.getAll().parallelStream().filter(Objects::nonNull)
					.collect(Collectors.groupingBy(t -> t.getEmbeddedId().getParty()));
		}
	}

	@Override
	public void createPartyWinnerChart(final AbstractOrderedLayout content) {

		final Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> map = getPartyMap();

		final DataSeries dataSeries = new DataSeries();

		final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DD_MMM_YYYY, Locale.ENGLISH);

		final Series series = new Series();

		for (final Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> entry : map.entrySet()) {
			series.addSeries(new XYseries().setLabel(getPartyName(entry.getKey())));
			addPartyData(dataSeries, simpleDateFormat, entry.getValue(), ViewRiksdagenVoteDataBallotPartySummaryDaily::getPartyWonPercentage);
		}

		series.addSeries(new XYseries().setLabel(NUMBER_BALLOTS));
		addPartyData(dataSeries, simpleDateFormat, getMaxSizeViewRiksdagenVoteDataBallotPartySummaryDaily(), ViewRiksdagenVoteDataBallotPartySummaryDaily::getNumberBallots);

		addChart(content,"Party winner by daily ballot average", new DCharts().setDataSeries(dataSeries).setOptions(getChartOptions().createOptionsXYDateFloatLegendInsideOneColumn(series)).show(), true);
	}

	/**
	 * Adds the party data.
	 *
	 * @param dataSeries       the data series
	 * @param simpleDateFormat the simple date format
	 * @param list             the list
	 * @param t                the t
	 */
	private static void addPartyData(final DataSeries dataSeries, final SimpleDateFormat simpleDateFormat,
			final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list, final Function<ViewRiksdagenVoteDataBallotPartySummaryDaily, Object> t) {
		dataSeries.newSeries();
		for (final ViewRiksdagenVoteDataBallotPartySummaryDaily viewRiksdagenVoteDataBallotPartySummaryDaily : list) {
			if (viewRiksdagenVoteDataBallotPartySummaryDaily != null) {
				dataSeries.add(
						simpleDateFormat
								.format(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()),
						t.apply(viewRiksdagenVoteDataBallotPartySummaryDaily));
			}
		}
	}

	/**
	 * Gets the view riksdagen vote data ballot party summary daily.
	 *
	 * @param party
	 *            the party
	 * @return the view riksdagen vote data ballot party summary daily
	 */
	private List<ViewRiksdagenVoteDataBallotPartySummaryDaily> getViewRiksdagenVoteDataBallotPartySummaryDaily(
			final String party) {
		initPartyMap();

		return partyMap.get(party);
	}

	@Override
	public void createPartyLineChart(final AbstractOrderedLayout content,final String partyId) {

		final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list = getViewRiksdagenVoteDataBallotPartySummaryDaily(
				partyId);

		if (list != null) {
			final Series series = new Series().addSeries(new XYseries().setLabel(PARTY_WON))
					.addSeries(new XYseries().setLabel(PARTY_ABSENT));

			final DataSeries dataSeries = new DataSeries();

			final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DD_MMM_YYYY, Locale.ENGLISH);

			addPartyData(dataSeries, simpleDateFormat, list, ViewRiksdagenVoteDataBallotPartySummaryDaily::getPartyWonPercentage);
			addPartyData(dataSeries, simpleDateFormat, list, ViewRiksdagenVoteDataBallotPartySummaryDaily::getPartyPercentageAbsent);

			addChart(content,"Party result by", new DCharts().setDataSeries(dataSeries).setOptions(getChartOptions().createOptionsPartyLineChart(series)).show(), true);
		}
	}

	@Override
	public void createPartyGenderChart(final AbstractOrderedLayout content) {

		createPartyBallotChart(content,viewRiksdagenVoteDataBallotPartySummaryDaily -> 100 - viewRiksdagenVoteDataBallotPartySummaryDaily.getPartyAvgPercentageMale().intValue());

	}

	@Override
	public void createPartyAgeChart(final AbstractOrderedLayout content) {
		createPartyBallotChart(content,viewRiksdagenVoteDataBallotPartySummaryDaily -> DateUtils.toCalendar(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()).get(Calendar.YEAR) - viewRiksdagenVoteDataBallotPartySummaryDaily.getPartyAvgBornYear().intValue());
	}

	/**
	 * Creates the party ballot chart.
	 *
	 * @param dataValueCalculator
	 *            the data value calculator
	 * @return the d charts
	 */
	private void createPartyBallotChart(final AbstractOrderedLayout content,final DataValueCalculator dataValueCalculator) {
		final Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> map = getPartyMap();

		final DataSeries dataSeries = new DataSeries();

		final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DD_MMM_YYYY, Locale.ENGLISH);

		final Series series = new Series();

		for (final Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> entry : map.entrySet()) {

			if (!"-".equals(entry.getKey())) {
				addBallotData(dataValueCalculator, dataSeries, simpleDateFormat, series, entry);
			}
		}

		addChart(content,"Party ballot chart", new DCharts().setDataSeries(dataSeries).setOptions(getChartOptions().createOptionsXYDateFloatLegendInsideOneColumn(series)).show(), true);
	}

	/**
	 * Adds the ballot data.
	 *
	 * @param dataValueCalculator the data value calculator
	 * @param dataSeries          the data series
	 * @param simpleDateFormat    the simple date format
	 * @param series              the series
	 * @param entry               the entry
	 */
	private void addBallotData(final DataValueCalculator dataValueCalculator, final DataSeries dataSeries,
			final SimpleDateFormat simpleDateFormat, final Series series,
			final Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> entry) {
		series.addSeries(new XYseries().setLabel(getPartyName(entry.getKey())));

		dataSeries.newSeries();
		final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list = entry.getValue();
		for (final ViewRiksdagenVoteDataBallotPartySummaryDaily viewRiksdagenVoteDataBallotPartySummaryDaily : list) {
			if (viewRiksdagenVoteDataBallotPartySummaryDaily != null) {
				dataSeries.add(
						simpleDateFormat
								.format(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()),
								dataValueCalculator.getDataValue(viewRiksdagenVoteDataBallotPartySummaryDaily));
			}
		}
	}

	/**
	 * The Interface DataValueCalculator.
	 */
	@FunctionalInterface
	interface DataValueCalculator {

		/**
		 * Gets the data value.
		 *
		 * @param item
		 *            the item
		 * @return the data value
		 */
		Object getDataValue(ViewRiksdagenVoteDataBallotPartySummaryDaily item);
	}

}


/*
 * 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.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.time.Month;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.codec.Charsets;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.http.client.fluent.Request;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * The Class EsvGovernmentBodyOperationOutcomeReaderImpl.
 */
@Component
final class EsvGovernmentBodyOperationOutcomeReaderImpl implements EsvGovernmentBodyOperationOutcomeReader {

	/** The Constant ORGANISATIONSNUMMER. */
	private static final String ORGANISATIONSNUMMER = "Organisationsnummer";

	/** The Constant MYNDIGHET. */
	private static final String MYNDIGHET = "Myndighet";

	/** The Constant ÅR. */
	private static final String YEAR = "År";

	/** The Constant UTFALL_DECEMBER. */
	private static final String UTFALL_DECEMBER = "Utfall december";

	/** The Constant UTFALL_NOVEMBER. */
	private static final String UTFALL_NOVEMBER = "Utfall november";

	/** The Constant UTFALL_OKTOBER. */
	private static final String UTFALL_OKTOBER = "Utfall oktober";

	/** The Constant UTFALL_SEPTEMBER. */
	private static final String UTFALL_SEPTEMBER = "Utfall september";

	/** The Constant UTFALL_AUGUSTI. */
	private static final String UTFALL_AUGUSTI = "Utfall augusti";

	/** The Constant UTFALL_JULI. */
	private static final String UTFALL_JULI = "Utfall juli";

	/** The Constant UTFALL_JUNI. */
	private static final String UTFALL_JUNI = "Utfall juni";

	/** The Constant UTFALL_MAJ. */
	private static final String UTFALL_MAJ = "Utfall maj";

	/** The Constant UTFALL_APRIL. */
	private static final String UTFALL_APRIL = "Utfall april";

	/** The Constant UTFALL_MARS. */
	private static final String UTFALL_MARS = "Utfall mars";

	/** The Constant UTFALL_FEBRUARI. */
	private static final String UTFALL_FEBRUARI = "Utfall februari";

	/** The Constant UTFALL_JANUARI. */
	private static final String UTFALL_JANUARI = "Utfall januari";

	/** The Constant SPECIFIC_OUTGOING_FIELDS. */
	private static final String[] SPECIFIC_OUTGOING_FIELDS = new String[] { "Inkomsttyp", "Inkomsttypsnamn", "Inkomsthuvudgrupp", "Inkomsthuvudgruppsnamn", "Inkomsttitelgrupp", "Inkomsttitelgruppsnamn", "Inkomsttitel", "Inkomsttitelsnamn", "Inkomstundertitel", "Inkomstundertitelsnamn"};

	/** The Constant SPECIFIC_INCOMING_FIELDS. */
	private static final String[] SPECIFIC_INCOMING_FIELDS = new String[] { "Utgiftsområde", "Utgiftsområdesnamn", "Anslag", "Anslagsnamn", "Anslagspost", "Anslagspostsnamn", "Anslagsdelpost", "Anslagsdelpostsnamn"};

	/** The esv excel reader. */
	@Autowired
	private EsvExcelReader esvExcelReader;

	private List<GovernmentBodyAnnualOutcomeSummary> incomeCsvValues;

	private List<GovernmentBodyAnnualOutcomeSummary> outGoingCsvValues;

	/**
	 * Instantiates a new esv government body operation outcome reader impl.
	 */
	public EsvGovernmentBodyOperationOutcomeReaderImpl() {
		super();
	}

	@Override
	public synchronized List<GovernmentBodyAnnualOutcomeSummary> readIncomeCsv() throws IOException {
		if (incomeCsvValues == null) {
			incomeCsvValues = readUsingZipInputStream(Request.Get(
				"https://www.esv.se/psidata/manadsutfall/GetFile/?documentType=Inkomst&fileType=Zip&fileName=M%C3%A5nadsutfall%20inkomster%20januari%202006%20-%20februari%202019,%20definitivt.zip&year=2019&month=2&status=Definitiv")
				.execute().returnContent().asStream(),SPECIFIC_OUTGOING_FIELDS);
		}
		return Collections.unmodifiableList(incomeCsvValues);
	}

	@Override
	public synchronized List<GovernmentBodyAnnualOutcomeSummary> readOutgoingCsv() throws IOException {
		if (outGoingCsvValues == null) {
			outGoingCsvValues = readUsingZipInputStream(Request.Get(
				"https://www.esv.se/psidata/manadsutfall/GetFile/?documentType=Utgift&fileType=Zip&fileName=M%C3%A5nadsutfall%20utgifter%20januari%202006%20-%20februari%202019,%20definitivt.zip&year=2019&month=2&status=Definitiv")
				.execute().returnContent().asStream(),SPECIFIC_INCOMING_FIELDS);
		}
		return Collections.unmodifiableList(outGoingCsvValues);
	}

	/**
	 * Read using zip input stream.
	 *
	 * @param inputStream
	 *            the input stream
	 * @param specificFields
	 *            the specific fields
	 * @return the list
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	private List<GovernmentBodyAnnualOutcomeSummary> readUsingZipInputStream(final InputStream inputStream,final String[] specificFields) throws IOException {
		final BufferedInputStream bis = new BufferedInputStream(inputStream);
		final ZipInputStream is = new ZipInputStream(bis);

		final List<GovernmentBodyAnnualOutcomeSummary> list = new ArrayList<>();
		try {
			ZipEntry entry;
			while ((entry = is.getNextEntry()) != null) {
				list.addAll(readCsvContent(is,specificFields));
			}
		} finally {
			is.close();
		}
		return list;
	}

	/**
	 * Read csv content.
	 *
	 * @param is
	 *            the is
	 * @param specificFields
	 *            the specific fields
	 * @return the list
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	private List<GovernmentBodyAnnualOutcomeSummary> readCsvContent(final InputStream is,final String[] specificFields) throws IOException {
		final CSVParser parser = CSVParser.parse(new InputStreamReader(is,Charsets.UTF_8), CSVFormat.EXCEL.withHeader().withDelimiter(';'));
		final List<CSVRecord> records = parser.getRecords();
		records.remove(0);

		final Map<Integer, Map<String,String>> orgMinistryMap = createOrgMinistryMap(esvExcelReader.getDataPerMinistry(null));

		final List<GovernmentBodyAnnualOutcomeSummary> list = new ArrayList<>();

		for (final CSVRecord csvRecord : records) {
			final GovernmentBodyAnnualOutcomeSummary governmentBodyAnnualOutcomeSummary = new GovernmentBodyAnnualOutcomeSummary(csvRecord.get(MYNDIGHET), csvRecord.get(ORGANISATIONSNUMMER), orgMinistryMap.get(Integer.valueOf(csvRecord.get(YEAR))).get(csvRecord.get(ORGANISATIONSNUMMER).replaceAll("-", "")), Integer.parseInt(csvRecord.get(YEAR)));

			for (final String field : specificFields) {
				governmentBodyAnnualOutcomeSummary.addDescriptionField(field,csvRecord.get(field));
			}

			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.JANUARY.getValue(),csvRecord.get(UTFALL_JANUARI));
			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.FEBRUARY.getValue(),csvRecord.get(UTFALL_FEBRUARI));
			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.MARCH.getValue(),csvRecord.get(UTFALL_MARS));

			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.APRIL.getValue(),csvRecord.get(UTFALL_APRIL));
			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.MAY.getValue(),csvRecord.get(UTFALL_MAJ));
			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.JUNE.getValue(),csvRecord.get(UTFALL_JUNI));

			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.JULY.getValue(),csvRecord.get(UTFALL_JULI));
			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.AUGUST.getValue(),csvRecord.get(UTFALL_AUGUSTI));
			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.SEPTEMBER.getValue(),csvRecord.get(UTFALL_SEPTEMBER));

			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.OCTOBER.getValue(),csvRecord.get(UTFALL_OKTOBER));
			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.NOVEMBER.getValue(),csvRecord.get(UTFALL_NOVEMBER));
			addResultForMonth(governmentBodyAnnualOutcomeSummary,Month.DECEMBER.getValue(),csvRecord.get(UTFALL_DECEMBER));

			list.add(governmentBodyAnnualOutcomeSummary);
		}

		return list;
	}

	/**
	 * Creates the org ministry map.
	 *
	 * @param data the data
	 * @return the map
	 */
	private static Map<Integer, Map<String, String>> createOrgMinistryMap(
			final Map<Integer, List<GovernmentBodyAnnualSummary>> data) {
		final Map<Integer, Map<String,String>> orgMinistryMap = new HashMap<>();

		final Set<Entry<Integer, List<GovernmentBodyAnnualSummary>>> entrySet = data.entrySet();

		for (final Entry<Integer, List<GovernmentBodyAnnualSummary>> entry : entrySet) {
			orgMinistryMap.put(entry.getKey(), entry.getValue().stream().collect(Collectors.groupingBy(t -> t.getOrgNumber().replaceAll("-","") ,Collectors.collectingAndThen(
                    Collectors.toList(),
                    values -> values.get(0).getMinistry()))));
		}

		return orgMinistryMap;
	}

	/**
	 * Adds the result for month.
	 *
	 * @param governmentBodyAnnualOutcomeSummary
	 *            the government body annual outcome summary
	 * @param month
	 *            the month
	 * @param value
	 *            the value
	 */
	private static void addResultForMonth(final GovernmentBodyAnnualOutcomeSummary governmentBodyAnnualOutcomeSummary, final int month,
			final String value) {
		if (value != null && value.length() >0 ) {
			governmentBodyAnnualOutcomeSummary.addData(month,Double.valueOf(value.replaceAll(",", ".")));
		}
	}

}


/*
 * 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.formfactory.impl;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.hack23.cia.web.impl.ui.application.views.common.formfactory.api.FormFactory;
import com.hack23.cia.web.impl.ui.application.views.common.sizing.ContentRatio;
import com.hack23.cia.web.impl.ui.application.views.common.sizing.ContentSize;
import com.hack23.cia.web.impl.ui.application.views.pageclicklistener.CommitFormWrapperClickListener;
import com.vaadin.data.BeanValidationBinder;
import com.vaadin.data.Binder;
import com.vaadin.data.Converter;
import com.vaadin.data.converter.StringToBigDecimalConverter;
import com.vaadin.data.converter.StringToBigIntegerConverter;
import com.vaadin.data.converter.StringToBooleanConverter;
import com.vaadin.data.converter.StringToDateConverter;
import com.vaadin.data.converter.StringToIntegerConverter;
import com.vaadin.data.converter.StringToLongConverter;
import com.vaadin.icons.VaadinIcons;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

/**
 * The Class FormFactoryImpl.
 */
@Service
public final class FormFactoryImpl implements FormFactory {

	/** The Constant SIZE_FOR_GRID. */
	private static final int SIZE_FOR_GRID = 8;

	/** The Constant HIDDEN_FIELD_NAME. */
	private static final String HIDDEN_FIELD_NAME = "password";

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

	@Override
	public <T extends Serializable> void addRequestInputFormFields(final FormLayout panelContent, final T item,
			final Class<T> beanType, final List<String> displayProperties,final String buttonLabel,final ClickListener buttonListener) {
		final BeanValidationBinder<T> binder = new BeanValidationBinder<>(beanType);
		binder.setBean(item);
		binder.setReadOnly(true);

		for (final String property : displayProperties) {

			final AbstractField buildAndBind = createField(property);
			binder.bind(buildAndBind,property);
			buildAndBind.setCaption(property);
			buildAndBind.setId(MessageFormat.format("{0}.{1}", buttonLabel, property));
			buildAndBind.setReadOnly(false);
			buildAndBind.setWidth(ContentSize.HALF_SIZE);

			panelContent.addComponent(buildAndBind);
		}

		final VerticalLayout verticalLayout = new VerticalLayout();
		verticalLayout.setWidth("50%");

		final Button button = new Button(buttonLabel,new CommitFormWrapperClickListener(binder,buttonListener));
		button.setId(buttonLabel);
		button.setWidth("25%");
		button.setIcon(VaadinIcons.BULLSEYE);
		button.setEnabled(false);
		binder.addStatusChangeListener(event -> button.setEnabled(event.getBinder().isValid()));

		verticalLayout.addComponent(button);
		verticalLayout.setComponentAlignment(button, Alignment.MIDDLE_RIGHT);

		panelContent.addComponent(verticalLayout);
	}

	/**
	 * Creates the field.
	 *
	 * @param property the property
	 * @return the abstract field
	 */
	private static AbstractField<?> createField(final String property) {
		if (StringUtils.containsIgnoreCase(property,HIDDEN_FIELD_NAME)) {
			return new PasswordField();
		} else {
			return new TextField();
		}
	}

	@Override
	public <T extends Serializable> void addFormPanelTextFields(final AbstractOrderedLayout panelContent, final T item,
			final Class<T> beanType, final List<String> displayProperties) {

		final Panel formPanel = new Panel();
		formPanel.setSizeFull();

		panelContent.addComponent(formPanel);
		if (displayProperties.size() > SIZE_FOR_GRID) {
			panelContent.setExpandRatio(formPanel, ContentRatio.GRID);
		}
		else {
			panelContent.setExpandRatio(formPanel, ContentRatio.SMALL_GRID);
		}

		final FormLayout formContent = new FormLayout();
		formPanel.setContent(formContent);
		formContent.setWidth(ContentSize.FULL_SIZE);

		final Binder<T> binder = new Binder<>(beanType);
		binder.setBean(item);
		binder.setReadOnly(true);

		PropertyDescriptor[] propertyDescriptors=null;
		try {
			final BeanInfo info = Introspector.getBeanInfo(item.getClass());
			propertyDescriptors = info.getPropertyDescriptors();
		} catch (final IntrospectionException exception) {
			LOGGER.error("No able to getfieldtypes for type:+ item.getClass()", exception);
		}

		createDisplayPropertyConverters(displayProperties, formContent, binder, propertyDescriptors);
	}

	/**
	 * Creates the display property converters.
	 *
	 * @param                     <T> the generic type
	 * @param displayProperties   the display properties
	 * @param formContent         the form content
	 * @param binder              the binder
	 * @param propertyDescriptors the property descriptors
	 */
	private static <T extends Serializable> void createDisplayPropertyConverters(final List<String> displayProperties,
			final ComponentContainer formContent, final Binder<T> binder, final PropertyDescriptor[] propertyDescriptors) {
		for (final String property : displayProperties) {
			final Class<?> typeOfProperty = getTypeOfProperty(propertyDescriptors, property);

			if (typeOfProperty != null) {
				final AbstractField<?> field = new TextField();
				field.setReadOnly(true);
				field.setCaption(property);
				field.setWidth(ContentSize.FULL_SIZE);
				formContent.addComponent(field);
				final Converter converter = getConverterForType(typeOfProperty);

				if (converter != null) {
					binder.forField(field).withConverter(converter).bind(property);
				} else {
					binder.forField(field).bind(property);
				}
			}
		}
	}

	/**
	 * Gets the converter for type.
	 *
	 * @param typeOfProperty
	 *            the type of property
	 * @return the converter for type
	 */
	private static Converter getConverterForType(final Class<?> typeOfProperty) {
		Converter converter;

		if (Date.class.equals(typeOfProperty)) {
			converter = new StringToDateConverter();
		} else if (Integer.class.equals(typeOfProperty) || "int".equalsIgnoreCase(typeOfProperty.getName())) {
			converter = new StringToIntegerConverter("Input value should be an integer");
		} else if (Long.class.equals(typeOfProperty) || "long".equalsIgnoreCase(typeOfProperty.getName())) {
			converter = new StringToLongConverter("Input value should be an long");
		} else if (BigInteger.class.equals(typeOfProperty)) {
			converter = new StringToBigIntegerConverter("Input value should be an biginteger");
		} else if (BigDecimal.class.equals(typeOfProperty)) {
			converter = new StringToBigDecimalConverter("Input value should be an bigdecimal");
		} else if (Boolean.class.equals(typeOfProperty) || "boolean".equalsIgnoreCase(typeOfProperty.getName())) {
			converter = new StringToBooleanConverter("Input value should be an boolean");
		} else if (typeOfProperty.isEnum()) {
			converter = new StringToEnumConverter();
		} else {
			converter = null;
		}

		return converter;
	}

	/**
	 * Gets the type of property.
	 *
	 * @param propertyDescriptors
	 *            the property descriptors
	 * @param property
	 *            the property
	 * @return the type of property
	 */
	private static Class<?> getTypeOfProperty(final PropertyDescriptor[] propertyDescriptors, final String property) {

		for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
			if (propertyDescriptor.getName().equalsIgnoreCase(property)) {
				return propertyDescriptor.getPropertyType();
			}
		}
		return null;
	}

}


/*
 * 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:07 PM CET
//

package com.hack23.cia.model.external.riksdagen.dokumentstatus.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 DocumentActivityContainer.
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "DocumentActivityContainer", propOrder = {
    "documentActivities"
})
@Entity(name = "DocumentActivityContainer")
@Table(name = "DOCUMENT_ACTIVITY_CONTAINER")
@Inheritance(strategy = InheritanceType.JOINED)
public class DocumentActivityContainer
    implements ModelObject
{

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

	/** The document activities. */
    @XmlElement(name = "aktivitet", required = true)
    protected List<DocumentActivityData> documentActivities = new ArrayList<>();

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

    /**
	 * Gets the document activities.
	 *
	 * @return the document activities
	 */
    @OneToMany(targetEntity = DocumentActivityData.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "DOCUMENT_ACTIVITIES_DOCUMENT_0")
    public List<DocumentActivityData> getDocumentActivities() {
        return this.documentActivities;
    }

    /**
	 * Sets the document activities.
	 *
	 * @param documentActivities the new document activities
	 */
    public void setDocumentActivities(final List<DocumentActivityData> documentActivities) {
        this.documentActivities = documentActivities;
    }

    /**
	 * With document activities.
	 *
	 * @param documentActivities the document activities
	 * @return the document activity container
	 */
    public DocumentActivityContainer withDocumentActivities(final List<DocumentActivityData> documentActivities) {
        setDocumentActivities(documentActivities);
        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 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.common;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

import com.hack23.cia.model.internal.application.user.impl.UserAccount;
import com.hack23.cia.model.internal.application.user.impl.UserAccount_;
import com.hack23.cia.service.api.action.common.ServiceRequest;
import com.hack23.cia.service.api.action.common.ServiceResponse;
import com.hack23.cia.service.data.api.UserDAO;

/**
 * The Class AbstractCommonBusinessServiceImpl.
 *
 * @param <T> the generic type
 * @param <V> the value type
 */
public abstract class AbstractCommonBusinessServiceImpl<T extends ServiceRequest, V extends ServiceResponse>
		implements BusinessService<T, V> {

	/** The user dao. */
	@Autowired
	private UserDAO userDAO;

	/** The clazz. */
	private final Class<T> clazz;

	/**
	 * Instantiates a new abstract common business service impl.
	 *
	 * @param clazz the clazz
	 */
	public AbstractCommonBusinessServiceImpl(final Class<T> clazz) {
		this.clazz = clazz;
	}

	@Override
	public final Class<? extends ServiceRequest> getSupportedService() {
		return clazz;
	}

	/**
	 * Gets the user account from security context.
	 *
	 * @return the user account from security context
	 */
	protected final UserAccount getUserAccountFromSecurityContext() {
		final SecurityContext context = SecurityContextHolder.getContext();
		if (context != null) {
			final Authentication authentication = context.getAuthentication();
			if (authentication != null) {
				return userDAO.findFirstByProperty(UserAccount_.userId, authentication.getPrincipal().toString());
			}
		}

		return null;
	}

	/**
	 * Gets the user dao.
	 *
	 * @return the user dao
	 */
	protected final UserDAO getUserDAO() {
		return userDAO;
	}

}


/*
 * 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:54 PM CET
//

package com.hack23.cia.model.external.val.kommunvalkrets.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 com.hack23.cia.model.common.api.ModelObject;

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

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

	/** The county regions. */
    @XmlElement(name = "l\u00e4n", required = true)
    protected List<SwedenCountyData> countyRegions = new ArrayList<>();

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

    /**
	 * Gets the county regions.
	 *
	 * @return the county regions
	 */
    @OneToMany(targetEntity = SwedenCountyData.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "COUNTY_REGIONS_SWEDEN_COUNTY_0")
    public List<SwedenCountyData> getCountyRegions() {
        return this.countyRegions;
    }

    /**
	 * Sets the county regions.
	 *
	 * @param countyRegions the new county regions
	 */
    public void setCountyRegions(final List<SwedenCountyData> countyRegions) {
        this.countyRegions = countyRegions;
    }

    /**
	 * 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(getCountyRegions().toArray(), ((SwedenCountyDataContainer) obj).getCountyRegions().toArray()).isEquals();
	}

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

}


//
// 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.25 at 12:05:09 AM CET
//

package com.hack23.cia.model.internal.application.data.impl;

import java.math.BigDecimal;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
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.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;

/**
 *
Java class for ViewApplicationActionEventPageModeWeeklySummary complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType name="ViewApplicationActionEventPageModeWeeklySummary">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="embeddedId" type="{http://data.application.internal.model.cia.hack23.com/impl}ApplicationActionEventPageModePeriodSummaryEmbeddedId"/>
 *         <element name="hits" type="{http://www.w3.org/2001/XMLSchema}long"/>
 *         <element name="rank" type="{http://www.w3.org/2001/XMLSchema}long"/>
 *         <element name="rank_percentage" type="{http://www.w3.org/2001/XMLSchema}decimal"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ViewApplicationActionEventPageModeWeeklySummary", propOrder = {
    "embeddedId",
    "hits",
    "rank",
    "rankPercentage"
})
@Entity(name = "ViewApplicationActionEventPageModeWeeklySummary")
@Table(name = "view_application_action_event_page_modes_weekly_summary")
@Inheritance(strategy = InheritanceType.JOINED)
public class ViewApplicationActionEventPageModeWeeklySummary
    implements ModelObject
{

    /**
	 *
	 */
	private static final long serialVersionUID = 1L;
	@XmlElement(required = true)
    protected ApplicationActionEventPageModePeriodSummaryEmbeddedId embeddedId;
    protected long hits;
    protected long rank;
    @XmlElement(name = "rank_percentage", required = true)
    protected BigDecimal rankPercentage;

    /**
     * Gets the value of the embeddedId property.
     *
     * @return
     *     possible object is
     *     {@link ApplicationActionEventPageModePeriodSummaryEmbeddedId }
     *
     */
    @EmbeddedId
    @AttributeOverrides({
        @AttributeOverride(name = "createdDate", column = @Column(name = "EMBEDDED_ID_CREATED_DATE")),
        @AttributeOverride(name = "page", column = @Column(name = "EMBEDDED_ID_PAGE")),
        @AttributeOverride(name = "pageMode", column = @Column(name = "EMBEDDED_ID_PAGE_MODE"))
    })
    public ApplicationActionEventPageModePeriodSummaryEmbeddedId getEmbeddedId() {
        return embeddedId;
    }

    /**
     * Sets the value of the embeddedId property.
     *
     * @param value
     *     allowed object is
     *     {@link ApplicationActionEventPageModePeriodSummaryEmbeddedId }
     *
     */
    public void setEmbeddedId(final ApplicationActionEventPageModePeriodSummaryEmbeddedId value) {
        this.embeddedId = value;
    }

    /**
     * Gets the value of the hits property.
     *
     */
    @Basic
    @Column(name = "HITS", precision = 20)
    public long getHits() {
        return hits;
    }

    /**
     * Sets the value of the hits property.
     *
     */
    public void setHits(final long value) {
        this.hits = value;
    }

    /**
     * Gets the value of the rank property.
     *
     */
    @Basic
    @Column(name = "RANK", precision = 20)
    public long getRank() {
        return rank;
    }

    /**
     * Sets the value of the rank property.
     *
     */
    public void setRank(final long value) {
        this.rank = value;
    }

    /**
     * Gets the value of the rankPercentage property.
     *
     * @return
     *     possible object is
     *     {@link BigDecimal }
     *
     */
    @Basic
    @Column(name = "RANK_PERCENTAGE", precision = 20, scale = 10)
    public BigDecimal getRankPercentage() {
        return rankPercentage;
    }

    /**
     * Sets the value of the rankPercentage property.
     *
     * @param value
     *     allowed object is
     *     {@link BigDecimal }
     *
     */
    public void setRankPercentage(final BigDecimal value) {
        this.rankPercentage = value;
    }

    public ViewApplicationActionEventPageModeWeeklySummary withEmbeddedId(final ApplicationActionEventPageModePeriodSummaryEmbeddedId value) {
        setEmbeddedId(value);
        return this;
    }

    public ViewApplicationActionEventPageModeWeeklySummary withHits(final long value) {
        setHits(value);
        return this;
    }

    public ViewApplicationActionEventPageModeWeeklySummary withRank(final long value) {
        setRank(value);
        return this;
    }

    public ViewApplicationActionEventPageModeWeeklySummary withRankPercentage(final BigDecimal value) {
        setRankPercentage(value);
        return this;
    }

	@Override
	public final String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

	@Override
	public final boolean equals(final Object obj) {
		return EqualsBuilder.reflectionEquals(this, obj);
	}

	@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:10 PM CET
//

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

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.ManyToOne;
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 CommitteeProposalComponentData.
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "CommitteeProposalComponentData", propOrder = {
    "againstProposalContainer",
    "document",
    "committeeProposalContainer"
})
@Entity(name = "CommitteeProposalComponentData")
@Table(name = "COMMITTEE_PROPOSAL_COMPONENT_0")
@Inheritance(strategy = InheritanceType.JOINED)
public class CommitteeProposalComponentData
    implements ModelObject
{

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

	/** The against proposal container. */
    @XmlElement(name = "dokmotforslag")
    protected AgainstProposalContainer againstProposalContainer;

    /** The document. */
    @XmlElement(name = "dokument")
    protected CommitteeDocumentData document;

    /** The committee proposal container. */
    @XmlElement(name = "dokutskottsforslag")
    protected CommitteeProposalContainer committeeProposalContainer;

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

    /**
	 * Gets the against proposal container.
	 *
	 * @return the against proposal container
	 */
    @ManyToOne(targetEntity = AgainstProposalContainer.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "AGAINST_PROPOSAL_CONTAINER_C_0")
    public AgainstProposalContainer getAgainstProposalContainer() {
        return againstProposalContainer;
    }

    /**
	 * Sets the against proposal container.
	 *
	 * @param value the new against proposal container
	 */
    public void setAgainstProposalContainer(final AgainstProposalContainer value) {
        this.againstProposalContainer = value;
    }

    /**
	 * Gets the document.
	 *
	 * @return the document
	 */
    @ManyToOne(targetEntity = CommitteeDocumentData.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "DOCUMENT_COMMITTEE_PROPOSAL__0")
    public CommitteeDocumentData getDocument() {
        return document;
    }

    /**
	 * Sets the document.
	 *
	 * @param value the new document
	 */
    public void setDocument(final CommitteeDocumentData value) {
        this.document = value;
    }

    /**
	 * Gets the committee proposal container.
	 *
	 * @return the committee proposal container
	 */
    @ManyToOne(targetEntity = CommitteeProposalContainer.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "COMMITTEE_PROPOSAL_CONTAINER_0")
    public CommitteeProposalContainer getCommitteeProposalContainer() {
        return committeeProposalContainer;
    }

    /**
	 * Sets the committee proposal container.
	 *
	 * @param value the new committee proposal container
	 */
    public void setCommitteeProposalContainer(final CommitteeProposalContainer value) {
        this.committeeProposalContainer = value;
    }

    /**
	 * With against proposal container.
	 *
	 * @param value the value
	 * @return the committee proposal component data
	 */
    public CommitteeProposalComponentData withAgainstProposalContainer(final AgainstProposalContainer value) {
        setAgainstProposalContainer(value);
        return this;
    }

    /**
	 * With document.
	 *
	 * @param value the value
	 * @return the committee proposal component data
	 */
    public CommitteeProposalComponentData withDocument(final CommitteeDocumentData value) {
        setDocument(value);
        return this;
    }

    /**
	 * With committee proposal container.
	 *
	 * @param value the value
	 * @return the committee proposal component data
	 */
    public CommitteeProposalComponentData withCommitteeProposalContainer(final CommitteeProposalContainer value) {
        setCommitteeProposalContainer(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;
    }

    /* (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);
	}

}


//
// 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.25 at 12:05:09 AM CET
//

package com.hack23.cia.model.internal.application.system.impl;

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

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.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.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;
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.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

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;
import com.hack23.cia.model.common.impl.xml.XmlDateTimeTypeAdapter;

/**
 *
Java class for ApplicationSession complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType name="ApplicationSession">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="modelObjectId" type="{http://www.w3.org/2001/XMLSchema}int" minOccurs="0"/>
 *         <element name="modelObjectVersion" type="{http://www.w3.org/2001/XMLSchema}int"/>
 *         <element name="createdDate" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
 *         <element name="destroyedDate" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
 *         <element name="ipInformation" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="userAgentInformation" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="sessionId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="userId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="locale" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="operatingSystem" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="screenSize" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="timeZone" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="sessionType" type="{http://system.application.internal.model.cia.hack23.com/impl}ApplicationSessionType" minOccurs="0"/>
 *         <element name="events" type="{http://system.application.internal.model.cia.hack23.com/impl}ApplicationActionEvent" maxOccurs="unbounded" minOccurs="0"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ApplicationSession", propOrder = {
    "modelObjectId",
    "modelObjectVersion",
    "createdDate",
    "destroyedDate",
    "ipInformation",
    "userAgentInformation",
    "sessionId",
    "userId",
    "locale",
    "operatingSystem",
    "screenSize",
    "timeZone",
    "sessionType",
    "events"
})
@Entity(name = "ApplicationSession")
@Table(name = "APPLICATION_SESSION")
@Inheritance(strategy = InheritanceType.JOINED)
public class ApplicationSession
    implements ModelObject
{

    /**
	 *
	 */
	private static final long serialVersionUID = 1L;
	protected Integer modelObjectId;
    protected int modelObjectVersion;
    @XmlElement(type = String.class)
    @XmlJavaTypeAdapter(XmlDateTimeTypeAdapter.class)
    @XmlSchemaType(name = "dateTime")
    protected Date createdDate;
    @XmlElement(type = String.class)
    @XmlJavaTypeAdapter(XmlDateTimeTypeAdapter.class)
    @XmlSchemaType(name = "dateTime")
    protected Date destroyedDate;
    protected String ipInformation;
    protected String userAgentInformation;
    protected String sessionId;
    protected String userId;
    protected String locale;
    protected String operatingSystem;
    protected String screenSize;
    protected String timeZone;
    @XmlSchemaType(name = "string")
    protected ApplicationSessionType sessionType;
    @XmlElement(nillable = true)
    protected List<ApplicationActionEvent> events;
    @XmlAttribute(name = "Hjid")
    protected Long hjid;

    /**
     * Gets the value of the modelObjectId property.
     *
     * @return
     *     possible object is
     *     {@link Integer }
     *
     */
    @Basic
    @Column(name = "MODEL_OBJECT_ID", precision = 10, scale = 0)
    public Integer getModelObjectId() {
        return modelObjectId;
    }

    /**
     * Sets the value of the modelObjectId property.
     *
     * @param value
     *     allowed object is
     *     {@link Integer }
     *
     */
    public void setModelObjectId(final Integer value) {
        this.modelObjectId = value;
    }

    /**
     * Gets the value of the modelObjectVersion property.
     *
     */
    @Version
    @Column(name = "MODEL_OBJECT_VERSION")
    public int getModelObjectVersion() {
        return modelObjectVersion;
    }

    /**
     * Sets the value of the modelObjectVersion property.
     *
     */
    public void setModelObjectVersion(final int value) {
        this.modelObjectVersion = value;
    }

    /**
     * Gets the value of the createdDate property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "CREATED_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    public Date getCreatedDate() {
        return createdDate;
    }

    /**
     * Sets the value of the createdDate property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setCreatedDate(final Date value) {
        this.createdDate = value;
    }

    /**
     * Gets the value of the destroyedDate property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "DESTROYED_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    public Date getDestroyedDate() {
        return destroyedDate;
    }

    /**
     * Sets the value of the destroyedDate property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setDestroyedDate(final Date value) {
        this.destroyedDate = value;
    }

    /**
     * Gets the value of the ipInformation property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "IP_INFORMATION")
    public String getIpInformation() {
        return ipInformation;
    }

    /**
     * Sets the value of the ipInformation property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setIpInformation(final String value) {
        this.ipInformation = value;
    }

    /**
     * Gets the value of the userAgentInformation property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "USER_AGENT_INFORMATION")
    public String getUserAgentInformation() {
        return userAgentInformation;
    }

    /**
     * Sets the value of the userAgentInformation property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setUserAgentInformation(final String value) {
        this.userAgentInformation = value;
    }

    /**
     * Gets the value of the sessionId property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "SESSION_ID")
    public String getSessionId() {
        return sessionId;
    }

    /**
     * Sets the value of the sessionId property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setSessionId(final String value) {
        this.sessionId = value;
    }

    /**
     * Gets the value of the userId property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "USER_ID")
    public String getUserId() {
        return userId;
    }

    /**
     * Sets the value of the userId property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setUserId(final String value) {
        this.userId = value;
    }

    /**
     * Gets the value of the locale property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "LOCALE")
    public String getLocale() {
        return locale;
    }

    /**
     * Sets the value of the locale property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setLocale(final String value) {
        this.locale = value;
    }

    /**
     * Gets the value of the operatingSystem property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "OPERATING_SYSTEM")
    public String getOperatingSystem() {
        return operatingSystem;
    }

    /**
     * Sets the value of the operatingSystem property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setOperatingSystem(final String value) {
        this.operatingSystem = value;
    }

    /**
     * Gets the value of the screenSize property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "SCREEN_SIZE")
    public String getScreenSize() {
        return screenSize;
    }

    /**
     * Sets the value of the screenSize property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setScreenSize(final String value) {
        this.screenSize = value;
    }

    /**
     * Gets the value of the timeZone property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    @Basic
    @Column(name = "TIME_ZONE")
    public String getTimeZone() {
        return timeZone;
    }

    /**
     * Sets the value of the timeZone property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setTimeZone(final String value) {
        this.timeZone = value;
    }

    /**
     * Gets the value of the sessionType property.
     *
     * @return
     *     possible object is
     *     {@link ApplicationSessionType }
     *
     */
    @Basic
    @Column(name = "SESSION_TYPE")
    @Enumerated(EnumType.STRING)
    public ApplicationSessionType getSessionType() {
        return sessionType;
    }

    /**
     * Sets the value of the sessionType property.
     *
     * @param value
     *     allowed object is
     *     {@link ApplicationSessionType }
     *
     */
    public void setSessionType(final ApplicationSessionType value) {
        this.sessionType = value;
    }

    /**
     * Gets the value of the events property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the events property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getEvents().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link ApplicationActionEvent }
     *
     *
     */
    @OneToMany(targetEntity = ApplicationActionEvent.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "EVENTS_APPLICATION_SESSION_H_0")
    public List<ApplicationActionEvent> getEvents() {
        if (events == null) {
            events = new ArrayList<>();
        }
        return this.events;
    }

    /**
     *
     *
     */
    public void setEvents(final List<ApplicationActionEvent> events) {
        this.events = events;
    }

    public ApplicationSession withModelObjectId(final Integer value) {
        setModelObjectId(value);
        return this;
    }

    public ApplicationSession withModelObjectVersion(final int value) {
        setModelObjectVersion(value);
        return this;
    }

    public ApplicationSession withCreatedDate(final Date value) {
        setCreatedDate(value);
        return this;
    }

    public ApplicationSession withDestroyedDate(final Date value) {
        setDestroyedDate(value);
        return this;
    }

    public ApplicationSession withIpInformation(final String value) {
        setIpInformation(value);
        return this;
    }

    public ApplicationSession withUserAgentInformation(final String value) {
        setUserAgentInformation(value);
        return this;
    }

    public ApplicationSession withSessionId(final String value) {
        setSessionId(value);
        return this;
    }

    public ApplicationSession withUserId(final String value) {
        setUserId(value);
        return this;
    }

    public ApplicationSession withLocale(final String value) {
        setLocale(value);
        return this;
    }

    public ApplicationSession withOperatingSystem(final String value) {
        setOperatingSystem(value);
        return this;
    }

    public ApplicationSession withScreenSize(final String value) {
        setScreenSize(value);
        return this;
    }

    public ApplicationSession withTimeZone(final String value) {
        setTimeZone(value);
        return this;
    }

    public ApplicationSession withSessionType(final ApplicationSessionType value) {
        setSessionType(value);
        return this;
    }

    public ApplicationSession withEvents(final List<ApplicationActionEvent> events) {
        setEvents(events);
        return this;
    }

	@Override
	public final String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

    /**
     * Gets the value of the hjid property.
     *
     * @return
     *     possible object is
     *     {@link Long }
     *
     */
    @Id
    @Column(name = "HJID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getHjid() {
        return hjid;
    }

    /**
     * Sets the value of the hjid property.
     *
     * @param value
     *     allowed object is
     *     {@link Long }
     *
     */
    public void setHjid(final Long value) {
        this.hjid = value;
    }

	@Override
	public final boolean equals(final Object obj) {
		return EqualsBuilder.reflectionEquals(this, obj);
	}

	@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.web.impl.ui.application.views.common.pagemode;

import org.springframework.beans.factory.annotation.Autowired;

import com.hack23.cia.service.api.ApplicationManager;
import com.hack23.cia.web.impl.ui.application.action.PageActionEventHelper;
import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.AdminChartDataManager;
import com.hack23.cia.web.impl.ui.application.views.common.formfactory.api.FormFactory;
import com.hack23.cia.web.impl.ui.application.views.common.gridfactory.api.GridFactory;
import com.hack23.cia.web.impl.ui.application.views.common.menufactory.api.ApplicationMenuItemFactory;
import com.hack23.cia.web.impl.ui.application.views.common.pagelinks.api.PageLinkFactory;
import com.hack23.cia.web.impl.ui.application.views.common.sizing.ContentRatio;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TabSheet.Tab;
import com.vaadin.ui.VerticalLayout;

/**
 * The Class AbstractPageModContentFactoryImpl.
 */
public abstract class AbstractPageModContentFactoryImpl implements PageModeContentFactory {

	/** The Constant GENERAL_PAGE_MODE_PAGE_VISIT. */
	public static final String GENERAL_PAGE_MODE_PAGE_VISIT = "General Page Mode Page Visit";

	/** The Constant CURRENT_PAGE_VISIT_HISTORY. */
	public static final String CURRENT_PAGE_VISIT_HISTORY = "Current Page Visit History";

	/** The Constant DEFAULT_RESULTS_PER_PAGE. */
	public static final int DEFAULT_RESULTS_PER_PAGE = 250;

	/** The application manager. */
	@Autowired
	private ApplicationManager applicationManager;

	/** The menu item factory. */
	@Autowired
	private ApplicationMenuItemFactory menuItemFactory;

	/** The grid factory. */
	@Autowired
	private GridFactory gridFactory;

	/** The form factory. */
	@Autowired
	private FormFactory formFactory;

	/** The page link factory. */
	@Autowired
	private PageLinkFactory pageLinkFactory;

	/** The page action event helper. */
	@Autowired
	private PageActionEventHelper pageActionEventHelper;

	/** The admin chart data manager. */
	@Autowired
	private AdminChartDataManager adminChartDataManager;

	/**
	 * Instantiates a new abstract page mod content factory impl.
	 */
	protected AbstractPageModContentFactoryImpl() {
		super();
	}

	/**
	 * Gets the page id.
	 *
	 * @param parameters
	 *            the parameters
	 * @return the page id
	 */
	protected final String getPageId(final String parameters) {
		if (parameters != null) {
			String cleanedString = parameters;
			if (parameters.contains("[")) {
				cleanedString = cleanedString.replace(cleanedString.substring(cleanedString.indexOf('[') , cleanedString.lastIndexOf(']')+1), "");
			}

			return cleanedString.substring(cleanedString.lastIndexOf('/') + "/".length(), cleanedString.length());
		} else {
			return "";
		}
	}

	/**
	 * Gets the page nr.
	 *
	 * @param parameters the parameters
	 * @return the page nr
	 */
	protected final int getPageNr(final String parameters) {
		final String cleanedString = parameters;
		String pageNrValue;
		if (cleanedString != null && cleanedString.contains("[") && cleanedString.contains("]")) {
			pageNrValue = cleanedString.substring(cleanedString.indexOf('[') + 1, cleanedString.lastIndexOf(']'));
		} else {
			pageNrValue = "";
		}

		int pageNr = 1;

		if (pageNrValue.length() > 0 && !pageNrValue.contains("/")) {
			pageNr = Integer.parseInt(pageNrValue);
		}
		return pageNr;
	}

	/**
	 * Gets the application manager.
	 *
	 * @return the application manager
	 */
	protected final ApplicationManager getApplicationManager() {
		return applicationManager;
	}

	/**
	 * Gets the menu item factory.
	 *
	 * @return the menu item factory
	 */
	protected final ApplicationMenuItemFactory getMenuItemFactory() {
		return menuItemFactory;
	}

	/**
	 * Gets the grid factory.
	 *
	 * @return the grid factory
	 */
	protected final GridFactory getGridFactory() {
		return gridFactory;
	}

	/**
	 * Gets the form factory.
	 *
	 * @return the form factory
	 */
	protected final FormFactory getFormFactory() {
		return formFactory;
	}

	/**
	 * Gets the page link factory.
	 *
	 * @return the page link factory
	 */
	protected final PageLinkFactory getPageLinkFactory() {
		return pageLinkFactory;
	}

	protected final AdminChartDataManager getAdminChartDataManager() {
		return adminChartDataManager;
	}

	/**
	 * Gets the page action event helper.
	 *
	 * @return the page action event helper
	 */
	protected final PageActionEventHelper getPageActionEventHelper() {
		return pageActionEventHelper;
	}

	/**
	 * Creates the panel content.
	 *
	 * @return the vertical layout
	 */
	protected final VerticalLayout createPanelContent() {
		final VerticalLayout panelContent = new VerticalLayout();
		panelContent.setMargin(true);
		panelContent.setWidth(100, Unit.PERCENTAGE);
		panelContent.setHeight(100, Unit.PERCENTAGE);
		panelContent.setStyleName("Header");
		return panelContent;
	}

	/**
	 * Creates the page visit history.
	 *
	 * @param pageName
	 *            the page name
	 * @param pageId
	 *            the page id
	 * @param panelContent
	 *            the panel content
	 */
	protected final void createPageVisitHistory(final String pageName, final String pageId,
			final VerticalLayout panelContent) {

		final TabSheet tabsheet = new TabSheet();
		tabsheet.setWidth(100, Unit.PERCENTAGE);
		tabsheet.setHeight(100, Unit.PERCENTAGE);

		panelContent.addComponent(tabsheet);
		panelContent.setExpandRatio(tabsheet, ContentRatio.LARGE);

		final HorizontalLayout tabContentPageItemRankHistory = new HorizontalLayout();
		tabContentPageItemRankHistory.setWidth(100, Unit.PERCENTAGE);
		tabContentPageItemRankHistory.setHeight(100, Unit.PERCENTAGE);
		final Tab tabPageItemRankHistory = tabsheet.addTab(tabContentPageItemRankHistory);

		tabPageItemRankHistory.setCaption(CURRENT_PAGE_VISIT_HISTORY);
		adminChartDataManager.createApplicationActionEventPageElementDailySummaryChart(tabContentPageItemRankHistory,
				pageName, pageId);

		final HorizontalLayout tabContentPageModeSummary = new HorizontalLayout();
		tabContentPageModeSummary.setWidth(100, Unit.PERCENTAGE);
		tabContentPageModeSummary.setHeight(100, Unit.PERCENTAGE);
		final Tab tabPageModeSummary = tabsheet.addTab(tabContentPageModeSummary);
		tabPageModeSummary.setCaption(GENERAL_PAGE_MODE_PAGE_VISIT);

		adminChartDataManager.createApplicationActionEventPageModeDailySummaryChart(tabContentPageModeSummary,
				pageName);

	}

}


/*
 * 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.List;
import java.util.Locale;
import java.util.function.Function;

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.model.internal.application.data.committee.impl.ViewRiksdagenVoteDataBallotPoliticianSummaryDaily;
import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.GenericChartDataManager;
import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.PoliticianChartDataManager;
import com.vaadin.ui.AbstractOrderedLayout;

/**
 * The Class ChartDataManagerImpl.
 */
@Service
public final class PoliticianDataManagerImpl extends AbstractChartDataManagerImpl implements PoliticianChartDataManager {

	/** The Constant ABSENT. */
	private static final String ABSENT = "Absent";

	/** The Constant PARTY_REBEL. */
	private static final String PARTY_REBEL = "Party Rebel";

	/** The Constant WON. */
	private static final String WON = "Won";

	/** The Constant NUMBER_BALLOTS. */
	private static final String NUMBER_BALLOTS = "Number ballots";

	/** The Constant DD_MMM_YYYY. */
	private static final String DD_MMM_YYYY = "dd-MMM-yyyy";

	/** The data chart manager. */
	@Autowired
	private GenericChartDataManager<ViewRiksdagenVoteDataBallotPoliticianSummaryDaily> dataChartManager;

	/**
	 * Instantiates a new politician data manager impl.
	 */
	public PoliticianDataManagerImpl() {
		super();
	}

	@Override
	public void createPersonLineChart(final AbstractOrderedLayout content,final String personId) {

		final List<ViewRiksdagenVoteDataBallotPoliticianSummaryDaily> list = dataChartManager.findByValue(personId);

		final Series series = new Series().addSeries(new XYseries().setLabel(WON))
				.addSeries(new XYseries().setLabel(PARTY_REBEL)).addSeries(new XYseries().setLabel(ABSENT))
				.addSeries(new XYseries().setLabel(NUMBER_BALLOTS));

		final DataSeries dataSeries = new DataSeries();

		final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DD_MMM_YYYY, Locale.ENGLISH);

		if (list != null) {
			addPoliticianIndicatorData(list, dataSeries, simpleDateFormat);
		}

		addChart(content,"Ballot indicators", new DCharts().setDataSeries(dataSeries).setOptions(getChartOptions().createOptionsPersonLineChart(series)).show(), true);
	}

	/**
	 * Adds the politician indicator data.
	 *
	 * @param list
	 *            the list
	 * @param dataSeries
	 *            the data series
	 * @param simpleDateFormat
	 *            the simple date format
	 */
	private static void addPoliticianIndicatorData(final List<ViewRiksdagenVoteDataBallotPoliticianSummaryDaily> list,
			final DataSeries dataSeries, final SimpleDateFormat simpleDateFormat) {
		addPoliticanData(list, dataSeries, simpleDateFormat, ViewRiksdagenVoteDataBallotPoliticianSummaryDaily::getWonPercentage);
		addPoliticanData(list, dataSeries, simpleDateFormat, ViewRiksdagenVoteDataBallotPoliticianSummaryDaily::getRebelPercentage);
		addPoliticanData(list, dataSeries, simpleDateFormat, ViewRiksdagenVoteDataBallotPoliticianSummaryDaily::getPoliticianPercentageAbsent);
		addPoliticanData(list, dataSeries, simpleDateFormat, ViewRiksdagenVoteDataBallotPoliticianSummaryDaily::getNumberBallots);
	}

	/**
	 * Adds the politican data.
	 *
	 * @param list             the list
	 * @param dataSeries       the data series
	 * @param simpleDateFormat the simple date format
	 * @param t                the t
	 */
	private static void addPoliticanData(final List<ViewRiksdagenVoteDataBallotPoliticianSummaryDaily> list,
			final DataSeries dataSeries, final SimpleDateFormat simpleDateFormat, final Function<ViewRiksdagenVoteDataBallotPoliticianSummaryDaily, Object> t) {
		dataSeries.newSeries();
		for (final ViewRiksdagenVoteDataBallotPoliticianSummaryDaily viewRiksdagenVoteDataBallotPoliticianSummaryDaily : list) {
			if (viewRiksdagenVoteDataBallotPoliticianSummaryDaily != null) {
				dataSeries.add(
						simpleDateFormat.format(
								viewRiksdagenVoteDataBallotPoliticianSummaryDaily.getEmbeddedId().getVoteDate()),
						t.apply(viewRiksdagenVoteDataBallotPoliticianSummaryDaily));
			}
		}
	}

}


/*
 * 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.api.action.user;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.hack23.cia.service.api.action.common.AbstractResponse;

/**
 * The Class SetGoogleAuthenticatorCredentialResponse.
 */
public final class SetGoogleAuthenticatorCredentialResponse extends AbstractResponse {

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

	/** The google auth key. */
	private String googleAuthKey;

	/** The google auth verification code. */
	private Integer googleAuthVerificationCode;

	/** The google auth scratch codes. */
	private List<Integer> googleAuthScratchCodes = new ArrayList<>();

	/** The otp auth totp url. */
	private String otpAuthTotpURL;

	/**
	 * Instantiates a new sets the google authenticator credential response.
	 *
	 * @param result
	 *            the result
	 */
	public SetGoogleAuthenticatorCredentialResponse(final ServiceResult result) {
		super(result);
	}

	/**
	 * Gets the google auth key.
	 *
	 * @return the google auth key
	 */
	public String getGoogleAuthKey() {
		return googleAuthKey;
	}

	/**
	 * Sets the google auth key.
	 *
	 * @param googleAuthKey
	 *            the new google auth key
	 */
	public void setGoogleAuthKey(final String googleAuthKey) {
		this.googleAuthKey = googleAuthKey;
	}

	/**
	 * Gets the google auth verification code.
	 *
	 * @return the google auth verification code
	 */
	public Integer getGoogleAuthVerificationCode() {
		return googleAuthVerificationCode;
	}

	/**
	 * Sets the google auth verification code.
	 *
	 * @param googleAuthVerificationCode
	 *            the new google auth verification code
	 */
	public void setGoogleAuthVerificationCode(final Integer googleAuthVerificationCode) {
		this.googleAuthVerificationCode = googleAuthVerificationCode;
	}

	/**
	 * Gets the google auth scratch codes.
	 *
	 * @return the google auth scratch codes
	 */
	public List<Integer> getGoogleAuthScratchCodes() {
		return googleAuthScratchCodes.stream().collect(Collectors.toList());
	}

	/**
	 * Sets the google auth scratch codes.
	 *
	 * @param googleAuthScratchCodes
	 *            the new google auth scratch codes
	 */
	public void setGoogleAuthScratchCodes(final List<Integer> googleAuthScratchCodes) {
		if (googleAuthScratchCodes != null) {
			this.googleAuthScratchCodes = googleAuthScratchCodes.stream().collect(Collectors.toList());
		}
	}

	/**
	 * Gets the otp auth totp url.
	 *
	 * @return the otp auth totp url
	 */
	public String getOtpAuthTotpURL() {
		return otpAuthTotpURL;
	}

	/**
	 * Sets the otp auth totp url.
	 *
	 * @param otpAuthTotpURL
	 *            the new otp auth totp url
	 */
	public void setOtpAuthTotpURL(final String otpAuthTotpURL) {
		this.otpAuthTotpURL = otpAuthTotpURL;
	}

}


/*
 * 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 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.ManyToOne;
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 PersonContainerData.
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PersonContainerData", propOrder = {
    "person"
})
@Entity(name = "PersonContainerData")
@Table(name = "PERSON_CONTAINER_DATA")
@Inheritance(strategy = InheritanceType.JOINED)
public class PersonContainerData
    implements ModelObject
{

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

	/** The person. */
    @XmlElement(required = true)
    protected PersonData person;

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

    /**
	 * Gets the person.
	 *
	 * @return the person
	 */
    @ManyToOne(targetEntity = PersonData.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "PERSON_PERSON_CONTAINER_DATA_0")
    public PersonData getPerson() {
        return person;
    }

    /**
	 * Sets the person.
	 *
	 * @param value the new person
	 */
    public void setPerson(final PersonData value) {
        this.person = value;
    }

    /**
	 * With person.
	 *
	 * @param value the value
	 * @return the person container data
	 */
    public PersonContainerData withPerson(final PersonData value) {
        setPerson(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;
    }

    /* (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.data.impl.util;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Set;

import org.hibernate.Hibernate;

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

	/**
	 * Instantiates a new load helper.
	 */
	private LoadHelper() {
		super();
	}

	/**
	 * Recursive initliaze.
	 *
	 * @param obj
	 *            the obj
	 * @param dejaVu
	 *            the deja vu
	 * @throws IllegalAccessException
	 *             the illegal access exception
	 * @throws InvocationTargetException
	 *             the invocation target exception
	 * @throws NoSuchMethodException
	 *             the no such method exception
	 */
	private static void recursiveInitialize(final Object obj, final Set<Object> dejaVu) {
		dejaVu.add(obj);
		if (!Hibernate.isInitialized(obj)) {
			Hibernate.initialize(obj);
		}
	}

	/**
	 * Recursive initliaze.
	 *
	 * @param <T>
	 *            the generic type
	 * @param obj
	 *            the obj
	 * @return the t
	 */
	public static <T> T recursiveInitialize(final T obj) {
		if (obj != null) {
			final Set<Object> dejaVu = Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>());
			recursiveInitialize(obj, dejaVu);
		}
		return obj;
	}

}


/*
 * 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.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.joda.time.DateTime;
import org.tltv.gantt.Gantt;
import org.tltv.gantt.client.shared.AbstractStep.CaptionMode;
import org.tltv.gantt.client.shared.Resolution;
import org.tltv.gantt.client.shared.Step;
import org.tltv.gantt.client.shared.SubStep;

import com.hack23.cia.web.impl.ui.application.views.common.sizing.ContentRatio;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.ui.AbstractOrderedLayout;

/**
 * The Class AbstractGhantChartManagerImpl.
 *
 * @param <T>
 *            the generic type
 */
public abstract class AbstractGhantChartManagerImpl<T extends Object> {

	/** The Constant PARTY_END_TAG. */
	private static final char PARTY_END_TAG = ')';

	/** The Constant PARTY_START_TAG. */
	private static final String PARTY_START_TAG = " (";

	/** The Constant CONTENT_SEPARATOR. */
	private static final char CONTENT_SEPARATOR = ' ';

	/** The Constant FILTER_DATA_BEFORE_YEAR. */
	private static final int FILTER_DATA_BEFORE_YEAR = 2000;

	/**
	 * Instantiates a new abstract ghant chart manager impl.
	 */
	public AbstractGhantChartManagerImpl() {
		super();
	}

	/**
	 * Creates the role ghant.
	 *
	 * @param roleSummaryLayoutTabsheet the role summary layout tabsheet
	 * @param assignmentList            the assignment list
	 */
	public final void createRoleGhant(final AbstractOrderedLayout roleSummaryLayoutTabsheet, final Collection<T> assignmentList) {

		final Comparator<T> compare = getComparator();

		final List<T> list = assignmentList.stream().filter(
				(final T x) -> new DateTime(getStepMapping().getFromDate(x).getTime()).getYear() > FILTER_DATA_BEFORE_YEAR)
				.collect(Collectors.toList());

		Collections.sort(list, compare);

		final Gantt createGantt = createGenericGantt(list, getRoleMapping(), getStepMapping());
		roleSummaryLayoutTabsheet.addComponent(createGantt);
		roleSummaryLayoutTabsheet.setExpandRatio(createGantt, ContentRatio.GRID);

	}

	/**
	 * Gets the comparator.
	 *
	 * @return the comparator
	 */
	protected abstract Comparator<T> getComparator();

	/**
	 * Gets the role mapping.
	 *
	 * @return the role mapping
	 */
	protected abstract Function<T, String> getRoleMapping();

	/**
	 * Gets the step mapping.
	 *
	 * @return the step mapping
	 */
	protected abstract StepMapping<T> getStepMapping();

	/**
	 * Creates the generic gantt.
	 *
	 * @param assignmentList
	 *            the assignment list
	 * @param roleMapping
	 *            the role mapping
	 * @param stepMapping
	 *            the step mapping
	 * @return the gantt
	 */
	private Gantt createGenericGantt(final List<T> assignmentList, final Function<T, String> roleMapping,
			final StepMapping<T> stepMapping) {

		final Map<String, List<T>> assignmentListMap = assignmentList.stream()
				.collect(Collectors.groupingBy(roleMapping, TreeMap::new, Collectors.toList()));

		final Gantt gantt = createGantt();

		if (!assignmentList.isEmpty()) {

			gantt.setStartDate(stepMapping.getFromDate(assignmentList.get(0)));
			gantt.setEndDate(
					stripDatesAfterCurrentDate(stepMapping.getToDate(assignmentList.get(assignmentList.size() - 1))));

			for (final Entry<String, List<T>> entry : entriesSortedByValues(assignmentListMap, stepMapping)) {

				final String stepName = entry.getKey();

				final Step step = new Step(stepName,CaptionMode.HTML);
				step.setDescription(stepName);

				final List<T> assignments = entry.getValue();

				Collections.sort(assignments, getComparator());

				addViewGenericRoleMemberToStep(stepName, step, assignments, stepMapping);

				gantt.addStep(step);
			}
		}

		return gantt;
	}

	/**
	 * Entries sorted by values.
	 *
	 * @param map
	 *            the map
	 * @param stepMapping
	 *            the step mapping
	 * @return the sorted set
	 */
	private SortedSet<Map.Entry<String, List<T>>> entriesSortedByValues(final Map<String, List<T>> map,
			final StepMapping<T> stepMapping) {
		final Comparator<? super Entry<String, List<T>>> compare = (o1, o2) -> {

			final Comparator<T> compare1 = (o11, o21) -> {
				final int compareDate = stepMapping.getFromDate(o11).compareTo(stepMapping.getFromDate(o21));
				if (compareDate == 0) {
					final int compareType = stepMapping.getRoleCode(o11).compareTo(stepMapping.getRoleCode(o21));
					if (compareType == 0) {
						return stepMapping.getOrg(o11).compareTo(stepMapping.getOrg(o21));
					} else {
						return compareType;
					}
				}

				return compareDate;
			};

			Collections.sort(o1.getValue(), compare1);
			Collections.sort(o2.getValue(), compare1);

			return compare1.compare(o1.getValue().get(0), o2.getValue().get(0));
		};

		final SortedSet<Map.Entry<String, List<T>>> sortedEntries = new TreeSet<>(compare);
		sortedEntries.addAll(map.entrySet());
		return sortedEntries;
	}

	/**
	 * Adds the view generic role member to step.
	 *
	 * @param stepName
	 *            the step name
	 * @param step
	 *            the step
	 * @param assignments
	 *            the assignments
	 * @param stepMapping
	 *            the step mapping
	 */
	private void addViewGenericRoleMemberToStep(final String stepName, final Step step, final List<T> assignments,
			final StepMapping<T> stepMapping) {

		for (final T assignmentData : assignments) {

			String subStepName = "";

			if (stepMapping.getRoleCode(assignmentData) != null) {
				subStepName = new StringBuilder().append(stepMapping.getFirstName(assignmentData))
						.append(CONTENT_SEPARATOR).append(stepMapping.getLastName(assignmentData))
						.append(PARTY_START_TAG).append(stepMapping.getParty(assignmentData)).append(PARTY_END_TAG)
						.toString();
			}

			final SubStep sameRoleSubStep = new SubStep(stepName + '.' + subStepName,CaptionMode.HTML);
			sameRoleSubStep.setDescription(stepName + '.' + subStepName);
			sameRoleSubStep.setBackgroundColor(stepMapping.getBackgroundColor(assignmentData));

			sameRoleSubStep.setStartDate(stepMapping.getFromDate(assignmentData).getTime());
			sameRoleSubStep.setEndDate(stripDatesAfterCurrentDate(stepMapping.getToDate(assignmentData)).getTime());

			step.addSubStep(sameRoleSubStep);
		}
	}

	/**
	 * Strip dates after current date.
	 *
	 * @param toDate
	 *            the to date
	 * @return the date
	 */
	private static final Date stripDatesAfterCurrentDate(final Date toDate) {
		final DateTime currentTime = new DateTime();

		if (currentTime.isBefore(toDate.getTime())) {
			return currentTime.plusDays(1).toDate();
		} else {
			return toDate;
		}
	}

	/**
	 * Creates the gantt.
	 *
	 * @return the gantt
	 */
	private static final Gantt createGantt() {
		final Gantt gantt = new Gantt();
		gantt.setSizeFull();
		gantt.setWidth(100, Unit.PERCENTAGE);
		gantt.setHeight(100, Unit.PERCENTAGE);
		gantt.setResizableSteps(false);
		gantt.setMovableSteps(false);
		gantt.setResolution(Resolution.Week);
		return gantt;
	}

	/**
	 * The Interface StepMapping.
	 *
	 * @param <T>
	 *            the generic type
	 */
	public interface StepMapping<T> {

		/**
		 * Gets the from date.
		 *
		 * @param t
		 *            the t
		 * @return the from date
		 */
		Date getFromDate(T t);

		/**
		 * Gets the to date.
		 *
		 * @param t
		 *            the t
		 * @return the to date
		 */
		Date getToDate(T t);

		/**
		 * Gets the role code.
		 *
		 * @param t
		 *            the t
		 * @return the role code
		 */
		String getRoleCode(T t);

		/**
		 * Gets the org.
		 *
		 * @param t
		 *            the t
		 * @return the org
		 */
		String getOrg(T t);

		/**
		 * Gets the party.
		 *
		 * @param t
		 *            the t
		 * @return the party
		 */
		String getParty(T t);

		/**
		 * Gets the background color.
		 *
		 * @param t
		 *            the t
		 * @return the background color
		 */
		String getBackgroundColor(T t);

		/**
		 * Gets the first name.
		 *
		 * @param assignmentData
		 *            the assignment data
		 * @return the first name
		 */
		Object getFirstName(T assignmentData);

		/**
		 * Gets the last name.
		 *
		 * @param assignmentData
		 *            the assignment data
		 * @return the last name
		 */
		Object getLastName(T assignmentData);

	}

}