/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo 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. * * OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.foundation.view; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.InvalidNameException; import org.openflexo.foundation.AttributeDataModification; import org.openflexo.foundation.FlexoException; import org.openflexo.foundation.FlexoModelObject; import org.openflexo.foundation.Inspectors; import org.openflexo.foundation.ontology.dm.OEDataModification; import org.openflexo.foundation.ontology.dm.ShemaDeleted; import org.openflexo.foundation.ontology.dm.ShemaFolderDeleted; import org.openflexo.foundation.ontology.dm.ShemaFolderInserted; import org.openflexo.foundation.ontology.dm.ShemaInserted; import org.openflexo.foundation.rm.DuplicateResourceException; import org.openflexo.foundation.rm.XMLStorageResourceData; import org.openflexo.foundation.utils.FlexoIndexManager; import org.openflexo.foundation.utils.Sortable; import org.openflexo.foundation.wkf.dm.ChildrenOrderChanged; import org.openflexo.foundation.xml.VEShemaLibraryBuilder; import org.openflexo.inspector.InspectableObject; import org.openflexo.localization.FlexoLocalization; import org.openflexo.toolbox.ToolBox; /** * @author bmangez <B>Class Description</B> */ public class ViewFolder extends ViewLibraryObject implements InspectableObject, Sortable { public static final FolderComparator COMPARATOR = new FolderComparator(); protected static final Logger logger = Logger.getLogger(ViewFolder.class.getPackage().getName()); // ========================================================================== // ============================= Instance variables // ========================= // ========================================================================== private String _name; // private transient FlexoComponentLibrary _componentLibrary; private Vector<ViewFolder> _subFolders; private Vector<ViewDefinition> _views; private ViewFolder _fatherFolder; private int index = -1; // ========================================================================== // ============================= Constructor // ================================ // ========================================================================== public ViewFolder(ViewLibrary viewLibrary) { super(viewLibrary); _subFolders = new Vector<ViewFolder>(); _views = new Vector<ViewDefinition>(); } @Override public void finalizeDeserialization(Object builder) { super.finalizeDeserialization(builder); if (getShemas().size() > 0 && !getShemas().firstElement().isIndexed()) { ViewDefinition[] cd = new ViewDefinition[getShemas().size()]; cd = getShemas().toArray(cd); Arrays.sort(cd, ViewDefinition.COMPARATOR); for (int i = 0; i < cd.length; i++) { cd[i].setIndexValue(i + 1); } } if (getSubFolders().size() > 0 && !getSubFolders().firstElement().isIndexed()) { ViewFolder[] folder = new ViewFolder[getSubFolders().size()]; folder = getSubFolders().toArray(folder); Arrays.sort(folder, ViewFolder.COMPARATOR); for (int i = 0; i < folder.length; i++) { folder[i].setIndexValue(i + 1); } } } public int getDepth() { if (getFatherFolder() != null) { return getFatherFolder().getDepth() + 1; } else { return 0; } } private static Vector<ViewFolder> getAllSubFoldersForFolder(ViewFolder folder) { Vector<ViewFolder> v = new Vector<ViewFolder>(); if (folder != null) { v.add(folder); Enumeration<ViewFolder> en = folder.getSubFolders().elements(); while (en.hasMoreElements()) { ViewFolder f = en.nextElement(); v.addAll(getAllSubFoldersForFolder(f)); } } return v; } public ViewFolder(String folderName, ViewLibrary componentLibrary) { this(componentLibrary); _name = folderName; } public ViewFolder(VEShemaLibraryBuilder builder) { this(builder.shemaLibrary); initializeDeserialization(builder); } /** * Creates and returns a newly created root process * * @return a newly created workflow */ public static ViewFolder createNewRootFolder(ViewLibrary library) { if (!library.hasRootFolder()) { return createNewFolder(library, null, library.getProject().getProject().getProjectName()); } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Cannot create root folder: a root folder is already declared"); } return null; } } public boolean containsShemas() { if (getShemas().size() > 0) { return true; } if (getSubFolders().size() > 0) { boolean answer = false; Enumeration<ViewFolder> en = getSubFolders().elements(); while (en.hasMoreElements() && !answer) { answer = en.nextElement().containsShemas(); } return answer; } return false; } /** * Creates and returns a newly created folder * * @return a newly created folder * @throws DuplicateResourceException */ public static ViewFolder createNewFolder(ViewLibrary library, ViewFolder parentFolder, String folderName) { ViewFolder newFolder = new ViewFolder(folderName, library); newFolder.setFatherFolder(parentFolder); if (parentFolder != null) { parentFolder.addToSubFolders(newFolder); } else { if (logger.isLoggable(Level.INFO)) { logger.info("NEW ROOT FOLDER"); } library.setRootFolder(newFolder); } /* * library.notifyObservers(new DataModification( DataModification.COMPONENT_FOLDER_ADDED_TO_LIBRARY, null, newFolder)); if * (parentFolder != null) { parentFolder.setChanged(); parentFolder.notifyObservers(new ComponentFolderInserted( parentFolder, * newFolder)); } */ return newFolder; } public Vector<ViewFolder> getAllSubFolders() { Vector<ViewFolder> v = new Vector<ViewFolder>(); v.addAll(getAllSubFoldersForFolder(this)); v.remove(this); return v; } public ViewFolder getShemaFolderWithName(String folderName) { for (ViewFolder folder : getAllSubFolders()) { if (folder.getName().equals(folderName)) { return folder; } } if (logger.isLoggable(Level.FINE)) { logger.fine("Could not find folder named " + folderName); } return null; } public Vector<FlexoModelObject> getAllChilds() { Vector<FlexoModelObject> answer = new Vector<FlexoModelObject>(); answer.addAll(getSubFolders()); answer.addAll(getShemas()); return answer; } /** * Overrides delete * * @see org.openflexo.foundation.FlexoModelObject#delete() */ @Override public void delete() { getFatherFolder().removeFromSubFolders(this); super.delete(); deleteObservers(); } public boolean delete(ViewDefinition def) { if (getShemas().contains(def)) { removeFromShemas(def); // getComponentLibrary().notifyTreeStructureChanged(); return true; } else { Enumeration<ViewFolder> en = getSubFolders().elements(); while (en.hasMoreElements()) { boolean isDeleted = en.nextElement().delete(def); if (isDeleted) { return true; } } return false; } } public boolean isValidForANewShemaName(String value) { if (value == null) { return false; } return getShemaNamed(value) == null; } public ViewDefinition getShemaNamed(String value) { if (value == null) { return null; } String searchedName = value; Enumeration<ViewDefinition> en = getShemas().elements(); ViewDefinition temp = null; while (en.hasMoreElements()) { temp = en.nextElement(); if (searchedName.toLowerCase().equals(temp.getName().toLowerCase())) { return temp; } } ViewDefinition cur = null; Enumeration<ViewFolder> en1 = getSubFolders().elements(); while (en1.hasMoreElements() && cur == null) { cur = en1.nextElement().getShemaNamed(searchedName); } if (cur != null && cur.getName().toLowerCase().equals(searchedName.toLowerCase())) { return cur; } return null; } /** * Returns reference to the main object in which this XML-serializable object is contained relating to storing scheme: here it's the * component library * * @return the component library object */ @Override public XMLStorageResourceData getXMLResourceData() { return getShemaLibrary(); } @Deprecated public Vector<ViewDefinition> getShemas() { return getViews(); } @Deprecated public void setShemas(Vector<ViewDefinition> views) { setViews(views); } @Deprecated public Vector<ViewDefinition> getAllShemas() { return getAllViews(); } public Vector<ViewDefinition> getViews() { return _views; } public void setViews(Vector<ViewDefinition> value) { _views = value; } public Vector<ViewDefinition> getAllViews() { Vector<ViewDefinition> v = new Vector<ViewDefinition>(); Enumeration<ViewFolder> en = getSortedSubFolders(); while (en.hasMoreElements()) { ViewFolder f = en.nextElement(); v.addAll(f.getAllShemas()); } Enumeration<ViewDefinition> en1 = getSortedShemas(); while (en1.hasMoreElements()) { v.add(en1.nextElement()); } return v; } public Enumeration<ViewDefinition> getSortedShemas() { disableObserving(); ViewDefinition[] o = FlexoIndexManager.sortArray(getShemas().toArray(new ViewDefinition[0])); enableObserving(); return ToolBox.getEnumeration(o); } public void addToShemas(ViewDefinition shema) { if (shema.getFolder() != null && shema.getFolder() != this) { if (logger.isLoggable(Level.WARNING)) { logger.warning("UNEXPECTEDELY Move shema " + shema + " from folder " + shema.getFolder().getName() + " to folder " + getName()); } shema.getFolder().removeFromShemas(shema); } _views.add(shema); shema.setFolder(this); if (!isDeserializing()) { int i = 0; for (Enumeration<ViewDefinition> en = getSortedShemas(); en.hasMoreElements(); i++) { ViewDefinition sd1 = en.nextElement(); if (ViewDefinition.COMPARATOR.compare(sd1, shema) > 0) { shema.setIndex(i + 1); break; } } FlexoIndexManager.reIndexObjectOfArray(getShemas().toArray(new ViewDefinition[0])); } setChanged(); notifyObservers(new ShemaInserted(shema, this)); if (isRootFolder()) { getShemaLibrary().setChanged(); getShemaLibrary().notifyObservers(new ShemaInserted(shema, this)); } } public void removeFromShemas(ViewDefinition sub) { _views.remove(sub); sub.setFolder(null); FlexoIndexManager.reIndexObjectOfArray(getShemas().toArray(new ViewDefinition[0])); setChanged(); notifyObservers(new ShemaDeleted(sub)); if (isRootFolder()) { getShemaLibrary().setChanged(); getShemaLibrary().notifyObservers(new ShemaDeleted(sub)); } } public Enumeration<ViewFolder> getSortedSubFolders() { disableObserving(); ViewFolder[] o = FlexoIndexManager.sortArray(getSubFolders().toArray(new ViewFolder[0])); enableObserving(); return ToolBox.getEnumeration(o); } public Vector<ViewFolder> getSubFolders() { return _subFolders; } public void setSubFolders(Vector<ViewFolder> value) { _subFolders = value; setChanged(); } public void addToSubFolders(ViewFolder sub) { if (!_subFolders.contains(sub)) { _subFolders.add(sub); sub.setFatherFolder(this); if (!isDeserializing()) { if (getSubFolders().size() > 0) { int i = 0; for (Enumeration<ViewFolder> en = getSortedSubFolders(); en.hasMoreElements() && i < getSubFolders().size(); i++) { ViewFolder f = getSubFolders().get(i); if (ViewFolder.COMPARATOR.compare(f, sub) > 0) { sub.setIndex(i + 1); break; } } // We don't care if no index has been set, it will then keep its current one which is the last one. } else { sub.setIndex(1); } FlexoIndexManager.reIndexObjectOfArray(getSubFolders().toArray(new ViewFolder[0])); } sub.setShemaLibrary(getShemaLibrary()); setChanged(); notifyObservers(new ShemaFolderInserted(sub)); if (isRootFolder()) { getShemaLibrary().setChanged(); getShemaLibrary().notifyObservers(new ShemaFolderInserted(sub)); } } } public void removeFromSubFolders(ViewFolder sub) { _subFolders.remove(sub); FlexoIndexManager.reIndexObjectOfArray(getSubFolders().toArray(new ViewFolder[0])); setChanged(); notifyObservers(new ShemaFolderDeleted(sub)); if (isRootFolder()) { getShemaLibrary().setChanged(); getShemaLibrary().notifyObservers(new ShemaFolderDeleted(sub)); } } @Override public String getName() { return _name; } @Override public void setName(String name) throws DuplicateFolderNameException, InvalidNameException { if (requireChange(_name, name)) { if (getFatherFolder() != null && getFatherFolder().getFolderNamed(name) != null) { throw new DuplicateFolderNameException(this, name); } // There is no reason to dismiss accents /* * if (!isDeserializing() && !name.matches(FileUtils.GOOD_CHARACTERS_REG_EXP + "+")) { throw new InvalidNameException(name); } */ String old = _name; _name = name; setChanged(); notifyObservers(new OEDataModification("name", old, name)); } } public ViewFolder getFatherFolder() { return _fatherFolder; } public void setFatherFolder(ViewFolder folder) { _fatherFolder = folder; } /** * @param folder * @deprecated use {@link #setFatherFolder(ViewFolder)} */ @Deprecated public void setParent(ViewFolder folder) { setFatherFolder(folder); } @Override public String getInspectorName() { return Inspectors.VE.OE_SHEMA_FOLDER_INSPECTOR; } @Override public String getFullyQualifiedName() { return "Folder:" + getName(); } /** * Search in the direct sub-folders of this folder for a folder named <code>name</code> (case insensitive). * * @param name * - the name of the direct sub-folder to find * @return the direct sub-folder named <code>name</code> or null if it cannot be found. */ public ViewFolder getFolderNamed(String name) { name = name.toLowerCase(); Enumeration<ViewFolder> en = getSubFolders().elements(); while (en.hasMoreElements()) { ViewFolder folder = en.nextElement(); if (folder.getName().toLowerCase().equals(name)) { return folder; } } return null; } public boolean isFatherOf(ViewFolder folder) { ViewFolder f = folder.getFatherFolder(); while (f != null) { if (f.equals(this)) { return true; } f = f.getFatherFolder(); } return false; } public static class FolderComparator implements Comparator<ViewFolder> { protected FolderComparator() { } /** * Overrides compare * * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override public int compare(ViewFolder o1, ViewFolder o2) { return o1.getName().compareTo(o2.getName()); } } public boolean isRootFolder() { return getFatherFolder() == null; } /** * Overrides getClassNameKey * * @see org.openflexo.foundation.FlexoModelObject#getClassNameKey() */ @Override public String getClassNameKey() { return "shema_folder"; } public boolean isIndexed() { return this.index > -1; } @Override public int getIndex() { if (isBeingCloned()) { return -1; } if (index == -1 && getCollection() != null) { index = getCollection().length; FlexoIndexManager.reIndexObjectOfArray(getCollection()); } return index; } @Override public void setIndex(int index) { if (isDeserializing() || isCreatedByCloning()) { setIndexValue(index); return; } FlexoIndexManager.switchIndexForKey(this.index, index, this); Collections.sort(getFatherFolder().getSubFolders(), FlexoIndexManager.INDEX_COMPARATOR); if (getIndex() != index) { setChanged(); AttributeDataModification dm = new AttributeDataModification("index", null, getIndex()); dm.setReentrant(true); notifyObservers(dm); } } @Override public int getIndexValue() { return getIndex(); } @Override public void setIndexValue(int index) { if (this.index == index) { return; } int old = this.index; this.index = index; setChanged(); notifyModification("index", old, index); if (!isDeserializing() && !isCreatedByCloning() && getFatherFolder() != null) { getFatherFolder().setChanged(); getFatherFolder().notifyObservers(new ChildrenOrderChanged()); if (getFatherFolder() == getViewLibrary().getRootFolder()) { getViewLibrary().setChanged(); getViewLibrary().notifyObservers(new ChildrenOrderChanged()); } } } /** * Overrides getCollection * * @see org.openflexo.foundation.utils.Sortable#getCollection() */ @Override public ViewFolder[] getCollection() { if (getFatherFolder() == null) { return new ViewFolder[] { this }; } return getFatherFolder().getSubFolders().toArray(new ViewFolder[0]); } public static class DuplicateFolderNameException extends FlexoException { private ViewFolder folder; private String name; /** * @param folder * @param name */ public DuplicateFolderNameException(ViewFolder folder, String name) { this.folder = folder; this.name = name; } public ViewFolder getFolder() { return folder; } public String getName() { return name; } /** * Overrides getLocalizedMessage * * @see org.openflexo.foundation.FlexoException#getLocalizedMessage() */ @Override public String getLocalizedMessage() { return FlexoLocalization.localizedForKey("duplicate_folder_name"); } } }