package org.sigmah.server.servlet.exporter.models; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.HashSet; import java.util.List; import javax.persistence.EntityManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sigmah.server.domain.OrgUnitModel; import org.sigmah.server.domain.User; import org.sigmah.server.domain.category.CategoryElement; import org.sigmah.server.domain.category.CategoryType; import org.sigmah.server.domain.element.FlexibleElement; import org.sigmah.server.domain.element.QuestionChoiceElement; import org.sigmah.server.domain.element.QuestionElement; import org.sigmah.server.domain.layout.LayoutConstraint; import org.sigmah.server.domain.layout.LayoutGroup; import org.sigmah.shared.dto.referential.ProjectModelStatus; /** * Exports and imports organizational units models. * * @author Raphaël Calabro (rcalabro@ideia.fr) V1.3 * @author Mehdi Benabdeslam (mehdi.benabdeslam@netapsys.fr)v2.0 */ public class OrgUnitModelHandler implements ModelHandler { private final static Log LOG = LogFactory.getLog(OrgUnitModelHandler.class); /** * The map of imported objects (original object, transformed object) */ public static HashMap<Object, Object> modelesReset = new HashMap<Object, Object>(); /** * The list of imported objects which are transformed or being transformed. */ public static HashSet<Object> modelesImport = new HashSet<Object>(); @Override public void importModel(InputStream inputStream, EntityManager em, User user) throws Exception { ObjectInputStream objectInputStream; em.getTransaction().begin(); try { objectInputStream = new ObjectInputStream(inputStream); OrgUnitModel orgUnitModel = (OrgUnitModel) objectInputStream.readObject(); orgUnitModel.resetImport(); saveOrgUnitFlexibleElement(orgUnitModel, em); // Set the staus to DRAFT orgUnitModel.setStatus(ProjectModelStatus.DRAFT); orgUnitModel.setOrganization(user.getOrganization()); em.persist(orgUnitModel); em.getTransaction().commit(); } catch (Exception e) { throw e; } } @Override public String exportModel(OutputStream outputStream, String identifier, EntityManager em) throws Exception { String name = ""; if (identifier != null) { final Integer orgUnitModelId = Integer.parseInt(identifier); final OrgUnitModel hibernateModel = em.find(OrgUnitModel.class, orgUnitModelId); if (hibernateModel == null) throw new Exception("No orgUnit model is associated with the identifier '" + identifier + "'."); name = hibernateModel.getName(); // Stripping hibernate proxies from the model. final OrgUnitModel realModel = Realizer.realize(hibernateModel); // Serialization try { final ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream); objectOutputStream.writeObject(realModel); } catch (Exception ex) { throw new Exception("An error occured while serializing the orgUnit model " + orgUnitModelId, ex); } } else { throw new Exception("The identifier is missing."); } return name; } /** * Save the flexible elements of imported organizational unit model * * @param orgUnitModel * the imported organizational unit model * @param em * the entity manager */ private void saveOrgUnitFlexibleElement(OrgUnitModel orgUnitModel, EntityManager em) { // OrgUnitModel → Banner → Layout → Groups → Constraints if (orgUnitModel.getBanner() != null && orgUnitModel.getBanner().getLayout() != null) { List<LayoutGroup> bannerLayoutGroups = orgUnitModel.getBanner().getLayout().getGroups(); if (bannerLayoutGroups != null) { for (LayoutGroup layoutGroup : bannerLayoutGroups) { List<LayoutConstraint> layoutConstraints = layoutGroup.getConstraints(); if (layoutConstraints != null) { for (LayoutConstraint layoutConstraint : layoutConstraints) { if (layoutConstraint.getElement() != null) { if (layoutConstraint.getElement() instanceof QuestionElement) { List<QuestionChoiceElement> questionChoiceElements = ((QuestionElement) layoutConstraint.getElement()).getChoices(); CategoryType type = ((QuestionElement) layoutConstraint.getElement()).getCategoryType(); if (questionChoiceElements != null || type != null) { FlexibleElement parent = layoutConstraint.getElement(); ((QuestionElement) parent).setChoices(null); ((QuestionElement) parent).setCategoryType(null); em.persist(parent); // Save QuestionChoiceElement with their QuestionElement parent(saved above) if (questionChoiceElements != null) { for (QuestionChoiceElement questionChoiceElement : questionChoiceElements) { if (questionChoiceElement != null) { questionChoiceElement.setId(null); questionChoiceElement.setParentQuestion((QuestionElement) parent); CategoryElement categoryElement = questionChoiceElement.getCategoryElement(); if (categoryElement != null) { questionChoiceElement.setCategoryElement(null); em.persist(questionChoiceElement); saveOrgUnitModelCategoryElement(categoryElement, em); questionChoiceElement.setCategoryElement(categoryElement); em.merge(questionChoiceElement); } else { em.persist(questionChoiceElement); } } } // Set saved QuestionChoiceElement to QuestionElement parent and update it ((QuestionElement) parent).setChoices(questionChoiceElements); } // Save the Category type of QuestionElement parent(saved above) if (type != null) { if (em.find(CategoryType.class, type.getId()) == null) { List<CategoryElement> typeElements = type.getElements(); if (typeElements != null) { type.setElements(null); em.merge(type); for (CategoryElement element : typeElements) { if (em.find(CategoryElement.class, element.getId()) == null) { element.setParentType(type); saveOrgUnitModelCategoryElement(element, em); } } type.setElements(typeElements); em.merge(type); } } // Set the saved CategoryType to QuestionElement parent and update it ((QuestionElement) parent).setCategoryType(type); } // Update the QuestionElement parent em.merge(parent); } else { em.persist(layoutConstraint.getElement()); } } else { em.persist(layoutConstraint.getElement()); } } } } } } } // OrgUnitModel → Detail → Layout → Groups → Constraints if (orgUnitModel.getDetails() != null && orgUnitModel.getDetails().getLayout() != null) { List<LayoutGroup> detailLayoutGroups = orgUnitModel.getDetails().getLayout().getGroups(); if (detailLayoutGroups != null) { for (LayoutGroup layoutGroup : detailLayoutGroups) { List<LayoutConstraint> layoutConstraints = layoutGroup.getConstraints(); if (layoutConstraints != null) { for (LayoutConstraint layoutConstraint : layoutConstraints) { if (layoutConstraint.getElement() != null) { if (layoutConstraint.getElement() instanceof QuestionElement) { List<QuestionChoiceElement> questionChoiceElements = ((QuestionElement) layoutConstraint.getElement()).getChoices(); CategoryType type = ((QuestionElement) layoutConstraint.getElement()).getCategoryType(); if (questionChoiceElements != null || type != null) { FlexibleElement parent = layoutConstraint.getElement(); ((QuestionElement) parent).setChoices(null); ((QuestionElement) parent).setCategoryType(null); em.persist(parent); // Save QuestionChoiceElement with their QuestionElement parent(saved above) if (questionChoiceElements != null) { for (QuestionChoiceElement questionChoiceElement : questionChoiceElements) { if (questionChoiceElement != null) { questionChoiceElement.setId(null); questionChoiceElement.setParentQuestion((QuestionElement) parent); CategoryElement categoryElement = questionChoiceElement.getCategoryElement(); if (categoryElement != null) { questionChoiceElement.setCategoryElement(null); em.persist(questionChoiceElement); saveOrgUnitModelCategoryElement(categoryElement, em); questionChoiceElement.setCategoryElement(categoryElement); em.merge(questionChoiceElement); } else { em.persist(questionChoiceElement); } } } // Set saved QuestionChoiceElement to QuestionElement parent and update it ((QuestionElement) parent).setChoices(questionChoiceElements); } // Save the Category type of QuestionElement parent(saved above) if (type != null) { if (em.find(CategoryType.class, type.getId()) == null) { List<CategoryElement> typeElements = type.getElements(); if (typeElements != null) { type.setElements(null); em.merge(type); for (CategoryElement element : typeElements) { if (em.find(CategoryElement.class, element.getId()) == null) { element.setParentType(type); saveOrgUnitModelCategoryElement(element, em); } } type.setElements(typeElements); em.merge(type); } } // Set the saved CategoryType to QuestionElement parent and update it ((QuestionElement) parent).setCategoryType(type); } // Update the QuestionElement parent em.merge(parent); } else { em.persist(layoutConstraint.getElement()); } } else { em.persist(layoutConstraint.getElement()); } } } } } } } } /** * Save the category element of a question choice element. * * @param categoryElement * the category element to save. * @param em * the entity manager. */ private void saveOrgUnitModelCategoryElement(CategoryElement categoryElement, EntityManager em) { if (!modelesImport.contains(categoryElement)) { modelesImport.add(categoryElement); if (!modelesReset.containsKey(categoryElement)) { CategoryElement key = categoryElement; categoryElement.setId(null); CategoryType parentType = categoryElement.getParentType(); if (!modelesImport.contains(parentType)) { modelesImport.add(parentType); if (!modelesReset.containsKey(parentType)) { CategoryType parentKey = parentType; parentType.setId(null); List<CategoryElement> elements = parentType.getElements(); if (elements != null) { parentType.setElements(null); em.persist(parentType); for (CategoryElement element : elements) { categoryElement.setParentType(parentType); saveOrgUnitModelCategoryElement(element, em); } parentType.setElements(elements); em.merge(parentType); } else { em.persist(parentType); } modelesReset.put(parentKey, parentType); } else { parentType = (CategoryType) modelesReset.get(parentType); } } categoryElement.setParentType(parentType); em.persist(categoryElement); modelesReset.put(key, categoryElement); } else { categoryElement = (CategoryElement) modelesReset.get(categoryElement); } } } }