/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.engines.impl;
import java.io.File;
import java.util.*;
import org.jboss.tools.common.meta.*;
import org.jboss.tools.common.model.*;
import org.jboss.tools.common.model.impl.*;
import org.jboss.tools.common.model.loaders.impl.*;
import org.jboss.tools.common.model.util.XModelObjectLoaderUtil;
public class EnginesLoader extends URLRootLoader {
public EnginesLoader() {}
public void load(XModelObject object) {
super.load(object);
XChild[] cs = object.getModelEntity().getChildren();
for (int i = 0; i < cs.length; i++) {
if(!cs[i].isRequired() || cs[i].getMaxCount() != 1) continue;
if(object.getChildren(cs[i].getName()).length > 0) continue;
//April 2008: catch removed. This call is proved to be safe.
object.addChild(XModelObjectLoaderUtil.createValidObject(object.getModel(), cs[i].getName()));
}
if(isFilePath(getPath(object))) {
File f = file(object);
if(f.isFile()) {
object.getModel().getFileRegistry().register(f);
} else {
object.getModel().getFileRegistry().unregister(f);
}
}
}
public boolean save(XModelObject object) {
boolean b = super.save(object);
if(b && isFilePath(getPath(object))) {
File f = file(object);
if(f.isFile()) object.getModel().getFileRegistry().register(f);
}
return b;
}
public boolean update(XModelObject object) throws XModelException {
if(!isFilePath(getPath(object))) return true;
File f = file(object);
if(!object.getModel().getFileRegistry().isUpdated(f)) return true;
XModelObject c = object.copy(0);
load(c);
merge(object, c);
return true;
}
public String fileroot(XModelObject object) {
return XModelConstants.getWorkspace(object.getModel()) + XModelObjectConstants.SEPARATOR;
}
protected String fileName(XModelObject object) {
return object.getModelEntity().getName().toLowerCase() + ".rex"; //$NON-NLS-1$
}
public static void merge(XModelObject object, XModelObject update) throws XModelException {
merge(object, update, object.isActive());
}
public static void merge(XModelObject object, XModelObject update, boolean fire) throws XModelException {
XModelObjectLoaderUtil.mergeAttributes(object, update, fire);
Map<String,XModelObject> map = getChildrenForSaveAsMap(object);
Set<String> set = null;
XModelObject[] cs = update.getChildren();
for (int i = 0; i < cs.length; i++) {
XModelObject c = object.getChildByPath(cs[i].getPathPart());
if(c == null) {
if(set == null) set = getChildrenToRemove(map, update);
c = findAppropriateChild(set, cs[i], map);
if(c == null) {
c = cs[i].copy();
object.addChild(c);
} else {
boolean has_id = c.getModelEntity().getAttribute(XModelObjectLoaderUtil.ATTR_ID_NAME) != null
|| ((XModelObjectImpl)c).hasIdAttr();
if(has_id) {
c.removeFromParent();
EnginesLoader.merge(c, cs[i], false);
if(!object.addChild(c)) {
c.set(XModelObjectImpl.DUPLICATE, "1234");
object.addChild(c);
}
if(c.get(XModelObjectImpl.DUPLICATE) != null) {
c.set(XModelObjectImpl.DUPLICATE, "");
}
} else {
EnginesLoader.merge(c, cs[i], fire);
}
}
} else if(c.getModelEntity().getName().equals(cs[i].getModelEntity().getName())) {
merge(c, cs[i], fire);
} else {
object.removeChild(c);
object.addChild(cs[i].copy());
}
map.remove(c.getPathPart());
}
if(!map.isEmpty()) {
Iterator<XModelObject> it = map.values().iterator();
while(it.hasNext()) {
XModelObject o = (XModelObject)it.next();
XChild childEntity = object.getModelEntity().getChild(o.getModelEntity().getName());
if(childEntity != null && childEntity.isRequired()) {
continue;
}
o.removeFromParent();
}
}
boolean doFire = false;
for (int i = 0; i < cs.length; i++) {
XModelObject c = object.getChildByPath(cs[i].getPathPart());
if(c == null) continue;
int ci = ((RegularObjectImpl)object).getIndexOfChild(c);
if(ci == i) continue;
doFire = true;
((RegularObjectImpl)object).move(ci, i, false);
}
if(fire && doFire) ((XModelImpl)object.getModel()).fireStructureChanged(object);
}
static Map<String,XModelObject> emptyMap = new HashMap<String,XModelObject>();
private static Map<String,XModelObject> getChildrenForSaveAsMap(XModelObject object) {
XModelObject[] cs = object.getChildrenForSave();
if(cs.length == 0) return emptyMap;
Map<String,XModelObject> map = new HashMap<String,XModelObject>();
for (int i = 0; i < cs.length; i++) {
map.put(cs[i].getPathPart(), cs[i]);
}
return map;
}
public static Set<String> getChildrenToRemove(Map<String,XModelObject> save, XModelObject update) {
Iterator<String> it = save.keySet().iterator();
Set<String> set = new HashSet<String>();
while(it.hasNext()) {
String p = it.next();
if(update.getChildByPath(p) == null) set.add(p);
}
return set;
}
public static XModelObject findAppropriateChild(Set<String> set, XModelObject updateChild, Map<String,XModelObject> map) {
String entity = updateChild.getModelEntity().getName();
Iterator<String> it = set.iterator();
while(it.hasNext()) {
String p = it.next();
XModelObject o = map.get(p);
if(o == null) continue;
if(entity.equals(o.getModelEntity().getName())) {
it.remove();
map.remove(p);
return o;
}
}
return null;
}
}