/*******************************************************************************
* 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.loaders.impl;
import java.util.*;
import org.jboss.tools.common.meta.*;
import org.jboss.tools.common.model.loaders.*;
import org.jboss.tools.common.model.plugin.ModelPlugin;
import org.jboss.tools.common.model.util.ModelFeatureFactory;
public class ModelEntityRecognizer implements EntityRecognizer {
private HashMap<String,EntityRecognizer[]> recognizers = new HashMap<String,EntityRecognizer[]>();
private Set<String> umbiguousExtensions = new HashSet<String>();
public ModelEntityRecognizer(XModelMetaData meta) {
load(meta);
}
public String getEntityName(EntityRecognizerContext context) {
String ext = context.getExtension();
if(ext != null) ext = ext.toLowerCase();
EntityRecognizer[] list = recognizers.get(ext);
if(list == null || list.length == 0) return "FileAny"; //$NON-NLS-1$
for (EntityRecognizer r: list) {
String n = r.getEntityName(context);
if(n != null) return n;
}
return null;
}
public boolean isBodyRequired(EntityRecognizerContext context, String entityForNullBody) {
return entityForNullBody == null
|| (context.getExtension() != null && umbiguousExtensions.contains(context.getExtension()));
}
private void load(XModelMetaData meta) {
XMapping m = meta.getMapping("Recognizers"); //$NON-NLS-1$
if(m == null) return;
HashMap<String,RL> ext_list = new HashMap<String,RL>();
HashMap<String,EntityRecognizer> cls_recw = new HashMap<String,EntityRecognizer>();
String[] keys = m.getKeys();
for (int i = 0; i < keys.length; i++) {
String k = keys[i];
String clsname = m.getValue(k);
if(clsname == null || clsname.trim().length() == 0) continue;
EntityRecognizer r = cls_recw.get(clsname);
if(r == null) {
r = new EntityRecognizerWrapper(clsname);
cls_recw.put(clsname, r);
}
int d = k.indexOf('$');
String ext = (d < 0) ? k : k.substring(0, d);
RL rl = ext_list.get(ext);
if(rl == null) {
rl = new RL();
ext_list.put(ext, rl);
}
int p = (d < 0) ? 0 : parsePriority(k.substring(d + 1));
rl.add(r, p);
}
String[] ks = ext_list.keySet().toArray(new String[0]);
for (int i = 0; i < ks.length; i++) {
RL rl = ext_list.get(ks[i]);
EntityRecognizer[] rs = rl.list();
ext_list.remove(ks[i]);
if(rs.length > 0) {
recognizers.put(ks[i], rs);
}
}
for (String ext: recognizers.keySet()) {
EntityRecognizer[] rs = recognizers.get(ext);
if(rs != null && rs.length > 1) {
umbiguousExtensions.add(ext);
}
}
}
private EntityRecognizer find(String clsname) {
try {
return (EntityRecognizer)ModelFeatureFactory.getInstance().createFeatureInstance(clsname);
} catch (ClassCastException e) {
ModelPlugin.getPluginLog().logError("Entity recognizer " + clsname + " must be instanceof EntityRecognizer", e); //$NON-NLS-1$ //$NON-NLS-2$
}
return null;
}
private int parsePriority(String s) {
if(s == null) return 10;
try {
return (s.length() == 0) ? 0 : Integer.parseInt(s);
} catch (NumberFormatException e) {
return 10;
}
}
private class RL {
private Vector<R> v = new Vector<R>(2);
public void add(EntityRecognizer r, int p) {
R x = resolve(r, p);
for (int i = 0; i < v.size(); i++) {
R y = v.elementAt(i);
if(x.p < y.p) {
v.insertElementAt(x, i);
return;
}
}
v.addElement(x);
}
private R resolve(EntityRecognizer r, int p) {
for (int i = 0; i < v.size(); i++) {
R x = v.elementAt(i);
if(x.r != r) continue;
if(p < x.p) x.p = p;
v.removeElement(x);
return x;
}
return new R(r, p);
}
public EntityRecognizer[] list() {
EntityRecognizer[] rs = new EntityRecognizer[v.size()];
for (int i = 0; i < v.size(); i++) {
R x = (R)v.elementAt(i);
rs[i] = x.r;
}
return rs;
}
}
private class R {
EntityRecognizer r;
int p;
R(EntityRecognizer r, int p) {
this.r = r;
this.p = p;
}
}
private class EntityRecognizerWrapper implements EntityRecognizer {
String clsname;
EntityRecognizer resolved;
public EntityRecognizerWrapper(String clsname) {
this.clsname = clsname;
}
boolean checkResolved() {
if(resolved == null && clsname != null) {
resolved = find(clsname);
clsname = null;
}
return resolved != null;
}
public String getEntityName(EntityRecognizerContext context) {
if(!checkResolved()) return null;
return resolved.getEntityName(context);
}
}
}