/*******************************************************************************
* Copyright (c) 2007 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
*
* Contributor:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.seam.internal.core;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.XModelObjectConstants;
import org.jboss.tools.common.model.filesystems.impl.FileAnyImpl;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.seam.core.ISeamComponent;
import org.jboss.tools.seam.core.ISeamElement;
import org.jboss.tools.seam.core.ISeamProject;
import org.jboss.tools.seam.core.ISeamProperty;
import org.jboss.tools.seam.core.ISeamXmlComponentDeclaration;
import org.jboss.tools.seam.core.SeamCorePlugin;
import org.jboss.tools.seam.core.event.ISeamValue;
import org.jboss.tools.seam.core.event.ISeamValueList;
import org.jboss.tools.seam.core.event.ISeamValueString;
/**
* @author Viacheslav Kabanovich
*/
public class SeamMessagesLoader {
static class MessageBundle {
String bundle;
List<XModelObject> files = new ArrayList<XModelObject>();
MessageBundle(String bundle, List<XModelObject> files) {
this.bundle = bundle;
this.files = files;
}
}
static List<MessageBundle> EMPTY = new ArrayList<MessageBundle>();
List<MessageBundle> resources = EMPTY; // Maps the bundleName to the IResource
Map<String, Long> timestamps = null;
Set<String> keys = null;
Map<String, List<XModelObject>> properties = null;
ISeamElement object;
/**
* In Seam 1.2 "org.jboss.seam.core.resourceBundle"
* In Seam 2.0 "org.jboss.seam.core.resourceLoader"
*/
String resourceComponent;
public SeamMessagesLoader(ISeamElement object, String resourceComponent) {
this.object = object;
this.resourceComponent = resourceComponent;
}
public void revalidate() {
List<MessageBundle> resources2 = getResources();
if(changed(resources2)) {
timestamps = new HashMap<String, Long>();
for (int i = 0; i < resources2.size(); i++) {
List<XModelObject> r = resources2.get(i).files;
long q = 0;
for (XModelObject o: r) q += o.getTimeStamp();
timestamps.put(resources2.get(i).bundle, q);
}
resources = resources2;
keys = null;
properties = null;
}
}
private boolean changed(List<MessageBundle> resources2) {
if(resources == resources2) return false;
if(resources2.size() != resources.size()) return true;
if(timestamps == null) return true;
for (int i = 0; i < resources2.size(); i++) {
List<XModelObject> r2 = resources2.get(i).files;
List<XModelObject> r1 = resources.get(i).files;
if(r1 == null || r2.size() == r1.size()) return true;
long l1 = 0;
for (XModelObject o: r1) l1 += o.getTimeStamp();
Long l2 = timestamps.get(resources2.get(i).bundle);
if(l2 == null || l1 != l2.longValue()) return true;
}
return false;
}
public List<MessageBundle> getResources() {
ISeamProject p = object.getSeamProject();
if(p == null) return EMPTY;
IResource[] srcs = EclipseResourceUtil.getJavaSourceRoots(p.getProject());
List<String> names = getNames();
return names.isEmpty() ? EMPTY : getResources(names, srcs);
}
private List<String> getNames() {
ISeamProject p = object.getSeamProject();
if(p == null) {
return new ArrayList<String>();
}
ISeamComponent c = p.getComponent(resourceComponent);
if(c == null) {
return new ArrayList<String>();
}
List<String> names = new ArrayList<String>();
Set<ISeamXmlComponentDeclaration> ds = c.getXmlDeclarations();
for (ISeamXmlComponentDeclaration d: ds) {
ISeamProperty property = d.getProperty("bundleNames");
if(property == null) continue;
ISeamValue v = property.getValue();
if(v == null) continue;
if(v instanceof ISeamValueList) {
List<ISeamValueString> vs = ((ISeamValueList)v).getValues();
for (ISeamValueString s: vs) {
if(s.getValue() == null) continue;
String b = s.getValue().getValue();
names.add(b);
}
} else if(v instanceof ISeamValueString) {
ISeamValueString s = (ISeamValueString)v;
if(s.getValue() == null) continue;
String b = s.getValue().getValue();
if(b == null || b.length() == 0) continue;
String[] bi = b.split(",");
for (int i = 0; i < bi.length; i++) {
names.add(bi[i].trim());
}
}
}
if(ds.isEmpty()) {
names.add("messages");
}
return names;
}
public Collection<ISeamProperty> getProperties() {
throw new IllegalStateException("Not implemented");
}
public Map<String, List<XModelObject>> getPropertiesMap() {
if(properties == null) {
properties = new HashMap<String, List<XModelObject>>();
for (int i = 0; i < resources.size(); i++) {
List<XModelObject> list = resources.get(i).files;
for (XModelObject o: list) {
XModelObject[] ps = o.getChildren();
for (XModelObject p: ps) {
String propertyName = p.getAttributeValue(XModelObjectConstants.ATTR_NAME);
List<XModelObject> vs = properties.get(propertyName);
if(vs == null) {
vs = new ArrayList<XModelObject>();
properties.put(propertyName, vs);
}
vs.add(p);
}
}
}
}
return properties;
}
private List<MessageBundle> getResources(List<String> names, IResource[] srcs) {
List<MessageBundle> rs = new ArrayList<MessageBundle>();
for (String name: names) {
String n = name.replace('.', '/');
int k = n.lastIndexOf('/');
String p = k < 0 ? null : n.substring(0, k);
if(k >= 0) n = n.substring(k + 1);
IResource result = null;
for (int j = 0; j < srcs.length && result == null; j++) {
result = find(p, n, srcs[j]);
}
if(result != null) {
List<XModelObject> l = new ArrayList<XModelObject>();
XModelObject o = EclipseResourceUtil.createObjectForResource(result);
if(o != null) {
XModelObject[] os = o.getParent().getChildren();
String dn = o.getAttributeValue(XModelObjectConstants.ATTR_NAME);
for (XModelObject c: os) {
String fileName = FileAnyImpl.toFileName(c);
if(fileName.endsWith(".properties") && (c == o || fileName.startsWith(dn + "_"))) {
l.add(c);
}
}
rs.add(new MessageBundle(name, l));
}
}
}
return rs;
}
private IResource find(String pack, String name, IResource src) {
if(!(src instanceof IContainer)) return null;
IContainer c = (IContainer)src;
if(pack != null) {
c = c.getFolder(new Path(pack));
}
if(c == null || !c.exists()) return null;
String suffix = ".properties";
String name_ = name + "_";
String name_p = name + suffix;
IResource result = null;
try {
IResource[] rs = c.members();
for (int i = 0; i < rs.length; i++) {
String n = rs[i].getName();
if(name_p.equals(n)) return rs[i];
if(result == null && n.startsWith(name_) && n.endsWith(suffix)) {
result = rs[i];
}
}
} catch (CoreException e) {
SeamCorePlugin.getPluginLog().logError(e);
}
return result;
}
}