/*******************************************************************************
* 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.propertieseditor.bundlemodel;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.resources.IFile;
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.options.PreferenceModelUtilities;
import org.jboss.tools.common.model.ui.ModelUIPlugin;
public class BundleModel {
IFile main;
XModelObject object = PreferenceModelUtilities.getPreferenceModel().createModelObject(XModelObjectConstants.ENTITY_FILE_PROPERTIES, null);
String currentLocale = ""; //$NON-NLS-1$
Set<String> locales = new TreeSet<String>();
Set<String> removedLocales = new HashSet<String>();
boolean isModified;
public BundleModel() {}
public void dispose() {
modificationListener = null;
if (locales!=null) locales.clear();
locales = null;
if (removedLocales!=null) removedLocales.clear();
removedLocales = null;
main = null;
}
public void setMainFile(IFile f) {
main = f;
}
public String getName() {
String name = main.getName();
if(name.endsWith(".properties")) name = name.substring(0, name.length() - ".properties".length()); //$NON-NLS-1$ //$NON-NLS-2$
return name;
}
public IFile getMainFile() {
return main;
}
public XModelObject getModelObject() {
return object;
}
public IFile getFile(String locale) {
if(locale.length() == 0) return main;
String name = getName() + "_" + locale + ".properties"; //$NON-NLS-1$ //$NON-NLS-2$
return main.getParent().getFile(new Path("/" + name)); //$NON-NLS-1$
}
public String[] getLocales() {
return (String[])locales.toArray(new String[0]);
}
public void setCurrentLocale(String locale) {
currentLocale = locale;
PropertyModel[] ps = getPropertyModelArray();
for (int i = 0; i < ps.length; i++) ps[i].setLocale(locale);
}
public PropertyModel[] getPropertyModelArray() {
XModelObject[] cs = object.getChildren();
PropertyModel[] ps = new PropertyModel[cs.length];
for (int i = 0; i < ps.length; i++)
ps[i] = getPropertyModel(cs[i], currentLocale);
return ps;
}
public PropertyModel createPropertyModel(String name, String value, String locale) {
XModelObject o = PreferenceModelUtilities.getPreferenceModel().createModelObject("Property", null); //$NON-NLS-1$
o.setAttributeValue("name", name); //$NON-NLS-1$
o.setAttributeValue("value", value); //$NON-NLS-1$
object.addChild(o);
return getPropertyModel(o, locale);
}
public PropertyModel getPropertyModel(String name) {
return getPropertyModel(object.getChildByPath(name), currentLocale);
}
public PropertyModel getPropertyModel(XModelObject o, String locale) {
if(o == null) return null;
PropertyModel pm = (PropertyModel)o.getObject("propertyModel"); //$NON-NLS-1$
if(pm == null) {
pm = new PropertyModel(this);
pm.setModelObject(o);
if(locale != null) pm.setValue(locale, o.getAttributeValue("value")); //$NON-NLS-1$
pm.setLocale(currentLocale);
}
return pm;
}
public String getCurrentLocale() {
return currentLocale;
}
public void load() {
locales.clear();
removedLocales.clear();
locales.add(""); //$NON-NLS-1$
String name = getName();
String[][] p = loadFile(main);
if(p == null) return;
for (int i = 0; i < p.length; i++) {
createPropertyModel(p[i][0], p[i][1], ""); //$NON-NLS-1$
}
IResource[] rs = new IResource[0];
try {
rs = main.getParent().members();
} catch (CoreException e) {
ModelUIPlugin.getPluginLog().logError(e);
}
for (int i = 0; i < rs.length; i++) {
if(!(rs[i] instanceof IFile)) continue;
IFile f = (IFile)rs[i];
String nm = rs[i].getLocation().lastSegment().toString();
if(!nm.startsWith(name) || !nm.endsWith(".properties") || nm.indexOf("_") < 0) continue; //$NON-NLS-1$ //$NON-NLS-2$
nm = nm.substring(0, nm.length() - ".properties".length()); //$NON-NLS-1$
String locale = nm.substring(nm.indexOf("_") + 1); //$NON-NLS-1$
locales.add(locale);
p = loadFile(f);
if(p == null) continue;
for (int j = 0; j < p.length; j++) {
PropertyModel pm = getPropertyModel(p[j][0]);
if(pm == null) {
pm = createPropertyModel(p[j][0], p[j][1], locale);
} else {
pm.setValue(locale, p[j][1]);
}
}
}
}
private String[][] loadFile(IFile file) {
if(!file.exists()) return null;
ArrayList<String> keys = new ArrayList<String>();
ArrayList<String> values = new ArrayList<String>();
Properties p = new Properties();
InputStream s = null;
try {
s = file.getContents();
BufferedReader in = new BufferedReader(new InputStreamReader(s, "8859_1")); //$NON-NLS-1$
while (true) {
String line = in.readLine();
if(line == null) break;
if(line.length() == 0) continue;
char firstChar = line.charAt(0);
if ((firstChar == '#') || (firstChar == '!')) continue;
StringBuffer sb = new StringBuffer(line);
while (continueLine(line)) {
String nextLine = in.readLine();
if(nextLine == null) nextLine = ""; //$NON-NLS-1$
sb.append("\n"); //$NON-NLS-1$
sb.append(line = nextLine);
}
ByteArrayInputStream is = new ByteArrayInputStream(sb.toString().getBytes());
p.clear();
try {
p.load(is);
} catch (IllegalArgumentException e1) {
//ignore
} catch (IOException e) {
ModelUIPlugin.getPluginLog().logError(e);
}
Enumeration ee = p.keys();
if(ee.hasMoreElements()) {
String key = ee.nextElement().toString();
keys.add(key);
values.add(p.getProperty(key));
}
}
} catch (CoreException e) {
ModelUIPlugin.getPluginLog().logError(e);
} catch (IOException e) {
ModelUIPlugin.getPluginLog().logError(e);
} finally {
if(s!=null) {
try {
s.close();
} catch (IOException e) {
// ignore
}
}
}
String[][] r = new String[keys.size()][2];
for (int i = 0; i < r.length; i++) {
r[i][0] = keys.get(i).toString();
r[i][1] = values.get(i).toString();
}
return r;
}
private boolean continueLine(String line) {
int slashCount = 0;
int index = line.length() - 1;
while((index >= 0) && (line.charAt(index--) == '\\'))
slashCount++;
return (slashCount % 2 == 1);
}
public void addLocale(String locale) {
if(!locales.contains(locale)) {
locales.add(locale);
removedLocales.remove(locale);
setModified(true);
}
setCurrentLocale(locale);
}
public void removeLocale(String locale) {
if(locale.length() == 0 || !locales.contains(locale)) return;
locales.remove(locale);
removedLocales.add(locale);
setModified(true);
}
public void save() {
String[] ls = (String[])removedLocales.toArray(new String[0]);
for (int i = 0; i < ls.length; i++) {
IFile f = getFile(ls[i]);
if(f.exists()) try {
f.delete(true, true, null);
} catch (CoreException e) {
ModelUIPlugin.getPluginLog().logError(e);
}
}
removedLocales.clear();
ls = (String[])locales.toArray(new String[0]);
for (int i = 0; i < ls.length; i++) {
IFile f = getFile(ls[i]);
StringBuffer sb = new StringBuffer();
PropertyModel[] ps = getPropertyModelArray();
// String[][] r = new String[ps.length][2];
for (int k = 0; k < ps.length; k++) {
String key = ps[k].getName();
String value = ps[k].getValue(ls[i]);
if(ps[k].hasValue(ls[i])) {
Properties p0 = new Properties();
p0.setProperty(key, value);
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
p0.store(os, null);
} catch (IOException e) {
ModelUIPlugin.getPluginLog().logError(e);
continue;
}
String s = os.toString();
if(s.startsWith("#")) s = s.substring(s.indexOf('\n') + 1); //$NON-NLS-1$
sb.append(s);
}
}
ByteArrayInputStream is = new ByteArrayInputStream(sb.toString().getBytes());
try {
if(f.exists()) f.setContents(is, true, true, null);
else f.create(is, true, null);
} catch (CoreException e) {
ModelUIPlugin.getPluginLog().logError(e);
}
}
setModified(false);
}
public boolean isModified() {
return isModified;
}
public interface ModificationListener {
public void changed();
}
ModificationListener modificationListener;
public void setModified(boolean b) {
if(isModified == b) return;
isModified = b;
if(modificationListener != null) modificationListener.changed();
}
public void addModifiedListener(ModificationListener listener) {
modificationListener = listener;
}
public void removeModifiedListener(ModificationListener listener) {
modificationListener = null;
}
public boolean isEditable() {
IFile f = getFile(currentLocale);
if(f == null || !f.exists()) return true;
return !f.isReadOnly();
}
}