All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.marvelution.jira.plugins.sonar.services.layout.SonarPanelLayoutManagerService Maven / Gradle / Ivy

/*
 * Licensed to Marvelution under one or more contributor license 
 * agreements.  See the NOTICE file distributed with this work 
 * for additional information regarding copyright ownership.
 * Marvelution licenses this file to you 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.marvelution.jira.plugins.sonar.services.layout;

import static com.google.common.base.Preconditions.checkNotNull;

import java.io.IOException;
import java.util.Properties;

import net.java.ao.DBParam;
import net.java.ao.Query;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.activeobjects.tx.Transactional;
import com.marvelution.jira.plugins.sonar.services.layout.Layout.Context;
import com.marvelution.jira.plugins.sonar.services.layout.Layout.Type;
import com.marvelution.jira.plugins.sonar.upgrade.activeobjects.SonarGadgetsActiveObjectsValidator;

/**
 * Default {@link SonarPanelLayoutManager} implementation
 * 
 * @author Mark Rekveld
 */
@Transactional
public class SonarPanelLayoutManagerService implements SonarPanelLayoutManager {

	private static final Logger LOGGER = Logger.getLogger(SonarPanelLayoutManagerService.class);
	private static final Properties LAYOUT_DEFAULT = new Properties();

	private final ActiveObjects objects;
	private final SonarGadgetsActiveObjectsValidator gadgetsValidator;
	private boolean initialCheck = true; 

