/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.rubypeople.rdt.internal.corext.util;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.rubypeople.rdt.core.IRubyModel;
import org.rubypeople.rdt.core.IRubyProject;
import org.rubypeople.rdt.core.RubyCore;
import org.rubypeople.rdt.core.RubyModelException;
public class TypeInfoFactory {
private String[] fProjects;
private TypeInfo fLast;
private char[] fBuffer;
// private static final String CLASS= "class"; //$NON-NLS-1$
private static final String RUBY= "rb"; //$NON-NLS-1$
public TypeInfoFactory() {
super();
fProjects= getProjectList();
fLast= null;
fBuffer= new char[512];
}
public TypeInfo create(char[] packageName, char[] typeName, char[][] enclosingName, boolean isModule, String path) {
path = new Path(path).toPortableString();
String pn= getPackageName(packageName);
String tn= new String(typeName);
TypeInfo result= null;
String project = getProject(path);
if (project != null) {
result = createIFileTypeInfo(pn, tn, enclosingName, isModule, path, getIFileTypeInfo(fLast), project);
} else {
result = createExternalFileTypeInfo(pn, tn, enclosingName, isModule, path);
}
if (result == null) {
result= new UnresolvableTypeInfo(pn, tn, enclosingName, isModule, path);
} else {
fLast= result;
}
return result;
}
private TypeInfo createExternalFileTypeInfo(String packageName, String typeName, char[][] enclosingName, boolean isModule, String path) {
return new ExternalFileTypeInfo(packageName, typeName, enclosingName, isModule, path);
}
private static IFileTypeInfo getIFileTypeInfo(TypeInfo info) {
if (info == null || info.getElementType() != TypeInfo.IFILE_TYPE_INFO)
return null;
return (IFileTypeInfo)info;
}
private TypeInfo createIFileTypeInfo(String packageName, String typeName, char[][] enclosingName, boolean isModule, String path, IFileTypeInfo last, String project) {
String rest= path.substring(project.length() + 1); // the first slashes.
int index= rest.lastIndexOf(TypeInfo.SEPARATOR);
if (index == -1)
return null;
String middle= rest.substring(0, index);
rest= rest.substring(index + 1);
index= rest.lastIndexOf(TypeInfo.EXTENSION_SEPARATOR);
String file= null;
String extension= null;
if (index != -1) {
file= rest.substring(0, index);
extension= rest.substring(index + 1);
} else {
return null;
}
String src= null;
int ml= middle.length();
int pl= packageName.length();
// if we have a source or package then we have to substract the leading '/'
if (ml > 0 && ml - 1 > pl) {
// If we have a package then we have to substract the '/' between src and package
src= middle.substring(1, ml - pl - (pl > 0 ? 1 : 0));
}
if (last != null) {
if (src != null && src.equals(last.getFolder()))
src= last.getFolder();
}
if (typeName.equals(file)) {
file= typeName;
} else {
file= createString(file);
}
// if (CLASS.equals(extension))
// extension= CLASS;
/* else */ if (RUBY.equals(extension))
extension= RUBY;
else
extension= createString(extension);
return new IFileTypeInfo(packageName, typeName, enclosingName, isModule, project, src, file, extension);
}
private String getPackageName(char[] packageName) {
if (fLast == null)
return new String(packageName);
String lastPackageName= fLast.getPackageName();
if (Strings.equals(lastPackageName, packageName))
return lastPackageName;
return new String(packageName);
}
private String getProject(String path) {
for (int i= 0; i < fProjects.length; i++) {
String project= fProjects[i];
if (path.startsWith(project, 1))
return project;
}
return null;
}
private String createString(String s) {
if (s == null)
return null;
int length= s.length();
if (length > fBuffer.length)
fBuffer= new char[length];
s.getChars(0, length, fBuffer, 0);
return new String(fBuffer, 0, length);
}
private static String[] getProjectList() {
IRubyModel model= RubyCore.create(ResourcesPlugin.getWorkspace().getRoot());
String[] result;
try {
IRubyProject[] projects= model.getRubyProjects();
result= new String[projects.length];
for (int i= 0; i < projects.length; i++) {
result[i]= projects[i].getElementName();
}
} catch (RubyModelException e) {
result= new String[0];
}
// We have to sort the list of project names to make sure that we cut of the longest
// project from the path, if two projects with the same prefix exist. For example
// org.rubypeople.rdt.ui and org.rubypeople.rdt.ui.tests.
Arrays.sort(result, new Comparator() {
public int compare(Object o1, Object o2) {
int l1= ((String)o1).length();
int l2= ((String)o2).length();
if (l1 < l2)
return 1;
if (l2 < l1)
return -1;
return 0;
}
public boolean equals(Object obj) {
return super.equals(obj);
}
});
return result;
}
}