blob: d689514ad21e4a39ac6c60a4f81ee0369eaf5d93 [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* 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 org.jetbrains.jps.model.serialization.artifact;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import com.intellij.util.xmlb.XmlSerializer;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.*;
import org.jetbrains.jps.model.artifact.*;
import org.jetbrains.jps.model.artifact.elements.*;
import org.jetbrains.jps.model.library.JpsLibraryReference;
import org.jetbrains.jps.model.module.JpsModuleReference;
import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
import java.util.List;
/**
* @author nik
*/
public class JpsArtifactSerializer {
private static JpsPackagingElementSerializer<?>[] STANDARD_SERIALIZERS = {
new ArtifactRootElementSerializer(),
new DirectoryElementSerializer(),
new ArchiveElementSerializer(),
new FileCopyElementSerializer(),
new DirectoryCopyElementSerializer(),
new ExtractedDirectoryElementSerializer(),
new LibraryFilesElementSerializer(),
new ArtifactOutputElementSerializer()
};
private static final JpsArtifactPropertiesSerializer<?>[] STANDARD_TYPE_SERIALIZERS = {
new JpsArtifactDummyPropertiesSerializer("plain", DirectoryArtifactType.INSTANCE),
new JpsArtifactDummyPropertiesSerializer("jar", JarArtifactType.INSTANCE)
};
private static final String ELEMENT_TAG = "element";
private static final String ID_ATTRIBUTE = "id";
private static final SkipDefaultValuesSerializationFilters SERIALIZATION_FILTERS = new SkipDefaultValuesSerializationFilters();
public static void loadArtifacts(@NotNull JpsProject project, @Nullable Element componentElement) {
JpsArtifactService service = JpsArtifactService.getInstance();
for (Element artifactElement : JDOMUtil.getChildren(componentElement, "artifact")) {
ArtifactState state = XmlSerializer.deserialize(artifactElement, ArtifactState.class);
if (state == null) continue;
JpsArtifactPropertiesSerializer<?> serializer = getTypePropertiesSerializer(state.getArtifactType());
loadArtifact(project, service, state, serializer);
}
}
private static <P extends JpsElement> void loadArtifact(JpsProject project, JpsArtifactService service, ArtifactState state, JpsArtifactPropertiesSerializer<P> serializer) {
JpsPackagingElement rootElement = loadPackagingElement(state.getRootElement());
if (rootElement != null) {
List<ArtifactPropertiesState> propertiesList = state.getPropertiesList();
JpsArtifact artifact = service.addArtifact(project, state.getName(), (JpsCompositePackagingElement)rootElement,
serializer.getType(), serializer.loadProperties(propertiesList));
artifact.setBuildOnMake(state.isBuildOnMake());
artifact.setOutputPath(state.getOutputPath());
for (ArtifactPropertiesState propertiesState : propertiesList) {
JpsArtifactExtensionSerializer<?> extensionSerializer = getExtensionSerializer(propertiesState.getId());
if (extensionSerializer != null) {
loadExtension(extensionSerializer, artifact, propertiesState.getOptions());
}
}
}
}
public static void saveArtifact(@NotNull JpsArtifact artifact, Element componentElement) {
ArtifactState state = new ArtifactState();
state.setName(artifact.getName());
state.setBuildOnMake(artifact.isBuildOnMake());
state.setOutputPath(artifact.getOutputPath());
JpsArtifactPropertiesSerializer<?> serializer = getTypePropertiesSerializer(artifact.getArtifactType());
doSaveArtifact(artifact, componentElement, state, serializer);
}
private static <P extends JpsElement> void doSaveArtifact(JpsArtifact artifact, Element componentElement, ArtifactState state,
JpsArtifactPropertiesSerializer<P> serializer) {
state.setArtifactType(serializer.getTypeId());
state.setRootElement(savePackagingElement(artifact.getRootElement()));
List<ArtifactPropertiesState> propertiesList = state.getPropertiesList();
//noinspection unchecked
serializer.saveProperties((P)artifact.getProperties(), propertiesList);
for (JpsModelSerializerExtension serializerExtension : JpsModelSerializerExtension.getExtensions()) {
for (JpsArtifactExtensionSerializer<?> extensionSerializer : serializerExtension.getArtifactExtensionSerializers()) {
JpsElement extension = artifact.getContainer().getChild(extensionSerializer.getRole());
if (extension != null) {
ArtifactPropertiesState propertiesState = new ArtifactPropertiesState();
propertiesState.setId(extensionSerializer.getId());
propertiesState.setOptions(saveExtension(extensionSerializer, extension));
propertiesList.add(propertiesState);
}
}
}
componentElement.addContent(XmlSerializer.serialize(state, SERIALIZATION_FILTERS));
}
private static <E extends JpsElement> void loadExtension(JpsArtifactExtensionSerializer<E> serializer,
JpsArtifact artifact,
Element options) {
E e = serializer.loadExtension(options);
artifact.getContainer().setChild(serializer.getRole(), e);
}
private static <E extends JpsElement> Element saveExtension(JpsArtifactExtensionSerializer<?> serializer,
E extension) {
Element optionsTag = new Element("options");
//noinspection unchecked
((JpsArtifactExtensionSerializer<E>)serializer).saveExtension(extension, optionsTag);
return optionsTag;
}
private static <P extends JpsPackagingElement> Element savePackagingElement(P element) {
//noinspection unchecked
JpsPackagingElementSerializer<P> serializer = findElementSerializer((Class<P>)element.getClass());
Element tag = new Element(ELEMENT_TAG).setAttribute(ID_ATTRIBUTE, serializer.getTypeId());
serializer.save(element, tag);
if (element instanceof JpsCompositePackagingElement) {
for (JpsPackagingElement child : ((JpsCompositePackagingElement)element).getChildren()) {
tag.addContent(savePackagingElement(child));
}
}
return tag;
}
@Nullable
private static JpsPackagingElement loadPackagingElement(Element element) {
JpsPackagingElement packagingElement = createPackagingElement(element);
if (packagingElement instanceof JpsCompositePackagingElement) {
for (Element childElement : JDOMUtil.getChildren(element, ELEMENT_TAG)) {
JpsPackagingElement child = loadPackagingElement(childElement);
if (child != null) {
((JpsCompositePackagingElement)packagingElement).addChild(child);
}
}
}
return packagingElement;
}
@Nullable
private static JpsPackagingElement createPackagingElement(Element element) {
String typeId = element.getAttributeValue(ID_ATTRIBUTE);
JpsPackagingElementSerializer<?> serializer = findElementSerializer(typeId);
if (serializer != null) {
return serializer.load(element);
}
return null;
}
@Nullable
private static JpsPackagingElementSerializer<?> findElementSerializer(@NotNull String typeId) {
for (JpsPackagingElementSerializer<?> serializer : STANDARD_SERIALIZERS) {
if (serializer.getTypeId().equals(typeId)) {
return serializer;
}
}
for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
for (JpsPackagingElementSerializer<?> serializer : extension.getPackagingElementSerializers()) {
if (serializer.getTypeId().equals(typeId)) {
return serializer;
}
}
}
return null;
}
@NotNull
private static <E extends JpsPackagingElement> JpsPackagingElementSerializer<E> findElementSerializer(@NotNull Class<E> elementClass) {
for (JpsPackagingElementSerializer<?> serializer : STANDARD_SERIALIZERS) {
if (serializer.getElementClass().isAssignableFrom(elementClass)) {
//noinspection unchecked
return (JpsPackagingElementSerializer<E>)serializer;
}
}
for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
for (JpsPackagingElementSerializer<?> serializer : extension.getPackagingElementSerializers()) {
if (serializer.getElementClass().isAssignableFrom(elementClass)) {
//noinspection unchecked
return (JpsPackagingElementSerializer<E>)serializer;
}
}
}
throw new IllegalArgumentException("Serializer not found for " + elementClass);
}
@Nullable
private static JpsArtifactExtensionSerializer<?> getExtensionSerializer(String id) {
for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
for (JpsArtifactExtensionSerializer<?> serializer : extension.getArtifactExtensionSerializers()) {
if (serializer.getId().equals(id)) {
return serializer;
}
}
}
return null;
}
private static JpsArtifactPropertiesSerializer<?> getTypePropertiesSerializer(String typeId) {
for (JpsArtifactPropertiesSerializer serializer : STANDARD_TYPE_SERIALIZERS) {
if (serializer.getTypeId().equals(typeId)) {
return serializer;
}
}
for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
for (JpsArtifactPropertiesSerializer serializer : extension.getArtifactTypePropertiesSerializers()) {
if (serializer.getTypeId().equals(typeId)) {
return serializer;
}
}
}
return STANDARD_TYPE_SERIALIZERS[0];
}
private static JpsArtifactPropertiesSerializer<?> getTypePropertiesSerializer(JpsArtifactType type) {
for (JpsArtifactPropertiesSerializer serializer : STANDARD_TYPE_SERIALIZERS) {
if (serializer.getType().equals(type)) {
return serializer;
}
}
for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
for (JpsArtifactPropertiesSerializer serializer : extension.getArtifactTypePropertiesSerializers()) {
if (serializer.getType().equals(type)) {
return serializer;
}
}
}
return null;
}
private static class ArtifactRootElementSerializer extends JpsPackagingElementSerializer<JpsArtifactRootElement> {
public ArtifactRootElementSerializer() {
super("root", JpsArtifactRootElement.class);
}
@Override
public JpsArtifactRootElement load(Element element) {
return JpsPackagingElementFactory.getInstance().createArtifactRoot();
}
@Override
public void save(JpsArtifactRootElement element, Element tag) {
}
}
private static class DirectoryElementSerializer extends JpsPackagingElementSerializer<JpsDirectoryPackagingElement> {
public DirectoryElementSerializer() {
super("directory", JpsDirectoryPackagingElement.class);
}
@Override
public JpsDirectoryPackagingElement load(Element element) {
return JpsPackagingElementFactory.getInstance().createDirectory(element.getAttributeValue("name"));
}
@Override
public void save(JpsDirectoryPackagingElement element, Element tag) {
tag.setAttribute("name", element.getDirectoryName());
}
}
private static class ArchiveElementSerializer extends JpsPackagingElementSerializer<JpsArchivePackagingElement> {
public ArchiveElementSerializer() {
super("archive", JpsArchivePackagingElement.class);
}
@Override
public JpsArchivePackagingElement load(Element element) {
return JpsPackagingElementFactory.getInstance().createArchive(element.getAttributeValue("name"));
}
@Override
public void save(JpsArchivePackagingElement element, Element tag) {
tag.setAttribute("name", element.getArchiveName());
}
}
private static class FileCopyElementSerializer extends JpsPackagingElementSerializer<JpsFileCopyPackagingElement> {
public FileCopyElementSerializer() {
super("file-copy", JpsFileCopyPackagingElement.class);
}
@Override
public JpsFileCopyPackagingElement load(Element element) {
return JpsPackagingElementFactory.getInstance().createFileCopy(element.getAttributeValue("path"),
element.getAttributeValue("output-file-name"));
}
@Override
public void save(JpsFileCopyPackagingElement element, Element tag) {
tag.setAttribute("path", element.getFilePath());
String outputFileName = element.getRenamedOutputFileName();
if (outputFileName != null) {
tag.setAttribute("output-path-name", outputFileName);
}
}
}
private static class DirectoryCopyElementSerializer extends JpsPackagingElementSerializer<JpsDirectoryCopyPackagingElement> {
public DirectoryCopyElementSerializer() {
super("dir-copy", JpsDirectoryCopyPackagingElement.class);
}
@Override
public JpsDirectoryCopyPackagingElement load(Element element) {
return JpsPackagingElementFactory.getInstance().createDirectoryCopy(element.getAttributeValue("path"));
}
@Override
public void save(JpsDirectoryCopyPackagingElement element, Element tag) {
tag.setAttribute("path", element.getDirectoryPath());
}
}
private static class ExtractedDirectoryElementSerializer
extends JpsPackagingElementSerializer<JpsExtractedDirectoryPackagingElement> {
public ExtractedDirectoryElementSerializer() {
super("extracted-dir", JpsExtractedDirectoryPackagingElement.class);
}
@Override
public JpsExtractedDirectoryPackagingElement load(Element element) {
return JpsPackagingElementFactory.getInstance().createExtractedDirectory(element.getAttributeValue("path"),
element.getAttributeValue("path-in-jar"));
}
@Override
public void save(JpsExtractedDirectoryPackagingElement element, Element tag) {
tag.setAttribute("path", element.getFilePath());
tag.setAttribute("path-in-jar", element.getPathInJar());
}
}
private static class LibraryFilesElementSerializer extends JpsPackagingElementSerializer<JpsLibraryFilesPackagingElement> {
public LibraryFilesElementSerializer() {
super("library", JpsLibraryFilesPackagingElement.class);
}
@Override
public JpsLibraryFilesPackagingElement load(Element element) {
String level = element.getAttributeValue("level");
String libraryName = element.getAttributeValue("name");
String moduleName = element.getAttributeValue("module-name");
JpsElementReference<? extends JpsCompositeElement> parentReference;
if (moduleName != null) {
parentReference = JpsElementFactory.getInstance().createModuleReference(moduleName);
}
else {
parentReference = JpsLibraryTableSerializer.createLibraryTableReference(level);
}
return JpsPackagingElementFactory.getInstance()
.createLibraryElement(JpsElementFactory.getInstance().createLibraryReference(libraryName, parentReference));
}
@Override
public void save(JpsLibraryFilesPackagingElement element, Element tag) {
JpsLibraryReference reference = element.getLibraryReference();
JpsElementReference<? extends JpsCompositeElement> parentReference = reference.getParentReference();
tag.setAttribute("level", JpsLibraryTableSerializer.getLevelId(parentReference));
tag.setAttribute("name", reference.getLibraryName());
if (parentReference instanceof JpsModuleReference) {
tag.setAttribute("module-name", ((JpsModuleReference)parentReference).getModuleName());
}
}
}
private static class ArtifactOutputElementSerializer extends JpsPackagingElementSerializer<JpsArtifactOutputPackagingElement> {
public ArtifactOutputElementSerializer() {
super("artifact", JpsArtifactOutputPackagingElement.class);
}
@Override
public JpsArtifactOutputPackagingElement load(Element element) {
return JpsPackagingElementFactory.getInstance()
.createArtifactOutput(JpsArtifactService.getInstance().createReference(element.getAttributeValue("artifact-name")));
}
@Override
public void save(JpsArtifactOutputPackagingElement element, Element tag) {
tag.setAttribute("artifact-name", element.getArtifactReference().getArtifactName());
}
}
}