	/**
	 * Constructor
	 *
	 * @param objects the {@link ActiveObjects} implementation
	 */
	public SonarPanelLayoutManagerService(ActiveObjects objects, SonarGadgetsActiveObjectsValidator gadgetsValidator) {
		this.objects = checkNotNull(objects, "activeObjects");
		this.gadgetsValidator = checkNotNull(gadgetsValidator, "gadgetsValidator");
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Gadget[] getGadgets() {
		if (initialCheck) {
			gadgetsValidator.upgrade(null, objects);
			initialCheck = false;
		}
		return objects.find(Gadget.class);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Gadget getGadget(String shortName) {
		Gadget[] gadgets = objects.find(Gadget.class, Query.select().where("SHORT_NAME = ?", shortName).limit(1));
		if (gadgets != null && gadgets.length == 1) {
			return gadgets[0];
		}
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean addGadgetToColumn(Gadget gadget, Integer columnId) {
		return addGadgetToColumn(gadget, columnId, -1);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean addGadgetToColumn(Gadget gadget, Integer columnId, int position) {
		return addGadgetToColumn(gadget, objects.get(Column.class, columnId), position);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean addGadgetToColumn(Gadget gadget, Column column) {
		return addGadgetToColumn(gadget, column, -1);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean addGadgetToColumn(Gadget gadget, Column column, int position) {
		checkNotNull(gadget, "Gadget may not be null");
		checkNotNull(column, "Column may not be null");
		if (position == -1) {
			ColumnToGadget relation = objects.create(ColumnToGadget.class, new DBParam("COLUMN_ID", column.getID()),
				new DBParam("GADGET_ID", gadget.getID()));
			relation.save();
		} else {
			ColumnToGadget[] relations = objects.find(ColumnToGadget.class,
				Query.select().where("COLUMN_ID = ?", column.getID()));
			// Create the new relation
			ColumnToGadget relation = objects.create(ColumnToGadget.class, new DBParam("COLUMN_ID", column.getID()),
				new DBParam("GADGET_ID", gadget.getID()));
			relation.save();
			if (relations != null && relations.length >= position) {
				for (int index = position; index < relations.length; index++) {
					ColumnToGadget recreate = relations[index];
					ColumnToGadget recreation = objects.create(ColumnToGadget.class,
						new DBParam("COLUMN_ID", column.getID()),
						new DBParam("GADGET_ID", recreate.getGadget().getID()));
					recreation.save();
					objects.delete(recreate);
				}
			}
		}
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean removeGadgetFromColumn(Gadget gadget, Integer columnId) {
		return removeGadgetFromColumn(gadget, objects.get(Column.class, columnId));
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean removeGadgetFromColumn(Gadget gadget, Column column) {
		checkNotNull(gadget, "Gadget may not be null");
		checkNotNull(column, "Column may not be null");
		objects.delete(objects.find(ColumnToGadget.class,
			Query.select().where("COLUMN_ID = ? AND GADGET_ID = ?", column.getID(), gadget.getID())));
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean removeAllGadgetsFromColumn(Column column) {
		checkNotNull(column, "Column may not be null");
		objects.delete(objects.find(ColumnToGadget.class, Query.select().where("COLUMN_ID = ?", column.getID())));
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Layout createLayout(Layout.Type type, Long contextID) {
		if (objects.count(Layout.class,
			Query.select().where("CONTEXT = ? AND CONTEXT_ID = ?", Layout.Context.PROJECT, contextID)) == 0) {
			return createLayout(type, Layout.Context.PROJECT, contextID);
		} else {
			LOGGER.debug("Looks like there is already a Layout for ContextID " + contextID + " return that layout");
			return getLayout(contextID);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Layout changeLayoutType(Layout layout, Type newType) {
		checkNotNull(layout, "layout cannot be null");
		checkNotNull(newType, "newType cannot be null");
		if (!layout.getType().equals(newType)) {
			LOGGER.debug("Updating Layout " + layout.getID() + " to type " + newType);
			Column[] columns = layout.getColumns();
			int index = 0;
			while (index < columns.length) {
				LOGGER.debug("Checking column " + columns[index].getID());
				if (index < newType.columns.length) {
					LOGGER.debug("Updating cloumn " + columns[index].getID() + " to type " + newType.columns[index]);
					Column column = columns[index];
					column.setType(newType.columns[index]);
					column.save();
				} else {
					LOGGER.debug("Deleting unneeded column " + columns[index]);
					deleteColumn(columns[index]);
				}
				index++;
			}
			// Loop through all the columns to make sure they are there
			while (index < newType.columns.length) {
				LOGGER.debug("Creating missing column of type " + newType.columns[index]);
				createColumn(layout, newType.columns[index]);
				index++;
			}
			layout.setType(newType);
			layout.save();
		}
		return layout;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean removeLayout(Layout layout) {
		checkNotNull(layout, "layout cannot be null");
		if (layout.getContext().equals(Layout.Context.SYSTEM)) {
			throw new IllegalStateException("The SYSTEM layout cannot be deleted!");
		}
		LOGGER.debug("Deleting Layout " + layout.getID() + " for context " + layout.getContext() + " "
			+ layout.getContextID());
		for (Column column : layout.getColumns()) {
			deleteColumn(column);
		}
		objects.delete(layout);
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Layout getSystemLayout() {
		Layout[] layouts = objects.find(Layout.class, Query.select().where("CONTEXT = ?", Layout.Context.SYSTEM));
		if (layouts.length == 0) {
			LOGGER.debug("Missing the Layout for Context SYSTEM, creating a new Layout for the Context.");
			return createLayout(Layout.Type.AA, Layout.Context.SYSTEM, -1L);
		} else if (layouts.length > 1) {
			LOGGER.warn("Multiple Layouts found for Context SYSTEM, this is not supported."
				+ " Deleting all except the first.");
			for (int index = 1; index < layouts.length; index++) {
				objects.delete(layouts[index]);
			}
			return layouts[0];
		} else {
			return layouts[0];
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Layout getLayout(Long contextID) {
		Layout[] layouts = objects.find(Layout.class,
				Query.select().where("CONTEXT = ? AND CONTEXT_ID = ?", Layout.Context.PROJECT, contextID).limit(1));
		if (layouts != null && layouts.length == 1) {
			return layouts[0];
		}
		return getSystemLayout();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Layout getLayout(Context context) {
		if (Context.SYSTEM.equals(context)) {
			return getSystemLayout();
		} else if (Context.PROJECT.equals(context)) {
			throw new IllegalArgumentException("Cannot get a PROJECT Context Layout without the project Id");
		} else {
			Layout[] layouts = objects.find(Layout.class, Query.select().where("CONTEXT = ?", context));
			if (layouts != null && layouts.length == 1) {
				return layouts[0];
			} else {
				LOGGER.debug("Missing the Layout for Context " + context + ", creating a new Layout for the Context.");
				return createLayout(Layout.Type.AA, context, -1L);
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Layout getLayoutById(int layoutID) {
		return objects.get(Layout.class, layoutID);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Layout[] getLayouts() {
		return objects.find(Layout.class);
	}

	/**
	 * Internal method create a new {@link Layout}
	 * 
	 * @param type the {@link Layout.Type}
	 * @param context the {@link Layout.Context}
	 * @param contextID the Contextual ID, may be null if the {@link Layout.Context} supports it
	 * @return the {@link Layout}
	 */
	private Layout createLayout(Layout.Type type, Layout.Context context, Long contextID) {
		LOGGER.debug("Creating a new Layout of Type '" + type + "' and Context '" + context + "'");
		Layout layout = objects.create(Layout.class, new DBParam("TYPE", type), new DBParam("CONTEXT", context));
		if (contextID > -1) {
			layout.setContextID(contextID);
		}
		layout.save();
		for (int index = 0; index < type.columns.length; index++) {
			Column column = createColumn(layout, type.columns[index]);
			if (StringUtils.isNotBlank(LAYOUT_DEFAULT.getProperty(context.name() + ".column." + index))) {
				for (String shortname : LAYOUT_DEFAULT.getProperty(context.name() + ".column." + index).split(",")) {
					LOGGER.debug("Adding default gadget '" + shortname + "' to the " + context + " column " + index);
					addGadgetToColumn(getGadget(shortname), column);
				}
			}
		}
		return layout;
	}

	/**
	 * Internal method to create a {@link Column}
	 * 
	 * @param layout the {@link Layout} to link the column to
	 * @param type the {@link Column.Type}
	 * @return the {@link Column}
	 */
	private Column createColumn(Layout layout, Column.Type type) {
		LOGGER.debug("Creating a new Column of Type '" + type + "' for Layout with ID " + layout.getID());
		Column column = objects.create(Column.class, new DBParam("LAYOUT_ID", layout.getID()), new DBParam("TYPE", type));
		column.save();
		LOGGER.debug("Created column with ID " + column.getID());
		return column;
	}

	/**
	 * Internal method to delete a {@link Column} and all associated Gadgets
	 * 
	 * @param column the {@link Column} to delete
	 */
	private void deleteColumn(Column column) {
		LOGGER.debug("Deleting unneeded column with ID: " + column.getID());
		objects.delete(objects.find(ColumnToGadget.class, Query.select().where("COLUMN_ID = ?", column.getID())));
		objects.delete(column);
	}

	static {
		try {
			LAYOUT_DEFAULT.load(SonarPanelLayoutManagerService.class.getResourceAsStream("layout-default.properties"));
		} catch (IOException e) {
			LOGGER.error("Failed to laod the layout-default.properties", e);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy