/*******************************************************************************
* Copyright (c) Jun 27, 2011 Zend Technologies Ltd.
* 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
*******************************************************************************/
package org.zend.sdklib.internal.mapping;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.zend.sdklib.mapping.IMapping;
import org.zend.sdklib.mapping.IMappingChangeEvent;
import org.zend.sdklib.mapping.IMappingChangeEvent.Kind;
import org.zend.sdklib.mapping.IMappingChangeListener;
import org.zend.sdklib.mapping.IMappingEntry;
import org.zend.sdklib.mapping.IMappingEntry.Type;
import org.zend.sdklib.mapping.IMappingLoader;
import org.zend.sdklib.mapping.IMappingModel;
import org.zend.sdklib.mapping.MappingModelFactory;
/**
* Default implementation of {@link IMappingModel}.
*
* @author Wojciech Galanciak, 2011
*
*/
public class MappingModel implements IMappingModel {
private List<IMappingEntry> entries;
private List<IMapping> defaultExclusion;
private List<IMappingChangeListener> listeners;
private IMappingLoader loader;
private File mappingFile;
private boolean isLoaded;
public MappingModel(IMappingLoader loader, File mappingFile)
throws IOException {
this.loader = loader;
this.mappingFile = mappingFile;
this.listeners = new ArrayList<IMappingChangeListener>();
this.isLoaded = mappingFile.exists();
this.entries = mappingFile.exists() ? loader.load(new FileInputStream(mappingFile))
: loader.load(null);
this.defaultExclusion = loader.getDefaultExclusion();
}
public MappingModel(File mappingFile) throws IOException {
this(new DefaultMappingLoader(), mappingFile);
}
/*
* (non-Javadoc)
*
* @see
* org.zend.sdklib.mapping.IMappingModel#addEntry(org.zend.sdklib.mapping
* .IMappingEntry)
*/
@Override
public boolean addEntry(IMappingEntry toAdd) {
if (toAdd == null || entries.contains(toAdd)) {
return false;
}
entries.add(toAdd);
modelChanged(new MappingChangeEvent(Kind.ADD_ENTRY, toAdd));
return true;
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#removeEntry(java.lang.String)
*/
@Override
public boolean removeEntry(String folder, Type type) {
for (IMappingEntry entry : entries) {
if (entry.getFolder().equals(folder) && entry.getType() == type) {
entries.remove(entry);
modelChanged(new MappingChangeEvent(Kind.REMOVE_ENTRY, entry));
return true;
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#addMapping(java.lang.String,
* org.zend.sdklib.mapping.IMapping)
*/
@Override
public boolean addMapping(String folder, Type type, String path, boolean isGlobal) {
if (folder == null || path == null) {
return false;
}
IMapping toAdd = new Mapping(path, isGlobal);
for (IMappingEntry entry : entries) {
if (entry.getFolder().equals(folder) && entry.getType() == type) {
List<IMapping> mappings = entry.getMappings();
for (IMapping mapping : mappings) {
if (mapping.equals(toAdd)) {
return false;
}
String exisitngPath = mapping.getPath();
if (path.startsWith(mapping.getPath())) {
if (exisitngPath.endsWith("/")) {
return false;
} else {
String subPath = path.substring(exisitngPath
.length());
if (subPath.length() > 0 && subPath.startsWith("/")) {
return false;
}
}
}
}
if (entry.getMappings().add(toAdd)) {
modelChanged(new MappingChangeEvent(Kind.ADD_MAPPING, entry));
return true;
} else {
return false;
}
}
}
List<IMapping> mappings = new ArrayList<IMapping>();
mappings.add(toAdd);
return addEntry(new MappingEntry(folder, mappings, type));
}
/*
* (non-Javadoc)
*
* @see
* org.zend.sdklib.mapping.IMappingModel#removeMapping(java.lang.String,
* java.lang.String)
*/
@Override
public boolean removeMapping(String folder, Type type, String path) {
if (folder == null || path == null) {
return false;
}
for (IMappingEntry entry : entries) {
if (entry.getFolder().equals(folder) && entry.getType() == type) {
List<IMapping> mappings = entry.getMappings();
for (IMapping mapping : mappings) {
if (mapping.getPath().equals(path)) {
if (mappings.remove(mapping)) {
if (mappings.size() == 0) {
return removeEntry(folder, type);
} else {
modelChanged(new MappingChangeEvent(Kind.REMOVE_MAPPING, entry));
return true;
}
} else {
return false;
}
}
}
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see
* org.zend.sdklib.mapping.IMappingModel#modifyMapping(java.lang.String,
* org.zend.sdklib.mapping.IMapping)
*/
@Override
public boolean modifyMapping(String folder, Type type, IMapping toModify) {
if (folder == null || toModify == null) {
return false;
}
for (IMappingEntry entry : entries) {
if (entry.getFolder().equals(folder) && entry.getType() == type) {
List<IMapping> mappings = entry.getMappings();
for (IMapping mapping : mappings) {
if (mapping.getPath().equals(toModify.getPath())) {
mapping.setGlobal(toModify.isGlobal());
modelChanged(new MappingChangeEvent(
Kind.MODIFY_MAPPING, entry));
return true;
}
}
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#getEntry(java.lang.String,
* org.zend.sdklib.mapping.IMappingEntry.Type)
*/
@Override
public IMappingEntry getEntry(String folder, Type type) {
for (IMappingEntry entry : entries) {
if (entry.getFolder().equals(folder) && entry.getType() == type) {
return entry;
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#getEnties()
*/
@Override
public List<IMappingEntry> getEnties() {
return entries;
}
@Override
public List<IMappingEntry> getEnties(Type type, String tag) {
List<IMappingEntry> result = new ArrayList<IMappingEntry>(entries.size());
for (IMappingEntry entry : entries) {
if (entry.getType() == type
&& entry.getFolder().equals(tag)) {
result.add(entry);
}
}
return result;
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#persist()
*/
@Override
public void store() throws IOException {
loader.store(this, new File(mappingFile.getParentFile(),
MappingModelFactory.DEPLOYMENT_PROPERTIES));
modelChanged(new MappingChangeEvent(Kind.STORE, null));
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#isExcluded(java.lang.String,
* java.lang.String)
*/
@Override
public boolean isExcluded(String folder, String path) throws IOException {
if (path != null && folder != null) {
if (isInternalExcluded(path, defaultExclusion)) {
return true;
}
IMappingEntry entry = getEntry(folder, Type.EXCLUDE);
if (entry != null) {
return isInternalExcluded(path, entry.getMappings());
}
}
return false;
}
@Override
public boolean isLoaded() {
return isLoaded;
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#load(java.io.InputStream,
* java.io.File)
*/
@Override
public void load(InputStream stream, File mappingFile) throws IOException {
this.mappingFile = mappingFile;
this.isLoaded = mappingFile != null && mappingFile.exists();
this.entries = isLoaded ? loader.load(new FileInputStream(mappingFile))
: loader.load(null);
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#load(java.io.InputStream)
*/
@Override
public void load(InputStream stream) throws IOException {
this.entries = loader.load(stream);
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#getFolders()
*/
@Override
public List<String> getFolders() {
List<String> result = new ArrayList<String>();
for (IMappingEntry entry : entries) {
String folder = entry.getFolder();
if (!result.contains(folder)) {
result.add(entry.getFolder());
}
}
return result;
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#getFolder(java.lang.String)
*/
@Override
public String[] getFolders(String path) throws IOException {
List<String> result = new ArrayList<String>();
for (IMappingEntry entry : entries) {
if (entry.getType() == Type.INCLUDE) {
if (isExcluded(entry.getFolder(), path)) {
continue;
}
List<IMapping> mappings = entry.getMappings();
path = new File(path).toString();
for (IMapping include : mappings) {
if (include.isGlobal()) {
String fileName = path.substring(path
.lastIndexOf(File.separator) + 1);
if (include.getPath().equals(fileName)) {
result.add(entry.getFolder());
continue;
}
} else {
File pathFile = new File(path);
if (pathFile.isAbsolute()) {
File includeFile = new File(mappingFile.getParentFile(), include.getPath());
if (pathFile.getCanonicalPath().startsWith(
includeFile.getCanonicalPath())) {
result.add(entry.getFolder());
}
}
if (include.getPath().equals(path)) {
result.add(entry.getFolder());
continue;
} else {
int index = path.lastIndexOf(File.separator);
if (index > -1) {
String fileName = path.substring(0,
path.lastIndexOf(File.separator));
if (include.getPath().equals(fileName)) {
result.add(entry.getFolder());
continue;
}
}
}
}
}
}
}
return result.toArray(new String[0]);
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#getPath(java.lang.String)
*/
@Override
public String getPath(String name) throws IOException {
for (IMappingEntry entry : entries) {
if (entry.getType() == Type.INCLUDE) {
List<IMapping> mappings = entry.getMappings();
for (IMapping include : mappings) {
File includeFile = new File(mappingFile.getParentFile(), include.getPath());
if (includeFile.isDirectory()) {
File[] members = includeFile.listFiles();
for (File member : members) {
String result = findFileInDirectory(member, name, entry.getFolder());
if (result != null) {
return result;
}
}
} else {
if (includeFile.getName().equals(name)) {
String result = includeFile.getCanonicalPath();
if (!isExcluded(entry.getFolder(), result)) {
return result;
}
}
}
}
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see
* org.zend.sdklib.mapping.IMappingModel#getPackagePath(java.lang.String)
*/
@Override
public String getPackagePath(String folder, String path) throws IOException {
for (IMappingEntry entry : entries) {
if (entry.getFolder().equals(folder) && entry.getType() == Type.INCLUDE) {
List<IMapping> mappings = entry.getMappings();
for (IMapping include : mappings) {
if (isExcluded(entry.getFolder(),
new File(mappingFile.getParentFile(), path).getCanonicalPath())) {
continue;
}
String includePath = new File(include.getPath()).getPath();
path = new File(path).getPath();
if (includePath.equals(path)) {
return new File(entry.getFolder(), path).getPath();
} else {
String fileName = path;
while (fileName != null && fileName.length() > 0) {
int index = fileName.lastIndexOf(File.separator);
fileName = index != -1 ? fileName.substring(0,
index) : "";
if (includePath.equals(fileName)) {
return new File(entry.getFolder(), path)
.getPath();
}
}
}
}
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see
* org.zend.sdklib.mapping.IMappingModel#addMappingChangeListener(org.zend
* .sdklib.mapping.IMappingChangeListener)
*/
@Override
public void addMappingChangeListener(IMappingChangeListener listener) {
listeners.add(listener);
}
/*
* (non-Javadoc)
*
* @see
* org.zend.sdklib.mapping.IMappingModel#removeMappingChangeListener(org
* .zend.sdklib.mapping.IMappingChangeListener)
*/
@Override
public void removeMappingChangeListener(IMappingChangeListener listener) {
listeners.remove(listener);
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.mapping.IMappingModel#getDefaultExclusion()
*/
@Override
public List<IMapping> getDefaultExclusion() {
return defaultExclusion;
}
protected void modelChanged(IMappingChangeEvent event) {
for (IMappingChangeListener listener : listeners) {
listener.mappingChanged(event);
}
}
private boolean isInternalExcluded(String path, List<IMapping> mappings)
throws IOException {
for (IMapping mapping : mappings) {
if (mapping.isGlobal()) {
int index = path.lastIndexOf("/");
if (index == -1) {
index = path.lastIndexOf("\\");
}
String fileName = path.substring(index + 1);
if (mapping.getPath().equals(fileName)) {
return true;
}
} else {
String fullPath = new File(mappingFile.getParentFile(), mapping.getPath())
.getCanonicalPath();
if (fullPath.equals(path)) {
return true;
}
}
}
return false;
}
private String findFileInDirectory(File file, String name, String folder) throws IOException {
String result = null;
if (!isExcluded(folder, file.getCanonicalPath())) {
if (file.isDirectory()) {
File[] members = file.listFiles();
for (File member : members) {
result = findFileInDirectory(member, name, folder);
if (result != null) {
return result;
}
}
} else {
if (file.getName().equals(name)) {
result = file.getPath();
}
}
}
return result;
}
@Override
public IMappingLoader getLoader() {
return loader;
}
public File getMappingFile() {
return mappingFile;
}
}