/*******************************************************************************
* 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.options.impl;
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.options.*;
public class SharableElementImpl extends XModelObjectImpl implements SharableElement {
private static final long serialVersionUID = 7922861006119791921L;
private static final Map<String,String> singular = new HashMap<String,String>(3);
static {
singular.put("scope", "scope"); //$NON-NLS-1$ //$NON-NLS-2$
singular.put("sharing", "sharing"); //$NON-NLS-1$ //$NON-NLS-2$
}
static boolean isSingular(String property) {
return singular.get(property) != null;
}
protected XScope general_ = new XScope(GENERAL);
protected XScope project_ = new XScope(PROJECT);
protected Map<String,XScope> scopes = new HashMap<String,XScope>();
protected XScope scope = project_;
private Map<String,SharableElement> children = new HashMap<String,SharableElement>();
private SharableComparator comparator = null;
protected String name = ""; //$NON-NLS-1$
public SharableElementImpl() {
super();
scopes.put(GENERAL, general_);
scopes.put(PROJECT, project_);
}
public SharableElement getSharableParent() {
Object p = getParent();
return (p instanceof SharableElement)
? (SharableElement)p : null;
}
public SharableElement[] getSharableChildren() {
return children.values().toArray(new SharableElement[0]);
}
private int getChildrenCount(String entity) {
SharableElement[] cs = getSharableChildren();
int k = 0;
for (int i = 0; i < cs.length; i++) {
if(entity.equals(cs[i].getModelEntity().getName())) ++k;
}
return k;
}
private void setScope0(String scopename) {
scope = (XScope)scopes.get(scopename);
if(scope == null) scope = project_;
}
public void setScope(String scopename) {
setScope0(scopename);
if(!scope.exists()) scope.setExists(true);
}
public String getScope() {
return scope.getName();
}
public boolean exists() {
return general_.exists() || project_.exists();
}
XScope getXScope(String scopename) {
return (XScope)scopes.get(scopename);
}
public boolean scopeExists(String scopename) {
XScope s = getXScope(scopename);
return (s != null && s.exists());
}
public void setScopeExists(String scopename, boolean b) {
XScope s = getXScope(scopename);
if(s == null || s.exists() == b ||
!XStudioLoaderPeer.instance().isScopeEditable(scopename)) return;
setScopeExists0(scopename, b);
}
void setScopeExists0(String scopename, boolean b) {
XScope s = getXScope(scopename);
if(s == null || s.exists() == b) return;
s.setExists(b);
if(!b) {
SharableElement[] cs = getSharableChildren();
for (int i = 0; i < cs.length; i++) {
SharableElementImpl c = (SharableElementImpl)cs[i];
if(c != null) c.setScopeExists0(scopename, false);
}
} else {
SharableElementImpl p = (SharableElementImpl)getSharableParent();
if(p != null) p.setScopeExists0(scopename, true);
}
}
protected void onSetEntity(String entityName) {
XModelEntity entity = getModel().getMetaData().getEntity(entityName);
XAttribute[] as = entity.getAttributes();
for (int i = 0; i < LIST.length; i++) {
scope = (XScope)scopes.get(LIST[i]);
for (int j = 0; j < as.length; j++) {
if(isSingular(as[j].getName())) continue;
setAttributeValue(as[j].getName(), as[j].getDefaultValue());
}
}
comparator = new SharableComparator(entity.getChildren());
}
////////////////// children ////////////////
public boolean addSharableChild(SharableElement child) {
String childname = child.name();
if(findSharableChild(childname) != null) return false;
children.put(childname, child);
return true;
}
public void removeSharableChild(String name) {
if(canRemoveChild(name)) {
children.remove(name);
}
}
public boolean canRemoveChild(String name) {
SharableElementImpl s = (SharableElementImpl)children.get(name);
if(s == null) return false;
for (int i = 0; i < LIST.length; i++) {
XScope sc = s.getXScope(LIST[i]);
if(sc.exists() &&
!XStudioLoaderPeer.instance().isScopeEditable(LIST[i]))
return false;
}
return true;
}
public SharableElement findSharableChild(String childname) {
return (SharableElement)children.get(childname);
}
////////////////// override ////////////////
public String get(String name) {
if("scope".equals(name)) { //$NON-NLS-1$
return getScope();
} else if("sharing".equals(name)) { //$NON-NLS-1$
String x = (general_.exists() ? GENERAL + "," : "") //$NON-NLS-1$ //$NON-NLS-2$
+ (project_.exists() ? PROJECT + "," : ""); //$NON-NLS-1$ //$NON-NLS-2$
int c = x.length() - 1;
return (c < 0) ? "" : x.substring(0, c); //$NON-NLS-1$
}
return (XModelObjectConstants.XML_ATTR_NAME.equals(name)) ? name()
: scope.getProperty(name);
}
public void set(String name, String value) {
if("scope".equals(name)) { //$NON-NLS-1$
String ov = get(name);
if(ov.equals(value)) return;
String max = XStudioLoaderPeer.getMaxScope(ov, value);
if(!XStudioLoaderPeer.instance().isScopeEditable(max)) return;
setScope0(value);
if(!scope.exists())
setScopeExists(scope.getName(), true);
} else if("sharing".equals(name)) { //$NON-NLS-1$
setScopeExists(GENERAL, value.indexOf(GENERAL) >= 0);
setScopeExists(PROJECT, value.indexOf(PROJECT) >= 0);
} else if(XModelObjectConstants.XML_ATTR_NAME.equals(name)) {
setName(value);
} else {
scope.setProperty(name, value);
}
}
public String getAttributeValue(String name, String scopename) {
XScope current = scope;
setScope0(scopename);
String res = getAttributeValue(name);
scope = current;
return res;
}
public String getDefaultValue(String name) {
XAttribute a = getModelEntity().getAttribute(name);
if(a == null) return null;
if(a.getXMLName() == null || a.getXMLName().length() == 0) return a.getDefaultValue();
String v = getAttributeValue(name, GENERAL);
if(v == null || v.length() == 0) v = a.getDefaultValue();
return v;
}
protected String getEntityName() {
return "SharableDefault"; //$NON-NLS-1$
}
public String name() {
return name;
}
public void setName_0(String value) {
name = value;
}
public boolean setName(String value) {
if(value == null) return false;
String oldvalue = name();
if(value.equals(oldvalue)) return true;
SharableElement p = getSharableParent();
if(p != null && p.findSharableChild(value) != null) return false;
if(p != null && p.findSharableChild(oldvalue) == null) return false;
String op = getPath();
setName_0(value);
if(p != null) {
SharableElementImpl sp = (SharableElementImpl)p;
sp.children.remove(oldvalue);
sp.children.put(value, this);
((XModelImpl)getModel()).fireNodeChanged(this, op);
fireUpdateChilds();
}
return true;
}
protected void fireUpdateChilds() {}
public boolean addChild_0(XModelObject child) {
if(child == null) return false;
boolean res = false;
String ce = child.getModelEntity().getName();
XChild c_ent = getModelEntity().getChild(ce);
if(c_ent == null) return false;
if(c_ent.getMaxCount() < Integer.MAX_VALUE && getChildrenCount(ce) >= c_ent.getMaxCount()) {
return false;
}
if(child instanceof SharableElement) {
SharableElementImpl sc = (SharableElementImpl)child;
res = addSharableChild(sc);
if(res) {
sc.setParent_0(this);
for (int i = 0; i < LIST.length; i++) {
if(sc.scopeExists(LIST[i])) {
setScopeExists(LIST[i], true);
}
if(!scopeExists(LIST[i])) {
((XScope)sc.scopes.get(LIST[i])).setExists(false);
}
}
}
}
return res;
}
public void removeChild_0(XModelObject o) {
if(o instanceof SharableElement) {
removeSharableChild(((SharableElement)o).name());
}
}
public XModelObject[] getChildren() {
SharableElement[] cs = getSharableChildren();
Arrays.sort(cs, comparator);
return cs;
}
public boolean isObjectEditable() {
return isScopeEditable(scope.getName());
}
public boolean isScopeEditable(String scopename) {
return XStudioLoaderPeer.instance().isScopeEditable(scopename);
}
public boolean isScopeExists(String scopename) {
XScope s = getXScope(scopename);
return (s != null && s.exists());
}
public boolean isAttributeEditable(String attributeName) {
return isSingular(attributeName) || isObjectEditable();
}
private void shareProperties0(XScope fs, XScope ts) {
Properties fp = fs.properties(), tp = ts.properties();
Enumeration en = fp.keys();
while(en.hasMoreElements()) {
String key = (String)en.nextElement();
String val = fp.getProperty(key);
tp.setProperty(key, val);
}
}
public void sharing(String fromscope, String toscope) {
XScope fs = getXScope(fromscope), ts = getXScope(toscope);
if(!ts.exists()) setScopeExists(toscope, true);
if(!ts.exists()) return;
shareProperties0(fs, ts);
childsharing(fromscope, toscope);
}
protected void childsharing(String fromscope, String toscope) {
((XModelImpl)getModel()).fireNodeChanged(this, getPath());
}
static String IMAGE_PROPERTY = "IMAGE";
public void merge(String fromscope, String toscope, boolean merge_all) {
XScope fs = getXScope(fromscope), ts = getXScope(toscope);
boolean existed = ts.exists();
if(!existed) setScopeExists(toscope, true);
if(!ts.exists()) return;
if(!existed || merge_all) {
shareProperties0(fs, ts);
} else if(fs.exists() && getModelEntity().getName().equals("SharableIcon") && GENERAL.equals(fromscope)) {
String image = fs.getProperty(IMAGE_PROPERTY);
String image2 = ts.getProperty(IMAGE_PROPERTY);
if(image != null && !image.equals(image2)) {
ts.setProperty(IMAGE_PROPERTY, image);
}
}
mergeChildren(fromscope, toscope, existed, merge_all);
setScope(PROJECT);
}
protected void mergeChildren(String fromscope, String toscope, boolean existed, boolean merge_all) {
SharableElement[] cs = getSharableChildren();
for (int i = 0; i < cs.length; i++)
((SharableElementImpl)cs[i]).merge(fromscope, toscope, merge_all);
}
}
class XScope {
private String name;
private Properties properties = new Properties();
private XModelObject child = null;
private boolean exists = false;
public XScope(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getProperty(String name) {
return properties.getProperty(name);
}
public void setProperty(String name, String value) {
properties.setProperty(name, value);
}
public boolean exists() {
return exists;
}
public void setExists(boolean b) {
exists = b;
}
public XModelObject getChild() {
return child;
}
public void setChild(XModelObject child) {
this.child = child;
}
Properties properties() {
return properties;
}
}
class SharableComparator implements Comparator<SharableElement> {
private Hashtable<String,Integer> entities = null;
public SharableComparator(XChild[] c) {
entities = new Hashtable<String,Integer>(c.length);
for (int i = 0; i < c.length; i++) {
entities.put(c[i].getName(), Integer.valueOf(i * 100));
}
}
public int compare(SharableElement o1, SharableElement o2) {
int i1 = getEntityRange(o1);
int i2 = getEntityRange(o2);
if(i1 != i2) return (i1 - i2) ;
return o1.name().compareTo(o2.name());
}
private int getEntityRange(SharableElement s) {
Integer i = entities.get(s.getModelEntity().getName());
return (i == null) ? 1000 : i.intValue();
}
public boolean equals(Object obj) {
return obj == this;
}
}