/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.patching.metadata;
import static java.util.Collections.unmodifiableList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jboss.as.patching.Constants;
import org.jboss.as.patching.PatchingException;
import org.jboss.as.patching.logging.PatchLogger;
import org.jboss.as.patching.metadata.Patch.PatchType;
import org.jboss.as.patching.metadata.impl.IdentityImpl;
import org.jboss.as.patching.metadata.impl.PatchElementProviderImpl;
/**
* @author Emanuel Muckenhuber
*/
public class PatchBuilder extends ModificationBuilderTarget<PatchBuilder> implements Builder, PatchMetadataResolver {
protected String patchId;
private String description;
private String link;
private Identity identity;
private PatchType patchType;
private final List<ContentModification> modifications = new ArrayList<ContentModification>();
private List<PatchElementHolder> elements = Collections.emptyList();
private Set<String> elementIds = Collections.emptySet();
public static PatchBuilder create() {
return new PatchBuilder();
}
protected PatchBuilder() {
}
public PatchBuilder setPatchId(String patchId) {
if (!Patch.PATCH_NAME_PATTERN.matcher(patchId).matches()) {
throw PatchLogger.ROOT_LOGGER.illegalPatchName(patchId);
}
this.patchId = patchId;
return this;
}
public PatchBuilder setLink(String link) {
this.link = link;
return this;
}
public PatchBuilder setDescription(String description) {
this.description = description;
return this;
}
public PatchIdentityBuilder upgradeIdentity(final String name, final String version, final String resultingVersion) {
final PatchIdentityBuilder builder = new PatchIdentityBuilder(name, version, PatchType.CUMULATIVE, this);
final IdentityImpl identity = builder.getIdentity();
identity.setResultingVersion(resultingVersion);
this.identity = identity;
this.patchType = PatchType.CUMULATIVE;
return builder;
}
public PatchIdentityBuilder oneOffPatchIdentity(final String name, final String version) {
final PatchIdentityBuilder builder = new PatchIdentityBuilder(name, version, PatchType.ONE_OFF, this);
final IdentityImpl identity = builder.getIdentity();
this.identity = identity;
this.patchType = PatchType.ONE_OFF;
return builder;
}
@Override
protected PatchBuilder internalAddModification(ContentModification modification) {
this.modifications.add(modification);
return this;
}
public PatchElementBuilder upgradeElement(final String patchId, final String layerName, final boolean addOn) {
if (!Patch.PATCH_NAME_PATTERN.matcher(patchId).matches()) {
throw PatchLogger.ROOT_LOGGER.illegalPatchName(patchId);
}
final PatchElementBuilder builder = new PatchElementBuilder(patchId, layerName, addOn, this);
builder.upgrade();
addElement(patchId, builder);
return builder;
}
public PatchElementBuilder oneOffPatchElement(final String patchId, final String layerName, final boolean addOn) {
if (!Patch.PATCH_NAME_PATTERN.matcher(patchId).matches()) {
throw PatchLogger.ROOT_LOGGER.illegalPatchName(patchId);
}
final PatchElementBuilder builder = new PatchElementBuilder(patchId, layerName, addOn, this);
builder.oneOffPatch();
addElement(patchId, builder);
return builder;
}
public PatchElementBuilder addElement(final String patchId, final String layerName, final boolean addOn) {
if (!Patch.PATCH_NAME_PATTERN.matcher(patchId).matches()) {
throw PatchLogger.ROOT_LOGGER.illegalPatchName(patchId);
}
final PatchElementBuilder builder = new PatchElementBuilder(patchId, layerName, addOn, this);
//builder.cumulativePatch();
addElement(patchId, builder);
return builder;
}
public PatchBuilder addElement(final PatchElement element) {
addElement(element.getId(), new PatchElementHolder() {
@Override
public PatchElement createElement(PatchType patchType) {
final PatchType type = element.getProvider().getPatchType();
if (type == null) {
if (patchType == PatchType.CUMULATIVE) {
((PatchElementProviderImpl)element.getProvider()).upgrade();
} else {
((PatchElementProviderImpl)element.getProvider()).oneOffPatch();
}
} else if (patchType != PatchBuilder.this.patchType) {
throw PatchLogger.ROOT_LOGGER.patchTypesDontMatch();
}
return element;
}
});
return this;
}
protected void addElement(String id, PatchElementHolder element) {
switch(elements.size()) {
case 0:
elements = Collections.singletonList(element);
elementIds = Collections.singleton(id);
break;
case 1:
elements = new ArrayList<PatchElementHolder>(elements);
elementIds = new HashSet<String>(elementIds);
default:
elements.add(element);
if(!id.equals(Constants.BASE) && !elementIds.add(id)) {
throw PatchLogger.ROOT_LOGGER.duplicateElementPatchId(id);
}
}
}
public List<ContentModification> getModifications() {
return modifications;
}
@Override
public Patch resolvePatch(String name, String version) throws PatchingException {
return build();
}
@Override
public Patch build() {
assert notNull(identity);
assert notNull(patchId);
// Create the elements
final List<PatchElement> elements = new ArrayList<PatchElement>();
for (final PatchElementHolder holder : this.elements) {
elements.add(holder.createElement(patchType));
}
return new PatchImpl(patchId, description, link, identity, unmodifiableList(elements), unmodifiableList(modifications));
}
@Override
protected PatchBuilder returnThis() {
return this;
}
static boolean notNull(Object o) {
return o != null;
}
protected interface PatchElementHolder {
PatchElement createElement(final PatchType type);
}
}