/**
* Copyright (C) 2015 Collaborne B.V. (opensource@collaborne.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.collaborne.jsonschema.generator;
import java.net.URI;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.collaborne.jsonschema.generator.model.Mapping;
import com.github.fge.jackson.jsonpointer.JsonPointer;
import com.github.fge.jackson.jsonpointer.JsonPointerException;
import com.github.fge.jsonschema.core.load.SchemaLoader;
public abstract class AbstractGenerator implements Generator {
private final Logger logger = LoggerFactory.getLogger(AbstractGenerator.class);
private final Map<String, Object> features = new HashMap<>();
private Map<URI, Mapping> mappings = new HashMap<>();
private Map<URI, String> defaultPackageNames = new HashMap<>();
private Path outputDirectory;
private SchemaLoader schemaLoader;
@Override
public <T>T getFeature(Feature<T> feature) {
return feature.get(features);
}
@Override
public <T>T setFeature(Feature<T> feature, T value) {
return feature.set(features, value);
}
@Override
public void addMapping(URI type, Mapping mapping) {
if (!type.isAbsolute()) {
logger.warn("{}: Adding mapping for non-absolute type", type);
}
mappings.put(type, mapping);
}
@Override
public void addDefaultPackageName(URI baseUri, String packageName) {
URI packageUri;
if (baseUri.getFragment() == null) {
packageUri = baseUri.resolve("#");
} else {
packageUri = baseUri;
}
defaultPackageNames.put(packageUri, packageName);
}
/**
* Get the default package name for the given type.
*
* @param type
* @return
*/
public String getDefaultPackageName(URI type) {
URI searchUri;
if (type.getFragment() == null) {
searchUri = type.resolve("#");
} else {
searchUri = type;
}
String defaultPackageName = defaultPackageNames.get(searchUri);
while (defaultPackageName == null && !(searchUri.getFragment().isEmpty() && (searchUri.getPath().isEmpty() || "/".equals(searchUri.getPath())))) {
try {
if (!searchUri.getFragment().isEmpty()) {
JsonPointer pointer = new JsonPointer(searchUri.getFragment());
searchUri = searchUri.resolve("#" + pointer.parent().toString());
} else {
String path = searchUri.getPath();
int lastSlashIndex = path.lastIndexOf('/');
searchUri = searchUri.resolve(path.substring(0, lastSlashIndex)).resolve("#" + searchUri.getFragment());
}
defaultPackageName = defaultPackageNames.get(searchUri);
} catch (JsonPointerException e) {
// Assuming that the type was valid before we shouldn't end up here.
// However, that's just half the truth: it is possible to ask for a type with an URI that has a fragment that
// cannot be interpreted as a JsonPointer (which starts with '/').
throw new IllegalArgumentException("Cannot construct JSON pointer", e);
}
}
if (defaultPackageName == null) {
defaultPackageName = getFeature(FEATURE_DEFAULT_PACKAGE_NAME);
logger.warn("{}: Using package name {}", type, defaultPackageName);
}
return defaultPackageName;
}
protected Path getOutputDirectory() {
return outputDirectory;
}
@Override
public void setOutputDirectory(Path outputDirectory) {
this.outputDirectory = outputDirectory;
}
@Override
public void setSchemaLoader(SchemaLoader schemaLoader) {
this.schemaLoader = schemaLoader;
}
protected SchemaLoader getSchemaLoader() {
return schemaLoader;
}
/**
* Get an existing mapping for the given {@code type}.
*
* If no mapping is known for this type, {@code null} is returned.
*
* @param type
* @return
*/
protected Mapping getMapping(URI type) {
return mappings.get(type);
}
}