/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.persistence;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.servoy.j2db.FlattenedSolution;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.PersistHelper;
import com.servoy.j2db.util.Utils;
/**
* @author jcompagner
*/
public class FlattenedForm extends Form implements IFlattenedPersistWrapper<Form>
{
private static final long serialVersionUID = 1L;
public static final Comparator<IFormElement> FORM_INDEX_WITH_HIERARCHY_COMPARATOR = new Comparator<IFormElement>()
{
public int compare(IFormElement element1, IFormElement element2)
{
Form form1 = getFormIndexContext(element1);
Form form2 = getFormIndexContext(element2);
// first sort on the hierarchy, elements of super-forms are sorted before elements of sub-forms
if (!Utils.equalObjects(form1, form2))
{
boolean isChildForm = hasFormInHierarchy(form1, form2);
if (isChildForm == hasFormInHierarchy(form2, form1))
{
// how can this happen, transitivity is not respected
Debug.error("Cannot sort elements, transitivity is not respected for forms:" + form1 + " and " + form2);
}
return isChildForm ? 1 : -1;
}
return element1.getFormIndex() - element2.getFormIndex();
}
};
private final FlattenedSolution flattenedSolution;
private final Form form;
/**
* @param parent
* @param element_id
* @param uuid
*/
public FlattenedForm(FlattenedSolution flattenedSolution, Form form)
{
super(form.getParent(), form.getID(), form.getUUID());
this.flattenedSolution = flattenedSolution;
this.form = form;
fill();
}
public Form getWrappedPersist()
{
return form;
}
public List<Form> getAllForms()
{
return flattenedSolution.getFormHierarchy(form);
}
/**
* @return the form
*/
public Form getForm()
{
return form;
}
public static Form getWrappedForm(Form form)
{
return form instanceof FlattenedForm ? ((FlattenedForm)form).getForm() : form;
}
@Override
public void setExtendsID(int arg)
{
// override the Form.setExtendsID so that the persist fire is not happening
// and the extends form is not get right aways.
setTypedProperty(StaticContentSpecLoader.PROPERTY_EXTENDSID, arg);
}
@Override
public Form getExtendsForm()
{
// if the extends form is asked for now look it up if there is one
if (getExtendsID() > 0)
{
return flattenedSolution.getForm(getExtendsID());
}
return null;
}
private void fill()
{
List<Form> allForms = flattenedSolution.getFormHierarchy(form);
copyPropertiesMap(form.getPropertiesMap(), false);
// caches for the duplicate (over the form hierarchy) methods/variables, so that only
// the first method based on its name is added.
Set<String> methods = new HashSet<String>(64);
Set<String> variables = new HashSet<String>(64);
List<Integer> existingIDs = new ArrayList<Integer>();
for (Form f : allForms)
{
for (IPersist ip : f.getAllObjectsAsList())
{
Integer extendsID = (ip instanceof ISupportExtendsID) ? new Integer(((ISupportExtendsID)ip).getExtendsID()) : Integer.valueOf(-1);
if (!existingIDs.contains(new Integer(ip.getID())) && !existingIDs.contains(extendsID))
{
if (ip instanceof ISupportExtendsID && PersistHelper.isOverrideOrphanElement((ISupportExtendsID)ip))
{
// some deleted element
continue;
}
boolean addScriptMethod = (ip instanceof ScriptMethod && methods.add(((ScriptMethod)ip).getName()));
boolean addScriptVariable = (ip instanceof ScriptVariable && variables.add(((ScriptVariable)ip).getName()));
boolean addOtherElement = (!(ip instanceof Part) && !(ip instanceof ScriptMethod) && !(ip instanceof ScriptVariable));
if (addScriptVariable || addScriptMethod || addOtherElement)
{
if (ip instanceof TabPanel)
{
internalAddChild(new FlattenedTabPanel((TabPanel)ip));
}
else if (ip instanceof Portal)
{
internalAddChild(new FlattenedPortal((Portal)ip));
}
else if (ip instanceof LayoutContainer)
{
internalAddChild(new FlattenedLayoutContainer((LayoutContainer)ip));
}
else
{
internalAddChild(ip);
}
}
}
if (ip instanceof ISupportExtendsID && PersistHelper.isOverrideElement((ISupportExtendsID)ip) && !existingIDs.contains(extendsID))
{
existingIDs.add(extendsID);
}
}
}
Part prevPart = null;
Collections.reverse(allForms); // change from sub-first to super-first
for (Form f : allForms)
{
// Add parts
Iterator<Part> parts = f.getParts();
while (parts.hasNext())
{
// Sub-forms can only add parts to the bottom
Part part = parts.next();
if (PersistHelper.isOverrideElement(part))
{
Part parentPart = null;
Iterator<Part> it = getParts();
while (it.hasNext())
{
Part temp = it.next();
if (temp.getID() == part.getExtendsID() || temp.getExtendsID() == part.getExtendsID())
{
parentPart = temp;
break;
}
}
if (parentPart != null)
{
internalAddChild(part);
internalRemoveChild(parentPart);
}
}
else
{
if (prevPart == null || prevPart.getPartType() < part.getPartType() || (prevPart.getPartType() == part.getPartType() && part.canBeMoved()))
{
internalAddChild(part);
prevPart = part;
}
}
}
}
setSize(checkParts(getParts(), getSize())); // recalculate height
}
@Override
public Iterator<IFormElement> getFormElementsSortedByFormIndex()
{
return new FormTypeIterator(getAllObjectsAsList(), FORM_INDEX_WITH_HIERARCHY_COMPARATOR);
}
/**
* Called only in develop time.
*/
public void reload()
{
internalClearAllObjects();
fill();
}
private static boolean hasFormInHierarchy(Form form1, Form form2)
{
Form superForm = form1.getExtendsForm();
while (superForm != null)
{
if (superForm.getID() == form2.getID()) return true;
superForm = superForm.getExtendsForm();
}
return false;
}
private static Form getFormIndexContext(IFormElement element)
{
if (element instanceof IFlattenedPersistWrapper)
{
element = (IFormElement)((IFlattenedPersistWrapper)element).getWrappedPersist();
}
if (element.getFormIndex() == 0 || element.getExtendsID() <= 0)
{
return (Form)element.getParent();
}
IFormElement currentElement = element;
while (currentElement != null)
{
if (((AbstractBase)currentElement).hasProperty(StaticContentSpecLoader.PROPERTY_FORMINDEX.getPropertyName()))
{
return (Form)currentElement.getParent();
}
currentElement = (IFormElement)PersistHelper.getSuperPersist(currentElement);
}
return (Form)element.getParent();
}
}